summaryrefslogtreecommitdiff
path: root/midi-dump.hs
blob: 1a331e828348b32664038ce271d40fcb91484307 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import AlsaSeq
import Control.Concurrent (threadDelay)
import qualified Sound.ALSA.Exception as AlsaExc
import qualified Data.Set as Set
import qualified Haskore.Basic.Pitch as Pitch
import qualified Sound.ALSA.Sequencer.Event as Event
import Control.Monad.RWS.Strict

main = main' `AlsaExc.catch` handler
  where
  handler e = putStrLn $ "alsa_exception: " ++ AlsaExc.show e

data LoopState = LoopState {
  keysDown :: MidiPitchSet,
  inputHistory :: [Maybe Event.T]
}

emptyLoopState = LoopState Set.empty []

main' = withAlsaInit $ \h public private q publicAddr privateAddr -> do
  cmdlineAlsaConnect h public

  putStrLn "Rock on!"

  (s, ()) <- execRWST loop (h, public, private, q, publicAddr, privateAddr) emptyLoopState
  return ()

loop = do
  (h, public, private, q, publicAddr, privateAddr) <- ask
  loopState <- get
  oldKeys <- gets keysDown
  let forwardNOW = forwardNoteEvent h q publicAddr

  (events, newKeys) <- liftIO $ parseAlsaEvents' h oldKeys forwardNOW

  if (oldKeys == newKeys) then
    liftIO $ threadDelay 15000 -- 15ms.  Seems like a lot, but it sounds OK.  Cuts CPU down to 2%.
  else do
    let newHistory = if Set.null oldKeys then Nothing:newEvents else newEvents
        newEvents = map Just events
    liftIO $ printChordLn newKeys
    put loopState { keysDown = newKeys, inputHistory = newHistory ++ inputHistory loopState }

  loop