alsa 0.2 → 0.4
raw patch · 7 files changed
Files
- LICENSE +1/−0
- Sound/Alsa.hs +234/−118
- Sound/Alsa/Error.hs +18/−7
- Sound/Alsa/Sequencer/Client.hs +1/−1
- Sound/Alsa/Sequencer/Errors.hs +12/−8
- Sound/Alsa/Sequencer/Event.hs +1/−1
- alsa.cabal +10/−7
LICENSE view
@@ -1,3 +1,4 @@+Copyright (c) 2009 Henning Thielemann Copyright (c) 2006 Bjorn Bringert Copyright (c) 2006 Iavor S. Diatchki
Sound/Alsa.hs view
@@ -1,9 +1,11 @@ module Sound.Alsa (SampleFmt(..), SampleFreq,+ Time, SoundFmt(..), SoundSource(..), SoundSink(..),+ SoundBufferTime(..), withSoundSource, withSoundSourceRunning, withSoundSink,@@ -13,60 +15,74 @@ audioBytesPerFrame, soundSourceBytesPerFrame, soundSinkBytesPerFrame,- soundSourceReadBytes,- soundSinkWriteBytes, copySound, alsaSoundSource, alsaSoundSink,+ alsaSoundSourceTime,+ alsaSoundSinkTime, fileSoundSource,- fileSoundSink+ fileSoundSink, ) where import Sound.Alsa.Core-import Sound.Alsa.Error+import Sound.Alsa.Error (rethrowAlsaExceptions, catchXRun, ) -import Control.Concurrent-import Control.Exception (bracket, bracket_)-import Control.Monad (liftM,when)-import Foreign-import Foreign.C+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.Concurrent (myThreadId, )+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 qualified System.IO as IO import System.IO+ (IOMode(ReadMode, WriteMode), Handle, openBinaryFile, hClose, ) -- -- * Generic sound API -- -data SampleFmt = SampleFmtLinear16BitSignedLE- | SampleFmtMuLaw8Bit- deriving (Show)+class (Storable y, Frame.C y) => SampleFmt y where+ sampleFmtToPcmFormat :: y -> PcmFormat type SampleFreq = Int -data SoundFmt = SoundFmt {- sampleFmt :: SampleFmt,- sampleFreq :: SampleFreq,- numChannels :: 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 handle =+data SoundSource y handle = SoundSource {- soundSourceFmt :: SoundFmt,+ soundSourceFmt :: SoundFmt y, soundSourceOpen :: IO handle, soundSourceClose :: handle -> IO (), soundSourceStart :: handle -> IO (), soundSourceStop :: handle -> IO (),- soundSourceRead :: handle -> Ptr () -> Int -> IO Int+ soundSourceRead :: handle -> Ptr y -> Int -> IO Int } -data SoundSink handle =+data SoundSink y handle = SoundSink {- soundSinkFmt :: SoundFmt,+ soundSinkFmt :: SoundFmt y, soundSinkOpen :: IO handle, soundSinkClose :: handle -> IO (),- soundSinkWrite :: handle -> Ptr () -> Int -> IO (),+ soundSinkWrite :: handle -> Ptr y -> Int -> IO (), soundSinkStart :: handle -> IO (), soundSinkStop :: handle -> IO () }@@ -75,7 +91,14 @@ -- -- -nullSoundSource :: SoundFmt -> SoundSource h+defaultBufferTime :: SoundBufferTime+defaultBufferTime =+ SoundBufferTime {+ bufferTime = 500000, -- 0.5s+ periodTime = 100000 -- 0.1s+ }++nullSoundSource :: SoundFmt y -> SoundSource y h nullSoundSource fmt = SoundSource { soundSourceFmt = fmt,@@ -86,7 +109,7 @@ soundSourceRead = \_ _ _ -> return 0 } -nullSoundSink :: SoundFmt -> SoundSink h+nullSoundSink :: SoundFmt y -> SoundSink y h nullSoundSink fmt = SoundSink { soundSinkFmt = fmt,@@ -98,65 +121,101 @@ } -withSoundSource :: SoundSource h -> (h -> IO a) -> IO a+withSoundSource :: SoundSource y h -> (h -> IO a) -> IO a withSoundSource source = bracket (soundSourceOpen source) (soundSourceClose source) -withSoundSourceRunning :: SoundSource h -> h -> IO a -> IO a+withSoundSourceRunning :: SoundSource y h -> h -> IO a -> IO a withSoundSourceRunning src h = bracket_ (soundSourceStart src h) (soundSourceStop src h) -withSoundSink :: SoundSink h -> (h -> IO a) -> IO a+withSoundSink :: SoundSink y h -> (h -> IO a) -> IO a withSoundSink sink = bracket (soundSinkOpen sink) (soundSinkClose sink) -withSoundSinkRunning :: SoundSink h -> h -> IO a -> IO a+withSoundSinkRunning :: SoundSink y h -> h -> IO a -> IO a withSoundSinkRunning src h = bracket_ (soundSinkStart src h) (soundSinkStop src h) -soundFmtMIME :: SoundFmt -> String++instance SampleFmt Word8 where+ sampleFmtToPcmFormat _ = PcmFormatU8++instance SampleFmt Int8 where+ sampleFmtToPcmFormat _ = PcmFormatS8++instance SampleFmt Word16 where+ sampleFmtToPcmFormat _ = PcmFormatU16++instance SampleFmt Int16 where+ sampleFmtToPcmFormat _ = PcmFormatS16++instance SampleFmt Word32 where+ sampleFmtToPcmFormat _ = PcmFormatU32++instance SampleFmt Int32 where+ sampleFmtToPcmFormat _ = PcmFormatS32++instance SampleFmt Float where+ sampleFmtToPcmFormat _ = PcmFormatFloat++instance SampleFmt Double where+ sampleFmtToPcmFormat _ = PcmFormatFloat64++instance SampleFmt MuLaw.T where+ sampleFmtToPcmFormat _ = PcmFormatMuLaw++instance SampleFmt a => SampleFmt (Stereo.T a) where+ sampleFmtToPcmFormat y =+ sampleFmtToPcmFormat (Stereo.left y)++withSampleFmt :: (y -> a) -> (SoundFmt y -> a)+withSampleFmt f _ = f undefined+++soundFmtMIME :: SampleFmt y => SoundFmt y -> String soundFmtMIME fmt = t ++ r ++ c- where t = case sampleFmt fmt of+ where t = "audio/basic"+{-+ t = case sampleFmt fmt of SampleFmtLinear16BitSignedLE -> "audio/L16" SampleFmtMuLaw8Bit -> "audio/basic"+-} r = ";rate=" ++ show (sampleFreq fmt) c | numChannels fmt == 1 = "" | otherwise = ";channels=" ++ show (numChannels fmt) -audioBytesPerSample :: SoundFmt -> Int-audioBytesPerSample fmt =- case sampleFmt fmt of- SampleFmtLinear16BitSignedLE -> 2- SampleFmtMuLaw8Bit -> 1+numChannels :: SampleFmt y => SoundFmt y -> Int+numChannels = withSampleFmt Frame.numberOfChannels --- assumes interleaved data-audioBytesPerFrame :: SoundFmt -> Int+audioBytesPerSample :: SampleFmt y => SoundFmt y -> Int+audioBytesPerSample = withSampleFmt Frame.sizeOfElement++{-+assumes interleaved data++Due to alignment constraints+a frame might occupy more than the calculated size+in an array in memory.+-}+audioBytesPerFrame :: SampleFmt y => SoundFmt y -> Int audioBytesPerFrame fmt = numChannels fmt * audioBytesPerSample fmt -soundSourceBytesPerFrame :: SoundSource h -> Int+soundSourceBytesPerFrame :: SampleFmt y => SoundSource y h -> Int soundSourceBytesPerFrame = audioBytesPerFrame . soundSourceFmt -soundSinkBytesPerFrame :: SoundSink h -> Int+soundSinkBytesPerFrame :: SampleFmt y => SoundSink y h -> Int soundSinkBytesPerFrame = audioBytesPerFrame . soundSinkFmt -soundSourceReadBytes :: SoundSource h -> h -> Ptr () -> Int -> IO Int-soundSourceReadBytes src h buf n =- liftM (* c) $ soundSourceRead src h buf (n `div` c)- where c = soundSourceBytesPerFrame src--soundSinkWriteBytes :: SoundSink h -> h -> Ptr () -> Int -> IO ()-soundSinkWriteBytes src h buf n =- soundSinkWrite src h buf (n `div` c)- where c = soundSinkBytesPerFrame src--copySound :: SoundSource h1- -> SoundSink h2- -> Int -- ^ Buffer size (in bytes) to use+copySound :: SampleFmt y =>+ SoundSource y h1+ -> SoundSink y h2+ -> Int -- ^ Buffer size (in sample frames) to use -> IO () copySound source sink bufSize =- allocaBytes bufSize $ \buf ->+ allocaArray bufSize $ \buf -> withSoundSource source $ \from -> withSoundSink sink $ \to ->- let loop = do n <- soundSourceReadBytes source from buf bufSize- when (n > 0) $ do soundSinkWriteBytes sink to buf n+ let loop = do n <- soundSourceRead source from buf bufSize+ when (n > 0) $ do soundSinkWrite sink to buf n loop in loop @@ -165,23 +224,26 @@ -- +debug :: String -> IO () debug s = do t <- myThreadId- hPutStrLn stderr $ show t ++ ": " ++ s+ IO.hPutStrLn IO.stderr $ show t ++ ": " ++ s -alsaOpen :: String -- ^ device, e.g @"default"@- -> SoundFmt -> PcmStream -> IO Pcm-alsaOpen dev fmt stream = rethrowAlsaExceptions $+alsaOpen :: SampleFmt y =>+ String -- ^ device, e.g @"default"@+ -> SoundFmt y+ -> SoundBufferTime+ -> PcmStream+ -> IO Pcm+alsaOpen dev fmt time stream = rethrowAlsaExceptions $ do debug "alsaOpen" h <- pcm_open dev stream 0- let buffer_time = 500000 -- 0.5s- period_time = 100000 -- 0.1s (buffer_time,buffer_size,period_time,period_size) <-- setHwParams h (sampleFmtToPcmFormat (sampleFmt fmt))+ setHwParams h (withSampleFmt sampleFmtToPcmFormat fmt) (numChannels fmt) (sampleFreq fmt)- buffer_time- period_time+ (bufferTime time)+ (periodTime time) setSwParams h buffer_size period_size pcm_prepare h debug $ "buffer_time = " ++ show buffer_time@@ -189,21 +251,18 @@ debug $ "period_time = " ++ show period_time debug $ "period_size = " ++ show period_size when (stream == PcmStreamPlayback) $- callocaBytes (audioBytesPerFrame fmt * period_size) $ \buf ->+ callocaArray fmt period_size $ \buf -> do pcm_writei h buf period_size return () return h -sampleFmtToPcmFormat :: SampleFmt -> PcmFormat-sampleFmtToPcmFormat SampleFmtLinear16BitSignedLE = PcmFormatS16Le-sampleFmtToPcmFormat SampleFmtMuLaw8Bit = PcmFormatMuLaw setHwParams :: Pcm -> PcmFormat -> Int -- ^ number of channels- -> Int -- ^ sample frequency- -> Int -- ^ buffer time- -> Int -- ^ period time+ -> 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@@ -212,21 +271,22 @@ 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- (buffer_time,_) <-+ (actual_buffer_time,_) <- pcm_hw_params_set_buffer_time_near h p buffer_time EQ buffer_size <- pcm_hw_params_get_buffer_size p- (period_time,_) <-+ (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 (buffer_time,buffer_size,period_time,period_size)+ 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+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@@ -272,96 +332,152 @@ do debug "alsaStop" pcm_drain pcm -alsaRead :: SoundFmt -> Pcm -> Ptr () -> Int -> IO Int-alsaRead fmt h buf n = rethrowAlsaExceptions $+alsaRead ::+ SampleFmt y =>+ Pcm -> Ptr y -> Int -> IO Int+alsaRead h buf n = rethrowAlsaExceptions $ do --debug $ "Reading " ++ show n ++ " samples..." n' <- pcm_readi h buf n `catchXRun` handleOverRun --debug $ "Got " ++ show n' ++ " samples." if n' < n- then do n'' <- alsaRead fmt h (buf `plusPtr` (n' * c)) (n - n')+ then do n'' <- alsaRead h (advancePtr buf n') (n - n') return (n' + n'') else return n'- where c = audioBytesPerFrame fmt- handleOverRun = do debug "snd_pcm_readi reported buffer over-run"+ where handleOverRun = do debug "snd_pcm_readi reported buffer over-run" pcm_prepare h- alsaRead fmt h buf n+ alsaRead h buf n -alsaWrite :: SoundFmt -> Pcm -> Ptr () -> Int -> IO ()-alsaWrite fmt h buf n = rethrowAlsaExceptions $- do alsaWrite_ fmt h buf n+alsaWrite ::+ SampleFmt y =>+ Pcm -> Ptr y -> Int -> IO ()+alsaWrite h buf n = rethrowAlsaExceptions $+ do alsaWrite_ h buf n return () -alsaWrite_ :: SoundFmt -> Pcm -> Ptr () -> Int -> IO Int-alsaWrite_ fmt h buf n =+alsaWrite_ ::+ SampleFmt y =>+ Pcm -> Ptr y -> Int -> IO Int+alsaWrite_ h buf n = do --debug $ "Writing " ++ show n ++ " samples..." n' <- pcm_writei h buf n `catchXRun` handleUnderRun --debug $ "Wrote " ++ show n' ++ " samples." if (n' /= n)- then do n'' <- alsaWrite_ fmt h (buf `plusPtr` (n' * c)) (n - n')+ then do n'' <- alsaWrite_ h (advancePtr buf n') (n - n') return (n' + n'') else return n'- where c = audioBytesPerFrame fmt- handleUnderRun = do debug "snd_pcm_writei reported buffer under-run"+ where handleUnderRun = do debug "snd_pcm_writei reported buffer under-run" pcm_prepare h- alsaWrite_ fmt h buf n+ alsaWrite_ h buf n -alsaSoundSource :: String -> SoundFmt -> SoundSource Pcm+alsaSoundSource ::+ SampleFmt y =>+ String -> SoundFmt y -> SoundSource y Pcm alsaSoundSource dev fmt = (nullSoundSource fmt) {- soundSourceOpen = alsaOpen dev fmt PcmStreamCapture,- soundSourceClose = alsaClose,- soundSourceStart = alsaStart,- soundSourceStop = alsaStop,- soundSourceRead = alsaRead fmt- }+ soundSourceOpen = alsaOpen dev fmt defaultBufferTime PcmStreamCapture,+ soundSourceClose = alsaClose,+ soundSourceStart = alsaStart,+ soundSourceStop = alsaStop,+ soundSourceRead = alsaRead+ } -alsaSoundSink :: String -> SoundFmt -> SoundSink Pcm+alsaSoundSink ::+ SampleFmt y =>+ String -> SoundFmt y -> SoundSink y Pcm alsaSoundSink dev fmt = (nullSoundSink fmt) {- soundSinkOpen = alsaOpen dev fmt PcmStreamPlayback,- soundSinkClose = alsaClose,- soundSinkStart = alsaStart,- soundSinkStop = alsaStop,- soundSinkWrite = alsaWrite fmt- }+ soundSinkOpen = alsaOpen dev fmt defaultBufferTime PcmStreamPlayback,+ soundSinkClose = alsaClose,+ soundSinkStart = alsaStart,+ soundSinkStop = alsaStop,+ soundSinkWrite = alsaWrite+ } +alsaSoundSourceTime ::+ SampleFmt y =>+ String -> SoundFmt y -> SoundBufferTime -> SoundSource y Pcm+alsaSoundSourceTime dev fmt time =+ (nullSoundSource fmt) {+ soundSourceOpen = alsaOpen dev fmt time PcmStreamCapture,+ soundSourceClose = alsaClose,+ soundSourceStart = alsaStart,+ soundSourceStop = alsaStop,+ soundSourceRead = alsaRead+ }++alsaSoundSinkTime ::+ SampleFmt y =>+ String -> SoundFmt y -> SoundBufferTime -> SoundSink y Pcm+alsaSoundSinkTime dev fmt time =+ (nullSoundSink fmt) {+ soundSinkOpen = alsaOpen dev fmt time PcmStreamPlayback,+ soundSinkClose = alsaClose,+ soundSinkStart = alsaStart,+ soundSinkStop = alsaStop,+ soundSinkWrite = alsaWrite+ }+ -- -- * File stuff -- -fileRead :: SoundFmt -> Handle -> Ptr () -> Int -> IO Int-fileRead fmt h buf n = liftM (`div` c) $ hGetBuf h buf (n * c)- where c = audioBytesPerSample fmt+{- |+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) -fileWrite :: SoundFmt -> Handle -> Ptr () -> Int -> IO ()-fileWrite fmt h buf n = hPutBuf h buf (n * c)- where c = audioBytesPerSample fmt+{- |+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 :: FilePath -> SoundFmt -> SoundSource Handle+fileSoundSource ::+ SampleFmt y =>+ FilePath -> SoundFmt y -> SoundSource y Handle fileSoundSource file fmt = (nullSoundSource fmt) { soundSourceOpen = openBinaryFile file ReadMode, soundSourceClose = hClose,- soundSourceRead = fileRead fmt+ soundSourceRead = fileRead } -fileSoundSink :: FilePath -> SoundFmt -> SoundSink Handle+fileSoundSink ::+ SampleFmt y =>+ FilePath -> SoundFmt y -> SoundSink y Handle fileSoundSink file fmt = (nullSoundSink fmt) { soundSinkOpen = openBinaryFile file WriteMode, soundSinkClose = hClose,- soundSinkWrite = fileWrite fmt+ soundSinkWrite = fileWrite } -- -- * Marshalling utilities -- -callocaBytes :: Int -> (Ptr a -> IO b) -> IO b-callocaBytes n f = allocaBytes n (\p -> clearBytes p n >> f p)+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 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)
Sound/Alsa/Error.hs view
@@ -3,10 +3,11 @@ #-} module Sound.Alsa.Error where -import Control.Exception (catchDyn,throwDyn)-import Data.Typeable-import Foreign.C.Error-import Foreign.C.String+import Control.Exception.Extensible (Exception, throw, catch, )+import Data.Typeable (Typeable, )+import Foreign.C.Error (Errno(Errno), ePIPE, errnoToIOError, )+import Foreign.C.String (CString, peekCString, )+import Prelude hiding (catch, ) data AlsaException = AlsaException { exception_location :: String@@ -14,6 +15,16 @@ , exception_code :: Errno } deriving (Typeable) +instance Show AlsaException where+ showsPrec p (AlsaException l d (Errno c)) =+ showParen (p>10)+ (showString "AlsaException " .+ shows l . showString " " .+ shows d . showString " " .+ showParen True (showString "Errno " . shows c))++instance Exception AlsaException where+ checkResult :: Integral a => String -> a -> IO a checkResult f r | r < 0 = throwAlsa f (Errno (negate (fromIntegral r)))@@ -24,21 +35,21 @@ throwAlsa :: String -> Errno -> IO a throwAlsa fun err = do d <- strerror err- throwDyn AlsaException+ throw AlsaException { exception_location = fun , exception_description = d , exception_code = err } catchAlsa :: IO a -> (AlsaException -> IO a) -> IO a-catchAlsa = catchDyn+catchAlsa = catch catchAlsaErrno :: Errno -> IO a -- ^ Action -> IO a -- ^ Handler -> IO a catchAlsaErrno e x h =- catchAlsa x (\ex -> if exception_code ex == e then h else throwDyn ex)+ catchAlsa x (\ex -> if exception_code ex == e then h else throw ex) catchXRun :: IO a -- ^ Action -> IO a -- ^ Handler
Sound/Alsa/Sequencer/Client.hs view
@@ -108,7 +108,7 @@ query_first_client h = do x <- client_info_malloc with_client_info x (`snd_seq_client_info_set_client` (-1))- b <- query_next_client h x+ _b <- query_next_client h x -- XXX: check that we did get the first client (should be System) return x
Sound/Alsa/Sequencer/Errors.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE ForeignFunctionInterface #-} -------------------------------------------------------------------------------- -- | -- Module : Sound.Alsa.Sequencer.Errors@@ -12,16 +13,18 @@ module Sound.Alsa.Sequencer.Errors where -import Foreign.C.Types(CInt)-import Foreign.C.String(CString,peekCString)-import Control.Exception(throwDyn,catchDyn)-import Data.Word-import Data.Typeable+import Foreign.C.Types (CInt, )+import Foreign.C.String (CString, peekCString, )+import Control.Exception.Extensible (Exception, throw, catch, )+import Data.Word (Word, )+import Data.Typeable (Typeable(typeOf), mkTyCon, mkTyConApp, )+import Prelude hiding (catch, ) + data AlsaException = AlsaException { exception_code :: !Word -- ^ the (positive) error code , exception_description :: !String -- ^ a text description of the problem- }+ } deriving Show instance Eq AlsaException where x == y = exception_code x == exception_code y@@ -32,6 +35,7 @@ instance Typeable AlsaException where typeOf _ = mkTyConApp (mkTyCon "Sound.Alsa.Sequencer.AlsaException") [] +instance Exception AlsaException where -- | Returns the message for an error code.@@ -43,7 +47,7 @@ -- | Catch an exception generated by the binding. alsa_catch :: IO a -> (AlsaException -> IO a) -> IO a-alsa_catch = catchDyn+alsa_catch = catch check_error :: CInt -> IO Word check_error = check_error' fromIntegral (const Nothing)@@ -54,7 +58,7 @@ | otherwise = case err x of Just a -> return a _ -> do msg <- strerror x- throwDyn AlsaException+ throw AlsaException { exception_code = fromIntegral (negate x) , exception_description = msg }
Sound/Alsa/Sequencer/Event.hs view
@@ -99,7 +99,7 @@ event_output (SndSeq h) e = alloca_ev e $ \p -> check_error =<< snd_seq_event_output h p -foreign import ccall "alsa/asoundlib.h snd_seq_event_output "+foreign import ccall "alsa/asoundlib.h snd_seq_event_output" snd_seq_event_output :: Ptr SndSeq_ -> Ptr Event -> IO CInt
alsa.cabal view
@@ -1,14 +1,17 @@ Name: alsa-Version: 0.2-Copyright: Bjorn Bringert, Iavor S. Diatchki-Maintainer: bjorn@bringert.net, iavor.diatchki@gmail.com-Author: Bjorn Bringert, Iavor S. Diatchki+Version: 0.4+Copyright: Bjorn Bringert, Iavor S. Diatchki, Henning Thielemann+Maintainer: Henning Thielemann <alsa@henning-thielemann.de>+Author: Bjorn Bringert <bjorn@bringert.net>, Iavor S. Diatchki <iavor.diatchki@gmail.com> Category: Sound, Music License: BSD3-License-file: LICENSE+License-file: LICENSE+Homepage: http://www.haskell.org/haskellwiki/ALSA Build-depends:- base >= 3,- array >= 0.1 && <0.3+ sample-frame >=0.0.1 && <0.1,+ array >= 0.1 && <0.4,+ extensible-exceptions >=0.1.1 && <0.2,+ base >= 3 && <6 Stability: Experimental Extensions: ForeignFunctionInterface, GeneralizedNewtypeDeriving, EmptyDataDecls Build-Type: Simple