scide: LookupDialog - redo lookup on classes after partial lookup
[supercollider.git] / SCClassLibrary / Common / Control / Bus.sc
blobade7ddbd75e81bbc0d204aa59c3eedfda9e748a8
1 Bus {
3         var <rate,<index,<numChannels,<server;
4         var mapSymbol;
6         *control { arg server,numChannels=1;
7                 var alloc;
8                 server = server ? Server.default;
9                 alloc = server.controlBusAllocator.alloc(numChannels);
10                 if(alloc.isNil,{
11                         error("Meta_Bus:control: failed to get a control bus allocated."
12                                 + "numChannels:" + numChannels + "server:" + server.name);
13                         ^nil
14                 });
15                 ^this.new(\control,alloc,numChannels,server)
16         }
17         *audio { arg server,numChannels=1;
18                 var alloc;
19                 server = server ? Server.default;
20                 alloc = server.audioBusAllocator.alloc(numChannels);
21                 if(alloc.isNil,{
22                         error("Meta_Bus:audio: failed to get an audio bus allocated."
23                         + "numChannels:" + numChannels + "server:" + server.name);
24                         ^nil
25                 });
26                 ^this.new(\audio,alloc,numChannels,server)
27         }
28         *alloc { arg rate,server,numChannels=1;
29                 ^this.perform(rate ? \audio,server,numChannels);
30         }
32         *new { arg rate=\audio,index=0,numChannels=2,server;
33                 ^super.newCopyArgs(rate,index,numChannels,server ? Server.default)
34         }
36         isSettable {
37                 ^rate != \audio
38         }
40         set { arg ... values; // shouldn't be larger than this.numChannels
41                 if(this.isSettable, {
42                         server.sendBundle(nil,(["/c_set"]
43                                 ++ values.collect({ arg v,i; [index + i ,v] }).flat));
44                 }, {error("Cannot set an audio rate bus")});
45         }
46         setMsg { arg ... values;
47                 if(this.isSettable, {
48                         ^["/c_set"]
49                                 ++ values.collect({ arg v,i; [index + i ,v] }).flat
50                 }, {error("Cannot set an audio rate bus"); ^nil});
51         }
53         setn { arg values;
54                 // could throw an error if values.size > numChannels
55                 if(this.isSettable, {
56                         server.sendBundle(nil,
57                                 ["/c_setn",index,values.size] ++ values);
58                 }, {error("Cannot set an audio rate bus")});
59         }
60         setnMsg { arg values;
61                 if(this.isSettable, {
62                         ^["/c_setn",index,values.size] ++ values;
63                 }, {error("Cannot set an audio rate bus"); ^nil});
64         }
65         setAt { |offset ... values|
66                 // shouldn't be larger than this.numChannels - offset
67                 if(this.isSettable, {
68                         server.sendBundle(nil,(["/c_set"]
69                                 ++ values.collect({ arg v,i; [index + offset + i ,v] }).flat));
70                 }, {error("Cannot set an audio rate bus")});
71         }
72         setnAt { |offset, values|
73                 // could throw an error if values.size > numChannels
74                 if(this.isSettable, {
75                         server.sendBundle(nil,
76                                 ["/c_setn",index + offset, values.size] ++ values);
77                 }, {error("Cannot set an audio rate bus")});
78         }
79         setPairs { | ... pairs|
80                 if(this.isSettable, {
81                         server.sendBundle(nil,(["/c_set"]
82                                 ++ pairs.clump(2).collect({ arg pair; [pair[0] + index, pair[1]] }).flat));
83                 }, {error("Cannot set an audio rate bus")});
84         }
86         get { arg action;
87                 if(numChannels == 1, {
88                         action = action ? { |vals| "Bus % index: % value: %.\n".postf(rate, index, vals); };
89                         OSCpathResponder(server.addr,['/c_set',index], { arg time, r, msg;
90                                 action.value(msg.at(2)); r.remove }).add;
91                         server.listSendMsg(["/c_get",index]);
92                 }, {this.getn(action)});
93         }
95         getn { arg count, action;
96                 action = action ? { |vals| "Bus % index: % values: %.\n".postf(rate, index, vals); };
97                 OSCpathResponder(server.addr,['/c_setn',index],{arg time, r, msg;
98                         action.value(msg.copyToEnd(3)); r.remove } ).add;
99                 server.listSendMsg(this.getnMsg(count));
100         }
101         getMsg {
102                 ^["/c_get",index];
103         }
104         getnMsg { arg count;
105                 ^["/c_getn",index, count ? numChannels];
106         }
108         getSynchronous {
109                 if (not(this.isSettable)) {
110                         Error("Bus-getSynchronous only works for control-rate busses").throw;
111                 } {
112                         ^server.getControlBusValue(index);
113                 }
114         }
116         getnSynchronous {|count|
117                 if (not(this.isSettable)) {
118                         Error("Bus-getnSynchronous only works for control-rate busses").throw;
119                 } {
120                         ^server.getControlBusValues(index, count ? numChannels);
121                 }
122         }
124         setSynchronous { |... values|
125                 if (not(this.isSettable)) {
126                         Error("Bus-setSynchronous only works for control-rate busses").throw;
127                 } {
128                         if (values.size == 1) {
129                                 server.setControlBusValue(index, values[0])
130                         } {
131                                 server.setControlBusValues(index, values)
132                         }
133                 }
134         }
136         setnSynchronous {|values|
137                 if (not(this.isSettable)) {
138                         Error("Bus-setnSynchronous only works for control-rate busses").throw;
139                 } {
140                         server.setControlBusValues(index, values)
141                 }
142         }
144         fill { arg value,numChans;
145                 // could throw an error if numChans > numChannels
146                 server.sendBundle(nil,
147                         ["/c_fill",index,numChans,value]);
148         }
150         fillMsg { arg value;
151                 ^["/c_fill",index,numChannels,value];
152         }
155         free {
156                 if(index.isNil,{ (this.asString + " has already been freed").warn; ^this });
157                 if(rate == \audio,{
158                         server.audioBusAllocator.free(index);
159                 },{
160                         server.controlBusAllocator.free(index);
161                 });
162                 index = nil;
163                 numChannels = nil;
164                 mapSymbol = nil;
165         }
167         // allow reallocation
169         alloc {
170                 if(rate === 'audio', {
171                         index = server.audioBusAllocator.alloc(numChannels);
172                 }, {
173                         index = server.controlBusAllocator.alloc(numChannels);
174                 });
175                 mapSymbol = nil;
176         }
178         realloc {
179                 var r, n;
180                 if(index.notNil, {
181                         r = rate; n = numChannels;
182                         this.free;
183                         rate = r; numChannels = n;
184                         this.alloc;
185                 })
186         }
188         // alternate syntaxes
189         setAll { arg value;
190                 this.fill(value,numChannels);
191         }
193         value_ { arg value;
194                 this.fill(value,numChannels);
195         }
197         printOn { arg stream;
198                 stream << this.class.name << "(" <<*
199                         [rate, index, numChannels, server]  <<")"
200         }
202         storeOn { arg stream;
203                 stream << this.class.name << "(" <<*
204                         [rate.asCompileString, index, numChannels, server.asCompileString]  <<")"
205         }
206         == { arg aBus;
207                 ^this.compareObject(aBus, #[\index, \numChannels, \rate, \server])
208         }
209         hash {
210                 ^this.instVarHash(#[\index, \numChannels, \rate, \server])
211         }
213         isAudioOut { // audio interface
214                 ^(rate === \audio and: {index < server.options.firstPrivateBus})
215         }
217         ar { |numChannels=(this.numChannels), offset=0|
218                 if(rate == \audio,{
219                         ^In.ar(index + offset, numChannels)
220                 },{
221                         //"Bus converting control to audio rate".inform;
222                         ^K2A.ar( In.kr(index + offset, numChannels) )
223                 })
224         }
225         kr { |numChannels=(this.numChannels), offset=0|
226                 if(rate == \audio,{
227                         ^A2K.kr( In.ar(index + offset, numChannels) )
228                 },{
229                         ^In.kr(index + offset, numChannels)
230                 })
231         }
233         play { arg target=0, outbus, fadeTime, addAction=\addToTail;
234                 if(this.isAudioOut.not,{ // returns a Synth
235                         ^{ this.ar }.play(target, outbus, fadeTime, addAction);
236                 });
237         }
239         asUGenInput { ^this.index }
240         asControlInput { ^this.index }
242         asMap {
243                 ^mapSymbol ?? {
244                         if(index.isNil) { MethodError("bus not allocated.", this).throw };
245                         mapSymbol = if(rate == \control) { "c" } { "a" };
246                         mapSymbol = (mapSymbol ++ index).asSymbol;
247                 }
248         }
250         // added by nescivi; gets a subbus from another bus
252         *newFrom { |bus, offset, numChannels=1|
253                 if ( offset > bus.numChannels or: {numChannels + offset >
254                         bus.numChannels} )
255                 {
256                         Error( "Bus:newFrom tried to reach outside the channel range of
257 %".format( bus )).throw
258                 };
259                 ^Bus.new( bus.rate, bus.index + offset, numChannels);
260         }
262         subBus{|offset, numChannels=1|
263                 ^Bus.newFrom( this, offset, numChannels );
264         }