{-# LANGUAGE DeriveDataTypeable #-} module SFML.Audio.SoundRecorder ( module SFML.Utils , SoundRecorderException(..) , SoundRecorderStartCallback , SoundRecorderProcessCallback , SoundRecorderStopCallback , createSoundRecorder , destroy , startRecording , stopRecording , getSampleRate , isSoundRecorderAvailable ) where import SFML.Audio.SFSampled import SFML.Audio.SFSoundRecorder import SFML.Audio.Types import SFML.SFResource import SFML.Utils import Control.Exception import Control.Monad ((>=>)) import Data.Typeable import Data.Word (Word16) import Foreign.C.Types import Foreign.Ptr (Ptr, nullPtr) checkNull :: SoundRecorder -> Maybe SoundRecorder checkNull sr@(SoundRecorder ptr) = if ptr == nullPtr then Nothing else Just sr data SoundRecorderException = SoundRecorderException String deriving (Show, Typeable) instance Exception SoundRecorderException -- | Type of the callback used when starting a capture. type SoundRecorderStartCallback a = Ptr a -> IO CInt -- | Type of the callback used to process audio data. type SoundRecorderProcessCallback a = Ptr Word16 -> CUInt -> Ptr a -> IO Bool -- | Type of the callback used when stopping a capture. type SoundRecorderStopCallback a = Ptr a -> IO () -- typedef sfBool (*sfSoundRecorderStartCallback)(void*); -- typedef sfBool (*sfSoundRecorderProcessCallback)(const sfInt16*, size_t, void*); -- typedef void (*sfSoundRecorderStopCallback)(void*); -- | Construct a new sound recorder from callback functions. createSoundRecorder :: Ptr (SoundRecorderStartCallback a) -- ^ (onStart) Callback function which will be called when a new capture starts (can be NULL) -> Ptr (SoundRecorderProcessCallback a) -- ^ (onProcess) Callback function which will be called each time there's audio data to process -> Ptr (SoundRecorderStopCallback a) -- ^ (onStop) Callback function which will be called when the current capture stops (can be NULL) -> Ptr a -- ^ Data to pass to the callback function (can be NULL) -> IO (Either SoundRecorderException SoundRecorder) -- ^ A new 'SoundRecorder' object ('Nothing' if failed) createSoundRecorder c1 c2 c3 d = let err = SoundRecorderException $ "Failed creating sound recorder: onStart = " ++ show c1 ++ " onProcess = " ++ show c2 ++ " onStop = " ++ show c3 ++ " userData = " ++ show d in sfSoundRecorder_create c1 c2 c3 d >>= return . tagErr err . checkNull foreign import ccall unsafe "sfSoundRecorder_create" sfSoundRecorder_create :: Ptr (SoundRecorderStartCallback a) -> Ptr (SoundRecorderProcessCallback a) -> Ptr (SoundRecorderStopCallback a) -> Ptr a -> IO SoundRecorder -- CSFML_AUDIO_API sfSoundRecorder* sfSoundRecorder_create(sfSoundRecorderStartCallback onStart, sfSoundRecorderProcessCallback onProcess, sfSoundRecorderStopCallback onStop, void* userData); instance SFResource SoundRecorder where {-# INLINABLE destroy #-} destroy = sfSoundRecorder_destroy foreign import ccall unsafe "sfSoundRecorder_destroy" sfSoundRecorder_destroy :: SoundRecorder -> IO () -- CSFML_AUDIO_API void sfSoundRecorder_destroy(sfSoundRecorder* soundRecorder); instance SFSoundRecorder SoundRecorder where {-# INLINABLE startRecording #-} startRecording rec rate = sfSoundRecorder_start rec (fromIntegral rate) {-# INLINABLE stopRecording #-} stopRecording = sfSoundRecorder_stop foreign import ccall unsafe "sfSoundRecorder_start" sfSoundRecorder_start :: SoundRecorder -> CUInt -> IO () -- CSFML_AUDIO_API void sfSoundRecorder_start(sfSoundRecorder* soundRecorder, unsigned int sampleRate); foreign import ccall unsafe "sfSoundRecorder_stop" sfSoundRecorder_stop :: SoundRecorder -> IO () -- CSFML_AUDIO_API void sfSoundRecorder_stop(sfSoundRecorder* soundRecorder); instance SFSampled SoundRecorder where {-# INLINABLE getSampleRate #-} getSampleRate = sfSoundRecorder_getSampleRate >=> return . fromIntegral foreign import ccall unsafe "sfSoundRecorder_getSampleRate" sfSoundRecorder_getSampleRate :: SoundRecorder -> IO CUInt -- CSFML_AUDIO_API unsigned int sfSoundRecorder_getSampleRate(const sfSoundRecorder* soundRecorder); -- | Check if the system supports audio capture. -- -- This function should always be called before using -- the audio capture features. If it returns false, then -- any attempt to use 'SoundRecorder' will fail. isSoundRecorderAvailable :: IO Bool isSoundRecorderAvailable = fmap (toEnum . fromIntegral) sfSoundRecorder_isAvailable foreign import ccall unsafe "sfSoundRecorder_isAvailable" sfSoundRecorder_isAvailable :: IO CInt -- CSFML_AUDIO_API sfBool sfSoundRecorder_isAvailable(void);