common: prevent buffer overflow
[supercollider.git] / server / scsynth / SC_Group.cpp
blob7a6432b6bf4f47dbc83ed49b9557a92070ba7f32
1 /*
2 SuperCollider real time audio synthesis system
3 Copyright (c) 2002 James McCartney. All rights reserved.
4 http://www.audiosynth.com
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.
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.
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
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_Errors.h"
32 #include "scsynthsend.h"
34 NodeDef gGroupNodeDef;
36 void Group_Dtor(Group *inGroup)
38 Group_DeleteAll(inGroup);
39 inGroup->mNode.mWorld->mNumGroups--;
40 Node_Dtor(&inGroup->mNode);
43 void GroupNodeDef_Init()
45 str4cpy(gGroupNodeDef.mName, "group");
46 gGroupNodeDef.mHash = Hash(gGroupNodeDef.mName);
47 gGroupNodeDef.mAllocSize = sizeof(Group);
50 int Group_New(World *inWorld, int32 inID, Group** outGroup)
52 Group *group;
53 int err = Node_New(inWorld, &gGroupNodeDef, inID, (Node**)&group);
54 if (err) return err;
56 group->mNode.mCalcFunc = (NodeCalcFunc)&Group_Calc;
57 group->mNode.mIsGroup = true;
58 group->mHead = 0;
59 group->mTail = 0;
60 inWorld->mNumGroups++;
61 *outGroup = group;
63 return kSCErr_None;
66 void Group_Calc(Group *inGroup)
68 Node *child = inGroup->mHead;
69 while (child) {
70 Node *next = child->mNext;
71 (*child->mCalcFunc)(child);
72 child = next;
76 void Group_CalcTrace(Group *inGroup)
78 scprintf("TRACE Group %d\n", inGroup->mNode.mID);
79 Node *child = inGroup->mHead;
80 while (child) {
81 Node *next = child->mNext;
82 scprintf(" %d %s\n", child->mID, (char*)child->mDef->mName);
83 (*child->mCalcFunc)(child);
84 child = next;
86 inGroup->mNode.mCalcFunc = (NodeCalcFunc)&Group_Calc;
89 void Group_Trace(Group *inGroup)
91 if (inGroup->mNode.mCalcFunc == (NodeCalcFunc)&Group_Calc) {
92 inGroup->mNode.mCalcFunc = (NodeCalcFunc)&Group_CalcTrace;
96 void Group_DumpNodeTree(Group *inGroup)
98 static int tabCount = 0;
99 if(tabCount == 0) scprintf("NODE TREE Group %d\n", inGroup->mNode.mID);
100 tabCount++;
101 Node *child = inGroup->mHead;
102 while (child) {
103 Node *next = child->mNext;
104 for(int i = 0; i < tabCount; i ++) scprintf(" "); // small 'tabs'
105 scprintf("%d %s\n", child->mID, (char*)child->mDef->mName);
106 if (child->mIsGroup) {
107 Group_DumpTree((Group*)child);
109 (*child->mCalcFunc)(child);
110 child = next;
112 tabCount--;
115 void Group_DumpNodeTreeAndControls(Group *inGroup)
117 static int tabCount = 0;
118 if(tabCount == 0) scprintf("NODE TREE Group %d\n", inGroup->mNode.mID);
119 tabCount++;
120 Node *child = inGroup->mHead;
121 while (child) {
122 Node *next = child->mNext;
123 int i;
124 for(i = 0; i < tabCount; i ++) scprintf(" "); // small 'tabs'
125 scprintf("%d %s", child->mID, (char*)child->mDef->mName); // def will be 'group' if it's a group
126 if (child->mIsGroup) {
127 Group_DumpTreeAndControls((Group*)child);
128 } else {
129 Graph* childGraph = (Graph*)child;
130 int numControls = childGraph->mNumControls;
131 if(numControls > 0) {
132 scprintf("\n ");
133 for(i = 0; i < tabCount; i ++) scprintf(" ");
134 char **names;
135 names = new char*[numControls];
137 for(i = 0; i < numControls; i++){
138 names[i] = NULL;
141 // check the number of named controls and stash their names at the correct index
142 GraphDef* def = (GraphDef*)(child->mDef);
143 int numNamedControls = def->mNumParamSpecs;
144 for(i = 0; i < numNamedControls; i++){
145 ParamSpec *paramSpec = def->mParamSpecs + i;
146 names[paramSpec->mIndex] = (char*)paramSpec->mName;
149 // now print the names and values in index order, checking for mappings
150 for(i=0; i < numControls; i++){
151 float *ptr = childGraph->mControls + i;
153 if(names[i]){
154 scprintf(" %s: ", names[i]);
155 } else {
156 scprintf(" ", names[i]);
158 // the ptr in nMapControls should be the same as the control itself, if not, it's mapped.
159 if((childGraph->mMapControls[i]) != ptr){
160 int bus;
161 if(childGraph->mControlRates[i] == 2){
162 bus = (childGraph->mMapControls[i]) - (child->mWorld->mAudioBus);
163 bus = (int)((float)bus / child->mWorld->mBufLength);
164 scprintf("a%d", bus);
165 } else {
166 bus = (childGraph->mMapControls[i]) - (child->mWorld->mControlBus);
167 scprintf("c%d", bus);
169 //scprintf("bus: %d\n", bus);
170 } else {
171 scprintf("%.14g", *ptr);
176 scprintf("\n");
177 (*child->mCalcFunc)(child);
178 child = next;
180 tabCount--;
183 void Group_CalcDumpTree(Group *inGroup)
185 Group_DumpNodeTree(inGroup);
186 inGroup->mNode.mCalcFunc = (NodeCalcFunc)&Group_Calc;
189 void Group_DumpTree(Group* inGroup)
191 if (inGroup->mNode.mCalcFunc == (NodeCalcFunc)&Group_Calc) {
192 inGroup->mNode.mCalcFunc = (NodeCalcFunc)&Group_CalcDumpTree;
196 void Group_CalcDumpTreeAndControls(Group *inGroup)
198 Group_DumpNodeTreeAndControls(inGroup);
199 inGroup->mNode.mCalcFunc = (NodeCalcFunc)&Group_Calc;
202 void Group_DumpTreeAndControls(Group* inGroup)
204 if (inGroup->mNode.mCalcFunc == (NodeCalcFunc)&Group_Calc) {
205 inGroup->mNode.mCalcFunc = (NodeCalcFunc)&Group_CalcDumpTreeAndControls;
209 // count the children for this group (deep)
210 void Group_CountNodeTags(Group* inGroup, int* count)
212 Node *child = inGroup->mHead;
213 while (child) {
214 Node *next = child->mNext;
215 (*count)+= 2;
216 if (child->mIsGroup) {
217 Group_CountNodeTags((Group*)child, count);
218 } else { (*count)++; } // for the defname
219 child = next;
223 // count the children for this group (deep)
224 void Group_CountNodeAndControlTags(Group* inGroup, int* count, int* controlAndDefCount)
226 Node *child = inGroup->mHead;
227 while (child) {
228 Node *next = child->mNext;
229 (*count)++;
230 if (child->mIsGroup) {
231 Group_CountNodeAndControlTags((Group*)child, count, controlAndDefCount);
232 } else {
233 //(*controlCount) += ((Graph*)child)->mNumControls + ((GraphDef*)(child->mDef))->mNumParamSpecs + 1;
234 (*controlAndDefCount) += ((Graph*)child)->mNumControls * 2 + 2; // def, numControls, name or index and value for each
236 child = next;
240 void Group_QueryTree(Group* inGroup, big_scpacket *packet)
242 packet->addtag('i');
243 packet->addi(inGroup->mNode.mID);
245 // count the children for this group, but not their children (shallow)
246 int count = 0;
247 Node *child = inGroup->mHead;
248 while (child) {
249 Node *next = child->mNext;
250 count++;
251 child = next;
254 packet->addtag('i');
255 packet->addi(count); // numChildren; for a Group >= 0
257 // now iterate over the children
258 // id, numChildren, defname
259 child = inGroup->mHead;
260 while (child) {
261 Node *next = child->mNext;
262 if (child->mIsGroup) {
263 Group_QueryTree((Group*)child, packet);
264 } else {
265 packet->addtag('i'); // nodeID
266 packet->addtag('i'); // numChildren
267 packet->addtag('s'); // defname
268 packet->addi(child->mID);
269 packet->addi(-1);
270 packet->adds((char*)child->mDef->mName);
272 child = next;
276 void Group_QueryTreeAndControls(Group* inGroup, big_scpacket *packet)
278 packet->addtag('i');
279 packet->addi(inGroup->mNode.mID);
281 // count the children for this group, but not their children (shallow)
282 int count = 0;
283 Node *child = inGroup->mHead;
284 while (child) {
285 Node *next = child->mNext;
286 count++;
287 child = next;
290 packet->addtag('i');
291 packet->addi(count);
293 // now iterate over the children
294 // id, numChildren, defname
295 child = inGroup->mHead;
296 while (child) {
297 Node *next = child->mNext;
298 if (child->mIsGroup) {
299 Group_QueryTreeAndControls((Group*)child, packet);
300 } else {
301 packet->addtag('i');
302 packet->addtag('i');
303 packet->addtag('s');
304 packet->addi(child->mID); // nodeID
305 packet->addi(-1); // numChildren
306 packet->adds((char*)child->mDef->mName); // defName
308 Graph* childGraph = (Graph*)child;
309 int numControls = childGraph->mNumControls;
310 packet->addtag('i');
311 packet->addi(numControls);
313 char **names;
314 names = new char*[numControls];
315 int i;
316 for(i = 0; i < numControls; i++){
317 names[i] = NULL;
320 // check the number of named controls and stash their names
321 GraphDef* def = (GraphDef*)(child->mDef);
322 int numNamedControls = def->mNumParamSpecs;
323 for(i = 0; i < numNamedControls; i++){
324 ParamSpec *paramSpec = def->mParamSpecs + i;
325 names[paramSpec->mIndex] = (char*)paramSpec->mName;
328 // now add the names and values in index order, checking for mappings
329 for(i=0; i < numControls; i++){
330 float *ptr = childGraph->mControls + i;
332 if(names[i]){
333 packet->addtag('s');
334 packet->adds(names[i]);
335 } else {
336 packet->addtag('i');
337 packet->addi(i);
339 // the ptr in nMapControls should be the same as the control itself, if not, it's mapped.
340 if((childGraph->mMapControls[i]) != ptr){
341 // it's mapped
342 int bus = (childGraph->mMapControls[i]) - (child->mWorld->mControlBus);
343 //scprintf("bus: %d\n", bus);
344 char buf[10]; //should be long enough
345 sprintf(buf, "%c%d", 'c', bus);
346 packet->addtag('s');
347 packet->adds(buf);
348 } else {
349 packet->addtag('f');
350 packet->addf(*ptr);
354 child = next;
359 void Group_DeleteAll(Group *inGroup)
361 Node *child = inGroup->mHead;
362 while (child) {
363 Node *next = child->mNext;
364 child->mPrev = child->mNext = 0;
365 child->mParent = 0;
366 Node_Delete(child);
367 child = next;
369 inGroup->mHead = inGroup->mTail = 0;
372 void Group_DeepFreeGraphs(Group *inGroup)
374 Node *child = inGroup->mHead;
375 while (child) {
376 Node *next = child->mNext;
377 if (child->mIsGroup) {
378 Group_DeepFreeGraphs((Group*)child);
379 } else {
380 Node_Remove(child);
381 Node_Delete(child);
383 child = next;
387 void Group_AddHead (Group *s, Node *child)
389 if (child->mID == 0) return; // failed
390 child->mPrev = 0;
391 child->mNext = s->mHead;
392 if (s->mHead) { s->mHead->mPrev = child; s->mHead = child; }
393 else s->mHead = s->mTail = child;
394 child->mParent = s;
397 void Group_AddTail (Group *s, Node *child)
399 if (child->mID == 0) return; // failed
400 child->mPrev = s->mTail;
401 child->mNext = 0;
402 if (s->mTail) { s->mTail->mNext = child; s->mTail = child; }
403 else s->mHead = s->mTail = child;
404 child->mParent = s;
407 void Group_Insert(Group *s, Node *child, int index)
409 if (child->mID == 0) return; // failed
410 if (index <= 0) Group_AddHead(s, child);
411 else {
412 Node *before = s->mHead;
413 for (int i=0; i<index; ++i) {
414 before = before->mNext;
415 if (!before) {
416 Group_AddTail(s, child);
417 return;
420 Node_AddBefore(child, before);
424 void Group_MapControl(Group *inGroup, uint32 inIndex, uint32 inBus)
426 Node *child = inGroup->mHead;
427 while (child) {
428 Node *next = child->mNext;
429 Node_MapControl(child, inIndex, inBus);
430 child = next;
434 void Group_MapControl(Group *inGroup, int32 inHash, int32 *inName, uint32 inIndex, uint32 inBus)
436 Node *child = inGroup->mHead;
437 while (child) {
438 Node *next = child->mNext;
439 Node_MapControl(child, inHash, inName, inIndex, inBus);
440 child = next;
444 void Group_MapAudioControl(Group *inGroup, uint32 inIndex, uint32 inBus)
446 Node *child = inGroup->mHead;
447 while (child) {
448 Node *next = child->mNext;
449 Node_MapAudioControl(child, inIndex, inBus);
450 child = next;
454 void Group_MapAudioControl(Group *inGroup, int32 inHash, int32 *inName, uint32 inIndex, uint32 inBus)
456 Node *child = inGroup->mHead;
457 while (child) {
458 Node *next = child->mNext;
459 Node_MapAudioControl(child, inHash, inName, inIndex, inBus);
460 child = next;
463 void Group_SetControl(Group *inGroup, uint32 inIndex, float inValue)
465 Node *child = inGroup->mHead;
466 while (child) {
467 Node *next = child->mNext;
468 Node_SetControl(child, inIndex, inValue);
469 child = next;
473 void Group_SetControl(Group *inGroup, int32 inHash, int32 *inName, uint32 inIndex, float inValue)
475 Node *child = inGroup->mHead;
476 while (child) {
477 Node *next = child->mNext;
478 Node_SetControl(child, inHash, inName, inIndex, inValue);
479 child = next;