summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Cady <d@jerkface.net>2015-12-05 00:35:23 -0500
committerAndrew Cady <d@jerkface.net>2015-12-05 01:10:53 -0500
commit05f25fe9b784e49099bde8b718147fcec1a0a9d7 (patch)
tree1471e78e7af4f37630ff36894e0045a0bb27a66f
parent060af37ea78454b32b915c3364296720be118025 (diff)
add facility to queue midi output to synth
-rw-r--r--AlsaSeq.hs3
-rw-r--r--midi-dump.hs48
2 files changed, 39 insertions, 12 deletions
diff --git a/AlsaSeq.hs b/AlsaSeq.hs
index 7fff575..5b65967 100644
--- a/AlsaSeq.hs
+++ b/AlsaSeq.hs
@@ -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
5import AlsaSeq 5import AlsaSeq
@@ -48,11 +48,12 @@ recordEvents (Recording s orig) new = Recording s (new ++ orig)
48data LoopState = LoopState { 48data 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
55initializeState now = LoopState False Set.empty (emptyRecording now) now 56initializeState now = LoopState False Set.empty [] (emptyRecording now) now
56 57
57data LoopEnv = LoopEnv { 58data 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 108mainLoop = 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
120playNote noteOn note =
121 playNoteEv $ Event.NoteEv onoff note
122 where onoff = if noteOn then Event.NoteOn else Event.NoteOff
123
124playNoteEv nevdata = do
125 ms <- getMidiSender
126 publicAddr <- asks _publicAddr
127 liftIO $ ms $ Event.simple publicAddr nevdata
128
129whenFlag flag f = gets flag >>= flip when f
111 130
112processCommand "exit" = modify $ \s -> s { _wantExit = True } 131processCommand "exit" = modify $ \s -> s { _wantExit = True }
113processCommand "" = return () 132processCommand "" = return ()
133processCommand "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 }
114processCommand str = liftIO $ putStrLn $ "Unknown command: " ++ str 137processCommand str = liftIO $ putStrLn $ "Unknown command: " ++ str
115 138
116processMidi = do 139getMidiSender = 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
145processMidi = 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
167startSaver sqlite = do 193startSaver 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