release: 12
[jack_mixer.git] / jack_mixer_c.c
blob62946e7ef278eaef398c697ffbcd7a39c4a2468c
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 return 0;
221 static PyObject*
222 Channel_get_balance(ChannelObject *self, void *closure)
224 return PyFloat_FromDouble(channel_balance_read(self->channel));
227 static int
228 Channel_set_balance(ChannelObject *self, PyObject *value, void *closure)
230 channel_balance_write(self->channel, PyFloat_AsDouble(value));
231 return 0;
234 static PyObject*
235 Channel_get_out_mute(ChannelObject *self, void *closure)
237 PyObject *result;
239 if (channel_is_out_muted(self->channel)) {
240 result = Py_True;
241 } else {
242 result = Py_False;
244 Py_INCREF(result);
245 return result;
248 static int
249 Channel_set_out_mute(ChannelObject *self, PyObject *value, void *closure)
251 if (value == Py_True) {
252 channel_out_mute(self->channel);
253 } else {
254 channel_out_unmute(self->channel);
256 return 0;
259 static PyObject*
260 Channel_get_solo(ChannelObject *self, void *closure)
262 PyObject *result;
264 if (channel_is_soloed(self->channel)) {
265 result = Py_True;
266 } else {
267 result = Py_False;
269 Py_INCREF(result);
270 return result;
273 static int
274 Channel_set_solo(ChannelObject *self, PyObject *value, void *closure)
276 if (value == Py_True) {
277 channel_solo(self->channel);
278 } else {
279 channel_unsolo(self->channel);
281 return 0;
284 static PyObject*
285 Channel_get_meter(ChannelObject *self, void *closure)
287 PyObject *result;
288 double left, right;
290 if (channel_is_stereo(self->channel)) {
291 result = PyTuple_New(2);
292 channel_stereo_meter_read(self->channel, &left, &right);
293 PyTuple_SetItem(result, 0, PyFloat_FromDouble(left));
294 PyTuple_SetItem(result, 1, PyFloat_FromDouble(right));
295 } else {
296 result = PyTuple_New(1);
297 channel_mono_meter_read(self->channel, &left);
298 PyTuple_SetItem(result, 0, PyFloat_FromDouble(left));
300 return result;
303 static PyObject*
304 Channel_get_abspeak(ChannelObject *self, void *closure)
306 return PyFloat_FromDouble(channel_abspeak_read(self->channel));
309 static int
310 Channel_set_abspeak(ChannelObject *self, PyObject *value, void *closure)
312 if (value != Py_None) {
313 fprintf(stderr, "abspeak can only be reset (set to None)\n");
314 return -1;
316 channel_abspeak_reset(self->channel);
317 return 0;
320 static int
321 Channel_set_midi_scale(ChannelObject *self, PyObject *value, void *closure)
323 ScaleObject *scale_object = (ScaleObject*)value; /* XXX: check */
325 channel_set_midi_scale(self->channel, scale_object->scale);
326 return 0;
330 static PyObject*
331 Channel_get_midi_change_callback(ChannelObject *self, void *closure)
333 if (self->midi_change_callback) {
334 Py_INCREF(self->midi_change_callback);
335 return self->midi_change_callback;
336 } else {
337 Py_INCREF(Py_None);
338 return Py_None;
342 static void
343 channel_midi_callback(void *userdata)
345 ChannelObject *self = (ChannelObject*)userdata;
346 PyGILState_STATE gstate;
348 gstate = PyGILState_Ensure();
349 PyObject_CallObject(self->midi_change_callback, NULL);
350 PyGILState_Release(gstate);
353 static int
354 Channel_set_midi_change_callback(ChannelObject *self, PyObject *value, void *closure)
356 if (value == Py_None) {
357 self->midi_change_callback = NULL;
358 channel_set_midi_change_callback(self->channel, NULL, NULL);
359 } else {
360 if (!PyCallable_Check(value)) {
361 PyErr_SetString(PyExc_TypeError, "value must be callable");
362 return -1;
364 if (self->midi_change_callback) {
365 Py_XDECREF(self->midi_change_callback);
367 Py_INCREF(value);
368 self->midi_change_callback = value;
369 channel_set_midi_change_callback(self->channel,
370 channel_midi_callback, self);
373 return 0;
376 static PyObject*
377 Channel_get_name(ChannelObject *self, void *closure)
379 return PyUnicode_FromString(channel_get_name(self->channel));
382 static int
383 Channel_set_name(ChannelObject *self, PyObject *value, void *closure)
385 channel_rename(self->channel, PyUnicode_AsUTF8(value));
386 return 0;
389 static PyObject*
390 Channel_get_balance_midi_cc(ChannelObject *self, void *closure)
392 return PyLong_FromLong(channel_get_balance_midi_cc(self->channel));
395 static int
396 Channel_set_balance_midi_cc(ChannelObject *self, PyObject *value, void *closure)
398 int new_cc;
399 unsigned int result;
401 new_cc = PyLong_AsLong(value);
402 result = channel_set_balance_midi_cc(self->channel, new_cc);
403 if (result == 0) {
404 return 0;
406 if (result == 2) {
407 PyErr_SetString(PyExc_RuntimeError, "value out of range");
409 return -1;
412 static PyObject*
413 Channel_get_volume_midi_cc(ChannelObject *self, void *closure)
415 return PyLong_FromLong(channel_get_volume_midi_cc(self->channel));
418 static int
419 Channel_set_volume_midi_cc(ChannelObject *self, PyObject *value, void *closure)
421 int new_cc;
422 unsigned int result;
424 new_cc = PyLong_AsLong(value);
425 result = channel_set_volume_midi_cc(self->channel, new_cc);
426 if (result == 0) {
427 return 0;
429 if (result == 2) {
430 PyErr_SetString(PyExc_RuntimeError, "value out of range");
432 return -1;
435 static PyObject*
436 Channel_get_mute_midi_cc(ChannelObject *self, void *closure)
438 return PyLong_FromLong(channel_get_mute_midi_cc(self->channel));
441 static int
442 Channel_set_mute_midi_cc(ChannelObject *self, PyObject *value, void *closure)
444 int new_cc;
445 unsigned int result;
447 new_cc = PyLong_AsLong(value);
448 result = channel_set_mute_midi_cc(self->channel, new_cc);
449 if (result == 0) {
450 return 0;
452 if (result == 2) {
453 PyErr_SetString(PyExc_RuntimeError, "value out of range");
455 return -1;
458 static PyObject*
459 Channel_get_solo_midi_cc(ChannelObject *self, void *closure)
461 return PyLong_FromLong(channel_get_solo_midi_cc(self->channel));
464 static int
465 Channel_set_solo_midi_cc(ChannelObject *self, PyObject *value, void *closure)
467 int new_cc;
468 unsigned int result;
470 new_cc = PyLong_AsLong(value);
471 result = channel_set_solo_midi_cc(self->channel, new_cc);
472 if (result == 0) {
473 return 0;
475 if (result == 2) {
476 PyErr_SetString(PyExc_RuntimeError, "value out of range");
478 return -1;
481 static PyObject*
482 Channel_get_midi_in_got_events(ChannelObject *self, void *closure)
484 PyObject *result;
486 if (channel_get_midi_in_got_events(self->channel)) {
487 result = Py_True;
488 } else {
489 result = Py_False;
491 Py_INCREF(result);
492 return result;
495 static PyGetSetDef Channel_getseters[] = {
496 {"is_stereo",
497 (getter)Channel_get_is_stereo, NULL,
498 "mono/stereo", NULL},
499 {"volume",
500 (getter)Channel_get_volume, (setter)Channel_set_volume,
501 "volume", NULL},
502 {"balance",
503 (getter)Channel_get_balance, (setter)Channel_set_balance,
504 "balance", NULL},
505 {"out_mute",
506 (getter)Channel_get_out_mute, (setter)Channel_set_out_mute,
507 "out_mute", NULL},
508 {"solo",
509 (getter)Channel_get_solo, (setter)Channel_set_solo,
510 "solo", NULL},
511 {"meter",
512 (getter)Channel_get_meter, NULL,
513 "meter", NULL},
514 {"abspeak",
515 (getter)Channel_get_abspeak, (setter)Channel_set_abspeak,
516 "balance", NULL},
517 {"midi_scale",
518 NULL, (setter)Channel_set_midi_scale,
519 "midi scale", NULL},
520 {"midi_change_callback",
521 (getter)Channel_get_midi_change_callback,
522 (setter)Channel_set_midi_change_callback,
523 "midi change callback", NULL},
524 {"name",
525 (getter)Channel_get_name,
526 (setter)Channel_set_name,
527 "name", NULL},
528 {"balance_midi_cc",
529 (getter)Channel_get_balance_midi_cc,
530 (setter)Channel_set_balance_midi_cc,
531 "Balance MIDI CC", NULL},
532 {"volume_midi_cc",
533 (getter)Channel_get_volume_midi_cc,
534 (setter)Channel_set_volume_midi_cc,
535 "Volume MIDI CC", NULL},
536 {"mute_midi_cc",
537 (getter)Channel_get_mute_midi_cc,
538 (setter)Channel_set_mute_midi_cc,
539 "Mute MIDI CC", NULL},
540 {"solo_midi_cc",
541 (getter)Channel_get_solo_midi_cc,
542 (setter)Channel_set_solo_midi_cc,
543 "Mute MIDI CC", NULL},
544 {"midi_in_got_events",
545 (getter)Channel_get_midi_in_got_events, NULL,
546 "Got new MIDI IN events", NULL},
547 {NULL}
550 static PyObject*
551 Channel_remove(ChannelObject *self, PyObject *args)
553 if (! PyArg_ParseTuple(args, "")) return NULL;
554 remove_channel(self->channel);
555 Py_INCREF(Py_None);
556 return Py_None;
559 static PyObject*
560 Channel_autoset_midi_cc(ChannelObject *self, PyObject *args)
562 if (! PyArg_ParseTuple(args, "")) return NULL;
563 channel_autoset_midi_cc(self->channel);
564 Py_INCREF(Py_None);
565 return Py_None;
568 static PyMethodDef channel_methods[] = {
569 {"remove", (PyCFunction)Channel_remove, METH_VARARGS, "Remove"},
570 {"autoset_midi_cc", (PyCFunction)Channel_autoset_midi_cc, METH_VARARGS, "Autoset MIDI CC"},
571 {NULL}
574 static PyTypeObject ChannelType = {
575 PyVarObject_HEAD_INIT(NULL, 0)
576 "jack_mixer_c.Channel", /*tp_name*/
577 sizeof(ChannelObject), /*tp_basicsize*/
578 0, /*tp_itemsize*/
579 (destructor)Channel_dealloc, /*tp_dealloc*/
580 0, /*tp_print*/
581 0, /*tp_getattr*/
582 0, /*tp_setattr*/
583 0, /*tp_compare*/
584 0, /*tp_repr*/
585 0, /*tp_as_number*/
586 0, /*tp_as_sequence*/
587 0, /*tp_as_mapping*/
588 0, /*tp_hash */
589 0, /*tp_call*/
590 0, /*tp_str*/
591 0, /*tp_getattro*/
592 0, /*tp_setattro*/
593 0, /*tp_as_buffer*/
594 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
595 "Channel objects", /* tp_doc */
596 0, /* tp_traverse */
597 0, /* tp_clear */
598 0, /* tp_richcompare */
599 0, /* tp_weaklistoffset */
600 0, /* tp_iter */
601 0, /* tp_iternext */
602 channel_methods, /* tp_methods */
603 0, /* tp_members */
604 Channel_getseters, /* tp_getset */
605 0, /* tp_base */
606 0, /* tp_dict */
607 0, /* tp_descr_get */
608 0, /* tp_descr_set */
609 0, /* tp_dictoffset */
610 (initproc)Channel_init, /* tp_init */
611 0, /* tp_alloc */
612 Channel_new, /* tp_new */
615 static PyObject*
616 Channel_New(jack_mixer_channel_t channel)
618 ChannelObject *self;
619 self = (ChannelObject*)PyObject_NEW(ChannelObject, &ChannelType);
620 if (self != NULL) {
621 self->channel = channel;
622 self->midi_change_callback = NULL;
624 return (PyObject*)self;
627 /** Output Channel Type **/
629 typedef struct {
630 PyObject_HEAD
631 PyObject *midi_change_callback;
632 jack_mixer_output_channel_t *output_channel;
633 } OutputChannelObject;
635 static int
636 OutputChannel_set_prefader(OutputChannelObject *self, PyObject *value, void *closure)
638 if (value == Py_True) {
639 output_channel_set_prefader(self->output_channel, true);
640 } else {
641 output_channel_set_prefader(self->output_channel, false);
643 return 0;
646 static PyObject*
647 OutputChannel_get_prefader(OutputChannelObject *self, void *closure)
649 PyObject *result;
651 if (output_channel_is_prefader(self->output_channel)) {
652 result = Py_True;
653 } else {
654 result = Py_False;
656 Py_INCREF(result);
657 return result;
660 static PyGetSetDef OutputChannel_getseters[] = {
661 {"prefader",
662 (getter)OutputChannel_get_prefader, (setter)OutputChannel_set_prefader,
663 "prefader", NULL},
664 {NULL}
667 static PyObject*
668 OutputChannel_remove(OutputChannelObject *self, PyObject *args)
670 if (! PyArg_ParseTuple(args, "")) return NULL;
671 remove_output_channel(self->output_channel);
672 Py_INCREF(Py_None);
673 return Py_None;
676 static PyObject*
677 OutputChannel_set_solo(OutputChannelObject *self, PyObject *args)
679 PyObject *channel;
680 unsigned char solo;
682 if (! PyArg_ParseTuple(args, "Ob", &channel, &solo)) return NULL;
684 output_channel_set_solo(self->output_channel,
685 ((ChannelObject*)channel)->channel,
686 solo);
688 Py_INCREF(Py_None);
689 return Py_None;
692 static PyObject*
693 OutputChannel_set_muted(OutputChannelObject *self, PyObject *args)
695 PyObject *channel;
696 unsigned char muted;
698 if (! PyArg_ParseTuple(args, "Ob", &channel, &muted)) return NULL;
700 output_channel_set_muted(self->output_channel,
701 ((ChannelObject*)channel)->channel,
702 muted);
704 Py_INCREF(Py_None);
705 return Py_None;
708 static PyObject*
709 OutputChannel_is_solo(OutputChannelObject *self, PyObject *args)
711 PyObject *channel;
712 PyObject *result;
714 if (! PyArg_ParseTuple(args, "O", &channel)) return NULL;
716 if (output_channel_is_solo(self->output_channel,
717 ((ChannelObject*)channel)->channel)) {
718 result = Py_True;
719 } else {
720 result = Py_False;
723 Py_INCREF(result);
724 return result;
727 static PyObject*
728 OutputChannel_is_muted(OutputChannelObject *self, PyObject *args)
730 PyObject *channel;
731 PyObject *result;
733 if (! PyArg_ParseTuple(args, "O", &channel)) return NULL;
735 if (output_channel_is_muted(self->output_channel,
736 ((ChannelObject*)channel)->channel)) {
737 result = Py_True;
738 } else {
739 result = Py_False;
742 Py_INCREF(result);
743 return result;
746 static PyMethodDef output_channel_methods[] = {
747 {"remove", (PyCFunction)OutputChannel_remove, METH_VARARGS, "Remove"},
748 {"set_solo", (PyCFunction)OutputChannel_set_solo, METH_VARARGS, "Set a channel as solo"},
749 {"set_muted", (PyCFunction)OutputChannel_set_muted, METH_VARARGS, "Set a channel as muted"},
750 {"is_solo", (PyCFunction)OutputChannel_is_solo, METH_VARARGS, "Is a channel set as solo"},
751 {"is_muted", (PyCFunction)OutputChannel_is_muted, METH_VARARGS, "Is a channel set as muted"},
752 {NULL}
755 static PyTypeObject OutputChannelType = {
756 PyVarObject_HEAD_INIT(NULL, 0)
757 "jack_mixer_c.OutputChannel", /*tp_name*/
758 sizeof(OutputChannelObject), /*tp_basicsize*/
759 0, /*tp_itemsize*/
760 0, /*tp_dealloc*/
761 0, /*tp_print*/
762 0, /*tp_getattr*/
763 0, /*tp_setattr*/
764 0, /*tp_compare*/
765 0, /*tp_repr*/
766 0, /*tp_as_number*/
767 0, /*tp_as_sequence*/
768 0, /*tp_as_mapping*/
769 0, /*tp_hash */
770 0, /*tp_call*/
771 0, /*tp_str*/
772 0, /*tp_getattro*/
773 0, /*tp_setattro*/
774 0, /*tp_as_buffer*/
775 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
776 "Output Channel objects", /* tp_doc */
777 0, /* tp_traverse */
778 0, /* tp_clear */
779 0, /* tp_richcompare */
780 0, /* tp_weaklistoffset */
781 0, /* tp_iter */
782 0, /* tp_iternext */
783 output_channel_methods, /* tp_methods */
784 0, /* tp_members */
785 OutputChannel_getseters, /* tp_getset */
786 &ChannelType, /* tp_base */
787 0, /* tp_dict */
788 0, /* tp_descr_get */
789 0, /* tp_descr_set */
790 0, /* tp_dictoffset */
791 0, /* tp_init */
792 0, /* tp_alloc */
793 0, /* tp_new */
796 static PyObject*
797 OutputChannel_New(jack_mixer_output_channel_t output_channel)
799 OutputChannelObject *self;
800 self = (OutputChannelObject*)PyObject_NEW(OutputChannelObject, &OutputChannelType);
801 if (self != NULL) {
802 self->midi_change_callback = NULL;
803 self->output_channel = output_channel;
805 return (PyObject*)self;
809 /** Mixer Type **/
811 typedef struct {
812 PyObject_HEAD
813 jack_mixer_t mixer;
814 } MixerObject;
816 static void
817 Mixer_dealloc(MixerObject *self)
819 if (self->mixer)
820 destroy(self->mixer);
821 Py_TYPE(self)->tp_free((PyObject*)self);
824 static PyObject*
825 Mixer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
827 MixerObject *self;
829 self = (MixerObject*)type->tp_alloc(type, 0);
831 if (self != NULL) {
832 self->mixer = NULL;
835 return (PyObject*)self;
838 static int
839 Mixer_init(MixerObject *self, PyObject *args, PyObject *kwds)
841 static char *kwlist[] = {"name", "stereo", NULL};
842 char *name;
843 int stereo = 1;
845 if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|b", kwlist, &name, &stereo))
846 return -1;
848 self->mixer = create(name, (bool)stereo);
849 if (self->mixer == NULL) {
850 PyErr_SetString(PyExc_RuntimeError,
851 "error creating mixer, probably jack is not running");
852 return -1;
855 return 0;
858 static PyMemberDef Mixer_members[] = {
859 {NULL}
862 static PyObject*
863 Mixer_get_channels_count(MixerObject *self, void *closure)
865 return PyLong_FromLong(get_channels_count(self->mixer));
868 static PyObject*
869 Mixer_get_client_name(MixerObject *self, void *closure)
871 return PyUnicode_FromString(get_client_name(self->mixer));
874 static PyObject*
875 Mixer_get_last_midi_channel(MixerObject *self, void *closure)
877 return PyLong_FromLong(get_last_midi_channel(self->mixer));
880 static int
881 Mixer_set_last_midi_channel(MixerObject *self, PyObject *value, void *closure)
883 int new_channel;
884 unsigned int result;
886 new_channel = PyLong_AsLong(value);
887 result = set_last_midi_channel(self->mixer, new_channel);
888 if (result == 0) {
889 return 0;
891 return -1;
894 static PyGetSetDef Mixer_getseters[] = {
895 {"channels_count", (getter)Mixer_get_channels_count, NULL,
896 "channels count", NULL},
897 {"last_midi_channel", (getter)Mixer_get_last_midi_channel, (setter)Mixer_set_last_midi_channel,
898 "last midi channel", NULL},
899 {NULL}
902 static PyObject*
903 Mixer_add_channel(MixerObject *self, PyObject *args)
905 char *name;
906 int stereo;
907 jack_mixer_channel_t channel;
909 if (! PyArg_ParseTuple(args, "si", &name, &stereo)) return NULL;
911 channel = add_channel(self->mixer, name, (bool)stereo);
913 if (channel == NULL) {
914 PyErr_SetString(PyExc_RuntimeError, "error adding channel");
915 return NULL;
918 return Channel_New(channel);
921 static PyObject*
922 Mixer_add_output_channel(MixerObject *self, PyObject *args)
924 char *name;
925 int stereo = 1;
926 int system = 0;
927 jack_mixer_output_channel_t channel;
929 if (! PyArg_ParseTuple(args, "s|bb", &name, &stereo, &system)) return NULL;
931 channel = add_output_channel(self->mixer, name, (bool)stereo, (bool)system);
933 return OutputChannel_New(channel);
936 static PyObject*
937 Mixer_destroy(MixerObject *self, PyObject *args)
939 if (self->mixer) {
940 destroy(self->mixer);
941 self->mixer = NULL;
943 Py_INCREF(Py_None);
944 return Py_None;
947 static PyMethodDef Mixer_methods[] = {
948 {"add_channel", (PyCFunction)Mixer_add_channel, METH_VARARGS, "Add a new channel"},
949 {"add_output_channel", (PyCFunction)Mixer_add_output_channel, METH_VARARGS, "Add a new output channel"},
950 {"destroy", (PyCFunction)Mixer_destroy, METH_VARARGS, "Destroy JACK Mixer"},
951 {"client_name", (PyCFunction)Mixer_get_client_name, METH_VARARGS, "Get jack client name"},
952 // {"remove_channel", (PyCFunction)Mixer_remove_channel, METH_VARARGS, "Remove a channel"},
953 {NULL}
956 static PyTypeObject MixerType = {
957 PyVarObject_HEAD_INIT(NULL, 0)
958 "jack_mixer_c.Mixer", /*tp_name*/
959 sizeof(MixerObject), /*tp_basicsize*/
960 0, /*tp_itemsize*/
961 (destructor)Mixer_dealloc, /*tp_dealloc*/
962 0, /*tp_print*/
963 0, /*tp_getattr*/
964 0, /*tp_setattr*/
965 0, /*tp_compare*/
966 0, /*tp_repr*/
967 0, /*tp_as_number*/
968 0, /*tp_as_sequence*/
969 0, /*tp_as_mapping*/
970 0, /*tp_hash */
971 0, /*tp_call*/
972 0, /*tp_str*/
973 0, /*tp_getattro*/
974 0, /*tp_setattro*/
975 0, /*tp_as_buffer*/
976 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
977 "Mixer objects", /* tp_doc */
978 0, /* tp_traverse */
979 0, /* tp_clear */
980 0, /* tp_richcompare */
981 0, /* tp_weaklistoffset */
982 0, /* tp_iter */
983 0, /* tp_iternext */
984 Mixer_methods, /* tp_methods */
985 Mixer_members, /* tp_members */
986 Mixer_getseters, /* tp_getset */
987 0, /* tp_base */
988 0, /* tp_dict */
989 0, /* tp_descr_get */
990 0, /* tp_descr_set */
991 0, /* tp_dictoffset */
992 (initproc)Mixer_init, /* tp_init */
993 0, /* tp_alloc */
994 Mixer_new, /* tp_new */
998 static PyMethodDef jack_mixer_methods[] = {
999 {NULL, NULL, 0, NULL} /* Sentinel */
1003 static struct PyModuleDef moduledef = {
1004 PyModuleDef_HEAD_INIT,
1005 "jack_mixer_c", /* m_name */
1006 "Jack Mixer C Helper Module", /* m_doc */
1007 -1, /* m_size */
1008 jack_mixer_methods, /* m_methods */
1009 NULL, /* m_reload */
1010 NULL, /* m_traverse */
1011 NULL, /* m_clear */
1012 NULL, /* m_free */
1015 PyMODINIT_FUNC PyInit_jack_mixer_c(void)
1017 PyObject *m;
1019 if (PyType_Ready(&MixerType) < 0)
1020 return NULL;
1021 if (PyType_Ready(&ChannelType) < 0)
1022 return NULL;
1023 if (PyType_Ready(&OutputChannelType) < 0)
1024 return NULL;
1025 if (PyType_Ready(&ScaleType) < 0)
1026 return NULL;
1028 m = PyModule_Create(&moduledef);
1029 //m = Py_InitModule3("jack_mixer_c", jack_mixer_methods, "module doc");
1031 Py_INCREF(&MixerType);
1032 PyModule_AddObject(m, "Mixer", (PyObject*)&MixerType);
1033 Py_INCREF(&ChannelType);
1034 PyModule_AddObject(m, "Channel", (PyObject*)&ChannelType);
1035 Py_INCREF(&OutputChannelType);
1036 PyModule_AddObject(m, "OutputChannel", (PyObject*)&OutputChannelType);
1037 Py_INCREF(&ScaleType);
1038 PyModule_AddObject(m, "Scale", (PyObject*)&ScaleType);
1040 return m;