| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 
 | class:: Group
summary:: Client-side representation of a group node on the server
categories:: Server>Nodes, Server>Abstractions
description::
A Group is the client-side representation of a group node on the server, which is a collection of other nodes organized as a linked list.
The Nodes within a Group may be controlled together, and may be both link::Classes/Synth::s and other Groups.
Groups are thus useful for controlling a number of nodes at once, and when used as targets can be very helpful in controlling order of execution. (See link::Guides/Order-of-execution:: for more details on this topic).
For more on the crucial distinction between client objects and server nodes, see link::Guides/ClientVsServer::. For information on creating nodes without using objects, see link::Guides/NodeMessaging::.
N.B. Group is a subclass of Node, and thus many of its most useful and important methods are documented in the link::Classes/Node:: help file. Please refer to it for more information.
subsection:: RootNode and the default group
When a Server is booted there is a top level group with an ID of zero that defines the root of the tree. This is represented by a subclass of Group: link::Classes/RootNode::.
If the Server was booted from within SCLang (as opposed to from the command line) then a default_group with an ID of 1 will be automatically created. This group is the default enclosing group for all Nodes, i.e. it's what you get if you don't specify.
In general you should create new Nodes within the default group of a Server rather than in its RootNode.
See link::Classes/Server::, link::Reference/default_group:: and link::Classes/RootNode:: for more detail.
subsection:: Bundling
Some of the methods below have two versions: a regular one which sends its corresponding message to the server immediately, and one which returns the message in an link::Classes/Array:: so that it can be added to a bundle.
It is also possible to capture the messages generated by the regular methods using Server's automated bundling capabilities. See link::Classes/Server:: and link::Guides/Bundled-Messages:: for more detail.
classmethods::
private:: creationCmd
subsection:: Creation with Immediate Instantiation on the Server
method:: new
Create and return a Group.
argument:: target
A target for this Group. If target is not a Group or Synth, it will be converted as follows: If it is a Server, it will be converted to the default_group of that server. If it is nil, to the default_group of the default Server.
argument:: addAction
one of the following Symbols:
table::
## \addToHead || (the default) add at the head of the group specified by target
## \addToTail || add at the tail of the group specified by target
## \addAfter || add immediately after target in its server's node order
## \addBefore || add immediately before target in its server's node order
## \addReplace || replace target and take its place in its server's node order
::
Note: A Synth is not a valid target for \addToHead and \addToTail.
discussion::
code::
s.boot;
g = Group.new; // add a Group at the head of the default Server's default group
h = Group.new(g, \addAfter);
s.queryAllNodes; // note the Group within the default group (ID 1)
g.free; h.free;
::
subsection:: Convenience methods for add actions
The following convenience methods correspond to the add actions above:
method:: after
Create and return a Group and add it immediately after aNode.
method:: before
Create and return a Group and add it immediately before aNode.
method:: head
Create and return a Group. If aGroup is a Group add it at the head of that group. If it is a Server, add it at the head of the default_group of that server. If it is nil, add it at the head of the default_group of the default Server.
method:: tail
Create and return a Group. If aGroup is a Group add it at the tail of that group. If it is a Server, add it at the tail of the default_group of that server. If it is nil, add it at the tail of the default_group of the default Server.
method:: replace
Create and return a Group and use it to replace nodeToReplace, taking its place in its server's node order.
subsection:: Creation without Instantiation on the Server
For use in message bundles it is also possible to create a Group object in the client app without immediately creating a group node on the server. Once done one can call methods which create messages to add to a bundle, which when sent to the server will instantiate the group or perform other operations. (See strong::Control::, below.)
method:: basicNew
Create and return a Group object without creating a group node on the server. (This method is inherited from Node and is documented here only for convenience.)
argument:: server
An optional instance of Server. If nil this will default to the default Server.
argument:: nodeID
An optional node ID number. If not supplied one will be generated by the Server's NodeIDAllocator. Normally you should not need to supply an ID.
discussion::
code::
s.boot;
g = Group.basicNew(s); // Create without sending
s.sendBundle(nil, g.newMsg;); // Now send a message; create at the head of s' default group
s.queryAllNodes;
g.free;
::
After creation, use instance methods code::newMsg, addToHeadMsg, addToTailMsg, addBeforeMsg, addAfterMsg, addReplaceMsg:: to instantiate this synth on the server. See link::#instancemethods#Instance Methods:: below.
instancemethods::
subsection:: Creation without Instantiation on the Server
Use class method code::basicNew:: to create a Synth without instantiating it on the server. Then use the following instance methods:
method:: newMsg
Returns a message of the type g_new which can be bundled. When sent to the server this message will instantiate this group. If target is nil, it will default to the default_group of the Server specified in *basicNew when this Group was created. The default addAction is \addToHead. (See *new above for details of addActions.
method:: addToHeadMsg
Returns a message of the type g_new which can be bundled. When sent to the server this message will instantiate this group. If aGroup is a Group it will be added at the head of that group. If it is nil, it will be added at the head of the default_group of this Group's server (as specified when *basicNew was called).
method:: addToTailMsg
Returns a message of the type g_new which can be bundled. When sent to the server this message will instantiate this group. If aGroup is a Group it will be added at the tail of that group. If it is nil, it will be added at the tail of the default_group of this Group's server (as specified when *basicNew was called).
method:: addBeforeMsg
Returns a message of the type g_new which can be bundled. When sent to the server this message will instantiate this group, immediately before aNode.
method:: addAfterMsg
Returns a message of the type g_new which can be bundled. When sent to the server this message will instantiate this group, immediately after aNode.
method:: addReplaceMsg
Returns a message of the type g_new which can be bundled. When sent to the server this message will instantiate this group, replacing nodeToReplace in the server's node order.
subsection:: Control and Introspection
For further methods of controlling Groups (set, map, etc.), see the link::Classes/Node:: help file.
method:: moveNodeToHead, moveNodeToHeadMsg
Move aNode to the head of this group
method:: moveNodeToTail, moveNodeToTailMsg
Move aNode to the tail of this group
method:: freeAll, freeAllMsg
Free all the nodes in this group, but do not free this group itself.
method:: deepFree, deepFreeMsg
Free all Synths in the group, and all Synths in any enclosed groups, but do not free this group or any of its enclosed groups.
method:: dumpTree
Post a representation of this group's node subtree. (Sends a message of the type g_dumpTree.) If code::postControls:: is true, then the current Control (arg) values for any synths contained in this group will be posted as well. The default is false.
method:: queryTree
note:: not working yet ::
Queries the server for a message describing this group's node subtree. (Sends a message of the type g_queryTree.) This reply is passed to the action function as an argument. See g_queryTree in Server-Command-Reference or the example below for information on how the reply is structured.
Examples::
code::
(
s = Server.default; // just to be sure
s.boot;
)
(
SynthDef("help-Group-moto-rev", { arg out=0,freq=100,ffreq=120;
	var x;
	x = RLPF.ar(LFPulse.ar(SinOsc.kr(0.2, 0, 10, freq), [0,0.1], 0.1),
		ffreq, 0.1).clip2(0.4);
	Out.ar(out, x);
}).add;
SynthDef("help-Group-wah", { arg out, rate = 1.5, cfreq = 1400, mfreq = 1200, rq=0.1;
	var zin, zout, q;
	zin = In.ar(out, 2);
	cfreq = Lag3.kr(cfreq, 0.1);
	mfreq = Lag3.kr(mfreq, 0.1);
	q   = Ramp.kr(rq, 0.1);
	zout = RLPF.ar(zin, LFNoise1.kr(rate, mfreq, cfreq), q, 10).distort
		* 0.15;
	// replace the incoming bus with the effected version
	ReplaceOut.ar( out , zout );
}).add;
)
g = Group.new;
(
l = Array.fill(3,{
	// random freq for each synth, added to g at the head
	Synth("help-Group-moto-rev",["out",0,"freq",rrand(10,120)],g,\addToHead);
});
)
// set all controls that match "ffreq" in all nodes in g to 90
g.set("ffreq",300);
g.set("freq",80);
// since we stored the Synths in an Array, we can also control them individually
(
r = Routine({
	inf.do({
		l.do({ arg node;
			node.set("freq",rrand(10,120));
			1.0.wait;
		});
	})
});
r.play;
)
// g is in a group too. Since we didn't specify it's the default group (ID 1) of the default Server
g.group.inspect;
// asking a wah to go order-of-execution after g, in the same group as g.
x = Synth.after(g,"help-Group-wah",["out",0]);
// now dump my tree to confirm
g.dumpTree;
x.free;
// free all nodes in g, but not g itself
g.freeAll;
// don't forget the Routine is still running...
r.stop;
// oh, and set l to nil so the Synths and Array can be garbage collected
l = nil;
// and i'm still on the server, its just my children that were freed
g.query;
// don't need the individual synth objects this time
(
3.do({
	// random freq for each synth, added to g at the head
	Synth("help-Group-moto-rev",["out",0,"freq",rrand(10,1200)],g,\addToHead);
});
)
// now query my tree and post a graph of it (duplicates dumpTree)
// msg format is ['/g_querytree.reply', node1-ID, numChildren, defName, child1-ID, numChildren, ...]
//(
//g.queryTree({|msg|
//	var i = 1, tabs = 0, dumpFunc;
//	("NODE TREE Group" + msg[1]).postln;
//	if(msg[2] > 0, {
//		dumpFunc = {|numChildren|
//			tabs = tabs + 1;
//			numChildren.do({
//				i = i + 3;
//				tabs.do({ "   ".post });
//				msg[i].post;
//				(" " ++ msg[i + 2]).postln;
//				if(msg[i + 1] > 0, { dumpFunc.value(msg[i + 1]) });
//			});
//			tabs = tabs - 1;
//		};
//		dumpFunc.value(msg[2]);
//	});
//});
//)
// kill me and my children
g.free;
// see, I'm gone
g.query;
::
 |