{-# LINE 1 "src/Sound/ALSA/PCM/Core/Handle.hsc" #-}
{-# 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 Data.Semigroup (Semigroup, (<>), )

import Prelude hiding (any, )





data Struct i y = Struct

newtype Handle i y = Handle {forall i y. Handle i y -> Ptr (Struct i y)
dePcm :: Ptr (Struct i y)}

data Interleaved = Interleaved
data Noninterleaved = Noninterleaved


instance Storable (Handle i y) where
   sizeOf :: Handle i y -> Int
sizeOf = (Handle i y -> Ptr (Struct i y)) -> Handle i y -> Int
forall core wrapper.
Storable core =>
(wrapper -> core) -> wrapper -> Int
Store.sizeOf Handle i y -> Ptr (Struct i y)
forall i y. Handle i y -> Ptr (Struct i y)
dePcm
   alignment :: Handle i y -> Int
alignment = (Handle i y -> Ptr (Struct i y)) -> Handle i y -> Int
forall core wrapper.
Storable core =>
(wrapper -> core) -> wrapper -> Int
Store.alignment Handle i y -> Ptr (Struct i y)
forall i y. Handle i y -> Ptr (Struct i y)
dePcm
   peek :: Ptr (Handle i y) -> IO (Handle i y)
peek = (Ptr (Struct i y) -> Handle i y)
-> Ptr (Handle i y) -> IO (Handle i y)
forall core wrapper.
Storable core =>
(core -> wrapper) -> Ptr wrapper -> IO wrapper
Store.peek Ptr (Struct i y) -> Handle i y
forall i y. Ptr (Struct i y) -> Handle i y
Handle
   poke :: Ptr (Handle i y) -> Handle i y -> IO ()
poke = (Handle i y -> Ptr (Struct i y))
-> Ptr (Handle i y) -> Handle i y -> IO ()
forall core wrapper.
Storable core =>
(wrapper -> core) -> Ptr wrapper -> wrapper -> IO ()
Store.poke Handle i y -> Ptr (Struct i y)
forall i y. Handle i y -> Ptr (Struct i y)
dePcm


type SampleFreq = Int
type Time = Int
type Size = Int


data Stream =
     StreamPlayback
   | StreamCapture
   deriving (Stream -> Stream -> Bool
(Stream -> Stream -> Bool)
-> (Stream -> Stream -> Bool) -> Eq Stream
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Stream -> Stream -> Bool
== :: Stream -> Stream -> Bool
$c/= :: Stream -> Stream -> Bool
/= :: Stream -> Stream -> Bool
Eq,Int -> Stream -> ShowS
[Stream] -> ShowS
Stream -> String
(Int -> Stream -> ShowS)
-> (Stream -> String) -> ([Stream] -> ShowS) -> Show Stream
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Stream -> ShowS
showsPrec :: Int -> Stream -> ShowS
$cshow :: Stream -> String
show :: Stream -> String
$cshowList :: [Stream] -> ShowS
showList :: [Stream] -> ShowS
Show,Stream
Stream -> Stream -> Bounded Stream
forall a. a -> a -> Bounded a
$cminBound :: Stream
minBound :: Stream
$cmaxBound :: Stream
maxBound :: Stream
Bounded)

instance Enum Stream where
   fromEnum :: Stream -> Int
fromEnum Stream
StreamPlayback = Int
0
{-# LINE 52 "src/Sound/ALSA/PCM/Core/Handle.hsc" #-}
   fromEnum StreamCapture  = 1
{-# LINE 53 "src/Sound/ALSA/PCM/Core/Handle.hsc" #-}

   toEnum :: Int -> Stream
toEnum Int
0 = Stream
StreamPlayback
{-# LINE 55 "src/Sound/ALSA/PCM/Core/Handle.hsc" #-}
   toEnum 1  = StreamCapture
{-# LINE 56 "src/Sound/ALSA/PCM/Core/Handle.hsc" #-}
   toEnum unmatched = error ("Stream.toEnum: Cannot match " ++ show unmatched)


newtype Mode = Mode C.CInt

nonBlock  :: Mode
nonBlock :: Mode
nonBlock  = CInt -> Mode
Mode CInt
1
async  :: Mode
async :: Mode
async  = CInt -> Mode
Mode CInt
2

{-# LINE 64 "src/Sound/ALSA/PCM/Core/Handle.hsc" #-}

instance Semigroup Mode where
   Mode a <> Mode b = Mode (a .|. b)

instance Monoid Mode where
   mempty :: Mode
mempty = CInt -> Mode
Mode CInt
0
   mappend :: Mode -> Mode -> Mode
mappend = Mode -> Mode -> Mode
forall a. Semigroup a => a -> a -> a
(<>)

modes :: [Mode] -> Mode
modes :: [Mode] -> Mode
modes = [Mode] -> Mode
forall a. Monoid a => [a] -> a
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 :: forall i y. String -> Stream -> Mode -> IO (Handle i y)
open String
device Stream
dir Mode
mode =
   (Ptr (Handle i y) -> IO (Handle i y)) -> IO (Handle i y)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr (Handle i y) -> IO (Handle i y)) -> IO (Handle i y))
-> (Ptr (Handle i y) -> IO (Handle i y)) -> IO (Handle i y)
forall a b. (a -> b) -> a -> b
$ \Ptr (Handle i y)
ptr ->
   String -> (CString -> IO (Handle i y)) -> IO (Handle i y)
forall a. String -> (CString -> IO a) -> IO a
withCString String
device ((CString -> IO (Handle i y)) -> IO (Handle i y))
-> (CString -> IO (Handle i y)) -> IO (Handle i y)
forall a b. (a -> b) -> a -> b
$ \CString
deviceCStr ->
   Ptr (Handle i y) -> CString -> CInt -> Mode -> IO CInt
forall i y. Ptr (Handle i y) -> CString -> CInt -> Mode -> IO CInt
open_ Ptr (Handle i y)
ptr CString
deviceCStr (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> CInt) -> Int -> CInt
forall a b. (a -> b) -> a -> b
$ Stream -> Int
forall a. Enum a => a -> Int
fromEnum Stream
dir) Mode
mode IO CInt -> (CInt -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=
   String -> CInt -> IO ()
forall a. Integral a => String -> a -> IO ()
checkResult_ String
"PCM.open" IO () -> IO (Handle i y) -> IO (Handle i y)
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>
   Ptr (Handle i y) -> IO (Handle i y)
forall a. Storable a => Ptr a -> IO a
peek Ptr (Handle i y)
ptr

close :: Handle i y -> IO ()
close :: forall i y. Handle i y -> IO ()
close Handle i y
h =
   Handle i y -> IO CInt
forall i y. Handle i y -> IO CInt
close_ Handle i y
h IO CInt -> (CInt -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= String -> CInt -> IO ()
forall a. Integral a => String -> a -> IO ()
checkResult_ String
"PCM.close"

prepare :: Handle i y -> IO ()
prepare :: forall i y. Handle i y -> IO ()
prepare Handle i y
h =
   Handle i y -> IO CInt
forall i y. Handle i y -> IO CInt
prepare_ Handle i y
h IO CInt -> (CInt -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= String -> CInt -> IO ()
forall a. Integral a => String -> a -> IO ()
checkResult_ String
"PCM.prepare"

start :: Handle i y -> IO ()
start :: forall i y. Handle i y -> IO ()
start Handle i y
h =
   Handle i y -> IO CInt
forall i y. Handle i y -> IO CInt
start_ Handle i y
h IO CInt -> (CInt -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= String -> CInt -> IO ()
forall a. Integral a => String -> a -> IO ()
checkResult_ String
"PCM.start"

drop :: Handle i y -> IO ()
drop :: forall i y. Handle i y -> IO ()
drop Handle i y
h =
   Handle i y -> IO CInt
forall i y. Handle i y -> IO CInt
drop_ Handle i y
h IO CInt -> (CInt -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= String -> CInt -> IO ()
forall a. Integral a => String -> a -> IO ()
checkResult_ String
"PCM.drop"

drain :: Handle i y -> IO ()
drain :: forall i y. Handle i y -> IO ()
drain Handle i y
h =
   Handle i y -> IO CInt
forall i y. Handle i y -> IO CInt
drain_ Handle i y
h IO CInt -> (CInt -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= String -> CInt -> IO ()
forall a. Integral a => String -> a -> IO ()
checkResult_ String
"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 :: forall y. Handle Interleaved y -> Ptr y -> Int -> IO Int
readi Handle Interleaved y
h Ptr y
buf Int
n =
   (CLong -> Int) -> IO CLong -> IO Int
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap CLong -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (IO CLong -> IO Int) -> IO CLong -> IO Int
forall a b. (a -> b) -> a -> b
$
   String -> CLong -> IO CLong
forall a. Integral a => String -> a -> IO a
checkResult String
"PCM.readi" (CLong -> IO CLong) -> IO CLong -> IO CLong
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Handle Interleaved y -> Ptr y -> CULong -> IO CLong
forall y. Handle Interleaved y -> Ptr y -> CULong -> IO CLong
readi_ Handle Interleaved y
h Ptr y
buf (Int -> CULong
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n)

writei :: Handle Interleaved y -> Ptr y -> Size -> IO Size
writei :: forall y. Handle Interleaved y -> Ptr y -> Int -> IO Int
writei Handle Interleaved y
h Ptr y
buf Int
n =
   (CLong -> Int) -> IO CLong -> IO Int
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap CLong -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (IO CLong -> IO Int) -> IO CLong -> IO Int
forall a b. (a -> b) -> a -> b
$
   String -> CLong -> IO CLong
forall a. Integral a => String -> a -> IO a
checkResult String
"PCM.writei" (CLong -> IO CLong) -> IO CLong -> IO CLong
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Handle Interleaved y -> Ptr y -> CULong -> IO CLong
forall y. Handle Interleaved y -> Ptr y -> CULong -> IO CLong
writei_ Handle Interleaved y
h Ptr y
buf (Int -> CULong
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n)

readn :: Handle Noninterleaved y -> Ptr (Ptr y) -> Size -> IO Size
readn :: forall y. Handle Noninterleaved y -> Ptr (Ptr y) -> Int -> IO Int
readn Handle Noninterleaved y
h Ptr (Ptr y)
buf Int
n =
   (CLong -> Int) -> IO CLong -> IO Int
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap CLong -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (IO CLong -> IO Int) -> IO CLong -> IO Int
forall a b. (a -> b) -> a -> b
$
   String -> CLong -> IO CLong
forall a. Integral a => String -> a -> IO a
checkResult String
"PCM.readn" (CLong -> IO CLong) -> IO CLong -> IO CLong
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Handle Noninterleaved y -> Ptr (Ptr y) -> CULong -> IO CLong
forall y.
Handle Noninterleaved y -> Ptr (Ptr y) -> CULong -> IO CLong
readn_ Handle Noninterleaved y
h Ptr (Ptr y)
buf (Int -> CULong
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n)

writen :: Handle Noninterleaved y -> Ptr (Ptr y) -> Size -> IO Size
writen :: forall y. Handle Noninterleaved y -> Ptr (Ptr y) -> Int -> IO Int
writen Handle Noninterleaved y
h Ptr (Ptr y)
buf Int
n =
   (CLong -> Int) -> IO CLong -> IO Int
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap CLong -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (IO CLong -> IO Int) -> IO CLong -> IO Int
forall a b. (a -> b) -> a -> b
$
   String -> CLong -> IO CLong
forall a. Integral a => String -> a -> IO a
checkResult String
"PCM.writen" (CLong -> IO CLong) -> IO CLong -> IO CLong
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Handle Noninterleaved y -> Ptr (Ptr y) -> CULong -> IO CLong
forall y.
Handle Noninterleaved y -> Ptr (Ptr y) -> CULong -> IO CLong
writen_ Handle Noninterleaved y
h Ptr (Ptr y)
buf (Int -> CULong
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n)


{-# INLINE arraySize #-}
arraySize :: Storable y => Ptr y -> Int -> Int
arraySize :: forall y. Storable y => Ptr y -> Int -> Int
arraySize Ptr y
p Int
n = Ptr y -> Int -> Ptr y
forall a. Storable a => Ptr a -> Int -> Ptr a
advancePtr Ptr y
p Int
n Ptr y -> Ptr y -> Int
forall a b. Ptr a -> Ptr b -> Int
`minusPtr` Ptr y
p