release: 13
[jack_mixer.git] / jack_mixer_c.c
blob3e93a7e55a1e0df0168c624b53ed376ade20cce2
1 /*
2 * This file is part of jack_mixer
4 * Copyright (C) 2009 Frederic Peters <fpeters@0d.be>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include <Python.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdbool.h>
26 #include <structmember.h>
28 #include "jack_mixer.h"
31 /** Scale Type **/
33 typedef struct {
34 PyObject_HEAD
35 jack_mixer_scale_t scale;
36 } ScaleObject;
38 static void
39 Scale_dealloc(ScaleObject *self)
41 if (self->scale)
42 scale_destroy(self->scale);
43 Py_TYPE(self)->tp_free((PyObject*)self);
46 static int
47 Scale_init(ScaleObject *self, PyObject *args, PyObject *kwds)
49 self->scale = scale_create();
50 return 0;
53 static PyObject*
54 Scale_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
56 ScaleObject *self;
58 self = (ScaleObject*)type->tp_alloc(type, 0);
60 return (PyObject*)self;
63 static PyObject*
64 Scale_add_threshold(ScaleObject *self, PyObject *args)
66 float db, scale_value;
68 if (! PyArg_ParseTuple(args, "ff", &db, &scale_value)) return NULL;
70 scale_add_threshold(self->scale, db, scale_value);
72 Py_INCREF(Py_None);
73 return Py_None;
76 static PyObject*
77 Scale_calculate_coefficients(ScaleObject *self, PyObject *args)
79 if (! PyArg_ParseTuple(args, "")) return NULL;
80 scale_calculate_coefficients(self->scale);
81 Py_INCREF(Py_None);
82 return Py_None;
85 static PyObject*
86 Scale_db_to_scale(ScaleObject *self, PyObject *args)
88 double db;
89 if (! PyArg_ParseTuple(args, "d", &db)) return NULL;
90 return PyFloat_FromDouble(scale_db_to_scale(self->scale, db));
93 static PyObject*
94 Scale_scale_to_db(ScaleObject *self, PyObject *args)
96 double scale_value;
97 if (! PyArg_ParseTuple(args, "d", &scale_value)) return NULL;
98 return PyFloat_FromDouble(scale_scale_to_db(self->scale, scale_value));
101 static PyMethodDef Scale_methods[] = {
102 {"add_threshold", (PyCFunction)Scale_add_threshold, METH_VARARGS, "Add threshold"},
103 {"calculate_coefficients", (PyCFunction)Scale_calculate_coefficients,
104 METH_VARARGS, "Calculate coefficients"},
105 {"db_to_scale", (PyCFunction)Scale_db_to_scale, METH_VARARGS, "dB to scale"},
106 {"scale_to_db", (PyCFunction)Scale_scale_to_db, METH_VARARGS, "scale to dB"},
107 {NULL}
110 static PyTypeObject ScaleType = {
111 PyVarObject_HEAD_INIT(NULL, 0)
112 "jack_mixer_c.Scale", /*tp_name*/
113 sizeof(ScaleObject), /*tp_basicsize*/
114 0, /*tp_itemsize*/
115 (destructor)Scale_dealloc, /*tp_dealloc*/
116 0, /*tp_print*/
117 0, /*tp_getattr*/
118 0, /*tp_setattr*/
119 0, /*tp_compare*/
120 0, /*tp_repr*/
121 0, /*tp_as_number*/
122 0, /*tp_as_sequence*/
123 0, /*tp_as_mapping*/
124 0, /*tp_hash */
125 0, /*tp_call*/
126 0, /*tp_str*/
127 0, /*tp_getattro*/
128 0, /*tp_setattro*/
129 0, /*tp_as_buffer*/
130 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
131 "Scale objects", /* tp_doc */
132 0, /* tp_traverse */
133 0, /* tp_clear */
134 0, /* tp_richcompare */
135 0, /* tp_weaklistoffset */
136 0, /* tp_iter */
137 0, /* tp_iternext */
138 Scale_methods, /* tp_methods */
139 0, /* tp_members */
140 0, /* tp_getset */
141 0, /* tp_base */
142 0, /* tp_dict */
143 0, /* tp_descr_get */
144 0, /* tp_descr_set */
145 0, /* tp_dictoffset */
146 (initproc)Scale_init, /* tp_init */
147 0, /* tp_alloc */
148 Scale_new, /* tp_new */
152 /** Channel Type **/
154 typedef struct {
155 PyObject_HEAD
156 PyObject *midi_change_callback;
157 jack_mixer_channel_t channel;
158 } ChannelObject;
160 static void
161 Channel_dealloc(ChannelObject *self)
163 Py_XDECREF(self->midi_change_callback);
164 Py_TYPE(self)->tp_free((PyObject*)self);
167 static int
168 Channel_init(ChannelObject *self, PyObject *args, PyObject *kwds)
170 self->midi_change_callback = NULL;
171 return 0;
174 static PyObject*
175 Channel_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
177 ChannelObject *self;
179 self = (ChannelObject*)type->tp_alloc(type, 0);
181 if (self != NULL) {
182 self->channel = NULL;
183 self->midi_change_callback = NULL;
186 return (PyObject*)self;
189 static PyObject*
190 Channel_get_is_stereo(ChannelObject *self, void *closure)
192 PyObject *result;
194 bool is_stereo = channel_is_stereo(self->channel);
195 if (is_stereo) {
196 result = Py_True;
197 } else {
198 result = Py_False;
200 Py_INCREF(result);
201 return result;
204 static PyObject*
205 Channel_get_volume(ChannelObject *self, void *closure)
207 return PyFloat_FromDouble(channel_volume_read(self->channel));
210 static int
211 Channel_set_volume(ChannelObject *self, PyObject *value, void *closure)
213 if (self->channel == NULL) {
214 PyErr_SetString(PyExc_RuntimeError, "unitialized channel");
215 return -1;
217 channel_volume_write(self->channel, PyFloat_AsDouble(value));
218 channel_set_midi_cc_volume_picked_up(self->channel, false);
219 return 0;
222 static PyObject*
223 Channel_get_balance(ChannelObject *self, void *closure)
225 return PyFloat_FromDouble(channel_balance_read(self->channel));
228 static int
229 Channel_set_balance(ChannelObject *self, PyObject *value, void *closure)
231 channel_balance_write(self->channel, PyFloat_AsDouble(value));
232 channel_set_midi_cc_balance_picked_up(self->channel, false);
233 return 0;
236 static PyObject*
237 Channel_get_out_mute(ChannelObject *self, void *closure)
239 PyObject *result;
241 if (channel_is_out_muted(self->channel)) {
242 result = Py_True;
243 } else {
244 result = Py_False;
246 Py_INCREF(result);
247 return result;
250 static int
251 Channel_set_out_mute(ChannelObject *self, PyObject *value, void *closure)
253 if (value == Py_True) {
254 channel_out_mute(self->channel);
255 } else {
256 channel_out_unmute(self->channel);
258 return 0;
261 static PyObject*
262 Channel_get_solo(ChannelObject *self, void *closure)
264 PyObject *result;
266 if (channel_is_soloed(self->channel)) {
267 result = Py_True;
268 } else {
269 result = Py_False;
271 Py_INCREF(result);
272 return result;
275 static int
276 Channel_set_solo(ChannelObject *self, PyObject *value, void *closure)
278 if (value == Py_True) {
279 channel_solo(self->channel);
280 } else {
281 channel_unsolo(self->channel);
283 return 0;
286 static PyObject*
287 Channel_get_meter(ChannelObject *self, void *closure)
289 PyObject *result;
290 double left, right;
292 if (channel_is_stereo(self->channel)) {
293 result = PyTuple_New(2);
294 channel_stereo_meter_read(self->channel, &left, &right);
295 PyTuple_SetItem(result, 0, PyFloat_FromDouble(left));
296 PyTuple_SetItem(result, 1, PyFloat_FromDouble(right));
297 } else {
298 result = PyTuple_New(1);
299 channel_mono_meter_read(self->channel, &left);
300 PyTuple_SetItem(result, 0, PyFloat_FromDouble(left));
302 return result;
305 static PyObject*
306 Channel_get_abspeak(ChannelObject *self, void *closure)
308 return PyFloat_FromDouble(channel_abspeak_read(self->channel));
311 static int
312 Channel_set_abspeak(ChannelObject *self, PyObject *value, void *closure)
314 if (value != Py_None) {
315 fprintf(stderr, "abspeak can only be reset (set to None)\n");
316 return -1;
318 channel_abspeak_reset(self->channel);
319 return 0;
322 static int
323 Channel_set_midi_scale(ChannelObject *self, PyObject *value, void *closure)
325 ScaleObject *scale_object = (ScaleObject*)value; /* XXX: check */
327 channel_set_midi_scale(self->channel, scale_object->scale);
328 return 0;
332 static PyObject*
333 Channel_get_midi_change_callback(ChannelObject *self, void *closure)
335 if (self->midi_change_callback) {
336 Py_INCREF(self->midi_change_callback);
337 return self->midi_change_callback;
338 } else {
339 Py_INCREF(Py_None);
340 return Py_None;
344 static void
345 channel_midi_callback(void *userdata)
347 ChannelObject *self = (ChannelObject*)userdata;
348 PyGILState_STATE gstate;
350 gstate = PyGILState_Ensure();
351 PyObject_CallObject(self->midi_change_callback, NULL);
352 PyGILState_Release(gstate);
355 static int
356 Channel_set_midi_change_callback(ChannelObject *self, PyObject *value, void *closure)
358 if (value == Py_None) {
359 self->midi_change_callback = NULL;
360 channel_set_midi_change_callback(self->channel, NULL, NULL);
361 } else {
362 if (!PyCallable_Check(value)) {
363 PyErr_SetString(PyExc_TypeError, "value must be callable");
364 return -1;
366 if (self->midi_change_callback) {
367 Py_XDECREF(self->midi_change_callback);
369 Py_INCREF(value);
370 self->midi_change_callback = value;
371 channel_set_midi_change_callback(self->channel,
372 channel_midi_callback, self);
375 return 0;
378 static PyObject*
379 Channel_get_name(ChannelObject *self, void *closure)
381 return PyUnicode_FromString(channel_get_name(self->channel));
384 static int
385 Channel_set_name(ChannelObject *self, PyObject *value, void *closure)
387 channel_rename(self->channel, PyUnicode_AsUTF8(value));
388 return 0;
391 static PyObject*
392 Channel_get_balance_midi_cc(ChannelObject *self, void *closure)
394 return PyLong_FromLong(channel_get_balance_midi_cc(self->channel));
397 static int
398 Channel_set_balance_midi_cc(ChannelObject *self, PyObject *value, void *closure)
400 int new_cc;
401 unsigned int result;
403 new_cc = PyLong_AsLong(value);
404 result = channel_set_balance_midi_cc(self->channel, new_cc);
405 if (result == 0) {
406 return 0;
408 if (result == 2) {
409 PyErr_SetString(PyExc_RuntimeError, "value out of range");
411 return -1;
414 static PyObject*
415 Channel_get_volume_midi_cc(ChannelObject *self, void *closure)
417 return PyLong_FromLong(channel_get_volume_midi_cc(self->channel));
420 static int
421 Channel_set_volume_midi_cc(ChannelObject *self, PyObject *value, void *closure)
423 int new_cc;
424 unsigned int result;
426 new_cc = PyLong_AsLong(value);
427 result = channel_set_volume_midi_cc(self->channel, new_cc);
428 if (result == 0) {
429 return 0;
431 if (result == 2) {
432 PyErr_SetString(PyExc_RuntimeError, "value out of range");
434 return -1;
437 static PyObject*
438 Channel_get_mute_midi_cc(ChannelObject *self, void *closure)
440 return PyLong_FromLong(channel_get_mute_midi_cc(self->channel));
443 static int
444 Channel_set_mute_midi_cc(ChannelObject *self, PyObject *value, void *closure)
446 int new_cc;
447 unsigned int result;
449 new_cc = PyLong_AsLong(value);
450 result = channel_set_mute_midi_cc(self->channel, new_cc);
451 if (result == 0) {
452 return 0;
454 if (result == 2) {
455 PyErr_SetString(PyExc_RuntimeError, "value out of range");
457 return -1;
460 static PyObject*
461 Channel_get_solo_midi_cc(ChannelObject *self, void *closure)
463 return PyLong_FromLong(channel_get_solo_midi_cc(self->channel));
466 static int
467 Channel_set_solo_midi_cc(ChannelObject *self, PyObject *value, void *closure)
469 int new_cc;
470 unsigned int result;
472 new_cc = PyLong_AsLong(value);
473 result = channel_set_solo_midi_cc(self->channel, new_cc);
474 if (result == 0) {
475 return 0;
477 if (result == 2) {
478 PyErr_SetString(PyExc_RuntimeError, "value out of range");
480 return -1;
483 static PyObject*
484 Channel_get_midi_in_got_events(ChannelObject *self, void *closure)
486 PyObject *result;
488 if (channel_get_midi_in_got_events(self->channel)) {
489 result = Py_True;
490 } else {
491 result = Py_False;
493 Py_INCREF(result);
494 return result;
497 static PyGetSetDef Channel_getseters[] = {
498 {"is_stereo",
499 (getter)Channel_get_is_stereo, NULL,
500 "mono/stereo", NULL},
501 {"volume",
502 (getter)Channel_get_volume, (setter)Channel_set_volume,
503 "volume", NULL},
504 {"balance",
505 (getter)Channel_get_balance, (setter)Channel_set_balance,
506 "balance", NULL},
507 {"out_mute",
508 (getter)Channel_get_out_mute, (setter)Channel_set_out_mute,
509 "out_mute", NULL},
510 {"solo",
511 (getter)Channel_get_solo, (setter)Channel_set_solo,
512 "solo", NULL},
513 {"meter",
514 (getter)Channel_get_meter, NULL,
515 "meter", NULL},
516 {"abspeak",
517 (getter)Channel_get_abspeak, (setter)Channel_set_abspeak,
518 "balance", NULL},
519 {"midi_scale",
520 NULL, (setter)Channel_set_midi_scale,
521 "midi scale", NULL},
522 {"midi_change_callback",
523 (getter)Channel_get_midi_change_callback,
524 (setter)Channel_set_midi_change_callback,
525 "midi change callback", NULL},
526 {"name",
527 (getter)Channel_get_name,
528 (setter)Channel_set_name,
529 "name", NULL},
530 {"balance_midi_cc",
531 (getter)Channel_get_balance_midi_cc,
532 (setter)Channel_set_balance_midi_cc,
533 "Balance MIDI CC", NULL},
534 {"volume_midi_cc",
535 (getter)Channel_get_volume_midi_cc,
536 (setter)Channel_set_volume_midi_cc,
537 "Volume MIDI CC", NULL},
538 {"mute_midi_cc",
539 (getter)Channel_get_mute_midi_cc,
540 (setter)Channel_set_mute_midi_cc,
541 "Mute MIDI CC", NULL},
542 {"solo_midi_cc",
543 (getter)Channel_get_solo_midi_cc,
544 (setter)Channel_set_solo_midi_cc,
545 "Mute MIDI CC", NULL},
546 {"midi_in_got_events",
547 (getter)Channel_get_midi_in_got_events, NULL,
548 "Got new MIDI IN events", NULL},
549 {NULL}
552 static PyObject*
553 Channel_remove(ChannelObject *self, PyObject *args)
555 if (! PyArg_ParseTuple(args, "")) return NULL;
556 remove_channel(self->channel);
557 Py_INCREF(Py_None);
558 return Py_None;
561 static PyObject*
562 Channel_autoset_volume_midi_cc(ChannelObject *self, PyObject *args)
564 if (! PyArg_ParseTuple(args, "")) return NULL;
565 channel_autoset_volume_midi_cc(self->channel);
566 Py_INCREF(Py_None);
567 return Py_None;
570 static PyObject*
571 Channel_autoset_balance_midi_cc(ChannelObject *self, PyObject *args)
573 if (! PyArg_ParseTuple(args, "")) return NULL;
574 channel_autoset_balance_midi_cc(self->channel);
575 Py_INCREF(Py_None);
576 return Py_None;
579 static PyObject*
580 Channel_autoset_mute_midi_cc(ChannelObject *self, PyObject *args)
582 if (! PyArg_ParseTuple(args, "")) return NULL;
583 channel_autoset_mute_midi_cc(self->channel);
584 Py_INCREF(Py_None);
585 return Py_None;
588 static PyObject*
589 Channel_autoset_solo_midi_cc(ChannelObject *self, PyObject *args)
591 if (! PyArg_ParseTuple(args, "")) return NULL;
592 channel_autoset_solo_midi_cc(self->channel);
593 Py_INCREF(Py_None);
594 return Py_None;
597 static PyMethodDef channel_methods[] = {
598 {"remove", (PyCFunction)Channel_remove, METH_VARARGS, "Remove"},
599 {"autoset_volume_midi_cc",
600 (PyCFunction)Channel_autoset_volume_midi_cc, METH_VARARGS, "Autoset Volume MIDI CC"},
601 {"autoset_balance_midi_cc",
602 (PyCFunction)Channel_autoset_balance_midi_cc, METH_VARARGS, "Autoset Balance MIDI CC"},
603 {"autoset_mute_midi_cc",
604 (PyCFunction)Channel_autoset_mute_midi_cc, METH_VARARGS, "Autoset Mute MIDI CC"},
605 {"autoset_solo_midi_cc",
606 (PyCFunction)Channel_autoset_solo_midi_cc, METH_VARARGS, "Autoset Solo MIDI CC"},
607 {NULL}
610 static PyTypeObject ChannelType = {
611 PyVarObject_HEAD_INIT(NULL, 0)
612 "jack_mixer_c.Channel", /*tp_name*/
613 sizeof(ChannelObject), /*tp_basicsize*/
614 0, /*tp_itemsize*/
615 (destructor)Channel_dealloc, /*tp_dealloc*/
616 0, /*tp_print*/
617 0, /*tp_getattr*/
618 0, /*tp_setattr*/
619 0, /*tp_compare*/
620 0, /*tp_repr*/
621 0, /*tp_as_number*/
622 0, /*tp_as_sequence*/
623 0, /*tp_as_mapping*/
624 0, /*tp_hash */
625 0, /*tp_call*/
626 0, /*tp_str*/
627 0, /*tp_getattro*/
628 0, /*tp_setattro*/
629 0, /*tp_as_buffer*/
630 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
631 "Channel objects", /* tp_doc */
632 0, /* tp_traverse */
633 0, /* tp_clear */
634 0, /* tp_richcompare */
635 0, /* tp_weaklistoffset */
636 0, /* tp_iter */
637 0, /* tp_iternext */
638 channel_methods, /* tp_methods */
639 0, /* tp_members */
640 Channel_getseters, /* tp_getset */
641 0, /* tp_base */
642 0, /* tp_dict */
643 0, /* tp_descr_get */
644 0, /* tp_descr_set */
645 0, /* tp_dictoffset */
646 (initproc)Channel_init, /* tp_init */
647 0, /* tp_alloc */
648 Channel_new, /* tp_new */
651 static PyObject*
652 Channel_New(jack_mixer_channel_t channel)
654 ChannelObject *self;
655 self = (ChannelObject*)PyObject_NEW(ChannelObject, &ChannelType);
656 if (self != NULL) {
657 self->channel = channel;
658 self->midi_change_callback = NULL;
660 return (PyObject*)self;
663 /** Output Channel Type **/
665 typedef struct {
666 PyObject_HEAD
667 PyObject *midi_change_callback;
668 jack_mixer_output_channel_t *output_channel;
669 } OutputChannelObject;
671 static int
672 OutputChannel_set_prefader(OutputChannelObject *self, PyObject *value, void *closure)
674 if (value == Py_True) {
675 output_channel_set_prefader(self->output_channel, true);
676 } else {
677 output_channel_set_prefader(self->output_channel, false);
679 return 0;
682 static PyObject*
683 OutputChannel_get_prefader(OutputChannelObject *self, void *closure)
685 PyObject *result;
687 if (output_channel_is_prefader(self->output_channel)) {
688 result = Py_True;
689 } else {
690 result = Py_False;
692 Py_INCREF(result);
693 return result;
696 static PyGetSetDef OutputChannel_getseters[] = {
697 {"prefader",
698 (getter)OutputChannel_get_prefader, (setter)OutputChannel_set_prefader,
699 "prefader", NULL},
700 {NULL}
703 static PyObject*
704 OutputChannel_remove(OutputChannelObject *self, PyObject *args)
706 if (! PyArg_ParseTuple(args, "")) return NULL;
707 remove_output_channel(self->output_channel);
708 Py_INCREF(Py_None);
709 return Py_None;
712 static PyObject*
713 OutputChannel_set_solo(OutputChannelObject *self, PyObject *args)
715 PyObject *channel;
716 unsigned char solo;
718 if (! PyArg_ParseTuple(args, "Ob", &channel, &solo)) return NULL;
720 output_channel_set_solo(self->output_channel,
721 ((ChannelObject*)channel)->channel,
722 solo);
724 Py_INCREF(Py_None);
725 return Py_None;
728 static PyObject*
729 OutputChannel_set_muted(OutputChannelObject *self, PyObject *args)
731 PyObject *channel;
732 unsigned char muted;
734 if (! PyArg_ParseTuple(args, "Ob", &channel, &muted)) return NULL;
736 output_channel_set_muted(self->output_channel,
737 ((ChannelObject*)channel)->channel,
738 muted);
740 Py_INCREF(Py_None);
741 return Py_None;
744 static PyObject*
745 OutputChannel_is_solo(OutputChannelObject *self, PyObject *args)
747 PyObject *channel;
748 PyObject *result;
750 if (! PyArg_ParseTuple(args, "O", &channel)) return NULL;
752 if (output_channel_is_solo(self->output_channel,
753 ((ChannelObject*)channel)->channel)) {
754 result = Py_True;
755 } else {
756 result = Py_False;
759 Py_INCREF(result);
760 return result;
763 static PyObject*
764 OutputChannel_is_muted(OutputChannelObject *self, PyObject *args)
766 PyObject *channel;
767 PyObject *result;
769 if (! PyArg_ParseTuple(args, "O", &channel)) return NULL;
771 if (output_channel_is_muted(self->output_channel,
772 ((ChannelObject*)channel)->channel)) {
773 result = Py_True;
774 } else {
775 result = Py_False;
778 Py_INCREF(result);
779 return result;
782 static PyObject*
783 OutputChannel_set_in_prefader(OutputChannelObject *self, PyObject *args)
785 PyObject *channel;
786 unsigned char prefader;
788 if (! PyArg_ParseTuple(args, "Ob", &channel, &prefader)) return NULL;
790 output_channel_set_in_prefader(self->output_channel,
791 ((ChannelObject*)channel)->channel,
792 prefader);
794 Py_INCREF(Py_None);
795 return Py_None;
798 static PyObject*
799 OutputChannel_is_in_prefader(OutputChannelObject *self, PyObject *args)
801 PyObject *channel;
802 PyObject *result;
804 if (! PyArg_ParseTuple(args, "O", &channel)) return NULL;
806 if (output_channel_is_in_prefader(self->output_channel,
807 ((ChannelObject*)channel)->channel)) {
808 result = Py_True;
809 } else {
810 result = Py_False;
813 Py_INCREF(result);
814 return result;
817 static PyMethodDef output_channel_methods[] = {
818 {"remove", (PyCFunction)OutputChannel_remove, METH_VARARGS, "Remove"},
819 {"set_solo", (PyCFunction)OutputChannel_set_solo, METH_VARARGS, "Set a channel as solo"},
820 {"set_muted", (PyCFunction)OutputChannel_set_muted, METH_VARARGS, "Set a channel as muted"},
821 {"is_solo", (PyCFunction)OutputChannel_is_solo, METH_VARARGS, "Is a channel set as solo"},
822 {"is_muted", (PyCFunction)OutputChannel_is_muted, METH_VARARGS, "Is a channel set as muted"},
823 {"set_in_prefader", (PyCFunction)OutputChannel_set_in_prefader, METH_VARARGS, "Set a channel as prefader"},
824 {"is_in_prefader", (PyCFunction)OutputChannel_is_in_prefader, METH_VARARGS, "Is a channel set as prefader"},
825 {NULL}
828 static PyTypeObject OutputChannelType = {
829 PyVarObject_HEAD_INIT(NULL, 0)
830 "jack_mixer_c.OutputChannel", /*tp_name*/
831 sizeof(OutputChannelObject), /*tp_basicsize*/
832 0, /*tp_itemsize*/
833 0, /*tp_dealloc*/
834 0, /*tp_print*/
835 0, /*tp_getattr*/
836 0, /*tp_setattr*/
837 0, /*tp_compare*/
838 0, /*tp_repr*/
839 0, /*tp_as_number*/
840 0, /*tp_as_sequence*/
841 0, /*tp_as_mapping*/
842 0, /*tp_hash */
843 0, /*tp_call*/
844 0, /*tp_str*/
845 0, /*tp_getattro*/
846 0, /*tp_setattro*/
847 0, /*tp_as_buffer*/
848 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
849 "Output Channel objects", /* tp_doc */
850 0, /* tp_traverse */
851 0, /* tp_clear */
852 0, /* tp_richcompare */
853 0, /* tp_weaklistoffset */
854 0, /* tp_iter */
855 0, /* tp_iternext */
856 output_channel_methods, /* tp_methods */
857 0, /* tp_members */
858 OutputChannel_getseters, /* tp_getset */
859 &ChannelType, /* tp_base */
860 0, /* tp_dict */
861 0, /* tp_descr_get */
862 0, /* tp_descr_set */
863 0, /* tp_dictoffset */
864 0, /* tp_init */
865 0, /* tp_alloc */
866 0, /* tp_new */
869 static PyObject*
870 OutputChannel_New(jack_mixer_output_channel_t output_channel)
872 OutputChannelObject *self;
873 self = (OutputChannelObject*)PyObject_NEW(OutputChannelObject, &OutputChannelType);
874 if (self != NULL) {
875 self->midi_change_callback = NULL;
876 self->output_channel = output_channel;
878 return (PyObject*)self;
882 /** Mixer Type **/
884 typedef struct {
885 PyObject_HEAD
886 jack_mixer_t mixer;
887 } MixerObject;
889 static void
890 Mixer_dealloc(MixerObject *self)
892 if (self->mixer)
893 destroy(self->mixer);
894 Py_TYPE(self)->tp_free((PyObject*)self);
897 static PyObject*
898 Mixer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
900 MixerObject *self;
902 self = (MixerObject*)type->tp_alloc(type, 0);
904 if (self != NULL) {
905 self->mixer = NULL;
908 return (PyObject*)self;
911 static int
912 Mixer_init(MixerObject *self, PyObject *args, PyObject *kwds)
914 static char *kwlist[] = {"name", "stereo", NULL};
915 char *name;
916 int stereo = 1;
918 if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|b", kwlist, &name, &stereo))
919 return -1;
921 self->mixer = create(name, (bool)stereo);
922 if (self->mixer == NULL) {
923 PyErr_SetString(PyExc_RuntimeError,
924 "error creating mixer, probably jack is not running");
925 return -1;
928 return 0;
931 static PyMemberDef Mixer_members[] = {
932 {NULL}
935 static PyObject*
936 Mixer_get_channels_count(MixerObject *self, void *closure)
938 return PyLong_FromLong(get_channels_count(self->mixer));
941 static PyObject*
942 Mixer_get_client_name(MixerObject *self, void *closure)
944 return PyUnicode_FromString(get_client_name(self->mixer));
947 static PyObject*
948 Mixer_get_last_midi_channel(MixerObject *self, void *closure)
950 return PyLong_FromLong(get_last_midi_channel(self->mixer));
953 static int
954 Mixer_set_last_midi_channel(MixerObject *self, PyObject *value, void *closure)
956 int new_channel;
957 unsigned int result;
959 new_channel = PyLong_AsLong(value);
960 result = set_last_midi_channel(self->mixer, new_channel);
961 if (result == 0) {
962 return 0;
964 return -1;
967 static PyObject*
968 Mixer_get_midi_behavior_mode(MixerObject *self, void *closure)
970 return PyLong_FromLong(get_midi_behavior_mode(self->mixer));
973 static int
974 Mixer_set_midi_behavior_mode(MixerObject *self, PyObject *value, void *closure)
976 int mode;
977 unsigned int result;
979 mode = PyLong_AsLong(value);
980 result = set_midi_behavior_mode(self->mixer, mode);
981 if (result == 0) {
982 return 0;
984 return -1;
989 static PyGetSetDef Mixer_getseters[] = {
990 {"channels_count", (getter)Mixer_get_channels_count, NULL,
991 "channels count", NULL},
992 {"last_midi_channel", (getter)Mixer_get_last_midi_channel, (setter)Mixer_set_last_midi_channel,
993 "last midi channel", NULL},
994 {"midi_behavior_mode", (getter)Mixer_get_midi_behavior_mode, (setter)Mixer_set_midi_behavior_mode,
995 "midi behavior mode", NULL},
996 {NULL}
999 static PyObject*
1000 Mixer_add_channel(MixerObject *self, PyObject *args)
1002 char *name;
1003 int stereo;
1004 jack_mixer_channel_t channel;
1006 if (! PyArg_ParseTuple(args, "si", &name, &stereo)) return NULL;
1008 channel = add_channel(self->mixer, name, (bool)stereo);
1010 if (channel == NULL) {
1011 PyErr_SetString(PyExc_RuntimeError, "error adding channel");
1012 return NULL;
1015 return Channel_New(channel);
1018 static PyObject*
1019 Mixer_add_output_channel(MixerObject *self, PyObject *args)
1021 char *name;
1022 int stereo = 1;
1023 int system = 0;
1024 jack_mixer_output_channel_t channel;
1026 if (! PyArg_ParseTuple(args, "s|bb", &name, &stereo, &system)) return NULL;
1028 channel = add_output_channel(self->mixer, name, (bool)stereo, (bool)system);
1030 return OutputChannel_New(channel);
1033 static PyObject*
1034 Mixer_destroy(MixerObject *self, PyObject *args)
1036 if (self->mixer) {
1037 destroy(self->mixer);
1038 self->mixer = NULL;
1040 Py_INCREF(Py_None);
1041 return Py_None;
1044 static PyMethodDef Mixer_methods[] = {
1045 {"add_channel", (PyCFunction)Mixer_add_channel, METH_VARARGS, "Add a new channel"},
1046 {"add_output_channel", (PyCFunction)Mixer_add_output_channel, METH_VARARGS, "Add a new output channel"},
1047 {"destroy", (PyCFunction)Mixer_destroy, METH_VARARGS, "Destroy JACK Mixer"},
1048 {"client_name", (PyCFunction)Mixer_get_client_name, METH_VARARGS, "Get jack client name"},
1049 // {"remove_channel", (PyCFunction)Mixer_remove_channel, METH_VARARGS, "Remove a channel"},
1050 {NULL}
1053 static PyTypeObject MixerType = {
1054 PyVarObject_HEAD_INIT(NULL, 0)
1055 "jack_mixer_c.Mixer", /*tp_name*/
1056 sizeof(MixerObject), /*tp_basicsize*/
1057 0, /*tp_itemsize*/
1058 (destructor)Mixer_dealloc, /*tp_dealloc*/
1059 0, /*tp_print*/
1060 0, /*tp_getattr*/
1061 0, /*tp_setattr*/
1062 0, /*tp_compare*/
1063 0, /*tp_repr*/
1064 0, /*tp_as_number*/
1065 0, /*tp_as_sequence*/
1066 0, /*tp_as_mapping*/
1067 0, /*tp_hash */
1068 0, /*tp_call*/
1069 0, /*tp_str*/
1070 0, /*tp_getattro*/
1071 0, /*tp_setattro*/
1072 0, /*tp_as_buffer*/
1073 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
1074 "Mixer objects", /* tp_doc */
1075 0, /* tp_traverse */
1076 0, /* tp_clear */
1077 0, /* tp_richcompare */
1078 0, /* tp_weaklistoffset */
1079 0, /* tp_iter */
1080 0, /* tp_iternext */
1081 Mixer_methods, /* tp_methods */
1082 Mixer_members, /* tp_members */
1083 Mixer_getseters, /* tp_getset */
1084 0, /* tp_base */
1085 0, /* tp_dict */
1086 0, /* tp_descr_get */
1087 0, /* tp_descr_set */
1088 0, /* tp_dictoffset */
1089 (initproc)Mixer_init, /* tp_init */
1090 0, /* tp_alloc */
1091 Mixer_new, /* tp_new */
1095 static PyMethodDef jack_mixer_methods[] = {
1096 {NULL, NULL, 0, NULL} /* Sentinel */
1100 static struct PyModuleDef moduledef = {
1101 PyModuleDef_HEAD_INIT,
1102 "jack_mixer_c", /* m_name */
1103 "Jack Mixer C Helper Module", /* m_doc */
1104 -1, /* m_size */
1105 jack_mixer_methods, /* m_methods */
1106 NULL, /* m_reload */
1107 NULL, /* m_traverse */
1108 NULL, /* m_clear */
1109 NULL, /* m_free */
1112 PyMODINIT_FUNC PyInit_jack_mixer_c(void)
1114 PyObject *m;
1116 if (PyType_Ready(&MixerType) < 0)
1117 return NULL;
1118 if (PyType_Ready(&ChannelType) < 0)
1119 return NULL;
1120 if (PyType_Ready(&OutputChannelType) < 0)
1121 return NULL;
1122 if (PyType_Ready(&ScaleType) < 0)
1123 return NULL;
1125 m = PyModule_Create(&moduledef);
1126 //m = Py_InitModule3("jack_mixer_c", jack_mixer_methods, "module doc");
1128 Py_INCREF(&MixerType);
1129 PyModule_AddObject(m, "Mixer", (PyObject*)&MixerType);
1130 Py_INCREF(&ChannelType);
1131 PyModule_AddObject(m, "Channel", (PyObject*)&ChannelType);
1132 Py_INCREF(&OutputChannelType);
1133 PyModule_AddObject(m, "OutputChannel", (PyObject*)&OutputChannelType);
1134 Py_INCREF(&ScaleType);
1135 PyModule_AddObject(m, "Scale", (PyObject*)&ScaleType);
1137 return m;