jack-0.6.2: src/Sound/JACK/Private.hs
module Sound.JACK.Private where
import qualified Sound.JACK.Exception as JackExc
import qualified Sound.JACK.FFI as JackFFI
import Sound.JACK.FFI.MIDI (EventBuffer, )
import Sound.JACK.FFI (NFrames, )
import qualified Control.Monad.Exception.Synchronous as Sync
import qualified Control.Exception as Exc
import qualified Foreign.Marshal.Alloc as Alloc
import qualified Foreign.C.String as CString
import Foreign.Storable (Storable, )
import Foreign.Ptr (Ptr, )
import qualified Foreign.C.Types as C
import Foreign.C.Error (Errno, eOK, )
-- | Handles of Jack clients
newtype Client = Client (Ptr JackFFI.Client)
-- | Jack Port Type
class PortType typ where
portTypeToCString :: typ -> String
instance PortType C.CFloat where
portTypeToCString _ = "32 bit float mono audio"
instance PortType EventBuffer where
portTypeToCString _ = "8 bit raw midi"
newtype Port typ dir = Port (Ptr (JackFFI.Port typ))
portGetBuffer ::
(PortType typ) =>
Port typ dir -> NFrames -> IO (Ptr typ)
portGetBuffer (Port port) nframes =
JackFFI.port_get_buffer port nframes
withCString ::
String ->
(CString.CString -> Sync.ExceptionalT e IO b) ->
Sync.ExceptionalT e IO b
withCString str f =
Sync.ExceptionalT $
CString.withCString str (Sync.runExceptionalT . f)
alloca ::
(Storable a) =>
(Ptr a -> Sync.ExceptionalT e IO b) ->
Sync.ExceptionalT e IO b
alloca f =
Sync.ExceptionalT $
Alloc.alloca (Sync.runExceptionalT . f)
{-
Mixing of explicit exceptions
with "unchecked" exceptions embedded in IO monad is really not nice.
We should switch to an exception-free IO monad
like explicit-exception:SIO.
-}
bracket ::
Sync.ExceptionalT e IO handle ->
(handle -> Sync.ExceptionalT e IO ()) ->
(handle -> Sync.ExceptionalT e IO a) ->
Sync.ExceptionalT e IO a
bracket open close act =
Sync.ExceptionalT $
Exc.bracket
(Sync.runExceptionalT open)
{-
Exception of 'close' cannot be maintained,
since we can only propagate an exception
or generate a new one.
Generally exceptions in closing functions are a bad idea.
-}
(\r ->
case r of
Sync.Success a -> Sync.runExceptionalT $ close a
Sync.Exception e -> return $ Sync.Exception e)
(\r ->
case r of
Sync.Success a -> Sync.runExceptionalT $ act a
Sync.Exception e -> return $ Sync.Exception e)
bracket_ ::
Sync.ExceptionalT e IO () ->
Sync.ExceptionalT e IO () ->
Sync.ExceptionalT e IO a ->
Sync.ExceptionalT e IO a
bracket_ open close act =
bracket open (\() -> close) (\() -> act)
liftErrno ::
(JackExc.ThrowsErrno e) =>
IO Errno -> Sync.ExceptionalT e IO ()
liftErrno =
Sync.ExceptionalT .
fmap (\err ->
Sync.assert (JackExc.errno err) $ err == eOK)