-------------------------------------------------------------------------------- -- | -- Module : Sound.ALSA.Sequencer.Subscribe.Query -- Copyright : (c) Dylan Simon, 2011 -- License : BSD3 -- -- Stability : provisional -- -- This module contains functions for working with subscriptions. -- Reference: -- -------------------------------------------------------------------------------- module Sound.ALSA.Sequencer.Subscribe.Query ( T , Query.Type(..) {- , alloc , copy , clone -} , getClient , getPort , getRoot , getType , getIndex , getNumSubs , getAddr , getQueue , getExclusive , getTimeUpdate , getTimeReal {- , setClient , setPort , setType , setIndex -} , query , queryAll ) where import qualified Sound.ALSA.Sequencer.Marshal.QuerySubscribe as Query import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq import qualified Sound.ALSA.Sequencer.Area as Area import qualified Sound.ALSA.Sequencer.Marshal.Address as Addr import qualified Sound.ALSA.Sequencer.Marshal.Client as Client import qualified Sound.ALSA.Sequencer.Marshal.Port as Port import qualified Sound.ALSA.Sequencer.Marshal.Queue as Queue import qualified Sound.ALSA.Exception as Exc import Foreign.C.Error (Errno(Errno), eNOENT, ) import Foreign.C.Types (CInt, ) import Foreign.Ptr (Ptr, ) import Foreign.Marshal.Alloc (alloca, ) import Foreign.Storable (peek, poke, ) import Data.Word (Word, ) type T = Area.QuerySubscribe type T_ = Area.QuerySubscribe_ alloc :: IO T _copy :: T -> T -> IO () _clone :: T -> IO T getClient :: T -> IO Client.T getPort :: T -> IO Port.T getType :: T -> IO Query.Type getIndex :: T -> IO Word getNumSubs :: T -> IO Word getQueue :: T -> IO Queue.T getExclusive :: T -> IO Bool getTimeUpdate :: T -> IO Bool getTimeReal :: T -> IO Bool _setClient :: T -> Client.T -> IO () _setPort :: T -> Port.T -> IO () setType :: T -> Query.Type -> IO () setIndex :: T -> Word -> IO () alloc = Area.query_subscribe_malloc _copy = Area.query_subscribe_copy _clone = Area.query_subscribe_clone getClient = Area.query_subscribe_get_client getPort = Area.query_subscribe_get_port getType = Area.query_subscribe_get_type getIndex = Area.query_subscribe_get_index getNumSubs = Area.query_subscribe_get_num_subs getQueue = Area.query_subscribe_get_queue getExclusive = Area.query_subscribe_get_exclusive getTimeUpdate = Area.query_subscribe_get_time_update getTimeReal = Area.query_subscribe_get_time_real _setClient = Area.query_subscribe_set_client _setPort = Area.query_subscribe_set_port setType = Area.query_subscribe_set_type setIndex = Area.query_subscribe_set_index -- | Get the client/port address of a query getRoot :: T -> IO Addr.T getRoot q = peek =<< Area.with_query_subscribe q snd_seq_query_subscribe_get_root foreign import ccall unsafe "alsa/asoundlib.h snd_seq_query_subscribe_get_root" snd_seq_query_subscribe_get_root :: Ptr T_ -> IO (Ptr Addr.T) -- | Get the address of subscriber of query getAddr :: T -> IO Addr.T getAddr q = peek =<< Area.with_query_subscribe q snd_seq_query_subscribe_get_addr foreign import ccall unsafe "alsa/asoundlib.h snd_seq_query_subscribe_get_addr" snd_seq_query_subscribe_get_addr :: Ptr T_ -> IO (Ptr Addr.T) -- | Set the client/port address of a query setRoot :: T -> Addr.T -> IO () setRoot q c = alloca $ \p -> poke p c >> Area.with_query_subscribe q (`snd_seq_query_subscribe_set_root` p) foreign import ccall unsafe "alsa/asoundlib.h snd_seq_query_subscribe_set_root" snd_seq_query_subscribe_set_root :: Ptr T_ -> Ptr Addr.T -> IO () -- | Query port subscriber list queryPort :: Seq.T mode -> T -> IO Bool queryPort (Seq.Cons h) q = Exc.checkResultMaybe "query_port_subscribers" (const True) (\e -> if Errno (negate e) == eNOENT then Just False else Nothing) =<< Area.with_query_subscribe q (snd_seq_query_port_subscribers h) foreign import ccall unsafe "alsa/asoundlib.h snd_seq_query_port_subscribers" snd_seq_query_port_subscribers :: Ptr Seq.Core -> Ptr T_ -> IO CInt -- | Queries a subscriber connected to (Write) or from (Read) a given address: @'query' seq addr typ index@ query :: Seq.T mode -> Addr.T -> Query.Type -> Word -> IO (Maybe T) query ss root t i = do q <- alloc setRoot q root setType q t setIndex q i r <- queryPort ss q return $ if r then Just q else Nothing -- | Queries the list of subscribers accessing a port queryAll :: Seq.T mode -> Addr.T -> Query.Type -> IO [T] queryAll ss root t = queryRest 0 where queryRest i = query ss root t i >>= maybe (return []) (\q -> (q:) `fmap` queryRest (succ i))