jack 0.7.1.4 → 0.7.2
raw patch · 9 files changed
+538/−33 lines, 9 filesdep ~arraydep ~basedep ~enumsetnew-component:exe:jack-callbacksnew-component:exe:jack-latency
Dependency ranges changed: array, base, enumset, transformers
Files
- INSTALL +4/−6
- examples/Callbacks.hs +73/−0
- examples/Latency.hs +50/−0
- jack.cabal +44/−9
- src/Sound/JACK.hs +264/−9
- src/Sound/JACK/Common.h +7/−0
- src/Sound/JACK/Exception.hs +1/−1
- src/Sound/JACK/FFI.hsc +94/−4
- src/Sound/JACK/FFI/MIDI.hsc +1/−4
INSTALL view
@@ -1,12 +1,10 @@ Installation: -runhaskell Setup.hs configure-runhaskell Setup.hs build-runhaskell Setup.hs install+runhaskell Setup configure+runhaskell Setup build+runhaskell Setup install More information: -runhaskell Setup.hs help--+runhaskell Setup help
+ examples/Callbacks.hs view
@@ -0,0 +1,73 @@+-- This example demonstrates the use of various specialized JACK callbacks.+module Main where++import Foreign.C.Types (CFloat)+import qualified Control.Monad.Exception.Synchronous as Sync+import qualified Control.Monad.Trans.Class as Trans+import qualified Foreign.C.Error as E+import qualified Sound.JACK.Audio as Audio+import qualified Sound.JACK as JACK+import System.Environment (getProgName, )+import Common++main :: IO ()+main = do+ name <- getProgName+ JACK.handleExceptions $+ JACK.withClientDefault name $ \client ->+ JACK.withPort client "input" $ \input ->+ JACK.withPort client "output" $ \output ->+ JACK.withFreewheel client freewheel $+ JACK.withBufferSize client bufferSize $+ JACK.withSampleRate client sampleRate $+ JACK.withPortConnect client portConnect $+ JACK.withPortRename client portRename $+ JACK.withPortRegistration client portRegistration $+ JACK.withClientRegistration client clientRegistration $+ JACK.withGraphOrder client graphOrder $+ JACK.withXRun client xRun $+ Audio.withProcessMono client input process output $+ mainWait client name++process :: CFloat -> IO CFloat+process s = return s++-- Signals entering freewheel mode+freewheel :: Bool -> IO ()+freewheel b = putStrLn $ "Freewheel: " ++ show b++-- Signals the change of buffer size+bufferSize :: JACK.NFrames -> Sync.ExceptionalT E.Errno IO ()+bufferSize s = Trans.lift $ putStrLn $ "Buffer size: " ++ show s++-- Signals the change of sample rate+sampleRate :: JACK.NFrames -> Sync.ExceptionalT E.Errno IO ()+sampleRate s = Trans.lift $ putStrLn $ "Sample rate: " ++ show s++-- Signals port connection+portConnect :: JACK.PortId -> JACK.PortId -> Bool -> IO ()+portConnect p1 p2 True = putStrLn $ "Port connect: " ++ show p1 ++ " to " ++ show p2+portConnect p1 p2 False = putStrLn $ "Port disconnect: " ++ show p1 ++ " to " ++ show p2++-- Signals the change of port name+portRename :: JACK.PortId -> String -> String -> IO ()+portRename p s1 s2 = putStrLn $ "Port rename: " ++ show p ++ ", " ++ s1 ++ " to " ++ s2++-- Signals port registration+portRegistration :: JACK.PortId -> Bool -> IO ()+portRegistration p True = putStrLn $ "Port registered: " ++ show p+portRegistration p False = putStrLn $ "Port unregistered: " ++ show p++-- Signals client registration+clientRegistration :: String -> Bool -> IO ()+clientRegistration s True = putStrLn $ "Client registered: " ++ s+clientRegistration s False = putStrLn $ "Client unregistered: " ++ s++-- Signals reordering of the JACK graph+graphOrder :: Sync.ExceptionalT E.Errno IO ()+graphOrder = Trans.lift $ putStrLn "Processing graph reordered"++-- Signals Xruns+xRun :: Sync.ExceptionalT E.Errno IO ()+xRun = Trans.lift $ putStrLn "Xrun happened"+
+ examples/Latency.hs view
@@ -0,0 +1,50 @@+-- This example demonstrates the use of JACK latency API+module Main where++import Foreign.C.Types (CFloat)+import qualified Sound.JACK.Audio as Audio+import qualified Sound.JACK as JACK+import System.Environment (getProgName, )+import Data.IORef+import Common++main :: IO ()+main = do+ name <- getProgName+ ref <- newIORef 0+ JACK.handleExceptions $+ JACK.withClientDefault name $ \client ->+ JACK.withPort client "input" $ \input ->+ JACK.withPort client "output" $ \output ->+ JACK.withLatency client (latency input output) $+ Audio.withProcessMono client input (process ref) output $+ mainWait client name++process :: IORef CFloat -> CFloat -> IO CFloat+process r v = do+ v' <- readIORef r+ writeIORef r v+ return v'++latency ::+ Audio.Port JACK.Input ->+ Audio.Port JACK.Output ->+ JACK.LatencyCallbackMode ->+ IO ()+latency input output mode =+ if mode == JACK.jackCaptureLatency+ then modifyLatencyRange "Capture" input output mode+ else modifyLatencyRange "Playback" output input mode++modifyLatencyRange ::+ String ->+ Audio.Port from ->+ Audio.Port to ->+ JACK.LatencyCallbackMode ->+ IO ()+modifyLatencyRange name from to mode = do+ JACK.LatencyRange (JACK.NFrames a) (JACK.NFrames b) <-+ JACK.getLatencyRange from mode+ putStrLn $ name ++ " latency recalculation: " ++ show a ++ " " ++ show b+ JACK.setLatencyRange to mode $+ JACK.LatencyRange (JACK.NFrames $ a+1) (JACK.NFrames $ b+1)
jack.cabal view
@@ -1,6 +1,7 @@+Cabal-Version: 2.2 Name: jack-Version: 0.7.1.4-License: GPL+Version: 0.7.2+License: GPL-2.0-only License-File: LICENSE Author: Henning Thielemann, Stefan Kersten, Soenke Hahn <soenkehahn@gmail.com> Maintainer: Henning Thielemann <haskell@henning-thielemann.de>@@ -12,18 +13,19 @@ In order to adapt to your system, you may have to disable pkgConfig or jackFree cabal flags. .- You should compile your clients with @ghc --make -O2 -threaded ...@+ You must compile your clients with @-threaded@+ otherwise you will encounter segfaults. Homepage: http://www.haskell.org/haskellwiki/JACK Category: Sound Build-Type: Simple-Cabal-Version: 1.14-Tested-With: GHC==7.0.4, GHC==7.2.2, GHC==7.4.2, GHC==7.6.3-Tested-With: GHC==8.4.1+Tested-With: GHC==7.4.2, GHC==7.6.3, GHC==7.8.4+Tested-With: GHC==8.4.4, GHC==8.6.5, GHC==9.0.1 Extra-Source-Files: CHANGELOG INSTALL free/Sound/JACK/FFIFree.hs jackfree/Sound/JACK/FFIFree.hs+ src/Sound/JACK/Common.h Source-Repository head type: darcs@@ -32,7 +34,7 @@ Source-Repository this type: darcs location: https://hub.darcs.net/thielema/jack/- tag: 0.7.1.4+ tag: 0.7.2 Flag pkgConfig description: Use pkg-config tool for check version and presence of jack@@ -54,7 +56,7 @@ bytestring >=0.9.1.4 && <0.11, explicit-exception >=0.1.7 && <0.2, transformers >=0.2 && <0.6,- enumset >=0.0 && <0.1,+ enumset >=0.0.5 && <0.1, array >=0.4 && <0.6, semigroups >=0.1 && <1.0, base >=4.0 && <5.0@@ -69,8 +71,9 @@ Sound.JACK.FFIFree Sound.JACK.FFI.MIDI Default-Language: Haskell98- Build-Tools: hsc2hs >=0.66 && <1.0+ Build-Tool-Depends: hsc2hs:hsc2hs >=0.66 && <1.0 Hs-Source-Dirs: src+ Include-Dirs: src GHC-Options: -Wall -fwarn-tabs -fwarn-incomplete-record-updates If impl(ghc >= 6.12) GHC-Options: -fwarn-unused-do-bind@@ -109,6 +112,38 @@ GHC-Options: -Wall -fwarn-tabs -fwarn-incomplete-record-updates Hs-Source-Dirs: examples Main-Is: Amplify.hs++Executable jack-callbacks+ If flag(buildExamples)+ Build-Depends:+ jack,+ explicit-exception >=0.1.7 && <0.2,+ transformers,+ array,+ base >=3.0 && <5+ Else+ Buildable: False+ Default-Language: Haskell98+ GHC-Options: -Wall -fwarn-tabs -fwarn-incomplete-record-updates+ Hs-Source-Dirs: examples+ Main-Is: Callbacks.hs+ Other-Modules: Common++Executable jack-latency+ If flag(buildExamples)+ Build-Depends:+ jack,+ explicit-exception >=0.1.7 && <0.2,+ transformers,+ array,+ base >=3.0 && <5+ Else+ Buildable: False+ Default-Language: Haskell98+ GHC-Options: -Wall -fwarn-tabs -fwarn-incomplete-record-updates+ Hs-Source-Dirs: examples+ Main-Is: Latency.hs+ Other-Modules: Common Executable jack-capture If flag(buildExamples)
src/Sound/JACK.hs view
@@ -27,7 +27,7 @@ -} module Sound.JACK ( -- * general stuff- Client,+ Client(..), newClient, newClientDefault, disposeClient,@@ -43,7 +43,7 @@ Direction, Input, Output, JackFFI.UnknownType, UnknownDirection, - Port,+ Port(..), newPort, disposePort, withPort,@@ -59,10 +59,54 @@ setProcess, withProcess, + Freewheel,+ makeFreewheel,+ setFreewheel,+ withFreewheel,++ BufferSize,+ makeBufferSize,+ setBufferSize,+ withBufferSize,++ SampleRate,+ makeSampleRate,+ setSampleRate,+ withSampleRate,++ PortRename,+ makePortRename,+ setPortRename,+ withPortRename,++ GraphOrder,+ makeGraphOrder,+ setGraphOrder,+ withGraphOrder,++ XRun,+ makeXRun,+ setXRun,+ withXRun,++ Latency,+ LatencyCallbackMode,+ makeLatency,+ setLatency,+ withLatency,+ JackFFI.jackCaptureLatency,+ JackFFI.jackPlaybackLatency,++ JackFFI.LatencyRange(..),+ getLatencyRange,+ setLatencyRange,+ recomputeTotalLatencies,+ getBufferSize, getSampleRate, lastFrameTime, + ClientRegistration, makeClientRegistration, setClientRegistration, withClientRegistration,@@ -71,6 +115,8 @@ makePortRegistration, setPortRegistration, withPortRegistration,++ PortConnect, makePortConnect, setPortConnect, withPortConnect,@@ -109,14 +155,19 @@ import qualified Sound.JACK.FFI as JackFFI import qualified Sound.JACK.FFIFree as JackFFIFree import Sound.JACK.FFI.MIDI (EventBuffer, )-import Sound.JACK.FFI (Process, Input, Output, nframesIndices, nframesBounds, )+import Sound.JACK.FFI+ (Process, Input, Output, Freewheel, BufferSize, SampleRate,+ ClientRegistration, PortRename, PortConnect, GraphOrder,+ XRun, Latency, LatencyCallbackMode,+ nframesIndices, nframesBounds, ) import qualified Control.Monad.Exception.Synchronous as Sync import qualified Control.Monad.Trans.Class as Trans import qualified Control.Exception as Exc import Control.Monad (join)-import Control.Applicative (Const(Const), (<$>), (<$), )+import Control.Applicative (Const(Const), (<$>), (<*>), (<$), ) +import Foreign.Marshal.Utils (with) import qualified Foreign.Marshal.Array as Array import qualified Foreign.C.String as CString import qualified Foreign.C.Types as C@@ -125,7 +176,7 @@ (Ptr, FunPtr, nullPtr, castPtr, freeHaskellFunPtr, nullFunPtr, ) import Foreign.C.String (CString, peekCString, ) import Foreign.C.Error (Errno(Errno), eOK)-import qualified Data.EnumSet as ES+import qualified Data.EnumBitSet as ES import Control.Concurrent (MVar, putMVar, newEmptyMVar, takeMVar, threadDelay) @@ -322,7 +373,8 @@ _dummy :: C.CInt _dummy = undefined -foreign import ccall "wrapper" makeProcess :: Process arg -> IO (FunPtr (Process arg))+foreign import ccall "wrapper"+ makeProcess :: Process arg -> IO (FunPtr (Process arg)) getClient :: Client -> Ptr JackFFI.Client@@ -487,6 +539,201 @@ Sync.switchT return (\() -> return eOK) $ proc nframes) setProcess +foreign import ccall "wrapper"+ makeFreewheel ::+ JackFFI.Freewheel arg -> IO (FunPtr (JackFFI.Freewheel arg))++setFreewheel ::+ (JackExc.ThrowsErrno e) =>+ Client ->+ FunPtr (JackFFI.Freewheel arg) ->+ Ptr arg ->+ Sync.ExceptionalT e IO ()+setFreewheel client procPtr arg =+ liftErrno $ JackFFI.set_freewheel_callback (getClient client) procPtr arg++withFreewheel ::+ (JackExc.ThrowsErrno e) =>+ Client ->+ (Bool -> IO ()) ->+ Sync.ExceptionalT e IO a ->+ Sync.ExceptionalT e IO a+withFreewheel =+ withCallback+ (\fw ->+ makeFreewheel $ \ starting _arg ->+ fw (if starting == 0 then False else True))+ setFreewheel++foreign import ccall "wrapper"+ makeBufferSize ::+ JackFFI.BufferSize arg -> IO (FunPtr (JackFFI.BufferSize arg))++setBufferSize ::+ (JackExc.ThrowsErrno e) =>+ Client ->+ FunPtr (JackFFI.BufferSize arg) ->+ Ptr arg ->+ Sync.ExceptionalT e IO ()+setBufferSize client procPtr arg =+ liftErrno $ JackFFI.set_buffer_size_callback (getClient client) procPtr arg++withBufferSize ::+ (JackExc.ThrowsErrno e) =>+ Client ->+ (JackFFI.NFrames -> Sync.ExceptionalT Errno IO ()) ->+ Sync.ExceptionalT e IO a ->+ Sync.ExceptionalT e IO a+withBufferSize =+ withCallback+ (\bs ->+ makeBufferSize $ \ nframes _arg ->+ Sync.switchT return (\() -> return eOK) $ bs nframes)+ setBufferSize++foreign import ccall "wrapper"+ makeSampleRate ::+ JackFFI.SampleRate arg -> IO (FunPtr (JackFFI.SampleRate arg))++setSampleRate ::+ (JackExc.ThrowsErrno e) =>+ Client ->+ FunPtr (JackFFI.SampleRate arg) ->+ Ptr arg ->+ Sync.ExceptionalT e IO ()+setSampleRate client procPtr arg =+ liftErrno $ JackFFI.set_sample_rate_callback (getClient client) procPtr arg++withSampleRate ::+ (JackExc.ThrowsErrno e) =>+ Client ->+ (JackFFI.NFrames -> Sync.ExceptionalT Errno IO ()) ->+ Sync.ExceptionalT e IO a ->+ Sync.ExceptionalT e IO a+withSampleRate =+ withCallback+ (\bs ->+ makeSampleRate $ \ nframes _arg ->+ Sync.switchT return (\() -> return eOK) $ bs nframes)+ setSampleRate++foreign import ccall "wrapper"+ makePortRename ::+ JackFFI.PortRename arg -> IO (FunPtr (JackFFI.PortRename arg))++setPortRename ::+ (JackExc.ThrowsErrno e) =>+ Client ->+ FunPtr (JackFFI.PortRename arg) ->+ Ptr arg ->+ Sync.ExceptionalT e IO ()+setPortRename client procPtr arg =+ liftErrno $ JackFFI.set_port_rename_callback (getClient client) procPtr arg++withPortRename ::+ (JackExc.ThrowsErrno e) =>+ Client ->+ (JackFFI.PortId -> String -> String -> IO ()) ->+ Sync.ExceptionalT e IO a ->+ Sync.ExceptionalT e IO a+withPortRename =+ withCallback+ (\pr ->+ makePortRename $ \ portid n1 n2 _arg ->+ join $+ pr portid+ <$> peekCString (JackFFI.deconsPortName n1)+ <*> peekCString (JackFFI.deconsPortName n2))+ setPortRename++foreign import ccall "wrapper"+ makeGraphOrder ::+ JackFFI.GraphOrder arg -> IO (FunPtr (JackFFI.GraphOrder arg))++setGraphOrder ::+ (JackExc.ThrowsErrno e) =>+ Client ->+ FunPtr (JackFFI.GraphOrder arg) ->+ Ptr arg ->+ Sync.ExceptionalT e IO ()+setGraphOrder client procPtr arg =+ liftErrno $ JackFFI.set_graph_order_callback (getClient client) procPtr arg++withGraphOrder ::+ (JackExc.ThrowsErrno e) =>+ Client ->+ Sync.ExceptionalT Errno IO () ->+ Sync.ExceptionalT e IO a ->+ Sync.ExceptionalT e IO a+withGraphOrder =+ withCallback+ (\go -> makeGraphOrder $ \ _arg -> Sync.switchT return (\() -> return eOK) go)+ setGraphOrder++foreign import ccall "wrapper"+ makeXRun :: JackFFI.XRun arg -> IO (FunPtr (JackFFI.XRun arg))++setXRun ::+ (JackExc.ThrowsErrno e) =>+ Client ->+ FunPtr (JackFFI.XRun arg) ->+ Ptr arg ->+ Sync.ExceptionalT e IO ()+setXRun client procPtr arg =+ liftErrno $ JackFFI.set_xrun_callback (getClient client) procPtr arg++withXRun ::+ (JackExc.ThrowsErrno e) =>+ Client ->+ Sync.ExceptionalT Errno IO () ->+ Sync.ExceptionalT e IO a ->+ Sync.ExceptionalT e IO a+withXRun =+ withCallback+ (\go -> makeXRun $ \ _arg -> Sync.switchT return (\() -> return eOK) go)+ setXRun++foreign import ccall "wrapper"+ makeLatency :: JackFFI.Latency arg -> IO (FunPtr (JackFFI.Latency arg))++setLatency ::+ (JackExc.ThrowsErrno e) =>+ Client ->+ FunPtr (JackFFI.Latency arg) ->+ Ptr arg ->+ Sync.ExceptionalT e IO ()+setLatency client procPtr arg =+ liftErrno $ JackFFI.set_latency_callback (getClient client) procPtr arg++withLatency ::+ (JackExc.ThrowsErrno e) =>+ Client ->+ (LatencyCallbackMode -> IO ()) ->+ Sync.ExceptionalT e IO a ->+ Sync.ExceptionalT e IO a+withLatency =+ withCallback+ (\lc ->+ makeLatency $ \ mode _arg ->+ lc mode)+ setLatency++getLatencyRange ::+ Port typ dir -> LatencyCallbackMode -> IO JackFFI.LatencyRange+getLatencyRange (Port ptr) mode =+ with (JackFFI.LatencyRange (JackFFI.NFrames 0) (JackFFI.NFrames 0)) $+ \rptr -> JackFFI.port_get_latency_range ptr mode rptr >> peek rptr++setLatencyRange ::+ Port typ dir -> LatencyCallbackMode -> JackFFI.LatencyRange -> IO ()+setLatencyRange (Port ptr) mode range =+ with range $ JackFFI.port_set_latency_range ptr mode++recomputeTotalLatencies ::+ JackExc.ThrowsErrno e => Client -> Sync.ExceptionalT e IO ()+recomputeTotalLatencies (Client ptr) =+ liftErrno $ JackFFI.recompute_total_latencies ptr+ getBufferSize :: Client -> IO Int getBufferSize (Client ptr) = fmap fromIntegral $ JackFFI.get_buffer_size ptr@@ -504,7 +751,10 @@ JackFFI.last_frame_time client -- | Create a client registration callback 'FunPtr'.-foreign import ccall "wrapper" makeClientRegistration :: JackFFI.ClientRegistration arg -> IO (FunPtr (JackFFI.ClientRegistration arg))+foreign import ccall "wrapper"+ makeClientRegistration ::+ JackFFI.ClientRegistration arg ->+ IO (FunPtr (JackFFI.ClientRegistration arg)) -- | Set the client registration callback. setClientRegistration ::@@ -533,7 +783,10 @@ -- | Create a port registration callback 'FunPtr'.-foreign import ccall "wrapper" makePortRegistration :: JackFFI.PortRegistration arg -> IO (FunPtr (JackFFI.PortRegistration arg))+foreign import ccall "wrapper"+ makePortRegistration ::+ JackFFI.PortRegistration arg ->+ IO (FunPtr (JackFFI.PortRegistration arg)) -- | Set the port registration callback. setPortRegistration ::@@ -560,7 +813,9 @@ -- | Create a port connect callback 'FunPtr'.-foreign import ccall "wrapper" makePortConnect :: JackFFI.PortConnect arg -> IO (FunPtr (JackFFI.PortConnect arg))+foreign import ccall "wrapper"+ makePortConnect ::+ JackFFI.PortConnect arg -> IO (FunPtr (JackFFI.PortConnect arg)) -- | Set the port connect callback. setPortConnect ::
+ src/Sound/JACK/Common.h view
@@ -0,0 +1,7 @@+#include <stdio.h>++/* cf. FFI cookbook */+#if __GLASGOW_HASKELL__ < 800+#define hsc_alignment(t) \+ printf("(%lu)", (unsigned long)offsetof(struct {char x__; t (y__); }, y__));+#endif
src/Sound/JACK/Exception.hs view
@@ -10,7 +10,7 @@ import qualified Sound.JACK.FFI as JackFFI import qualified Foreign.C.Error as FE-import qualified Data.EnumSet as ES+import qualified Data.EnumBitSet as ES import Data.Bits (Bits, )
src/Sound/JACK/FFI.hsc view
@@ -25,19 +25,25 @@ import Foreign.Ptr (Ptr, FunPtr) import Foreign.C.String (CString)+import Foreign.Storable (Storable, pokeByteOff, peekByteOff)+import qualified Foreign.Storable as St import qualified Foreign.C.Error as E import qualified Foreign.C.Types as C -import qualified Data.EnumSet as ES+import Control.Applicative (liftA2)++import qualified Data.EnumBitSet as ES import Data.Word (Word, Word32, Word64, ) import Data.Ix (Ix(range, inRange, rangeSize, index)) import Data.Monoid (Monoid, mempty, mappend, ) import Data.Semigroup (Semigroup, (<>), ) -import Numeric.NonNegative.Class as NonNeg+import qualified Numeric.NonNegative.Class as NonNeg #include "jack/types.h"+#include <Sound/JACK/Common.h> + data Client = Client data Port typ = Port @@ -49,7 +55,8 @@ foreign import ccall "static jack/jack.h jack_client_open"- client_open :: CString -> OpenOptionSet -> Ptr StatusSet -> CString -> IO (Ptr Client)+ client_open ::+ CString -> OpenOptionSet -> Ptr StatusSet -> CString -> IO (Ptr Client) {-# DEPRECATED client_new "use client_open instead" #-} foreign import ccall "static jack/jack.h jack_client_new"@@ -67,7 +74,8 @@ | ServerName deriving (Enum, Eq, Ord, Show, Ix) -wordNullOption, wordNoStartServer, wordUseExactName, wordServerName :: OpenOptionSet+wordNullOption, wordNoStartServer, wordUseExactName, wordServerName ::+ OpenOptionSet wordNullOption = ES.empty wordNoStartServer = ES.fromEnum NoStartServer wordUseExactName = ES.fromEnum UseExactName@@ -135,6 +143,12 @@ newtype NFrames = NFrames #{type jack_nframes_t} deriving (Show, Eq, Ord) +instance Storable NFrames where+ alignment _ = #{alignment jack_nframes_t}+ sizeOf _ = #{size jack_nframes_t}+ peek p = fmap NFrames $ peekByteOff p 0+ poke p (NFrames n) = pokeByteOff p 0 n+ nframesToWord :: NFrames -> Word nframesToWord (NFrames n) = fromIntegral n @@ -175,6 +189,24 @@ set_process_callback :: Ptr Client -> FunPtr (Process arg) -> Ptr arg -> IO E.Errno +type Freewheel arg = C.CInt -> Ptr arg -> IO ()++foreign import ccall "static jack/jack.h jack_set_freewheel_callback"+ set_freewheel_callback ::+ Ptr Client -> FunPtr (Freewheel arg) -> Ptr arg -> IO E.Errno++type BufferSize arg = NFrames -> Ptr arg -> IO E.Errno++foreign import ccall "static jack/jack.h jack_set_buffer_size_callback"+ set_buffer_size_callback ::+ Ptr Client -> FunPtr (BufferSize arg) -> Ptr arg -> IO E.Errno++type SampleRate arg = NFrames -> Ptr arg -> IO E.Errno++foreign import ccall "static jack/jack.h jack_set_sample_rate_callback"+ set_sample_rate_callback ::+ Ptr Client -> FunPtr (SampleRate arg) -> Ptr arg -> IO E.Errno+ type ClientRegistration arg = CString -> C.CInt -> Ptr arg -> IO () foreign import ccall "static jack/jack.h jack_set_client_registration_callback"@@ -195,13 +227,47 @@ set_port_registration_callback :: Ptr Client -> FunPtr (PortRegistration arg) -> Ptr arg -> IO E.Errno +type PortRename arg = PortId -> PortName -> PortName -> Ptr arg -> IO ()++foreign import ccall "static jack/jack.h jack_set_port_rename_callback"+ set_port_rename_callback ::+ Ptr Client -> FunPtr (PortRename arg) -> Ptr arg -> IO E.Errno+ type PortConnect arg = PortId -> PortId -> C.CInt -> Ptr arg -> IO () foreign import ccall "static jack/jack.h jack_set_port_connect_callback" set_port_connect_callback :: Ptr Client -> FunPtr (PortConnect arg) -> Ptr arg -> IO E.Errno +type GraphOrder arg = Ptr arg -> IO E.Errno +foreign import ccall "static jack/jack.h jack_set_graph_order_callback"+ set_graph_order_callback ::+ Ptr Client -> FunPtr (GraphOrder arg) -> Ptr arg -> IO E.Errno++type XRun arg = Ptr arg -> IO E.Errno++foreign import ccall "static jack/jack.h jack_set_xrun_callback"+ set_xrun_callback ::+ Ptr Client -> FunPtr (XRun arg) -> Ptr arg -> IO E.Errno++newtype+ LatencyCallbackMode =+ LatencyCallbackMode #{type jack_latency_callback_mode_t}+ deriving (Eq, Ord, Show)++jackCaptureLatency :: LatencyCallbackMode+jackCaptureLatency = LatencyCallbackMode #const JackCaptureLatency++jackPlaybackLatency :: LatencyCallbackMode+jackPlaybackLatency = LatencyCallbackMode #const JackPlaybackLatency++type Latency arg = LatencyCallbackMode -> Ptr arg -> IO ()++foreign import ccall "static jack/jack.h jack_set_latency_callback"+ set_latency_callback ::+ Ptr Client -> FunPtr (Latency arg) -> Ptr arg -> IO E.Errno+ foreign import ccall "static jack/jack.h jack_port_by_id" port_by_id :: Ptr Client -> PortId -> IO (Ptr (Port UnknownType))@@ -242,6 +308,30 @@ port_get_all_connections :: Ptr Client -> Ptr (Port typ) -> IO (Ptr CString) +data LatencyRange = LatencyRange NFrames NFrames deriving (Show, Eq, Ord)++instance Storable LatencyRange where+ alignment _ = #{alignment jack_latency_range_t}+ sizeOf _ = #{size jack_latency_range_t}+ peek p =+ liftA2 LatencyRange+ (#{peek jack_latency_range_t, min} p)+ (#{peek jack_latency_range_t, max} p)+ poke p (LatencyRange a b) = do+ #{poke jack_latency_range_t, min} p a+ #{poke jack_latency_range_t, max} p b++foreign import ccall "static jack/jack.h jack_port_get_latency_range"+ port_get_latency_range ::+ Ptr (Port a) -> LatencyCallbackMode -> Ptr LatencyRange -> IO ()++foreign import ccall "static jack/jack.h jack_port_set_latency_range"+ port_set_latency_range ::+ Ptr (Port a) -> LatencyCallbackMode -> Ptr LatencyRange -> IO ()++foreign import ccall "static jack/jack.h jack_recompute_total_latencies"+ recompute_total_latencies ::+ Ptr Client -> IO E.Errno foreign import ccall "static jack/jack.h jack_last_frame_time" last_frame_time :: Ptr Client -> IO NFrames
src/Sound/JACK/FFI/MIDI.hsc view
@@ -1,6 +1,7 @@ {-# LANGUAGE ForeignFunctionInterface #-} #include "jack/midiport.h"+#include <Sound/JACK/Common.h> module Sound.JACK.FFI.MIDI (@@ -43,10 +44,6 @@ import System.IO (hPutStrLn, stderr, ) --- cf. FFI cookbook-#if __GLASGOW_HASKELL__ < 800-#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)-#endif -- could also be an empty data declaration data EventBuffer = EventBuffer