summaryrefslogtreecommitdiff
path: root/midi-dump.hs
diff options
context:
space:
mode:
Diffstat (limited to 'midi-dump.hs')
-rw-r--r--midi-dump.hs37
1 files changed, 28 insertions, 9 deletions
diff --git a/midi-dump.hs b/midi-dump.hs
index f332482..536d78d 100644
--- a/midi-dump.hs
+++ b/midi-dump.hs
@@ -29,6 +29,7 @@ import qualified Sound.ALSA.Sequencer.Time as Time
29import qualified Sound.ALSA.Sequencer.RealTime as RealTime 29import qualified Sound.ALSA.Sequencer.RealTime as RealTime
30 30
31import Midi 31import Midi
32import RealTimeQueue as Q hiding (null)
32 33
33verbose :: Bool 34verbose :: Bool
34verbose = False 35verbose = False
@@ -42,13 +43,14 @@ data LoopState = LoopState {
42 _wantExit :: Bool, 43 _wantExit :: Bool,
43 keysDown :: MidiPitchSet, 44 keysDown :: MidiPitchSet,
44 _playNOW :: [Event.Data], 45 _playNOW :: [Event.Data],
46 _scheduled :: Q.Queue Event.Data,
45 _recording :: Recording, 47 _recording :: Recording,
46 _replay :: Recording, 48 _replay :: Recording,
47 _lastTick :: TimeSpec 49 _lastTick :: TimeSpec
48} 50}
49 51
50initializeState :: TimeSpec -> LoopState 52initializeState :: TimeSpec -> LoopState
51initializeState now = LoopState False Set.empty [] (StartRecording now) (StartRecording now) now 53initializeState now = LoopState False Set.empty [] createQueue (StartRecording now) (StartRecording now) now
52 54
53data LoopEnv = LoopEnv { 55data LoopEnv = LoopEnv {
54 _saver :: Chan CompleteRecording, 56 _saver :: Chan CompleteRecording,
@@ -131,14 +133,23 @@ mainLoop = do
131 maybeReadLine >>= maybe processMidi processCommand 133 maybeReadLine >>= maybe processMidi processCommand
132 wantExit <- gets _wantExit 134 wantExit <- gets _wantExit
133 135
134 scheduled <- gets _playNOW 136 playImmediates
135 unless (null scheduled) $ do 137 playScheduled
136 forM_ scheduled playNoteEv
137 -- TODO: flush ALSA output here (and remove flush from playNoteEv)
138 modify $ \s -> s { _playNOW = [] }
139 138
140 unless wantExit mainLoop 139 unless wantExit mainLoop
141 140
141playScheduled :: MidiController ()
142playScheduled = queueAction $ runScheduledIO (TimeSpec 1 0) $ uncurry alsaDelayNoteEv
143-- TODO: flush ALSA output here (and remove flush from playNoteEv)
144
145playImmediates :: MidiController ()
146playImmediates = do
147 immediate <- gets _playNOW
148 unless (null immediate) $ do
149 forM_ immediate playNoteEv
150 -- TODO: flush ALSA output here (and remove flush from playNoteEv)
151 modify $ \s -> s { _playNOW = [] }
152
142_playNote :: Bool -> Event.Note -> RWST LoopEnv () LoopState IO () 153_playNote :: Bool -> Event.Note -> RWST LoopEnv () LoopState IO ()
143_playNote noteOn note = 154_playNote noteOn note =
144 playNoteEv $ Event.NoteEv onoff note 155 playNoteEv $ Event.NoteEv onoff note
@@ -149,14 +160,22 @@ delayEvent evt ts = evt {Event.time = Time.consRel $ Time.Real (RealTime.fromInt
149 where nanosecs = timeSpecAsNanoSecs ts 160 where nanosecs = timeSpecAsNanoSecs ts
150 161
151playNoteEv :: Event.Data -> RWST LoopEnv () LoopState IO () 162playNoteEv :: Event.Data -> RWST LoopEnv () LoopState IO ()
152playNoteEv = delayNoteEv (TimeSpec 0 0) 163playNoteEv = alsaDelayNoteEv (TimeSpec 0 0)
153 164
154delayNoteEv :: TimeSpec -> Event.Data -> RWST LoopEnv () LoopState IO () 165alsaDelayNoteEv :: TimeSpec -> Event.Data -> RWST LoopEnv () LoopState IO ()
155delayNoteEv delay nevdata = do 166alsaDelayNoteEv delay nevdata = do
156 ms <- getMidiSender 167 ms <- getMidiSender
157 publicAddr <- asks _publicAddr 168 publicAddr <- asks _publicAddr
158 liftIO $ ms $ Event.simple publicAddr nevdata `delayEvent` delay 169 liftIO $ ms $ Event.simple publicAddr nevdata `delayEvent` delay
159 170
171queueAction :: (Queue Event.Data -> MidiController (Queue Event.Data)) -> MidiController ()
172queueAction act = do
173 q <- gets _scheduled
174 act q >>= \q' -> modify $ \s -> s { _scheduled = q' }
175
176delayNoteEv :: TimeSpec -> Event.Data -> RWST LoopEnv () LoopState IO ()
177delayNoteEv delay nevdata = queueAction $ scheduleEventIO (delay, nevdata)
178
160_whenFlag :: forall (m :: * -> *) s. MonadState s m => (s -> Bool) -> m () -> m () 179_whenFlag :: forall (m :: * -> *) s. MonadState s m => (s -> Bool) -> m () -> m ()
161_whenFlag flag f = gets flag >>= flip when f 180_whenFlag flag f = gets flag >>= flip when f
162 181