7 #include <structmember.h>
9 #include "jack_mixer.h"
16 jack_mixer_scale_t scale;
20 Scale_dealloc(ScaleObject *self)
23 scale_destroy(self->scale);
24 self->ob_type->tp_free((PyObject*)self);
28 Scale_init(ScaleObject *self, PyObject *args, PyObject *kwds)
30 self->scale = scale_create();
35 Scale_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
39 self = (ScaleObject*)type->tp_alloc(type, 0);
41 return (PyObject*)self;
45 Scale_add_threshold(ScaleObject *self, PyObject *args)
47 float db, scale_value;
49 if (! PyArg_ParseTuple(args, "ff", &db, &scale_value)) return NULL;
51 scale_add_threshold(self->scale, db, scale_value);
58 Scale_calculate_coefficients(ScaleObject *self, PyObject *args)
60 if (! PyArg_ParseTuple(args, "")) return NULL;
61 scale_calculate_coefficients(self->scale);
67 Scale_db_to_scale(ScaleObject *self, PyObject *args)
70 if (! PyArg_ParseTuple(args, "d", &db)) return NULL;
71 return PyFloat_FromDouble(scale_db_to_scale(self->scale, db));
75 Scale_scale_to_db(ScaleObject *self, PyObject *args)
78 if (! PyArg_ParseTuple(args, "d", &scale_value)) return NULL;
79 return PyFloat_FromDouble(scale_scale_to_db(self->scale, scale_value));
82 static PyMethodDef Scale_methods[] = {
83 {"add_threshold", (PyCFunction)Scale_add_threshold, METH_VARARGS, "Add threshold"},
84 {"calculate_coefficients", (PyCFunction)Scale_calculate_coefficients,
85 METH_VARARGS, "Calculate coefficients"},
86 {"db_to_scale", (PyCFunction)Scale_db_to_scale, METH_VARARGS, "dB to scale"},
87 {"scale_to_db", (PyCFunction)Scale_scale_to_db, METH_VARARGS, "scale to dB"},
91 static PyTypeObject ScaleType = {
92 PyObject_HEAD_INIT(NULL)
94 "jack_mixer_c.Scale", /*tp_name*/
95 sizeof(ScaleObject), /*tp_basicsize*/
97 (destructor)Scale_dealloc, /*tp_dealloc*/
104 0, /*tp_as_sequence*/
112 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
113 "Scale objects", /* tp_doc */
116 0, /* tp_richcompare */
117 0, /* tp_weaklistoffset */
120 Scale_methods, /* tp_methods */
125 0, /* tp_descr_get */
126 0, /* tp_descr_set */
127 0, /* tp_dictoffset */
128 (initproc)Scale_init, /* tp_init */
130 Scale_new, /* tp_new */
138 PyObject *midi_change_callback;
139 jack_mixer_channel_t channel;
143 Channel_dealloc(ChannelObject *self)
145 Py_XDECREF(self->midi_change_callback);
146 self->ob_type->tp_free((PyObject*)self);
150 Channel_init(ChannelObject *self, PyObject *args, PyObject *kwds)
152 self->midi_change_callback = NULL;
157 Channel_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
161 self = (ChannelObject*)type->tp_alloc(type, 0);
164 self->channel = NULL;
165 self->midi_change_callback = NULL;
168 return (PyObject*)self;
172 Channel_get_is_stereo(ChannelObject *self, void *closure)
176 bool is_stereo = channel_is_stereo(self->channel);
187 Channel_get_volume(ChannelObject *self, void *closure)
189 return PyFloat_FromDouble(channel_volume_read(self->channel));
193 Channel_set_volume(ChannelObject *self, PyObject *value, void *closure)
195 channel_volume_write(self->channel, PyFloat_AsDouble(value));
200 Channel_get_balance(ChannelObject *self, void *closure)
202 return PyFloat_FromDouble(channel_balance_read(self->channel));
206 Channel_set_balance(ChannelObject *self, PyObject *value, void *closure)
208 channel_balance_write(self->channel, PyFloat_AsDouble(value));
213 Channel_get_mute(ChannelObject *self, void *closure)
217 if (channel_is_muted(self->channel)) {
227 Channel_set_mute(ChannelObject *self, PyObject *value, void *closure)
229 if (value == Py_True) {
230 channel_mute(self->channel);
232 channel_unmute(self->channel);
238 Channel_get_solo(ChannelObject *self, void *closure)
242 if (channel_is_soloed(self->channel)) {
252 Channel_set_solo(ChannelObject *self, PyObject *value, void *closure)
254 if (value == Py_True) {
255 channel_solo(self->channel);
257 channel_unsolo(self->channel);
263 Channel_get_meter(ChannelObject *self, void *closure)
268 if (channel_is_stereo(self->channel)) {
269 result = PyTuple_New(2);
270 channel_stereo_meter_read(self->channel, &left, &right);
271 PyTuple_SetItem(result, 0, PyFloat_FromDouble(left));
272 PyTuple_SetItem(result, 1, PyFloat_FromDouble(right));
274 result = PyTuple_New(1);
275 channel_mono_meter_read(self->channel, &left);
276 PyTuple_SetItem(result, 0, PyFloat_FromDouble(left));
282 Channel_get_abspeak(ChannelObject *self, void *closure)
284 return PyFloat_FromDouble(channel_abspeak_read(self->channel));
288 Channel_set_abspeak(ChannelObject *self, PyObject *value, void *closure)
290 if (value != Py_None) {
291 fprintf(stderr, "abspeak can only be reset (set to None)\n");
294 channel_abspeak_reset(self->channel);
299 Channel_set_midi_scale(ChannelObject *self, PyObject *value, void *closure)
301 ScaleObject *scale_object = (ScaleObject*)value; /* XXX: check */
303 channel_set_midi_scale(self->channel, scale_object->scale);
309 Channel_get_midi_change_callback(ChannelObject *self, void *closure)
311 if (self->midi_change_callback) {
312 Py_INCREF(self->midi_change_callback);
313 return self->midi_change_callback;
321 channel_midi_callback(void *userdata)
323 ChannelObject *self = (ChannelObject*)userdata;
324 PyGILState_STATE gstate;
326 gstate = PyGILState_Ensure();
327 PyObject_CallObject(self->midi_change_callback, NULL);
328 PyGILState_Release(gstate);
332 Channel_set_midi_change_callback(ChannelObject *self, PyObject *value, void *closure)
334 if (value == Py_None) {
335 self->midi_change_callback = NULL;
336 channel_set_midi_change_callback(self->channel, NULL, NULL);
338 if (!PyCallable_Check(value)) {
339 PyErr_SetString(PyExc_TypeError, "value must be callable");
342 if (self->midi_change_callback) {
343 Py_XDECREF(self->midi_change_callback);
346 self->midi_change_callback = value;
347 channel_set_midi_change_callback(self->channel,
348 channel_midi_callback, self);
355 Channel_get_name(ChannelObject *self, void *closure)
357 return PyString_FromString(channel_get_name(self->channel));
361 Channel_set_name(ChannelObject *self, PyObject *value, void *closure)
363 channel_rename(self->channel, PyString_AsString(value));
368 static PyGetSetDef Channel_getseters[] = {
370 (getter)Channel_get_is_stereo, NULL,
371 "mono/stereo", NULL},
373 (getter)Channel_get_volume, (setter)Channel_set_volume,
376 (getter)Channel_get_balance, (setter)Channel_set_balance,
379 (getter)Channel_get_mute, (setter)Channel_set_mute,
382 (getter)Channel_get_solo, (setter)Channel_set_solo,
385 (getter)Channel_get_meter, NULL,
388 (getter)Channel_get_abspeak, (setter)Channel_set_abspeak,
391 NULL, (setter)Channel_set_midi_scale,
393 {"midi_change_callback",
394 (getter)Channel_get_midi_change_callback,
395 (setter)Channel_set_midi_change_callback,
396 "midi change callback", NULL},
398 (getter)Channel_get_name,
399 (setter)Channel_set_name,
405 Channel_remove(ChannelObject *self, PyObject *args)
407 if (! PyArg_ParseTuple(args, "")) return NULL;
408 remove_channel(self->channel);
414 static PyMethodDef channel_methods[] = {
415 {"remove", (PyCFunction)Channel_remove, METH_VARARGS, "Remove"},
419 static PyTypeObject ChannelType = {
420 PyObject_HEAD_INIT(NULL)
422 "jack_mixer_c.Channel", /*tp_name*/
423 sizeof(ChannelObject), /*tp_basicsize*/
425 (destructor)Channel_dealloc, /*tp_dealloc*/
432 0, /*tp_as_sequence*/
440 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
441 "Channel objects", /* tp_doc */
444 0, /* tp_richcompare */
445 0, /* tp_weaklistoffset */
448 channel_methods, /* tp_methods */
450 Channel_getseters, /* tp_getset */
453 0, /* tp_descr_get */
454 0, /* tp_descr_set */
455 0, /* tp_dictoffset */
456 (initproc)Channel_init, /* tp_init */
458 Channel_new, /* tp_new */
462 Channel_New(jack_mixer_channel_t channel)
465 self = (ChannelObject*)PyObject_NEW(ChannelObject, &ChannelType);
467 self->channel = channel;
468 self->midi_change_callback = NULL;
470 return (PyObject*)self;
477 PyObject *main_mix_channel;
482 Mixer_dealloc(MixerObject *self)
484 Py_XDECREF(self->main_mix_channel);
486 destroy(self->mixer);
487 self->ob_type->tp_free((PyObject*)self);
491 Mixer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
495 self = (MixerObject*)type->tp_alloc(type, 0);
498 self->main_mix_channel = NULL;
502 return (PyObject*)self;
506 Mixer_init(MixerObject *self, PyObject *args, PyObject *kwds)
508 static char *kwlist[] = {"name", NULL};
511 if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &name))
514 self->mixer = create(name);
515 if (self->mixer == NULL) {
519 self->main_mix_channel = Channel_New(get_main_mix_channel(self->mixer));
524 static PyMemberDef Mixer_members[] = {
525 {"main_mix_channel", T_OBJECT, offsetof(MixerObject, main_mix_channel), 0, "main_mix_channel"},
530 Mixer_get_channels_count(MixerObject *self, void *closure)
532 return PyInt_FromLong(get_channels_count(self->mixer));
535 static PyGetSetDef Mixer_getseters[] = {
536 {"channels_count", (getter)Mixer_get_channels_count, NULL,
537 "channels count", NULL},
542 Mixer_add_channel(MixerObject *self, PyObject *args)
546 jack_mixer_channel_t channel;
548 if (! PyArg_ParseTuple(args, "sb", &name, &stereo)) return NULL;
550 channel = add_channel(self->mixer, name, (bool)stereo);
552 return Channel_New(channel);
555 static PyMethodDef Mixer_methods[] = {
556 {"add_channel", (PyCFunction)Mixer_add_channel, METH_VARARGS, "Add a new channel"},
557 // {"remove_channel", (PyCFunction)Mixer_remove_channel, METH_VARARGS, "Remove a channel"},
561 static PyTypeObject MixerType = {
562 PyObject_HEAD_INIT(NULL)
564 "jack_mixer_c.Mixer", /*tp_name*/
565 sizeof(MixerObject), /*tp_basicsize*/
567 (destructor)Mixer_dealloc, /*tp_dealloc*/
574 0, /*tp_as_sequence*/
582 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
583 "Mixer objects", /* tp_doc */
586 0, /* tp_richcompare */
587 0, /* tp_weaklistoffset */
590 Mixer_methods, /* tp_methods */
591 Mixer_members, /* tp_members */
592 Mixer_getseters, /* tp_getset */
595 0, /* tp_descr_get */
596 0, /* tp_descr_set */
597 0, /* tp_dictoffset */
598 (initproc)Mixer_init, /* tp_init */
600 Mixer_new, /* tp_new */
604 static PyMethodDef jack_mixer_methods[] = {
605 {NULL} /* Sentinel */
610 PyMODINIT_FUNC initjack_mixer_c(void)
614 if (PyType_Ready(&MixerType) < 0)
616 if (PyType_Ready(&ChannelType) < 0)
618 if (PyType_Ready(&ScaleType) < 0)
621 m = Py_InitModule3("jack_mixer_c", jack_mixer_methods, "Jack Mixer C Helper Module");
623 Py_INCREF(&MixerType);
624 PyModule_AddObject(m, "Mixer", (PyObject*)&MixerType);
625 Py_INCREF(&ChannelType);
626 PyModule_AddObject(m, "Channel", (PyObject*)&ChannelType);
627 Py_INCREF(&ScaleType);
628 PyModule_AddObject(m, "Scale", (PyObject*)&ScaleType);