1
/*************************************************************************
2
* Copyright 2010 Olivier Belanger *
4
* This file is part of pyo, a python module to help digital signal *
5
* processing script creation. *
7
* pyo is free software: you can redistribute it and/or modify *
8
* it under the terms of the GNU General Public License as published by *
9
* the Free Software Foundation, either version 3 of the License, or *
10
* (at your option) any later version. *
12
* pyo 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 *
15
* GNU General Public License for more details. *
17
* You should have received a copy of the GNU General Public License *
18
* along with pyo. If not, see <http://www.gnu.org/licenses/>. *
19
*************************************************************************/
22
#include "structmember.h"
23
#include "pyomodule.h"
24
#include "streammodule.h"
25
#include "servermodule.h"
26
#include "dummymodule.h"
40
Pattern_generate_i(Pattern *self) {
46
tm = PyFloat_AS_DOUBLE(self->time);
48
for (i=0; i<self->bufsize; i++) {
49
if (self->currentTime >= tm) {
51
self->currentTime = 0.;
54
self->currentTime += self->sampleToSec;
56
if (flag == 1 || self->init == 1) {
58
result = PyObject_Call((PyObject *)self->callable, PyTuple_New(0), NULL);
65
Pattern_generate_a(Pattern *self) {
69
MYFLT *tm = Stream_getData((Stream *)self->time_stream);
72
for (i=0; i<self->bufsize; i++) {
73
if (self->currentTime >= tm[i]) {
75
self->currentTime = 0.;
78
self->currentTime += self->sampleToSec;
80
if (flag == 1 || self->init == 1) {
82
result = PyObject_Call((PyObject *)self->callable, PyTuple_New(0), NULL);
90
Pattern_setProcMode(Pattern *self)
92
int procmode = self->modebuffer[0];
95
self->proc_func_ptr = Pattern_generate_i;
98
self->proc_func_ptr = Pattern_generate_a;
104
Pattern_compute_next_data_frame(Pattern *self)
106
(*self->proc_func_ptr)(self);
110
Pattern_traverse(Pattern *self, visitproc visit, void *arg)
113
Py_VISIT(self->callable);
114
Py_VISIT(self->time);
115
Py_VISIT(self->time_stream);
120
Pattern_clear(Pattern *self)
123
Py_CLEAR(self->callable);
124
Py_CLEAR(self->time);
125
Py_CLEAR(self->time_stream);
130
Pattern_dealloc(Pattern* self)
134
self->ob_type->tp_free((PyObject*)self);
137
static PyObject * Pattern_deleteStream(Pattern *self) { DELETE_STREAM };
140
Pattern_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
144
self = (Pattern *)type->tp_alloc(type, 0);
146
self->time = PyFloat_FromDouble(1.);
147
self->modebuffer[0] = 0;
151
Stream_setFunctionPtr(self->stream, Pattern_compute_next_data_frame);
152
self->mode_func_ptr = Pattern_setProcMode;
154
Stream_setStreamActive(self->stream, 0);
156
self->sampleToSec = 1. / self->sr;
157
self->currentTime = 0.;
159
return (PyObject *)self;
163
Pattern_init(Pattern *self, PyObject *args, PyObject *kwds)
165
PyObject *timetmp=NULL, *calltmp=NULL;
167
static char *kwlist[] = {"callable", "time", NULL};
169
if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, &calltmp, &timetmp))
173
PyObject_CallMethod((PyObject *)self, "setFunction", "O", calltmp);
177
PyObject_CallMethod((PyObject *)self, "setTime", "O", timetmp);
180
Py_INCREF(self->stream);
181
PyObject_CallMethod(self->server, "addStream", "O", self->stream);
183
(*self->mode_func_ptr)(self);
189
static PyObject * Pattern_getServer(Pattern* self) { GET_SERVER };
190
static PyObject * Pattern_getStream(Pattern* self) { GET_STREAM };
193
Pattern_play(Pattern *self, PyObject *args, PyObject *kwds)
199
static PyObject * Pattern_stop(Pattern *self) { STOP };
202
Pattern_setFunction(Pattern *self, PyObject *arg)
206
if (! PyCallable_Check(arg)) {
207
PyErr_SetString(PyExc_TypeError, "The callable attribute must be a valid Python function.");
213
Py_XDECREF(self->callable);
215
self->callable = tmp;
222
Pattern_setTime(Pattern *self, PyObject *arg)
224
PyObject *tmp, *streamtmp;
231
int isNumber = PyNumber_Check(arg);
235
Py_DECREF(self->time);
237
self->time = PyNumber_Float(tmp);
238
self->modebuffer[0] = 0;
242
streamtmp = PyObject_CallMethod((PyObject *)self->time, "_getStream", NULL);
243
Py_INCREF(streamtmp);
244
Py_XDECREF(self->time_stream);
245
self->time_stream = (Stream *)streamtmp;
246
self->modebuffer[0] = 1;
249
(*self->mode_func_ptr)(self);
255
static PyMemberDef Pattern_members[] = {
256
{"server", T_OBJECT_EX, offsetof(Pattern, server), 0, "Pyo server."},
257
{"stream", T_OBJECT_EX, offsetof(Pattern, stream), 0, "Stream object."},
258
{"time", T_OBJECT_EX, offsetof(Pattern, time), 0, "Pattern time factor."},
259
{NULL} /* Sentinel */
262
static PyMethodDef Pattern_methods[] = {
263
{"getServer", (PyCFunction)Pattern_getServer, METH_NOARGS, "Returns server object."},
264
{"_getStream", (PyCFunction)Pattern_getStream, METH_NOARGS, "Returns stream object."},
265
{"deleteStream", (PyCFunction)Pattern_deleteStream, METH_NOARGS, "Remove stream from server and delete the object."},
266
{"play", (PyCFunction)Pattern_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
267
{"stop", (PyCFunction)Pattern_stop, METH_NOARGS, "Stops computing."},
268
{"setTime", (PyCFunction)Pattern_setTime, METH_O, "Sets time factor."},
269
{"setFunction", (PyCFunction)Pattern_setFunction, METH_O, "Sets the function to be called."},
270
{NULL} /* Sentinel */
273
PyTypeObject PatternType = {
274
PyObject_HEAD_INIT(NULL)
276
"_pyo.Pattern_base", /*tp_name*/
277
sizeof(Pattern), /*tp_basicsize*/
279
(destructor)Pattern_dealloc, /*tp_dealloc*/
286
0, /*tp_as_sequence*/
294
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
295
"Pattern objects. Create a metronome.", /* tp_doc */
296
(traverseproc)Pattern_traverse, /* tp_traverse */
297
(inquiry)Pattern_clear, /* tp_clear */
298
0, /* tp_richcompare */
299
0, /* tp_weaklistoffset */
302
Pattern_methods, /* tp_methods */
303
Pattern_members, /* tp_members */
307
0, /* tp_descr_get */
308
0, /* tp_descr_set */
309
0, /* tp_dictoffset */
310
(initproc)Pattern_init, /* tp_init */
312
Pattern_new, /* tp_new */
321
Stream *input_stream;
328
Score_selector(Score *self) {
329
int i, inval, state, res;
331
MYFLT *in = Stream_getData((Stream *)self->input_stream);
333
for (i=0; i<self->bufsize; i++) {
335
if (inval != self->last_value) {
336
res = sprintf(self->curfname, "%s%i()\n", self->fname, inval);
337
state = PyRun_SimpleString(self->curfname);
338
self->last_value = inval;
344
Score_setProcMode(Score *self)
346
self->proc_func_ptr = Score_selector;
350
Score_compute_next_data_frame(Score *self)
352
(*self->proc_func_ptr)(self);
356
Score_traverse(Score *self, visitproc visit, void *arg)
359
Py_VISIT(self->input);
360
Py_VISIT(self->input_stream);
365
Score_clear(Score *self)
368
Py_CLEAR(self->input);
369
Py_CLEAR(self->input_stream);
374
Score_dealloc(Score* self)
377
free(self->curfname);
379
self->ob_type->tp_free((PyObject*)self);
382
static PyObject * Score_deleteStream(Score *self) { DELETE_STREAM };
385
Score_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
389
self = (Score *)type->tp_alloc(type, 0);
391
self->last_value = -99;
394
Stream_setFunctionPtr(self->stream, Score_compute_next_data_frame);
395
self->mode_func_ptr = Score_setProcMode;
397
return (PyObject *)self;
401
Score_init(Score *self, PyObject *args, PyObject *kwds)
403
PyObject *inputtmp, *input_streamtmp;
405
static char *kwlist[] = {"input", "fname", NULL};
407
if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|s", kwlist, &inputtmp, &self->fname))
412
Py_INCREF(self->stream);
413
PyObject_CallMethod(self->server, "addStream", "O", self->stream);
415
(*self->mode_func_ptr)(self);
421
static PyObject * Score_getServer(Score* self) { GET_SERVER };
422
static PyObject * Score_getStream(Score* self) { GET_STREAM };
424
static PyObject * Score_play(Score *self, PyObject *args, PyObject *kwds) { PLAY };
425
static PyObject * Score_stop(Score *self) { STOP };
427
static PyMemberDef Score_members[] = {
428
{"server", T_OBJECT_EX, offsetof(Score, server), 0, "Pyo server."},
429
{"stream", T_OBJECT_EX, offsetof(Score, stream), 0, "Stream object."},
430
{NULL} /* Sentinel */
433
static PyMethodDef Score_methods[] = {
434
{"getServer", (PyCFunction)Score_getServer, METH_NOARGS, "Returns server object."},
435
{"_getStream", (PyCFunction)Score_getStream, METH_NOARGS, "Returns stream object."},
436
{"deleteStream", (PyCFunction)Score_deleteStream, METH_NOARGS, "Remove stream from server and delete the object."},
437
{"play", (PyCFunction)Score_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
438
{"stop", (PyCFunction)Score_stop, METH_NOARGS, "Stops computing."},
439
{NULL} /* Sentinel */
442
PyTypeObject ScoreType = {
443
PyObject_HEAD_INIT(NULL)
445
"_pyo.Score_base", /*tp_name*/
446
sizeof(Score), /*tp_basicsize*/
448
(destructor)Score_dealloc, /*tp_dealloc*/
455
0, /*tp_as_sequence*/
463
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
464
"Score objects. Calls numbered function from an integer count.", /* tp_doc */
465
(traverseproc)Score_traverse, /* tp_traverse */
466
(inquiry)Score_clear, /* tp_clear */
467
0, /* tp_richcompare */
468
0, /* tp_weaklistoffset */
471
Score_methods, /* tp_methods */
472
Score_members, /* tp_members */
476
0, /* tp_descr_get */
477
0, /* tp_descr_set */
478
0, /* tp_dictoffset */
479
(initproc)Score_init, /* tp_init */
481
Score_new, /* tp_new */
497
CallAfter_generate(CallAfter *self) {
499
PyObject *tuple, *result;
501
for (i=0; i<self->bufsize; i++) {
502
if (self->currentTime >= self->time) {
503
if (self->arg == Py_None)
504
tuple = PyTuple_New(0);
506
tuple = PyTuple_New(1);
507
PyTuple_SET_ITEM(tuple, 0, self->arg);
509
result = PyObject_Call(self->callable, tuple, NULL);
512
PyObject_CallMethod((PyObject *)self, "stop", NULL);
515
self->currentTime += self->sampleToSec;
520
CallAfter_setProcMode(CallAfter *self)
522
self->proc_func_ptr = CallAfter_generate;
526
CallAfter_compute_next_data_frame(CallAfter *self)
528
(*self->proc_func_ptr)(self);
532
CallAfter_traverse(CallAfter *self, visitproc visit, void *arg)
535
Py_VISIT(self->callable);
541
CallAfter_clear(CallAfter *self)
544
Py_CLEAR(self->callable);
550
CallAfter_dealloc(CallAfter* self)
553
CallAfter_clear(self);
554
self->ob_type->tp_free((PyObject*)self);
557
static PyObject * CallAfter_deleteStream(CallAfter *self) { DELETE_STREAM };
560
CallAfter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
564
self = (CallAfter *)type->tp_alloc(type, 0);
570
Stream_setFunctionPtr(self->stream, CallAfter_compute_next_data_frame);
571
self->mode_func_ptr = CallAfter_setProcMode;
573
self->sampleToSec = 1. / self->sr;
574
self->currentTime = 0.;
576
return (PyObject *)self;
580
CallAfter_init(CallAfter *self, PyObject *args, PyObject *kwds)
582
PyObject *calltmp=NULL, *argtmp=NULL;
584
static char *kwlist[] = {"callable", "time", "arg", NULL};
586
if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_FO, kwlist, &calltmp, &self->time, &argtmp))
589
if (! PyCallable_Check(calltmp))
593
Py_DECREF(self->arg);
598
Py_XDECREF(self->callable);
599
self->callable = calltmp;
601
Py_INCREF(self->stream);
602
PyObject_CallMethod(self->server, "addStream", "O", self->stream);
604
(*self->mode_func_ptr)(self);
610
static PyObject * CallAfter_getServer(CallAfter* self) { GET_SERVER };
611
static PyObject * CallAfter_getStream(CallAfter* self) { GET_STREAM };
613
static PyObject * CallAfter_play(CallAfter *self, PyObject *args, PyObject *kwds) { PLAY };
614
static PyObject * CallAfter_stop(CallAfter *self) { STOP };
616
static PyMemberDef CallAfter_members[] = {
617
{"server", T_OBJECT_EX, offsetof(CallAfter, server), 0, "Pyo server."},
618
{"stream", T_OBJECT_EX, offsetof(CallAfter, stream), 0, "Stream object."},
619
{NULL} /* Sentinel */
622
static PyMethodDef CallAfter_methods[] = {
623
{"getServer", (PyCFunction)CallAfter_getServer, METH_NOARGS, "Returns server object."},
624
{"_getStream", (PyCFunction)CallAfter_getStream, METH_NOARGS, "Returns stream object."},
625
{"deleteStream", (PyCFunction)CallAfter_deleteStream, METH_NOARGS, "Remove stream from server and delete the object."},
626
{"play", (PyCFunction)CallAfter_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
627
{"stop", (PyCFunction)CallAfter_stop, METH_NOARGS, "Stops computing."},
628
{NULL} /* Sentinel */
631
PyTypeObject CallAfterType = {
632
PyObject_HEAD_INIT(NULL)
634
"_pyo.CallAfter_base", /*tp_name*/
635
sizeof(CallAfter), /*tp_basicsize*/
637
(destructor)CallAfter_dealloc, /*tp_dealloc*/
644
0, /*tp_as_sequence*/
652
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
653
"CallAfter objects. Create a metronome.", /* tp_doc */
654
(traverseproc)CallAfter_traverse, /* tp_traverse */
655
(inquiry)CallAfter_clear, /* tp_clear */
656
0, /* tp_richcompare */
657
0, /* tp_weaklistoffset */
660
CallAfter_methods, /* tp_methods */
661
CallAfter_members, /* tp_members */
665
0, /* tp_descr_get */
666
0, /* tp_descr_set */
667
0, /* tp_dictoffset */
668
(initproc)CallAfter_init, /* tp_init */
670
CallAfter_new, /* tp_new */