diff options
author | Andrew Cady <d@jerkface.net> | 2015-12-05 00:35:23 -0500 |
---|---|---|
committer | Andrew Cady <d@jerkface.net> | 2015-12-05 01:10:53 -0500 |
commit | 05f25fe9b784e49099bde8b718147fcec1a0a9d7 (patch) | |
tree | 1471e78e7af4f37630ff36894e0045a0bb27a66f | |
parent | 060af37ea78454b32b915c3364296720be118025 (diff) |
add facility to queue midi output to synth
-rw-r--r-- | AlsaSeq.hs | 3 | ||||
-rw-r--r-- | midi-dump.hs | 48 |
2 files changed, 39 insertions, 12 deletions
@@ -193,6 +193,7 @@ forwardNoteEvent h q publicAddr ev = do | |||
193 | 193 | ||
194 | -- data T = Cons { highPriority :: !Bool , tag :: !Tag , queue :: !Queue.T , time :: !Time.T , source :: !Addr.T , dest :: !Addr.T , body :: !Data } deriving Show | 194 | -- data T = Cons { highPriority :: !Bool , tag :: !Tag , queue :: !Queue.T , time :: !Time.T , source :: !Addr.T , dest :: !Addr.T , body :: !Data } deriving Show |
195 | 195 | ||
196 | let (Event.Cons highPriority tag _ time _ _ body) = ev in Event.output h (Event.Cons highPriority tag q time publicAddr Addr.subscribers body) | 196 | let (Event.Cons highPriority tag _ time _ _ body) = ev |
197 | Event.output h (Event.Cons highPriority tag q time publicAddr Addr.subscribers body) | ||
197 | Event.drainOutput h | 198 | Event.drainOutput h |
198 | return () | 199 | return () |
diff --git a/midi-dump.hs b/midi-dump.hs index 747ae28..dd59a96 100644 --- a/midi-dump.hs +++ b/midi-dump.hs | |||
@@ -1,5 +1,5 @@ | |||
1 | {-# LANGUAGE FlexibleContexts #-} | 1 | {-# LANGUAGE FlexibleContexts #-} |
2 | {-# LANGUAGE FlexibleInstances #-} | 2 | {-# LANGUAGE FlexibleInstances #-} |
3 | {-# LANGUAGE OverloadedStrings #-} | 3 | {-# LANGUAGE OverloadedStrings #-} |
4 | 4 | ||
5 | import AlsaSeq | 5 | import AlsaSeq |
@@ -48,11 +48,12 @@ recordEvents (Recording s orig) new = Recording s (new ++ orig) | |||
48 | data LoopState = LoopState { | 48 | data LoopState = LoopState { |
49 | _wantExit :: Bool, | 49 | _wantExit :: Bool, |
50 | keysDown :: MidiPitchSet, | 50 | keysDown :: MidiPitchSet, |
51 | _playNOW :: [Event.Data], | ||
51 | _recording :: Recording, | 52 | _recording :: Recording, |
52 | lastTick :: TimeSpec | 53 | lastTick :: TimeSpec |
53 | } | 54 | } |
54 | 55 | ||
55 | initializeState now = LoopState False Set.empty (emptyRecording now) now | 56 | initializeState now = LoopState False Set.empty [] (emptyRecording now) now |
56 | 57 | ||
57 | data LoopEnv = LoopEnv { | 58 | data LoopEnv = LoopEnv { |
58 | _saver :: Chan FinishedRecording, | 59 | _saver :: Chan FinishedRecording, |
@@ -101,25 +102,50 @@ main' = withAlsaInit $ \h public private q publicAddr privateAddr -> do | |||
101 | 102 | ||
102 | let env = LoopEnv saver sqlite startTime startTimeReal h public private q publicAddr privateAddr doSave lineReader | 103 | let env = LoopEnv saver sqlite startTime startTimeReal h public private q publicAddr privateAddr doSave lineReader |
103 | 104 | ||
104 | (_, ()) <- execRWST loop env $ initializeState startTimeReal | 105 | (_, ()) <- execRWST mainLoop env $ initializeState startTimeReal |
105 | return () | 106 | return () |
106 | where | 107 | |
107 | loop = do | 108 | mainLoop = do |
108 | maybeReadLine >>= maybe processMidi processCommand | 109 | maybeReadLine >>= maybe processMidi processCommand |
109 | wantExit <- gets _wantExit | 110 | wantExit <- gets _wantExit |
110 | unless wantExit loop | 111 | |
112 | scheduled <- gets _playNOW | ||
113 | unless (null scheduled) $ do | ||
114 | forM_ scheduled playNoteEv | ||
115 | -- TODO: flush ALSA output here | ||
116 | modify $ \s -> s { _playNOW = [] } | ||
117 | |||
118 | unless wantExit mainLoop | ||
119 | |||
120 | playNote noteOn note = | ||
121 | playNoteEv $ Event.NoteEv onoff note | ||
122 | where onoff = if noteOn then Event.NoteOn else Event.NoteOff | ||
123 | |||
124 | playNoteEv nevdata = do | ||
125 | ms <- getMidiSender | ||
126 | publicAddr <- asks _publicAddr | ||
127 | liftIO $ ms $ Event.simple publicAddr nevdata | ||
128 | |||
129 | whenFlag flag f = gets flag >>= flip when f | ||
111 | 130 | ||
112 | processCommand "exit" = modify $ \s -> s { _wantExit = True } | 131 | processCommand "exit" = modify $ \s -> s { _wantExit = True } |
113 | processCommand "" = return () | 132 | processCommand "" = return () |
133 | processCommand "C" = do | ||
134 | let mkNote pitch = Event.simpleNote (Event.Channel 0) (Event.Pitch pitch) (Event.Velocity 128) | ||
135 | let notes = (Event.NoteEv Event.NoteOn . mkNote) <$> [60, 64, 67] | ||
136 | modify $ \s -> s { _playNOW = notes } | ||
114 | processCommand str = liftIO $ putStrLn $ "Unknown command: " ++ str | 137 | processCommand str = liftIO $ putStrLn $ "Unknown command: " ++ str |
115 | 138 | ||
116 | processMidi = do | 139 | getMidiSender = do |
117 | h <- asks _h | 140 | h <- asks _h |
118 | q <- asks _q | 141 | q <- asks _q |
119 | publicAddr <- asks _publicAddr | 142 | publicAddr <- asks _publicAddr |
143 | return $ forwardNoteEvent h q publicAddr | ||
120 | 144 | ||
145 | processMidi = do | ||
146 | h <- asks _h | ||
121 | oldKeys <- gets keysDown | 147 | oldKeys <- gets keysDown |
122 | let forwardNOW = forwardNoteEvent h q publicAddr | 148 | forwardNOW <- getMidiSender |
123 | (events, newKeys) <- liftIO $ parseAlsaEvents' h oldKeys forwardNOW | 149 | (events, newKeys) <- liftIO $ parseAlsaEvents' h oldKeys forwardNOW |
124 | 150 | ||
125 | 151 | ||
@@ -166,7 +192,7 @@ saveMidi recording = do | |||
166 | 192 | ||
167 | startSaver sqlite = do | 193 | startSaver sqlite = do |
168 | chan <- liftIO newChan | 194 | chan <- liftIO newChan |
169 | thread <- liftIO $ forkIO (saver chan) | 195 | _thread <- liftIO $ forkIO (saver chan) |
170 | return chan | 196 | return chan |
171 | where | 197 | where |
172 | saver chan = forever $ do | 198 | saver chan = forever $ do |