// title: exhaustive MIDI debugger // author: soundlake // description: // Inspired by https://sccode.org/1-5co // Written in 3.11.2. // // All arguments are labeled. Source ID becomes more human-readable format; MIDIEndPoint.device and MIDIEndPoint.name. // code: MIDIClient.init; MIDIIn.connectAll; ( // List or comment out the message types to debug ~types = [ "noteOn", "noteOff", "control", "touch", "polytouch", "bend", "program", "sysex", // System Common "smpte", "mtcQF", "songPosition", "songSelect", "tuneRequest", "midiClock", // System Realtime "sysrt", "tick", "start", "continue", "stop", "activeSense", "reset" ]; // Register sources ~sources = Dictionary.new; MIDIClient.sources.do({ |mep| ~sources.add(mep.uid -> mep.device.catArgs(", ", mep.name)); }); // Register the debugger MIDIdef.freeAll; ~types.do({ |type| var key, func, msgType; key = (type + "Func").asSymbol; msgType = type.asSymbol; // Define the debugger funciton depend on the message type func = case { [ "noteOn", "noteOff", "control", "touch", "polytouch", "bend", "program", ].includesEqual(type)} {{ arg value, num, chan, srcID; ~sources[srcID].catArgs( ", ", (type ++ ",").padRight(12), "ch: 0x", chan.asHexString(2), ", ", "num: 0x", num.asHexString(2), ", ", "val: ", value ).postln; }} { type == "sysex" } {{ arg data, srcID; ~sources[srcID].catArgs( ", ", (type ++ ",").padRight(12), ", data: Int8Array", data.collect({ |n| "0x" ++ n.asHexString(2) }) ).postln; }} { type == "smpte" } {{ arg seconds, framerate, dropframe, srcID; ~sources[srcID].catArgs( ", ", (type ++ ",").padRight(12), "seconds: ", seconds, ", ", "framerate: ", framerate, ", ", "dropframe: ", dropframe ).postln; }} { type == "mtcQF" } {{ arg data, srcID, pieceNumber; ~sources[srcID].catArgs( ", ", (type ++ ",").padRight(12), ", pieceNumber: ", pieceNumber, ", data: ", data ).postln; }} { type == "songPosition" } {{ arg position, srcID; ~sources[srcID].catArgs( ", ", (type ++ ",").padRight(12), ", position: ", position ).postln; }} { type == "songSelect" } {{ arg song, srcID; ~sources[srcID].catArgs( ", ", (type ++ ",").padRight(12), ", song: ", song ).postln; }} { [ "tuneRequest", "midiClock", "tick", "start", "stop", "continue" "reset", "activeSense" ].includesEqual(type) } {{ arg srcID; ~sources[srcID].catArgs( ", ", (type ++ ",").padRight(12) ).postln; }} { type == "sysrt" } {{ arg data, srcID, index; var table; table = Dictionary.newFrom([ 1, "MIDI Time Code Quarter Frames", 2, "Song Position", 3, "Song Select", 6, "Tune Request", 8, "MIDI Clock", 9, "Tick", 10, "Start", 11, "Continue", 12, "Stop", 14, "Active Sense", 15, "Reset" ]); ~sources[srcID].catArgs( ", ", (type ++ ",").padRight(12), ", ", table[index] ).postln; }} { true } {{ arg ...args; args.postln }}; MIDIdef.new(key, func, nil, nil, msgType); }) )