1 /*
2 linevent.c:
3
4 Copyright (C) 1991 Barry Vercoe, John ffitch, matt ingalls
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" /* LINEVENT.C */
25 #include <ctype.h>
26
27 #ifdef MSVC
28 #include <fcntl.h>
29 #endif
30
31 #include "linevent.h"
32
33 #ifdef PIPES
34 # if defined(SGI) || defined(LINUX) || defined(NeXT) || defined(__MACH__)
35 # define _popen popen
36 # define _pclose pclose
37 # elif defined(__BEOS__) || defined(__HAIKU__) || defined(__MACH__)
38 # include <stdio.h>
39 # define _popen popen
40 # define _pclose pclose
41 # else
42 FILE *_popen(const char *, const char *);
43 # endif
44 #endif
45
46 #define LBUFSIZ1 32768
47 #define LF '\n'
48
49 /* typedef struct { */
50 /* char *Linep, *Linebufend; */
51 /* FILE *Linecons; */
52 /* int stdmode; */
53 /* EVTBLK prve; */
54 /* char Linebuf[LBUFSIZ]; */
55 /* } LINEVENT_GLOBALS; */
56
57 static void sensLine(CSOUND *csound, void *userData);
58
59 #define STA(x) (csound->lineventStatics.x)
60 #define MAXSTR 1048576 /* 1MB */
61
RTLineset(CSOUND * csound)62 void RTLineset(CSOUND *csound) /* set up Linebuf & ready the input files */
63 { /* callable once from musmon.c */
64 OPARMS *O = csound->oparms;
65 /* csound->lineventGlobals = (LINEVENT_GLOBALS*) */
66 /* csound->Calloc(csound, */
67 /* sizeof(LINEVENT_GLOBALS)); */
68
69 STA(linebufsiz) = LBUFSIZ1;
70 STA(Linebuf) = (char *) csound->Calloc(csound, STA(linebufsiz));
71 STA(orchestrab) = (char *) csound->Calloc(csound, MAXSTR);
72 STA(orchestra) = STA(orchestrab);
73 STA(prve).opcod = ' ';
74 STA(Linebufend) = STA(Linebuf) + STA(linebufsiz);
75 STA(Linep) = STA(Linebuf);
76 if (strcmp(O->Linename, "stdin") == 0) {
77 #if defined(DOSGCC) || defined(WIN32)
78 setvbuf(stdin, NULL, _IONBF, 0);
79 /* WARNING("-L stdin: system has no fcntl function to get stdin"); */
80 #else
81 STA(stdmode) = fcntl(csound->Linefd, F_GETFL, 0);
82 if (UNLIKELY(fcntl(csound->Linefd, F_SETFL, STA(stdmode) | O_NDELAY) < 0))
83 csoundDie(csound, Str("-L stdin fcntl failed"));
84 #endif
85 }
86 #ifdef PIPES
87 else if (UNLIKELY(O->Linename[0] == '|')) {
88 csound->Linepipe = _popen(&(O->Linename[1]), "r");
89 if (LIKELY(csound->Linepipe != NULL)) {
90 csound->Linefd = fileno(csound->Linepipe);
91 setvbuf(csound->Linepipe, NULL, _IONBF, 0);
92 }
93 else csoundDie(csound, Str("Cannot open %s"), O->Linename);
94 }
95 #endif
96 #define MODE ,0
97 else
98 if (UNLIKELY((csound->Linefd=open(O->Linename, O_RDONLY|O_NDELAY MODE)) < 0))
99 csoundDie(csound, Str("Cannot open %s"), O->Linename);
100 if(csound->oparms->odebug)
101 csound->Message(csound, Str("stdmode = %.8x Linefd = %d\n"),
102 STA(stdmode), csound->Linefd);
103 csound->RegisterSenseEventCallback(csound, sensLine, NULL);
104 }
105
106 #ifdef PIPES
107 int _pclose(FILE*);
108 #endif
109
RTclose(CSOUND * csound)110 void RTclose(CSOUND *csound)
111 {
112 if (csound->oparms->Linein == 0)
113 return;
114 csound->oparms->Linein = 0;
115 if(csound->oparms->odebug)
116 csound->Message(csound, Str("stdmode = %.8x Linefd = %d\n"),
117 STA(stdmode), csound->Linefd);
118 #ifdef PIPES
119 if (csound->oparms->Linename[0] == '|')
120 _pclose(csound->Linepipe);
121 else
122 #endif
123 {
124 if (strcmp(csound->oparms->Linename, "stdin") != 0)
125 close(csound->Linefd);
126 #if !defined(DOSGCC) && !defined(WIN32)
127 else
128 if (UNLIKELY(fcntl(csound->Linefd, F_SETFL, STA(stdmode))))
129 csoundDie(csound, Str("Failed to set file status\n"));
130 #endif
131 }
132
133 //csound->Free(csound, csound->lineventGlobals);
134 //csound->lineventGlobals = NULL;
135 }
136
137 /* does string segment contain LF? */
138
containsLF(char * cp,char * endp)139 static inline int containsLF(char *cp, char *endp)
140 {
141 while (cp < endp) {
142 if (UNLIKELY(*cp++ == LF))
143 return 1;
144 }
145 return 0;
146 }
147
linevent_alloc(CSOUND * csound,int reallocsize)148 static CS_NOINLINE int linevent_alloc(CSOUND *csound, int reallocsize)
149 {
150 volatile jmp_buf tmpExitJmp;
151 int err;
152 unsigned int tmp;
153
154 if (reallocsize > 0) {
155 /* VL 20-11-17 need to record the STA(Linep) offset
156 in relation to STA(Linebuf) */
157 tmp = (STA(Linep) - STA(Linebuf));
158 STA(Linebuf) = (char *) csound->ReAlloc(csound,
159 (void *) STA(Linebuf), reallocsize);
160
161 STA(linebufsiz) = reallocsize;
162 STA(Linebufend) = STA(Linebuf) + STA(linebufsiz);
163 /* VL 20-11-17 so we can place it in the correct position
164 after reallocation */
165 STA(Linep) = STA(Linebuf) + tmp;
166 } else if (STA(Linebuf)==NULL) {
167 STA(linebufsiz) = LBUFSIZ1;
168 STA(Linebuf) = (char *) csound->Calloc(csound, STA(linebufsiz));
169 }
170 if (STA(Linebuf) == NULL) {
171 return 1;
172 }
173 //csound->Message(csound, "1. realloc: %d\n", reallocsize);
174 if (STA(Linep)) return 0;
175 csound->Linefd = -1;
176 memcpy((void*) &tmpExitJmp, (void*) &csound->exitjmp, sizeof(jmp_buf));
177 if ((err = setjmp(csound->exitjmp)) != 0) {
178 memcpy((void*) &csound->exitjmp, (void*) &tmpExitJmp, sizeof(jmp_buf));
179 //csound->lineventGlobals = NULL;
180 return -1;
181 }
182
183
184 memcpy((void*) &csound->exitjmp, (void*) &tmpExitJmp, sizeof(jmp_buf));
185 STA(prve).opcod = ' ';
186 STA(Linebufend) = STA(Linebuf) + STA(linebufsiz);
187 STA(Linep) = STA(Linebuf);
188 csound->RegisterSenseEventCallback(csound, sensLine, NULL);
189
190 return 0;
191 }
192
193 /* insert text from an external source,
194 to be interpreted as if coming in from stdin/Linefd for -L */
195
csoundInputMessageInternal(CSOUND * csound,const char * message)196 void csoundInputMessageInternal(CSOUND *csound, const char *message)
197 {
198 int32 size = (int32) strlen(message);
199 int n;
200
201 if ((n=linevent_alloc(csound, 0)) != 0) return;
202
203 if (!size) return;
204 if (UNLIKELY((STA(Linep) + size) >= STA(Linebufend))) {
205 int extralloc = STA(Linep) + size - STA(Linebufend);
206 csound->Message(csound, "realloc %d\n", extralloc);
207 // csound->Message(csound, "extralloc: %d %d %d\n",
208 // extralloc, size, (int)(STA(Linebufend) - STA(Linep)));
209 // FIXME -- Coverity points out that this test is always false
210 // and n is never used
211 #if 0
212 if ((n=linevent_alloc(csound, (STA(linebufsiz) + extralloc))) != 0) {
213 csoundErrorMsg(csound, Str("LineBuffer Overflow - "
214 "Input Data has been Lost"));
215 return;
216 }
217 #else
218 n = linevent_alloc(csound, (STA(linebufsiz) + extralloc));
219
220 #endif
221 }
222 //csound->Message(csound, "%u = %u\n", (STA(Linep) + size), STA(Linebufend) );
223 memcpy(STA(Linep), message, size);
224 if (STA(Linep)[size - 1] != (char) '\n')
225 STA(Linep)[size++] = (char) '\n';
226 STA(Linep) += size;
227 }
228
229 /* accumlate RT Linein buffer, & place completed events in EVTBLK */
230 /* does more syntax checking than rdscor, since not preprocessed */
231
sensLine(CSOUND * csound,void * userData)232 static void sensLine(CSOUND *csound, void *userData)
233 {
234 char *cp, *Linestart, *Linend;
235 int c, cm1, cpp1, n, pcnt, oflag = STA(oflag);
236 IGN(userData);
237
238 while (1) {
239 if(STA(oflag) > oflag) break;
240 Linend = STA(Linep);
241 if (csound->Linefd >= 0) {
242 n = read(csound->Linefd, Linend, STA(Linebufend) - Linend);
243 Linend += (n > 0 ? n : 0);
244 }
245 if (Linend <= STA(Linebuf))
246 break;
247 Linestart = STA(Linebuf);
248 cp = Linestart;
249
250 while (containsLF(Linestart, Linend)) {
251 EVTBLK e;
252 char *sstrp = NULL;
253 int scnt = 0;
254 int strsiz = 0;
255 memset(&e, 0, sizeof(EVTBLK));
256 e.strarg = NULL; e.scnt = 0;
257 c = *cp;
258 while (isblank(c)) /* skip initial white space */
259 c = *(++cp);
260 if (c == LF) { /* if null line, bugout */
261 Linestart = (++cp);
262 continue;
263 }
264 cm1 = *(cp-1);
265 cpp1 = *(cp+1);
266
267 /* new orchestra input
268 */
269 if(STA(oflag)) {
270 if(c == '}' && cm1 != '}' && cpp1 != '}') {
271 STA(oflag) = 0;
272 STA(orchestra) = STA(orchestrab);
273 csoundCompileOrc(csound, STA(orchestrab));
274 csound->Message(csound, "::compiling orchestra::\n");
275 Linestart = (++cp);
276 continue;
277 }
278 else {
279 char *pc;
280 memcpy(STA(orchestra), Linestart, Linend - Linestart);
281 STA(orchestra) += (Linend - Linestart);
282 *STA(orchestra) = '\0';
283 STA(oflag)++;
284 if((pc = strrchr(STA(orchestrab), '}')) != NULL) {
285
286 if(*(pc-1) != '}') {
287 *pc = '\0';
288 cp = strrchr(Linestart, '}');
289 } else {
290 Linestart = Linend;
291 }
292 } else {
293 Linestart = Linend;
294 }
295 continue;
296 }
297 } else if(c == '{') {
298 STA(oflag) = 1;
299 csound->Message(csound,
300 "::reading orchestra, use '}' to terminate::\n");
301 cp++;
302 continue;
303 }
304
305 switch (c) { /* look for legal opcode */
306 case 'e': /* Quit realtime */
307 case 'i':
308 case 'q':
309 case 'f':
310 case 'a':
311 case 'd':
312 e.opcod = c;
313 break;
314 default:
315 csound->ErrorMsg(csound, Str("unknown opcode %c"), c);
316 goto Lerr;
317 } /* for params that follow: */
318 pcnt = 0;
319 do {
320 char *newcp;
321 do { /* skip white space */
322 c = *(++cp);
323 } while (isblank(c));
324 if (c == LF)
325 break;
326 pcnt++;
327 if (c == '"') { /* if find character string */
328 if (e.strarg == NULL)
329 e.strarg = csound->Malloc(csound, strsiz=SSTRSIZ);
330 sstrp = e.strarg;
331 n = scnt;
332 while (n-->0) sstrp += strlen(sstrp)+1;
333 n = 0;
334
335 while ((c = *(++cp)) != '"') {
336 /* VL: allow strings to be multi-line */
337 // if (UNLIKELY(c == LF)) {
338 // csound->ErrorMsg(csound, Str("unmatched quotes"));
339 // goto Lerr;
340 //}
341
342 if(c == '\\') {
343 cp++;
344 if(*cp == '"') c = *cp; /* if it is a double quote */
345 /* otherwise we ignore it */
346 else cp--;
347 }
348 sstrp[n++] = c; /* save in private strbuf */
349
350 if (UNLIKELY((sstrp-e.strarg)+n >= strsiz-10)) {
351 e.strarg = csound->ReAlloc(csound, e.strarg, strsiz+=SSTRSIZ);
352 sstrp = e.strarg+n;
353 }
354 }
355 sstrp[n] = '\0';
356 {
357 union {
358 MYFLT d;
359 int32 i;
360 } ch;
361 ch.d = SSTRCOD; ch.i += scnt++;
362 e.p[pcnt] = ch.d; /* set as string with count */
363 }
364 e.scnt = scnt;
365 //printf("string: %s\n", sstrp);
366 continue;
367 }
368 if (UNLIKELY(!(isdigit(c) || c == '+' || c == '-' || c == '.')))
369 goto Lerr;
370 if (c == '.' && /* if lone dot, */
371 (isblank(n = cp[1]) || n == LF)) {
372 if (UNLIKELY(e.opcod != 'i' ||
373 STA(prve).opcod != 'i' || pcnt > STA(prve).pcnt)) {
374 csound->ErrorMsg(csound, Str("dot carry has no reference"));
375 goto Lerr;
376 } /* pfld carry */
377 e.p[pcnt] = STA(prve).p[pcnt];
378 if (UNLIKELY(csound->ISSTRCOD(e.p[pcnt]))) {
379 csound->ErrorMsg(csound, Str("cannot carry string p-field"));
380 goto Lerr;
381 }
382 continue;
383 }
384 e.p[pcnt] = (MYFLT) cs_strtod(cp, &newcp);
385 cp = newcp - 1;
386 } while (pcnt < PMAX);
387 if (e.opcod =='f' && e.p[1]<FL(0.0)); /* an OK case */
388 else /* Check for sufficient pfields (0-based, opcode counted already). */
389 if (UNLIKELY(pcnt < 2 && e.opcod != 'e')) {
390 csound->ErrorMsg(csound, Str("too few pfields (%d)"), pcnt + 1);
391 goto Lerr;
392 }
393 if (UNLIKELY(pcnt > 1 && e.p[2] < FL(0.0))) {
394 csound->ErrorMsg(csound, Str("-L with negative p2 illegal"));
395 goto Lerr;
396 }
397 e.pcnt = pcnt; /* & record pfld count */
398 if (e.opcod == 'i') { /* do carries for instr data */
399 memcpy((void*) &STA(prve), (void*) &e,
400 (size_t) ((char*) &(e.p[pcnt + 1]) - (char*) &e));
401 /* FIXME: how to carry string args ? */
402 STA(prve).strarg = NULL;
403 }
404 if (UNLIKELY(pcnt >= PMAX && c != LF)) {
405 csound->ErrorMsg(csound, Str("too many pfields"));
406 while (*(++cp) != LF) /* flush any excess data */
407 ;
408 }
409 Linestart = (++cp);
410 insert_score_event_at_sample(csound, &e, csound->icurTime);
411 continue;
412 Lerr:
413 n = cp - Linestart; /* error position */
414 while (*cp != LF)
415 cp++; /* go on to LF */
416 *cp = '\0'; /* & insert NULL */
417 csound->ErrorMsg(csound, Str("illegal RT scoreline:\n%s\n%*s"),
418 Linestart, n + 1, "^"); /* mark the error */
419 Linestart = (++cp);
420 }
421 if (Linestart != &(STA(Linebuf)[0])) {
422 int len = (int) (Linend - Linestart);
423 /* move any remaining characters to the beginning of the buffer */
424 for (n = 0; n < len; n++)
425 STA(Linebuf)[n] = Linestart[n];
426 n = (int) (Linestart - &(STA(Linebuf)[0]));
427 STA(Linep) -= n;
428 Linend -= n;
429 }
430 if (Linend == STA(Linep)) /* return if no more data is available */
431 break;
432 STA(Linep) = Linend; /* accum the chars */
433 }
434
435 }
436
437 /* send a lineevent from the orchestra -matt 2001/12/07 */
438
439 static const char *errmsg_1 =
440 Str_noop("event: param 1 must be \"a\", \"i\", \"q\", \"f\", \"d\", or \"e\"");
441 static const char *errmsg_2 =
442 Str_noop("event: string name is allowed only for \"i\", \"d\", and \"q\" events");
443
eventOpcode_(CSOUND * csound,LINEVENT * p,int insname,char p1)444 int eventOpcode_(CSOUND *csound, LINEVENT *p, int insname, char p1)
445 {
446 EVTBLK evt;
447 int i;
448 char opcod;
449 memset(&evt, 0, sizeof(EVTBLK));
450
451 if (p1==0)
452 opcod = *((STRINGDAT*) p->args[0])->data;
453 else opcod = p1;
454
455 if (UNLIKELY((opcod != 'a' && opcod != 'i' && opcod != 'q' && opcod != 'f' &&
456 opcod != 'e' && opcod != 'd')
457 /*|| ((STRINGDAT*) p->args[0])->data[1] != '\0'*/))
458 return csound->PerfError(csound, &(p->h), "%s", Str(errmsg_1));
459 evt.strarg = NULL; evt.scnt = 0;
460 evt.opcod = opcod;
461 if (p->flag==1) evt.pcnt = p->argno-2;
462 else
463 evt.pcnt = p->INOCOUNT - 1;
464
465 /* IV - Oct 31 2002: allow string argument */
466 if (evt.pcnt > 0) {
467 if (insname) {
468 int res;
469 if (UNLIKELY(evt.opcod != 'i' && evt.opcod != 'q' && opcod != 'd'))
470 return csound->PerfError(csound, &(p->h), "%s", Str(errmsg_2));
471 res = csound->strarg2insno(csound, ((STRINGDAT*) p->args[1])->data, 1);
472 if (UNLIKELY(res == NOT_AN_INSTRUMENT)) return NOTOK;
473 evt.p[1] = (MYFLT) res;
474 evt.strarg = NULL; evt.scnt = 0;
475 }
476 else {
477 int res;
478 if (csound->ISSTRCOD(*p->args[1])) {
479 res = csound->strarg2insno(csound,
480 get_arg_string(csound, *p->args[1]), 1);
481 if (UNLIKELY(res == NOT_AN_INSTRUMENT)) return NOTOK;
482 evt.p[1] = (MYFLT)res;
483 } else { /* Should check for valid instr num here */
484 MYFLT insno = FABS(*p->args[1]);
485 evt.p[1] = *p->args[1];
486 if (UNLIKELY((opcod == 'i' || opcod == 'd') && (insno ==0 ||
487 insno > csound->engineState.maxinsno ||
488 !csound->engineState.instrtxtp[(int)insno]))) {
489 csound->Message(csound, Str("WARNING: Cannot Find Instrument %d\n"),
490 (int) insno);
491 return NOTOK;
492 }
493 }
494 evt.strarg = NULL; evt.scnt = 0;
495 }
496 for (i = 2; i <= evt.pcnt; i++)
497 evt.p[i] = *p->args[i];
498 }
499
500 if(opcod == 'd') {
501 evt.opcod = 'i';
502 evt.p[1] *= -1;
503 }
504
505 if (UNLIKELY(insert_score_event_at_sample(csound, &evt, csound->icurTime) != 0))
506 return csound->PerfError(csound, &(p->h),
507 Str("event: error creating '%c' event"),
508 opcod);
509 return OK;
510 }
511
eventOpcode(CSOUND * csound,LINEVENT * p)512 int eventOpcode(CSOUND *csound, LINEVENT *p)
513 {
514 return eventOpcode_(csound, p, 0, 0);
515 }
516
eventOpcode_S(CSOUND * csound,LINEVENT * p)517 int eventOpcode_S(CSOUND *csound, LINEVENT *p)
518 {
519 return eventOpcode_(csound, p, 1, 0);
520 }
521
522
523
524 /* i-time version of event opcode */
525
eventOpcodeI_(CSOUND * csound,LINEVENT * p,int insname,char p1)526 int eventOpcodeI_(CSOUND *csound, LINEVENT *p, int insname, char p1)
527 {
528 EVTBLK evt;
529 int i, err = 0;
530 char opcod;
531 memset(&evt, 0, sizeof(EVTBLK));
532
533 if (p1==0)
534 opcod = *((STRINGDAT*) p->args[0])->data;
535 else opcod = p1;
536 if (UNLIKELY((opcod != 'a' && opcod != 'i' && opcod != 'q' && opcod != 'f' &&
537 opcod != 'e' && opcod != 'd')
538 /*|| ((STRINGDAT*) p->args[0])->data[1] != '\0'*/))
539 return csound->InitError(csound, "%s", Str(errmsg_1));
540 evt.strarg = NULL; evt.scnt = 0;
541 evt.opcod = opcod;
542 if (p->flag==1) evt.pcnt = p->argno-1;
543 else
544 evt.pcnt = p->INOCOUNT - 1;
545 /* IV - Oct 31 2002: allow string argument */
546 if (evt.pcnt > 0) {
547 if (insname) {
548 int res;
549 if (UNLIKELY(evt.opcod != 'i' && evt.opcod != 'q' && opcod != 'd'))
550 return csound->InitError(csound, "%s", Str(errmsg_2));
551 res = csound->strarg2insno(csound,((STRINGDAT *)p->args[1])->data, 1);
552 if (UNLIKELY(res == NOT_AN_INSTRUMENT)) return NOTOK;
553 evt.p[1] = (MYFLT)res;
554 evt.strarg = NULL; evt.scnt = 0;
555 for (i = 2; i <= evt.pcnt; i++)
556 evt.p[i] = *p->args[i];
557 }
558 else {
559 evt.strarg = NULL; evt.scnt = 0;
560 if (csound->ISSTRCOD(*p->args[1])) {
561 int res = csound->strarg2insno(csound,
562 get_arg_string(csound, *p->args[1]), 1);
563 if (UNLIKELY(evt.p[1] == NOT_AN_INSTRUMENT)) return NOTOK;
564 evt.p[1] = (MYFLT)res;
565 }
566 else { /* Should check for valid instr num here */
567 MYFLT insno = FABS(*p->args[1]);
568 evt.p[1] = *p->args[1];
569 if (UNLIKELY((opcod == 'i' || opcod == 'd') && (insno ==0 ||
570 insno > csound->engineState.maxinsno ||
571 !csound->engineState.instrtxtp[(int)insno]))) {
572 csound->Message(csound, Str("WARNING: Cannot Find Instrument %d\n"),
573 (int) insno);
574 return NOTOK;
575 }
576 evt.strarg = NULL; evt.scnt = 0;
577 }
578 for (i = 2; i <= evt.pcnt; i++)
579 evt.p[i] = *p->args[i];
580 }
581
582 }
583 if(opcod == 'd') {
584 evt.opcod = 'i';
585 evt.p[1] *= -1;
586 }
587
588
589 if (opcod == 'f' && (int) evt.pcnt >= 2 && evt.p[2] <= FL(0.0)) {
590 FUNC *dummyftp;
591 err = csound->hfgens(csound, &dummyftp, &evt, 0);
592 }
593 else
594 err = insert_score_event_at_sample(csound, &evt, csound->icurTime);
595 if (UNLIKELY(err))
596 csound->InitError(csound, Str("event_i: error creating '%c' event"),
597 opcod);
598 return (err == 0 ? OK : NOTOK);
599 }
600
eventOpcodeI(CSOUND * csound,LINEVENT * p)601 int eventOpcodeI(CSOUND *csound, LINEVENT *p)
602 {
603 return eventOpcodeI_(csound, p, 0, 0);
604 }
605
eventOpcodeI_S(CSOUND * csound,LINEVENT * p)606 int eventOpcodeI_S(CSOUND *csound, LINEVENT *p)
607 {
608 return eventOpcodeI_(csound, p, 1, 0);
609 }
610
instanceOpcode_(CSOUND * csound,LINEVENT2 * p,int insname)611 int instanceOpcode_(CSOUND *csound, LINEVENT2 *p, int insname)
612 {
613 EVTBLK evt;
614 int i;
615
616 evt.strarg = NULL; evt.scnt = 0;
617 evt.opcod = 'i';
618 evt.pcnt = p->INOCOUNT;
619
620 /* pass in the memory to hold the instance after insertion */
621 evt.pinstance = (void *) p->inst;
622
623 /* IV - Oct 31 2002: allow string argument */
624 if (evt.pcnt > 0) {
625 int res;
626 if (insname) {
627 res = csound->strarg2insno(csound,
628 ((STRINGDAT*) p->args[0])->data, 1);
629 if (UNLIKELY(evt.p[1] == NOT_AN_INSTRUMENT)) return NOTOK;
630 evt.p[1] = (MYFLT)res;
631 evt.strarg = NULL; evt.scnt = 0;
632 }
633 else {
634 if (csound->ISSTRCOD(*p->args[0])) {
635 res = csound->strarg2insno(csound,
636 get_arg_string(csound, *p->args[0]), 1);
637 if (UNLIKELY(evt.p[1] == NOT_AN_INSTRUMENT)) return NOTOK;
638 evt.p[1] = (MYFLT)res;
639 } else evt.p[1] = *p->args[0];
640 evt.strarg = NULL; evt.scnt = 0;
641 }
642 for (i = 2; i <= evt.pcnt; i++)
643 evt.p[i] = *p->args[i-1];
644 }
645 if (insert_score_event_at_sample(csound, &evt, csound->icurTime) != 0)
646 return csound->PerfError(csound, &(p->h),
647 Str("instance: error creating event"));
648
649 return OK;
650 }
651
instanceOpcode(CSOUND * csound,LINEVENT2 * p)652 int instanceOpcode(CSOUND *csound, LINEVENT2 *p)
653 {
654 return instanceOpcode_(csound, p, 0);
655 }
656
instanceOpcode_S(CSOUND * csound,LINEVENT2 * p)657 int instanceOpcode_S(CSOUND *csound, LINEVENT2 *p)
658 {
659 return instanceOpcode_(csound, p, 1);
660 }
661