MIDIDevice{ var name, \type->type, \channel->channel, \spec->ControlSpec.new( minval: minVal, maxval: maxVal, step: step, default: default, units: units ) ]); } connectPorts{ if(inPortNum.notNil,{ this.connectInPort(inPortNum); }); if(outPortNum.notNil,{ this.connectOutPort(outPortNum); }); } connectInPort{ arg inPortNum; if(verbose,{ postln("Connecting MIDIIn for "++name); }); inPort = MIDIIn.new(inPortNum); MIDIIn.connect(inPortNum, inPortNum); } connectOutPort{ arg outPortNum; if(verbose,{ postln("Connecting MIDIOut for "++name); }); outPort = MIDIOut.new(outPortNum); outPort.latency=0; outPort.connect(outPortNum, outPortNum); } disconnectPorts{ this.disconnectInPort(); this.disconnectOutPort(); } disconnectInPort{ if(inPort.notNil, { if(verbose,{ postln("Disconnecting MIDIIn for "++name); }); try{ MIDIIn.disconnect(inPortNum, inPortNum); } }); } disconnectOutPort{ if(outPort.notNil, { if(verbose,{ postln("Disconnecting MIDIOut for "++name); }); try{ outPort.disconnect(outPortNum, outPortNum); } }); } connectPassThroughs{ if(passThroughs.notNil,{ if(verbose,{ postln("Setting up passthroughs for "++name); }); passThroughs.keysValuesDo({|channel, type| MIDIdef.new( key: ("passThrough_"++uid++"_"++channel).asSymbol, func: {arg ...args; if(verbose,{ ("passThrough_"++uid++"_"++channel++": "++args).postln; }); case {type==\control}{outPort.control(chan: channel, val: args[0])} {type==\bend}{outPort.bend(chan: channel, val: args[0])} {type==\midiClock}{outPort.midiClock} {type==\bend}{outPort.bend(chan: channel, veloc: args[0])} {type==\noteOn}{outPort.noteOn(chan: channel, note: args[1], veloc: args[0])} {type==\noteOff}{outPort.noteOn(chan: channel, note: args[1], veloc: args[0])} {type==\polyTouch}{outPort.polyTouch(chan: channel, note: args[1], val: args[0])} {type==\program}{outPort.program(chan: channel, num: args[0])} {type==\touch}{outPort.touch(chan: channel, val: args[0])} {type==\start}{outPort.start} {type==\stop}{outPort.stop} {type==\continue}{outPort.continue}; }, chan: channel, msgType: type, ); }); }); } disconnectPassThroughs{ if(passThroughs.notNil,{ if(verbose,{ postln("Cleaning up passthroughs for "++name); }); passThroughs.keysValuesDo({|channel, type| MIDIdef(("passThrough_"++uid++"_"++channel).asSymbol).free; }); }); } }