--------------------------------------------------------------------------------
-- |
-- Module    : Sound.ALSA.Sequencer.Port
-- Copyright : (c) Henning Thielemann, 2010
--             (c) Iavor S. Diatchki, 2007
-- License   : BSD3
--
-- Maintainer: Henning Thielemann
-- Stability : provisional
--
-- This module contains functions for working with ports.
-- Reference:
-- <http://www.alsa-project.org/alsa-doc/alsa-lib/group___seq_port.html>
--------------------------------------------------------------------------------

{-# LANGUAGE ForeignFunctionInterface #-}
module Sound.ALSA.Sequencer.Port
  ( Port.T(Port.Cons)
  , create
  , createSimple
  , delete
  , deleteSimple

  , withSimple

  , Port.systemTimer
  , Port.systemAnnounce
  , Port.unknown

  , Port.Cap
  , Port.capRead
  , Port.capWrite
  , Port.capSyncRead
  , Port.capSyncWrite
  , Port.capDuplex
  , Port.capSubsRead
  , Port.capSubsWrite
  , Port.capNoExport
  , Port.caps

  , Port.Type
  , Port.typeSpecific
  , Port.typeMidiGeneric
  , Port.typeMidiGM
  , Port.typeMidiGS
  , Port.typeMidiXG
  , Port.typeMidiMT32
  , Port.typeMidiGM2

  , Port.typeSynth
  , Port.typeDirectSample
  , Port.typeSample

  , Port.typeHardware
  , Port.typeSoftware
  , Port.typeSynthesizer
  , Port.typePort
  , Port.typeApplication
  , Port.types

  ) where

import qualified Sound.ALSA.Sequencer.Marshal.Port as Port
import qualified Sound.ALSA.Sequencer.Marshal.PortInfo as PortInfo
import qualified Sound.ALSA.Sequencer.Marshal.Sequencer as Seq
import qualified Sound.ALSA.Exception as Exc

import qualified Foreign.C.Types as C
import Foreign.C.String (CString, withCAString, )
import Foreign.Ptr (Ptr, )

import qualified Data.EnumBitSet as EnumSet -- expose EnumSet.Cons for foreign call

import Control.Exception (bracket, )



--------------------------------------------------------------------------------

-- | Create a port - simple version.
createSimple :: Seq.T mode -> String -> Port.Cap -> Port.Type -> IO Port.T
createSimple :: forall mode. T mode -> String -> Cap -> Type -> IO T
createSimple (Seq.Cons Ptr Core
h) String
s Cap
c Type
t =
  forall a. String -> (CString -> IO a) -> IO a
withCAString String
s forall a b. (a -> b) -> a -> b
$ \CString
a ->
    CInt -> T
Port.imp forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` (forall a. Integral a => String -> a -> IO a
Exc.checkResult String
"create_simple_port" forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr Core -> CString -> Cap -> Type -> IO CInt
snd_seq_create_simple_port Ptr Core
h CString
a Cap
c Type
t)

foreign import ccall unsafe "alsa/asoundlib.h snd_seq_create_simple_port"
  snd_seq_create_simple_port :: Ptr Seq.Core -> CString -> Port.Cap -> Port.Type
                                -> IO C.CInt


-- | Delete the port.
deleteSimple :: Seq.T mode -> Port.T -> IO ()
deleteSimple :: forall mode. T mode -> T -> IO ()
deleteSimple (Seq.Cons Ptr Core
h) (Port.Cons Word8
p) =
  forall a. Integral a => String -> a -> IO ()
Exc.checkResult_ String
"delete_simple_port" forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr Core -> CInt -> IO CInt
snd_seq_delete_simple_port Ptr Core
h (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
p)

foreign import ccall unsafe "alsa/asoundlib.h snd_seq_delete_simple_port"
  snd_seq_delete_simple_port :: Ptr Seq.Core -> C.CInt -> IO C.CInt


withSimple ::
   Seq.T mode -> String -> Port.Cap -> Port.Type ->
   (Port.T -> IO a) ->
   IO a
withSimple :: forall mode a.
T mode -> String -> Cap -> Type -> (T -> IO a) -> IO a
withSimple T mode
ss String
s Cap
c Type
t =
   forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket (forall mode. T mode -> String -> Cap -> Type -> IO T
createSimple T mode
ss String
s Cap
c Type
t) (forall mode. T mode -> T -> IO ()
deleteSimple T mode
ss)



--------------------------------------------------------------------------------

-- | Create a new port, as described by the info structure.
create :: Seq.T mode -> PortInfo.T -> IO ()
create :: forall mode. T mode -> T -> IO ()
create (Seq.Cons Ptr Core
h) T
p =
  forall a. Integral a => String -> a -> IO ()
Exc.checkResult_ String
"create_port" forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< forall a. T -> (Ptr T_ -> IO a) -> IO a
PortInfo.with T
p (Ptr Core -> Ptr T_ -> IO CInt
snd_seq_create_port Ptr Core
h)

foreign import ccall unsafe "alsa/asoundlib.h snd_seq_create_port"
  snd_seq_create_port :: Ptr Seq.Core -> Ptr PortInfo.T_ -> IO C.CInt

-- | Delete the port.
delete :: Seq.T mode -> Port.T -> IO ()
delete :: forall mode. T mode -> T -> IO ()
delete (Seq.Cons Ptr Core
h) (Port.Cons Word8
p) =
  forall a. Integral a => String -> a -> IO ()
Exc.checkResult_ String
"delete_port" forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Ptr Core -> CInt -> IO CInt
snd_seq_delete_port Ptr Core
h (forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
p)

foreign import ccall unsafe "alsa/asoundlib.h snd_seq_delete_port"
  snd_seq_delete_port :: Ptr Seq.Core -> C.CInt -> IO C.CInt



_dummyEnumSet :: EnumSet.T Int Bool
_dummyEnumSet :: T Int Bool
_dummyEnumSet = forall a. HasCallStack => a
undefined