]> Git — Sourcephile - tmp/julm/arpeggigon.git/blob - RCMA/Translator/Jack.hs
Reworked on Jack. Doesn't compile.
[tmp/julm/arpeggigon.git] / RCMA / Translator / Jack.hs
1 {-# LANGUAGE Arrows #-}
2
3 -- Contains all the information and functions necessary to run a Jack
4 -- port and exchange information through reactive values and Yampa.
5 module RCMA.Translator.Jack where
6
7 import qualified Control.Monad.Exception.Synchronous as Sync
8 import qualified Control.Monad.Trans.Class as Trans
9 import qualified Data.EventList.Absolute.TimeBody as EventListAbs
10 import Data.ReactiveValue
11 import qualified Foreign.C.Error as E
12 import RCMA.Translator.Message
13 import qualified Sound.JACK as Jack
14 import qualified Sound.JACK.MIDI as JMIDI
15
16 rcmaName :: String
17 rcmaName = "RCMA"
18
19 inPortName :: String
20 inPortName = "input"
21
22 outPortName :: String
23 outPortName = "output"
24
25 -- Starts a default client with an input and an output port. Doesn't
26 -- do anything as such.
27 jackSetup :: IO ()
28 jackSetup = Jack.handleExceptions $
29 Jack.withClientDefault rcmaName $ \client ->
30 Jack.withPort client outPortName $ \output ->
31 Jack.withPort client inPortName $ \input ->
32 jackRun client input output (jackCallBack client input output)
33
34 -- Loop that does nothing except setting up a callback function
35 -- (called when Jack is ready to take new inputs).
36 jackRun client input output callback =
37 Jack.withProcess client callback $ do
38 Trans.lift $ putStrLn $ "Started " ++ rcmaName
39 Trans.lift $ Jack.waitForBreak
40
41 -- The callback function. It pumps value out of the input port, mix
42 -- them with value coming from the machine itself and stuff them into
43 -- the output port. When this function is not running, events are
44 -- processed.
45 jackCallBack client input output nframes@(Jack.NFrames nframesInt) = do
46 -- This gets the sample rate of the client and the last frame number
47 -- it processed. We then use it to calculate the current absolute time
48 sr <- Trans.lift $ Jack.getSampleRate client
49 (Jack.NFrames lframeInt) <- Trans.lift $ Jack.lastFrameTime client
50 -- Read the events in the input buffer. /!\ This is in a weird
51 -- structure that we dismount right after into a list.
52 inBuffT <- JMIDI.readEventsFromPort input nframes
53 let rateD = fromIntegral sr
54 inBuff :: [(Frames, RawMessage)]
55 inBuff = map (\(Jack.NFrames n,e) -> (fromIntegral n, e)) $
56 EventListAbs.toPairList inBuffT
57
58 return ()