packages feed

hmidi-0.1: examples/chords.hs

--
-- A very simple example application using System.MIDI.
--
-- It accepts NoteOn / NoteOff messages from a MIDI source and 
-- sends corresponding chords to a MIDI destination.
--

module Main where

import Control.Monad
import System.MIDI

-- the essence

chord = [0,4,7]
output_channel = 1

mycallback outconn event@(MidiEvent _ (MidiMessage chn msg)) = do
  case msg of
    NoteOff k   -> forM_ chord $ \j -> send outconn $ MidiMessage output_channel $ NoteOff (k+j)
    NoteOn  k v -> forM_ chord $ \j -> send outconn $ MidiMessage output_channel $ NoteOn  (k+j) v
    _           -> return () 
mycallback _ _ = return ()

-- source / destination selection

maybeRead :: Read a => String -> Maybe a
maybeRead s = case reads s of 
  [(x,"")] -> Just x
  _        -> Nothing
  
select srclist = do
  names <- mapM getName srclist
  forM_ (zip [1..] names) $ \(i,name) -> putStrLn $ show i ++ ": " ++ name
  let nsrc = length srclist
  src <- case srclist of
    []  -> fail "no midi devices found"
    [x] -> return x
    _   -> do
      putStrLn "please select a midi device"
      l <- getLine
      let k = case maybeRead l of
        { Nothing -> nsrc
        ; Just m  -> if m<1 || m>nsrc then nsrc else m
        }
      putStrLn $ "device #" ++ show k ++ " selected."
      return $ srclist!!(k-1)
  return src
      
-- main      
      
main = do

  srclist <- enumerateSources
  putStrLn "midi sources:"
  src <- select srclist

  dstlist <- enumerateDestinations
  putStrLn "\nmidi destinations:"
  dst <- select dstlist

  outconn <- openDestination dst
  inconn  <- openSource src $ Just (mycallback outconn)
  putStrLn "connected"
 
  start inconn ; putStrLn "started. Press 'ENTER' to exit."
  getLine
  stop inconn  ; putStrLn "stopped."
  
  close inconn ; putStrLn "closed."
  close outconn