diff options
author | Andrew Cady <d@jerkface.net> | 2014-01-14 08:06:00 -0500 |
---|---|---|
committer | Andrew Cady <d@jerkface.net> | 2014-01-14 08:06:05 -0500 |
commit | e7547448ce9d4af01cd2a78036606f123a25cfaf (patch) | |
tree | 48d3f9780e3ec6895d147ecc94b0d23bd64e4a09 /midi-dump.hs | |
parent | fcf7062c5ecbda5d2815caea624e1e04cc8be557 (diff) |
axis --> fluidsynth alsa proxy works!
Diffstat (limited to 'midi-dump.hs')
-rw-r--r-- | midi-dump.hs | 136 |
1 files changed, 68 insertions, 68 deletions
diff --git a/midi-dump.hs b/midi-dump.hs index 4d1946c..74b9596 100644 --- a/midi-dump.hs +++ b/midi-dump.hs | |||
@@ -1,82 +1,82 @@ | |||
1 | import Control.Monad (forever, ) | ||
2 | import Control.Monad (mplus, ) | ||
3 | import Data.Maybe.HT (toMaybe, ) | ||
4 | import qualified Sound.ALSA.Exception as AlsaExc | ||
5 | import qualified Sound.ALSA.Sequencer.Address as Addr | ||
6 | import qualified Sound.ALSA.Sequencer as SndSeq | ||
1 | import qualified Sound.ALSA.Sequencer.Client as Client | 7 | import qualified Sound.ALSA.Sequencer.Client as Client |
2 | import qualified Sound.ALSA.Sequencer.Port as Port | 8 | import qualified Sound.ALSA.Sequencer.Connect as Connect |
3 | import qualified Sound.ALSA.Sequencer.Event as Event | 9 | import qualified Sound.ALSA.Sequencer.Event as Event |
4 | import qualified Sound.ALSA.Sequencer as SndSeq | 10 | import qualified Sound.ALSA.Sequencer.Event.RemoveMonad as Remove |
5 | import qualified Sound.ALSA.Exception as AlsaExc | ||
6 | import Control.Monad (forever, ) | ||
7 | |||
8 | |||
9 | import qualified Sound.ALSA.Sequencer.Client.Info as ClientInfo | ||
10 | import qualified Sound.ALSA.Sequencer.Port.Info as PortInfo | ||
11 | import qualified Sound.ALSA.Sequencer.Port as Port | 11 | import qualified Sound.ALSA.Sequencer.Port as Port |
12 | import qualified Data.EnumSet as EnumSet | 12 | import qualified Sound.ALSA.Sequencer.Port.InfoMonad as PortInfo |
13 | import Text.Printf (printf, ) | 13 | import qualified Sound.ALSA.Sequencer.Queue as Queue |
14 | import Control.Monad (liftM5, liftM2, join, when, filterM, forM_) | 14 | import qualified Sound.ALSA.Sequencer.RealTime as RealTime |
15 | import qualified Sound.ALSA.Sequencer.Time as Time | ||
16 | import qualified System.Exit as Exit | ||
17 | import qualified System.IO as IO | ||
18 | import System.Environment (getArgs, ) | ||
15 | 19 | ||
16 | import Sound.ALSA.Sequencer.Connect as AlsaConn | 20 | main :: IO () |
17 | import qualified Sound.ALSA.Sequencer.Address as Addr | 21 | main = (do |
22 | SndSeq.withDefault SndSeq.Block $ \h -> do | ||
23 | Client.setName (h :: SndSeq.T SndSeq.DuplexMode) "Haskell-Beat" | ||
24 | Port.withSimple h "inout" | ||
25 | (Port.caps [Port.capRead, Port.capSubsRead, | ||
26 | Port.capWrite, Port.capSubsWrite]) | ||
27 | (Port.types [Port.typeMidiGeneric, Port.typeApplication]) $ \public -> do | ||
28 | Port.withSimple h "private" | ||
29 | (Port.caps [Port.capRead, Port.capWrite]) | ||
30 | (Port.types [Port.typeMidiGeneric]) $ \private -> do | ||
31 | Queue.with h $ \q -> do | ||
18 | 32 | ||
33 | PortInfo.modify h public $ do | ||
34 | PortInfo.setTimestamping True | ||
35 | PortInfo.setTimestampReal True | ||
36 | PortInfo.setTimestampQueue q | ||
19 | 37 | ||
20 | listPorts :: IO () | 38 | c <- Client.getId h |
21 | listPorts = do | 39 | let publicAddr = Addr.Cons c public |
22 | putStrLn " Port Client name Port name Caps" | 40 | privateAddr = Addr.Cons c private |
23 | SndSeq.withDefault SndSeq.Block $ \h -> | ||
24 | ClientInfo.queryLoop_ (h :: SndSeq.T SndSeq.OutputMode) $ \cinfo -> do | ||
25 | client <- ClientInfo.getClient cinfo | ||
26 | PortInfo.queryLoop_ h client $ \pinfo -> do | ||
27 | join $ liftM5 (\a b c d e -> when (c == "AXIS-49 2A") $ printf "%3d:%-3d %-32.32s %-24.24s %s\n" a b c d e) | ||
28 | (fmap (\(Client.Cons p) -> p) $ PortInfo.getClient pinfo) | ||
29 | (fmap (\(Port.Cons p) -> p) $ PortInfo.getPort pinfo) | ||
30 | (ClientInfo.getName cinfo) | ||
31 | (PortInfo.getName pinfo) | ||
32 | (do | ||
33 | caps <- PortInfo.getCapability pinfo | ||
34 | let disp (cap, char) = | ||
35 | if EnumSet.disjoint caps cap then ' ' else char | ||
36 | return $ map disp $ | ||
37 | (Port.capRead, 'r') : | ||
38 | (Port.capSubsRead, 'R') : | ||
39 | (Port.capWrite, 'w') : | ||
40 | (Port.capSubsWrite, 'W') : | ||
41 | []) | ||
42 | 41 | ||
43 | findPort wantName f = do | 42 | --args <- getArgs |
44 | SndSeq.withDefault SndSeq.Block $ \h -> | 43 | let args = ["20", "128"] |
45 | ClientInfo.queryLoop_ (h :: SndSeq.T SndSeq.OutputMode) $ \cinfo -> do | 44 | case args of |
46 | name <- (ClientInfo.getName cinfo) | 45 | [input, output] -> |
47 | when (name == wantName) $ do | 46 | (Connect.createFrom h public =<< Addr.parse h input) |
48 | client <- ClientInfo.getClient cinfo | 47 | >> |
49 | PortInfo.queryLoop_ h client $ \pinfo -> do | 48 | (Connect.createTo h public =<< Addr.parse h output) |
50 | port <- (fmap (\(Client.Cons p) -> p) $ PortInfo.getClient pinfo) | 49 | >> |
51 | f $ show port | 50 | return () |
51 | _ -> | ||
52 | IO.hPutStrLn IO.stderr "need arguments: input-client output-client" | ||
53 | >> | ||
54 | Exit.exitFailure | ||
52 | 55 | ||
53 | main :: IO () | ||
54 | main = (do | ||
55 | --outport <- findPort "AXIS-49 2A" return -- nope | ||
56 | --outport <- findPort "AXIS-49 2A" (\p -> return p) -- nope | ||
57 | putStrLn "Starting." | ||
58 | SndSeq.withDefault SndSeq.Nonblock $ \h -> do | ||
59 | Client.setName (h :: SndSeq.T SndSeq.InputMode) "Axis-of-Eval" | ||
60 | putStrLn "Created sequencer." | ||
61 | Port.withSimple h "primary" | ||
62 | (Port.caps [Port.capWrite, Port.capSubsWrite]) Port.typeMidiGeneric $ \ _p1 -> do | ||
63 | Port.withSimple h "secondary" | ||
64 | (Port.caps [Port.capWrite, Port.capSubsWrite]) Port.typeMidiGeneric $ \ _p2 -> do | ||
65 | putStrLn "Created ports." | 56 | putStrLn "Created ports." |
66 | 57 | ||
67 | clientID <- Client.getId h | 58 | let wait = do |
59 | ev <- Event.input h | ||
60 | case Event.body ev of | ||
61 | Event.NoteEv Event.NoteOn n -> return (Event.NoteOn, n) | ||
62 | Event.NoteEv Event.NoteOff n -> return (Event.NoteOff, n) | ||
63 | _ -> wait | ||
68 | 64 | ||
69 | findPort "AXIS-49 2A" (connectAxis h clientID _p1) | 65 | Queue.control h q Event.QueueStart Nothing |
70 | 66 | ||
71 | forever $ do | 67 | let mkEv e = |
72 | putStrLn "waiting for an event:" | 68 | (Event.simple publicAddr e) { |
73 | print =<< Event.input h) | 69 | Event.queue = q, |
74 | `AlsaExc.catch` \e -> | 70 | Event.time = Time.consAbs $ Time.Real $ RealTime.fromDouble 0 |
75 | putStrLn $ "alsa_exception: " ++ AlsaExc.show e | 71 | } |
76 | 72 | ||
77 | connectAxis h myID myPort axisID = do | 73 | let go = do |
78 | myID_int <- (\(Client.Cons p) -> return p) myID | 74 | (onoff, note) <- wait |
79 | printf "Found my ID: %d.\nFound Axis ID: %s.\n" myID_int axisID | 75 | print note |
80 | AlsaConn.createFrom h myPort =<< Addr.parse h (axisID ++ ":0") | 76 | Event.output h $ mkEv $ Event.NoteEv onoff note |
81 | return () | 77 | _ <- Event.drainOutput h |
78 | go | ||
82 | 79 | ||
80 | go) | ||
81 | `AlsaExc.catch` \e -> | ||
82 | putStrLn $ "alsa_exception: " ++ AlsaExc.show e | ||