{
   "is_private" : null,
   "id" : "1-5f8",
   "code" : "MIDIClient.init;\r\nMIDIIn.connectAll;\r\n(\r\n// List or comment out the message types to debug\r\n~types = [\r\n\t\"noteOn\",\r\n\t\"noteOff\",\r\n\t\"control\",\r\n\t\"touch\",\r\n\t\"polytouch\",\r\n\t\"bend\",\r\n\t\"program\",\r\n\t\"sysex\",\r\n\t// System Common\r\n\t\"smpte\",\r\n\t\"mtcQF\",\r\n\t\"songPosition\",\r\n\t\"songSelect\",\r\n\t\"tuneRequest\",\r\n\t\"midiClock\",\r\n\t// System Realtime\r\n\t\"sysrt\",\r\n\t\"tick\",\r\n\t\"start\",\r\n\t\"continue\",\r\n\t\"stop\",\r\n\t\"activeSense\",\r\n\t\"reset\"\r\n];\r\n\r\n// Register sources\r\n~sources = Dictionary.new;\r\nMIDIClient.sources.do({ |mep|\r\n\t~sources.add(mep.uid -> mep.device.catArgs(\", \", mep.name));\r\n});\r\n\r\n// Register the debugger\r\nMIDIdef.freeAll;\r\n~types.do({ |type|\r\n\tvar key, func, msgType;\r\n\r\n\tkey = (type + \"Func\").asSymbol;\r\n\tmsgType = type.asSymbol;\r\n\r\n\t// Define the debugger funciton depend on the message type\r\n\tfunc = case\r\n\t{ [\r\n\t\t\"noteOn\",\r\n\t\t\"noteOff\",\r\n\t\t\"control\",\r\n\t\t\"touch\",\r\n\t\t\"polytouch\",\r\n\t\t\"bend\",\r\n\t\t\"program\",\r\n\t].includesEqual(type)} {{\r\n\t\targ value, num, chan, srcID;\r\n\t\t~sources[srcID].catArgs(\r\n\t\t\t\", \", (type ++ \",\").padRight(12),\r\n\t\t\t\"ch: 0x\", chan.asHexString(2), \", \",\r\n\t\t\t\"num: 0x\", num.asHexString(2), \", \",\r\n\t\t\t\"val: \", value\r\n\t\t).postln;\r\n\t}}\r\n\t{ type == \"sysex\" } {{\r\n\t\targ data, srcID;\r\n\t\t~sources[srcID].catArgs(\r\n\t\t\t\", \", (type ++ \",\").padRight(12),\r\n\t\t\t\", data: Int8Array\", data.collect({ |n| \"0x\" ++ n.asHexString(2) })\r\n\t\t).postln;\r\n\t}}\r\n\t{ type == \"smpte\" } {{\r\n\t\targ seconds, framerate, dropframe, srcID;\r\n\t\t~sources[srcID].catArgs(\r\n\t\t\t\", \", (type ++ \",\").padRight(12),\r\n\t\t\t\"seconds: \", seconds, \", \",\r\n\t\t\t\"framerate: \", framerate, \", \",\r\n\t\t\t\"dropframe: \", dropframe\r\n\t\t).postln;\r\n\t}}\r\n\t{ type == \"mtcQF\" } {{\r\n\t\targ data, srcID, pieceNumber;\r\n\t\t~sources[srcID].catArgs(\r\n\t\t\t\", \", (type ++ \",\").padRight(12),\r\n\t\t\t\", pieceNumber: \", pieceNumber,\r\n\t\t\t\", data: \", data\r\n\t\t).postln;\r\n\t}}\r\n\t{ type == \"songPosition\" } {{\r\n\t\targ position, srcID;\r\n\t\t~sources[srcID].catArgs(\r\n\t\t\t\", \", (type ++ \",\").padRight(12),\r\n\t\t\t\", position: \", position\r\n\t\t).postln;\r\n\t}}\r\n\t{ type == \"songSelect\" } {{\r\n\t\targ song, srcID;\r\n\t\t~sources[srcID].catArgs(\r\n\t\t\t\", \", (type ++ \",\").padRight(12),\r\n\t\t\t\", song: \", song\r\n\t\t).postln;\r\n\t}}\r\n\t{ [\r\n\t\t\"tuneRequest\",\r\n\t\t\"midiClock\",\r\n\t\t\"tick\",\r\n\t\t\"start\",\r\n\t\t\"stop\",\r\n\t\t\"continue\"\r\n\t\t\"reset\",\r\n\t\t\"activeSense\"\r\n\t].includesEqual(type) } {{\r\n\t\targ srcID;\r\n\t\t~sources[srcID].catArgs(\r\n\t\t\t\", \", (type ++ \",\").padRight(12)\r\n\t\t).postln;\r\n\t}}\r\n\t{ type == \"sysrt\" } {{\r\n\t\targ data, srcID, index;\r\n\t\tvar table;\r\n\t\ttable = Dictionary.newFrom([\r\n\t\t\t1, \"MIDI Time Code Quarter Frames\",\r\n\t\t\t2, \"Song Position\",\r\n\t\t\t3, \"Song Select\",\r\n\t\t\t6, \"Tune Request\",\r\n\t\t\t8, \"MIDI Clock\",\r\n\t\t\t9, \"Tick\",\r\n\t\t\t10, \"Start\",\r\n\t\t\t11, \"Continue\",\r\n\t\t\t12, \"Stop\",\r\n\t\t\t14, \"Active Sense\",\r\n\t\t\t15, \"Reset\"\r\n\t\t]);\r\n\r\n\t\t~sources[srcID].catArgs(\r\n\t\t\t\", \", (type ++ \",\").padRight(12),\r\n\t\t\t\", \", table[index]\r\n\t\t).postln;\r\n\t}}\r\n\t{ true } {{ arg ...args; args.postln }};\r\n\r\n\tMIDIdef.new(key, func, nil, nil, msgType);\r\n})\r\n)",
   "labels" : [
      "midi"
   ],
   "ancestor_list" : [],
   "description" : "Inspired by https://sccode.org/1-5co\r\nWritten in 3.11.2.\r\n\r\nAll arguments are labeled. Source ID becomes more human-readable format; MIDIEndPoint.device and MIDIEndPoint.name.",
   "author" : "soundlake",
   "name" : "exhaustive MIDI debugger"
}
