1 BusPlug : AbstractFunction {
4 var <>monitor, <>parentGroup; // if nil, uses default group
5 var busArg; // cache for "/s_new" bus arg
8 classvar <>defaultNumAudio=2, <>defaultNumControl=1;
12 ^super.newCopyArgs(server ? Server.default);
17 ^this.new(bus.server).bus_(bus)
20 *audio { | server, numChannels |
21 ^this.new(server).defineBus(\audio, numChannels)
24 *control { | server, numChannels |
25 ^this.new(server).defineBus(\control, numChannels)
41 rate { ^if(bus.isNil) { \scalar } { bus.rate } }
42 numChannels { ^if(bus.isNil) { nil } { bus.numChannels } }
43 index { ^if(bus.isNil) { nil } { bus.index } }
46 ^bus.isNil or: { bus.index.isNil and: { bus.numChannels.isNil } }
54 ^this.index.notNil and: { server.serverRunning }
57 prepareOutput { } // see subclass
60 ar { | numChannels, offset = 0 |
62 this.defineBus(\audio, numChannels)
65 ^InBus.ar(bus, numChannels ? bus.numChannels, offset)
68 kr { | numChannels, offset = 0 |
70 this.defineBus(\control, numChannels)
73 ^InBus.kr(bus, numChannels ? bus.numChannels, offset)
77 embedInStream { | inval | // for now, force multichannel expansion in streams early.
78 ^this.asControlInput.embedInStream(inval);
82 if(this.isPlaying.not) {
83 if(this.isNeutral) { this.defineBus(\control, 1) };
99 if(UGen.buildSynthDef.isNil) { ^this }; // only return when in ugen graph.
100 something !? { n = something.numChannels };
101 ^if(something.respondsTo(\rate) and: { something.rate == 'audio'}) { this.ar(n) } { this.kr(n) }
104 composeUnaryOp { | aSelector |
105 ^UnaryOpPlug.new(aSelector, this)
107 composeBinaryOp { | aSelector, something |
108 ^BinaryOpPlug.new(aSelector, this, something)
110 reverseComposeBinaryOp { | aSelector, something |
111 ^BinaryOpPlug.new(aSelector, something, this)
113 composeNAryOp { |aSelector, anArgList|
114 ^thisMethod.notYetImplemented
115 //^NAryOpPlug.new(aSelector, [this]++anArgList) // nary op ugens are not yet implemented
121 // bus initialization
127 busLoaded = bus.server.serverRunning;
130 // returns false if failed
131 initBus { | rate, numChannels |
132 if(rate.isNil or: { rate === 'scalar' }) { ^true }; // this is no problem
134 this.defineBus(rate, numChannels);
137 numChannels = numChannels ? this.numChannels;
138 ^(bus.rate === rate) and: { numChannels <= bus.numChannels }
142 defineBus { | rate = \audio, numChannels |
143 if(numChannels.isNil) {
144 numChannels = if(rate === \audio) {
145 this.class.defaultNumAudio
147 this.class.defaultNumControl }
149 this.bus = Bus.alloc(rate, server, numChannels);
155 if(bus.rate === \control) { bus.setAll(0) }; // clean up
163 busArg { ^busArg ?? { this.makeBusArg } }
166 var index, numChannels, prefix;
167 if(bus.isNil) { ^busArg = "" }; // still neutral
168 prefix = if(this.rate == \audio) { "\a" } { "\c" };
170 numChannels = this.numChannels;
171 ^busArg = if(numChannels == 1) {
174 { |i| prefix ++ (index + i) }.dup(numChannels)
184 asBus { ^if(this.isNeutral) { nil } { bus } }
185 asNodeArg { ^if(this.isNeutral) { nil } { this.busArg } }
194 play { | out, numChannels, group, multi=false, vol, fadeTime, addAction |
195 var bundle = MixedBundle.new;
196 if(this.homeServer.serverRunning.not) {
197 ("server not running:" + this.homeServer).warn;
200 this.playToBundle(bundle, out.asControlInput, numChannels, group, multi, vol, fadeTime, addAction);
201 // homeServer: multi client support: monitor only locally
202 bundle.schedSend(this.homeServer, this.clock ? TempoClock.default, this.quant)
205 playN { | outs, amps, ins, vol, fadeTime, group, addAction |
206 var bundle = MixedBundle.new;
207 if(this.homeServer.serverRunning.not) {
208 ("server not running:" + this.homeServer).warn;
211 this.playNToBundle(bundle, outs.asControlInput, amps, ins, vol, fadeTime, group, addAction);
212 bundle.schedSend(this.homeServer, this.clock ? TempoClock.default, this.quant)
218 vol { ^if(monitor.isNil) { 1.0 } { monitor.vol } }
219 vol_ { arg val; this.initMonitor(val) }
221 monitorIndex { ^if(monitor.isNil) { nil } { monitor.out } }
222 monitorGroup { ^if(monitor.isNil) { nil } { monitor.group } }
224 initMonitor { | vol |
225 if(this.rate !== 'audio') { Error("can only monitor audio proxy").throw };
226 if(monitor.isNil) { monitor = Monitor.new };
227 if (vol.notNil) { monitor.vol_(vol) };
231 stop { | fadeTime = 0.1, reset = false |
232 monitor.stop(fadeTime);
233 if(reset) { monitor = nil };
236 scope { | bufsize = 4096, zoom |
237 if(this.isNeutral.not) { ^bus.scope(bufsize, zoom) }
244 playToBundle { | bundle, out, numChannels,
245 group, multi=false, vol, fadeTime, addAction |
246 this.newMonitorToBundle(bundle, numChannels);
247 group = group ?? { if(parentGroup.isPlaying) { parentGroup } { this.homeServer.asGroup } };
248 monitor.usedPlayN = false;
249 monitor.playToBundle(bundle, bus.index, bus.numChannels, out, numChannels, group,
250 multi, vol, fadeTime, addAction);
253 playNToBundle { | bundle, outs, amps, ins, vol, fadeTime, group, addAction |
254 this.newMonitorToBundle(bundle); // todo: numChannels
255 monitor.usedPlayN = true;
256 group = group ?? { if(parentGroup.isPlaying) { parentGroup } { this.homeServer.asGroup } };
257 monitor.playNBusToBundle(bundle, outs, amps, ins, bus, vol, fadeTime, group, addAction);
261 newMonitorToBundle { | bundle, numChannels |
262 this.initBus(\audio, numChannels);
265 if(this.isPlaying.not) { this.wakeUpToBundle(bundle) };
271 // netwrk node proxy support
274 homeServer { ^server }
277 stream << this.class.name << "." << bus.rate << "("
278 << server << ", " << bus.numChannels <<")";