1 /*
2 * threadsafe.c: threadsafe API functions
3 * Copyright (c) V Lazzarini, 2013
4 *
5 * L I C E N S E
6 *
7 * This software is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include "csoundCore.h"
23 #include "csound_orc.h"
24 #include <stdlib.h>
25
26 #ifdef USE_DOUBLE
27 # define MYFLT_INT_TYPE int64_t
28 #else
29 # define MYFLT_INT_TYPE int32_t
30 #endif
31
32 int csoundKillInstanceInternal(CSOUND *csound, MYFLT instr, char *instrName,
33 int mode, int allow_release, int async);
34 int csoundCompileTreeInternal(CSOUND *csound, TREE *root, int async);
35 int csoundCompileOrcInternal(CSOUND *csound, const char *str, int async);
36 void merge_state(CSOUND *csound, ENGINE_STATE *engineState,
37 TYPE_TABLE* typetable, OPDS *ids);
38 void killInstance(CSOUND *csound, MYFLT instr, int insno, INSDS *ip,
39 int mode, int allow_release);
40 void csoundInputMessageInternal(CSOUND *csound, const char *message);
41 int csoundReadScoreInternal(CSOUND *csound, const char *message);
42 void csoundTableCopyOutInternal(CSOUND *csound, int table, MYFLT *ptable);
43 void csoundTableCopyInInternal(CSOUND *csound, int table, MYFLT *ptable);
44 void csoundTableSetInternal(CSOUND *csound, int table, int index, MYFLT value);
45 int csoundScoreEventInternal(CSOUND *csound, char type,
46 const MYFLT *pfields, long numFields);
47 int csoundScoreEventAbsoluteInternal(CSOUND *csound, char type,
48 const MYFLT *pfields, long numFields,
49 double time_ofs);
50 void set_channel_data_ptr(CSOUND *csound, const char *name,
51 void *ptr, int newSize);
52
53 enum {INPUT_MESSAGE=1, READ_SCORE, SCORE_EVENT, SCORE_EVENT_ABS,
54 TABLE_COPY_OUT, TABLE_COPY_IN, TABLE_SET, MERGE_STATE, KILL_INSTANCE};
55
56 /* MAX QUEUE SIZE */
57 #define API_MAX_QUEUE 1024
58 /* ARG LIST ALIGNMENT */
59 #define ARG_ALIGN 8
60
61 /* Message queue structure */
62 typedef struct _message_queue {
63 int64_t message; /* message id */
64 char *args; /* args, arg pointers */
65 int64_t rtn; /* return value */
66 } message_queue_t;
67
68
69 /* atomicGetAndIncrementWithModulus */
atomicGet_Incr_Mod(volatile long * val,long mod)70 static long atomicGet_Incr_Mod(volatile long* val, long mod) {
71 volatile long oldVal, newVal;
72 do {
73 oldVal = *val;
74 newVal = (oldVal + 1) % mod;
75 } while (ATOMIC_CMP_XCH(val, newVal, oldVal));
76 return oldVal;
77 }
78
79 /* called by csoundCreate() at the start
80 and also by csoundStart() to cover de-allocation
81 by reset
82 */
allocate_message_queue(CSOUND * csound)83 void allocate_message_queue(CSOUND *csound) {
84 if (csound->msg_queue == NULL) {
85 int i;
86 csound->msg_queue = (message_queue_t **)
87 csound->Calloc(csound, sizeof(message_queue_t*)*API_MAX_QUEUE);
88 for (i = 0; i < API_MAX_QUEUE; i++) {
89 csound->msg_queue[i] =
90 (message_queue_t*)
91 csound->Calloc(csound, sizeof(message_queue_t));
92 }
93 }
94 }
95
96
97 /* enqueue should be called by the relevant API function */
message_enqueue(CSOUND * csound,int32_t message,char * args,int argsiz)98 void *message_enqueue(CSOUND *csound, int32_t message, char *args,
99 int argsiz) {
100 if(csound->msg_queue != NULL) {
101 int64_t *rtn;
102 volatile long items;
103
104 /* block if queue is full */
105 do {
106 items = ATOMIC_GET(csound->msg_queue_items);
107 } while(items >= API_MAX_QUEUE);
108
109 message_queue_t* msg =
110 csound->msg_queue[atomicGet_Incr_Mod(&csound->msg_queue_wget,
111 API_MAX_QUEUE)];
112 msg->message = message;
113 if(msg->args != NULL)
114 csound->Free(csound, msg->args);
115 msg->args = (char *)csound->Calloc(csound, argsiz);
116 memcpy(msg->args, args, argsiz);
117 rtn = &msg->rtn;
118 csound->msg_queue[atomicGet_Incr_Mod(&csound->msg_queue_wput,
119 API_MAX_QUEUE)] = msg;
120 ATOMIC_INCR(csound->msg_queue_items);
121 return (void *) rtn;
122 }
123 else return NULL;
124 }
125
126 /* dequeue should be called by kperf_*()
127 NB: these calls are already in place
128 */
message_dequeue(CSOUND * csound)129 void message_dequeue(CSOUND *csound) {
130 if(csound->msg_queue != NULL) {
131 long rp = csound->msg_queue_rstart;
132 long items = csound->msg_queue_items;
133 long rend = rp + items;
134
135 while(rp < rend) {
136 message_queue_t* msg = csound->msg_queue[rp % API_MAX_QUEUE];
137 switch(msg->message) {
138 case INPUT_MESSAGE:
139 {
140 const char *str = msg->args;
141 csoundInputMessageInternal(csound, str);
142 }
143
144 break;
145 case READ_SCORE:
146 {
147 const char *str = msg->args;
148 csoundReadScoreInternal(csound, str);
149 }
150 break;
151 case SCORE_EVENT:
152 {
153 char type;
154 const MYFLT *pfields;
155 long numFields;
156 type = msg->args[0];
157 memcpy(&pfields, msg->args + ARG_ALIGN,
158 sizeof(MYFLT *));
159 memcpy(&numFields, msg->args + ARG_ALIGN*2,
160 sizeof(long));
161
162 csoundScoreEventInternal(csound, type, pfields, numFields);
163 }
164 break;
165 case SCORE_EVENT_ABS:
166 {
167 char type;
168 const MYFLT *pfields;
169 long numFields;
170 double ofs;
171 type = msg->args[0];
172 memcpy(&pfields, msg->args + ARG_ALIGN,
173 sizeof(MYFLT *));
174 memcpy(&numFields, msg->args + ARG_ALIGN*2,
175 sizeof(long));
176 memcpy(&ofs, msg->args + ARG_ALIGN*3,
177 sizeof(double));
178
179 csoundScoreEventAbsoluteInternal(csound, type, pfields, numFields,
180 ofs);
181 }
182 break;
183 case TABLE_COPY_OUT:
184 {
185 int table;
186 MYFLT *ptable;
187 memcpy(&table, msg->args, sizeof(int));
188 memcpy(&ptable, msg->args + ARG_ALIGN,
189 sizeof(MYFLT *));
190 csoundTableCopyOutInternal(csound, table, ptable);
191 }
192 break;
193 case TABLE_COPY_IN:
194 {
195 int table;
196 MYFLT *ptable;
197 memcpy(&table, msg->args, sizeof(int));
198 memcpy(&ptable, msg->args + ARG_ALIGN,
199 sizeof(MYFLT *));
200 csoundTableCopyInInternal(csound, table, ptable);
201 }
202 break;
203 case TABLE_SET:
204 {
205 int table, index;
206 MYFLT value;
207 memcpy(&table, msg->args, sizeof(int));
208 memcpy(&index, msg->args + ARG_ALIGN,
209 sizeof(int));
210 memcpy(&value, msg->args + 2*ARG_ALIGN,
211 sizeof(MYFLT));
212 csoundTableSetInternal(csound, table, index, value);
213 }
214 break;
215 case MERGE_STATE:
216 {
217 ENGINE_STATE *e;
218 TYPE_TABLE *t;
219 OPDS *ids;
220 memcpy(&e, msg->args, sizeof(ENGINE_STATE *));
221 memcpy(&t, msg->args + ARG_ALIGN,
222 sizeof(TYPE_TABLE *));
223 memcpy(&ids, msg->args + 2*ARG_ALIGN,
224 sizeof(OPDS *));
225 merge_state(csound, e, t, ids);
226 }
227 break;
228 case KILL_INSTANCE:
229 {
230 MYFLT instr;
231 int mode, insno, rls;
232 INSDS *ip;
233 memcpy(&instr, msg->args, sizeof(MYFLT));
234 memcpy(&insno, msg->args + ARG_ALIGN,
235 sizeof(int));
236 memcpy(&ip, msg->args + ARG_ALIGN*2,
237 sizeof(INSDS *));
238 memcpy(&mode, msg->args + ARG_ALIGN*3,
239 sizeof(int));
240 memcpy(&rls, msg->args + ARG_ALIGN*4,
241 sizeof(int));
242 killInstance(csound, instr, insno, ip, mode, rls);
243 }
244 break;
245 }
246 msg->message = 0;
247 rp += 1;
248 }
249 ATOMIC_SUB(csound->msg_queue_items, items);
250 csound->msg_queue_rstart = rp % API_MAX_QUEUE;
251 }
252 }
253
254 /* these are the message enqueueing functions for each relevant API function */
csoundInputMessage_enqueue(CSOUND * csound,const char * str)255 static inline void csoundInputMessage_enqueue(CSOUND *csound,
256 const char *str){
257 message_enqueue(csound,INPUT_MESSAGE, (char *) str, strlen(str)+1);
258 }
259
csoundReadScore_enqueue(CSOUND * csound,const char * str)260 static inline int64_t *csoundReadScore_enqueue(CSOUND *csound, const char *str){
261 return message_enqueue(csound, READ_SCORE, (char *) str, strlen(str)+1);
262 }
263
csoundTableCopyOut_enqueue(CSOUND * csound,int table,MYFLT * ptable)264 static inline void csoundTableCopyOut_enqueue(CSOUND *csound, int table,
265 MYFLT *ptable){
266 const int argsize = ARG_ALIGN*2;
267 char args[ARG_ALIGN*2];
268 memcpy(args, &table, sizeof(int));
269 memcpy(args+ARG_ALIGN, &ptable, sizeof(MYFLT *));
270 message_enqueue(csound,TABLE_COPY_OUT, args, argsize);
271 }
272
csoundTableCopyIn_enqueue(CSOUND * csound,int table,MYFLT * ptable)273 static inline void csoundTableCopyIn_enqueue(CSOUND *csound, int table,
274 MYFLT *ptable){
275 const int argsize = ARG_ALIGN*2;
276 char args[ARG_ALIGN*2];
277 memcpy(args, &table, sizeof(int));
278 memcpy(args+ARG_ALIGN, &ptable, sizeof(MYFLT *));
279 message_enqueue(csound,TABLE_COPY_IN, args, argsize);
280 }
281
csoundTableSet_enqueue(CSOUND * csound,int table,int index,MYFLT value)282 static inline void csoundTableSet_enqueue(CSOUND *csound, int table, int index,
283 MYFLT value)
284 {
285 const int argsize = ARG_ALIGN*3;
286 char args[ARG_ALIGN*3];
287 memcpy(args, &table, sizeof(int));
288 memcpy(args+ARG_ALIGN, &index, sizeof(int));
289 memcpy(args+2*ARG_ALIGN, &value, sizeof(MYFLT));
290 message_enqueue(csound,TABLE_SET, args, argsize);
291 }
292
293
csoundScoreEvent_enqueue(CSOUND * csound,char type,const MYFLT * pfields,long numFields)294 static inline int64_t *csoundScoreEvent_enqueue(CSOUND *csound, char type,
295 const MYFLT *pfields,
296 long numFields)
297 {
298 const int argsize = ARG_ALIGN*3;
299 char args[ARG_ALIGN*3];
300 args[0] = type;
301 memcpy(args+ARG_ALIGN, &pfields, sizeof(MYFLT *));
302 memcpy(args+2*ARG_ALIGN, &numFields, sizeof(long));
303 return message_enqueue(csound,SCORE_EVENT, args, argsize);
304 }
305
306
csoundScoreEventAbsolute_enqueue(CSOUND * csound,char type,const MYFLT * pfields,long numFields,double time_ofs)307 static inline int64_t *csoundScoreEventAbsolute_enqueue(CSOUND *csound, char type,
308 const MYFLT *pfields,
309 long numFields,
310 double time_ofs)
311 {
312 const int argsize = ARG_ALIGN*4;
313 char args[ARG_ALIGN*4];
314 args[0] = type;
315 memcpy(args+ARG_ALIGN, &pfields, sizeof(MYFLT *));
316 memcpy(args+2*ARG_ALIGN, &numFields, sizeof(long));
317 memcpy(args+3*ARG_ALIGN, &time_ofs, sizeof(double));
318 return message_enqueue(csound,SCORE_EVENT_ABS, args, argsize);
319 }
320
321 /* this is to be called from
322 csoundKillInstanceInternal() in insert.c
323 */
killInstance_enqueue(CSOUND * csound,MYFLT instr,int insno,INSDS * ip,int mode,int allow_release)324 void killInstance_enqueue(CSOUND *csound, MYFLT instr, int insno,
325 INSDS *ip, int mode,
326 int allow_release) {
327 const int argsize = ARG_ALIGN*5;
328 char args[ARG_ALIGN*5];
329 memcpy(args, &instr, sizeof(int));
330 memcpy(args+ARG_ALIGN, &insno, sizeof(int));
331 memcpy(args+ARG_ALIGN*2, &ip, sizeof(INSDS *));
332 memcpy(args+ARG_ALIGN*3, &mode, sizeof(int));
333 memcpy(args+ARG_ALIGN*4, &allow_release, sizeof(int));
334 message_enqueue(csound,KILL_INSTANCE,args,argsize);
335 }
336
337 /* this is to be called from
338 csoundCompileTreeInternal() in csound_orc_compile.c
339 */
mergeState_enqueue(CSOUND * csound,ENGINE_STATE * e,TYPE_TABLE * t,OPDS * ids)340 void mergeState_enqueue(CSOUND *csound, ENGINE_STATE *e, TYPE_TABLE* t, OPDS *ids) {
341 const int argsize = ARG_ALIGN*3;
342 char args[ARG_ALIGN*3];
343 memcpy(args, &e, sizeof(ENGINE_STATE *));
344 memcpy(args+ARG_ALIGN, &t, sizeof(TYPE_TABLE *));
345 memcpy(args+2*ARG_ALIGN, &ids, sizeof(OPDS *));
346 message_enqueue(csound,MERGE_STATE, args, argsize);
347 }
348
349 /* VL: These functions are slated to
350 be converted to message enqueueing
351 in the next API revision.
352 */
csoundInputMessage(CSOUND * csound,const char * message)353 void csoundInputMessage(CSOUND *csound, const char *message){
354 csoundLockMutex(csound->API_lock);
355 csoundInputMessageInternal(csound, message);
356 csoundUnlockMutex(csound->API_lock);
357 }
358
csoundReadScore(CSOUND * csound,const char * message)359 int csoundReadScore(CSOUND *csound, const char *message){
360 int res;
361 csoundLockMutex(csound->API_lock);
362 res = csoundReadScoreInternal(csound, message);
363 csoundUnlockMutex(csound->API_lock);
364 return res;
365 }
366
csoundTableCopyOut(CSOUND * csound,int table,MYFLT * ptable)367 void csoundTableCopyOut(CSOUND *csound, int table, MYFLT *ptable){
368
369 csoundLockMutex(csound->API_lock);
370 csoundTableCopyOutInternal(csound, table, ptable);
371 csoundUnlockMutex(csound->API_lock);
372 }
373
csoundTableCopyIn(CSOUND * csound,int table,MYFLT * ptable)374 void csoundTableCopyIn(CSOUND *csound, int table, MYFLT *ptable){
375 csoundLockMutex(csound->API_lock);
376 csoundTableCopyInInternal(csound, table, ptable);
377 csoundUnlockMutex(csound->API_lock);
378 }
379
csoundTableSet(CSOUND * csound,int table,int index,MYFLT value)380 void csoundTableSet(CSOUND *csound, int table, int index, MYFLT value)
381 {
382 csoundLockMutex(csound->API_lock);
383 csoundTableSetInternal(csound, table, index, value);
384 csoundUnlockMutex(csound->API_lock);
385 }
386
csoundScoreEvent(CSOUND * csound,char type,const MYFLT * pfields,long numFields)387 int csoundScoreEvent(CSOUND *csound, char type,
388 const MYFLT *pfields, long numFields)
389 {
390
391 csoundLockMutex(csound->API_lock);
392 csoundScoreEventInternal(csound, type, pfields, numFields);
393 csoundUnlockMutex(csound->API_lock);
394 return OK;
395
396 }
397
csoundScoreEventAbsolute(CSOUND * csound,char type,const MYFLT * pfields,long numFields,double time_ofs)398 int csoundScoreEventAbsolute(CSOUND *csound, char type,
399 const MYFLT *pfields, long numFields,
400 double time_ofs)
401 {
402 csoundLockMutex(csound->API_lock);
403 csoundScoreEventAbsoluteInternal(csound, type, pfields, numFields, time_ofs);
404 csoundUnlockMutex(csound->API_lock);
405 return OK;
406 }
407
csoundKillInstance(CSOUND * csound,MYFLT instr,char * instrName,int mode,int allow_release)408 int csoundKillInstance(CSOUND *csound, MYFLT instr, char *instrName,
409 int mode, int allow_release){
410 int async = 0;
411 return csoundKillInstanceInternal(csound, instr, instrName, mode,
412 allow_release, async);
413 }
414
csoundCompileTree(CSOUND * csound,TREE * root)415 int csoundCompileTree(CSOUND *csound, TREE *root) {
416 int async = 0;
417 return csoundCompileTreeInternal(csound, root, async);
418 }
419
csoundCompileOrc(CSOUND * csound,const char * str)420 int csoundCompileOrc(CSOUND *csound, const char *str) {
421 int async = 0;
422 return csoundCompileOrcInternal(csound, str, async);
423 }
424
425 int init0(CSOUND *csound);
426
csoundEvalCode(CSOUND * csound,const char * str)427 MYFLT csoundEvalCode(CSOUND *csound, const char *str)
428 {
429 int async = 0;
430 if (str && csoundCompileOrcInternal(csound,str,async)
431 == CSOUND_SUCCESS){
432 if(!(csound->engineStatus & CS_STATE_COMP)) {
433 init0(csound);
434 }
435 return csound->instr0->instance[0].retval;
436 }
437 #ifdef NAN
438 else return NAN;
439 #else
440 else return 0;
441 #endif
442 }
443
444 /** Async versions of the functions above
445 To be removed once everything is made async
446 */
csoundInputMessageAsync(CSOUND * csound,const char * message)447 void csoundInputMessageAsync(CSOUND *csound, const char *message){
448 csoundInputMessage_enqueue(csound, message);
449 }
450
csoundReadScoreAsync(CSOUND * csound,const char * message)451 void csoundReadScoreAsync(CSOUND *csound, const char *message){
452 csoundReadScore_enqueue(csound, message);
453 }
454
csoundTableCopyOutAsync(CSOUND * csound,int table,MYFLT * ptable)455 void csoundTableCopyOutAsync(CSOUND *csound, int table, MYFLT *ptable){
456 csoundTableCopyOut_enqueue(csound, table, ptable);
457 }
458
csoundTableCopyInAsync(CSOUND * csound,int table,MYFLT * ptable)459 void csoundTableCopyInAsync(CSOUND *csound, int table, MYFLT *ptable){
460 csoundTableCopyIn_enqueue(csound, table, ptable);
461 }
462
csoundTableSetAsync(CSOUND * csound,int table,int index,MYFLT value)463 void csoundTableSetAsync(CSOUND *csound, int table, int index, MYFLT value)
464 {
465 csoundTableSet_enqueue(csound, table, index, value);
466 }
467
csoundScoreEventAsync(CSOUND * csound,char type,const MYFLT * pfields,long numFields)468 void csoundScoreEventAsync(CSOUND *csound, char type,
469 const MYFLT *pfields, long numFields)
470 {
471 csoundScoreEvent_enqueue(csound, type, pfields, numFields);
472 }
473
csoundScoreEventAbsoluteAsync(CSOUND * csound,char type,const MYFLT * pfields,long numFields,double time_ofs)474 void csoundScoreEventAbsoluteAsync(CSOUND *csound, char type,
475 const MYFLT *pfields, long numFields,
476 double time_ofs)
477 {
478
479 csoundScoreEventAbsolute_enqueue(csound, type, pfields, numFields, time_ofs);
480 }
481
csoundCompileTreeAsync(CSOUND * csound,TREE * root)482 int csoundCompileTreeAsync(CSOUND *csound, TREE *root) {
483 int async = 1;
484 return csoundCompileTreeInternal(csound, root, async);
485 }
486
csoundCompileOrcAsync(CSOUND * csound,const char * str)487 int csoundCompileOrcAsync(CSOUND *csound, const char *str) {
488 int async = 1;
489 return csoundCompileOrcInternal(csound, str, async);
490 }
491
csoundKillInstanceAsync(CSOUND * csound,MYFLT instr,char * instrName,int mode,int allow_release)492 int csoundKillInstanceAsync(CSOUND *csound, MYFLT instr, char *instrName,
493 int mode, int allow_release){
494 int async = 1;
495 return csoundKillInstanceInternal(csound, instr, instrName, mode,
496 allow_release, async);
497 }
498
499
500
501 /* VL: the following do not depend on API_lock
502 therefore do not need to be in the message queue
503 */
504
csoundGetControlChannel(CSOUND * csound,const char * name,int * err)505 MYFLT csoundGetControlChannel(CSOUND *csound, const char *name, int *err)
506 {
507 MYFLT *pval;
508 int err_;
509 union {
510 MYFLT d;
511 MYFLT_INT_TYPE i;
512 } x;
513 x.d = FL(0.0);
514 if (UNLIKELY(strlen(name) == 0)) return FL(.0);
515 if ((err_ = csoundGetChannelPtr(csound, &pval, name,
516 CSOUND_CONTROL_CHANNEL | CSOUND_OUTPUT_CHANNEL))
517 == CSOUND_SUCCESS) {
518 #if defined(MSVC)
519 x.i = InterlockedExchangeAdd64((MYFLT_INT_TYPE *)pval, 0);
520 #elif defined(HAVE_ATOMIC_BUILTIN)
521 x.i = __atomic_load_n((MYFLT_INT_TYPE *)pval, __ATOMIC_SEQ_CST);
522 #else
523 x.d = *pval;
524 #endif
525 }
526 if (err) {
527 *err = err_;
528 }
529 return x.d;
530 }
531
csoundSetControlChannel(CSOUND * csound,const char * name,MYFLT val)532 void csoundSetControlChannel(CSOUND *csound, const char *name, MYFLT val){
533 MYFLT *pval;
534 #if defined(MSVC) || defined(HAVE_ATOMIC_BUILTIN)
535 union {
536 MYFLT d;
537 MYFLT_INT_TYPE i;
538 } x;
539 x.d = val;
540 #endif
541 if (csoundGetChannelPtr(csound, &pval, name,
542 CSOUND_CONTROL_CHANNEL | CSOUND_INPUT_CHANNEL)
543 == CSOUND_SUCCESS)
544
545 #if defined(MSVC)
546 InterlockedExchange64((MYFLT_INT_TYPE *)pval, x.i);
547 #elif defined(HAVE_ATOMIC_BUILTIN)
548 __atomic_store_n((MYFLT_INT_TYPE *)pval, x.i, __ATOMIC_SEQ_CST);
549 #else
550 {
551 spin_lock_t *lock = (spin_lock_t *)
552 csoundGetChannelLock(csound, (char*) name);
553 csoundSpinLock(lock);
554 *pval = val;
555 csoundSpinUnLock(lock);
556 }
557 #endif
558 }
559
csoundGetAudioChannel(CSOUND * csound,const char * name,MYFLT * samples)560 void csoundGetAudioChannel(CSOUND *csound, const char *name, MYFLT *samples)
561 {
562
563 MYFLT *psamples;
564 if (strlen(name) == 0) return;
565 if (csoundGetChannelPtr(csound, &psamples, name,
566 CSOUND_AUDIO_CHANNEL | CSOUND_OUTPUT_CHANNEL)
567 == CSOUND_SUCCESS) {
568 spin_lock_t *lock = (spin_lock_t *)csoundGetChannelLock(csound, (char*) name);
569 csoundSpinLock(lock);
570 memcpy(samples, psamples, csoundGetKsmps(csound)*sizeof(MYFLT));
571 csoundSpinUnLock(lock);
572 }
573 }
574
csoundSetAudioChannel(CSOUND * csound,const char * name,MYFLT * samples)575 void csoundSetAudioChannel(CSOUND *csound, const char *name, MYFLT *samples)
576 {
577 MYFLT *psamples;
578 if (csoundGetChannelPtr(csound, &psamples, name,
579 CSOUND_AUDIO_CHANNEL | CSOUND_INPUT_CHANNEL)
580 == CSOUND_SUCCESS){
581 spin_lock_t *lock = (spin_lock_t *)csoundGetChannelLock(csound, (char*) name);
582 csoundSpinLock(lock);
583 memcpy(psamples, samples, csoundGetKsmps(csound)*sizeof(MYFLT));
584 csoundSpinUnLock(lock);
585 }
586 }
587
csoundSetStringChannel(CSOUND * csound,const char * name,char * string)588 void csoundSetStringChannel(CSOUND *csound, const char *name, char *string)
589 {
590 MYFLT *pstring;
591
592 if (csoundGetChannelPtr(csound, &pstring, name,
593 CSOUND_STRING_CHANNEL | CSOUND_INPUT_CHANNEL)
594 == CSOUND_SUCCESS){
595
596 STRINGDAT* stringdat = (STRINGDAT*) pstring;
597 int size = stringdat->size; //csoundGetChannelDatasize(csound, name);
598 spin_lock_t *lock = (spin_lock_t *) csoundGetChannelLock(csound, (char*) name);
599
600 if (lock != NULL) {
601 csoundSpinLock(lock);
602 }
603
604 if (strlen(string) + 1 > (unsigned int) size) {
605 if (stringdat->data!=NULL) csound->Free(csound,stringdat->data);
606 stringdat->data = cs_strdup(csound, string);
607 stringdat->size = strlen(string) + 1;
608 //set_channel_data_ptr(csound,name,(void*)pstring, strlen(string)+1);
609 } else {
610 strcpy((char *) stringdat->data, string);
611 }
612
613 if (lock != NULL) {
614 csoundSpinUnLock(lock);
615 }
616 }
617 }
618
csoundGetStringChannel(CSOUND * csound,const char * name,char * string)619 void csoundGetStringChannel(CSOUND *csound, const char *name, char *string)
620 {
621 MYFLT *pstring;
622 char *chstring;
623 int n2;
624 if (strlen(name) == 0) return;
625 if (csoundGetChannelPtr(csound, &pstring, name,
626 CSOUND_STRING_CHANNEL | CSOUND_OUTPUT_CHANNEL)
627 == CSOUND_SUCCESS){
628 spin_lock_t *lock = (spin_lock_t *) csoundGetChannelLock(csound, (char*) name);
629 chstring = ((STRINGDAT *) pstring)->data;
630 if (lock != NULL)
631 csoundSpinLock(lock);
632 if (string != NULL && chstring != NULL) {
633 n2 = strlen(chstring);
634 strNcpy(string,chstring, n2+1);
635 //string[n2] = '\0';
636 }
637 if (lock != NULL)
638 csoundSpinUnLock(lock);
639 }
640 }
641
csoundSetPvsChannel(CSOUND * csound,const PVSDATEXT * fin,const char * name)642 PUBLIC int csoundSetPvsChannel(CSOUND *csound, const PVSDATEXT *fin,
643 const char *name)
644 {
645 MYFLT *pp;
646 PVSDATEXT *f;
647 if (LIKELY(csoundGetChannelPtr(csound, &pp, name,
648 CSOUND_PVS_CHANNEL | CSOUND_INPUT_CHANNEL)
649 == CSOUND_SUCCESS)){
650 spin_lock_t *lock = (spin_lock_t *)
651 csoundGetChannelLock(csound, name);
652 f = (PVSDATEXT *) pp;
653 csoundSpinLock(lock);
654
655
656 if (f->frame == NULL) {
657 f->frame = csound->Calloc(csound, sizeof(float)*(fin->N+2));
658 } else if (f->N < fin->N) {
659 f->frame = csound->ReAlloc(csound, f->frame, sizeof(float)*(fin->N+2));
660 }
661
662 memcpy(f, fin, sizeof(PVSDATEXT)-sizeof(float *));
663 if (fin->frame != NULL)
664 memcpy(f->frame, fin->frame, (f->N+2)*sizeof(float));
665 csoundSpinUnLock(lock);
666 } else {
667 return CSOUND_ERROR;
668 }
669 return CSOUND_SUCCESS;
670 }
671
csoundGetPvsChannel(CSOUND * csound,PVSDATEXT * fout,const char * name)672 PUBLIC int csoundGetPvsChannel(CSOUND *csound, PVSDATEXT *fout,
673 const char *name)
674 {
675 MYFLT *pp;
676 PVSDATEXT *f;
677 if (UNLIKELY(csoundGetChannelPtr(csound, &pp, name,
678 CSOUND_PVS_CHANNEL | CSOUND_OUTPUT_CHANNEL)
679 == CSOUND_SUCCESS)){
680 spin_lock_t *lock = (spin_lock_t *)
681 csoundGetChannelLock(csound, name);
682 f = (PVSDATEXT *) pp;
683 if (UNLIKELY(pp == NULL)) return CSOUND_ERROR;
684 csoundSpinLock(lock);
685 memcpy(fout, f, sizeof(PVSDATEXT)-sizeof(float *));
686 if (fout->frame != NULL && f->frame != NULL)
687 memcpy(fout->frame, f->frame, sizeof(float)*(fout->N));
688 csoundSpinUnLock(lock);
689 } else {
690 return CSOUND_ERROR;
691 }
692 return CSOUND_SUCCESS;
693 }
694