packages feed

alsa-mixer 0.1 → 0.1.1

raw patch · 4 files changed

+473/−475 lines, 4 filesdep −bytestringdep −template-haskellPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies removed: bytestring, template-haskell

API changes (from Hackage documentation)

- Sound.ALSA.Mixer: OtherChannel :: Int -> Channel
+ Sound.ALSA.Mixer: Last :: Channel
+ Sound.ALSA.Mixer: SND_MIXER_SCHN_MONO :: Channel
- Sound.ALSA.Mixer: type Mixer = ForeignPtr MixerT
+ Sound.ALSA.Mixer: type Mixer = ForeignPtr (())

Files

+ Sound/ALSA/Mixer/Internal.chs view
@@ -0,0 +1,470 @@+{-# LANGUAGE CPP, ForeignFunctionInterface #-}+module Sound.ALSA.Mixer.Internal+    ( Mixer()+    , SimpleElement()+    , SimpleElementId()+    , Channel(..)+    , allChannels+    , elements+    , getMixerByName+    , isPlaybackMono+    , isCaptureMono+    , hasPlaybackChannel+    , hasCaptureChannel+    , hasCommonVolume+    , hasPlaybackVolume+    , hasPlaybackVolumeJoined+    , hasCaptureVolume+    , hasCaptureVolumeJoined+    , hasCommonSwitch+    , hasPlaybackSwitch+    , hasPlaybackSwitchJoined+    , hasCaptureSwitch+    , hasCaptureSwitchJoined+    , getPlaybackVolume+    , getCaptureVolume+    , getPlaybackDb+    , getCaptureDb+    , getPlaybackSwitch+    , getCaptureSwitch+    , setPlaybackVolume+    , setCaptureVolume+    , setPlaybackDb+    , setCaptureDb+    , setPlaybackVolumeAll+    , setCaptureVolumeAll+    , setPlaybackDbAll+    , setCaptureDbAll+    , setPlaybackSwitch+    , setCaptureSwitch+    , setPlaybackSwitchAll+    , setCaptureSwitchAll+    , getPlaybackVolumeRange+    , getPlaybackDbRange+    , getCaptureVolumeRange+    , getCaptureDbRange+    , setPlaybackVolumeRange+    , setCaptureVolumeRange+    , getName+    , getIndex+    ) where++import Foreign+import Foreign.C.Error ( eNOENT )+import Foreign.C.String+import Foreign.C.Types+import Sound.ALSA.Exception ( checkResult_, throw )++#include "alsa/asoundlib.h"+{#context lib = "asoundlib" #}++{#pointer *snd_mixer_t as Mixer foreign#}+{#pointer *snd_mixer_elem_t as Element#}+{#pointer *snd_mixer_selem_id_t as SimpleElementId foreign#}+type SimpleElement = (Mixer, Element)++{#enum snd_mixer_selem_channel_id_t as Channel+    { SND_MIXER_SCHN_UNKNOWN as Unknown+    , SND_MIXER_SCHN_FRONT_LEFT as FrontLeft+    , SND_MIXER_SCHN_FRONT_RIGHT as FrontRight+    , SND_MIXER_SCHN_REAR_LEFT as RearLeft+    , SND_MIXER_SCHN_REAR_RIGHT as RearRight+    , SND_MIXER_SCHN_FRONT_CENTER as FrontCenter+    , SND_MIXER_SCHN_WOOFER as Woofer+    , SND_MIXER_SCHN_SIDE_LEFT as SideLeft+    , SND_MIXER_SCHN_SIDE_RIGHT as SideRight+    , SND_MIXER_SCHN_REAR_CENTER as RearCenter+    , SND_MIXER_SCHN_LAST as Last+    } deriving (Eq, Read, Show) #}++allChannels :: [Channel]+allChannels = map toEnum $ enumFromTo (fromEnum FrontLeft) (fromEnum RearCenter)++-----------------------------------------------------------------------+-- open+-- --------------------------------------------------------------------++{#fun snd_mixer_open as open+    { mallocMixer- `Mixer' peekMixer*+    , modeZero- `Int' fromIntegral- } -> `Int' checkOpen*- #}++mallocMixer f = do+    pm <- malloc+    f pm++modeZero f = f $ fromIntegral 0+checkOpen = checkResult_ "snd_mixer_open"+peekMixer pm = peek pm >>= newForeignPtr snd_mixer_close++-- 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 ())++-----------------------------------------------------------------------+-- attach+-- --------------------------------------------------------------------++{#fun snd_mixer_attach as attach+    { withForeignPtr* `Mixer', `String' } -> `Int' checkAttach*- #}++checkAttach = checkResult_ "snd_mixer_attach"++-----------------------------------------------------------------------+-- load+-- --------------------------------------------------------------------++{#fun snd_mixer_load as ^+    { withForeignPtr* `Mixer' } -> `Int' checkSndMixerLoad*- #}++checkSndMixerLoad = checkResult_ "snd_mixer_load"++{#fun snd_mixer_selem_register as ^+    { withForeignPtr* `Mixer'+    , id `Ptr ()'+    , id `Ptr (Ptr ())' } -> `Int' checkSndMixerSelemRegister*- #}++checkSndMixerSelemRegister = checkResult_ "snd_mixer_selem_register"++load :: Mixer -> IO ()+load fmix = do+    sndMixerSelemRegister fmix nullPtr nullPtr+    sndMixerLoad fmix++-----------------------------------------------------------------------+-- getId+-- --------------------------------------------------------------------++{#fun snd_mixer_selem_id_malloc as ^+    { alloca- `SimpleElementId' peekSimpleElementId* } -> `()' #}++{#fun snd_mixer_selem_get_id as ^ +    { id `Element', withForeignPtr* `SimpleElementId' } -> `()' #}++peekSimpleElementId pid = peek pid >>= newForeignPtr snd_mixer_selem_id_free++foreign import ccall "alsa/asoundlib.h &snd_mixer_selem_id_free"+  snd_mixer_selem_id_free :: FunPtr (Ptr () -> IO ())++getId :: Element -> IO SimpleElementId+getId e = do+   newSid <- sndMixerSelemIdMalloc+   sndMixerSelemGetId e newSid+   return newSid++-----------------------------------------------------------------------+-- elements+-- --------------------------------------------------------------------++{#fun snd_mixer_first_elem as ^+    { withForeignPtr* `Mixer' } -> `Element' id #}++{#fun snd_mixer_last_elem as ^+    { withForeignPtr* `Mixer' } -> `Element' id #}++{#fun snd_mixer_elem_next as ^+    { id `Element' } -> `Element' id #}++elements :: Mixer -> IO [(SimpleElementId, SimpleElement)]+elements fMix = do+    pFirst <- sndMixerFirstElem fMix+    pLast <- sndMixerLastElem fMix+    es <- elements' pFirst [] pLast+    mapM (simpleElement fMix) es+  where elements' pThis xs pLast | pThis == pLast = return $ pThis : xs+                                 | otherwise = do+                                     pNext <- sndMixerElemNext pThis+                                     elements' pNext (pThis : xs) pLast++-----------------------------------------------------------------------+-- simpleElement+-- --------------------------------------------------------------------++{#fun snd_mixer_find_selem as ^+    { withForeignPtr* `Mixer'+    , withForeignPtr* `SimpleElementId' } -> `Element' id #}++simpleElement :: Mixer -> Element -> IO (SimpleElementId, SimpleElement)+simpleElement fMix pElem = do+    fId <- getId pElem+    pSElem <- sndMixerFindSelem fMix fId+    if pSElem == nullPtr+        then throw "snd_mixer_find_selem" eNOENT+        else return (fId, (fMix, pSElem))++-----------------------------------------------------------------------+-- getName+-- --------------------------------------------------------------------++{#fun snd_mixer_selem_id_get_name as getName+    { withForeignPtr* `SimpleElementId' } -> `String' #}++-----------------------------------------------------------------------+-- getIndex+-- --------------------------------------------------------------------++{#fun snd_mixer_selem_id_get_index as getIndex+    { withForeignPtr* `SimpleElementId' } -> `Integer' fromIntegral #}++-----------------------------------------------------------------------+-- 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++-----------------------------------------------------------------------+-- utilities+-- --------------------------------------------------------------------++cToBool = toBool ++cFromBool = fromBool++withSimpleElement :: SimpleElement -> (Element -> IO a) -> IO a+withSimpleElement (m, s) f = do+    r <- f s+    touchForeignPtr m+    return r++channelToC = toEnum . fromEnum++cToIntegral = (>>= return . fromIntegral) . peek ++cFromIntegral :: Integer -> (Ptr CLong -> IO a) -> IO a+cFromIntegral = with . fromIntegral++negOne f = f $! negate 1++-----------------------------------------------------------------------+-- has+-- --------------------------------------------------------------------++{#fun snd_mixer_selem_is_playback_mono as isPlaybackMono+    { withSimpleElement* `SimpleElement' } -> `Bool' #}++{#fun snd_mixer_selem_is_capture_mono as isCaptureMono+    { withSimpleElement* `SimpleElement' } -> `Bool' #}++{#fun snd_mixer_selem_has_common_volume as hasCommonVolume+    { withSimpleElement* `SimpleElement' } -> `Bool' #}++{#fun snd_mixer_selem_has_playback_volume as hasPlaybackVolume+    { withSimpleElement* `SimpleElement' } -> `Bool' #}++{#fun snd_mixer_selem_has_playback_volume_joined as hasPlaybackVolumeJoined+    { withSimpleElement* `SimpleElement' } -> `Bool' #}++{#fun snd_mixer_selem_has_capture_volume as hasCaptureVolume+    { withSimpleElement* `SimpleElement' } -> `Bool' #}++{#fun snd_mixer_selem_has_capture_volume_joined as hasCaptureVolumeJoined+    { withSimpleElement* `SimpleElement' } -> `Bool' #}++{#fun snd_mixer_selem_has_common_switch as hasCommonSwitch+    { withSimpleElement* `SimpleElement' } -> `Bool' #}++{#fun snd_mixer_selem_has_playback_switch as hasPlaybackSwitch+    { withSimpleElement* `SimpleElement' } -> `Bool' #}++{#fun snd_mixer_selem_has_playback_switch_joined as hasPlaybackSwitchJoined+    { withSimpleElement* `SimpleElement' } -> `Bool' #}++{#fun snd_mixer_selem_has_capture_switch as hasCaptureSwitch+    { withSimpleElement* `SimpleElement' } -> `Bool' #}++{#fun snd_mixer_selem_has_capture_switch_joined as hasCaptureSwitchJoined+    { withSimpleElement* `SimpleElement' } -> `Bool' #}++{#fun snd_mixer_selem_has_playback_channel as hasPlaybackChannel+    { withSimpleElement* `SimpleElement'+    , channelToC `Channel' } -> `Bool' #}++{#fun snd_mixer_selem_has_capture_channel as hasCaptureChannel+    { withSimpleElement* `SimpleElement'+    , channelToC `Channel' } -> `Bool' #}++-----------------------------------------------------------------------+-- get+-- --------------------------------------------------------------------++{#fun snd_mixer_selem_get_playback_volume as getPlaybackVolume+    { withSimpleElement* `SimpleElement'+    , channelToC `Channel'+    , alloca- `Integer' cToIntegral* } -> `Int' checkGetPlaybackVolume*- #}++checkGetPlaybackVolume = checkResult_ "snd_mixer_selem_get_playback_volume"++{#fun snd_mixer_selem_get_capture_volume as getCaptureVolume+    { withSimpleElement* `SimpleElement'+    , channelToC `Channel'+    , alloca- `Integer' cToIntegral* } -> `Int' checkGetCaptureVolume*- #}++checkGetCaptureVolume = checkResult_ "snd_mixer_selem_get_capture_volume"++{#fun snd_mixer_selem_get_playback_dB as getPlaybackDb+    { withSimpleElement* `SimpleElement'+    , channelToC `Channel'+    , alloca- `Integer' cToIntegral* } -> `Int' checkPlaybackDb*- #}++checkPlaybackDb = checkResult_ "snd_mixer_selem_get_playback_dB"++{#fun snd_mixer_selem_get_capture_dB as getCaptureDb+    { withSimpleElement* `SimpleElement'+    , channelToC `Channel'+    , alloca- `Integer' cToIntegral* } -> `Int' checkCaptureDb*- #}++checkCaptureDb = checkResult_ "snd_mixer_selem_get_capture_dB"++peekBool = (>>= return . cToBool) . peek++{#fun snd_mixer_selem_get_playback_switch as getPlaybackSwitch+    { withSimpleElement* `SimpleElement'+    , channelToC `Channel'+    , alloca- `Bool' peekBool* } -> `Int' checkPlaybackSwitch*- #}++checkPlaybackSwitch = checkResult_ "snd_mixer_selem_get_playback_switch"++{#fun snd_mixer_selem_get_capture_switch as getCaptureSwitch+    { withSimpleElement* `SimpleElement'+    , channelToC `Channel'+    , alloca- `Bool' peekBool* } -> `Int' checkCaptureSwitch*- #}++checkCaptureSwitch = checkResult_ "snd_mixer_selem_get_capture_switch"++{#fun snd_mixer_selem_get_playback_volume_range as getPlaybackVolumeRange+    { withSimpleElement* `SimpleElement'+    , alloca- `Integer' cToIntegral*+    , alloca- `Integer' cToIntegral* } -> `Int' checkGetPlaybackVolumeRange*- #}++checkGetPlaybackVolumeRange = checkResult_ "snd_mixer_selem_get_playback_volume_range"++{#fun snd_mixer_selem_get_capture_volume_range as getCaptureVolumeRange+    { withSimpleElement* `SimpleElement'+    , alloca- `Integer' cToIntegral*+    , alloca- `Integer' cToIntegral* } -> `Int' checkGetCaptureVolumeRange*- #}++checkGetCaptureVolumeRange = checkResult_ "snd_mixer_selem_get_capture_volume_range"++{#fun snd_mixer_selem_get_playback_dB_range as getPlaybackDbRange+    { withSimpleElement* `SimpleElement'+    , alloca- `Integer' cToIntegral*+    , alloca- `Integer' cToIntegral* } -> `Int' checkGetPlaybackDbRange*- #}++checkGetPlaybackDbRange = checkResult_ "snd_mixer_selem_get_playback_dB_range"++{#fun snd_mixer_selem_get_capture_dB_range as getCaptureDbRange+    { withSimpleElement* `SimpleElement'+    , alloca- `Integer' cToIntegral*+    , alloca- `Integer' cToIntegral* } -> `Int' checkGetCaptureDbRange*- #}++checkGetCaptureDbRange = checkResult_ "snd_mixer_selem_get_capture_dB_range"++-----------------------------------------------------------------------+-- set+-- --------------------------------------------------------------------++{#fun snd_mixer_selem_set_playback_volume as setPlaybackVolume+    { withSimpleElement* `SimpleElement'+    , channelToC `Channel'+    , fromIntegral `Integer' } -> `Int' checkSetPlaybackVolume*- #}++checkSetPlaybackVolume = checkResult_ "snd_mixer_selem_set_playback_volume"++{#fun snd_mixer_selem_set_capture_volume as setCaptureVolume+    { withSimpleElement* `SimpleElement'+    , channelToC `Channel'+    , fromIntegral `Integer' } -> `Int' checkSetCaptureVolume*- #}++checkSetCaptureVolume = checkResult_ "snd_mixer_selem_set_capture_volume"++{#fun snd_mixer_selem_set_playback_dB as setPlaybackDb+    { withSimpleElement* `SimpleElement'+    , channelToC `Channel'+    , fromIntegral `Integer'+    , negOne- `Int' } -> `Int' checkSetPlaybackDb*- #}++checkSetPlaybackDb = checkResult_ "snd_mixer_selem_set_playback_dB"++{#fun snd_mixer_selem_set_capture_dB as setCaptureDb+    { withSimpleElement* `SimpleElement'+    , channelToC `Channel'+    , fromIntegral `Integer'+    , negOne- `Int' } -> `Int' checkSetCaptureDb*- #}++checkSetCaptureDb = checkResult_ "snd_mixer_selem_set_capture_dB"++{#fun snd_mixer_selem_set_playback_volume_all as setPlaybackVolumeAll+    { withSimpleElement* `SimpleElement'+    , fromIntegral `Integer' } -> `Int' checkSetPlaybackVolumeAll*- #}++checkSetPlaybackVolumeAll = checkResult_ "snd_mixer_selem_set_playback_volume_all"++{#fun snd_mixer_selem_set_capture_volume_all as setCaptureVolumeAll+    { withSimpleElement* `SimpleElement'+    , fromIntegral `Integer' } -> `Int' checkSetCaptureVolumeAll*- #}++checkSetCaptureVolumeAll = checkResult_ "snd_mixer_selem_set_capture_volume_all"++{#fun snd_mixer_selem_set_playback_dB_all as setPlaybackDbAll+    { withSimpleElement* `SimpleElement'+    , fromIntegral `Integer'+    , negOne- `Int' } -> `Int' checkSetPlaybackDbAll*- #}++checkSetPlaybackDbAll = checkResult_ "snd_mixer_selem_set_playback_dB_all"++{#fun snd_mixer_selem_set_capture_dB_all as setCaptureDbAll+    { withSimpleElement* `SimpleElement'+    , fromIntegral `Integer'+    , negOne- `Int' } -> `Int' checkSetCaptureDbAll*- #}++checkSetCaptureDbAll = checkResult_ "snd_mixer_selem_set_capture_dB_all"++{#fun snd_mixer_selem_set_playback_switch as setPlaybackSwitch+    { withSimpleElement* `SimpleElement'+    , channelToC `Channel'+    , `Bool' } -> `Int' checkSetPlaybackSwitch*- #}++checkSetPlaybackSwitch = checkResult_ "snd_mixer_selem_set_playback_switch"++{#fun snd_mixer_selem_set_capture_switch as setCaptureSwitch+    { withSimpleElement* `SimpleElement'+    , channelToC `Channel'+    , `Bool' } -> `Int' checkSetCaptureSwitch*- #}++checkSetCaptureSwitch = checkResult_ "snd_mixer_selem_set_capture_switch"++{#fun snd_mixer_selem_set_playback_switch_all as setPlaybackSwitchAll+    { withSimpleElement* `SimpleElement'+    , `Bool' } -> `Int' checkSetPlaybackSwitchAll*- #}++checkSetPlaybackSwitchAll = checkResult_ "snd_mixer_selem_set_playback_switch_all"++{#fun snd_mixer_selem_set_capture_switch_all as setCaptureSwitchAll+    { withSimpleElement* `SimpleElement'+    , `Bool' } -> `Int' checkSetCaptureSwitchAll*- #}++checkSetCaptureSwitchAll = checkResult_ "snd_mixer_selem_set_capture_switch_all"++{#fun snd_mixer_selem_set_playback_volume_range as setPlaybackVolumeRange'+    { withSimpleElement* `SimpleElement'+    , fromIntegral `Integer'+    , fromIntegral `Integer' } -> `Int' checkSetPlaybackVolumeRange*- #}++checkSetPlaybackVolumeRange = checkResult_ "snd_mixer_selem_set_playback_volume_range"++{#fun snd_mixer_selem_set_capture_volume_range as setCaptureVolumeRange'+    { withSimpleElement* `SimpleElement'+    , fromIntegral `Integer'+    , fromIntegral `Integer' } -> `Int' checkSetCaptureVolumeRange*- #}++checkSetCaptureVolumeRange = checkResult_ "snd_mixer_selem_set_capture_volume_range"++setPlaybackVolumeRange m = uncurry (setPlaybackVolumeRange' m)+setCaptureVolumeRange m = uncurry (setCaptureVolumeRange' m)
− Sound/ALSA/Mixer/Internal.hs
@@ -1,266 +0,0 @@-{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls, TemplateHaskell #-} -module Sound.ALSA.Mixer.Internal -    ( Mixer()-    , SimpleElement()-    , SimpleElementId()-    , Channel(..)-    , allChannels-    , elements-    , getMixerByName-    , isPlaybackMono-    , isCaptureMono-    , hasPlaybackChannel-    , hasCaptureChannel-    , hasCommonVolume-    , hasPlaybackVolume-    , hasPlaybackVolumeJoined-    , hasCaptureVolume-    , hasCaptureVolumeJoined-    , hasCommonSwitch-    , hasPlaybackSwitch-    , hasPlaybackSwitchJoined-    , hasCaptureSwitch-    , hasCaptureSwitchJoined-    , getPlaybackVolume-    , getCaptureVolume-    , getPlaybackDb-    , getCaptureDb-    , getPlaybackSwitch-    , getCaptureSwitch-    , setPlaybackVolume-    , setCaptureVolume-    , setPlaybackDb-    , setCaptureDb-    , setPlaybackVolumeAll-    , setCaptureVolumeAll-    , setPlaybackDbAll-    , setCaptureDbAll-    , setPlaybackSwitch-    , setCaptureSwitch-    , setPlaybackSwitchAll-    , setCaptureSwitchAll-    , getPlaybackVolumeRange-    , getPlaybackDbRange-    , getCaptureVolumeRange-    , getCaptureDbRange-    , setPlaybackVolumeRange-    , setCaptureVolumeRange-    , getName-    , getIndex-    ) where--import qualified Data.ByteString.Char8 as B-import Foreign-import Foreign.C.Error ( eNOENT )-import Foreign.C.String ( CString )-import Foreign.C.Types-import Sound.ALSA.Exception ( checkResult_, throw )-import Sound.ALSA.Mixer.Templates---------------------------------------------------------------------------- open--- ---------------------------------------------------------------------foreign import ccall "alsa/asoundlib.h snd_mixer_open"-  snd_mixer_open :: Ptr (Ptr MixerT) -> IO CInt---- 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 MixerT -> IO ()) --open :: IO Mixer-open = do-    ppmix <- malloc-    pmix <- do-        snd_mixer_open ppmix >>= checkResult_ "snd_mixer_open"-        peek ppmix-    newForeignPtr snd_mixer_close pmix---------------------------------------------------------------------------- attach--- ---------------------------------------------------------------------foreign import ccall "alsa/asoundlib.h snd_mixer_attach"-  snd_mixer_attach :: Ptr MixerT -> CString -> IO CInt--attach :: Mixer -> String -> IO ()-attach fmix name =-    B.useAsCString (B.pack name) $ \pName ->-        withForeignPtr fmix $ \pmix ->-            snd_mixer_attach pmix pName >>= checkResult_ "snd_mixer_attach"---------------------------------------------------------------------------- load--- ---------------------------------------------------------------------foreign import ccall "alsa/asoundlib.h snd_mixer_load"-  snd_mixer_load :: Ptr MixerT -> IO CInt--foreign import ccall "alsa/asoundlib.h snd_mixer_selem_register"-  snd_mixer_selem_register :: Ptr MixerT -> Ptr () -> Ptr () -> IO CInt--load :: Mixer -> IO ()-load fmix = withForeignPtr fmix $ \pmix -> do-    snd_mixer_selem_register pmix nullPtr nullPtr-        >>= checkResult_ "snd_mixer_selem_register"-    snd_mixer_load pmix >>= checkResult_ "snd_mixer_load"---------------------------------------------------------------------------- getId--- ---------------------------------------------------------------------foreign import ccall "alsa/asoundlib.h snd_mixer_selem_id_malloc"-  snd_mixer_selem_id_malloc :: Ptr (Ptr SimpleElementIdT) -> IO ()--foreign import ccall "alsa/asoundlib.h &snd_mixer_selem_id_free"-  snd_mixer_selem_id_free :: FunPtr (Ptr SimpleElementIdT -> IO ())--foreign import ccall "alsa/asoundlib.h snd_mixer_selem_get_id"-  snd_mixer_selem_get_id :: Element -> Ptr SimpleElementIdT -> IO ()--getId :: Element -> IO SimpleElementId-getId pElem = do-    pId <- alloca $ \ppId -> do-        snd_mixer_selem_id_malloc ppId-        peek ppId-    snd_mixer_selem_get_id pElem pId-    newForeignPtr snd_mixer_selem_id_free pId---------------------------------------------------------------------------- elements--- ---------------------------------------------------------------------foreign import ccall "alsa/asoundlib.h snd_mixer_first_elem"-  snd_mixer_first_elem :: Ptr MixerT -> IO Element--foreign import ccall "alsa/asoundlib.h snd_mixer_last_elem"-  snd_mixer_last_elem :: Ptr MixerT -> IO Element--foreign import ccall "alsa/asoundlib.h snd_mixer_elem_next"-  snd_mixer_elem_next :: Element -> IO Element--elements :: Mixer -> IO [(SimpleElementId, SimpleElement)]-elements fMix = withForeignPtr fMix $ \pMix -> do-    pFirst <- snd_mixer_first_elem pMix-    pLast <- snd_mixer_last_elem pMix-    es <- elements' pFirst [] pLast-    mapM (simpleElement fMix) es-  where elements' pThis xs pLast | pThis == pLast = return $ pThis : xs-                                 | otherwise = do-                                     pNext <- snd_mixer_elem_next pThis-                                     elements' pNext (pThis : xs) pLast---------------------------------------------------------------------------- simpleElement--- ---------------------------------------------------------------------foreign import ccall "alsa/asoundlib.h snd_mixer_find_selem"-  snd_mixer_find_selem :: Ptr MixerT -> Ptr SimpleElementIdT -> IO (Ptr SimpleElementT)--simpleElement :: Mixer -> Element -> IO (SimpleElementId, SimpleElement)-simpleElement fMix pElem = withForeignPtr fMix $ \pMix -> do-    fId <- getId pElem-    pSElem <- withForeignPtr fId $ snd_mixer_find_selem pMix-    if pSElem == nullPtr-        then throw "snd_mixer_find_selem" eNOENT-        else return (fId, (fMix, pSElem))---------------------------------------------------------------------------- getName--- ---------------------------------------------------------------------foreign import ccall "alsa/asoundlib.h snd_mixer_selem_id_get_name"-  snd_mixer_selem_id_get_name :: Ptr SimpleElementIdT -> IO CString--getName :: SimpleElementId -> IO String-getName fId = withForeignPtr fId $ \pId -> do-    cStr <- snd_mixer_selem_id_get_name pId-    bStr <- B.packCString cStr-    return $ B.unpack bStr---------------------------------------------------------------------------- getIndex--- ---------------------------------------------------------------------foreign import ccall "alsa/asoundlib.h snd_mixer_selem_id_get_index"-  snd_mixer_selem_id_get_index :: Ptr SimpleElementIdT -> IO CInt--getIndex :: SimpleElementId -> IO Integer-getIndex fId = withForeignPtr fId $ \pId -> do-    cIndex <- snd_mixer_selem_id_get_index pId-    return $! fromIntegral cIndex---------------------------------------------------------------------------- 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---------------------------------------------------------------------------$(has "snd_mixer_selem_is_playback_mono" "isPlaybackMono")-$(has "snd_mixer_selem_is_capture_mono" "isCaptureMono")-$(has "snd_mixer_selem_has_common_volume" "hasCommonVolume")-$(has "snd_mixer_selem_has_playback_volume" "hasPlaybackVolume")-$(has "snd_mixer_selem_has_playback_volume_joined" "hasPlaybackVolumeJoined")-$(has "snd_mixer_selem_has_capture_volume" "hasCaptureVolume")-$(has "snd_mixer_selem_has_capture_volume_joined" "hasCaptureVolumeJoined")-$(has "snd_mixer_selem_has_common_switch" "hasCommonSwitch")-$(has "snd_mixer_selem_has_playback_switch" "hasPlaybackSwitch")-$(has "snd_mixer_selem_has_playback_switch_joined" "hasPlaybackSwitchJoined")-$(has "snd_mixer_selem_has_capture_switch" "hasCaptureSwitch")-$(has "snd_mixer_selem_has_capture_switch_joined" "hasCaptureSwitchJoined")--has2 :: (Ptr SimpleElementT -> b -> IO CInt) -> SimpleElement -> b -> IO Bool-has2 f (fMix, pElem) y = do-    h <- f pElem y-    touchForeignPtr fMix-    return $! h == 1--hasChannel :: (Ptr SimpleElementT -> CInt -> IO CInt) -> SimpleElement -> Channel -> IO Bool-hasChannel f x chan = has2 f x $ fromIntegral $ fromEnum chan--foreign import ccall "alsa/asoundlib.h snd_mixer_selem_has_playback_channel"-  snd_mixer_selem_has_playback_channel :: Ptr SimpleElementT -> CInt -> IO CInt--hasPlaybackChannel :: SimpleElement -> Channel -> IO Bool-hasPlaybackChannel = hasChannel snd_mixer_selem_has_playback_channel--foreign import ccall "alsa/asoundlib.h snd_mixer_selem_has_capture_channel"-  snd_mixer_selem_has_capture_channel :: Ptr SimpleElementT -> CInt -> IO CInt--hasCaptureChannel :: SimpleElement -> Channel -> IO Bool-hasCaptureChannel = hasChannel snd_mixer_selem_has_capture_channel--$(getVol "snd_mixer_selem_get_playback_volume" "getPlaybackVolume")-$(getVol "snd_mixer_selem_get_capture_volume" "getCaptureVolume")-$(getVol "snd_mixer_selem_get_playback_dB" "getPlaybackDb")-$(getVol "snd_mixer_selem_get_capture_dB" "getCaptureDb")--$(getSwitch "snd_mixer_selem_get_playback_switch" "getPlaybackSwitch")-$(getSwitch "snd_mixer_selem_get_capture_switch" "getCaptureSwitch")--$(setVol "snd_mixer_selem_set_playback_volume" "setPlaybackVolume")-$(setVol "snd_mixer_selem_set_capture_volume" "setCaptureVolume")--$(setDb "snd_mixer_selem_set_playback_dB" "setPlaybackDb")-$(setDb "snd_mixer_selem_set_capture_dB" "setCaptureDb")--$(setVolAll "snd_mixer_selem_set_playback_volume_all" "setPlaybackVolumeAll")-$(setVolAll "snd_mixer_selem_set_capture_volume_all" "setCaptureVolumeAll")--$(setDbAll "snd_mixer_selem_set_playback_dB_all" "setPlaybackDbAll")-$(setDbAll "snd_mixer_selem_set_capture_dB_all" "setCaptureDbAll")--$(setSwitch "snd_mixer_selem_set_playback_switch" "setPlaybackSwitch")-$(setSwitch "snd_mixer_selem_set_capture_switch" "setCaptureSwitch")--$(setSwitchAll "snd_mixer_selem_set_playback_switch_all" "setPlaybackSwitchAll")-$(setSwitchAll "snd_mixer_selem_set_capture_switch_all" "setCaptureSwitchAll")--$(getRange "snd_mixer_selem_get_playback_volume_range" "getPlaybackVolumeRange")-$(getRange "snd_mixer_selem_get_playback_dB_range" "getPlaybackDbRange")-$(getRange "snd_mixer_selem_get_capture_volume_range" "getCaptureVolumeRange")-$(getRange "snd_mixer_selem_get_capture_dB_range" "getCaptureDbRange")--$(setRange "snd_mixer_selem_set_playback_volume_range" "setPlaybackVolumeRange")-$(setRange "snd_mixer_selem_set_capture_volume_range" "setCaptureVolumeRange")
− Sound/ALSA/Mixer/Templates.hs
@@ -1,204 +0,0 @@-{-# LANGUAGE TemplateHaskell, EmptyDataDecls #-}-module Sound.ALSA.Mixer.Templates where--import Foreign-import Foreign.C.Types-import Language.Haskell.TH-import Sound.ALSA.Exception ( checkResult_ )--data MixerT-data ElemT-data SimpleElementIdT-data SimpleElementT--type Mixer = ForeignPtr MixerT-type Element = Ptr ElemT-type SimpleElementId = ForeignPtr SimpleElementIdT-type SimpleElement = (Mixer, Ptr SimpleElementT)--data Channel = Unknown-             | FrontLeft-             | FrontRight-             | RearLeft-             | RearRight-             | FrontCenter-             | Woofer-             | SideLeft-             | SideRight-             | RearCenter-             | OtherChannel Int-    deriving (Read, Show, Eq)--instance Enum Channel where-    fromEnum Unknown = -1-    fromEnum FrontLeft = 0-    fromEnum FrontRight = 1-    fromEnum RearLeft = 2-    fromEnum RearRight = 3-    fromEnum FrontCenter = 4-    fromEnum Woofer = 5-    fromEnum SideLeft = 6-    fromEnum SideRight = 7-    fromEnum RearCenter = 8-    fromEnum (OtherChannel x) = x--    toEnum (-1) = Unknown-    toEnum 0 = FrontLeft-    toEnum 1 = FrontRight-    toEnum 2 = RearLeft-    toEnum 3 = RearRight-    toEnum 4 = FrontCenter-    toEnum 5 = Woofer-    toEnum 6 = SideLeft-    toEnum 7 = SideRight-    toEnum 8 = RearCenter-    toEnum x = OtherChannel x---- | All channels understood by ALSA.-allChannels :: [Channel]-allChannels = map toEnum $ enumFromTo 0 31--has :: String -> String -> Q [Dec]-has = template frgn hask body-  where frgn = [t| Ptr SimpleElementT -> IO CInt |]-        hask = [t| SimpleElement -> IO Bool |]-        body frgnName = [| \(fMix, pElem) -> do ret <- $(varE frgnName) pElem-                                                touchForeignPtr fMix-                                                return $ 1 == ret-                         |]--getVol :: String -> String -> Q [Dec]-getVol frgnStr = template frgn hask body frgnStr-  where frgn = [t| Ptr SimpleElementT -> CInt -> Ptr CLong -> IO CInt |]-        hask = [t| SimpleElement -> Channel -> IO Integer |]-        body frgnName = [| \(fMix, pElem) chan -> do-                               let iChan = fromIntegral $! fromEnum chan-                               vol <- alloca $ \pVol -> do-                                   ret <- $(varE frgnName) pElem iChan pVol-                                   checkResult_ frgnStr ret-                                   peek pVol-                               touchForeignPtr fMix-                               return $! fromIntegral vol-                         |]--getSwitch :: String -> String -> Q [Dec]-getSwitch frgnStr = template frgn hask body frgnStr-  where frgn = [t| Ptr SimpleElementT -> CInt -> Ptr CInt -> IO CInt |]-        hask = [t| SimpleElement -> Channel -> IO Bool |]-        body frgnName = [| \(fMix, pElem) chan -> do-                               let iChan = fromIntegral $! fromEnum chan-                               iBool <- alloca $ \pBool -> do-                                   ret <- $(varE frgnName) pElem iChan pBool-                                   checkResult_ frgnStr ret-                                   peek pBool-                               touchForeignPtr fMix-                               return $! iBool == 1 -                         |]--setVol :: String -> String -> Q [Dec]-setVol frgnStr = template frgn hask body frgnStr-  where frgn = [t| Ptr SimpleElementT -> CInt -> CLong -> IO CInt |]-        hask = [t| SimpleElement -> Channel -> Integer -> IO () |]-        body frgnName = [| \(fMix, pElem) chan vol -> do-                               let iChan = fromIntegral $! fromEnum chan-                                   iVol = fromIntegral $! vol-                               ret <- $(varE frgnName) pElem iChan iVol-                               touchForeignPtr fMix-                               checkResult_ frgnStr ret-                         |]--setDb :: String -> String -> Q [Dec]-setDb frgnStr = template frgn hask body frgnStr-  where frgn = [t| Ptr SimpleElementT -> CInt -> CLong -> CInt -> IO CInt |]-        hask = [t| SimpleElement -> Channel -> Integer -> IO () |]-        body frgnName = [| \(fMix, pElem) chan vol -> do-                               let iChan = fromIntegral $! fromEnum chan-                                   iVol = fromIntegral $! vol-                               ret <- $(varE frgnName) pElem iChan iVol (-1)-                               touchForeignPtr fMix-                               checkResult_ frgnStr ret-                         |]--setVolAll :: String -> String -> Q [Dec]-setVolAll frgnStr = template frgn hask body frgnStr-  where frgn = [t| Ptr SimpleElementT -> CLong -> IO CInt |]-        hask = [t| SimpleElement -> Integer -> IO () |]-        body frgnName = [| \(fMix, pElem) vol -> do-                               let iVol = fromIntegral $! vol-                               ret <- $(varE frgnName) pElem iVol-                               touchForeignPtr fMix-                               checkResult_ frgnStr ret-                         |]--setDbAll :: String -> String -> Q [Dec]-setDbAll frgnStr = template frgn hask body frgnStr-  where frgn = [t| Ptr SimpleElementT -> CLong -> CInt -> IO CInt |]-        hask = [t| SimpleElement -> Integer -> IO () |]-        body frgnName = [| \(fMix, pElem) vol -> do-                               let iVol = fromIntegral $! vol-                               ret <- $(varE frgnName) pElem iVol (-1)-                               touchForeignPtr fMix-                               checkResult_ frgnStr ret-                         |]--setSwitch :: String -> String -> Q [Dec]-setSwitch frgnStr = template frgn hask body frgnStr-  where frgn = [t| Ptr SimpleElementT -> CInt -> CInt -> IO CInt |]-        hask = [t| SimpleElement -> Channel -> Bool -> IO () |]-        body frgnName = [| \(fMix, pElem) chan bool -> do-                               let iChan = fromIntegral $! fromEnum chan -                                   iBool = if bool then 1 else 0-                               ret <- $(varE frgnName) pElem iChan iBool-                               touchForeignPtr fMix-                               checkResult_ frgnStr ret-                         |]--setSwitchAll :: String -> String -> Q [Dec]-setSwitchAll frgnStr = template frgn hask body frgnStr-  where frgn = [t| Ptr SimpleElementT -> CInt -> IO CInt |]-        hask = [t| SimpleElement -> Bool -> IO () |]-        body frgnName = [| \(fMix, pElem) bool -> do-                               let iBool = if bool then 1 else 0-                               ret <- $(varE frgnName) pElem iBool-                               touchForeignPtr fMix-                               checkResult_ frgnStr ret-                         |]--getRange :: String -> String -> Q [Dec]-getRange frgnStr = template frgn hask body frgnStr-  where frgn = [t| Ptr SimpleElementT -> Ptr CLong -> Ptr CLong -> IO CInt |]-        hask = [t| SimpleElement -> IO (Integer, Integer) |]-        body frgnName = [| \(fMix, pElem) ->-                               alloca $ \pMin ->-                                 alloca $ \pMax -> do-                                   ret <- $(varE frgnName) pElem pMin pMax-                                   checkResult_ frgnStr ret-                                   cMin <- peek pMin-                                   cMax <- peek pMax-                                   touchForeignPtr fMix-                                   return (fromIntegral cMin, fromIntegral cMax)-                         |]--setRange :: String -> String -> Q [Dec]-setRange frgnStr = template frgn hask body frgnStr-  where frgn = [t| Ptr SimpleElementT -> CLong -> CLong -> IO CInt |]-        hask = [t| SimpleElement -> (Integer, Integer) -> IO () |]-        body frgnName = [| \(fMix, pElem) (cMin, cMax) -> do-                               let iMin = fromIntegral $! cMin-                                   iMax = fromIntegral $! cMax-                               ret <- $(varE frgnName) pElem iMin iMax-                               touchForeignPtr fMix-                               checkResult_ frgnStr ret-                         |]--template :: Q Type -> Q Type -> (Name -> Q Exp) -> String -> String -> Q [Dec]-template frgnType haskType body frgn hask = do-    let frgnImp = "alsa/asoundlib.h " ++ frgn-        frgnName = mkName frgn-        haskName = mkName hask-    frgnDec <- forImpD cCall safe frgnImp frgnName frgnType-    let haskBody = normalB $ body frgnName-        haskClause = clause [] haskBody []-    haskDec <- funD haskName [ haskClause ]-    haskSig <- sigD haskName haskType-    return [ frgnDec, haskSig, haskDec ]
alsa-mixer.cabal view
@@ -1,5 +1,5 @@ Name:                alsa-mixer-Version:             0.1+Version:             0.1.1 Synopsis:            Bindings to the ALSA simple mixer API. Description:         This package provides bindings to the ALSA simple mixer API. License:             BSD3@@ -17,9 +17,7 @@  Library   Exposed-modules:     Sound.ALSA.Mixer-  Other-modules:       Sound.ALSA.Mixer.Internal, Sound.ALSA.Mixer.Templates+  Other-modules:       Sound.ALSA.Mixer.Internal   Extra-libraries:     asound   Build-depends:       base == 4.*,-                       alsa-core == 0.5.*,-                       bytestring == 0.9.*,-                       template-haskell+                       alsa-core == 0.5.*