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.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)
180 asBus { ^if(this.isNeutral) { nil } { bus } }
181 asNodeArg { ^if(this.isNeutral) { nil } { this.busArg } }
190 play { | out, numChannels, group, multi=false, vol, fadeTime, addAction |
191 var bundle = MixedBundle.new;
192 if(this.homeServer.serverRunning.not) {
193 ("server not running:" + this.homeServer).warn;
196 this.playToBundle(bundle, out.asControlInput, numChannels, group, multi, vol, fadeTime, addAction);
197 // homeServer: multi client support: monitor only locally
198 bundle.schedSend(this.homeServer, this.clock ? TempoClock.default, this.quant)
201 playN { | outs, amps, ins, vol, fadeTime, group, addAction |
202 var bundle = MixedBundle.new;
203 if(this.homeServer.serverRunning.not) {
204 ("server not running:" + this.homeServer).warn;
207 this.playNToBundle(bundle, outs.asControlInput, amps, ins, vol, fadeTime, group, addAction);
208 bundle.schedSend(this.homeServer, this.clock ? TempoClock.default, this.quant)
214 vol { ^if(monitor.isNil) { 1.0 } { monitor.vol } }
215 vol_ { arg val; this.initMonitor(val) }
217 monitorIndex { ^if(monitor.isNil) { nil } { monitor.out } }
218 monitorGroup { ^if(monitor.isNil) { nil } { monitor.group } }
220 initMonitor { | vol |
221 if(this.rate !== 'audio') { Error("can only monitor audio proxy").throw };
222 if(monitor.isNil) { monitor = Monitor.new };
223 if (vol.notNil) { monitor.vol_(vol) };
227 stop { | fadeTime = 0.1, reset = false |
228 monitor.stop(fadeTime);
229 if(reset) { monitor = nil };
232 scope { | bufsize = 4096, zoom |
233 if(this.isNeutral.not) { ^bus.scope(bufsize, zoom) }
236 record { | path, headerFormat = "aiff", sampleFormat = "int16", numChannels |
238 if(server.serverRunning.not) { "server not running".inform; ^nil };
239 rec = RecNodeProxy.newFrom(this, numChannels);
240 rec.open(path, headerFormat, sampleFormat);
250 playToBundle { | bundle, out, numChannels,
251 group, multi=false, vol, fadeTime, addAction |
252 this.newMonitorToBundle(bundle, numChannels);
253 group = group ?? { if(parentGroup.isPlaying) { parentGroup } { this.homeServer.asGroup } };
254 monitor.usedPlayN = false;
255 monitor.playToBundle(bundle, bus.index, bus.numChannels, out, numChannels, group,
256 multi, vol, fadeTime, addAction);
259 playNToBundle { | bundle, outs, amps, ins, vol, fadeTime, group, addAction |
260 this.newMonitorToBundle(bundle); // todo: numChannels
261 monitor.usedPlayN = true;
262 group = group ?? { if(parentGroup.isPlaying) { parentGroup } { this.homeServer.asGroup } };
263 monitor.playNBusToBundle(bundle, outs, amps, ins, bus, vol, fadeTime, group, addAction);
267 newMonitorToBundle { | bundle, numChannels |
268 this.initBus(\audio, numChannels);
271 if(this.isPlaying.not) { this.wakeUpToBundle(bundle) };
277 // netwrk node proxy support
280 homeServer { ^server }
283 stream << this.class.name << "." << bus.rate << "("
284 << server << ", " << bus.numChannels <<")";