1 /*
2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21
22 #include "SC_Group.h"
23 #include "SC_GraphDef.h"
24 #include "Hash.h"
25 #include "sc_msg_iter.h"
26 #include <string.h>
27 #include <stdio.h>
28 #include "SC_Prototypes.h"
29 #include "SC_Str4.h"
30 #include "SC_World.h"
31 #include "SC_WorldOptions.h"
32 #include "SC_Errors.h"
33 #include "scsynthsend.h"
34
35 NodeDef gGroupNodeDef;
36
Group_Dtor(Group * inGroup)37 void Group_Dtor(Group* inGroup) {
38 Group_DeleteAll(inGroup);
39 inGroup->mNode.mWorld->mNumGroups--;
40 Node_Dtor(&inGroup->mNode);
41 }
42
GroupNodeDef_Init()43 void GroupNodeDef_Init() {
44 str4cpy(gGroupNodeDef.mName, "group");
45 gGroupNodeDef.mHash = Hash(gGroupNodeDef.mName);
46 gGroupNodeDef.mAllocSize = sizeof(Group);
47 }
48
Group_New(World * inWorld,int32 inID,Group ** outGroup)49 int Group_New(World* inWorld, int32 inID, Group** outGroup) {
50 Group* group;
51 int err = Node_New(inWorld, &gGroupNodeDef, inID, (Node**)&group);
52 if (err)
53 return err;
54
55 group->mNode.mCalcFunc = (NodeCalcFunc)&Group_Calc;
56 group->mNode.mIsGroup = true;
57 group->mHead = nullptr;
58 group->mTail = nullptr;
59 inWorld->mNumGroups++;
60 *outGroup = group;
61
62 return kSCErr_None;
63 }
64
Group_Calc(Group * inGroup)65 void Group_Calc(Group* inGroup) {
66 Node* child = inGroup->mHead;
67 while (child) {
68 Node* next = child->mNext;
69 (*child->mCalcFunc)(child);
70 child = next;
71 }
72 }
73
Group_CalcTrace(Group * inGroup)74 void Group_CalcTrace(Group* inGroup) {
75 scprintf("TRACE Group %d\n", inGroup->mNode.mID);
76 Node* child = inGroup->mHead;
77 while (child) {
78 Node* next = child->mNext;
79 scprintf(" %d %s\n", child->mID, (char*)child->mDef->mName);
80 (*child->mCalcFunc)(child);
81 child = next;
82 }
83 inGroup->mNode.mCalcFunc = (NodeCalcFunc)&Group_Calc;
84 }
85
Group_Trace(Group * inGroup)86 void Group_Trace(Group* inGroup) {
87 if (inGroup->mNode.mCalcFunc == (NodeCalcFunc)&Group_Calc) {
88 inGroup->mNode.mCalcFunc = (NodeCalcFunc)&Group_CalcTrace;
89 }
90 }
91
Group_DumpNodeTree(Group * inGroup)92 void Group_DumpNodeTree(Group* inGroup) {
93 static int tabCount = 0;
94 if (tabCount == 0)
95 scprintf("NODE TREE Group %d\n", inGroup->mNode.mID);
96 tabCount++;
97 Node* child = inGroup->mHead;
98 while (child) {
99 Node* next = child->mNext;
100 for (int i = 0; i < tabCount; i++)
101 scprintf(" "); // small 'tabs'
102 scprintf("%d %s\n", child->mID, (char*)child->mDef->mName);
103 if (child->mIsGroup) {
104 Group_DumpTree((Group*)child);
105 }
106 (*child->mCalcFunc)(child);
107 child = next;
108 }
109 tabCount--;
110 }
111
Group_DumpNodeTreeAndControls(Group * inGroup)112 void Group_DumpNodeTreeAndControls(Group* inGroup) {
113 static int tabCount = 0;
114 if (tabCount == 0)
115 scprintf("NODE TREE Group %d\n", inGroup->mNode.mID);
116 tabCount++;
117 Node* child = inGroup->mHead;
118 while (child) {
119 Node* next = child->mNext;
120 int i;
121 for (i = 0; i < tabCount; i++)
122 scprintf(" "); // small 'tabs'
123 scprintf("%d %s", child->mID, (char*)child->mDef->mName); // def will be 'group' if it's a group
124 if (child->mIsGroup) {
125 Group_DumpTreeAndControls((Group*)child);
126 } else {
127 Graph* childGraph = (Graph*)child;
128 int numControls = childGraph->mNumControls;
129 if (numControls > 0) {
130 scprintf("\n ");
131 for (i = 0; i < tabCount; i++)
132 scprintf(" ");
133 char** names;
134 names = new char*[numControls];
135
136 for (i = 0; i < numControls; i++) {
137 names[i] = nullptr;
138 }
139
140 // check the number of named controls and stash their names at the correct index
141 GraphDef* def = (GraphDef*)(child->mDef);
142 int numNamedControls = def->mNumParamSpecs;
143 for (i = 0; i < numNamedControls; i++) {
144 ParamSpec* paramSpec = def->mParamSpecs + i;
145 names[paramSpec->mIndex] = (char*)paramSpec->mName;
146 }
147
148 // now print the names and values in index order, checking for mappings
149 for (i = 0; i < numControls; i++) {
150 float* ptr = childGraph->mControls + i;
151
152 if (names[i]) {
153 scprintf(" %s: ", names[i]);
154 } else {
155 scprintf(" ", names[i]);
156 }
157 // the ptr in nMapControls should be the same as the control itself, if not, it's mapped.
158 if ((childGraph->mMapControls[i]) != ptr) {
159 int bus;
160 if (childGraph->mControlRates[i] == 2) {
161 bus = (childGraph->mMapControls[i]) - (child->mWorld->mAudioBus);
162 bus = (int)((float)bus / child->mWorld->mBufLength);
163 scprintf("a%d", bus);
164 } else {
165 bus = (childGraph->mMapControls[i]) - (child->mWorld->mControlBus);
166 scprintf("c%d", bus);
167 }
168 // scprintf("bus: %d\n", bus);
169 } else {
170 scprintf("%.14g", *ptr);
171 }
172 }
173
174 delete[] names;
175 }
176 }
177 scprintf("\n");
178 (*child->mCalcFunc)(child);
179 child = next;
180 }
181 tabCount--;
182 }
183
Group_CalcDumpTree(Group * inGroup)184 void Group_CalcDumpTree(Group* inGroup) {
185 Group_DumpNodeTree(inGroup);
186 inGroup->mNode.mCalcFunc = (NodeCalcFunc)&Group_Calc;
187 }
188
Group_DumpTree(Group * inGroup)189 void Group_DumpTree(Group* inGroup) {
190 if (inGroup->mNode.mCalcFunc == (NodeCalcFunc)&Group_Calc) {
191 inGroup->mNode.mCalcFunc = (NodeCalcFunc)&Group_CalcDumpTree;
192 }
193 }
194
Group_CalcDumpTreeAndControls(Group * inGroup)195 void Group_CalcDumpTreeAndControls(Group* inGroup) {
196 Group_DumpNodeTreeAndControls(inGroup);
197 inGroup->mNode.mCalcFunc = (NodeCalcFunc)&Group_Calc;
198 }
199
Group_DumpTreeAndControls(Group * inGroup)200 void Group_DumpTreeAndControls(Group* inGroup) {
201 if (inGroup->mNode.mCalcFunc == (NodeCalcFunc)&Group_Calc) {
202 inGroup->mNode.mCalcFunc = (NodeCalcFunc)&Group_CalcDumpTreeAndControls;
203 }
204 }
205
206 // count the children for this group (deep)
Group_CountNodeTags(Group * inGroup,int * count)207 void Group_CountNodeTags(Group* inGroup, int* count) {
208 Node* child = inGroup->mHead;
209 while (child) {
210 Node* next = child->mNext;
211 (*count) += 2;
212 if (child->mIsGroup) {
213 Group_CountNodeTags((Group*)child, count);
214 } else {
215 (*count)++;
216 } // for the defname
217 child = next;
218 }
219 }
220
221 // count the children for this group (deep)
Group_CountNodeAndControlTags(Group * inGroup,int * count,int * controlAndDefCount)222 void Group_CountNodeAndControlTags(Group* inGroup, int* count, int* controlAndDefCount) {
223 Node* child = inGroup->mHead;
224 while (child) {
225 Node* next = child->mNext;
226 (*count)++;
227 if (child->mIsGroup) {
228 Group_CountNodeAndControlTags((Group*)child, count, controlAndDefCount);
229 } else {
230 //(*controlCount) += ((Graph*)child)->mNumControls + ((GraphDef*)(child->mDef))->mNumParamSpecs + 1;
231 (*controlAndDefCount) +=
232 ((Graph*)child)->mNumControls * 2 + 2; // def, numControls, name or index and value for each
233 }
234 child = next;
235 }
236 }
237
Group_QueryTree(Group * inGroup,big_scpacket * packet)238 void Group_QueryTree(Group* inGroup, big_scpacket* packet) {
239 packet->addtag('i');
240 packet->addi(inGroup->mNode.mID);
241
242 // count the children for this group, but not their children (shallow)
243 int count = 0;
244 Node* child = inGroup->mHead;
245 while (child) {
246 Node* next = child->mNext;
247 count++;
248 child = next;
249 }
250
251 packet->addtag('i');
252 packet->addi(count); // numChildren; for a Group >= 0
253
254 // now iterate over the children
255 // id, numChildren, defname
256 child = inGroup->mHead;
257 while (child) {
258 Node* next = child->mNext;
259 if (child->mIsGroup) {
260 Group_QueryTree((Group*)child, packet);
261 } else {
262 packet->addtag('i'); // nodeID
263 packet->addtag('i'); // numChildren
264 packet->addtag('s'); // defname
265 packet->addi(child->mID);
266 packet->addi(-1);
267 packet->adds((char*)child->mDef->mName);
268 }
269 child = next;
270 }
271 }
272
Group_QueryTreeAndControls(Group * inGroup,big_scpacket * packet)273 void Group_QueryTreeAndControls(Group* inGroup, big_scpacket* packet) {
274 packet->addtag('i');
275 packet->addi(inGroup->mNode.mID);
276
277 // count the children for this group, but not their children (shallow)
278 int count = 0;
279 Node* child = inGroup->mHead;
280 while (child) {
281 Node* next = child->mNext;
282 count++;
283 child = next;
284 }
285
286 packet->addtag('i');
287 packet->addi(count);
288
289 // now iterate over the children
290 // id, numChildren, defname
291 child = inGroup->mHead;
292 while (child) {
293 Node* next = child->mNext;
294 if (child->mIsGroup) {
295 Group_QueryTreeAndControls((Group*)child, packet);
296 } else {
297 packet->addtag('i');
298 packet->addtag('i');
299 packet->addtag('s');
300 packet->addi(child->mID); // nodeID
301 packet->addi(-1); // numChildren
302 packet->adds((char*)child->mDef->mName); // defName
303
304 Graph* childGraph = (Graph*)child;
305 int numControls = childGraph->mNumControls;
306 packet->addtag('i');
307 packet->addi(numControls);
308
309 char** names;
310 names = new char*[numControls];
311 int i;
312 for (i = 0; i < numControls; i++) {
313 names[i] = nullptr;
314 }
315
316 // check the number of named controls and stash their names
317 GraphDef* def = (GraphDef*)(child->mDef);
318 int numNamedControls = def->mNumParamSpecs;
319 for (i = 0; i < numNamedControls; i++) {
320 ParamSpec* paramSpec = def->mParamSpecs + i;
321 names[paramSpec->mIndex] = (char*)paramSpec->mName;
322 }
323
324 // now add the names and values in index order, checking for mappings
325 for (i = 0; i < numControls; i++) {
326 float* ptr = childGraph->mControls + i;
327
328 if (names[i]) {
329 packet->addtag('s');
330 packet->adds(names[i]);
331 } else {
332 packet->addtag('i');
333 packet->addi(i);
334 }
335 // the ptr in nMapControls should be the same as the control itself, if not, it's mapped.
336 if ((childGraph->mMapControls[i]) != ptr) {
337 // it's mapped
338 int bus;
339 const size_t BUF_SIZE(10);
340 char buf[BUF_SIZE];
341 if (childGraph->mControlRates[i] == 2) {
342 bus = (childGraph->mMapControls[i]) - (child->mWorld->mAudioBus);
343 bus = (int)((float)bus / child->mWorld->mBufLength);
344 snprintf(buf, BUF_SIZE, "%c%d", 'a', bus);
345 } else {
346 bus = (childGraph->mMapControls[i]) - (child->mWorld->mControlBus);
347 snprintf(buf, BUF_SIZE, "%c%d", 'c', bus);
348 }
349 // scprintf("bus: %d\n", bus);
350 packet->addtag('s');
351 packet->adds(buf);
352 } else {
353 packet->addtag('f');
354 packet->addf(*ptr);
355 }
356 }
357
358 delete[] names;
359 }
360 child = next;
361 }
362 }
363
364
Group_DeleteAll(Group * inGroup)365 void Group_DeleteAll(Group* inGroup) {
366 Node* child = inGroup->mHead;
367 while (child) {
368 Node* next = child->mNext;
369 child->mPrev = child->mNext = nullptr;
370 child->mParent = nullptr;
371 Node_Delete(child);
372 child = next;
373 }
374 inGroup->mHead = inGroup->mTail = nullptr;
375 }
376
Group_DeepFreeGraphs(Group * inGroup)377 void Group_DeepFreeGraphs(Group* inGroup) {
378 Node* child = inGroup->mHead;
379 while (child) {
380 Node* next = child->mNext;
381 if (child->mIsGroup) {
382 Group_DeepFreeGraphs((Group*)child);
383 } else {
384 Node_Remove(child);
385 Node_Delete(child);
386 }
387 child = next;
388 }
389 }
390
Group_AddHead(Group * s,Node * child)391 void Group_AddHead(Group* s, Node* child) {
392 if (child->mID == 0)
393 return; // failed
394 child->mPrev = nullptr;
395 child->mNext = s->mHead;
396 if (s->mHead) {
397 s->mHead->mPrev = child;
398 s->mHead = child;
399 } else
400 s->mHead = s->mTail = child;
401 child->mParent = s;
402 }
403
Group_AddTail(Group * s,Node * child)404 void Group_AddTail(Group* s, Node* child) {
405 if (child->mID == 0)
406 return; // failed
407 child->mPrev = s->mTail;
408 child->mNext = nullptr;
409 if (s->mTail) {
410 s->mTail->mNext = child;
411 s->mTail = child;
412 } else
413 s->mHead = s->mTail = child;
414 child->mParent = s;
415 }
416
Group_Insert(Group * s,Node * child,int index)417 void Group_Insert(Group* s, Node* child, int index) {
418 if (child->mID == 0)
419 return; // failed
420 if (index <= 0)
421 Group_AddHead(s, child);
422 else {
423 Node* before = s->mHead;
424 for (int i = 0; i < index; ++i) {
425 before = before->mNext;
426 if (!before) {
427 Group_AddTail(s, child);
428 return;
429 }
430 }
431 Node_AddBefore(child, before);
432 }
433 }
434
Group_MapControl(Group * inGroup,uint32 inIndex,uint32 inBus)435 void Group_MapControl(Group* inGroup, uint32 inIndex, uint32 inBus) {
436 Node* child = inGroup->mHead;
437 while (child) {
438 Node* next = child->mNext;
439 Node_MapControl(child, inIndex, inBus);
440 child = next;
441 }
442 }
443
Group_MapControl(Group * inGroup,int32 inHash,int32 * inName,uint32 inIndex,uint32 inBus)444 void Group_MapControl(Group* inGroup, int32 inHash, int32* inName, uint32 inIndex, uint32 inBus) {
445 Node* child = inGroup->mHead;
446 while (child) {
447 Node* next = child->mNext;
448 Node_MapControl(child, inHash, inName, inIndex, inBus);
449 child = next;
450 }
451 }
452
Group_MapAudioControl(Group * inGroup,uint32 inIndex,uint32 inBus)453 void Group_MapAudioControl(Group* inGroup, uint32 inIndex, uint32 inBus) {
454 Node* child = inGroup->mHead;
455 while (child) {
456 Node* next = child->mNext;
457 Node_MapAudioControl(child, inIndex, inBus);
458 child = next;
459 }
460 }
461
Group_MapAudioControl(Group * inGroup,int32 inHash,int32 * inName,uint32 inIndex,uint32 inBus)462 void Group_MapAudioControl(Group* inGroup, int32 inHash, int32* inName, uint32 inIndex, uint32 inBus) {
463 Node* child = inGroup->mHead;
464 while (child) {
465 Node* next = child->mNext;
466 Node_MapAudioControl(child, inHash, inName, inIndex, inBus);
467 child = next;
468 }
469 }
Group_SetControl(Group * inGroup,uint32 inIndex,float inValue)470 void Group_SetControl(Group* inGroup, uint32 inIndex, float inValue) {
471 Node* child = inGroup->mHead;
472 while (child) {
473 Node* next = child->mNext;
474 Node_SetControl(child, inIndex, inValue);
475 child = next;
476 }
477 }
478
Group_SetControl(Group * inGroup,int32 inHash,int32 * inName,uint32 inIndex,float inValue)479 void Group_SetControl(Group* inGroup, int32 inHash, int32* inName, uint32 inIndex, float inValue) {
480 Node* child = inGroup->mHead;
481 while (child) {
482 Node* next = child->mNext;
483 Node_SetControl(child, inHash, inName, inIndex, inValue);
484 child = next;
485 }
486 }
487