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