packages feed

alsa-mixer 0.1.2 → 0.2.0

raw patch · 3 files changed

+60/−57 lines, 3 filesdep +unix

Dependencies added: unix

Files

Sound/ALSA/Mixer.hs view
@@ -25,7 +25,7 @@       -- * Functions       -- ** Mixers     , controls-    , getMixerByName+    , withMixer       -- ** Controls     , getControlByName     , common@@ -152,7 +152,7 @@     hasPlaySwJ <- hasPlaybackSwitchJoined se     hasCaptSw <- hasCaptureSwitch se     hasCaptSwJ <- hasCaptureSwitchJoined se-    return $ if hasComSw +    return $ if hasComSw                 then Left $ if hasPlaySwJ                               then comJoinedSwitch pChans                               else comPerChannelSwitch pChans@@ -279,13 +279,11 @@                           , volume = v                           } --- | Get the named 'Control', if it exists, from the named 'Mixer'. Will--- throw an exception if the named 'Mixer' does not exist.-getControlByName :: String  -- ^ Mixer name+-- | Get the named 'Control', if it exists, from the named 'Mixer'.+getControlByName :: Mixer   -- ^ Mixer                  -> String  -- ^ Control name                  -> IO (Maybe Control)-getControlByName mixerName controlName = do-    mix <- getMixerByName mixerName+getControlByName mix controlName = do     cs <- controls mix     return $ lookup controlName $ zip (map name cs) cs @@ -294,13 +292,14 @@ The example function reads the volume and increases it by the value supplied.  >   changeVolumeBy :: Integer -> IO ()->   changeVolumeBy i = do->       Just control <- getControlByName "default" "Master"->       let Just playbackVolume = playback $ volume control->       (min, max) <- getRange playbackVolume->       Just vol <- getChannel FrontLeft $ value $ playbackVolume->       when ((i > 0 && vol < max) || (i < 0 && vol > min))->           $ setChannel FrontLeft (value $ playbackVolume) $ vol + i+>   changeVolumeBy i =+>       withMixer "default" $ \mixer ->+>         do Just control <- getControlByName mixer "Master"+>            let Just playbackVolume = playback $ volume control+>            (min, max) <- getRange playbackVolume+>            Just vol <- getChannel FrontLeft $ value $ playbackVolume+>            when ((i > 0 && vol < max) || (i < 0 && vol > min))+>              $ setChannel FrontLeft (value $ playbackVolume) $ vol + i  -} @@ -309,10 +308,11 @@ The example function reads the value of the switch and toggles it.  >   toggleMute :: IO ()->   toggleMute = do->       Just control <- getControlByName "default" "Master"->       let Just playbackSwitch = playback $ switch control->       Just sw <- getChannel FrontLeft playbackSwitch->       setChannel FrontLeft playbackSwitch $ not sw+>   toggleMute =+>       withMixer "default" $ \mixer ->+>         do Just control <- getControlByName "default" "Master"+>            let Just playbackSwitch = playback $ switch control+>            Just sw <- getChannel FrontLeft playbackSwitch+>            setChannel FrontLeft playbackSwitch $ not sw  -}
Sound/ALSA/Mixer/Internal.chs view
@@ -6,7 +6,7 @@     , Channel(..)     , allChannels     , elements-    , getMixerByName+    , withMixer     , isPlaybackMono     , isCaptureMono     , hasPlaybackChannel@@ -49,16 +49,19 @@     , getIndex     ) where +import Control.Monad (liftM, when)+import Control.Exception (bracket) import Foreign import Foreign.C.Error ( eNOENT ) import Foreign.C.String import Foreign.C.Types import Sound.ALSA.Exception ( checkResult_, throw )+import System.Posix.Process (getProcessID)  #include "alsa/asoundlib.h" {#context lib = "asoundlib" #} -{#pointer *snd_mixer_t as Mixer foreign#}+{#pointer *snd_mixer_t as Mixer newtype#} {#pointer *snd_mixer_elem_t as Element#} {#pointer *snd_mixer_selem_id_t as SimpleElementId foreign#} type SimpleElement = (Mixer, Element)@@ -84,29 +87,26 @@ -- open -- -------------------------------------------------------------------- -{#fun snd_mixer_open as open-    { mallocMixer- `Mixer' peekMixer*-    , modeZero- `Int' fromIntegral- } -> `Int' checkOpen*- #}+foreign import ccall safe "alsa/asoundlib.h snd_mixer_open"+  open_ :: Ptr (Ptr Mixer) -> CInt -> IO CInt -mallocMixer f = do-    pm <- malloc-    f pm+open :: IO Mixer+open = withPtr $ \ppm ->+  do open_ ppm (fromIntegral 0) >>= checkResult_ "snd_mixer_open"+     liftM Mixer $ peek ppm -modeZero f = f $ fromIntegral 0-checkOpen = checkResult_ "snd_mixer_open"-peekMixer pm = peek pm >>= newForeignPtr snd_mixer_close+withPtr :: (Ptr (Ptr a) -> IO a) -> IO a+withPtr = bracket malloc free --- Static address import for finalizer. Suppression of the return type may--- not be a good idea, but the workaround involves lots of C.-foreign import ccall "alsa/asoundlib.h &snd_mixer_close"-  snd_mixer_close :: FunPtr (Ptr () -> IO ())+foreign import ccall "alsa/asoundlib.h snd_mixer_close"+  freeMixer :: Ptr Mixer -> IO ()  ----------------------------------------------------------------------- -- attach -- --------------------------------------------------------------------  {#fun snd_mixer_attach as attach-    { withForeignPtr* `Mixer', `String' } -> `Int' checkAttach*- #}+    { id `Mixer', `String' } -> `Int' checkAttach*- #}  checkAttach = checkResult_ "snd_mixer_attach" @@ -115,12 +115,12 @@ -- --------------------------------------------------------------------  {#fun snd_mixer_load as ^-    { withForeignPtr* `Mixer' } -> `Int' checkSndMixerLoad*- #}+    { id `Mixer' } -> `Int' checkSndMixerLoad*- #}  checkSndMixerLoad = checkResult_ "snd_mixer_load"  {#fun snd_mixer_selem_register as ^-    { withForeignPtr* `Mixer'+    { id `Mixer'     , id `Ptr ()'     , id `Ptr (Ptr ())' } -> `Int' checkSndMixerSelemRegister*- #} @@ -157,10 +157,10 @@ -- --------------------------------------------------------------------  {#fun snd_mixer_first_elem as ^-    { withForeignPtr* `Mixer' } -> `Element' id #}+    { id `Mixer' } -> `Element' id #}  {#fun snd_mixer_last_elem as ^-    { withForeignPtr* `Mixer' } -> `Element' id #}+    { id `Mixer' } -> `Element' id #}  {#fun snd_mixer_elem_next as ^     { id `Element' } -> `Element' id #}@@ -181,7 +181,7 @@ -- --------------------------------------------------------------------  {#fun snd_mixer_find_selem as ^-    { withForeignPtr* `Mixer'+    { id `Mixer'     , withForeignPtr* `SimpleElementId' } -> `Element' id #}  simpleElement :: Mixer -> Element -> IO (SimpleElementId, SimpleElement)@@ -210,14 +210,19 @@ -- getMixerByName -- -------------------------------------------------------------------- --- | Returns the named 'Mixer'. Will throw an exception if the named mixer--- cannot be found. A mixer named \"default\" should always exist.-getMixerByName :: String -> IO Mixer-getMixerByName name = do-    mix <- open-    attach mix name-    load mix-    return mix+-- | Perform an 'IO' action with the named mixer. An exception will be+-- thrown if the named mixer cannot be found. A mixer named \"default\"+-- should always exist.+withMixer :: String -> (Mixer -> IO a) -> IO a+withMixer name f = bracket (do m <- open+                               attach m name+                               load m+                               pid <- getProcessID+                               return (pid, m))+                           (\(creatorPID, Mixer m) ->+                              do myPID <- getProcessID+                                 when (myPID == creatorPID) $ freeMixer m)+                           (f . snd)  ----------------------------------------------------------------------- -- utilities@@ -228,14 +233,11 @@ cFromBool = fromBool  withSimpleElement :: SimpleElement -> (Element -> IO a) -> IO a-withSimpleElement (m, s) f = do-    r <- f s-    touchForeignPtr m-    return r+withSimpleElement (m, s) f = f s  channelToC = toEnum . fromEnum -cToIntegral = (>>= return . fromIntegral) . peek +cToIntegral = (>>= return . fromIntegral) . peek  cFromIntegral :: Integer -> (Ptr CLong -> IO a) -> IO a cFromIntegral = with . fromIntegral
alsa-mixer.cabal view
@@ -1,5 +1,5 @@ Name:                alsa-mixer-Version:             0.1.2+Version:             0.2.0 Synopsis:            Bindings to the ALSA simple mixer API. Description:         This package provides bindings to the ALSA simple mixer API. License:             BSD3@@ -12,8 +12,8 @@ Cabal-version:       >=1.6  Source-repository head-  Type:     darcs-  Location: http://community.haskell.org/~ttuegel/alsa-mixer+  Type:     git+  Location: https://github.com/ttuegel/alsa-mixer.git  Library   Exposed-modules:     Sound.ALSA.Mixer@@ -21,4 +21,5 @@   Build-tools:         c2hs   Extra-libraries:     asound   Build-depends:       base == 4.*,-                       alsa-core == 0.5.*+                       alsa-core == 0.5.*,+                       unix == 2.6.*