packages feed

alsa-pcm 0.5.0.1 → 0.6

raw patch · 20 files changed

+2037/−1019 lines, 20 filesdep +containersdep +storable-recorddep +transformersdep ~alsa-seqdep ~arraynew-component:exe:alsa-sinePVP ok

version bump matches the API change (PVP)

Dependencies added: containers, storable-record, transformers

Dependency ranges changed: alsa-seq, array

API changes (from Hackage documentation)

- Sound.ALSA.PCM: data Pcm
- Sound.ALSA.PCM: instance SampleFmt Double
- Sound.ALSA.PCM: instance SampleFmt Float
- Sound.ALSA.PCM: instance SampleFmt Int16
- Sound.ALSA.PCM: instance SampleFmt Int32
- Sound.ALSA.PCM: instance SampleFmt Int8
- Sound.ALSA.PCM: instance SampleFmt T
- Sound.ALSA.PCM: instance SampleFmt Word16
- Sound.ALSA.PCM: instance SampleFmt Word32
- Sound.ALSA.PCM: instance SampleFmt Word8
- Sound.ALSA.PCM: instance SampleFmt a => SampleFmt (T a)
- Sound.ALSA.PCM: soundSinkFmt :: SoundSink y handle -> SoundFmt y
- Sound.ALSA.PCM: soundSourceFmt :: SoundSource y handle -> SoundFmt y
+ Sound.ALSA.PCM: alsaSoundSinkParams :: SampleFmt y => String -> T Interleaved y a -> (a -> T Interleaved y ()) -> SoundSink Pcm y
+ Sound.ALSA.PCM: alsaSoundSourceParams :: SampleFmt y => String -> T Interleaved y a -> (a -> T Interleaved y ()) -> SoundSource Pcm y
+ Sound.ALSA.PCM: type File = Handle
+ Sound.ALSA.PCM: type Pcm = Handle Interleaved
+ Sound.ALSA.PCM: type Size = Int
+ Sound.ALSA.PCM.Node.ALSA: StreamCapture :: Stream
+ Sound.ALSA.PCM.Node.ALSA: StreamPlayback :: Stream
+ Sound.ALSA.PCM.Node.ALSA: async :: Mode
+ Sound.ALSA.PCM.Node.ALSA: class Access i
+ Sound.ALSA.PCM.Node.ALSA: class SampleFmt y => MonoSampleFmt y
+ Sound.ALSA.PCM.Node.ALSA: class (Storable y, C y) => SampleFmt y
+ Sound.ALSA.PCM.Node.ALSA: close :: Handle i y -> IO ()
+ Sound.ALSA.PCM.Node.ALSA: data Handle i y
+ Sound.ALSA.PCM.Node.ALSA: data Interleaved
+ Sound.ALSA.PCM.Node.ALSA: data Mode
+ Sound.ALSA.PCM.Node.ALSA: data Noninterleaved
+ Sound.ALSA.PCM.Node.ALSA: data Stream
+ Sound.ALSA.PCM.Node.ALSA: drain :: Handle i y -> IO ()
+ Sound.ALSA.PCM.Node.ALSA: drop :: Handle i y -> IO ()
+ Sound.ALSA.PCM.Node.ALSA: modes :: [Mode] -> Mode
+ Sound.ALSA.PCM.Node.ALSA: nonBlock :: Mode
+ Sound.ALSA.PCM.Node.ALSA: open :: (Access i, SampleFmt y) => Mode -> Stream -> T i y a -> (a -> T i y b) -> String -> IO (b, Handle i y)
+ Sound.ALSA.PCM.Node.ALSA: prepare :: Handle i y -> IO ()
+ Sound.ALSA.PCM.Node.ALSA: readi :: SampleFmt y => Handle Interleaved y -> Ptr y -> Size -> IO Size
+ Sound.ALSA.PCM.Node.ALSA: readiRetry :: SampleFmt y => Handle Interleaved y -> Ptr y -> Size -> IO Size
+ Sound.ALSA.PCM.Node.ALSA: readn :: MonoSampleFmt y => Handle Noninterleaved y -> Ptr (Ptr y) -> Size -> IO Size
+ Sound.ALSA.PCM.Node.ALSA: start :: Handle i y -> IO ()
+ Sound.ALSA.PCM.Node.ALSA: type SampleFreq = Int
+ Sound.ALSA.PCM.Node.ALSA: type Size = Int
+ Sound.ALSA.PCM.Node.ALSA: type Time = Int
+ Sound.ALSA.PCM.Node.ALSA: writei :: SampleFmt y => Handle Interleaved y -> Ptr y -> Size -> IO Size
+ Sound.ALSA.PCM.Node.ALSA: writeiRetry :: SampleFmt y => Handle Interleaved y -> Ptr y -> Size -> IO Size
+ Sound.ALSA.PCM.Node.ALSA: writen :: MonoSampleFmt y => Handle Noninterleaved y -> Ptr (Ptr y) -> Size -> IO Size
+ Sound.ALSA.PCM.Node.File: class (Storable y, C y) => SampleFmt y
+ Sound.ALSA.PCM.Node.File: close :: SampleFmt y => Handle y -> IO ()
+ Sound.ALSA.PCM.Node.File: data Handle y
+ Sound.ALSA.PCM.Node.File: open :: SampleFmt y => IOMode -> FilePath -> IO (Handle y)
+ Sound.ALSA.PCM.Node.File: read :: SampleFmt y => Handle y -> Ptr y -> Size -> IO Size
+ Sound.ALSA.PCM.Node.File: type SampleFreq = Int
+ Sound.ALSA.PCM.Node.File: type Size = Int
+ Sound.ALSA.PCM.Node.File: type Time = Int
+ Sound.ALSA.PCM.Node.File: write :: SampleFmt y => Handle y -> Ptr y -> Size -> IO ()
+ Sound.ALSA.PCM.Parameters.Hardware: canMmapSampleResolution :: T i y (Bool)
+ Sound.ALSA.PCM.Parameters.Hardware: canOverrange :: T i y (Bool)
+ Sound.ALSA.PCM.Parameters.Hardware: canPause :: T i y (Bool)
+ Sound.ALSA.PCM.Parameters.Hardware: canResume :: T i y (Bool)
+ Sound.ALSA.PCM.Parameters.Hardware: canSyncStart :: T i y (Bool)
+ Sound.ALSA.PCM.Parameters.Hardware: data Interleaved
+ Sound.ALSA.PCM.Parameters.Hardware: data Noninterleaved
+ Sound.ALSA.PCM.Parameters.Hardware: data T i y a
+ Sound.ALSA.PCM.Parameters.Hardware: getBufferSize :: T i y (Size)
+ Sound.ALSA.PCM.Parameters.Hardware: getBufferSizeMax :: T i y (Size)
+ Sound.ALSA.PCM.Parameters.Hardware: getBufferSizeMin :: T i y (Size)
+ Sound.ALSA.PCM.Parameters.Hardware: getBufferTime :: T i y (Time, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: getBufferTimeMax :: T i y (Time, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: getBufferTimeMin :: T i y (Time, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: getChannels :: T i y (Word)
+ Sound.ALSA.PCM.Parameters.Hardware: getChannelsMax :: T i y (Word)
+ Sound.ALSA.PCM.Parameters.Hardware: getChannelsMin :: T i y (Word)
+ Sound.ALSA.PCM.Parameters.Hardware: getExportBuffer :: T i y (Bool)
+ Sound.ALSA.PCM.Parameters.Hardware: getFifoSize :: T i y (Word)
+ Sound.ALSA.PCM.Parameters.Hardware: getMinAlign :: T i y (Size)
+ Sound.ALSA.PCM.Parameters.Hardware: getPeriodSize :: T i y (Size, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: getPeriodSizeMax :: T i y (Size, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: getPeriodSizeMin :: T i y (Size, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: getPeriodTime :: T i y (Time, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: getPeriodTimeMax :: T i y (Time, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: getPeriodTimeMin :: T i y (Time, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: getPeriods :: T i y (Word, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: getPeriodsMax :: T i y (Word, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: getPeriodsMin :: T i y (Word, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: getRate :: T i y (SampleFreq, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: getRateMax :: T i y (SampleFreq, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: getRateMin :: T i y (SampleFreq, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: getRateNumden :: T i y (Word, Word)
+ Sound.ALSA.PCM.Parameters.Hardware: getRateResample :: T i y (Bool)
+ Sound.ALSA.PCM.Parameters.Hardware: getSbits :: T i y (Word)
+ Sound.ALSA.PCM.Parameters.Hardware: getTickTime :: T i y (Time, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: getTickTimeMax :: T i y (Time, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: getTickTimeMin :: T i y (Time, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: isBatch :: T i y (Bool)
+ Sound.ALSA.PCM.Parameters.Hardware: isBlockTransfer :: T i y (Bool)
+ Sound.ALSA.PCM.Parameters.Hardware: isDouble :: T i y (Bool)
+ Sound.ALSA.PCM.Parameters.Hardware: isHalfDuplex :: T i y (Bool)
+ Sound.ALSA.PCM.Parameters.Hardware: isJointDuplex :: T i y (Bool)
+ Sound.ALSA.PCM.Parameters.Hardware: setBufferSize :: Size -> T i y ()
+ Sound.ALSA.PCM.Parameters.Hardware: setBufferSizeFirst :: Size -> T i y (Size)
+ Sound.ALSA.PCM.Parameters.Hardware: setBufferSizeLast :: Size -> T i y (Size)
+ Sound.ALSA.PCM.Parameters.Hardware: setBufferSizeMax :: Size -> T i y (Size)
+ Sound.ALSA.PCM.Parameters.Hardware: setBufferSizeMin :: Size -> T i y (Size)
+ Sound.ALSA.PCM.Parameters.Hardware: setBufferSizeMinmax :: Size -> Size -> T i y (Size, Size)
+ Sound.ALSA.PCM.Parameters.Hardware: setBufferSizeNear :: Size -> T i y (Size)
+ Sound.ALSA.PCM.Parameters.Hardware: setBufferTime :: Time -> Ordering -> T i y ()
+ Sound.ALSA.PCM.Parameters.Hardware: setBufferTimeFirst :: Time -> Ordering -> T i y (Time, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setBufferTimeLast :: Time -> Ordering -> T i y (Time, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setBufferTimeMax :: Time -> Ordering -> T i y (Time, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setBufferTimeMin :: Time -> Ordering -> T i y (Time, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setBufferTimeMinmax :: Time -> Ordering -> Time -> Ordering -> T i y (Time, Ordering, Time, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setBufferTimeNear :: Time -> Ordering -> T i y (Time, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setChannels :: Word -> T Noninterleaved y ()
+ Sound.ALSA.PCM.Parameters.Hardware: setChannelsFirst :: Word -> T Noninterleaved y Word
+ Sound.ALSA.PCM.Parameters.Hardware: setChannelsLast :: Word -> T Noninterleaved y Word
+ Sound.ALSA.PCM.Parameters.Hardware: setChannelsMax :: Word -> T Noninterleaved y Word
+ Sound.ALSA.PCM.Parameters.Hardware: setChannelsMin :: Word -> T Noninterleaved y Word
+ Sound.ALSA.PCM.Parameters.Hardware: setChannelsMinmax :: Word -> Word -> T Noninterleaved y (Word, Word)
+ Sound.ALSA.PCM.Parameters.Hardware: setChannelsNear :: Word -> T Noninterleaved y Word
+ Sound.ALSA.PCM.Parameters.Hardware: setExportBuffer :: Bool -> T i y ()
+ Sound.ALSA.PCM.Parameters.Hardware: setPeriodSize :: Size -> Ordering -> T i y ()
+ Sound.ALSA.PCM.Parameters.Hardware: setPeriodSizeFirst :: Size -> Ordering -> T i y (Size, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setPeriodSizeInteger :: T i y ()
+ Sound.ALSA.PCM.Parameters.Hardware: setPeriodSizeLast :: Size -> Ordering -> T i y (Size, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setPeriodSizeMax :: Size -> Ordering -> T i y (Size, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setPeriodSizeMin :: Size -> Ordering -> T i y (Size, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setPeriodSizeMinmax :: Size -> Ordering -> Size -> Ordering -> T i y (Size, Ordering, Size, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setPeriodSizeNear :: Size -> Ordering -> T i y (Size, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setPeriodTime :: Time -> Ordering -> T i y ()
+ Sound.ALSA.PCM.Parameters.Hardware: setPeriodTimeFirst :: Time -> Ordering -> T i y (Time, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setPeriodTimeLast :: Time -> Ordering -> T i y (Time, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setPeriodTimeMax :: Time -> Ordering -> T i y (Time, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setPeriodTimeMin :: Time -> Ordering -> T i y (Time, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setPeriodTimeMinmax :: Time -> Ordering -> Time -> Ordering -> T i y (Time, Ordering, Time, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setPeriodTimeNear :: Time -> Ordering -> T i y (Time, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setPeriods :: Word -> Ordering -> T i y ()
+ Sound.ALSA.PCM.Parameters.Hardware: setPeriodsFirst :: Word -> Ordering -> T i y (Word, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setPeriodsInteger :: T i y ()
+ Sound.ALSA.PCM.Parameters.Hardware: setPeriodsLast :: Word -> Ordering -> T i y (Word, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setPeriodsMax :: Word -> Ordering -> T i y (Word, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setPeriodsMin :: Word -> Ordering -> T i y (Word, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setPeriodsMinmax :: Word -> Ordering -> Word -> Ordering -> T i y (Word, Ordering, Word, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setPeriodsNear :: Word -> Ordering -> T i y (Word, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setRate :: SampleFreq -> Ordering -> T i y ()
+ Sound.ALSA.PCM.Parameters.Hardware: setRateBufferTime :: SampleFreq -> Time -> Time -> T Interleaved y (Size, Size)
+ Sound.ALSA.PCM.Parameters.Hardware: setRateFirst :: SampleFreq -> Ordering -> T i y (SampleFreq, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setRateLast :: SampleFreq -> Ordering -> T i y (SampleFreq, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setRateMax :: SampleFreq -> Ordering -> T i y (SampleFreq, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setRateMin :: SampleFreq -> Ordering -> T i y (SampleFreq, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setRateMinmax :: SampleFreq -> Ordering -> SampleFreq -> Ordering -> T i y (SampleFreq, Ordering, SampleFreq, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setRateNear :: SampleFreq -> Ordering -> T i y (SampleFreq, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setRateResample :: Bool -> T i y ()
+ Sound.ALSA.PCM.Parameters.Hardware: setTickTime :: Time -> Ordering -> T i y ()
+ Sound.ALSA.PCM.Parameters.Hardware: setTickTimeFirst :: Time -> Ordering -> T i y (Time, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setTickTimeLast :: Time -> Ordering -> T i y (Time, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setTickTimeMax :: Time -> Ordering -> T i y (Time, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setTickTimeMin :: Time -> Ordering -> T i y (Time, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setTickTimeMinmax :: Time -> Ordering -> Time -> Ordering -> T i y (Time, Ordering, Time, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: setTickTimeNear :: Time -> Ordering -> T i y (Time, Ordering)
+ Sound.ALSA.PCM.Parameters.Hardware: testBufferSize :: Size -> T i y (Errno)
+ Sound.ALSA.PCM.Parameters.Hardware: testBufferTime :: Time -> Ordering -> T i y (Errno)
+ Sound.ALSA.PCM.Parameters.Hardware: testChannels :: Word -> T i y (Errno)
+ Sound.ALSA.PCM.Parameters.Hardware: testPeriodSize :: Size -> Ordering -> T i y (Errno)
+ Sound.ALSA.PCM.Parameters.Hardware: testPeriodTime :: Time -> Ordering -> T i y (Errno)
+ Sound.ALSA.PCM.Parameters.Hardware: testPeriods :: Word -> Ordering -> T i y (Errno)
+ Sound.ALSA.PCM.Parameters.Hardware: testRate :: SampleFreq -> Ordering -> T i y (Errno)
+ Sound.ALSA.PCM.Parameters.Hardware: testTickTime :: Time -> Ordering -> T i y (Errno)
+ Sound.ALSA.PCM.Parameters.Hardware: type SampleFreq = Int
+ Sound.ALSA.PCM.Parameters.Hardware: type Size = Int
+ Sound.ALSA.PCM.Parameters.Hardware: type Time = Int
+ Sound.ALSA.PCM.Parameters.Software: data T i y a
+ Sound.ALSA.PCM.Parameters.Software: data TimestampMode
+ Sound.ALSA.PCM.Parameters.Software: getAvailMin :: T i y Size
+ Sound.ALSA.PCM.Parameters.Software: getSilenceSize :: T i y Size
+ Sound.ALSA.PCM.Parameters.Software: getSilenceThreshold :: T i y Size
+ Sound.ALSA.PCM.Parameters.Software: getSleepMin :: T i y Word
+ Sound.ALSA.PCM.Parameters.Software: getStartThreshold :: T i y Size
+ Sound.ALSA.PCM.Parameters.Software: getStopThreshold :: T i y Size
+ Sound.ALSA.PCM.Parameters.Software: getTimestampMode :: T i y TimestampMode
+ Sound.ALSA.PCM.Parameters.Software: getXferAlign :: T i y Size
+ Sound.ALSA.PCM.Parameters.Software: setAvailMin :: Size -> T i y ()
+ Sound.ALSA.PCM.Parameters.Software: setBufferSize :: Size -> Size -> T i y ()
+ Sound.ALSA.PCM.Parameters.Software: setSilenceSize :: Size -> T i y ()
+ Sound.ALSA.PCM.Parameters.Software: setSilenceThreshold :: Size -> T i y ()
+ Sound.ALSA.PCM.Parameters.Software: setSleepMin :: Word -> T i y ()
+ Sound.ALSA.PCM.Parameters.Software: setStartThreshold :: Size -> T i y ()
+ Sound.ALSA.PCM.Parameters.Software: setStopThreshold :: Size -> T i y ()
+ Sound.ALSA.PCM.Parameters.Software: setTimestampMode :: TimestampMode -> T i y ()
+ Sound.ALSA.PCM.Parameters.Software: setXferAlign :: Size -> T i y ()
+ Sound.ALSA.PCM.Parameters.Software: timestampMmap :: TimestampMode
+ Sound.ALSA.PCM.Parameters.Software: timestampNone :: TimestampMode
+ Sound.ALSA.PCM.Parameters.Software: type Size = Int
- Sound.ALSA.PCM: SoundSink :: SoundFmt y -> IO handle -> (handle -> IO ()) -> (handle -> Ptr y -> Int -> IO ()) -> (handle -> IO ()) -> (handle -> IO ()) -> SoundSink y handle
+ Sound.ALSA.PCM: SoundSink :: IO (handle y) -> (handle y -> IO ()) -> (handle y -> Ptr y -> Size -> IO ()) -> (handle y -> IO ()) -> (handle y -> IO ()) -> SoundSink handle y
- Sound.ALSA.PCM: SoundSource :: SoundFmt y -> IO handle -> (handle -> IO ()) -> (handle -> IO ()) -> (handle -> IO ()) -> (handle -> Ptr y -> Int -> IO Int) -> SoundSource y handle
+ Sound.ALSA.PCM: SoundSource :: IO (handle y) -> (handle y -> IO ()) -> (handle y -> IO ()) -> (handle y -> IO ()) -> (handle y -> Ptr y -> Size -> IO Size) -> SoundSource handle y
- Sound.ALSA.PCM: alsaSoundSink :: SampleFmt y => String -> SoundFmt y -> SoundSink y Pcm
+ Sound.ALSA.PCM: alsaSoundSink :: SampleFmt y => String -> SoundFmt y -> SoundSink Pcm y
- Sound.ALSA.PCM: alsaSoundSinkTime :: SampleFmt y => String -> SoundFmt y -> SoundBufferTime -> SoundSink y Pcm
+ Sound.ALSA.PCM: alsaSoundSinkTime :: SampleFmt y => String -> SoundFmt y -> SoundBufferTime -> SoundSink Pcm y
- Sound.ALSA.PCM: alsaSoundSource :: SampleFmt y => String -> SoundFmt y -> SoundSource y Pcm
+ Sound.ALSA.PCM: alsaSoundSource :: SampleFmt y => String -> SoundFmt y -> SoundSource Pcm y
- Sound.ALSA.PCM: alsaSoundSourceTime :: SampleFmt y => String -> SoundFmt y -> SoundBufferTime -> SoundSource y Pcm
+ Sound.ALSA.PCM: alsaSoundSourceTime :: SampleFmt y => String -> SoundFmt y -> SoundBufferTime -> SoundSource Pcm y
- Sound.ALSA.PCM: copySound :: SampleFmt y => SoundSource y h1 -> SoundSink y h2 -> Int -> IO ()
+ Sound.ALSA.PCM: copySound :: SampleFmt y => SoundSource handleIn y -> SoundSink handleOut y -> Size -> IO ()
- Sound.ALSA.PCM: data SoundSink y handle
+ Sound.ALSA.PCM: data SoundSink handle y
- Sound.ALSA.PCM: data SoundSource y handle
+ Sound.ALSA.PCM: data SoundSource handle y
- Sound.ALSA.PCM: fileSoundSink :: SampleFmt y => FilePath -> SoundFmt y -> SoundSink y Handle
+ Sound.ALSA.PCM: fileSoundSink :: SampleFmt y => FilePath -> SoundSink File y
- Sound.ALSA.PCM: fileSoundSource :: SampleFmt y => FilePath -> SoundFmt y -> SoundSource y Handle
+ Sound.ALSA.PCM: fileSoundSource :: SampleFmt y => FilePath -> SoundSource File y
- Sound.ALSA.PCM: soundSinkBytesPerFrame :: SampleFmt y => SoundSink y h -> Int
+ Sound.ALSA.PCM: soundSinkBytesPerFrame :: SampleFmt y => SoundSink handle y -> Int
- Sound.ALSA.PCM: soundSinkClose :: SoundSink y handle -> handle -> IO ()
+ Sound.ALSA.PCM: soundSinkClose :: SoundSink handle y -> handle y -> IO ()
- Sound.ALSA.PCM: soundSinkOpen :: SoundSink y handle -> IO handle
+ Sound.ALSA.PCM: soundSinkOpen :: SoundSink handle y -> IO (handle y)
- Sound.ALSA.PCM: soundSinkStart :: SoundSink y handle -> handle -> IO ()
+ Sound.ALSA.PCM: soundSinkStart :: SoundSink handle y -> handle y -> IO ()
- Sound.ALSA.PCM: soundSinkStop :: SoundSink y handle -> handle -> IO ()
+ Sound.ALSA.PCM: soundSinkStop :: SoundSink handle y -> handle y -> IO ()
- Sound.ALSA.PCM: soundSinkWrite :: SoundSink y handle -> handle -> Ptr y -> Int -> IO ()
+ Sound.ALSA.PCM: soundSinkWrite :: SoundSink handle y -> handle y -> Ptr y -> Size -> IO ()
- Sound.ALSA.PCM: soundSourceBytesPerFrame :: SampleFmt y => SoundSource y h -> Int
+ Sound.ALSA.PCM: soundSourceBytesPerFrame :: SampleFmt y => SoundSource handle y -> Int
- Sound.ALSA.PCM: soundSourceClose :: SoundSource y handle -> handle -> IO ()
+ Sound.ALSA.PCM: soundSourceClose :: SoundSource handle y -> handle y -> IO ()
- Sound.ALSA.PCM: soundSourceOpen :: SoundSource y handle -> IO handle
+ Sound.ALSA.PCM: soundSourceOpen :: SoundSource handle y -> IO (handle y)
- Sound.ALSA.PCM: soundSourceRead :: SoundSource y handle -> handle -> Ptr y -> Int -> IO Int
+ Sound.ALSA.PCM: soundSourceRead :: SoundSource handle y -> handle y -> Ptr y -> Size -> IO Size
- Sound.ALSA.PCM: soundSourceStart :: SoundSource y handle -> handle -> IO ()
+ Sound.ALSA.PCM: soundSourceStart :: SoundSource handle y -> handle y -> IO ()
- Sound.ALSA.PCM: soundSourceStop :: SoundSource y handle -> handle -> IO ()
+ Sound.ALSA.PCM: soundSourceStop :: SoundSource handle y -> handle y -> IO ()
- Sound.ALSA.PCM: withSoundSink :: SoundSink y h -> (h -> IO a) -> IO a
+ Sound.ALSA.PCM: withSoundSink :: SoundSink handle y -> (handle y -> IO a) -> IO a
- Sound.ALSA.PCM: withSoundSinkRunning :: SoundSink y h -> h -> IO a -> IO a
+ Sound.ALSA.PCM: withSoundSinkRunning :: SoundSink handle y -> handle y -> IO a -> IO a
- Sound.ALSA.PCM: withSoundSource :: SoundSource y h -> (h -> IO a) -> IO a
+ Sound.ALSA.PCM: withSoundSource :: SoundSource handle y -> (handle y -> IO a) -> IO a
- Sound.ALSA.PCM: withSoundSourceRunning :: SoundSource y h -> h -> IO a -> IO a
+ Sound.ALSA.PCM: withSoundSourceRunning :: SoundSource handle y -> handle y -> IO a -> IO a

Files

alsa-pcm.cabal view
@@ -1,5 +1,5 @@ Name:          alsa-pcm-Version:       0.5.0.1+Version:       0.6 Copyright:     Bjorn Bringert, Iavor S. Diatchki, Henning Thielemann Maintainer:    Henning Thielemann <alsa@henning-thielemann.de> Author:        Henning Thielemann <alsa@henning-thielemann.de>, Bjorn Bringert <bjorn@bringert.net>, Iavor S. Diatchki <iavor.diatchki@gmail.com>@@ -19,6 +19,7 @@ Extra-Source-Files:   nodebug/Sound/ALSA/PCM/Debug.hs   debug/Sound/ALSA/PCM/Debug.hs+  src/Sound/ALSA/PCM/Core/Params.h  Source-Repository head   type:     darcs@@ -27,7 +28,7 @@ Source-Repository this   type:     darcs   location: http://code.haskell.org/alsa/pcm/-  tag:      0.5.0.1+  tag:      0.6  Flag buildExamples   description: Build example executables@@ -44,12 +45,14 @@ Library   Build-depends:     alsa-core >=0.5 && <0.6,+    storable-record >=0.0.2 && <0.1,     sample-frame >=0.0.1 && <0.1,-    array >= 0.1 && <0.4,+    array >= 0.1 && <0.5,     extensible-exceptions >=0.1.1 && <0.2,     base >= 3 && <5    Hs-Source-Dirs: src+  Include-Dirs: src   If flag(debug)     Hs-Source-Dirs: debug   Else@@ -57,10 +60,17 @@    Exposed-Modules:     Sound.ALSA.PCM+    Sound.ALSA.PCM.Node.ALSA+    Sound.ALSA.PCM.Node.File+    Sound.ALSA.PCM.Parameters.Hardware+    Sound.ALSA.PCM.Parameters.Software    Other-modules:-    Sound.ALSA.PCM.Core-    Sound.ALSA.PCM.C2HS+    Sound.ALSA.PCM.Core.Class+    Sound.ALSA.PCM.Core.Handle+    Sound.ALSA.PCM.Core.Convert+    Sound.ALSA.PCM.Core.HwParams+    Sound.ALSA.PCM.Core.SwParams     Sound.ALSA.PCM.Debug    GHC-Options: -Wall -fwarn-tabs@@ -70,77 +80,125 @@  Executable alsa-minisynth   Main-Is: synth.hs-  If !flag(buildSynthesizer)+  If flag(buildSynthesizer)+    Build-Depends:+      alsa-seq >=0.6 && <0.7,+      alsa-core >=0.5 && <0.6,+      containers >=0.2 && <0.5,+      transformers >=0.2 && <0.4,+      storablevector >=0.2.7 && <0.3,+      storable-record >=0.0.2 && <0.1,+      sample-frame >=0.0.1 && <0.1,+      base >=3 && <5+  Else     Buildable: False   Hs-Source-Dirs: src, debug, examples+  Include-Dirs: src   GHC-Options: -Wall -threaded   Other-modules:     Sound.ALSA.PCM-    Sound.ALSA.PCM.Core-    Sound.ALSA.PCM.C2HS-  Build-Depends:-    alsa-seq >=0.5 && <0.6,-    alsa-core >=0.5 && <0.6,-    storablevector >=0.2.7 && <0.3,-    sample-frame >=0.0.1 && <0.1,-    base >=3 && <5+    Sound.ALSA.PCM.Core.Class+    Sound.ALSA.PCM.Core.Handle+    Sound.ALSA.PCM.Core.HwParams+    Sound.ALSA.PCM.Core.SwParams +Executable alsa-sine+  Main-Is: sine.hs+  If flag(buildSynthesizer)+    Build-Depends:+      alsa-core >=0.5 && <0.6,+      storablevector >=0.2.7 && <0.3,+      storable-record >=0.0.2 && <0.1,+      sample-frame >=0.0.1 && <0.1,+      base >=3 && <5+  Else+    Buildable: False+  Hs-Source-Dirs: src, debug, examples+  Include-Dirs: src+  GHC-Options: -Wall -threaded+  Other-modules:+    Sound.ALSA.PCM+    Sound.ALSA.PCM.Core.Class+    Sound.ALSA.PCM.Core.Handle+    Sound.ALSA.PCM.Core.HwParams+    Sound.ALSA.PCM.Core.SwParams+ Executable alsa-duplex   Main-Is: duplex.hs-  If !flag(buildExamples)+  If flag(buildExamples)+    Build-Depends:+      alsa-core >=0.5 && <0.6,+      storable-record >=0.0.2 && <0.1,+      sample-frame >=0.0.1 && <0.1,+      base >=3 && <5+  Else     Buildable: False   Hs-Source-Dirs: src, debug, examples+  Include-Dirs: src   GHC-Options: -Wall -threaded   Other-modules:     Sound.ALSA.PCM-    Sound.ALSA.PCM.Core-    Sound.ALSA.PCM.C2HS-  Build-Depends:-    alsa-core >=0.5 && <0.6,-    sample-frame >=0.0.1 && <0.1,-    base >=3 && <5+    Sound.ALSA.PCM.Core.Class+    Sound.ALSA.PCM.Core.Handle+    Sound.ALSA.PCM.Core.HwParams+    Sound.ALSA.PCM.Core.SwParams  Executable alsa-play   Main-Is: play.hs-  If !flag(buildExamples)+  If flag(buildExamples)+    Build-Depends:+      alsa-core >=0.5 && <0.6,+      storable-record >=0.0.2 && <0.1,+      sample-frame >=0.0.1 && <0.1,+      base >=3 && <5+  Else     Buildable: False   Hs-Source-Dirs: src, debug, examples+  Include-Dirs: src   GHC-Options: -Wall -threaded   Other-modules:     Sound.ALSA.PCM-    Sound.ALSA.PCM.Core-    Sound.ALSA.PCM.C2HS-  Build-Depends:-    alsa-core >=0.5 && <0.6,-    sample-frame >=0.0.1 && <0.1,-    base >=3 && <5+    Sound.ALSA.PCM.Core.Class+    Sound.ALSA.PCM.Core.Handle+    Sound.ALSA.PCM.Core.HwParams+    Sound.ALSA.PCM.Core.SwParams  Executable alsa-record   Main-Is: record.hs-  If !flag(buildExamples)+  If flag(buildExamples)+    Build-Depends:+      alsa-core >=0.5 && <0.6,+      storable-record >=0.0.2 && <0.1,+      sample-frame >=0.0.1 && <0.1,+      base >=3 && <5+  Else     Buildable: False   Hs-Source-Dirs: src, debug, examples+  Include-Dirs: src   GHC-Options: -Wall -threaded   Other-modules:     Sound.ALSA.PCM-    Sound.ALSA.PCM.Core-    Sound.ALSA.PCM.C2HS-  Build-Depends:-    alsa-core >=0.5 && <0.6,-    sample-frame >=0.0.1 && <0.1,-    base >=3 && <5+    Sound.ALSA.PCM.Core.Class+    Sound.ALSA.PCM.Core.Handle+    Sound.ALSA.PCM.Core.HwParams+    Sound.ALSA.PCM.Core.SwParams  Executable alsa-volume-meter   Main-Is: volume_meter.hs-  If !flag(buildExamples)+  If flag(buildExamples)+    Build-Depends:+      alsa-core >=0.5 && <0.6,+      storable-record >=0.0.2 && <0.1,+      sample-frame >=0.0.1 && <0.1,+      base >=3 && <5+  Else     Buildable: False   Hs-Source-Dirs: src, debug, examples+  Include-Dirs: src   GHC-Options: -Wall -threaded   Other-modules:     Sound.ALSA.PCM-    Sound.ALSA.PCM.Core-    Sound.ALSA.PCM.C2HS-  Build-Depends:-    alsa-core >=0.5 && <0.6,-    sample-frame >=0.0.1 && <0.1,-    base >=3 && <5+    Sound.ALSA.PCM.Core.Class+    Sound.ALSA.PCM.Core.Handle+    Sound.ALSA.PCM.Core.HwParams+    Sound.ALSA.PCM.Core.SwParams
examples/duplex.hs view
@@ -13,7 +13,7 @@ bufSize = 4096  soundFormat :: SoundFmt Int16-soundFormat = SoundFmt { sampleFreq  = 8000 }+soundFormat = SoundFmt { sampleFreq = 8000 }  main :: IO () main = do args <- getArgs@@ -32,12 +32,12 @@  play :: FilePath -> IO () play file =-    do let source = fileSoundSource file soundFormat-           sink   = alsaSoundSink "plughw:0,0" soundFormat+    do let source = fileSoundSource file+           sink   = alsaSoundSink "default" soundFormat        copySound source sink bufSize  record :: FilePath -> IO () record file =-    do let source = alsaSoundSource "plughw:0,0" soundFormat-           sink   = fileSoundSink file soundFormat+    do let source = alsaSoundSource "default" soundFormat+           sink   = fileSoundSink file        copySound source sink bufSize
examples/play.hs view
@@ -19,7 +19,7 @@ play :: FilePath -> IO () play file =    copySound-      (fileSoundSource file soundFormat)+      (fileSoundSource file)       -- "default" allows mixing with other ALSA programs       (alsaSoundSink "default" soundFormat)       bufSize
examples/record.hs view
@@ -11,7 +11,7 @@ bufSize = 8192  soundFormat :: SoundFmt Int16-soundFormat = SoundFmt { sampleFreq  = 8000 }+soundFormat = SoundFmt { sampleFreq = 8000 }  main :: IO () main = do args <- getArgs@@ -22,6 +22,6 @@  record :: FilePath -> IO () record file =-    do let source = alsaSoundSource "plughw:0,0" soundFormat-           sink   = fileSoundSink file soundFormat+    do let source = alsaSoundSource "default" soundFormat+           sink   = fileSoundSink file        copySound source sink bufSize
+ examples/sine.hs view
@@ -0,0 +1,88 @@+{- |+Demonstrate how to adapt to the parameters 'sample rate' and 'buffer size'+that are supported natively by the hardware.+-}+import qualified Sound.ALSA.PCM.Node.ALSA as PCM+import qualified Sound.ALSA.PCM.Parameters.Software as SwParam+import qualified Sound.ALSA.PCM.Parameters.Hardware as HwParam++import qualified Sound.ALSA.PCM.Debug as Debug++import qualified Data.StorableVector.Lazy as SVL+import qualified Data.StorableVector.Base as SVB++import Control.Exception (bracket, )++++openPCM ::+   (PCM.Access i, PCM.SampleFmt y) =>+   IO (PCM.Size, PCM.SampleFreq, PCM.Handle i y)+openPCM = do+   Debug.put "alsaOpenTest"+   (((bufferSize,periodSize),(bufferTime,periodTime),sampleRate), h) <-+      PCM.open (PCM.modes []) PCM.StreamPlayback+         (setHwParams 44100 1024 64)+         (\q@(sizes,_,_) -> do+             uncurry SwParam.setBufferSize sizes+             return q)+         "plughw:0"+   PCM.prepare h+   Debug.put $ "bufferTime = " ++ show bufferTime+   Debug.put $ "bufferSize = " ++ show bufferSize+   Debug.put $ "periodTime = " ++ show periodTime+   Debug.put $ "periodSize = " ++ show periodSize+   return (periodSize, sampleRate, h)++closePCM :: (PCM.Size, PCM.SampleFreq, PCM.Handle i y) -> IO ()+closePCM (_,_,pcm) = do+   Debug.put "alsaClose"+   PCM.drain pcm+   PCM.close pcm++setHwParams ::+      PCM.SampleFreq -- ^ sample frequency+   -> PCM.Size -- ^ buffer size+   -> PCM.Size -- ^ period size+   -> HwParam.T i y ((PCM.Size,PCM.Size),(PCM.Time,PCM.Time),PCM.SampleFreq)+      -- ^ ((bufferSize,periodSize),(bufferTime,periodTime),sampleRate)+setHwParams rate bufferSize periodSize = do+{-+   (actualRate,ord) <- HwParam.getRateMax+   print ord+-}+   HwParam.setRateResample False+   (actualRate,_) <-+      HwParam.setRateNear rate EQ+   (actualPeriodSize,_) <-+      HwParam.setPeriodSizeNear periodSize EQ+   actualBufferSize <-+      HwParam.setBufferSizeNear+         (max bufferSize (actualPeriodSize*2))+{-+   let actualBufferSize = bufferSize+   HwParam.setBufferSize bufferSize+-}+   (actualBufferTime,_) <- HwParam.getBufferTime+   (actualPeriodTime,_) <- HwParam.getPeriodTime+   return ((actualBufferSize, actualPeriodSize),+           (actualBufferTime, actualPeriodTime),+           actualRate)++write ::+   (PCM.SampleFmt y) =>+   PCM.Handle PCM.Interleaved y -> SVB.Vector y -> IO ()+write h xs =+   SVB.withStartPtr xs $ \buf ->+      fmap (const ()) . PCM.writeiRetry h buf . fromIntegral+++main :: IO ()+main =+   bracket openPCM closePCM $ \(size,rate,h) -> do+   putStrLn $ "period size: " ++ show size+   putStrLn $ "sample rate: " ++ show rate+   mapM_ (write h) $+      SVL.chunks $+      SVL.map ((0.99*) . sin . ((2*pi * 440 / fromIntegral rate :: Float)*)) $+      SVL.iterate (SVL.chunkSize $ fromIntegral size) (1 +) 0
examples/synth.hs view
@@ -1,18 +1,19 @@-import qualified Sound.ALSA.PCM as PCM+import qualified Sound.ALSA.PCM.Node.ALSA as PCM+import qualified Sound.ALSA.PCM.Parameters.Software as SwParam+import qualified Sound.ALSA.PCM.Parameters.Hardware as HwParam -import qualified Sound.ALSA.PCM.Core as Core-import qualified Sound.ALSA.Exception as AlsaExc import qualified Sound.ALSA.PCM.Debug as Debug  import qualified Sound.ALSA.Sequencer.Address as Addr import qualified Sound.ALSA.Sequencer.Client as Client import qualified Sound.ALSA.Sequencer.Port as Port-import qualified Sound.ALSA.Sequencer.Port.Info as PortInfo+import qualified Sound.ALSA.Sequencer.Port.InfoMonad as PortInfo import qualified Sound.ALSA.Sequencer.Event as Event import qualified Sound.ALSA.Sequencer.Queue as Queue+import qualified Sound.ALSA.Sequencer.Time as Time import qualified Sound.ALSA.Sequencer.RealTime as RealTime import qualified Sound.ALSA.Sequencer as SndSeq--- import qualified Sound.ALSA.Exception as AlsaExc+import Sound.ALSA.Sequencer.Event (Pitch, Velocity, )  import qualified Data.StorableVector.ST.Strict as SVST import qualified Data.StorableVector as SV@@ -26,87 +27,74 @@  import qualified Data.Map as Map -import Data.Word (Word8, )- import Control.Exception (bracket, ) import Control.Monad (liftM, forever, )  import Debug.Trace (trace, )  -soundFormat :: PCM.SoundFmt Float-soundFormat = PCM.SoundFmt { PCM.sampleFreq = 44100 }--openPCM :: IO (Int, Int, Core.Pcm)+openPCM ::+   (PCM.Access i, PCM.SampleFmt y) =>+   IO (PCM.Size, PCM.SampleFreq, PCM.Handle i y) openPCM = do    Debug.put "alsaOpenTest"-   h <- Core.pcm_open "default" Core.PcmStreamPlayback 0-   (bufferTime,bufferSize,periodTime,periodSize,sampleRate) <--      setHwParams h-         (PCM.withSampleFmt PCM.sampleFmtToPcmFormat soundFormat)-         (PCM.numChannels soundFormat)-         (PCM.sampleFreq soundFormat)-         1024 64-   PCM.setSwParams h bufferSize periodSize-   Core.pcm_prepare h+   (((bufferSize,periodSize),(bufferTime,periodTime),sampleRate), h) <-+      PCM.open (PCM.modes []) PCM.StreamPlayback+         (setHwParams 44100 1024 64)+         (\q@(sizes,_,_) -> do+             uncurry SwParam.setBufferSize sizes+             return q)+         "default"+   PCM.prepare h    Debug.put $ "bufferTime = " ++ show bufferTime    Debug.put $ "bufferSize = " ++ show bufferSize    Debug.put $ "periodTime = " ++ show periodTime    Debug.put $ "periodSize = " ++ show periodSize    return (periodSize, sampleRate, h) -closePCM :: (Int, Int, Core.Pcm) -> IO ()-closePCM (_,_,pcm) = AlsaExc.rethrow $ do+closePCM :: (PCM.Size, PCM.SampleFreq, PCM.Handle i y) -> IO ()+closePCM (_,_,pcm) = do    Debug.put "alsaClose"-   Core.pcm_drain pcm-   Core.pcm_close pcm+   PCM.drain pcm+   PCM.close pcm  setHwParams ::-      Core.Pcm-   -> Core.PcmFormat-   -> Int -- ^ number of channels-   -> PCM.SampleFreq -- ^ sample frequency-   -> Int -- ^ buffer size-   -> Int -- ^ period size-   -> IO (Int,Int,Int,Int,Int)-      -- ^ (bufferTime,bufferSize,periodTime,periodSize)-setHwParams h format channels rate bufferSize periodSize =-   PCM.withHwParams h $ \p -> do-      Core.pcm_hw_params_set_access h p Core.PcmAccessRwInterleaved-      Core.pcm_hw_params_set_format h p format-      Core.pcm_hw_params_set_channels h p channels+      PCM.SampleFreq -- ^ sample frequency+   -> PCM.Size -- ^ buffer size+   -> PCM.Size -- ^ period size+   -> HwParam.T i y ((PCM.Size,PCM.Size),(PCM.Time,PCM.Time),PCM.SampleFreq)+      -- ^ ((bufferSize,periodSize),(bufferTime,periodTime),sampleRate)+setHwParams rate bufferSize periodSize = do {--      (actualRate,ord) <--         Core.pcm_hw_params_get_rate_max p-      print ord+   (actualRate,ord) <- HwParam.getRateMax+   print ord -}-      Core.pcm_hw_params_set_rate_resample h p False-      (actualRate,_) <--         Core.pcm_hw_params_set_rate_near h p rate EQ-      (actualPeriodSize,_) <--         Core.pcm_hw_params_set_period_size_near h p periodSize EQ-      actualBufferSize <--         Core.pcm_hw_params_set_buffer_size_near h p-            (max bufferSize (actualPeriodSize*2))+   HwParam.setRateResample False+   (actualRate,_) <-+      HwParam.setRateNear rate EQ+   (actualPeriodSize,_) <-+      HwParam.setPeriodSizeNear periodSize EQ+   actualBufferSize <-+      HwParam.setBufferSizeNear+         (max bufferSize (actualPeriodSize*2)) {--      let actualBufferSize = bufferSize-      Core.pcm_hw_params_set_buffer_size h p bufferSize+   let actualBufferSize = bufferSize+   HwParam.setBufferSize bufferSize -}-      (actualBufferTime,_) <- Core.pcm_hw_params_get_buffer_time p-      (actualPeriodTime,_) <- Core.pcm_hw_params_get_period_time p-      return (actualBufferTime, actualBufferSize,-              actualPeriodTime, actualPeriodSize,-              actualRate)+   (actualBufferTime,_) <- HwParam.getBufferTime+   (actualPeriodTime,_) <- HwParam.getPeriodTime+   return ((actualBufferSize, actualPeriodSize),+           (actualBufferTime, actualPeriodTime),+           actualRate)   setTimestamping ::    SndSeq.T mode -> Port.T -> Queue.T -> IO ()-setTimestamping h p q = do-   info <- PortInfo.get h p-   PortInfo.setTimestamping info True-   PortInfo.setTimestampReal info True-   PortInfo.setTimestampQueue info q-   PortInfo.set h p info+setTimestamping h p q =+   PortInfo.modify h p $ do+      PortInfo.setTimestamping True+      PortInfo.setTimestampReal True+      PortInfo.setTimestampQueue q   withInPort ::@@ -128,16 +116,17 @@  {- | RealTime.toFractional for NumericPrelude.--}+ realTimeToField :: (Fractional a) => RealTime.T -> a realTimeToField (RealTime.Cons s n) =    fromIntegral s + fromIntegral n / (10^(9::Int))+-}  addStamp ::    Time -> Event.T -> StampedEvent addStamp rate ev =-   (case Event.timestamp ev of-      Event.RealTime t ->+   (case Event.time ev of+      Time.Cons Time.Absolute (Time.Real t) ->          div (RealTime.toInteger t * rate) nano       _ -> error "unsupported time stamp type",     ev)@@ -186,7 +175,7 @@       (Addr.Cons c Port.unknown)       (Event.CustomEv Event.Echo dat))       { Event.queue = q-      , Event.timestamp = Event.RealTime t+      , Event.time = Time.consAbs $ Time.Real t       , Event.dest = Addr.Cons {            Addr.client = c,            Addr.port = p@@ -211,8 +200,8 @@                     _ -> False           if abort             then-               case Event.timestamp ev of-                 Event.RealTime t -> do+               case Event.time ev of+                 Time.Cons Time.Absolute (Time.Real _t) -> do --                    putStrLn $ "got Echo at: " ++ show (RealTime.toInteger t :: Double)                     return []                  _ -> error "unsupported time stamp type"@@ -245,19 +234,16 @@  arrange ::    (Storable a, Num a) =>-   Int ->+   PCM.Size ->    [(Int, SV.Vector a)] ->    SV.Vector a arrange size evs =    SVST.runSTVector (do-      v <- SVST.new size 0+      v <- SVST.new (fromIntegral size) 0       mapM_ (uncurry $ unsafeAddChunkToBuffer v) evs       return v)  -type Pitch = Word8-type Velocity = Word8- data OscillatorState a = OscillatorState a a Int  {-@@ -298,13 +284,13 @@ amplitudeFromVelocity ::    (Floating y) =>    Velocity -> y-amplitudeFromVelocity vel =+amplitudeFromVelocity (Event.Velocity vel) =    4 ** ((fromIntegral vel - 64) / 128)  frequencyFromPitch ::    (Floating y) =>    Pitch -> y-frequencyFromPitch pitch =+frequencyFromPitch (Event.Pitch pitch) =    440 * 2 ** (fromIntegral (fromIntegral pitch + 3 - 6*12 :: Int) / 12)  normalizeNote :: Event.NoteEv -> Event.Note -> (Event.NoteEv, Velocity)@@ -313,14 +299,14 @@       velocity ->          case notePart of             Event.NoteOn ->-               if velocity == 0-                 then (Event.NoteOff, 64)+               if velocity == Event.offVelocity+                 then (Event.NoteOff, Event.normalVelocity)                  else (Event.NoteOn, velocity)             _ -> (notePart, velocity)  processEvents ::    (Storable a, Floating a, Monad m) =>-   Int ->+   PCM.Size ->    PCM.SampleFreq ->    [StampedEvent] ->    MS.StateT (Time, Map.Map Pitch (OscillatorState a)) m [(Int, SV.Vector a)]@@ -332,7 +318,7 @@                 let mplayingNew =                        fmap                           (\(start,s0) ->-                             case renderTone (size-start) s0 of+                             case renderTone (fromIntegral size - start) s0 of                                 (chunk, s1) -> ((start,chunk), s1))                           mplaying                 in  (fmap snd mplayingNew,@@ -383,10 +369,11 @@   write ::-   (PCM.SampleFmt a) =>-   Core.Pcm -> SV.Vector a -> IO ()+   (PCM.SampleFmt y) =>+   PCM.Handle PCM.Interleaved y -> SV.Vector y -> IO () write h xs =-   SVB.withStartPtr xs $ PCM.alsaWrite h+   SVB.withStartPtr xs $ \buf ->+      fmap (const ()) . PCM.writeiRetry h buf . fromIntegral   {-@@ -405,9 +392,9 @@    withInPort SndSeq.Block $ \sq port ->       Queue.with sq $ \ q ->       do setTimestamping sq port q-         Queue.control sq q Event.QueueStart 0 Nothing+         Queue.control sq q Event.QueueStart Nothing          _ <- Event.drainOutput sq-         write h (SV.replicate (2*size) 0 :: SV.Vector Float)+         write h (SV.replicate (2 * fromIntegral size) 0 :: SV.Vector Float)          flip MS.evalStateT (0,Map.empty) $ forever $ do             startTime <- MS.gets fst             let stopTime = startTime + fromIntegral size
examples/volume_meter.hs view
@@ -11,17 +11,17 @@ bufSize = 1000  inputFormat :: SoundFmt Int16-inputFormat = SoundFmt { sampleFreq  = 8000 }+inputFormat = SoundFmt { sampleFreq = 8000 }   main :: IO ()-main = let source = alsaSoundSource "plughw:0,0" inputFormat+main = let source = alsaSoundSource "default" inputFormat         in allocaArray     bufSize $ \buf  ->            withSoundSource source  $ \from ->                loop source from bufSize buf --- FIXME: assumes little-endian machine-loop :: SoundSource Int16 h -> h -> Int -> Ptr Int16 -> IO ()+-- | assumes that the file contains numbers in the host's byte order+loop :: SoundSource h Int16 -> h Int16 -> Int -> Ptr Int16 -> IO () loop src h n buf =     do n' <- soundSourceRead src h (castPtr buf) n        avg <- avgBuf buf n'
src/Sound/ALSA/PCM.hs view
@@ -1,13 +1,14 @@ {-# LANGUAGE ForeignFunctionInterface #-} module Sound.ALSA.PCM-    (SampleFmt(..),+    (Class.SampleFmt(..),      SampleFreq,      Time,+     Size,      SoundFmt(..),      SoundSource(..),      SoundSink(..),      SoundBufferTime(..),-     Pcm,+     Pcm, File,      withSoundSource,      withSoundSourceRunning,      withSoundSink,@@ -22,159 +23,99 @@      alsaSoundSink,      alsaSoundSourceTime,      alsaSoundSinkTime,+     alsaSoundSourceParams,+     alsaSoundSinkParams,      fileSoundSource,      fileSoundSink,     ) where -import Sound.ALSA.PCM.Core (Pcm)-import qualified Sound.ALSA.PCM.Core as PCM+import qualified Sound.ALSA.PCM.Node.ALSA as PCM+import qualified Sound.ALSA.PCM.Node.File as File++import Sound.ALSA.PCM.Parameters.Hardware (Time, SampleFreq, Size, )+import Sound.ALSA.PCM.Core.Handle (arraySize, )+import qualified Sound.ALSA.PCM.Parameters.Software as SwParam+import qualified Sound.ALSA.PCM.Parameters.Hardware as HwParam+import qualified Sound.ALSA.PCM.Core.Class as Class import qualified Sound.ALSA.Exception as AlsaExc import qualified Sound.ALSA.PCM.Debug as Debug  import qualified Sound.Frame as Frame-import qualified Sound.Frame.Stereo as Stereo-import qualified Sound.Frame.MuLaw  as MuLaw -import Data.Word (Word8, Word16, Word32, )-import Data.Int (Int8, Int16, Int32, )- import Control.Exception (bracket, bracket_, )-import Control.Monad (liftM, when, )-import Foreign.Marshal.Array (advancePtr, allocaArray, )-import Foreign.C (CSize, CInt, )-import Foreign (Storable, Ptr, minusPtr, )+import Control.Monad (when, liftM2, liftM4, )++import qualified Foreign.C.Types as C+import Foreign.Marshal.Array (allocaArray, )+import Foreign.Ptr (Ptr, )+import Foreign.Storable (Storable, ) import qualified System.IO as IO-import System.IO-   (IOMode(ReadMode, WriteMode), Handle, openBinaryFile, hClose, )  -- -- * Generic sound API -- -class (Storable y, Frame.C y) => SampleFmt y where-   sampleFmtToPcmFormat :: y -> PCM.Format--type SampleFreq = Int- data SoundFmt y = SoundFmt {         sampleFreq :: SampleFreq         }   deriving (Show) -type Time = Int- data SoundBufferTime = SoundBufferTime {         bufferTime, periodTime :: Time         }   deriving (Show)  --- | Counts are in samples, not bytes. Multi-channel data is interleaved.-data SoundSource y handle =-    SoundSource {-                 soundSourceFmt   :: SoundFmt y,-                 soundSourceOpen  :: IO handle,-                 soundSourceClose :: handle -> IO (),-                 soundSourceStart :: handle -> IO (),-                 soundSourceStop  :: handle -> IO (),-                 soundSourceRead  :: handle -> Ptr y -> Int -> IO Int-                }+type Pcm = PCM.Handle PCM.Interleaved -data SoundSink y handle =-    SoundSink {-                 soundSinkFmt   :: SoundFmt y,-                 soundSinkOpen  :: IO handle,-                 soundSinkClose :: handle -> IO (),-                 soundSinkWrite :: handle -> Ptr y -> Int -> IO (),-                 soundSinkStart :: handle -> IO (),-                 soundSinkStop  :: handle -> IO ()-                }+type File = File.Handle --------- -defaultBufferTime :: SoundBufferTime-defaultBufferTime =-    SoundBufferTime {-        bufferTime = 500000, -- 0.5s-        periodTime = 100000  -- 0.1s-    }--nullSoundSource :: SoundFmt y -> SoundSource y h-nullSoundSource fmt =-    SoundSource {-                 soundSourceFmt   = fmt,-                 soundSourceOpen  = return undefined,-                 soundSourceClose = \_ -> return (),-                 soundSourceStart = \_ -> return (),-                 soundSourceStop  = \_ -> return (),-                 soundSourceRead  = \_ _ _ -> return 0-                }+-- | Counts are in samples, not bytes. Multi-channel data is interleaved.+data SoundSource handle y =+   SoundSource {+      soundSourceOpen  :: IO (handle y),+      soundSourceClose :: handle y -> IO (),+      soundSourceStart :: handle y -> IO (),+      soundSourceStop  :: handle y -> IO (),+      soundSourceRead  :: handle y -> Ptr y -> Size -> IO Size+   } -nullSoundSink :: SoundFmt y -> SoundSink y h-nullSoundSink fmt =-    SoundSink {-               soundSinkFmt   = fmt,-               soundSinkOpen  = return undefined,-               soundSinkClose = \_ -> return (),-               soundSinkStart = \_ -> return (),-               soundSinkStop  = \_ -> return (),-               soundSinkWrite = \_ _ _ -> return ()-              }+data SoundSink handle y =+   SoundSink {+      soundSinkOpen  :: IO (handle y),+      soundSinkClose :: handle y -> IO (),+      soundSinkWrite :: handle y -> Ptr y -> Size -> IO (),+      soundSinkStart :: handle y -> IO (),+      soundSinkStop  :: handle y -> IO ()+   }  -withSoundSource :: SoundSource y h -> (h -> IO a) -> IO a+withSoundSource :: SoundSource handle y -> (handle y -> IO a) -> IO a withSoundSource source =     bracket (soundSourceOpen source) (soundSourceClose source) -withSoundSourceRunning :: SoundSource y h -> h -> IO a -> IO a-withSoundSourceRunning src h = bracket_ (soundSourceStart src h) (soundSourceStop src h)+withSoundSourceRunning :: SoundSource handle y -> handle y -> IO a -> IO a+withSoundSourceRunning src h =+    bracket_ (soundSourceStart src h) (soundSourceStop src h) -withSoundSink :: SoundSink y h -> (h -> IO a) -> IO a+withSoundSink :: SoundSink handle y -> (handle y -> IO a) -> IO a withSoundSink sink =     bracket (soundSinkOpen sink) (soundSinkClose sink) -withSoundSinkRunning :: SoundSink y h -> h -> IO a -> IO a-withSoundSinkRunning src h = bracket_ (soundSinkStart src h) (soundSinkStop src h)+withSoundSinkRunning :: SoundSink handle y -> handle y -> IO a -> IO a+withSoundSinkRunning src h =+    bracket_ (soundSinkStart src h) (soundSinkStop src h)  -instance SampleFmt Word8 where-   sampleFmtToPcmFormat _ = PCM.FormatU8--instance SampleFmt Int8 where-   sampleFmtToPcmFormat _ = PCM.FormatS8--instance SampleFmt Word16 where-   sampleFmtToPcmFormat _ = PCM.FormatU16--instance SampleFmt Int16 where-   sampleFmtToPcmFormat _ = PCM.FormatS16--instance SampleFmt Word32 where-   sampleFmtToPcmFormat _ = PCM.FormatU32--instance SampleFmt Int32 where-   sampleFmtToPcmFormat _ = PCM.FormatS32--instance SampleFmt Float where-   sampleFmtToPcmFormat _ = PCM.FormatFloat--instance SampleFmt Double where-   sampleFmtToPcmFormat _ = PCM.FormatFloat64--instance SampleFmt MuLaw.T where-   sampleFmtToPcmFormat _ = PCM.FormatMuLaw--instance SampleFmt a => SampleFmt (Stereo.T a) where-   sampleFmtToPcmFormat y =-      sampleFmtToPcmFormat (Stereo.left y)- withSampleFmt :: (y -> a) -> (SoundFmt y -> a) withSampleFmt f _ = f undefined +withNodeSample :: (y -> a) -> (node y -> a)+withNodeSample f _ = f undefined -soundFmtMIME :: SampleFmt y => SoundFmt y -> String++soundFmtMIME :: Class.SampleFmt y => SoundFmt y -> String soundFmtMIME fmt = t ++ r ++ c   where t = "audio/basic" {-@@ -183,13 +124,15 @@                 SampleFmtMuLaw8Bit           -> "audio/basic" -}         r = ";rate=" ++ show (sampleFreq fmt)-        c | numChannels fmt == 1 = ""-          | otherwise = ";channels=" ++ show (numChannels fmt)+        c =+           if numChannels fmt == 1+             then ""+             else ";channels=" ++ show (numChannels fmt) -numChannels :: SampleFmt y => SoundFmt y -> Int+numChannels :: Class.SampleFmt y => SoundFmt y -> Int numChannels = withSampleFmt Frame.numberOfChannels -audioBytesPerSample :: SampleFmt y => SoundFmt y -> Int+audioBytesPerSample :: Class.SampleFmt y => SoundFmt y -> Int audioBytesPerSample = withSampleFmt Frame.sizeOfElement  {-@@ -199,22 +142,25 @@ a frame might occupy more than the calculated size in an array in memory. -}-audioBytesPerFrame :: SampleFmt y => SoundFmt y -> Int+audioBytesPerFrame :: Class.SampleFmt y => SoundFmt y -> Int audioBytesPerFrame fmt = numChannels fmt * audioBytesPerSample fmt -soundSourceBytesPerFrame :: SampleFmt y => SoundSource y h -> Int-soundSourceBytesPerFrame = audioBytesPerFrame . soundSourceFmt+soundSourceBytesPerFrame :: Class.SampleFmt y => SoundSource handle y -> Int+soundSourceBytesPerFrame =+   withNodeSample $ \y -> Frame.numberOfChannels y * Frame.sizeOfElement y -soundSinkBytesPerFrame :: SampleFmt y => SoundSink y h -> Int-soundSinkBytesPerFrame = audioBytesPerFrame . soundSinkFmt+soundSinkBytesPerFrame :: Class.SampleFmt y => SoundSink handle y -> Int+soundSinkBytesPerFrame =+   withNodeSample $ \y -> Frame.numberOfChannels y * Frame.sizeOfElement y -copySound :: SampleFmt y =>-             SoundSource y h1-          -> SoundSink y h2-          -> Int -- ^ Buffer size (in sample frames) to use-          -> IO ()+copySound ::+   Class.SampleFmt y =>+      SoundSource handleIn y+   -> SoundSink handleOut y+   -> Size -- ^ Buffer size (in sample frames) to use+   -> IO () copySound source sink bufSize =-    allocaArray     bufSize $ \buf ->+    allocaArray     (fromIntegral bufSize) $ \buf ->     withSoundSource source  $ \from ->     withSoundSink   sink    $ \to ->        let loop = do n <- soundSourceRead source from buf bufSize@@ -227,250 +173,192 @@ --  -alsaOpen :: SampleFmt y =>-           String -- ^ device, e.g @"default"@-        -> SoundFmt y-        -> SoundBufferTime-        -> PCM.Stream-        -> IO Pcm-alsaOpen dev fmt time stream = AlsaExc.rethrow $-    do Debug.put "alsaOpen"-       h <- PCM.open dev stream 0-       Debug.put $ "requested buffer_time = " ++ show (bufferTime time)-       Debug.put $ "requested period_time = " ++ show (periodTime time)-       (buffer_time,buffer_size,period_time,period_size) <--           setHwParams h (withSampleFmt sampleFmtToPcmFormat fmt)-                         (numChannels fmt)-                         (sampleFreq fmt)-                         (bufferTime time)-                         (periodTime time)-       setSwParams h buffer_size period_size-       PCM.prepare h-       Debug.put $ "buffer_time = " ++ show buffer_time-       Debug.put $ "buffer_size = " ++ show buffer_size-       Debug.put $ "period_time = " ++ show period_time-       Debug.put $ "period_size = " ++ show period_size-       when (stream == PCM.StreamPlayback) $-         callocaArray fmt period_size $ \buf ->-            PCM.writei h buf period_size >> return ()-       return h+{- |+The buffer is initialized with an empty block+which means that the zero bit pattern+should equal the number zero in the Class.SampleFmt type.+-}+alsaOpen :: Class.SampleFmt y =>+   PCM.Stream ->+   HwParam.T PCM.Interleaved y a ->+   (a -> SwParam.T PCM.Interleaved y ()) ->+   String {- ^ device, e.g @"default"@ -} ->+   IO (Pcm y)+alsaOpen stream hwParams swParams dev = AlsaExc.rethrow $ do+   Debug.put "alsaOpen"+   {-+   Debug.put $ "requested bufferTime = " ++ show (bufferTime time)+   Debug.put $ "requested periodTime = " ++ show (periodTime time)+   -}+   ((bufferTime_,bufferSize_,periodTime_,periodSize_), h) <-+      PCM.open (PCM.modes []) stream+         (liftM2 (,) hwParams $+          liftM4 (,,,)+             HwParam.getBufferSize+             HwParam.getBufferTime+             (fmap fst HwParam.getPeriodSize)+             (fmap fst HwParam.getPeriodTime))+         (\(a, params) -> swParams a >> return params)+         dev+   PCM.prepare h+   Debug.put $ "bufferTime = " ++ show bufferTime_+   Debug.put $ "bufferSize = " ++ show bufferSize_+   Debug.put $ "periodTime = " ++ show periodTime_+   Debug.put $ "periodSize = " ++ show periodSize_+   when (stream == PCM.StreamPlayback) $+      callocaArray periodSize_ $ \buf ->+         PCM.writei h buf (fromIntegral periodSize_) >> return ()+   return h +alsaClose :: Pcm y -> IO ()+alsaClose h = AlsaExc.rethrow $ do+   Debug.put "alsaClose"+   PCM.drain h+   PCM.close h -setHwParams :: Pcm-            -> PCM.Format-            -> Int -- ^ number of channels-            -> SampleFreq -- ^ sample frequency-            -> Time -- ^ buffer time-            -> Time -- ^ period time-            -> IO (Int,Int,Int,Int)-               -- ^ (buffer_time,buffer_size,period_time,period_size)-setHwParams h format channels rate buffer_time period_time-  = withHwParams h $ \p ->-    do PCM.hw_params_set_access h p PCM.AccessRwInterleaved-       PCM.hw_params_set_format h p format-       PCM.hw_params_set_channels h p channels-       PCM.hw_params_set_rate h p rate EQ-       (actual_buffer_time,_) <--           PCM.hw_params_set_buffer_time_near h p buffer_time EQ-       buffer_size <- PCM.hw_params_get_buffer_size p-       (actual_period_time,_) <--           PCM.hw_params_set_period_time_near h p period_time EQ-       (period_size,_) <- PCM.hw_params_get_period_size p-       return (actual_buffer_time,buffer_size,-               actual_period_time,period_size) -setSwParams :: Pcm-            -> Int -- ^ buffer size-            -> Int -- ^ period size-            -> IO ()-setSwParams h _buffer_size period_size = withSwParams h $ \p ->-    do -- let start_threshold =-       --        (buffer_size `div` period_size) * period_size-       --PCM.sw_params_set_start_threshold h p start_threshold-       PCM.sw_params_set_start_threshold h p 0-       PCM.sw_params_set_avail_min h p period_size-       PCM.sw_params_set_xfer_align h p 1-       -- pad buffer with silence when needed-       --PCM.sw_params_set_silence_size h p period_size-       --PCM.sw_params_set_silence_threshold h p period_size--withHwParams :: Pcm -> (PCM.HwParams -> IO a) -> IO a-withHwParams h f =-    bracket PCM.hw_params_malloc PCM.hw_params_free $ \p ->-    do PCM.hw_params_any h p-       x <- f p-       PCM.hw_params h p-       return x--withSwParams :: Pcm -> (PCM.SwParams -> IO a) -> IO a-withSwParams h f =-    bracket PCM.sw_params_malloc PCM.sw_params_free $ \p ->-    do PCM.sw_params_current h p-       x <- f p-       PCM.sw_params h p-       return x--alsaClose :: Pcm -> IO ()-alsaClose pcm = AlsaExc.rethrow $-    do Debug.put "alsaClose"-       PCM.drain pcm-       PCM.close pcm--alsaStart :: Pcm -> IO ()-alsaStart pcm = AlsaExc.rethrow $-    do Debug.put "alsaStart"-       PCM.prepare pcm-       PCM.start pcm-+alsaStart :: Pcm y -> IO ()+alsaStart h = AlsaExc.rethrow $ do+   Debug.put "alsaStart"+   PCM.prepare h+   PCM.start h  -- FIXME: use PCM.drain for sinks?-alsaStop :: Pcm -> IO ()-alsaStop pcm = AlsaExc.rethrow $-    do Debug.put "alsaStop"-       PCM.drain pcm+alsaStop :: Pcm y -> IO ()+alsaStop h = AlsaExc.rethrow $ do+   Debug.put "alsaStop"+   PCM.drain h + alsaRead ::-   SampleFmt y =>-   Pcm -> Ptr y -> Int -> IO Int+   Class.SampleFmt y =>+   Pcm y -> Ptr y -> Size -> IO Size alsaRead h buf0 n =-   let go buf offset = do-          -- debug $ "Reading " ++ show n ++ " samples..."-          nread <--             PCM.readi h buf (n-offset)-             `AlsaExc.catchXRun`-             do Debug.put "snd_pcm_readi reported buffer over-run"-                PCM.prepare h-                go buf offset-          let newOffset = offset+nread-          -- debug $ "Got " ++ show n' ++ " samples."-          if newOffset < n-            then go (advancePtr buf nread) newOffset-            else return newOffset-   in  AlsaExc.rethrow $ go buf0 0-+   AlsaExc.rethrow $ PCM.readiRetry h buf0 n  alsaWrite ::-   SampleFmt y =>-   Pcm -> Ptr y -> Int -> IO ()-alsaWrite h buf n = AlsaExc.rethrow $-    alsaWrite_ h buf n >> return ()+   Class.SampleFmt y =>+   Pcm y -> Ptr y -> Size -> IO Size+alsaWrite h buf0 n =+   AlsaExc.rethrow $ PCM.writeiRetry h buf0 n -alsaWrite_ ::-   SampleFmt y =>-   Pcm -> Ptr y -> Int -> IO Int-alsaWrite_ h buf0 n =-   let go buf offset = do-          --debug $ "Writing " ++ show n ++ " samples..."-          nwritten <--             PCM.writei h buf n-             `AlsaExc.catchXRun`-             do Debug.put "snd_pcm_writei reported buffer under-run"-                PCM.prepare h-                go buf offset-          let newOffset = offset+nwritten-          --debug $ "Wrote " ++ show n' ++ " samples."-          if newOffset < n-            then go (advancePtr buf nwritten) newOffset-            else return newOffset-   in  AlsaExc.rethrow $ go buf0 0 +defaultBufferTime :: SoundBufferTime+defaultBufferTime =+   SoundBufferTime {+      bufferTime = 500000, -- 0.5s+      periodTime = 100000  -- 0.1s+   } +bufferTimeParams ::+   SoundFmt y ->+   SoundBufferTime ->+   (HwParam.T PCM.Interleaved y (Size,Size),+    (Size,Size) -> SwParam.T PCM.Interleaved y ())+bufferTimeParams fmt time =+   (HwParam.setRateBufferTime+       (sampleFreq fmt)+       (bufferTime time)+       (periodTime time),+    uncurry SwParam.setBufferSize)+ alsaSoundSource ::-   SampleFmt y =>-   String -> SoundFmt y -> SoundSource y Pcm+   Class.SampleFmt y =>+   String -> SoundFmt y -> SoundSource Pcm y alsaSoundSource dev fmt =    alsaSoundSourceTime dev fmt defaultBufferTime  alsaSoundSink ::-   SampleFmt y =>-   String -> SoundFmt y -> SoundSink y Pcm+   Class.SampleFmt y =>+   String -> SoundFmt y -> SoundSink Pcm y alsaSoundSink dev fmt =    alsaSoundSinkTime dev fmt defaultBufferTime  alsaSoundSourceTime ::-   SampleFmt y =>-   String -> SoundFmt y -> SoundBufferTime -> SoundSource y Pcm+   Class.SampleFmt y =>+   String -> SoundFmt y -> SoundBufferTime -> SoundSource Pcm y alsaSoundSourceTime dev fmt time =-    (nullSoundSource fmt) {-        soundSourceOpen  = alsaOpen dev fmt time PCM.StreamCapture,-        soundSourceClose = alsaClose,-        soundSourceStart = alsaStart,-        soundSourceStop  = alsaStop,-        soundSourceRead  = alsaRead-    }+   uncurry (alsaSoundSourceParams dev) $+   bufferTimeParams fmt time  alsaSoundSinkTime ::-   SampleFmt y =>-   String -> SoundFmt y -> SoundBufferTime -> SoundSink y Pcm+   Class.SampleFmt y =>+   String -> SoundFmt y -> SoundBufferTime -> SoundSink Pcm y alsaSoundSinkTime dev fmt time =-    (nullSoundSink fmt) {-        soundSinkOpen  = alsaOpen dev fmt time PCM.StreamPlayback,-        soundSinkClose = alsaClose,-        soundSinkStart = alsaStart,-        soundSinkStop  = alsaStop,-        soundSinkWrite = alsaWrite-    }+   uncurry (alsaSoundSinkParams dev) $+   bufferTimeParams fmt time +alsaSoundSourceParams ::+   Class.SampleFmt y =>+   String ->+   HwParam.T PCM.Interleaved y a ->+   (a -> SwParam.T PCM.Interleaved y ()) ->+   SoundSource Pcm y+alsaSoundSourceParams dev hwParams swParams =+   SoundSource {+      soundSourceOpen  = alsaOpen PCM.StreamCapture hwParams swParams dev,+      soundSourceClose = alsaClose,+      soundSourceStart = alsaStart,+      soundSourceStop  = alsaStop,+      soundSourceRead  = alsaRead+   }++alsaSoundSinkParams ::+   Class.SampleFmt y =>+   String ->+   HwParam.T PCM.Interleaved y a ->+   (a -> SwParam.T PCM.Interleaved y ()) ->+   SoundSink Pcm y+alsaSoundSinkParams dev hwParams swParams =+   SoundSink {+      soundSinkOpen  = alsaOpen PCM.StreamPlayback hwParams swParams dev,+      soundSinkClose = alsaClose,+      soundSinkStart = alsaStart,+      soundSinkStop  = alsaStop,+      soundSinkWrite = \h buf n -> alsaWrite h buf n >> return ()+   }+ -- -- * File stuff -- -{- |-This expects pad bytes that are needed in memory-in order to satisfy aligment constraints.-This is only a problem for samples sizes like 24 bit.--}-fileRead ::-   SampleFmt y =>-   Handle -> Ptr y -> Int -> IO Int-fileRead h buf n =-   liftM (`div` arraySize buf 1) $-   IO.hGetBuf h buf (arraySize buf n)--{- |-Same restrictions as for 'fileRead'.--}-fileWrite ::-   SampleFmt y =>-   Handle -> Ptr y -> Int -> IO ()-fileWrite h buf n =-   IO.hPutBuf h buf (arraySize buf n)- fileSoundSource ::-   SampleFmt y =>-   FilePath -> SoundFmt y -> SoundSource y Handle-fileSoundSource file fmt =-    (nullSoundSource fmt) {-                           soundSourceOpen  = openBinaryFile file ReadMode,-                           soundSourceClose = hClose,-                           soundSourceRead  = fileRead-                          }+   Class.SampleFmt y =>+   FilePath -> SoundSource File y+fileSoundSource file =+   SoundSource {+      soundSourceOpen  = File.open IO.ReadMode file,+      soundSourceClose = File.close,+      soundSourceRead  = File.read,+      soundSourceStart = const $ return (),+      soundSourceStop  = const $ return ()+   }  fileSoundSink ::-   SampleFmt y =>-   FilePath -> SoundFmt y -> SoundSink y Handle-fileSoundSink file fmt =-    (nullSoundSink fmt) {-                         soundSinkOpen  = openBinaryFile file WriteMode,-                         soundSinkClose = hClose,-                         soundSinkWrite = fileWrite-                        }+   Class.SampleFmt y =>+   FilePath -> SoundSink File y+fileSoundSink file =+   SoundSink {+      soundSinkOpen  = File.open IO.WriteMode file,+      soundSinkClose = File.close,+      soundSinkWrite = File.write,+      soundSinkStart = const $ return (),+      soundSinkStop  = const $ return ()+   }  -- -- * Marshalling utilities -- -callocaArray :: Storable y => SoundFmt y -> Int -> (Ptr y -> IO b) -> IO b-callocaArray _ n f =-   allocaArray n $ \p ->-      clearBytes p (arraySize p n) >>-      f p+callocaArray :: Storable y => Size -> (Ptr y -> IO b) -> IO b+callocaArray n0 f =+   case fromIntegral n0 of+      n ->+         allocaArray n $ \p ->+            clearBytes p (arraySize p n) >>+            f p  clearBytes :: Ptr a -> Int -> IO () clearBytes p n = memset p 0 (fromIntegral n) >> return () -{-# INLINE arraySize #-}-arraySize :: Storable y => Ptr y -> Int -> Int-arraySize p n = advancePtr p n `minusPtr` p--foreign import ccall unsafe "string.h" memset :: Ptr a -> CInt -> CSize -> IO (Ptr a)+foreign import ccall unsafe "string.h" memset :: Ptr a -> C.CInt -> C.CSize -> IO (Ptr a)
− src/Sound/ALSA/PCM/C2HS.hs
@@ -1,237 +0,0 @@---  C->Haskell Compiler: Marshalling library------  Copyright (c) [1999...2005] Manuel M T Chakravarty------  Redistribution and use in source and binary forms, with or without---  modification, are permitted provided that the following conditions are met:------  1. Redistributions of source code must retain the above copyright notice,---     this list of conditions and the following disclaimer.---  2. Redistributions in binary form must reproduce the above copyright---     notice, this list of conditions and the following disclaimer in the---     documentation and/or other materials provided with the distribution.---  3. The name of the author may not be used to endorse or promote products---     derived from this software without specific prior written permission.------  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR---  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES---  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN---  NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,---  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED---  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR---  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF---  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING---  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS---  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.------- Description ---------------------------------------------------------------------  Language: Haskell 98------  This module provides the marshaling routines for Haskell files produced by---  C->Haskell for binding to C library interfaces.  It exports all of the---  low-level FFI (language-independent plus the C-specific parts) together---  with the C->HS-specific higher-level marshalling routines.-----module Sound.ALSA.PCM.C2HS (--  -- * Re-export the language-independent component of the FFI-  St.Storable, St.poke, St.peek, St.sizeOf, St.alignment,-  Ptr, castPtr, with,-  Alloc.alloca,--  -- * Re-export the C language component of the FFI-  C.CInt, C.CUInt, C.CLong, C.CULong, C.CChar, C.withCString,--  -- * Composite marshalling functions-  withCStringLenIntConv, peekCStringLenIntConv, withIntConv, withFloatConv,-  peekIntConv, peekFloatConv, withBool, peekBool, withEnum, peekEnum,--  -- * Conditional results using 'Maybe'-  nothingIf, nothingIfNull,--  -- * Bit masks-  combineBitMasks, containsBitMask, extractBitMasks,--  -- * Conversion between C and Haskell types-  cIntConv, cFloatConv, cToBool, cFromBool, cToEnum, cFromEnum-) where---import Foreign.Ptr (Ptr, nullPtr, castPtr, )-import Foreign.Storable (Storable, peek, )-import Foreign.Marshal.Utils (fromBool, toBool, with, )--import qualified Foreign.Storable as St-import qualified Foreign.Marshal.Alloc as Alloc-import qualified Foreign.C as C--import Data.Bits (Bits, (.|.), (.&.), )--import Control.Monad (liftM, )----- Composite marshalling functions--- ----------------------------------- Strings with explicit length----withCStringLenIntConv ::-   (Integral i) =>-   String -> ((Ptr C.CChar, i) -> IO a) -> IO a-withCStringLenIntConv s f =-   C.withCStringLen s $ \(p, n) -> f (p, cIntConv n)--peekCStringLenIntConv ::-   (Integral i) =>-   (Ptr C.CChar, i) -> IO String-peekCStringLenIntConv (s, n) =-   C.peekCStringLen (s, cIntConv n)----- Marshalling of numerals-----withIntConv   :: (Storable b, Integral a, Integral b)-              => a -> (Ptr b -> IO c) -> IO c-withIntConv    = with . cIntConv--withFloatConv :: (Storable b, RealFloat a, RealFloat b)-              => a -> (Ptr b -> IO c) -> IO c-withFloatConv  = with . cFloatConv--peekIntConv   :: (Storable a, Integral a, Integral b)-              => Ptr a -> IO b-peekIntConv    = liftM cIntConv . peek--peekFloatConv :: (Storable a, RealFloat a, RealFloat b)-              => Ptr a -> IO b-peekFloatConv  = liftM cFloatConv . peek---- Passing Booleans by reference-----withBool :: (Integral a, Storable a) => Bool -> (Ptr a -> IO b) -> IO b-withBool  = with . fromBool--peekBool :: (Integral a, Storable a) => Ptr a -> IO Bool-peekBool  = liftM toBool . peek----- Passing enums by reference-----withEnum :: (Enum a, Integral b, Storable b) => a -> (Ptr b -> IO c) -> IO c-withEnum  = with . cFromEnum--peekEnum :: (Enum a, Integral b, Storable b) => Ptr b -> IO a-peekEnum  = liftM cToEnum . peek----- Storing of 'Maybe' values--- ---------------------------{--instance Storable a => Storable (Maybe a) where-  sizeOf    _ = sizeOf    (undefined :: Ptr ())-  alignment _ = alignment (undefined :: Ptr ())--  peek p = do-             ptr <- peek (castPtr p)-             if ptr == nullPtr-               then return Nothing-               else liftM Just $ peek ptr--  poke p v = do-               ptr <- case v of-                        Nothing -> return nullPtr-                        Just v' -> new v'-               poke (castPtr p) ptr--}---- Conditional results using 'Maybe'--- ------------------------------------- Wrap the result into a 'Maybe' type.------ * the predicate determines when the result is considered to be non-existing,---   ie, it is represented by `Nothing'------ * the second argument allows to map a result wrapped into `Just' to some---   other domain----nothingIf       :: (a -> Bool) -> (a -> b) -> a -> Maybe b-nothingIf p f x  = if p x then Nothing else Just $ f x---- |Instance for special casing null pointers.----nothingIfNull :: (Ptr a -> b) -> Ptr a -> Maybe b-nothingIfNull  = nothingIf (== nullPtr)----- Support for bit masks--- ------------------------- Given a list of enumeration values that represent bit masks, combine these--- masks using bitwise disjunction.----combineBitMasks :: (Enum a, Bits b) => [a] -> b-combineBitMasks = foldl (.|.) 0 . map (fromIntegral . fromEnum)---- Tests whether the given bit mask is contained in the given bit pattern--- (i.e., all bits set in the mask are also set in the pattern).----containsBitMask :: (Bits a, Enum b) => a -> b -> Bool-bits `containsBitMask` bm = let bm' = fromIntegral . fromEnum $ bm-                            in-                            bm' .&. bits == bm'---- |Given a bit pattern, yield all bit masks that it contains.------ * This does *not* attempt to compute a minimal set of bit masks that when---   combined yield the bit pattern, instead all contained bit masks are---   produced.----extractBitMasks :: (Bits a, Enum b, Bounded b) => a -> [b]-extractBitMasks bits =-  [bm | bm <- [minBound..maxBound], bits `containsBitMask` bm]----- Conversion routines--- ----------------------- |Integral conversion----cIntConv :: (Integral a, Integral b) => a -> b-cIntConv  = fromIntegral---- |Floating conversion----cFloatConv :: (RealFloat a, RealFloat b) => a -> b-cFloatConv  = realToFrac--- As this conversion by default goes via `Rational', it can be very slow...-{-# RULES-  "cFloatConv/Float->Float"   forall (x::Float).  cFloatConv x = x;-  "cFloatConv/Double->Double" forall (x::Double). cFloatConv x = x- #-}---- |Obtain C value from Haskell 'Bool'.----cFromBool :: Num a => Bool -> a-cFromBool  = fromBool---- |Obtain Haskell 'Bool' from C value.----cToBool :: Num a => a -> Bool-cToBool  = toBool---- |Convert a C enumeration to Haskell.----cToEnum :: (Integral i, Enum e) => i -> e-cToEnum  = toEnum . cIntConv---- |Convert a Haskell enumeration to C.----cFromEnum :: (Enum e, Integral i) => e -> i-cFromEnum  = cIntConv . fromEnum
− src/Sound/ALSA/PCM/Core.chs
@@ -1,316 +0,0 @@-{-# LANGUAGE ForeignFunctionInterface #-}-module Sound.ALSA.PCM.Core where--import Sound.ALSA.PCM.C2HS (cIntConv, peekIntConv, withIntConv, cFromEnum, )-import Sound.ALSA.Exception (checkResult, checkResult_, )--import Foreign.C.Types (CUInt, CULong, CInt, CLong, CChar, )-import Foreign.C.String (withCString, )-import Foreign.Ptr (Ptr, castPtr, )-import Foreign.Storable (Storable, sizeOf, alignment, peek, poke, )-import Foreign.Marshal.Utils (with, )-import Foreign.Marshal.Alloc (alloca, )------ HACK for 32-bit machines.--- This is only used to be able to parse alsa/pcm.h,--- since snd_pcm_format_silence_64 use u_int64_t which is not--- defined on 32-bit machines, AFAICT-#if __WORDSIZE == 32-typedef unsigned long long int u_int64_t;-#endif--#include <alsa/asoundlib.h>--{#context prefix = "snd_pcm_"#}--{#pointer *snd_pcm_t as Pcm newtype #}--instance Storable Pcm where-    sizeOf (Pcm r) = sizeOf r-    alignment (Pcm r) = alignment r-    peek p = fmap Pcm (peek (castPtr p))-    poke p (Pcm r) = poke (castPtr p) r--{#pointer *snd_pcm_hw_params_t as HwParams newtype #}--instance Storable HwParams where-    sizeOf (HwParams r) = sizeOf r-    alignment (HwParams r) = alignment r-    peek p = fmap HwParams (peek (castPtr p))-    poke p (HwParams r) = poke (castPtr p) r--{#pointer *snd_pcm_sw_params_t as SwParams newtype #}--instance Storable SwParams where-    sizeOf (SwParams r) = sizeOf r-    alignment (SwParams r) = alignment r-    peek p = fmap SwParams (peek (castPtr p))-    poke p (SwParams r) = poke (castPtr p) r--{#enum _snd_pcm_stream as Stream {underscoreToCase} deriving (Eq,Show)#}--{#enum _snd_pcm_access as Access {underscoreToCase} deriving (Eq,Show)#}--{#enum _snd_pcm_format as Format {underscoreToCase} deriving (Eq,Show)#}--{#fun snd_pcm_open as open-  { alloca- `Pcm' peek*,-    withCString* `String',-    cFromEnum `Stream',-    `Int'}- -> `()' result*- #}-  where result = checkResult_ "PCM.open"--{#fun snd_pcm_close as close-  { id `Pcm' }- -> `()' result*- #}-  where result = checkResult_ "PCM.close"--{#fun prepare-  { id `Pcm' }- -> `()' result*- #}-  where result = checkResult_ "PCM.prepare"--{#fun start-  { id `Pcm' }- -> `()' result*- #}-  where result = checkResult_ "PCM.start"--{#fun drop-  { id `Pcm' }- -> `()' result*- #}-  where result = checkResult_ "PCM.drop"--{#fun drain-  { id `Pcm' }- -> `()' result*- #}-  where result = checkResult_ "PCM.drain"--{---- Only available in 1.0.11rc3 and later-{#fun set_params-  { id `Pcm',-    cFromEnum `PcmFormat',-    cFromEnum `PcmAccess',-    `Int',-    `Int',-    `Bool',-    `Int' }- -> `()' result*- #}-  where result = checkResult_ "PCM.set_params"--}--{#fun hw_params-  { id `Pcm',-    id `HwParams' }- -> `()' result*- #}-  where result = checkResult_ "PCM.hw_params"--{#fun hw_params_any-  { id `Pcm',-    id `HwParams' }- -> `()' result*- #}-  where result = checkResult_ "PCM.hw_params_any"--{#fun hw_params_set_access-  { id `Pcm',-    id `HwParams',-    cFromEnum `Access'- }- -> `()' result*- #}-  where result = checkResult_ "PCM.hw_params_set_access"--{#fun hw_params_set_format-  { id `Pcm',-    id `HwParams',-    cFromEnum `Format'- }- -> `()' result*- #}-  where result = checkResult_ "PCM.hw_params_set_format"--{#fun hw_params_set_rate-  { id `Pcm',-    id `HwParams',-    `Int',-    orderingToInt `Ordering'- }- -> `()' result*- #}-  where result = checkResult_ "PCM.hw_params_set_rate"--{---- Available in 1.0.9rc2 and later-{#fun hw_params_set_rate_resample-  { id `Pcm',-    id `HwParams',-    `Bool'- }- -> `()' result*- #}-  where result = checkResult_ "PCM.hw_params_set_rate_resample"--}--{#fun hw_params_set_channels-  { id `Pcm',-    id `HwParams',-    `Int'- }- -> `()' result*- #}-  where result = checkResult_ "PCM.hw_params_set_channels"--{#fun hw_params_set_buffer_size-  { id `Pcm',-    id `HwParams',-    `Int'- }- -> `()' result*- #}-  where result = checkResult_ "PCM.hw_params_set_buffer_size"--{#fun hw_params_get_buffer_size-  { id `HwParams',-    alloca- `Int' peekIntConv*- }- -> `()' result*- #}-  where result = checkResult_ "PCM.hw_params_get_buffer_size"--{#fun hw_params_get_period_size-  { id `HwParams',-    alloca- `Int' peekIntConv*,-    alloca- `Ordering' peekOrdering*- }- -> `()' result*- #}-  where result = checkResult_ "PCM.hw_params_get_period_size"--{#fun hw_params_set_period_time_near-  { id `Pcm',-    id `HwParams',-    withIntConv* `Int' peekIntConv*,-    withOrdering* `Ordering' peekOrdering*- }- -> `()' result*- #}-  where result = checkResult_ "PCM.hw_params_set_period_time_near"--{#fun hw_params_set_periods-  { id `Pcm',-    id `HwParams',-    `Int',-    orderingToInt `Ordering'- }- -> `()' result*- #}-  where result = checkResult_ "PCM.hw_params_set_periods"--{#fun hw_params_set_buffer_time_near-  { id `Pcm',-    id `HwParams',-    withIntConv* `Int' peekIntConv*,-    withOrdering* `Ordering' peekOrdering*- }- -> `()' result*- #}-  where result = checkResult_ "PCM.hw_params_set_buffer_time_near"--{#fun hw_params_get_buffer_time-  { id `HwParams',-    alloca- `Int' peekIntConv*,-    alloca- `Ordering' peekOrdering*- }- -> `()' result*- #}-  where result = checkResult_ "PCM.hw_params_get_buffer_time"--{#fun sw_params_set_start_threshold-  { id `Pcm',-    id `SwParams',-    `Int'- }- -> `()' result*- #}-  where result = checkResult_ "PCM.sw_params_set_start_threshold"--{#fun sw_params_set_avail_min-  { id `Pcm',-    id `SwParams',-    `Int'- }- -> `()' result*- #}-  where result = checkResult_ "PCM.sw_params_set_avail_min"--{#fun sw_params_set_xfer_align-  { id `Pcm',-    id `SwParams',-    `Int' }- -> `()' result*- #}-  where result = checkResult_ "PCM.sw_params_set_xfer_align"--{#fun sw_params_set_silence_threshold-  { id `Pcm',-    id `SwParams',-    `Int' }- -> `()' result*- #}-  where result = checkResult_ "PCM.sw_params_set_silence_threshold"--{#fun sw_params_set_silence_size-  { id `Pcm',-    id `SwParams',-    `Int' }- -> `()' result*- #}-  where result = checkResult_ "PCM.sw_params_set_silence_size"--{#fun readi-  { id `Pcm',-    castPtr `Ptr a',-    `Int'- }- -> `Int' result* #}-  where result = fmap fromIntegral . checkResult "PCM.readi"--{#fun writei-  { id `Pcm',-    castPtr `Ptr a',-    `Int'- }- -> `Int' result* #}-  where result = fmap fromIntegral . checkResult "PCM.writei"--{#fun hw_params_malloc-  { alloca- `HwParams' peek* }- -> `()' result*- #}-  where result = checkResult_ "PCM.hw_params_malloc"--{#fun hw_params_free-  { id `HwParams' }- -> `()' #}--{#fun sw_params_malloc-  { alloca- `SwParams' peek* }- -> `()' result*- #}-  where result = checkResult_ "PCM.sw_params_malloc"--{#fun sw_params_free-  { id `SwParams' }- -> `()' #}--{#fun sw_params-  { id `Pcm',-    id `SwParams' }- -> `()' result*- #}-  where result = checkResult_ "PCM.sw_params"--{#fun sw_params_current-  { id `Pcm',-    id `SwParams' }- -> `()' result*- #}-  where result = checkResult_ "PCM.sw_params_current"------- * Marshalling utilities-----orderingToInt :: Ordering -> CInt-orderingToInt o = fromIntegral (fromEnum o - 1)--intToOrdering :: CInt -> Ordering-intToOrdering i = compare i 0--peekOrdering :: Ptr CInt -> IO Ordering-peekOrdering = fmap intToOrdering . peek--withOrdering :: Ordering -> (Ptr CInt -> IO a) -> IO a-withOrdering o = with (orderingToInt o)
+ src/Sound/ALSA/PCM/Core/Class.hs view
@@ -0,0 +1,107 @@+module Sound.ALSA.PCM.Core.Class where++import qualified Sound.ALSA.PCM.Core.Handle as Core+import qualified Sound.ALSA.PCM.Core.HwParams as HwParams+import qualified Sound.ALSA.PCM.Core.SwParams as SwParams++import qualified Sound.Frame as Frame+import qualified Sound.Frame.Stereo as Stereo+import qualified Sound.Frame.MuLaw  as MuLaw++import Data.Word (Word8, Word16, Word32, )+import Data.Int (Int8, Int16, Int32, )++import Foreign (Storable, )+++class Access i where+   access :: HwParams.T i y HwParams.Access+   setChannels :: (Frame.C y) => HwParams.T i y ()++instance Access Core.Interleaved where+   access = return HwParams.accessRwInterleaved+   setChannels =+      HwParams.setChannels . fromIntegral =<<+         withSampleFmt Frame.numberOfChannels++instance Access Core.Noninterleaved where+   access = return HwParams.accessRwNoninterleaved+   setChannels = return ()++++{-+We should have support for 24bit samples+that are packed on disk but padded to 32bit in memory.+-}+class (Storable y, Frame.C y) => SampleFmt y where+   sampleFmtToPcmFormat :: y -> HwParams.Format++instance SampleFmt Word8 where+   sampleFmtToPcmFormat _ = HwParams.formatU8++instance SampleFmt Int8 where+   sampleFmtToPcmFormat _ = HwParams.formatS8++instance SampleFmt Word16 where+   sampleFmtToPcmFormat _ = HwParams.formatU16++instance SampleFmt Int16 where+   sampleFmtToPcmFormat _ = HwParams.formatS16++instance SampleFmt Word32 where+   sampleFmtToPcmFormat _ = HwParams.formatU32++instance SampleFmt Int32 where+   sampleFmtToPcmFormat _ = HwParams.formatS32++instance SampleFmt Float where+   sampleFmtToPcmFormat _ = HwParams.formatFloat++instance SampleFmt Double where+   sampleFmtToPcmFormat _ = HwParams.formatFloat64++instance SampleFmt MuLaw.T where+   sampleFmtToPcmFormat _ = HwParams.formatMuLaw++instance SampleFmt a => SampleFmt (Stereo.T a) where+   sampleFmtToPcmFormat y =+      sampleFmtToPcmFormat (Stereo.left y)+++{- |+Sample types of this class must have exactly one channel,+i.e. Frame.numberOfChannels == 1.+-}+class (SampleFmt y) => MonoSampleFmt y where++instance MonoSampleFmt Word8 where+instance MonoSampleFmt Int8 where+instance MonoSampleFmt Word16 where+instance MonoSampleFmt Int16 where+instance MonoSampleFmt Word32 where+instance MonoSampleFmt Int32 where+instance MonoSampleFmt Float where+instance MonoSampleFmt Double where+instance MonoSampleFmt MuLaw.T where+++withSampleFmt :: (y -> a) -> HwParams.T i y a+withSampleFmt f = return $ f undefined+++withHwParams ::+   (Access i, SampleFmt y) =>+   Core.Handle i y -> HwParams.T i y a -> IO a+withHwParams h f =+   HwParams.withIO h $ (\(HwParams.Cons act) -> act h) $ do+      HwParams.setAccess =<< access+      HwParams.setFormat =<< withSampleFmt sampleFmtToPcmFormat+      setChannels+      f++withSwParams ::+   (Access i, SampleFmt y) =>+   Core.Handle i y -> SwParams.T i y a -> IO a+withSwParams h (SwParams.Cons f) =+   SwParams.withIO h $ f h
+ src/Sound/ALSA/PCM/Core/Convert.hs view
@@ -0,0 +1,34 @@+module Sound.ALSA.PCM.Core.Convert where++import qualified Foreign.Marshal.Utils as U+import qualified Foreign.Storable as St+import Foreign.Ptr (Ptr, )++import qualified Prelude as P+import Prelude hiding (id, )+++data T h c =+        Cons {fromHaskell :: h -> c, toHaskell :: c -> h}++with ::+   (St.Storable c) =>+   T h c -> h -> (Ptr c -> IO a) -> IO a+with conv a = U.with (fromHaskell conv a)++peek ::+   (St.Storable a) =>+   T h a -> Ptr a -> IO h+peek conv aptr = fmap (toHaskell conv) $ St.peek aptr+++id :: T a a+id = Cons P.id P.id++int :: (Integral a, Integral b) => T a b+int = Cons fromIntegral fromIntegral++{-+word :: T Word C.CUInt+word = Cons fromIntegral fromIntegral+-}
+ src/Sound/ALSA/PCM/Core/Handle.hsc view
@@ -0,0 +1,157 @@+{-# LANGUAGE ForeignFunctionInterface #-}+module Sound.ALSA.PCM.Core.Handle where++import Sound.ALSA.Exception (checkResult, checkResult_, )++import qualified Foreign.Storable.Newtype as Store++import qualified Foreign.C.Types as C+import Foreign.C.String (CString, withCString, )+import Foreign.Ptr (Ptr, minusPtr, )+import Foreign.Storable (Storable, sizeOf, alignment, peek, poke, )+import Foreign.Marshal.Array (advancePtr, )+import Foreign.Marshal.Alloc (alloca, )++import Data.Bits ((.|.), )+import Data.Monoid (Monoid, mempty, mappend, mconcat, )++import Prelude hiding (any, )+++#include <alsa/asoundlib.h>+++data Struct i y = Struct++newtype Handle i y = Handle {dePcm :: Ptr (Struct i y)}++data Interleaved = Interleaved+data Noninterleaved = Noninterleaved+++instance Storable (Handle i y) where+   sizeOf = Store.sizeOf dePcm+   alignment = Store.alignment dePcm+   peek = Store.peek Handle+   poke = Store.poke dePcm+++type SampleFreq = Int+type Time = Int+type Size = Int+++data Stream =+     StreamPlayback+   | StreamCapture+   deriving (Eq,Show,Bounded)++instance Enum Stream where+   fromEnum StreamPlayback = #{const SND_PCM_STREAM_PLAYBACK}+   fromEnum StreamCapture  = #{const SND_PCM_STREAM_CAPTURE}++   toEnum #{const SND_PCM_STREAM_PLAYBACK} = StreamPlayback+   toEnum #{const SND_PCM_STREAM_CAPTURE}  = StreamCapture+   toEnum unmatched = error ("Stream.toEnum: Cannot match " ++ show unmatched)+++newtype Mode = Mode C.CInt++#{enum Mode, Mode,+   nonBlock = SND_PCM_NONBLOCK,+   async = SND_PCM_ASYNC }++instance Monoid Mode where+   mempty = Mode 0+   mappend (Mode a) (Mode b) = Mode (a .|. b)++modes :: [Mode] -> Mode+modes = mconcat+++foreign import ccall safe "alsa/pcm.h snd_pcm_open"+   open_ :: Ptr (Handle i y) -> CString -> C.CInt -> Mode -> IO C.CInt++foreign import ccall safe "alsa/pcm.h snd_pcm_close"+   close_ :: Handle i y -> IO C.CInt++foreign import ccall safe "alsa/pcm.h snd_pcm_prepare"+   prepare_ :: Handle i y -> IO C.CInt++foreign import ccall safe "alsa/pcm.h snd_pcm_start"+   start_ :: Handle i y -> IO C.CInt++foreign import ccall safe "alsa/pcm.h snd_pcm_drop"+   drop_ :: Handle i y -> IO C.CInt++foreign import ccall safe "alsa/pcm.h snd_pcm_drain"+   drain_ :: Handle i y -> IO C.CInt+++open :: String -> Stream -> Mode -> IO (Handle i y)+open device dir mode =+   alloca $ \ptr ->+   withCString device $ \deviceCStr ->+   open_ ptr deviceCStr (fromIntegral $ fromEnum dir) mode >>=+   checkResult_ "PCM.open" >>+   peek ptr++close :: Handle i y -> IO ()+close h =+   close_ h >>= checkResult_ "PCM.close"++prepare :: Handle i y -> IO ()+prepare h =+   prepare_ h >>= checkResult_ "PCM.prepare"++start :: Handle i y -> IO ()+start h =+   start_ h >>= checkResult_ "PCM.start"++drop :: Handle i y -> IO ()+drop h =+   drop_ h >>= checkResult_ "PCM.drop"++drain :: Handle i y -> IO ()+drain h =+   drain_ h >>= checkResult_ "PCM.drain"++++foreign import ccall safe "alsa/pcm.h snd_pcm_readi"+   readi_ :: Handle Interleaved y -> Ptr y -> C.CULong -> IO C.CLong++foreign import ccall safe "alsa/pcm.h snd_pcm_writei"+   writei_ :: Handle Interleaved y -> Ptr y -> C.CULong -> IO C.CLong++foreign import ccall safe "alsa/pcm.h snd_pcm_readn"+   readn_ :: Handle Noninterleaved y -> Ptr (Ptr y) -> C.CULong -> IO C.CLong++foreign import ccall safe "alsa/pcm.h snd_pcm_writen"+   writen_ :: Handle Noninterleaved y -> Ptr (Ptr y) -> C.CULong -> IO C.CLong+++readi :: Handle Interleaved y -> Ptr y -> Size -> IO Size+readi h buf n =+   fmap fromIntegral $+   checkResult "PCM.readi" =<< readi_ h buf (fromIntegral n)++writei :: Handle Interleaved y -> Ptr y -> Size -> IO Size+writei h buf n =+   fmap fromIntegral $+   checkResult "PCM.writei" =<< writei_ h buf (fromIntegral n)++readn :: Handle Noninterleaved y -> Ptr (Ptr y) -> Size -> IO Size+readn h buf n =+   fmap fromIntegral $+   checkResult "PCM.readn" =<< readn_ h buf (fromIntegral n)++writen :: Handle Noninterleaved y -> Ptr (Ptr y) -> Size -> IO Size+writen h buf n =+   fmap fromIntegral $+   checkResult "PCM.writen" =<< writen_ h buf (fromIntegral n)+++{-# INLINE arraySize #-}+arraySize :: Storable y => Ptr y -> Int -> Int+arraySize p n = advancePtr p n `minusPtr` p
+ src/Sound/ALSA/PCM/Core/HwParams.hsc view
@@ -0,0 +1,382 @@+{-# LANGUAGE ForeignFunctionInterface #-}+module Sound.ALSA.PCM.Core.HwParams where++import Sound.ALSA.PCM.Core.Handle (Handle, Time, Size, SampleFreq, )+import qualified Sound.ALSA.PCM.Core.Handle as H -- expose Handle constructor to FFI+import qualified Sound.ALSA.PCM.Core.Convert as Conv+import Sound.ALSA.PCM.Core.Convert (fromHaskell, )++import Sound.ALSA.Exception (checkResult, checkResult_, )++import Control.Applicative (Applicative(pure, (<*>)))++import Control.Exception (bracket, )++import qualified Foreign.Storable.Newtype as Store++import qualified Foreign.C.Types as C+import qualified Foreign.C.Error as E+import Foreign.Ptr (Ptr, )+import Foreign.Storable (Storable, sizeOf, alignment, peek, poke, )+import Foreign.Marshal.Alloc (alloca, )++import Data.Word (Word, )++import Prelude hiding (any, )++#include <alsa/asoundlib.h>+#include <Sound/ALSA/PCM/Core/Params.h>++++newtype T i y a = Cons (H.Handle i y -> Ptr Params -> IO a)++data Params = Params+++{-+T is a Reader monad.+-}+instance Functor (T i y) where+   fmap f (Cons act) = Cons $ \h p -> fmap f $ act h p++instance Applicative (T i y) where+   pure a = Cons $ \ _h _p -> pure a+   Cons f <*> Cons x = Cons $ \h p -> f h p <*> x h p++instance Monad (T i y) where+   return a = Cons $ \ _h _p -> return a+   Cons x >>= k =+      Cons $ \h p -> x h p >>= \a -> case k a of Cons y -> y h p++++withIO :: Handle i y -> (Ptr Params -> IO a) -> IO a+withIO h f =+   bracket malloc free $ \p -> do+      any h p+      x <- f p+      set h p+      return x+--    bracket_ (any h p) (set h p) (f p)+++foreign import ccall safe "alsa/pcm.h snd_pcm_hw_params_malloc"+   malloc_ :: Ptr (Ptr Params) -> IO C.CInt++foreign import ccall safe "alsa/pcm.h snd_pcm_hw_params_free"+   free :: Ptr Params -> IO ()++malloc :: IO (Ptr Params)+malloc =+   alloca $ \pp ->+   malloc_ pp >>=+   checkResult_ "HwParams.malloc" >>+   peek pp++++foreign import ccall safe "alsa/pcm.h snd_pcm_hw_params"+   set_ :: Handle i y -> Ptr Params -> IO C.CInt++foreign import ccall safe "alsa/pcm.h snd_pcm_hw_params_any"+   any_ :: Handle i y -> Ptr Params -> IO C.CInt++set :: Handle i y -> Ptr Params -> IO ()+set h p =+   set_ h p >>= checkResult_ "HwParams.set"++any :: Handle i y -> Ptr Params -> IO ()+any h p =+   any_ h p >>= checkResult_ "HwParams.any"++-- #accessor checked, "any", pcm_params, NULL+++newtype Bool_ = Bool_ {fromBool_ :: C.CInt}+   deriving (Eq, Ord)++instance Storable Bool_ where+   sizeOf = Store.sizeOf fromBool_+   alignment = Store.alignment fromBool_+   peek = Store.peek Bool_+   poke = Store.poke fromBool_++boolConv :: Conv.T Bool Bool_+boolConv =+   Conv.Cons+      (\b -> Bool_ $ fromIntegral $ fromEnum b)+      (Bool_ 0 /=)+++newtype Direction = Direction {fromDirection :: C.CInt}+   deriving (Eq, Ord)++instance Storable Direction where+   sizeOf = Store.sizeOf fromDirection+   alignment = Store.alignment fromDirection+   peek = Store.peek Direction+   poke = Store.poke fromDirection++ordConv :: Conv.T Ordering Direction+ordConv =+   Conv.Cons+      (\o -> Direction $ fromIntegral $ fromEnum o - 1)+      (\d -> compare d $ Direction 0)+++newtype Access = Access {fromAccess :: C.CInt}+   deriving (Eq, Ord)++instance Enum Access where+   toEnum n = Access $ fromIntegral n+   fromEnum (Access n) = fromIntegral n++instance Bounded Access where+   minBound = Access #{const SND_PCM_ACCESS_MMAP_INTERLEAVED}+   maxBound = Access #{const SND_PCM_ACCESS_LAST}++instance Storable Access where+   sizeOf = Store.sizeOf fromAccess+   alignment = Store.alignment fromAccess+   peek = Store.peek Access+   poke = Store.poke fromAccess++#{enum Access, Access,+   accessMmapInterleaved    = SND_PCM_ACCESS_MMAP_INTERLEAVED,+   accessMmapNoninterleaved = SND_PCM_ACCESS_MMAP_NONINTERLEAVED,+   accessMmapComplex        = SND_PCM_ACCESS_MMAP_COMPLEX,+   accessRwInterleaved      = SND_PCM_ACCESS_RW_INTERLEAVED,+   accessRwNoninterleaved   = SND_PCM_ACCESS_RW_NONINTERLEAVED }++++newtype Format = Format {fromFormat :: C.CInt}+   deriving (Eq, Ord)++instance Enum Format where+   toEnum n = Format $ fromIntegral n+   fromEnum (Format n) = fromIntegral n++instance Bounded Format where+   minBound = formatUnknown+   maxBound = Format #{const SND_PCM_FORMAT_LAST}++instance Storable Format where+   sizeOf = Store.sizeOf fromFormat+   alignment = Store.alignment fromFormat+   peek = Store.peek Format+   poke = Store.poke fromFormat++#{enum Format, Format,+   formatUnknown          = SND_PCM_FORMAT_UNKNOWN,+   formatS8               = SND_PCM_FORMAT_S8,+   formatU8               = SND_PCM_FORMAT_U8,+   formatS16Le            = SND_PCM_FORMAT_S16_LE,+   formatS16Be            = SND_PCM_FORMAT_S16_BE,+   formatU16Le            = SND_PCM_FORMAT_U16_LE,+   formatU16Be            = SND_PCM_FORMAT_U16_BE,+   formatS24Le            = SND_PCM_FORMAT_S24_LE,+   formatS24Be            = SND_PCM_FORMAT_S24_BE,+   formatU24Le            = SND_PCM_FORMAT_U24_LE,+   formatU24Be            = SND_PCM_FORMAT_U24_BE,+   formatS32Le            = SND_PCM_FORMAT_S32_LE,+   formatS32Be            = SND_PCM_FORMAT_S32_BE,+   formatU32Le            = SND_PCM_FORMAT_U32_LE,+   formatU32Be            = SND_PCM_FORMAT_U32_BE,+   formatFloatLe          = SND_PCM_FORMAT_FLOAT_LE,+   formatFloatBe          = SND_PCM_FORMAT_FLOAT_BE,+   formatFloat64Le        = SND_PCM_FORMAT_FLOAT64_LE,+   formatFloat64Be        = SND_PCM_FORMAT_FLOAT64_BE,+   formatIec958SubframeLe = SND_PCM_FORMAT_IEC958_SUBFRAME_LE,+   formatIec958SubframeBe = SND_PCM_FORMAT_IEC958_SUBFRAME_BE,+   formatMuLaw            = SND_PCM_FORMAT_MU_LAW,+   formatALaw             = SND_PCM_FORMAT_A_LAW,+   formatImaAdpcm         = SND_PCM_FORMAT_IMA_ADPCM,+   formatMpeg             = SND_PCM_FORMAT_MPEG,+   formatGsm              = SND_PCM_FORMAT_GSM,+   formatSpecial          = SND_PCM_FORMAT_SPECIAL,+   formatS243le           = SND_PCM_FORMAT_S24_3LE,+   formatS243be           = SND_PCM_FORMAT_S24_3BE,+   formatU243le           = SND_PCM_FORMAT_U24_3LE,+   formatU243be           = SND_PCM_FORMAT_U24_3BE,+   formatS203le           = SND_PCM_FORMAT_S20_3LE,+   formatS203be           = SND_PCM_FORMAT_S20_3BE,+   formatU203le           = SND_PCM_FORMAT_U20_3LE,+   formatU203be           = SND_PCM_FORMAT_U20_3BE,+   formatS183le           = SND_PCM_FORMAT_S18_3LE,+   formatS183be           = SND_PCM_FORMAT_S18_3BE,+   formatU183le           = SND_PCM_FORMAT_U18_3LE,+   formatU183be           = SND_PCM_FORMAT_U18_3BE,+   formatS16              = SND_PCM_FORMAT_S16,+   formatU16              = SND_PCM_FORMAT_U16,+   formatS24              = SND_PCM_FORMAT_S24,+   formatU24              = SND_PCM_FORMAT_U24,+   formatS32              = SND_PCM_FORMAT_S32,+   formatU32              = SND_PCM_FORMAT_U32,+   formatFloat            = SND_PCM_FORMAT_FLOAT,+   formatFloat64          = SND_PCM_FORMAT_FLOAT64,+   formatIec958Subframe   = SND_PCM_FORMAT_IEC958_SUBFRAME }+++newtype Subformat = Subformat {fromSubformat :: C.CUInt}+   deriving (Eq, Ord)++instance Storable Subformat where+   sizeOf = Store.sizeOf fromSubformat+   alignment = Store.alignment fromSubformat+   peek = Store.peek Subformat+   poke = Store.poke fromSubformat++++#accessor boolresult, "can_mmap_sample_resolution", params_only, NULL+#accessor boolresult, "is_double", params_only, NULL+#accessor boolresult, "is_batch", params_only, NULL+#accessor boolresult, "is_block_transfer", params_only, NULL+#accessor boolresult, "can_overrange", params_only, NULL+#accessor boolresult, "can_pause", params_only, NULL+#accessor boolresult, "can_resume", params_only, NULL+#accessor boolresult, "is_half_duplex", params_only, NULL+#accessor boolresult, "is_joint_duplex", params_only, NULL+#accessor boolresult, "can_sync_start", params_only, NULL+++#accessor checked, "get_rate_numden", params_only, \+               out(&uint_p, "rateNum"), out(&uint_p, "rateDen"), NULL+#accessor uintresult, "get_sbits", params_only, NULL+#accessor uintresult, "get_fifo_size", params_only, NULL++#accessor checked, "get_access", params_only, out(&access_p, "access"), NULL+#accessor errnoresult, "test_access", pcm_params, in(&access_p, "access"), NULL+#accessor checked, "set_access", pcm_params, in(&access_p, "access"), NULL+#accessor checked, "set_access_first", pcm_params, inout(&access_p, "access"), NULL+#accessor checked, "set_access_last", pcm_params, inout(&access_p, "access"), NULL+{- in order to use this, we would have to implement mask accessors, too+#accessor checked, "set_access_mask", pcm_params, inout(&access_mask, "mask"), NULL+#accessor checked, "get_access_mask", params_only, out(&access_mask, "mask"), NULL+-}++#accessor checked, "get_format", params_only, out(&format_p, "val"), NULL+#accessor errnoresult, "test_format", pcm_params, in(&format_p, "val"), NULL+#accessor checked, "set_format", pcm_params, in(&format_p, "val"), NULL+#accessor checked, "set_format_first", pcm_params, inout(&format_p, "format"), NULL+#accessor checked, "set_format_last", pcm_params, inout(&format_p, "format"), NULL+{-+#accessor checked, "set_format_mask", pcm_params, inout(&format_mask_p, "mask"), NULL+#accessor noresult, "get_format_mask", params_only, out(&format_mask_p, "mask"), NULL+-}++#accessor checked, "get_subformat", params_only, out(&subformat_p, "subformat"), NULL+#accessor errnoresult, "test_subformat", pcm_params, in(&subformat_p, "subformat"), NULL+#accessor checked, "set_subformat", pcm_params, in(&subformat_p, "subformat"), NULL+#accessor checked, "set_subformat_first", pcm_params, inout(&subformat_p, "subformat"), NULL+#accessor checked, "set_subformat_last", pcm_params, inout(&subformat_p, "subformat"), NULL+{-+#accessor checked, "set_subformat_mask", pcm_params, inout(&subformat_mask_p, "mask"), NULL+#accessor noresult, "get_subformat_mask", params_only, out(&subformat_mask_p, "mask"), NULL+-}++#accessor checked, "get_channels", params_only, out(&uint_p, "val"), NULL+#accessor checked, "get_channels_min", params_only, out(&uint_p, "val"), NULL+#accessor checked, "get_channels_max", params_only, out(&uint_p, "val"), NULL+#accessor errnoresult, "test_channels", pcm_params, in(&uint_p, "val"), NULL+#accessor checked, "set_channels", pcm_params, in(&uint_p, "val"), NULL+#accessor checked, "set_channels_min", pcm_params, inout(&uint_p, "val"), NULL+#accessor checked, "set_channels_max", pcm_params, inout(&uint_p, "val"), NULL+#accessor checked, "set_channels_minmax", pcm_params, inout(&uint_p, "vmin"), inout(&uint_p, "vmax"), NULL+#accessor checked, "set_channels_near", pcm_params, inout(&uint_p, "val"), NULL+#accessor checked, "set_channels_first", pcm_params, inout(&uint_p, "val"), NULL+#accessor checked, "set_channels_last", pcm_params, inout(&uint_p, "val"), NULL++#accessor checked, "get_rate", params_only, out(&rate_p, "val"), out(&direction_p, "dir"), NULL+#accessor checked, "get_rate_min", params_only, out(&rate_p, "val"), out(&direction_p, "dir"), NULL+#accessor checked, "get_rate_max", params_only, out(&rate_p, "val"), out(&direction_p, "dir"), NULL+#accessor errnoresult, "test_rate", pcm_params, in(&rate_p, "val"), in(&direction_p, "dir"), NULL+#accessor checked, "set_rate", pcm_params, in(&rate_p, "val"), in(&direction_p, "dir"), NULL+#accessor checked, "set_rate_min", pcm_params, inout(&rate_p, "val"), inout(&direction_p, "dir"), NULL+#accessor checked, "set_rate_max", pcm_params, inout(&rate_p, "val"), inout(&direction_p, "dir"), NULL+#accessor checked, "set_rate_minmax", pcm_params, inout(&rate_p, "vmin"), inout(&direction_p, "mindir"), inout(&rate_p, "vmax"), inout(&direction_p, "maxdir"), NULL+#accessor checked, "set_rate_near", pcm_params, inout(&rate_p, "val"), inout(&direction_p, "dir"), NULL+#accessor checked, "set_rate_first", pcm_params, inout(&rate_p, "val"), inout(&direction_p, "dir"), NULL+#accessor checked, "set_rate_last", pcm_params, inout(&rate_p, "val"), inout(&direction_p, "dir"), NULL+#accessor checked, "set_rate_resample", pcm_params, in(&bool_p, "val"), NULL+#accessor checked, "get_rate_resample", pcm_params, out(&bool_p, "val"), NULL+#accessor checked, "set_export_buffer", pcm_params, in(&bool_p, "val"), NULL+#accessor checked, "get_export_buffer", pcm_params, out(&bool_p, "val"), NULL++#accessor checked, "get_period_time", params_only, out(&time_p, "val"), out(&direction_p, "dir"), NULL+#accessor checked, "get_period_time_min", params_only, out(&time_p, "val"), out(&direction_p, "dir"), NULL+#accessor checked, "get_period_time_max", params_only, out(&time_p, "val"), out(&direction_p, "dir"), NULL+#accessor errnoresult, "test_period_time", pcm_params, in(&time_p, "val"), in(&direction_p, "dir"), NULL+#accessor checked, "set_period_time", pcm_params, in(&time_p, "val"), in(&direction_p, "dir"), NULL+#accessor checked, "set_period_time_min", pcm_params, inout(&time_p, "val"), inout(&direction_p, "dir"), NULL+#accessor checked, "set_period_time_max", pcm_params, inout(&time_p, "val"), inout(&direction_p, "dir"), NULL+#accessor checked, "set_period_time_minmax", pcm_params, inout(&time_p, "vmin"), inout(&direction_p, "mindir"), inout(&time_p, "vmax"), inout(&direction_p, "maxdir"), NULL+#accessor checked, "set_period_time_near", pcm_params, inout(&time_p, "val"), inout(&direction_p, "dir"), NULL+#accessor checked, "set_period_time_first", pcm_params, inout(&time_p, "val"), inout(&direction_p, "dir"), NULL+#accessor checked, "set_period_time_last", pcm_params, inout(&time_p, "val"), inout(&direction_p, "dir"), NULL++#accessor checked, "get_period_size", params_only, out(&uframes_p, "frames"), out(&direction_p, "dir"), NULL+#accessor checked, "get_period_size_min", params_only, out(&uframes_p, "frames"), out(&direction_p, "dir"), NULL+#accessor checked, "get_period_size_max", params_only, out(&uframes_p, "frames"), out(&direction_p, "dir"), NULL+#accessor errnoresult, "test_period_size", pcm_params, in(&uframes_p, "val"), in(&direction_p, "dir"), NULL+#accessor checked, "set_period_size", pcm_params, in(&uframes_p, "val"), in(&direction_p, "dir"), NULL+#accessor checked, "set_period_size_min", pcm_params, inout(&uframes_p, "val"), inout(&direction_p, "dir"), NULL+#accessor checked, "set_period_size_max", pcm_params, inout(&uframes_p, "val"), inout(&direction_p, "dir"), NULL+#accessor checked, "set_period_size_minmax", pcm_params, inout(&uframes_p, "vmin"), inout(&direction_p, "mindir"), inout(&uframes_p, "vmax"), inout(&direction_p, "maxdir"), NULL+#accessor checked, "set_period_size_near", pcm_params, inout(&uframes_p, "val"), inout(&direction_p, "dir"), NULL+#accessor checked, "set_period_size_first", pcm_params, inout(&uframes_p, "val"), inout(&direction_p, "dir"), NULL+#accessor checked, "set_period_size_last", pcm_params, inout(&uframes_p, "val"), inout(&direction_p, "dir"), NULL+#accessor checked, "set_period_size_integer", pcm_params, NULL++#accessor checked, "get_periods", params_only, out(&uint_p, "val"), out(&direction_p, "dir"), NULL+#accessor checked, "get_periods_min", params_only, out(&uint_p, "val"), out(&direction_p, "dir"), NULL+#accessor checked, "get_periods_max", params_only, out(&uint_p, "val"), out(&direction_p, "dir"), NULL+#accessor errnoresult, "test_periods", pcm_params, in(&uint_p, "val"), in(&direction_p, "dir"), NULL+#accessor checked, "set_periods", pcm_params, in(&uint_p, "val"), in(&direction_p, "dir"), NULL+#accessor checked, "set_periods_min", pcm_params, inout(&uint_p, "val"), inout(&direction_p, "dir"), NULL+#accessor checked, "set_periods_max", pcm_params, inout(&uint_p, "val"), inout(&direction_p, "dir"), NULL+#accessor checked, "set_periods_minmax", pcm_params, inout(&uint_p, "vmin"), inout(&direction_p, "mindir"), inout(&uint_p, "vmax"), inout(&direction_p, "maxdir"), NULL+#accessor checked, "set_periods_near", pcm_params, inout(&uint_p, "val"), inout(&direction_p, "dir"), NULL+#accessor checked, "set_periods_first", pcm_params, inout(&uint_p, "val"), inout(&direction_p, "dir"), NULL+#accessor checked, "set_periods_last", pcm_params, inout(&uint_p, "val"), inout(&direction_p, "dir"), NULL+#accessor checked, "set_periods_integer", pcm_params, NULL++#accessor checked, "get_buffer_time", params_only, out(&time_p, "val"), out(&direction_p, "dir"), NULL+#accessor checked, "get_buffer_time_min", params_only, out(&time_p, "val"), out(&direction_p, "dir"), NULL+#accessor checked, "get_buffer_time_max", params_only, out(&time_p, "val"), out(&direction_p, "dir"), NULL+#accessor errnoresult, "test_buffer_time", pcm_params, in(&time_p, "val"), in(&direction_p, "dir"), NULL+#accessor checked, "set_buffer_time", pcm_params, in(&time_p, "val"), in(&direction_p, "dir"), NULL+#accessor checked, "set_buffer_time_min", pcm_params, inout(&time_p, "val"), inout(&direction_p, "dir"), NULL+#accessor checked, "set_buffer_time_max", pcm_params, inout(&time_p, "val"), inout(&direction_p, "dir"), NULL+#accessor checked, "set_buffer_time_minmax", pcm_params, inout(&time_p, "vmin"), inout(&direction_p, "mindir"), inout(&time_p, "vmax"), inout(&direction_p, "maxdir"), NULL+#accessor checked, "set_buffer_time_near", pcm_params, inout(&time_p, "val"), inout(&direction_p, "dir"), NULL+#accessor checked, "set_buffer_time_first", pcm_params, inout(&time_p, "val"), inout(&direction_p, "dir"), NULL+#accessor checked, "set_buffer_time_last", pcm_params, inout(&time_p, "val"), inout(&direction_p, "dir"), NULL++#accessor checked, "get_buffer_size", params_only, out(&uframes_p, "val"), NULL+#accessor checked, "get_buffer_size_min", params_only, out(&uframes_p, "val"), NULL+#accessor checked, "get_buffer_size_max", params_only, out(&uframes_p, "val"), NULL+#accessor errnoresult, "test_buffer_size", pcm_params, in(&uframes_p, "val"), NULL+#accessor checked, "set_buffer_size", pcm_params, in(&uframes_p, "val"), NULL+#accessor checked, "set_buffer_size_min", pcm_params, inout(&uframes_p, "val"), NULL+#accessor checked, "set_buffer_size_max", pcm_params, inout(&uframes_p, "val"), NULL+#accessor checked, "set_buffer_size_minmax", pcm_params, inout(&uframes_p, "vmin"), inout(&uframes_p, "vmax"), NULL+#accessor checked, "set_buffer_size_near", pcm_params, inout(&uframes_p, "val"), NULL+#accessor checked, "set_buffer_size_first", pcm_params, inout(&uframes_p, "val"), NULL+#accessor checked, "set_buffer_size_last", pcm_params, inout(&uframes_p, "val"), NULL++#accessor checked, "get_tick_time", params_only, out(&time_p, "val"), out(&direction_p, "dir"), NULL+#accessor checked, "get_tick_time_min", params_only, out(&time_p, "val"), out(&direction_p, "dir"), NULL+#accessor checked, "get_tick_time_max", params_only, out(&time_p, "val"), out(&direction_p, "dir"), NULL+#accessor errnoresult, "test_tick_time", pcm_params, in(&time_p, "val"), in(&direction_p, "dir"), NULL+#accessor checked, "set_tick_time", pcm_params, in(&time_p, "val"), in(&direction_p, "dir"), NULL+#accessor checked, "set_tick_time_min", pcm_params, inout(&time_p, "val"), inout(&direction_p, "dir"), NULL+#accessor checked, "set_tick_time_max", pcm_params, inout(&time_p, "val"), inout(&direction_p, "dir"), NULL+#accessor checked, "set_tick_time_minmax", pcm_params, inout(&time_p, "vmin"), inout(&direction_p, "mindir"), inout(&time_p, "vmax"), inout(&direction_p, "maxdir"), NULL+#accessor checked, "set_tick_time_near", pcm_params, inout(&time_p, "val"), inout(&direction_p, "dir"), NULL+#accessor checked, "set_tick_time_first", pcm_params, inout(&time_p, "val"), inout(&direction_p, "dir"), NULL+#accessor checked, "set_tick_time_last", pcm_params, inout(&time_p, "val"), inout(&direction_p, "dir"), NULL++#accessor checked, "get_min_align", params_only, out(&uframes_p, "val"), NULL
+ src/Sound/ALSA/PCM/Core/Params.h view
@@ -0,0 +1,247 @@+#include <stdlib.h>+#include <stdarg.h>++typedef char bool;+const bool false = 0, true = 1;++enum context {pcm_params, params_only};++void make_camel_case (char *dst, const char *src) {+  while (*src != 0) {+    if (*src == '_') {+      src ++;+      if (*src == 0) {break;}+      *dst = *src - ('a'-'A'); // assumes that 'a'>'A'+    } else {+      *dst = *src;+    }+    src++;+    dst++;+  }+  *dst = 0;+}++void init_comma (bool *comma) {+  *comma = false;+}++void print_comma (bool *comma) {+  if (*comma) {+    printf(", ");+  }+  *comma = true;+}++struct type {+  char *convert;+  char *hsname;+  char *cname;+};++enum param_direction {dir_in, dir_out, dir_inout};++struct parameter {+  struct type *type;+  char *name;+  enum param_direction dir;+};++struct parameter *in (struct type* t, char *name) {+  struct parameter *p = malloc (sizeof(struct parameter));+  p->type = t;+  p->name = name;+  p->dir = dir_in;+  return p;+}++struct parameter *out (struct type* t, char *name) {+  struct parameter *p = malloc (sizeof(struct parameter));+  p->type = t;+  p->name = name;+  p->dir = dir_out;+  return p;+}++struct parameter *inout (struct type* t, char *name) {+  struct parameter *p = malloc (sizeof(struct parameter));+  p->type = t;+  p->name = name;+  p->dir = dir_inout;+  return p;+}+++struct type bool_p = {"boolConv", "Bool", "Bool_"};++struct type uint_p = {"Conv.int", "Word", "C.CUInt"};++struct type rate_p = {"Conv.int", "SampleFreq", "C.CUInt"};++struct type time_p = {"Conv.int", "Time", "C.CUInt"};++struct type direction_p = {"ordConv", "Ordering", "Direction"};++struct type uframes_p = {"Conv.int", "Size", "C.CUInt"};++struct type access_p = {"Conv.id", "Access", "Access"};++struct type format_p = {"Conv.id", "Format", "Format"};++struct type subformat_p = {"Conv.id", "Subformat", "Subformat"};++enum result {noresult, boolresult, uintresult, errnoresult, checked};+++void hsc_accessor (enum result res, const char *name, enum context ctx, ...) {+  va_list arg;+  struct parameter *p;+  bool comma;+  char *camelName = alloca (strlen (name) + 1);+  make_camel_case (camelName, name);++  printf("foreign import ccall safe \"alsa/pcm.h snd_pcm_hw_params_%s\"\n",+         name);+  printf("   %s_ :: ", camelName);+  if (ctx==pcm_params) {+//    printf("Ptr (Struct i y) -> Ptr Params -> ");+    printf("Handle i y -> Ptr Params -> ");+  } else {+    printf("Ptr Params -> ");+  }++  va_start (arg, ctx);+  while (p = va_arg (arg, struct parameter *)) {+    if (p->dir == dir_in) {+      printf("%s -> ", p->type->cname);+     } else {+      printf("Ptr %s -> ", p->type->cname);+    }+  }+  va_end (arg);++  printf("IO ");+  if (res == noresult) {+    printf("()");+  } else if (res == errnoresult) {+    printf("E.Errno");+  } else {+    printf("C.CInt");+  }+  printf("\n\n");++  printf("%s :: ", camelName);++  va_start (arg, ctx);+  while (p = va_arg (arg, struct parameter *)) {+    if (p->dir != dir_out) {+      printf("%s -> ", p->type->hsname);+    }+  }+  va_end (arg);++  printf("T i y (");+  init_comma(&comma);+  if (res == uintresult) {+    print_comma(&comma);+    printf("Word");+  } else if (res == errnoresult) {+    print_comma(&comma);+    printf("E.Errno");+  } else if (res == boolresult) {+    print_comma(&comma);+    printf("Bool");+  }+  va_start (arg, ctx);+  while (p = va_arg (arg, struct parameter *)) {+    if (p->dir != dir_in) {+      print_comma(&comma);+      printf("%s", p->type->hsname);+    }+  }+  va_end (arg);+  printf(")\n");++  printf("%s", camelName);+  va_start (arg, ctx);+  while (p = va_arg (arg, struct parameter *)) {+    if (p->dir != dir_out) {+      printf(" %s", p->name);+    }+  }+  va_end (arg);+  printf(" =\n");++  if (ctx==pcm_params) {+//    printf("   Cons $ \\(Handle h) p ->\n");+    printf("   Cons $ \\h p ->\n");+  } else {+    printf("   Cons $ \\ _ p ->\n");+  }+  va_start (arg, ctx);+  while (p = va_arg (arg, struct parameter *)) {+    if (p->dir == dir_out) {+      printf("   alloca $ \\%sPtr ->\n", p->name);+    } else if (p->dir == dir_inout) {+      printf("   Conv.with %s %s $ \\%sPtr ->\n",+         p->type->convert, p->name, p->name);+    }+  }+  va_end (arg);++  printf("   %s_", camelName);+  if (ctx==pcm_params) {+    printf(" h p");+  } else {+    printf(" p");+  }+  va_start (arg, ctx);+  while (p = va_arg (arg, struct parameter *)) {+    if (p->dir == dir_in) {+      printf(" (fromHaskell %s %s)",+                p->type->convert, p->name);+    } else {+      printf(" %sPtr", p->name);+    }+  }+  va_end (arg);+  if (res == uintresult) {+    printf(" >>=\n   checkResult \"HwParams.%s\" >>= \\res ->\n", camelName);+  } else if (res == boolresult || res == errnoresult) {+    printf(" >>= \\res ->\n");+  } else if (res == checked) {+    printf(" >>=\n   checkResult_ \"HwParams.%s\" >>\n", camelName);+  } else {+    printf(" >>\n");+  }++  va_start (arg, ctx);+  while (p = va_arg (arg, struct parameter *)) {+    if (p->dir != dir_in) {+      printf("   Conv.peek %s %sPtr >>= \\%sResult ->\n",+         p->type->convert, p->name, p->name);+    }+  }+  va_end (arg);++  printf("   return (");+  init_comma(&comma);+  if (res == uintresult) {+    print_comma(&comma);+    printf("fromIntegral res");+  } else if (res == errnoresult) {+    print_comma(&comma);+    printf("res");+  } else if (res == boolresult) {+    print_comma(&comma);+    printf("res/=0");+  }+  va_start (arg, ctx);+  while (p = va_arg (arg, struct parameter *)) {+    if (p->dir != dir_in) {+      print_comma(&comma);+      printf("%sResult", p->name);+    }+  }+  va_end (arg);+  printf(")\n");+}
+ src/Sound/ALSA/PCM/Core/SwParams.hsc view
@@ -0,0 +1,138 @@+{-# LANGUAGE ForeignFunctionInterface #-}+module Sound.ALSA.PCM.Core.SwParams where++import Sound.ALSA.PCM.Core.Handle (Handle, Size, )+import qualified Sound.ALSA.PCM.Core.Handle as H -- expose Handle constructor to FFI+import qualified Sound.ALSA.PCM.Core.Convert as Conv++import Sound.ALSA.Exception (checkResult_, )++import Control.Applicative (Applicative(pure, (<*>)))++import Control.Exception (bracket, )++import qualified Foreign.Storable.Newtype as Store++import qualified Foreign.C.Types as C+import Foreign.Ptr (Ptr, )+import Foreign.Storable (Storable, sizeOf, alignment, peek, poke, )+import Foreign.Marshal.Alloc (alloca, )++import Data.Word (Word, )+++#include <alsa/asoundlib.h>++newtype T i y a = Cons (H.Handle i y -> Ptr Params -> IO a)++data Params = Params+++{-+T is a Reader monad.+-}+instance Functor (T i y) where+   fmap f (Cons act) = Cons $ \h p -> fmap f $ act h p++instance Applicative (T i y) where+   pure a = Cons $ \ _h _p -> pure a+   Cons f <*> Cons x = Cons $ \h p -> f h p <*> x h p++instance Monad (T i y) where+   return a = Cons $ \ _h _p -> return a+   Cons x >>= k =+      Cons $ \h p -> x h p >>= \a -> case k a of Cons y -> y h p++++withIO :: Handle i y -> (Ptr Params -> IO a) -> IO a+withIO h f =+   bracket malloc free $ \p -> do+      current h p+      x <- f p+      set h p+      return x+--   bracket_ (current h p) (set h p) (f p)+++foreign import ccall safe "alsa/pcm.h snd_pcm_sw_params_malloc"+   malloc_ :: Ptr (Ptr Params) -> IO C.CInt++foreign import ccall safe "alsa/pcm.h snd_pcm_sw_params_free"+   free :: Ptr Params -> IO ()++malloc :: IO (Ptr Params)+malloc =+   alloca $ \pp ->+   malloc_ pp >>=+   checkResult_ "SwParams.malloc" >>+   peek pp++++foreign import ccall safe "alsa/pcm.h snd_pcm_sw_params"+   set_ :: Handle i y -> Ptr Params -> IO C.CInt++foreign import ccall safe "alsa/pcm.h snd_pcm_sw_params_current"+   current_ :: Handle i y -> Ptr Params -> IO C.CInt++set :: Handle i y -> Ptr Params -> IO ()+set h p =+   set_ h p >>= checkResult_ "SwParams.set"++current :: Handle i y -> Ptr Params -> IO ()+current h p =+   current_ h p >>= checkResult_ "SwParams.current"++++newtype TimestampMode = TimestampMode {fromTimestampMode :: C.CInt}+   deriving (Eq, Ord)++instance Enum TimestampMode where+   toEnum n = TimestampMode $ fromIntegral n+   fromEnum (TimestampMode n) = fromIntegral n++instance Storable TimestampMode where+   sizeOf = Store.sizeOf fromTimestampMode+   alignment = Store.alignment fromTimestampMode+   peek = Store.peek TimestampMode+   poke = Store.poke fromTimestampMode++#{enum TimestampMode, TimestampMode,+   timestampNone = SND_PCM_TSTAMP_NONE,+   timestampMmap = SND_PCM_TSTAMP_MMAP}++++#{let accessor hsName, cName, conv, hsType, cType =+"foreign import ccall safe \"alsa/pcm.h snd_pcm_sw_params_set_"cName"\"\n"+"   set"hsName"_ :: Handle i y -> Ptr Params -> "cType" -> IO C.CInt\n"+"\n"+"foreign import ccall safe \"alsa/pcm.h snd_pcm_sw_params_get_"cName"\"\n"+"   get"hsName"_ :: Ptr Params -> Ptr "cType" -> IO C.CInt\n"+"\n"+"set"hsName" :: "hsType" -> T i y ()\n"+"set"hsName" x =\n"+"   Cons $ \\h p ->\n"+"   set"hsName"_ h p (Conv.fromHaskell "conv" x) >>=\n"+"   checkResult_ \"SwParams.set"hsName"\"\n"+"\n"+"get"hsName" :: T i y "hsType"\n"+"get"hsName" =\n"+"   Cons $ \\_ p ->\n"+"   alloca $ \\ptr ->\n"+"   get"hsName"_ p ptr >>=\n"+"   checkResult_ \"SwParams.get"hsName"\" >>\n"+"   Conv.peek "conv" ptr\n"+}+++#accessor "TimestampMode", "tstamp_mode", "Conv.id", "TimestampMode", "TimestampMode"+#accessor "SleepMin", "sleep_min", "Conv.int", "Word", "C.CUInt"+#accessor "AvailMin", "avail_min", "Conv.int", "Size", "C.CULong"+#accessor "XferAlign", "xfer_align", "Conv.int", "Size", "C.CULong"+#accessor "StartThreshold", "start_threshold", "Conv.int", "Size", "C.CULong"+#accessor "StopThreshold", "stop_threshold", "Conv.int", "Size", "C.CULong"+#accessor "SilenceThreshold", "silence_threshold", "Conv.int", "Size", "C.CULong"+#accessor "SilenceSize", "silence_size", "Conv.int", "Size", "C.CULong"
+ src/Sound/ALSA/PCM/Node/ALSA.hs view
@@ -0,0 +1,126 @@+module Sound.ALSA.PCM.Node.ALSA (+   -- * Types+   Handle,+   PCM.Stream(..),+   PCM.Mode, PCM.modes, PCM.nonBlock, PCM.async,+   Interleaved, Noninterleaved,+   Time, SampleFreq, Size,+   -- * Classes+   Class.Access, Class.SampleFmt, Class.MonoSampleFmt,+   -- * Management of streams+   open,+   PCM.close,+   PCM.prepare,+   PCM.start,+   PCM.drop,+   PCM.drain,+   -- * Data transfer+   readi, writei, readiRetry, writeiRetry,+   readn, writen,+   ) where++import Sound.ALSA.PCM.Parameters.Hardware (Time, SampleFreq, Size, )+import Sound.ALSA.PCM.Core.Handle (Handle, Interleaved, Noninterleaved, prepare, )+import qualified Sound.ALSA.PCM.Parameters.Software as SwParam+import qualified Sound.ALSA.PCM.Parameters.Hardware as HwParam+import qualified Sound.ALSA.PCM.Core.Class as Class+import qualified Sound.ALSA.PCM.Core.Handle as PCM+import qualified Sound.ALSA.PCM.Debug as Debug+import qualified Sound.ALSA.Exception as AlsaExc++import Foreign.Marshal.Array (advancePtr, )+import Foreign (Ptr, )+++open ::+   (Class.Access i, Class.SampleFmt y) =>+      PCM.Mode+   -> PCM.Stream+   -> HwParam.T i y a+   -> (a -> SwParam.T i y b)+   -> String -- ^ device, e.g @\"default\"@+   -> IO (b, Handle i y)+open mode stream hwp swp dev = do+   h <- PCM.open dev stream mode+   a <- Class.withHwParams h hwp+   b <- Class.withSwParams h $ swp a+   return (b, h)+++readi ::+   (Class.SampleFmt y) =>+   Handle Interleaved y -> Ptr y -> Size -> IO Size+readi = PCM.readi++writei ::+   (Class.SampleFmt y) =>+   Handle Interleaved y -> Ptr y -> Size -> IO Size+writei = PCM.writei++{- |+The @Ptr (Ptr y)@ argument is actually a pointer to an array of pointers.+The array must have the size of number of channels.+In 'Noninterleaved' mode you must set the number of channels manually+using 'HwParam.setChannels' or its friends.+It is an unchecked error if the number of channels+set with 'HwParam.setChannels'+does not match the array size in the 'readn' call.+-}+readn ::+   (Class.MonoSampleFmt y) =>+   Handle Noninterleaved y -> Ptr (Ptr y) -> Size -> IO Size+readn = PCM.readn++{- |+Cf. 'readn'.+-}+writen ::+   (Class.MonoSampleFmt y) =>+   Handle Noninterleaved y -> Ptr (Ptr y) -> Size -> IO Size+writen = PCM.writen++++{- |+retry on buffer over-run+-}+readiRetry ::+   Class.SampleFmt y =>+   Handle Interleaved y -> Ptr y -> Size -> IO Size+readiRetry h buf0 n =+   let go buf offset = do+          -- debug $ "Reading " ++ show n ++ " samples..."+          nread <-+             readi h buf (n-offset)+             `AlsaExc.catchXRun`+             do Debug.put "snd_pcm_readi reported buffer over-run"+                prepare h+                go buf offset+          let newOffset = offset+nread+          -- debug $ "Got " ++ show n' ++ " samples."+          if newOffset < n+            then go (advancePtr buf (fromIntegral nread)) newOffset+            else return newOffset+   in  go buf0 0++{- |+retry on buffer under-run+-}+writeiRetry ::+   Class.SampleFmt y =>+   Handle Interleaved y -> Ptr y -> Size -> IO Size+writeiRetry h buf0 n =+   let go buf offset = do+          -- debug $ "Writing " ++ show n ++ " samples..."+          nwritten <-+             writei h buf (n-offset)+             `AlsaExc.catchXRun`+             do Debug.put "snd_pcm_writei reported buffer under-run"+                prepare h+                go buf offset+          let newOffset = offset+nwritten+          --debug $ "Wrote " ++ show n' ++ " samples."+          if newOffset < n+            then go (advancePtr buf (fromIntegral nwritten)) newOffset+            else return newOffset+   in  go buf0 0
+ src/Sound/ALSA/PCM/Node/File.hs view
@@ -0,0 +1,60 @@+module Sound.ALSA.PCM.Node.File (+   -- * Types+   Handle,+   Time, SampleFreq, Size,+   -- * Classes+   Class.SampleFmt,+   -- * Management of streams+   open, close,+   -- * Data transfer+   read, write,+   ) where++import qualified Sound.ALSA.PCM.Core.Class as Class+import Sound.ALSA.PCM.Parameters.Hardware (Time, SampleFreq, Size, )+import Sound.ALSA.PCM.Core.Handle (arraySize, )++import Control.Monad (liftM, )+import Foreign.Ptr (Ptr, )+import qualified System.IO as IO+import System.IO (IOMode, openBinaryFile, )++import Prelude hiding (read, )+++newtype Handle y = Handle IO.Handle+++open ::+   (Class.SampleFmt y) =>+   IOMode -> FilePath -> IO (Handle y)+open mode path =+   fmap Handle $ openBinaryFile path mode++close ::+   (Class.SampleFmt y) =>+   Handle y -> IO ()+close (Handle h) =+   IO.hClose h++{- |+This expects pad bytes that are needed in memory+in order to satisfy aligment constraints.+This is only a problem for samples sizes like 24 bit.+-}+read ::+   (Class.SampleFmt y) =>+   Handle y -> Ptr y -> Size -> IO Size+read (Handle h) buf n =+   liftM fromIntegral $+   liftM (`div` arraySize buf 1) $+   IO.hGetBuf h buf (arraySize buf (fromIntegral n))++{- |+Same restrictions as for 'fileRead'.+-}+write ::+   (Class.SampleFmt y) =>+   Handle y -> Ptr y -> Size -> IO ()+write (Handle h) buf n =+   IO.hPutBuf h buf (arraySize buf (fromIntegral n))
+ src/Sound/ALSA/PCM/Parameters/Hardware.hs view
@@ -0,0 +1,262 @@+module Sound.ALSA.PCM.Parameters.Hardware (+   -- * Types+   T, SampleFreq, Time, Size,+   Interleaved, Noninterleaved,++{-+   HwParams.Access,+   HwParams.accessMmapInterleaved,+   HwParams.accessMmapNoninterleaved,+   HwParams.accessMmapComplex,+   HwParams.accessRwInterleaved,+   HwParams.accessRwNoninterleaved,++   HwParams.Format,+   HwParams.formatUnknown,+   HwParams.formatS8,+   HwParams.formatU8,+   HwParams.formatS16Le,+   HwParams.formatS16Be,+   HwParams.formatU16Le,+   HwParams.formatU16Be,+   HwParams.formatS24Le,+   HwParams.formatS24Be,+   HwParams.formatU24Le,+   HwParams.formatU24Be,+   HwParams.formatS32Le,+   HwParams.formatS32Be,+   HwParams.formatU32Le,+   HwParams.formatU32Be,+   HwParams.formatFloatLe,+   HwParams.formatFloatBe,+   HwParams.formatFloat64Le,+   HwParams.formatFloat64Be,+   HwParams.formatIec958SubframeLe,+   HwParams.formatIec958SubframeBe,+   HwParams.formatMuLaw,+   HwParams.formatALaw,+   HwParams.formatImaAdpcm,+   HwParams.formatMpeg,+   HwParams.formatGsm,+   HwParams.formatSpecial,+   HwParams.formatS243le,+   HwParams.formatS243be,+   HwParams.formatU243le,+   HwParams.formatU243be,+   HwParams.formatS203le,+   HwParams.formatS203be,+   HwParams.formatU203le,+   HwParams.formatU203be,+   HwParams.formatS183le,+   HwParams.formatS183be,+   HwParams.formatU183le,+   HwParams.formatU183be,+   HwParams.formatS16,+   HwParams.formatU16,+   HwParams.formatS24,+   HwParams.formatU24,+   HwParams.formatS32,+   HwParams.formatU32,+   HwParams.formatFloat,+   HwParams.formatFloat64,+   HwParams.formatIec958Subframe,++   HwParams.Subformat,+-}++   -- * Primitive accessors to hardware parameters+   HwParams.canMmapSampleResolution,+   HwParams.isDouble,+   HwParams.isBatch,+   HwParams.isBlockTransfer,+   HwParams.canOverrange,+   HwParams.canPause,+   HwParams.canResume,+   HwParams.isHalfDuplex,+   HwParams.isJointDuplex,+   HwParams.canSyncStart,+   HwParams.getRateNumden,+   HwParams.getSbits,+   HwParams.getFifoSize,+{- integrated in 'with'+   HwParams.getAccess,+   HwParams.testAccess,+   HwParams.setAccess,+   HwParams.setAccessFirst,+   HwParams.setAccessLast,+   HwParams.getFormat,+   HwParams.testFormat,+   HwParams.setFormat,+   HwParams.setFormatFirst,+   HwParams.setFormatLast,+-}+{- don't know how to use this reasonably+   HwParams.getSubformat,+   HwParams.testSubformat,+   HwParams.setSubformat,+   HwParams.setSubformatFirst,+   HwParams.setSubformatLast,+-}+   HwParams.getChannels,+   HwParams.getChannelsMin,+   HwParams.getChannelsMax,+   HwParams.testChannels,+   setChannels,+   setChannelsMin,+   setChannelsMax,+   setChannelsMinmax,+   setChannelsNear,+   setChannelsFirst,+   setChannelsLast,+   HwParams.getRate,+   HwParams.getRateMin,+   HwParams.getRateMax,+   HwParams.testRate,+   HwParams.setRate,+   HwParams.setRateMin,+   HwParams.setRateMax,+   HwParams.setRateMinmax,+   HwParams.setRateNear,+   HwParams.setRateFirst,+   HwParams.setRateLast,+   HwParams.setRateResample,+   HwParams.getRateResample,+   HwParams.setExportBuffer,+   HwParams.getExportBuffer,+   HwParams.getPeriodTime,+   HwParams.getPeriodTimeMin,+   HwParams.getPeriodTimeMax,+   HwParams.testPeriodTime,+   HwParams.setPeriodTime,+   HwParams.setPeriodTimeMin,+   HwParams.setPeriodTimeMax,+   HwParams.setPeriodTimeMinmax,+   HwParams.setPeriodTimeNear,+   HwParams.setPeriodTimeFirst,+   HwParams.setPeriodTimeLast,+   HwParams.getPeriodSize,+   HwParams.getPeriodSizeMin,+   HwParams.getPeriodSizeMax,+   HwParams.testPeriodSize,+   HwParams.setPeriodSize,+   HwParams.setPeriodSizeMin,+   HwParams.setPeriodSizeMax,+   HwParams.setPeriodSizeMinmax,+   HwParams.setPeriodSizeNear,+   HwParams.setPeriodSizeFirst,+   HwParams.setPeriodSizeLast,+   HwParams.setPeriodSizeInteger,+   HwParams.getPeriods,+   HwParams.getPeriodsMin,+   HwParams.getPeriodsMax,+   HwParams.testPeriods,+   HwParams.setPeriods,+   HwParams.setPeriodsMin,+   HwParams.setPeriodsMax,+   HwParams.setPeriodsMinmax,+   HwParams.setPeriodsNear,+   HwParams.setPeriodsFirst,+   HwParams.setPeriodsLast,+   HwParams.setPeriodsInteger,+   HwParams.getBufferTime,+   HwParams.getBufferTimeMin,+   HwParams.getBufferTimeMax,+   HwParams.testBufferTime,+   HwParams.setBufferTime,+   HwParams.setBufferTimeMin,+   HwParams.setBufferTimeMax,+   HwParams.setBufferTimeMinmax,+   HwParams.setBufferTimeNear,+   HwParams.setBufferTimeFirst,+   HwParams.setBufferTimeLast,+   HwParams.getBufferSize,+   HwParams.getBufferSizeMin,+   HwParams.getBufferSizeMax,+   HwParams.testBufferSize,+   HwParams.setBufferSize,+   HwParams.setBufferSizeMin,+   HwParams.setBufferSizeMax,+   HwParams.setBufferSizeMinmax,+   HwParams.setBufferSizeNear,+   HwParams.setBufferSizeFirst,+   HwParams.setBufferSizeLast,+   HwParams.getTickTime,+   HwParams.getTickTimeMin,+   HwParams.getTickTimeMax,+   HwParams.testTickTime,+   HwParams.setTickTime,+   HwParams.setTickTimeMin,+   HwParams.setTickTimeMax,+   HwParams.setTickTimeMinmax,+   HwParams.setTickTimeNear,+   HwParams.setTickTimeFirst,+   HwParams.setTickTimeLast,+   HwParams.getMinAlign,++   -- * Complex hardware parameter configuration+   setRateBufferTime,+   ) where++import qualified Sound.ALSA.PCM.Core.HwParams as HwParams+import Sound.ALSA.PCM.Core.HwParams (T, )+import Sound.ALSA.PCM.Core.Handle+          (SampleFreq, Time, Size, Interleaved, Noninterleaved, )++import Data.Word (Word, )+++{-+Our approach cannot assert, that setChannels is called.+Is this necessary, at all?+If yes, setChannel accessors could return a secret value,+that must be passed to 'writen' in order to prove,+that setChannel was called.+-}++{- |+For non-interleaved access the number of channels must be set manually.+It can be chosen at runtime,+but the compiler cannot check whether the number of allocated channels+matches the one in 'readn' and 'writen'.++In interleaved access the number of channels is derived from the type+and must not be set manually.+The number is static+but the compiler checks consistency with 'readi' and 'writei'.+-}+setChannels :: Word -> T Noninterleaved y ()+setChannels = HwParams.setChannels++setChannelsMin :: Word -> T Noninterleaved y Word+setChannelsMin = HwParams.setChannelsMin++setChannelsMax :: Word -> T Noninterleaved y Word+setChannelsMax = HwParams.setChannelsMax++setChannelsMinmax :: Word -> Word -> T Noninterleaved y (Word, Word)+setChannelsMinmax = HwParams.setChannelsMinmax++setChannelsNear :: Word -> T Noninterleaved y Word+setChannelsNear = HwParams.setChannelsNear++setChannelsFirst :: Word -> T Noninterleaved y Word+setChannelsFirst = HwParams.setChannelsFirst++setChannelsLast :: Word -> T Noninterleaved y Word+setChannelsLast = HwParams.setChannelsLast++++setRateBufferTime ::+      SampleFreq -- ^ sample frequency+   -> Time -- ^ buffer time+   -> Time -- ^ period time+   -> T Interleaved y (Size,Size)+      -- ^ (bufferSize,periodSize)+setRateBufferTime rate bufferTime periodTime = do+   HwParams.setRate rate EQ+   _ <- HwParams.setBufferTimeNear bufferTime EQ+   bufferSize <- HwParams.getBufferSize+   _ <- HwParams.setPeriodTimeNear periodTime EQ+   (periodSize,_) <- HwParams.getPeriodSize+   return (bufferSize,periodSize)
+ src/Sound/ALSA/PCM/Parameters/Software.hs view
@@ -0,0 +1,37 @@+module Sound.ALSA.PCM.Parameters.Software (+   -- * Types+   SwParams.T, Size,+   TimestampMode, timestampNone, timestampMmap,++   -- * Primitive accessors to software parameters+   getAvailMin,         setAvailMin,+   getSilenceSize,      setSilenceSize,+   getSilenceThreshold, setSilenceThreshold,+   getSleepMin,         setSleepMin,+   getStartThreshold,   setStartThreshold,+   getStopThreshold,    setStopThreshold,+   getTimestampMode,    setTimestampMode,+   getXferAlign,        setXferAlign,++   -- * Complex software parameter configuration+   setBufferSize,+   ) where++import Sound.ALSA.PCM.Core.SwParams as SwParams+import Sound.ALSA.PCM.Core.Handle (Size, )+++setBufferSize ::+      Size -- ^ buffer size+   -> Size -- ^ period size+   -> SwParams.T i y ()+setBufferSize _bufferSize periodSize = do+   -- let startThreshold =+   --        (setBufferSize `div` periodSize) * periodSize+   -- setStartThreshold startThreshold+   setStartThreshold 0+   setAvailMin $ fromIntegral periodSize+   setXferAlign 1+   -- pad buffer with silence when needed+   -- setSilenceSize periodSize+   -- setSilenceThreshold periodSize