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 :: forall y. T Interleaved y Access
access = Access -> T Interleaved y Access
forall a. a -> T Interleaved y a
forall (m :: * -> *) a. Monad m => a -> m a
return Access
HwParams.accessRwInterleaved
   setChannels :: forall y. C y => T Interleaved y ()
setChannels =
      Word -> T Interleaved y ()
forall i y. Word -> T i y ()
HwParams.setChannels (Word -> T Interleaved y ())
-> (Int -> Word) -> Int -> T Interleaved y ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Word
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> T Interleaved y ())
-> T Interleaved y Int -> T Interleaved y ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<<
         (y -> Int) -> T Interleaved y Int
forall y a i. (y -> a) -> T i y a
withSampleFmt y -> Int
forall y. C y => y -> Int
Frame.numberOfChannels

instance Access Core.Noninterleaved where
   access :: forall y. T Noninterleaved y Access
access = Access -> T Noninterleaved y Access
forall a. a -> T Noninterleaved y a
forall (m :: * -> *) a. Monad m => a -> m a
return Access
HwParams.accessRwNoninterleaved
   setChannels :: forall y. C y => T Noninterleaved y ()
setChannels = () -> T Noninterleaved y ()
forall a. a -> T Noninterleaved y a
forall (m :: * -> *) a. Monad m => a -> m a
return ()



class (Storable y, Frame.C y) => SampleFmt y where
   sampleFmtToPcmFormat :: y -> HwParams.Format

instance SampleFmt Word8 where
   sampleFmtToPcmFormat :: Word8 -> Format
sampleFmtToPcmFormat Word8
_ = Format
HwParams.formatU8

instance SampleFmt Int8 where
   sampleFmtToPcmFormat :: Int8 -> Format
sampleFmtToPcmFormat Int8
_ = Format
HwParams.formatS8

instance SampleFmt Word16 where
   sampleFmtToPcmFormat :: Word16 -> Format
sampleFmtToPcmFormat Word16
_ = Format
HwParams.formatU16

instance SampleFmt Int16 where
   sampleFmtToPcmFormat :: Int16 -> Format
sampleFmtToPcmFormat Int16
_ = Format
HwParams.formatS16

instance SampleFmt Word32 where
   sampleFmtToPcmFormat :: Word32 -> Format
sampleFmtToPcmFormat Word32
_ = Format
HwParams.formatU32

instance SampleFmt Int32 where
   sampleFmtToPcmFormat :: Int32 -> Format
sampleFmtToPcmFormat Int32
_ = Format
HwParams.formatS32

instance SampleFmt Float where
   sampleFmtToPcmFormat :: Float -> Format
sampleFmtToPcmFormat Float
_ = Format
HwParams.formatFloat

instance SampleFmt Double where
   sampleFmtToPcmFormat :: Double -> Format
sampleFmtToPcmFormat Double
_ = Format
HwParams.formatFloat64

instance SampleFmt MuLaw.T where
   sampleFmtToPcmFormat :: T -> Format
sampleFmtToPcmFormat T
_ = Format
HwParams.formatMuLaw

instance SampleFmt a => SampleFmt (Stereo.T a) where
   sampleFmtToPcmFormat :: T a -> Format
sampleFmtToPcmFormat T a
y =
      a -> Format
forall y. SampleFmt y => y -> Format
sampleFmtToPcmFormat (T a -> a
forall a. T a -> a
Stereo.left T a
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 :: forall y a i. (y -> a) -> T i y a
withSampleFmt y -> a
f = a -> T i y a
forall a. a -> T i y a
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> T i y a) -> a -> T i y a
forall a b. (a -> b) -> a -> b
$ y -> a
f y
forall a. HasCallStack => a
undefined


withHwParams ::
   (Access i, SampleFmt y) =>
   Core.Handle i y -> HwParams.T i y a -> IO a
withHwParams :: forall i y a.
(Access i, SampleFmt y) =>
Handle i y -> T i y a -> IO a
withHwParams Handle i y
h T i y a
f =
   Handle i y -> (Ptr Params -> IO a) -> IO a
forall i y a. Handle i y -> (Ptr Params -> IO a) -> IO a
HwParams.withIO Handle i y
h ((Ptr Params -> IO a) -> IO a) -> (Ptr Params -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ (\(HwParams.Cons Handle i y -> Ptr Params -> IO a
act) -> Handle i y -> Ptr Params -> IO a
act Handle i y
h) (T i y a -> Ptr Params -> IO a) -> T i y a -> Ptr Params -> IO a
forall a b. (a -> b) -> a -> b
$ do
      Access -> T i y ()
forall i y. Access -> T i y ()
HwParams.setAccess (Access -> T i y ()) -> T i y Access -> T i y ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< T i y Access
forall y. T i y Access
forall i y. Access i => T i y Access
access
      Format -> T i y ()
forall i y. Format -> T i y ()
HwParams.setFormat (Format -> T i y ()) -> T i y Format -> T i y ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (y -> Format) -> T i y Format
forall y a i. (y -> a) -> T i y a
withSampleFmt y -> Format
forall y. SampleFmt y => y -> Format
sampleFmtToPcmFormat
      T i y ()
forall y. C y => T i y ()
forall i y. (Access i, C y) => T i y ()
setChannels
      T i y a
f

withSwParams ::
   (Access i, SampleFmt y) =>
   Core.Handle i y -> SwParams.T i y a -> IO a
withSwParams :: forall i y a.
(Access i, SampleFmt y) =>
Handle i y -> T i y a -> IO a
withSwParams Handle i y
h (SwParams.Cons Handle i y -> Ptr Params -> IO a
f) =
   Handle i y -> (Ptr Params -> IO a) -> IO a
forall i y a. Handle i y -> (Ptr Params -> IO a) -> IO a
SwParams.withIO Handle i y
h ((Ptr Params -> IO a) -> IO a) -> (Ptr Params -> IO a) -> IO a
forall a b. (a -> b) -> a -> b
$ Handle i y -> Ptr Params -> IO a
f Handle i y
h