import Control.Monad import qualified Data.IntMap as M import HSCurses.Curses import Sound.OpenSoundControl import Sound.SC3 import System.Environment repeatM_ :: (Monad m) => m a -> m () repeatM_ = sequence_ . repeat extract :: OSC -> Maybe (Int, Int) extract (Message "/midi" [Int _, Blob [0xb0, c, x]]) = Just (fromIntegral c, fromIntegral x) extract _ = Nothing ctl :: Transport t => t -> (Int, Int) -> IO () ctl fd (i, x) = let i_ = fromIntegral i x_ = fromIntegral x / 128.0 in send fd (c_set1 i_ x_) c_init :: IO Window c_init = do w <- initScr -- initsrc keypad w True -- keypad nl False -- nonl cBreak True -- cbreak echo False -- noecho leaveOk True -- leaveok return w pad :: Bool -> Int -> String -> String pad d n xs | m == n = xs | m > n = take n xs | otherwise = let s = replicate (n - m) ' ' in if d then xs ++ s else s ++ xs where m = length xs padr :: Int -> String -> String padr = pad True c_draw :: Window -> M.IntMap String -> (Int, Int) -> IO () c_draw w m (i, x) = do let n = 8 c = (i `rem` n) * n r = (i `quot` n) * 2 a = if even i then attr0 else setReverse attr0 True attrOn a mvWAddStr w r c (padr n (M.findWithDefault "" i m)) mvWAddStr w (r + 1) c (padr n (show x)) -- mvwaddstr attrOff a refresh -- refresh c_end :: Window -> IO () c_end w = do mvWAddStr w 16 16 "a test" -- mvwaddstr _ <- getch -- getch endWin -- endwin tctl :: [(Int, String)] -> IO () tctl u = do m <- openUDP "127.0.0.1" 57150 -- midi.osc s <- openUDP "127.0.0.1" 57110 -- scsynth w <- c_init let u' = M.fromList u send m (Message "/receive" [Int 0xffff]) repeatM_ (do p <- recv m let ix = extract p act a = ctl s a >> c_draw w u' a maybe (return ()) act ix) c_end w main :: IO () main = do a <- getArgs if null a then usage else run (head a) usage :: IO () usage = putStrLn "usage: tctl settings" run :: FilePath -> IO () run fn = do d <- readFile fn tctl (read d) {- let { f = lagIn 1 0 0.1 * 200 + 600 ; a = lagIn 1 1 0.1 * 0.1 ; l = lagIn 1 2 0.1 * 2 - 1 } in audition (out 0 (pan2 (sinOsc AR f 0) l a)) -}