1 /*
2 cscorfns.c:
3
4 Copyright (C) 1991 Barry Vercoe, John ffitch
5
6 This file is part of Csound.
7
8 The Csound Library is free software; you can redistribute it
9 and/or modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version.
12
13 Csound is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with Csound; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 02110-1301 USA
22 */
23
24 #include "csoundCore.h" /* CSCORFNS.C */
25 #include "cscore.h"
26 #include "corfile.h"
27
28 #define TYP_FREE 0
29 #define TYP_EVENT 1
30 #define TYP_EVLIST 2
31 #define TYP_SPACE 3
32 #define NSLOTS 100 /* default slots in cscoreListCreate list */
33 #define MAXALLOC 32768L
34
35 extern int lplay(CSOUND *, EVLIST *);
36
37 typedef struct space {
38 CSHDR h;
39 struct space *nxtspace;
40 } SPACE;
41
42 /* RWD: moved from below for use in reset */
43 typedef struct {
44 FILE *iscfp;
45 EVENT *next;
46 MYFLT until;
47 int wasend, warped, atEOF;
48 } INFILE;
49 static INFILE *infiles = NULL; /* array of infile status blks */
50
51 /* next two from cscoreDefineEvent() really */
52 static EVENT *evtmp = NULL;
53 static EVTBLK *evtmpblk;
54
55 static SPACE spaceanchor = { { NULL, NULL, TYP_SPACE, 0 }, NULL };
56 static CSHDR *nxtfree = NULL; /* fast pointer to yet unused free space */
57 static EVENT *nxtevt = NULL; /* to hold nxt infil event, PMAX pfields */
58 static EVTBLK *nxtevtblk; /* cs.h EVTBLK subset of EVENT nxtevt */
59 static int warpout = 0;
60 static MYFLT curuntil; /* initialised to zero by cscoreFileOpen */
61 static int wasend; /* ditto */
62 static int atEOF; /* zero when file opened;
63 stays one once rdscor returns 0 */
64
65
cscoreRESET(CSOUND * csound)66 void cscoreRESET(CSOUND *csound)
67 {
68 nxtfree = NULL;
69 nxtevt = NULL;
70 nxtevtblk = NULL;
71 infiles = NULL; /* FIXME: leak? (any others here?) */
72 csound->warped = warpout = 0;
73 evtmp = NULL;
74 evtmpblk = NULL;
75 if (spaceanchor.nxtspace != NULL) {
76 SPACE *p = spaceanchor.nxtspace;
77 SPACE *n;
78 do {
79 n = p->nxtspace;
80 csound->Free(csound, p);
81 p = n;
82 }
83 while (p != NULL);
84 }
85 spaceanchor.nxtspace = NULL;
86 spaceanchor.h.prvblk = NULL;
87 spaceanchor.h.nxtblk = NULL;
88 spaceanchor.h.type = TYP_SPACE;
89 spaceanchor.h.size = 0;
90 return;
91 }
92
morespace(CSOUND * csound)93 static SPACE *morespace(CSOUND *csound)
94 { /* alloc large amount of memory, keep in a */
95 SPACE *space, *prvspace; /* chain. Put SPACE blk at top & init rem as */
96 CSHDR *free; /* a FREE blk */
97
98 prvspace = &spaceanchor;
99 while ((space = prvspace->nxtspace) != NULL)
100 prvspace = space;
101 space = (SPACE *) csound->Malloc(csound, (long) MAXALLOC);
102 prvspace->nxtspace = space;
103 space->nxtspace = NULL;
104 space->h.prvblk = NULL;
105 space->h.nxtblk = (CSHDR *) ((char *) space + sizeof(SPACE));
106 space->h.type = TYP_SPACE;
107 space->h.size = sizeof(SPACE);
108 free = space->h.nxtblk;
109 free->prvblk = (CSHDR *) space; /* init rem as a TYP_FREE blk */
110 free->nxtblk = NULL;
111 free->type = TYP_FREE;
112 free->size = MAXALLOC - sizeof(SPACE);
113 return(space);
114 }
115
116 /* search space chains for min size free blk */
117 /* else alloc new space blk & reset fast free */
118
getfree(CSOUND * csound,int minfreesiz)119 static CSHDR *getfree(CSOUND *csound, int minfreesiz)
120 {
121 SPACE *curspace;
122 CSHDR *blkp;
123
124 curspace = &spaceanchor;
125 while ((curspace = curspace->nxtspace) != NULL) {
126 blkp = curspace->h.nxtblk;
127 do {
128 if (blkp->type == TYP_FREE && blkp->size >= minfreesiz)
129 return(blkp);
130 } while ((blkp = blkp->nxtblk) != NULL);
131 }
132 curspace = morespace(csound); /* else alloc more space, and */
133 nxtfree = curspace->h.nxtblk; /* reset the fast free pointer */
134 return(nxtfree);
135 }
136
137 /* return a TYP_EVENT or TYP_EVLIST to free space */
138 /* consolidate with any prev or follow free space */
139
csfree(CSHDR * bp)140 static void csfree(CSHDR *bp)
141 {
142 CSHDR *prvp, *nxtp;
143
144 if ((prvp = bp->prvblk) != NULL && prvp->type == TYP_FREE) {
145 if ((nxtp = bp->nxtblk) != NULL && nxtp->type == TYP_FREE) {
146 if ((prvp->nxtblk = nxtp->nxtblk) != NULL)
147 nxtp->nxtblk->prvblk = prvp;
148 prvp->size += bp->size + nxtp->size;
149 }
150 else {
151 if ((prvp->nxtblk = bp->nxtblk) != NULL)
152 bp->nxtblk->prvblk = prvp;
153 prvp->size += bp->size;
154 }
155 }
156 else {
157 if ((nxtp = bp->nxtblk) != NULL && nxtp->type == TYP_FREE) {
158 if ((bp->nxtblk = nxtp->nxtblk) != NULL)
159 nxtp->nxtblk->prvblk = bp;
160 bp->size += nxtp->size;
161 }
162 bp->type = TYP_FREE;
163 }
164 }
165
166 /* create an array of event pointer slots */
167
cscoreListCreate(CSOUND * csound,int nslots)168 PUBLIC EVLIST * cscoreListCreate(CSOUND *csound, int nslots)
169 {
170 CSHDR *newblk, *newfree;
171 EVLIST *a;
172 int needsiz = sizeof(EVLIST) + nslots * sizeof(EVENT *);
173 int minfreesiz = needsiz + sizeof(CSHDR);
174
175 if (UNLIKELY(minfreesiz > MAXALLOC)) {
176 csound->Message(csound, Str("Not enough memory\n"));
177 exit(1);
178 }
179 if (nxtfree != NULL && nxtfree->size >= minfreesiz)
180 newblk = nxtfree;
181 else newblk = getfree(csound, minfreesiz);
182 newfree = (CSHDR *) ((char *)newblk + needsiz);
183 newfree->prvblk = newblk;
184 newfree->nxtblk = newblk->nxtblk;
185 newfree->type = TYP_FREE;
186 newfree->size = newblk->size - needsiz;
187 newblk->nxtblk = newfree;
188 newblk->type = TYP_EVLIST;
189 newblk->size = needsiz;
190 if (newblk == nxtfree) nxtfree = newfree;
191 a = (EVLIST *) newblk;
192 a->nslots = nslots;
193 a->nevents= 0;
194 return(a);
195 }
196
197 /* creat a new event space */
198
cscoreCreateEvent(CSOUND * csound,int pcnt)199 PUBLIC EVENT * cscoreCreateEvent(CSOUND *csound, int pcnt)
200 {
201 CSHDR *newblk, *newfree;
202 EVENT *e;
203 int needsiz = sizeof(EVENT) + pcnt * sizeof(MYFLT);
204 int minfreesiz = needsiz + sizeof(CSHDR);
205
206 if (UNLIKELY(minfreesiz > MAXALLOC)) {
207 csound->Message(csound, Str("Not enough memory\n"));
208 exit(1);
209 }
210 if (nxtfree != NULL && nxtfree->size >= minfreesiz)
211 newblk = nxtfree;
212 else newblk = getfree(csound, minfreesiz);
213 newfree = (CSHDR *) ((char *)newblk + needsiz);
214 newfree->prvblk = newblk;
215 newfree->nxtblk = newblk->nxtblk;
216 newfree->type = TYP_FREE;
217 newfree->size = newblk->size - needsiz;
218 newblk->nxtblk = newfree;
219 newblk->type = TYP_EVENT;
220 newblk->size = needsiz;
221 if (newblk == nxtfree) nxtfree = newfree;
222 e = (EVENT *) newblk;
223 e->pcnt = pcnt;
224 return(e);
225 }
226
227 /* make a new copy of an event */
228
cscoreCopyEvent(CSOUND * csound,EVENT * e)229 PUBLIC EVENT * cscoreCopyEvent(CSOUND *csound, EVENT *e)
230 {
231 EVENT *f;
232 int n;
233 MYFLT *p, *q;
234
235 n = e->pcnt;
236 f = cscoreCreateEvent(csound, n);
237 f->op = e->op;
238 f->strarg = e->strarg;
239 /* f->pcnt was set by cscoreCreateEvent */
240 /* previous method of copying these was dangerous! - akozar */
241 f->p2orig = e->p2orig;
242 f->p3orig = e->p3orig;
243 p = &e->p[0];
244 q = &f->p[0];
245 n += 1; /* p[] is one larger than pcnt b/c p[0] unused */
246 while (n--)
247 *q++ = *p++;
248 return(f);
249 }
250
251 /* RWD: cannot addd init arg as this is a std public func */
252 /* Can only do reentry by moving statics outside: fortunately, */
253 /* names are unique */
254
255 /* define an event from string arg */
256
cscoreDefineEvent(CSOUND * csound,char * s)257 PUBLIC EVENT * cscoreDefineEvent(CSOUND *csound, char *s)
258 {
259 MYFLT *p, *q;
260
261 if (evtmp == NULL) {
262 evtmp = cscoreCreateEvent(csound, PMAX);
263 evtmpblk = (EVTBLK *) &evtmp->strarg;
264 }
265 while (*s == ' ')
266 s++;
267 evtmp->op = *s++; /* read opcode */
268 while (*s == ' ')
269 s++;
270 p = &evtmp->p[1];
271 q = &evtmp->p[PMAX];
272 #ifdef USE_DOUBLE
273 while (CS_SSCANF(s,"%lf",p++) > 0) /* read pfields */
274 #else
275 while (CS_SSCANF(s,"%f",p++) > 0) /* read pfields */
276 #endif
277 {
278 while ((*s >= '0' && *s <= '9') || *s == '.' || *s == '-')
279 s++;
280 while (*s == ' ')
281 s++;
282 if (UNLIKELY(p > q && *s != '\0')) { /* too many ? */
283 p++;
284 csound->Message(csound,
285 Str("PMAX exceeded, string event truncated.\n"));
286 break;
287 }
288 }
289 evtmp->pcnt = p - &evtmp->p[1] - 1; /* set count of params recvd */
290 evtmp->p2orig = evtmp->p[2];
291 evtmp->p3orig = evtmp->p[3];
292 return (cscoreCopyEvent(csound, evtmp)); /* copy event to a new space */
293 }
294
295 /* get nxt event from input score buf */
296 /* and refill the buf */
297
cscoreGetEvent(CSOUND * csound)298 PUBLIC EVENT * cscoreGetEvent(CSOUND *csound)
299 {
300 EVENT *e;
301
302 if (!atEOF && nxtevt->op != '\0')
303 e = cscoreCopyEvent(csound, nxtevt);
304 else e = NULL;
305 if (!(rdscor(csound, nxtevtblk))) {
306 nxtevt->op = '\0';
307 atEOF = 1;
308 }
309 return(e);
310 }
311
312 /* put an event to cscore outfile */
313
cscorePutEvent(CSOUND * csound,EVENT * e)314 PUBLIC void cscorePutEvent(CSOUND *csound, EVENT *e)
315 {
316 int pcnt;
317 MYFLT *q;
318 int c = e->op;
319
320 if (c == 's') warpout = 0; /* new section: init to non-warped */
321 putc(c, csound->oscfp);
322 q = &e->p[1];
323 if ((pcnt = e->pcnt)) {
324 if (pcnt--) fprintf(csound->oscfp," %g",*q++);
325 //else goto termin; /* cannot happen */
326 if (pcnt--) {
327 if (warpout) { fprintf(csound->oscfp," %g", e->p2orig);}
328 fprintf(csound->oscfp," %g",*q++);
329 }
330 else goto termin;
331 if (pcnt--) {
332 if (warpout) { fprintf(csound->oscfp," %g", e->p3orig); }
333 fprintf(csound->oscfp," %g",*q++);
334 }
335 else goto termin;
336 while (pcnt--)
337 { fprintf(csound->oscfp," %g",*q++); }
338 }
339 termin:
340 putc((int)'\n', csound->oscfp);
341 if (c == 'w') warpout = 1; /* was warp statement: sect now warped */
342 }
343
cscorePutString(CSOUND * csound,char * s)344 PUBLIC void cscorePutString(CSOUND *csound, char *s)
345 {
346 fprintf(csound->oscfp,"%s\n", s);
347 if (*s == 's') warpout = 0;
348 else if (*s == 'w') warpout = 1;
349 }
350
351 /* expand an event list by NSLOTS more slots */
352 /* copy the previous list, free up the old */
353
lexpand(CSOUND * csound,EVLIST * a)354 static EVLIST * lexpand(CSOUND *csound, EVLIST *a)
355 {
356 EVLIST *b;
357 EVENT **p, **q;
358 int n;
359
360 b = cscoreListCreate(csound, a->nslots + NSLOTS);
361 b->nevents = n = a->nevents;
362 p = &a->e[1];
363 q = &b->e[1];
364 while (n--)
365 *q++ = *p++;
366 csfree((CSHDR *) a);
367 return(b);
368 }
369
370 /* append an event to a list */
371
cscoreListAppendEvent(CSOUND * csound,EVLIST * a,EVENT * e)372 PUBLIC EVLIST * cscoreListAppendEvent(CSOUND *csound, EVLIST *a, EVENT *e)
373 {
374 int n;
375
376 if ((n = a->nevents) == a->nslots)
377 a = lexpand(csound, a);
378 a->e[n+1] = e;
379 a->nevents++;
380 return(a);
381 }
382
383 /* append a string event to a list */
384
cscoreListAppendStringEvent(CSOUND * csound,EVLIST * a,char * s)385 PUBLIC EVLIST * cscoreListAppendStringEvent(CSOUND *csound, EVLIST *a, char *s)
386 {
387 EVENT *e = cscoreDefineEvent(csound, s);
388 return(cscoreListAppendEvent(csound,a,e));
389 }
390
391 /* get section events from the scorefile */
392
cscoreListGetSection(CSOUND * csound)393 PUBLIC EVLIST * cscoreListGetSection(CSOUND *csound)
394 {
395 EVLIST *a;
396 EVENT *e, **p;
397 int nevents = 0;
398
399 a = cscoreListCreate(csound, NSLOTS);
400 p = &a->e[1];
401 if (UNLIKELY(csound->scstr == NULL || csound->scstr->body[0] == '\0'))
402 return a;
403 while ((e = cscoreGetEvent(csound)) != NULL) {
404 if (e->op == 's' || e->op == 'e')
405 break;
406 if (nevents == a->nslots) {
407 a->nevents = nevents;
408 a = lexpand(csound, a);
409 p = &a->e[nevents+1];
410 }
411 *p++ = e;
412 nevents++;
413 }
414 a->nevents = nevents;
415 return(a);
416 }
417
418 /* get section events from the scorefile */
419
cscoreListGetUntil(CSOUND * csound,MYFLT beatno)420 PUBLIC EVLIST * cscoreListGetUntil(CSOUND *csound, MYFLT beatno)
421 {
422 EVLIST *a;
423 EVENT *e, **p;
424 int nevents = 0;
425 char op;
426
427 a = cscoreListCreate(csound, NSLOTS);
428 p = &a->e[1];
429 while ((op = nxtevt->op) == 't' || op == 'w' || op == 's' || op == 'e'
430 || (op != '\0' && nxtevt->p2orig < beatno)) {
431 e = cscoreGetEvent(csound);
432 if (e->op == 's') {
433 wasend = 1;
434 break;
435 }
436 if (e->op == 'e')
437 break;
438 if (nevents == a->nslots) {
439 a->nevents = nevents;
440 a = lexpand(csound,a);
441 p = &a->e[nevents+1];
442 }
443 *p++ = e;
444 nevents++;
445 }
446 a->nevents = nevents;
447 return(a);
448 }
449
450 /* get section events from the scorefile */
451
cscoreListGetNext(CSOUND * csound,MYFLT nbeats)452 PUBLIC EVLIST * cscoreListGetNext(CSOUND *csound, MYFLT nbeats)
453 {
454 if (wasend) {
455 wasend = 0;
456 curuntil = nbeats;
457 }
458 else curuntil += nbeats;
459 return(cscoreListGetUntil(csound,curuntil));
460 }
461
462 /* put listed events to cscore output */
463
cscoreListPut(CSOUND * csound,EVLIST * a)464 PUBLIC void cscoreListPut(CSOUND *csound, EVLIST *a)
465 {
466 EVENT **p;
467 int n;
468
469 n = a->nevents;
470 p = &a->e[1];
471 while (n--)
472 cscorePutEvent(csound, *p++);
473 }
474
cscoreListPlay(CSOUND * csound,EVLIST * a)475 PUBLIC int cscoreListPlay(CSOUND *csound, EVLIST *a)
476 {
477 return lplay(csound, a);
478 }
479
cscoreListCopy(CSOUND * csound,EVLIST * a)480 PUBLIC EVLIST * cscoreListCopy(CSOUND *csound, EVLIST *a)
481 {
482 EVLIST *b;
483 EVENT **p, **q;
484 int n = a->nevents;
485
486 b = cscoreListCreate(csound, n);
487 b->nevents = n;
488 p = &a->e[1];
489 q = &b->e[1];
490 while (n--)
491 *q++ = *p++;
492 return(b);
493 }
494
cscoreListCopyEvents(CSOUND * csound,EVLIST * a)495 PUBLIC EVLIST * cscoreListCopyEvents(CSOUND *csound, EVLIST *a)
496 {
497 EVLIST *b;
498 EVENT **p, **q;
499 int n = a->nevents;
500
501 b = cscoreListCreate(csound, n);
502 b->nevents = n;
503 p = &a->e[1];
504 q = &b->e[1];
505 while (n--)
506 *q++ = cscoreCopyEvent(csound, *p++);
507 return(b);
508 }
509
cscoreListAppendList(CSOUND * csound,EVLIST * a,EVLIST * b)510 PUBLIC EVLIST * cscoreListAppendList(CSOUND *csound, EVLIST *a, EVLIST *b)
511 {
512 EVENT **p, **q;
513 int i, j;
514
515 i = a->nevents;
516 j = b->nevents;
517 if (i + j >= a->nslots) {
518 EVLIST *c;
519 int n = i;
520 c = cscoreListCreate(csound, i+j);
521 p = &a->e[1];
522 q = &c->e[1];
523 while (n--)
524 *q++ = *p++;
525 csfree((CSHDR *) a);
526 a = c;
527 }
528 a->nevents = i+j;
529 p = &a->e[i+1];
530 q = &b->e[1];
531 while (j--)
532 *p++ = *q++;
533 return(a);
534 }
535
cscoreListConcatenate(CSOUND * csound,EVLIST * a,EVLIST * b)536 PUBLIC EVLIST * cscoreListConcatenate(CSOUND *csound, EVLIST *a, EVLIST *b)
537 {
538 return cscoreListAppendList(csound, a, b);
539 }
540
541 /* put evlist pointers into chronological order */
542
cscoreListSort(CSOUND * csound,EVLIST * a)543 PUBLIC void cscoreListSort(CSOUND *csound, EVLIST *a)
544 {
545 IGN(csound);
546 EVENT **p, **q;
547 EVENT *e, *f;
548 int n, gap, i, j;
549
550 n = a->nevents;
551 e = a->e[n];
552 if (e->op == 's' || e->op == 'e')
553 --n;
554 for (gap = n/2; gap > 0; gap /=2)
555 for (i = gap; i < n; i++)
556 for (j = i-gap; j >= 0; j -= gap) {
557 p = &a->e[j+1]; e = *p;
558 q = &a->e[j+1+gap]; f = *q;
559 if (e->op == 'w')
560 break;
561 if (e->p[2] < f->p[2])
562 break;
563 if (e->p[2] == f->p[2]) {
564 if (e->op == f->op) {
565 if (e->op == 'f')
566 break;
567 if (e->p[1] < f->p[1])
568 break;
569 if (e->p[1] == f->p[1])
570 if (e->p[3] <= f->p[3])
571 break;
572 }
573 else if (e->op < f->op)
574 break;
575 }
576 *p = f; *q = e;
577 }
578 }
579
cscoreListExtractInstruments(CSOUND * csound,EVLIST * a,char * s)580 PUBLIC EVLIST * cscoreListExtractInstruments(CSOUND *csound,
581 EVLIST *a, char *s) /* list extract by instr numbers */
582 {
583 int x[5], xcnt;
584 int xn, *xp, insno, n;
585 EVENT **p, **q, *e;
586 EVLIST *b, *c;
587
588 xcnt = sscanf(s,"%d%d%d%d%d",&x[0],&x[1],&x[2],&x[3],&x[4]);
589 n = a->nevents;
590 b = cscoreListCreate(csound, n);
591 p = &a->e[1];
592 q = &b->e[1];
593 while ((n--) && (e = *p++) != NULL) {
594 if (e->op != 'i')
595 *q++ = e;
596 else {
597 insno = (int)e->p[1];
598 xn = xcnt; xp = x;
599 while (xn--)
600 if (*xp++ == insno) {
601 *q++ = e;
602 break;
603 }
604 }
605 }
606 c = cscoreListCopy(csound,b);
607 csfree((CSHDR *) b);
608 return(c);
609 }
610
cscoreListExtractTime(CSOUND * csound,EVLIST * a,MYFLT from,MYFLT to)611 PUBLIC EVLIST * cscoreListExtractTime(CSOUND *csound,
612 EVLIST *a, MYFLT from, MYFLT to) /* list extract by time */
613 {
614 EVENT **p, **q, *e;
615 EVLIST *b, *c;
616 MYFLT maxp3;
617 int n;
618
619 n = a->nevents;
620 b = cscoreListCreate(csound,n);
621 p = &a->e[1];
622 q = &b->e[1];
623 maxp3 = to - from;
624 while ((n--) && (e = *p++) != NULL)
625 switch (e->op) {
626 case 'f':
627 if (e->p[2] < to) {
628 *q++ = e = cscoreCopyEvent(csound,e);
629 b->nevents++;
630 if (e->p[2] <= from)
631 e->p[2] = FL(0.0);
632 else e->p[2] -= from;
633 }
634 break;
635 case 'i':
636 if (e->p[2] < from) {
637 if (e->p[2] + e->p[3] > from) {
638 *q++ = e = cscoreCopyEvent(csound,e);
639 b->nevents++;
640 e->p[3] -= from - e->p[2];
641 e->p[2] = FL(0.0);
642 if (e->p[3] > maxp3)
643 e->p[3] = maxp3;
644 }
645 }
646 else if ((e->p[2] >= from) && (e->p[2] < to)) {
647 *q++ = e = cscoreCopyEvent(csound, e);
648 b->nevents++;
649 if (e->p[2] + e->p[3] > to)
650 e->p[3] = to - e->p[2];
651 e->p[2] -= from;
652 }
653 break;
654 default:
655 *q++ = cscoreCopyEvent(csound,e);
656 b->nevents++;
657 break;
658 }
659 c = cscoreListCopy(csound,b);
660 csfree((CSHDR *) b);
661 return(c);
662 }
663
664 /* look for f statements with non-0 p[2] */
665
fp2chk(CSOUND * csound,EVLIST * a,char * s)666 static void fp2chk(CSOUND *csound, EVLIST *a, char *s)
667 {
668 EVENT *e, **ep = &a->e[1];
669 int n = a->nevents, count = 0;
670
671 while (n--)
672 if ((e = *ep++) && e->op == 'f' && e->p[2] != 0.)
673 count++;
674 if (count)
675 csound->Message(csound, Str("%s found %d f event%s with non-zero p2\n"),
676 s, count, count==1 ? "" : Str("s"));
677 }
678
679 /* separate f events from evlist */
680
cscoreListSeparateF(CSOUND * csound,EVLIST * a)681 PUBLIC EVLIST * cscoreListSeparateF(CSOUND *csound, EVLIST *a)
682 {
683 EVLIST *b, *c;
684 EVENT **p, **q, **r;
685 int n;
686
687 n = a->nevents;
688 b = cscoreListCreate(csound, n);
689 p = q = &a->e[1];
690 r = &b->e[1];
691 while (n--) {
692 if ((*p)->op == 'f')
693 *r++ = *p++;
694 else *q++ = *p++;
695 }
696 a->nevents = q - &a->e[1];
697 b->nevents = r - &b->e[1];
698 c = cscoreListCopy(csound,b);
699 csfree((CSHDR *) b);
700 fp2chk(csound, c, "cscoreListSeparateF");
701 return(c);
702 }
703
704 /* separate t,w,f events from evlist */
705
cscoreListSeparateTWF(CSOUND * csound,EVLIST * a)706 PUBLIC EVLIST * cscoreListSeparateTWF(CSOUND *csound, EVLIST *a)
707 {
708 EVLIST *b, *c;
709 EVENT **p, **q, **r;
710 int n, op;
711
712 n = a->nevents;
713 b = cscoreListCreate(csound,n);
714 p = q = &a->e[1];
715 r = &b->e[1];
716 while (n--) {
717 if ((op = (*p)->op) == 't' || op == 'w' || op == 'f')
718 *r++ = *p++;
719 else *q++ = *p++;
720 }
721 a->nevents = q - &a->e[1];
722 b->nevents = r - &b->e[1];
723 c = cscoreListCopy(csound,b);
724 csfree((CSHDR *) b);
725 fp2chk(csound, c, "cscoreListSeparateTWF");
726 return(c);
727 }
728
729 /* give back event space */
730
cscoreFreeEvent(CSOUND * csound,EVENT * e)731 PUBLIC void cscoreFreeEvent(CSOUND *csound, EVENT *e)
732 {
733 IGN(csound);
734 csfree((CSHDR *) e);
735 }
736
737 /* give back list space */
738
cscoreListFree(CSOUND * csound,EVLIST * a)739 PUBLIC void cscoreListFree(CSOUND *csound, EVLIST *a)
740 {
741 IGN(csound);
742 csfree((CSHDR *) a);
743 }
744
745 /* give back list and its event spaces */
746
cscoreListFreeEvents(CSOUND * csound,EVLIST * a)747 PUBLIC void cscoreListFreeEvents(CSOUND *csound, EVLIST *a)
748 {
749 IGN(csound);
750 EVENT **p = &a->e[1];
751 int n = a->nevents;
752
753 while (n--)
754 csfree((CSHDR *) *p++);
755 csfree((CSHDR *) a);
756 }
757
758 #define MAXOPEN 5
759
savinfdata(CSOUND * csound,FILE * fp,EVENT * next,MYFLT until,int wasend,int warp,int eof)760 static void savinfdata( /* store input file data */
761 CSOUND *csound,
762 FILE *fp,
763 EVENT *next,
764 MYFLT until,
765 int wasend,
766 int warp,
767 int eof)
768 {
769 INFILE *infp;
770 int n;
771
772 if ((infp = infiles) == NULL) {
773 infp = infiles = (INFILE *) csound->Calloc(csound, MAXOPEN * sizeof(INFILE));
774 goto save;
775 }
776 for (n = MAXOPEN; n--; infp++)
777 if (infp->iscfp == fp)
778 goto save;
779 for (infp = infiles, n = MAXOPEN; n--; infp++)
780 if (infp->iscfp == NULL)
781 goto save;
782 csound->ErrorMsg(csound, Str("cscore: too many input files open"));
783 exit(0); /* FIXME: should not call exit */
784
785 save:
786 infp->iscfp = fp;
787 infp->next = next;
788 infp->until = until;
789 infp->wasend = wasend;
790 infp->warped = warp;
791 infp->atEOF = eof;
792 }
793
794 /* make fp the cur scfp & retreive other data */
795 /* set nxtevtblk to subset cs.h EVTBLK struct */
796 /* if nxtevt buffer is empty, read one event */
797
makecurrent(CSOUND * csound,FILE * fp)798 static void makecurrent(CSOUND *csound, FILE *fp)
799 {
800 INFILE *infp;
801 int n;
802
803 if ((infp = infiles) != NULL)
804 for (n = MAXOPEN; n--; infp++)
805 if (infp->iscfp == fp) {
806 csound->scfp = fp;
807 nxtevt = infp->next;
808 nxtevtblk = (EVTBLK *) &nxtevt->strarg;
809 curuntil = infp->until;
810 wasend = infp->wasend;
811 atEOF = infp->atEOF;
812 csound->warped = infp->warped;
813 if (nxtevt->op == '\0')
814 if (csound->scstr == NULL ||
815 csound->scstr->body[0] == '\0' ||
816 !(rdscor(csound, nxtevtblk))) {
817 nxtevt->op = '\0';
818 atEOF = 1;
819 }
820 return;
821 }
822 csound->ErrorMsg(csound, Str("cscore: tried to set an unknown file pointer"
823 " as the current file"));
824 exit(0); /* FIXME: should not call exit */
825 }
826
827 /* verify initial scfp, init other data */
828 /* record & make all this current */
csoundInitializeCscore(CSOUND * csound,FILE * insco,FILE * outsco)829 PUBLIC int csoundInitializeCscore(CSOUND *csound, FILE* insco, FILE* outsco)
830 {
831 EVENT *next;
832
833 if (insco != NULL) {
834 CORFIL *inf = corfile_create_w(csound);
835 int c;
836 while ((c=getc(insco))!=EOF) corfile_putc(csound, c, inf);
837 corfile_rewind(inf);
838 csound->scstr = inf;
839 }
840 if (outsco == NULL) {
841 csound->ErrorMsg(csound,
842 Str("csoundInitializeCscore: no output score given."));
843 return CSOUND_INITIALIZATION;
844 }
845 csound->scfp = insco;
846 csound->oscfp = outsco;
847
848 next = cscoreCreateEvent(csound, PMAX); /* creat EVENT blk receiving buf */
849 next->op = '\0';
850
851 savinfdata(csound, csound->scfp,
852 next, FL(0.0), 1, 0, 0);/* curuntil 0, wasend, non-warp, not eof */
853 makecurrent(csound, csound->scfp); /* make all this current */
854
855 return CSOUND_SUCCESS;
856 }
857
858
859
860 /* open new cscore input file, init data */
861 /* & save; no rdscor until made current */
862
cscoreFileOpen(CSOUND * csound,char * name)863 PUBLIC FILE *cscoreFileOpen(CSOUND *csound, char *name)
864 {
865 FILE *fp;
866 EVENT *next;
867 char *pathname;
868
869 /* keeping fopen() because the FILE* is returned to the user control
870 program and who knows what they will do with it ... */
871 pathname = csoundFindInputFile(csound, name, "INCDIR");
872 if (pathname == NULL || (fp = fopen(pathname, "r")) == NULL) {
873 csound->ErrorMsg(csound, Str("cscoreFileOpen: error opening %s"), name);
874 exit(0); /* FIXME: should not call exit */
875 }
876 csoundNotifyFileOpened(csound, pathname, CSFTYPE_SCORE, 0, 0);
877 csound->Free(csound, pathname);
878 /* alloc a receiving evtblk */
879 next = cscoreCreateEvent(csound,PMAX); /* FIXME: need next->op = '\0' ?? */
880 /* save all, wasend, non-warped, not eof */
881 savinfdata(csound, fp, next, FL(0.0), 1, 0, 0);
882 return(fp);
883 }
884
cscoreFileClose(CSOUND * csound,FILE * fp)885 PUBLIC void cscoreFileClose(CSOUND *csound, FILE *fp)
886 {
887 INFILE *infp;
888 int n;
889
890 if (fp == NULL) {
891 csound->Message(csound, Str("cscoreFileClose: NULL file pointer\n"));
892 return;
893 }
894 if ((infp = infiles) != NULL)
895 for (n = MAXOPEN; n--; infp++)
896 if (infp->iscfp == fp) {
897 infp->iscfp = NULL;
898 csound->Free(csound, (char *)infp->next);
899 fclose(fp);
900 if (csound->scfp == fp) csound->scfp = NULL;
901 return;
902 }
903 csound->Message(csound, Str("cscoreFileClose: fp not recorded\n"));
904 }
905
cscoreFileGetCurrent(CSOUND * csound)906 PUBLIC FILE *cscoreFileGetCurrent(CSOUND *csound)
907 {
908 if (csound->scfp == NULL) {
909 csound->ErrorMsg(csound, Str("cscoreFileGetCurrent: no fp current"));
910 exit(0); /* FIXME: should not call exit */
911 }
912 return(csound->scfp);
913 }
914
915 /* save the current infil states */
916 /* make fp & its states current */
917
cscoreFileSetCurrent(CSOUND * csound,FILE * fp)918 PUBLIC void cscoreFileSetCurrent(CSOUND *csound, FILE *fp)
919 {
920 if (fp != NULL) {
921 CORFIL *inf = corfile_create_w(csound);
922 int c;
923 fseek(fp, 0, SEEK_SET);
924 while ((c=getc(fp))!=EOF) corfile_putc(csound, c, inf);
925 corfile_rewind(inf);
926 corfile_rm(csound, &csound->scstr);
927 csound->scstr = inf;
928 nxtevt->op = '\0';
929 atEOF = 0;
930 }
931 if (csound->scfp != NULL)
932 savinfdata(csound,
933 csound->scfp, nxtevt, curuntil, wasend, csound->warped, atEOF);
934 makecurrent(csound, fp);
935 }
936
937 /* count entries in event list */
938
cscoreListCount(CSOUND * csound,EVLIST * a)939 PUBLIC int cscoreListCount(CSOUND *csound, EVLIST *a)
940 {
941 IGN(csound);
942 EVENT **p;
943 int n, nrem;
944
945 n = 0;
946 nrem = a->nslots;
947 p = &a->e[1];
948 while ((nrem--) && *p++ != NULL)
949 n++;
950 return(n);
951 }
952
953