-------------------------------------------------------------------------------- -- | -- Module : Sound.ALSA.Sequencer.Queue -- Copyright : (c) Henning Thielemann, 2010-2012 -- (c) Iavor S. Diatchki, 2007 -- License : BSD3 -- -- Maintainer: Henning Thielemann -- Stability : provisional -- -- This module contains functions for working with sequencer queue. -- Reference: -- -------------------------------------------------------------------------------- {-# LANGUAGE ForeignFunctionInterface #-} module Sound.ALSA.Sequencer.Queue ( -- * General Queue Functions Queue.T , Queue.direct , alloc , allocNamed , free , with , withNamed , control ) where import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq import qualified Sound.ALSA.Sequencer.Marshal.Address as Addr import qualified Sound.ALSA.Sequencer.Marshal.Event as Event import qualified Sound.ALSA.Sequencer.Marshal.Queue as Queue import qualified Sound.ALSA.Sequencer.Marshal.Time as Time import qualified Sound.ALSA.Exception as Exc import qualified Foreign.C.Types as C import Foreign.C.String (CString, withCAString, ) import Foreign.Ptr (Ptr, ) import Control.Exception (bracket, ) import Control.Functor.HT (void, ) alloc :: Seq.T mode -> IO Queue.T -- ^ Queue.T identifier. alloc (Seq.Cons h) = fmap Queue.imp $ Exc.checkResult "Queue.alloc" =<< alloc_ h foreign import ccall unsafe "alsa/asoundlib.h snd_seq_alloc_queue" alloc_ :: Ptr Seq.Core -> IO C.CInt with :: Seq.T mode -> (Queue.T -> IO a) -> IO a with s = bracket (alloc s) (free s) allocNamed :: Seq.T mode -> String -> IO Queue.T allocNamed (Seq.Cons h) x = withCAString x $ \s -> fmap Queue.imp $ Exc.checkResult "Queue.allocNamed" =<< allocNamed_ h s foreign import ccall unsafe "alsa/asoundlib.h snd_seq_alloc_named_queue" allocNamed_ :: Ptr Seq.Core -> CString -> IO C.CInt withNamed :: Seq.T mode -> String -> (Queue.T -> IO a) -> IO a withNamed s nm = bracket (allocNamed s nm) (free s) -- | Delete the specified queue. free :: Seq.T mode -- ^ Sequencer handle. -> Queue.T -- ^ Queue.T identifier. -> IO () free (Seq.Cons h) q = Exc.checkResult_ "Queue.free" =<< free_ h (Queue.exp q) foreign import ccall unsafe "alsa/asoundlib.h snd_seq_free_queue" free_ :: Ptr Seq.Core -> C.CInt -> IO C.CInt {- | start/stop/continue a queue In the prototype event you can provide additional information. The prototype event does not need to be a queue control event, this part is ignored anyway. In the prototype event you may also specify a queue. This is the queue that the timestamp of the prototype event refers to. This way you can control the target queue using timing from another queue. -} control :: Seq.T mode -- ^ Sequencer handle. -> Queue.T -- ^ target Queue.T. -> Event.QueueEv -> Maybe Event.T -- ^ prototype event that may provide timestamp, source queue -> IO () control h q cmd me = case cmd of Event.QueueSetPosTick _ -> controlCustom h q cmd me Event.QueueSetPosTime _ -> controlCustom h q cmd me Event.QueueSkew _ -> controlCustom h q cmd me _ -> controlPlain h q cmd me controlCustom, controlPlain :: Seq.T mode -> Queue.T -> Event.QueueEv -> Maybe Event.T -> IO () controlCustom h q cmd me = eventOutput h $ case me of Nothing -> -- cf. Event.simple Event.Cons { Event.highPriority = False, Event.tag = Event.Tag 0, Event.queue = Queue.direct, Event.time = Time.consAbs $ Time.Tick 0, Event.source = Addr.unknown, Event.dest = Addr.systemTimer, Event.body = Event.QueueEv cmd q } Just ev -> ev { Event.dest = Addr.systemTimer, Event.body = Event.QueueEv cmd q } eventOutput :: Seq.T mode -> Event.T -> IO () eventOutput h e = void $ Event.with e $ \p -> Exc.checkResult "Queue.control.eventOutput" =<< eventOutput_ h p foreign import ccall safe "alsa/asoundlib.h snd_seq_event_output" eventOutput_ :: Seq.T mode -> Ptr Event.T -> IO C.CInt controlPlain h q cmd me = Event.withMaybe me $ \p -> let (c,v) = Event.expQueueEv cmd in Exc.checkResult_ "Queue.control" =<< control_ h (Queue.exp q) (fromIntegral $ Event.unEType c) v p foreign import ccall unsafe "alsa/asoundlib.h snd_seq_control_queue" control_ :: Seq.T mode -> C.CInt -> C.CInt -> C.CInt -> Ptr Event.T -> IO C.CInt