1 // see MIDIResponder help for all classes on this page
5 var <>function,<>swallowEvent=false,
6 <>matchEvent; // for matching ports, channels, and parameters
8 if(this.class.initialized.not,{ this.class.init });
9 matchEvent.port = matchEvent.port.asMIDIInPortUID;
10 if(install,{this.class.add(this);});
12 respond { arg src,chan,num,value;
13 if(this.match(src,chan,num,value),{
14 this.value(src,chan,num,value)
19 match { arg src,chan,num,value;
20 ^matchEvent.match(src,chan,num,value);
22 value { arg src,chan,a,b;
23 function.value(src, chan, a, b)
27 this.class.remove(this)
30 if(this == MIDIResponder,{
31 this.allSubclasses.do({ |responderClass| responderClass.removeAll })
40 NoteOnResponder : MIDIResponder {
41 classvar <norinit = false,<nonr;
43 *new { arg function, src, chan, num, veloc, install=true,swallowEvent=false;
44 ^super.new.function_(function)
45 .matchEvent_(MIDIEvent(nil, src, chan, num, veloc))
46 .swallowEvent_(swallowEvent)
49 *initialized { ^norinit }
52 if(MIDIClient.initialized.not,{ MIDIIn.connectAll });
55 MIDIIn.addFuncTo(\noteOn, { arg src, chan, note, veloc;
57 r.respond(src,chan,note,veloc)
62 nonr = nonr.add(resp);
69 oneShot = this.class.new({ |src,chan,num,value|
70 this.matchEvent_(MIDIEvent(nil,src,chan,nil,nil));
72 },nil,nil,nil,nil,true,true)
76 NoteOffResponder : NoteOnResponder {
77 classvar <noffinit = false,<noffr;
80 if(MIDIClient.initialized.not,{ MIDIIn.connectAll });
83 MIDIIn.addFuncTo(\noteOff, { arg src, chan, note, veloc;
85 r.respond(src,chan,note,veloc)
89 *initialized { ^noffinit }
90 *responders { ^noffr }
93 noffr = noffr.add(resp);
100 CCResponder : MIDIResponder {
101 classvar <ccinit = false,<ccr,<ccnumr;
103 *new { arg function, src, chan, num, value, install=true,swallowEvent=false;
104 ^super.new.function_(function).swallowEvent_(swallowEvent)
105 .matchEvent_(MIDIEvent(nil, src, chan, num, value))
108 *initialized { ^ccinit }
109 *responders { ^ccnumr.select(_.notNil).flat ++ ccr }
112 if(this.initialized.not,{ this.init });
113 if((temp = resp.matchEvent.ctlnum).isNumber) {
114 ccnumr[temp] = ccnumr[temp].add(resp);
121 if((temp = resp.matchEvent.ctlnum).isNumber) {
122 ccnumr[temp].remove(resp)
128 if(MIDIClient.initialized.not,{ MIDIIn.connectAll });
131 ccnumr = Array.newClear(128);
132 MIDIIn.addFuncTo(\control, { arg src,chan,num,val;
133 // first try cc num specific
134 // then try non-specific (matches any cc )
135 [ccnumr[num], ccr].any({ |stack|
136 stack.notNil and: {stack.any({ |r| r.respond(src,chan,num,val) })}
142 oneShot = CCResponder({ |src,chan,num,value|
143 this.matchEvent_(MIDIEvent(nil,src,chan,num,nil));
145 },nil,nil,nil,nil,true,true)
148 matchEvent_ { |midiEvent|
149 // if ctlnum changes from non-number to number, or vice versa,
150 // this responder is going to move between ccr and ccnumr
151 if(matchEvent.notNil and:
152 { matchEvent.ctlnum.isNumber !== midiEvent.ctlnum.isNumber })
155 matchEvent = midiEvent;
156 this.class.add(this);
158 matchEvent = midiEvent;
163 TouchResponder : MIDIResponder {
164 classvar <touchinit = false,<touchr;
166 *new { arg function, src, chan, value, install=true,swallowEvent=false;
167 ^super.new.function_(function).swallowEvent_(swallowEvent)
168 .matchEvent_(MIDIEvent(nil, src, chan, nil, value))
172 if(MIDIClient.initialized.not,{ MIDIIn.connectAll });
175 MIDIIn.addFuncTo(\touch, { arg src, chan, val;
177 r.respond(src,chan,nil,val)
181 value { arg src,chan,num,val;
183 function.value(src,chan,val);
185 *initialized { ^touchinit }
186 *responders { ^touchr }
189 touchr = touchr.add(resp);
196 oneShot = this.class.new({ |src,chan,num,value|
197 this.matchEvent_(MIDIEvent(nil,src,chan,nil,nil));
199 },nil,nil,nil,true,true)
203 BendResponder : TouchResponder {
204 classvar <bendinit = false,<bendr;
207 if(MIDIClient.initialized.not,{ MIDIIn.connectAll });
210 MIDIIn.addFuncTo(\bend, { arg src, chan, val;
212 r.respond(src,chan,nil,val)
216 *initialized { ^bendinit }
217 *responders { ^bendr }
220 bendr = bendr.add(resp);
229 the note on function would return an object which is stored.
230 when a matching note off event occurs, the object is passed into the note off function
236 ProgramChangeResponder : MIDIResponder {
237 classvar <pcinit = false,<pcr;
239 *new { arg function, src, chan, value, install=true;
240 ^super.new.function_(function)
241 .matchEvent_(MIDIEvent(nil, src.asMIDIInPortUID, chan, nil, value))
245 if(MIDIClient.initialized.not,{ MIDIIn.connectAll });
248 MIDIIn.addFuncTo(\program, { arg src, chan, val;
250 if(r.matchEvent.match(src, chan, nil, val))
251 { r.value(src,chan,val) };
255 value { arg src,chan,val;
256 function.value(src,chan,val);
258 *initialized { ^pcinit }