pulseaudio 0.0.1.1 → 0.0.2.0
raw patch · 5 files changed
+102/−5 lines, 5 filesdep +transformersPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: transformers
API changes (from Hackage documentation)
+ Sound.Pulse: Pulse :: (Context -> (a -> IO ()) -> IO ()) -> Pulse a
+ Sound.Pulse: data Pulse a
+ Sound.Pulse: instance Control.Monad.IO.Class.MonadIO Sound.Pulse.Pulse
+ Sound.Pulse: instance GHC.Base.Applicative Sound.Pulse.Pulse
+ Sound.Pulse: instance GHC.Base.Functor Sound.Pulse.Pulse
+ Sound.Pulse: instance GHC.Base.Monad Sound.Pulse.Pulse
+ Sound.Pulse: pulseListM :: (Context -> (a -> IO ()) -> IO () -> IO ()) -> Pulse [a]
+ Sound.Pulse: runGetPulse :: MonadIO m => Context -> Pulse a -> m a
+ Sound.Pulse: runPulse :: MonadIO m => Context -> Pulse a -> (a -> IO ()) -> m ()
+ Sound.Pulse: runPulse_ :: MonadIO m => Context -> Pulse a -> m ()
+ Sound.Pulse.Serverinfo: getServerInfoM :: Pulse ServerInfo
+ Sound.Pulse.Sinkinfo: getContextSinkByIndexM :: Word32 -> Pulse Sinkinfo
+ Sound.Pulse.Sinkinfo: getContextSinkByNameM :: String -> Pulse Sinkinfo
+ Sound.Pulse.Sinkinfo: getContextSinksM :: Pulse [Sinkinfo]
+ Sound.Pulse.Subscribe: subscribeEventsM :: [SubscriptionMask] -> (Context -> Subscription) -> Pulse Operation
- Sound.Pulse.Subscribe: subscribeEvents :: Context -> [SubscriptionMask] -> ((SubscriptionEventFacility, SubscriptionEventType) -> Word32 -> IO ()) -> IO Operation
+ Sound.Pulse.Subscribe: subscribeEvents :: Context -> [SubscriptionMask] -> Subscription -> IO Operation
Files
- pulseaudio.cabal +5/−1
- src/Sound/Pulse.hs +64/−0
- src/Sound/Pulse/Serverinfo.hsc +5/−0
- src/Sound/Pulse/Sinkinfo.hsc +17/−0
- src/Sound/Pulse/Subscribe.hs +11/−4
pulseaudio.cabal view
@@ -10,7 +10,7 @@ -- PVP summary: +-+------- breaking API changes -- | | +----- non-breaking API additions -- | | | +--- code changes with no API change-version: 0.0.1.1+version: 0.0.2.0 -- A short (one-line) description of the package. synopsis: A low-level (incomplete) wrapper around the pulseaudio client asynchronous api@@ -104,6 +104,7 @@ ,Sound.Pulse.Operation ,Sound.Pulse.Serverinfo ,Sound.Pulse.Volume+ ,Sound.Pulse @@ -123,6 +124,9 @@ ,stm ,containers + if impl(ghc < 8.0)+ build-depends: transformers+ -- Directories containing source files. hs-source-dirs: src
+ src/Sound/Pulse.hs view
@@ -0,0 +1,64 @@+{-# LANGUAGE InstanceSigs #-}+-- {-# LANGUAGE ScopedTypeVariables #-}+module Sound.Pulse+ ( Pulse (..)+ , runPulse+ , runPulse_+ , runGetPulse++ , pulseListM+ )+where++import Control.Applicative+import Control.Monad.IO.Class+import Control.Concurrent.MVar (newEmptyMVar, takeMVar, putMVar, newMVar, modifyMVar_)+import Sound.Pulse.Context (Context)++data Pulse a = Pulse (Context -> (a -> IO ()) -> IO ())++instance Functor Pulse where+ fmap :: (a -> b) -> Pulse a -> Pulse b+ fmap f (Pulse x) =+ let g cxt y = x cxt (y . f)+ in Pulse g++instance Applicative Pulse where+ pure :: a -> Pulse a+ pure x = Pulse (\_ f -> f x)++ (<*>) :: Pulse (a -> b) -> Pulse a -> Pulse b+ (Pulse f0) <*> (Pulse g0) =+ let g1 cxt h t = g0 cxt (h . t)+ in Pulse (\cxt h -> f0 cxt (g1 cxt h))++instance Monad Pulse where+ return :: a -> Pulse a+ return = pure++ (>>=) :: Pulse a -> (a -> Pulse b) -> Pulse b+ (Pulse a) >>= f =+ Pulse (\cxt g -> a cxt (\v -> let Pulse h = f v in h cxt g))++instance MonadIO Pulse where+ liftIO :: IO a -> Pulse a+ liftIO a = Pulse (\_ f -> f =<< a)++runPulse :: MonadIO m => Context -> Pulse a -> (a -> IO ()) -> m ()+runPulse cxt (Pulse x) f = liftIO $ x cxt f++runPulse_ :: MonadIO m => Context -> Pulse a -> m ()+runPulse_ cxt (Pulse x) = liftIO $ x cxt (const $ return ())++runGetPulse :: MonadIO m => Context -> Pulse a -> m a+runGetPulse cxt x = liftIO $ do+ var <- newEmptyMVar+ runPulse cxt x (putMVar var)+ takeMVar var++pulseListM :: (Context -> (a -> IO ()) -> IO () -> IO ()) -> Pulse [a]+pulseListM fun = Pulse $ \cxt f -> do+ var <- newMVar []+ let cb v = modifyMVar_ var $ return . (v:)+ fun cxt cb (f . reverse =<< takeMVar var)+
src/Sound/Pulse/Serverinfo.hsc view
@@ -26,6 +26,7 @@ module Sound.Pulse.Serverinfo ( ServerInfo(..) , getServerInfo+ , getServerInfoM ) where @@ -36,6 +37,7 @@ import Control.Applicative ((<$>), (<*>)) import Data.Word (Word32, Word)+import Sound.Pulse import Sound.Pulse.SampleSpec import Sound.Pulse.ChannelPosition import Sound.Pulse.Context@@ -91,3 +93,6 @@ freeHaskellFunPtr (castPtrToFunPtr fP) _ <- ptrToOperation =<< pa_context_get_server_info cxt funP (castFunPtrToPtr funP) return ()++getServerInfoM :: Pulse ServerInfo+getServerInfoM = Pulse getServerInfo
src/Sound/Pulse/Sinkinfo.hsc view
@@ -32,6 +32,10 @@ , getContextSinks , getContextSinkByName , getContextSinkByIndex++ , getContextSinksM+ , getContextSinkByNameM+ , getContextSinkByIndexM ) where @@ -41,11 +45,13 @@ #include <pulse/introspect.h> import Control.Applicative ((<$>), (<*>))+import Sound.Pulse import Sound.Pulse.Volume import Sound.Pulse.Operation import Sound.Pulse.Userdata import Data.Word (Word32, Word8, Word) +import Control.Monad (void) import Foreign.Ptr (Ptr, FunPtr, freeHaskellFunPtr, castFunPtrToPtr, castPtrToFunPtr) import Foreign.C.Types (CInt(..), CUInt(..)) import Foreign.C.String (peekCString, withCString, CString)@@ -150,6 +156,9 @@ funP <- mkCallback fun endf ptrToOperation =<< pa_context_get_sink_info_list cxt funP (castFunPtrToPtr funP) +getContextSinksM :: Pulse [Sinkinfo]+getContextSinksM = pulseListM (\c cb e -> void $ getContextSinks c cb e)+ -- |Get a sink by name getContextSinkByName :: Context@@ -160,6 +169,10 @@ funP <- mkCallback fun (return ()) ptrToOperation =<< withCString name (\ptr -> pa_context_get_sink_info_by_name cxt ptr funP (castFunPtrToPtr funP)) +getContextSinkByNameM :: String -> Pulse Sinkinfo+getContextSinkByNameM name =+ Pulse (\cxt cb -> void $ getContextSinkByName cxt name cb)+ -- |Get a sink by index getContextSinkByIndex :: Context@@ -169,3 +182,7 @@ getContextSinkByIndex cxt idx fun = do funP <- mkCallback fun (return ()) ptrToOperation =<< pa_context_get_sink_info_by_index cxt (fromIntegral idx) funP (castFunPtrToPtr funP)++getContextSinkByIndexM :: Word32 -> Pulse Sinkinfo+getContextSinkByIndexM index =+ Pulse (\cxt cb -> void $ getContextSinkByIndex cxt index cb)
src/Sound/Pulse/Subscribe.hs view
@@ -29,6 +29,7 @@ , SubscriptionMask(..) , subscribeEvents+ , subscribeEventsM ) where @@ -37,6 +38,7 @@ import Data.Bits ((.&.)) import Foreign.Ptr import Foreign.C.Types+import Sound.Pulse import Sound.Pulse.Context import Sound.Pulse.Userdata import Sound.Pulse.Def (SubscriptionEventFacility(..), SubscriptionEventType(..), subscriptionEventFacilityFromInt, subscriptionEventFacilityToInt, subscriptionEventTypeFromInt, subscriptionEventTypeToInt, SubscriptionMask(..), subscriptionMasksToInt)@@ -63,6 +65,9 @@ -> Ptr Userdata -> IO (Ptr UOperation) +type Subscription =+ (SubscriptionEventFacility, SubscriptionEventType) -> Word32 -> IO ()+ -- |Currently the function given here is leaked! even if it's reset later on -- This is currently unavoidable, since we don't know when the last event -- occured.@@ -71,10 +76,7 @@ subscribeEvents :: Context -- ^The Context to subscribe on -> [SubscriptionMask] -- ^The events that should be reported- -> ((SubscriptionEventFacility, SubscriptionEventType)- -> Word32- -> IO ()- ) -- ^Callback function that will be called on every event received.+ -> Subscription -- ^Callback function that will be called on every event received. -> IO Operation subscribeEvents cxt mask fun = do funP <- mkSubscribeCB $ \_ ival idx _ ->@@ -82,3 +84,8 @@ pa_context_set_subscribe_callback cxt funP nullPtr sucP <- wrapSuccess (\_ -> return ()) ptrToOperation =<< pa_context_subscribe cxt (subscriptionMasksToInt mask) sucP nullPtr+++subscribeEventsM :: [SubscriptionMask] -> (Context -> Subscription) -> Pulse Operation+subscribeEventsM mask sub =+ Pulse $ \cxt f -> f =<< subscribeEvents cxt mask (sub cxt)