1 /*
2 * C S O U N D
3 *
4 * External language interfaces for the "C" and "C++" Csound API.
5 *
6 * L I C E N S E
7 *
8 * This software is free software; you can redistribute it and/or
9 * 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 * This software 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 GNU
16 * 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 this software; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 #ifndef MACOSX
24 %module(directors="1") csnd6
25 %feature("director") CsoundCallbackWrapper;
26 %feature("nodirector") Csound;
27 #else /* fix for OSX */
28 /* MODULE name is now csnd6 */
29 %module csnd6
30 #endif
31 %begin %{
32 #include <cmath>
33 %}
34 %include "typemaps.i"
35 %include "std_string.i"
36 %include "std_vector.i"
37 %include "carrays.i"
38 %array_functions(int, intp);
39 %array_functions(float, floatp);
40 %array_functions(double, doublep);
41 %array_class(int, intArray);
42 %array_class(float, floatArray);
43 %array_class(double, doubleArray)
44
45 %begin %{
46 #ifdef _MSC_VER
47 #define SWIG_PYTHON_INTERPRETER_NO_DEBUG
48 #endif
49 %}
50
51 %feature("autodoc", "1");
52 %{
53 #include <cmath>
54 #include <cstddef>
55 #include "csound.h"
56 #include "cfgvar.h"
57 #include "csound.hpp"
58 #include "cs_glue.hpp"
59 #include "csPerfThread.hpp"
60 #include "CsoundFile.hpp"
61 #include "CppSound.hpp"
62 #include "filebuilding.h"
63 #include "Soundfile.hpp"
64 %}
65
66 %apply int { size_t };
67 typedef unsigned int uint32_t;
68 #ifndef MSVC
69 %apply long long { uint32_t };
70 #endif
71
72 /* %typemap(in) char ** { */
73 /* Check if is a list */
74 /* if (PyList_Check($input)) {
75 int size = PyList_Size($input);
76 int i = 0;
77 $1 = (char **) malloc((size+1)*sizeof(char *));
78 for (i = 0; i < size; i++) {
79 PyObject *o = PyList_GetItem($input,i);
80 if (PyString_Check(o))
81 $1[i] = PyString_AsString(PyList_GetItem($input,i));
82 else {
83 PyErr_SetString(PyExc_TypeError,"list must contain strings");
84 free($1);
85 return NULL;
86 }
87 }
88 $1[i] = 0;
89 } else {
90 PyErr_SetString(PyExc_TypeError,"not a list");
91 return NULL;
92 }
93 }
94
95 %typemap(freearg) char ** {
96 free((char *) $1);
97 } */
98
99 %include "exclusions.i"
100 %ignore csoundSetCscoreCallback(CSOUND *,void (*cscoreCallback_)(CSOUND *));
101
102 // typemap for callbacks
103 %typemap(in) PyObject
104
105 *pyfunc {
106 if($input != Py_None)
107 if(!PyCallable_Check($input)){
108 PyErr_SetString(PyExc_TypeError, "Not a callable object!");
109 return NULL;
110 }
111 $1 = $input;
112 }
113
114 %{
115 // this will be used as an interface to the
116 // message callback
PythonMessageCallback(CSOUND * in,int attr,const char * format,va_list valist)117 static void PythonMessageCallback(CSOUND *in, int attr,
118 const char *format, va_list valist){
119
120 PyObject *res;
121 Csound *p = (Csound *) csoundGetHostData(in);
122 pycbdata *pydata = (pycbdata *)p->pydata;
123 PyObject *pyfunc = pydata->mfunc, *arg;
124 char *mbuf = new char[sizeof(format)*10 + 256];
125 vsprintf(mbuf, format, valist);
126 //if(ch = strrchr(mbuf, '\n')) *ch = '\0';
127 if (strlen(mbuf) > 1){
128 #ifndef PYTHON_23_or_older
129 if(!PyEval_ThreadsInitialized())
130 #endif
131 PyEval_InitThreads();
132 PyGILState_STATE gst;
133 // printf("MESS BEFORE \n");
134 gst = PyGILState_Ensure();
135 arg = Py_BuildValue("(s)", mbuf);
136 res = PyEval_CallObject(pyfunc, arg);
137 if (res == NULL){
138 PyErr_SetString(PyExc_TypeError, "Exception in callback");
139 }else Py_DECREF(res);
140 // printf("Mes: %s \n", mbuf);
141 PyGILState_Release(gst);
142 // printf("MESS OVER \n");
143 }
144 delete[] mbuf;
145 }
VoidMessageCallback(CSOUND * in,int attr,const char * format,va_list valist)146 static void VoidMessageCallback(CSOUND *in, int attr,
147 const char *format, va_list valist){
148 //printf("void message callback\n");
149 }
150
151
PythonInChannelCallback(CSOUND * in,const char * chan,void * v,const void * channelType)152 static void PythonInChannelCallback(CSOUND *in, const char *chan, void *v,
153 const void *channelType){
154
155 PyObject *res;
156 Csound *p = (Csound *) csoundGetHostData(in);
157 pycbdata *pydata = (pycbdata *)p->pydata;
158 PyObject *pyfunc = pydata->invalfunc, *arg;
159 PyGILState_STATE gst;
160 MYFLT *val = (MYFLT *) v;
161 gst = PyGILState_Ensure();
162 arg = Py_BuildValue("(s)", chan);
163 res = PyEval_CallObject(pyfunc, arg);
164 if (res == NULL){
165 PyErr_SetString(PyExc_TypeError, "Exception in callback");
166 }else{
167 if(PyFloat_Check(res)) *val = (MYFLT) PyFloat_AsDouble(res);
168 else *val = 0.0;
169 Py_DECREF(res);
170 }
171 PyGILState_Release(gst);
172
173
174 }
175
PythonOutChannelCallback(CSOUND * in,const char * chan,void * v,const void * channelType)176 static void PythonOutChannelCallback(CSOUND *in, const char *chan, void *v,
177 const void *channelType) {
178
179 PyObject *res;
180 Csound *p = (Csound *) csoundGetHostData(in);
181 pycbdata *pydata = (pycbdata *)p->pydata;
182 PyObject *pyfunc = pydata->outvalfunc, *arg;
183 PyGILState_STATE gst;
184 MYFLT *val = (MYFLT *) v;
185 gst = PyGILState_Ensure();
186 arg = Py_BuildValue("(s,d)", chan, (double) *val);
187 res = PyEval_CallObject(pyfunc, arg);
188 if (res == NULL){
189 PyErr_SetString(PyExc_TypeError, "Exception in callback");
190 }else Py_DECREF(res);
191 PyGILState_Release(gst);
192
193 }
194
PythonMidiInOpen(CSOUND * in,void ** udata,const char * name)195 static int PythonMidiInOpen(CSOUND *in, void **udata, const char *name){
196
197 PyObject *res;
198 Csound *p = (Csound *) csoundGetHostData(in);
199 pycbdata *pydata = (pycbdata *)p->pydata;
200 PyObject *pyfunc = pydata->midiinopenfunc, *arg;
201 PyGILState_STATE gst;
202 gst = PyGILState_Ensure();
203 arg = Py_BuildValue("(s)", name);
204 res = PyEval_CallObject(pyfunc, arg);
205 if (res == NULL){
206 PyErr_SetString(PyExc_TypeError, "Exception in callback");
207 }else {
208 *udata = (void *) res;
209 }
210 PyGILState_Release(gst);
211 return 0;
212 }
213
PythonMidiInClose(CSOUND * in,void * udata)214 static int PythonMidiInClose(CSOUND *in, void *udata){
215 PyObject *res;
216 Csound *p = (Csound *) csoundGetHostData(in);
217 pycbdata *pydata = (pycbdata *)p->pydata;
218 PyObject *pyfunc = pydata->midiinclosefunc, *arg;
219 PyGILState_STATE gst;
220 gst = PyGILState_Ensure();
221 arg = Py_BuildValue("(O)", (PyObject *) udata);
222 res = PyEval_CallObject(pyfunc, arg);
223 if (res == NULL){
224 PyErr_SetString(PyExc_TypeError, "Exception in callback");
225 }else Py_DECREF(res);
226 Py_DECREF((PyObject *) udata);
227 PyGILState_Release(gst);
228 return 0;
229 }
230
PythonMidiRead(CSOUND * in,void * udata,unsigned char * buf,int nBytes)231 static int PythonMidiRead(CSOUND *in, void *udata,
232 unsigned char *buf, int nBytes){
233 PyObject *res;
234 int i;
235 Csound *p = (Csound *) csoundGetHostData(in);
236 pycbdata *pydata = (pycbdata *)p->pydata;
237 PyObject *pyfunc = pydata->midireadfunc, *arg;
238 PyGILState_STATE gst;
239 gst = PyGILState_Ensure();
240 arg = Py_BuildValue("(O,i)", (PyObject *) udata, nBytes);
241 res = PyEval_CallObject(pyfunc, arg);
242 if (res == NULL){
243 PyErr_SetString(PyExc_TypeError, "Exception in callback");
244 }else {
245 if(PyList_Check(res))
246 for(i=0; i < nBytes; i++)
247 buf[i] = (char) PyInt_AsLong(PyList_GetItem(res,i));
248 else for(i=0; i < nBytes; i++) buf[i] = 0;
249 Py_DECREF(res);
250 }
251 PyGILState_Release(gst);
252 return 0;
253 }
254
pythonMessageCallback(CSOUND * csound,int attr,const char * format,va_list valist)255 static void pythonMessageCallback(CSOUND *csound,
256 int attr, const char *format, va_list valist)
257 {
258 char buffer[8192];
259 static std::string lineBuffer = "print '''"; // FIXME
260 unsigned int i, len;
261 #ifdef HAVE_C99
262 len = (unsigned int) vsnprintf(&(buffer[0]), (size_t) 8192, format, valist);
263 if (len >= 8192U)
264 {
265 PyRun_SimpleString("print '''Error: message buffer overflow'''");
266 return;
267 }
268 #else
269 len = (unsigned int) vsprintf(&(buffer[0]), format, valist);
270 if (len >= 8192U)
271 {
272 PyRun_SimpleString("print '''Error: message buffer overflow'''");
273 exit(-1);
274 }
275 #endif
276 for (i = 0; i < len; i++) {
277 if (buffer[i] == '\n') {
278 lineBuffer += "'''";
279 PyRun_SimpleString(lineBuffer.c_str());
280 lineBuffer = "print '''";
281 continue;
282 }
283 if (buffer[i] == '\'' || buffer[i] == '\\')
284 lineBuffer += '\\';
285 lineBuffer += buffer[i];
286 }
287 }
288
289 %}
290
291 %ignore csoundSetHostData(CSOUND *, void *);
292 %ignore csoundGetHostData(CSOUND *);
293 %include "csound.h"
294 %include "cfgvar.h"
295 %apply MYFLT &OUTPUT { MYFLT &dflt, MYFLT &min, MYFLT &max };
296 %apply MYFLT &OUTPUT { MYFLT &value };
297
298
299 %ignore Csound::SetCscoreCallback(void (*cscoreCallback_)(CSOUND *));
300 %ignore Csound::SetOutputChannelCallback(channelCallback_t inputChannelCalback);
301 %ignore Csound::SetInputChannelCallback(channelCallback_t inputChannelCalback);
302 %ignore Csound::SetExternalMidiInOpenCallback(int (*)(CSOUND *, void *, const char*));
303 %ignore Csound::SetExternalMidiReadCallback(int (*)(CSOUND *, void *, unsigned char *, int));
304 %ignore Csound::SetExternalMidiInCloseCallback(int (*)(CSOUND *, void *));
305
306 %ignore Csound::SetHostData(void *);
307 %ignore Csound::GetHostData();
308 %ignore Csound::SetMessageCallback(void (*)(CSOUND *, int attr,const char *format, va_list valist));
309 %include "csound.hpp"
310
311 %extend Csound {
SetHostData(PyObject * data)312 void SetHostData(PyObject *data){
313 ((pycbdata *)self->pydata)->hostdata = data;
314 }
GetHostData()315 PyObject *GetHostData() {
316 return ((pycbdata *)self->pydata)->hostdata;
317 }
318 //#ifndef PYTHON_23_or_older
SetMessageCallback(PyObject * pyfunc)319 void SetMessageCallback(PyObject *pyfunc){
320 // thread safety mechanism
321 if (pyfunc == Py_None){
322 Py_XINCREF(pyfunc);
323 self->SetMessageCallback(VoidMessageCallback);
324 return;
325 }
326
327 pycbdata *pydata = (pycbdata *) self->pydata;
328 if(pydata->mfunc == NULL) {
329 if(!PyEval_ThreadsInitialized()) PyEval_InitThreads();
330 }
331 else Py_XDECREF(pydata->mfunc);
332 pydata->mfunc = pyfunc;
333 self->SetMessageCallback(PythonMessageCallback);
334 Py_XINCREF(pyfunc);
335 }
336
SetInputChannelCallback(PyObject * pyfunc)337 void SetInputChannelCallback(PyObject *pyfunc){
338 // thread safety mechanism
339 pycbdata *pydata = (pycbdata *) self->pydata;
340 if(pydata->invalfunc == NULL) {
341 if(!PyEval_ThreadsInitialized()) PyEval_InitThreads();
342 }
343 else Py_XDECREF(pydata->invalfunc);
344 pydata->invalfunc = pyfunc;
345 self->SetInputChannelCallback(PythonInChannelCallback);
346 Py_XINCREF(pyfunc);
347 }
348
SetOutputChannelCallback(PyObject * pyfunc)349 void SetOutputChannelCallback(PyObject *pyfunc){
350 // thread safety mechanism
351 pycbdata *pydata = (pycbdata *) self->pydata;
352 if(pydata->outvalfunc == NULL){
353 if(!PyEval_ThreadsInitialized()) PyEval_InitThreads();
354 }
355 else Py_XDECREF(pydata->outvalfunc);
356
357 pydata->outvalfunc = pyfunc;
358 self->SetOutputChannelCallback(PythonOutChannelCallback);
359 Py_XINCREF(pyfunc);
360 }
SetExternalMidiInOpenCallback(PyObject * pyfunc)361 void SetExternalMidiInOpenCallback(PyObject *pyfunc){
362 // thread safety mechanism
363 pycbdata *pydata = (pycbdata *) self->pydata;
364 if(pydata->midiinopenfunc == NULL) {
365 if(!PyEval_ThreadsInitialized()) PyEval_InitThreads();
366 }
367 else Py_XDECREF(pydata->midiinopenfunc);
368 pydata->midiinopenfunc = pyfunc;
369 self->SetExternalMidiInOpenCallback(PythonMidiInOpen);
370 Py_XINCREF(pyfunc);
371 }
372
SetExternalMidiInCloseCallback(PyObject * pyfunc)373 void SetExternalMidiInCloseCallback(PyObject *pyfunc){
374 // thread safety mechanism
375 pycbdata *pydata = (pycbdata *) self->pydata;
376 if(pydata->midiinclosefunc == NULL) {
377 if(!PyEval_ThreadsInitialized()) PyEval_InitThreads();
378 }
379 else Py_XDECREF(pydata->midiinclosefunc);
380 pydata->midiinopenfunc = pyfunc;
381 self->SetExternalMidiInCloseCallback(PythonMidiInClose);
382 Py_XINCREF(pyfunc);
383 }
384
385
SetExternalMidiReadCallback(PyObject * pyfunc)386 void SetExternalMidiReadCallback(PyObject *pyfunc){
387 // thread safety mechanism
388 pycbdata *pydata = (pycbdata *) self->pydata;
389 if(pydata->midireadfunc == NULL) {
390 if(!PyEval_ThreadsInitialized()) PyEval_InitThreads();
391 }
392 else Py_XDECREF(pydata->midireadfunc);
393 pydata->midiinopenfunc = pyfunc;
394 self->SetExternalMidiReadCallback(PythonMidiRead);
395 Py_XINCREF(pyfunc);
396 }
397 //#endif
398 }
399
400 %clear MYFLT &dflt;
401 %clear MYFLT &min;
402 %clear MYFLT &max;
403 %clear MYFLT &value;
404
405
406 %{
407 // this will be used as an interface to the
408 // callback
PythonCallback(void * p)409 static void PythonCallback(void *p){
410
411 PyObject *res;
412 PyGILState_STATE stat;
413 CsoundPerformanceThread *t = (CsoundPerformanceThread *) p;
414 stat = PyGILState_Ensure();
415 res = PyEval_CallObject(t->pydata.func, t->pydata.data);
416 if (res == NULL){
417 PyErr_SetString(PyExc_TypeError, "Exception in callback");
418 }
419 else Py_DECREF(res);
420 PyGILState_Release(stat);
421 }
422 %}
423
424
425 %ignore CsoundPerformanceThread::SetProcessCallback(void (*Callback)(void *), void *cbdata);
426
427 %include "cs_glue.hpp"
428 %include "csPerfThread.hpp"
429
430 %extend CsoundPerformanceThread {
431 // Set the Python callback
SetProcessCallback(PyObject * pyfunc,PyObject * p)432 void SetProcessCallback(PyObject *pyfunc, PyObject *p){
433 if(self->GetProcessCallback() == NULL) {
434 #ifndef PYTHON_23_or_older
435 if(!PyEval_ThreadsInitialized())
436 #endif
437 PyEval_InitThreads();
438 }
439 else Py_XDECREF(self->pydata.func);
440 self->pydata.func = pyfunc;
441 self->pydata.data = Py_BuildValue("(O)", p);
442 self->SetProcessCallback(PythonCallback, (void *)self);
443 Py_XINCREF(pyfunc);
444
445 }
446
447
448 }
449
450 //#ifndef MACOSX
451 %include "CsoundFile.hpp"
452 //#endif
453 %include "CppSound.hpp"
454 /*
455 %include "filebuilding.h"
456 %include "Soundfile.hpp"
457 */
458
459
460 %extend CppSound {
setPythonMessageCallback()461 void setPythonMessageCallback()
462 {
463 self->SetMessageCallback(pythonMessageCallback);
464 }
465
466
467 };
468