build: run configure automatically after autogen
[jack_mixer.git] / jack_mixer_c.c
blob00d0cb6f72e98b7343c8c455eeb910a7400a3a78
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 self->ob_type->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 PyObject_HEAD_INIT(NULL)
112 0, /*ob_size*/
113 "jack_mixer_c.Scale", /*tp_name*/
114 sizeof(ScaleObject), /*tp_basicsize*/
115 0, /*tp_itemsize*/
116 (destructor)Scale_dealloc, /*tp_dealloc*/
117 0, /*tp_print*/
118 0, /*tp_getattr*/
119 0, /*tp_setattr*/
120 0, /*tp_compare*/
121 0, /*tp_repr*/
122 0, /*tp_as_number*/
123 0, /*tp_as_sequence*/
124 0, /*tp_as_mapping*/
125 0, /*tp_hash */
126 0, /*tp_call*/
127 0, /*tp_str*/
128 0, /*tp_getattro*/
129 0, /*tp_setattro*/
130 0, /*tp_as_buffer*/
131 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
132 "Scale objects", /* tp_doc */
133 0, /* tp_traverse */
134 0, /* tp_clear */
135 0, /* tp_richcompare */
136 0, /* tp_weaklistoffset */
137 0, /* tp_iter */
138 0, /* tp_iternext */
139 Scale_methods, /* tp_methods */
140 0, /* tp_members */
141 0, /* tp_getset */
142 0, /* tp_base */
143 0, /* tp_dict */
144 0, /* tp_descr_get */
145 0, /* tp_descr_set */
146 0, /* tp_dictoffset */
147 (initproc)Scale_init, /* tp_init */
148 0, /* tp_alloc */
149 Scale_new, /* tp_new */
153 /** Channel Type **/
155 typedef struct {
156 PyObject_HEAD
157 PyObject *midi_change_callback;
158 jack_mixer_channel_t channel;
159 } ChannelObject;
161 static void
162 Channel_dealloc(ChannelObject *self)
164 Py_XDECREF(self->midi_change_callback);
165 self->ob_type->tp_free((PyObject*)self);
168 static int
169 Channel_init(ChannelObject *self, PyObject *args, PyObject *kwds)
171 self->midi_change_callback = NULL;
172 return 0;
175 static PyObject*
176 Channel_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
178 ChannelObject *self;
180 self = (ChannelObject*)type->tp_alloc(type, 0);
182 if (self != NULL) {
183 self->channel = NULL;
184 self->midi_change_callback = NULL;
187 return (PyObject*)self;
190 static PyObject*
191 Channel_get_is_stereo(ChannelObject *self, void *closure)
193 PyObject *result;
195 bool is_stereo = channel_is_stereo(self->channel);
196 if (is_stereo) {
197 result = Py_True;
198 } else {
199 result = Py_False;
201 Py_INCREF(result);
202 return result;
205 static PyObject*
206 Channel_get_volume(ChannelObject *self, void *closure)
208 return PyFloat_FromDouble(channel_volume_read(self->channel));
211 static int
212 Channel_set_volume(ChannelObject *self, PyObject *value, void *closure)
214 if (self->channel == NULL) {
215 PyErr_SetString(PyExc_RuntimeError, "unitialized channel");
216 return -1;
218 channel_volume_write(self->channel, PyFloat_AsDouble(value));
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 return 0;
235 static PyObject*
236 Channel_get_mute(ChannelObject *self, void *closure)
238 PyObject *result;
240 if (channel_is_muted(self->channel)) {
241 result = Py_True;
242 } else {
243 result = Py_False;
245 Py_INCREF(result);
246 return result;
249 static int
250 Channel_set_mute(ChannelObject *self, PyObject *value, void *closure)
252 if (value == Py_True) {
253 channel_mute(self->channel);
254 } else {
255 channel_unmute(self->channel);
257 return 0;
260 static PyObject*
261 Channel_get_solo(ChannelObject *self, void *closure)
263 PyObject *result;
265 if (channel_is_soloed(self->channel)) {
266 result = Py_True;
267 } else {
268 result = Py_False;
270 Py_INCREF(result);
271 return result;
274 static int
275 Channel_set_solo(ChannelObject *self, PyObject *value, void *closure)
277 if (value == Py_True) {
278 channel_solo(self->channel);
279 } else {
280 channel_unsolo(self->channel);
282 return 0;
285 static PyObject*
286 Channel_get_meter(ChannelObject *self, void *closure)
288 PyObject *result;
289 double left, right;
291 if (channel_is_stereo(self->channel)) {
292 result = PyTuple_New(2);
293 channel_stereo_meter_read(self->channel, &left, &right);
294 PyTuple_SetItem(result, 0, PyFloat_FromDouble(left));
295 PyTuple_SetItem(result, 1, PyFloat_FromDouble(right));
296 } else {
297 result = PyTuple_New(1);
298 channel_mono_meter_read(self->channel, &left);
299 PyTuple_SetItem(result, 0, PyFloat_FromDouble(left));
301 return result;
304 static PyObject*
305 Channel_get_abspeak(ChannelObject *self, void *closure)
307 return PyFloat_FromDouble(channel_abspeak_read(self->channel));
310 static int
311 Channel_set_abspeak(ChannelObject *self, PyObject *value, void *closure)
313 if (value != Py_None) {
314 fprintf(stderr, "abspeak can only be reset (set to None)\n");
315 return -1;
317 channel_abspeak_reset(self->channel);
318 return 0;
321 static int
322 Channel_set_midi_scale(ChannelObject *self, PyObject *value, void *closure)
324 ScaleObject *scale_object = (ScaleObject*)value; /* XXX: check */
326 channel_set_midi_scale(self->channel, scale_object->scale);
327 return 0;
331 static PyObject*
332 Channel_get_midi_change_callback(ChannelObject *self, void *closure)
334 if (self->midi_change_callback) {
335 Py_INCREF(self->midi_change_callback);
336 return self->midi_change_callback;
337 } else {
338 Py_INCREF(Py_None);
339 return Py_None;
343 static void
344 channel_midi_callback(void *userdata)
346 ChannelObject *self = (ChannelObject*)userdata;
347 PyGILState_STATE gstate;
349 gstate = PyGILState_Ensure();
350 PyObject_CallObject(self->midi_change_callback, NULL);
351 PyGILState_Release(gstate);
354 static int
355 Channel_set_midi_change_callback(ChannelObject *self, PyObject *value, void *closure)
357 if (value == Py_None) {
358 self->midi_change_callback = NULL;
359 channel_set_midi_change_callback(self->channel, NULL, NULL);
360 } else {
361 if (!PyCallable_Check(value)) {
362 PyErr_SetString(PyExc_TypeError, "value must be callable");
363 return -1;
365 if (self->midi_change_callback) {
366 Py_XDECREF(self->midi_change_callback);
368 Py_INCREF(value);
369 self->midi_change_callback = value;
370 channel_set_midi_change_callback(self->channel,
371 channel_midi_callback, self);
374 return 0;
377 static PyObject*
378 Channel_get_name(ChannelObject *self, void *closure)
380 return PyString_FromString(channel_get_name(self->channel));
383 static int
384 Channel_set_name(ChannelObject *self, PyObject *value, void *closure)
386 channel_rename(self->channel, PyString_AsString(value));
387 return 0;
390 static PyObject*
391 Channel_get_balance_midi_cc(ChannelObject *self, void *closure)
393 return PyInt_FromLong(channel_get_balance_midi_cc(self->channel));
396 static int
397 Channel_set_balance_midi_cc(ChannelObject *self, PyObject *value, void *closure)
399 unsigned int new_cc;
400 unsigned int result;
402 new_cc = PyInt_AsLong(value);
403 result = channel_set_balance_midi_cc(self->channel, new_cc);
404 if (result == 0) {
405 return 0;
407 if (result == 1) {
408 PyErr_SetString(PyExc_RuntimeError, "value already in use");
409 } else if (result == 2) {
410 PyErr_SetString(PyExc_RuntimeError, "value out of range");
412 return -1;
415 static PyObject*
416 Channel_get_volume_midi_cc(ChannelObject *self, void *closure)
418 return PyInt_FromLong(channel_get_volume_midi_cc(self->channel));
421 static int
422 Channel_set_volume_midi_cc(ChannelObject *self, PyObject *value, void *closure)
424 unsigned int new_cc;
425 unsigned int result;
427 new_cc = PyInt_AsLong(value);
428 result = channel_set_volume_midi_cc(self->channel, new_cc);
429 if (result == 0) {
430 return 0;
432 if (result == 1) {
433 PyErr_SetString(PyExc_RuntimeError, "value already in use");
434 } else if (result == 2) {
435 PyErr_SetString(PyExc_RuntimeError, "value out of range");
437 return -1;
440 static PyObject*
441 Channel_get_midi_in_got_events(ChannelObject *self, void *closure)
443 PyObject *result;
445 if (channel_get_midi_in_got_events(self->channel)) {
446 result = Py_True;
447 } else {
448 result = Py_False;
450 Py_INCREF(result);
451 return result;
455 static PyGetSetDef Channel_getseters[] = {
456 {"is_stereo",
457 (getter)Channel_get_is_stereo, NULL,
458 "mono/stereo", NULL},
459 {"volume",
460 (getter)Channel_get_volume, (setter)Channel_set_volume,
461 "volume", NULL},
462 {"balance",
463 (getter)Channel_get_balance, (setter)Channel_set_balance,
464 "balance", NULL},
465 {"mute",
466 (getter)Channel_get_mute, (setter)Channel_set_mute,
467 "mute", NULL},
468 {"solo",
469 (getter)Channel_get_solo, (setter)Channel_set_solo,
470 "solo", NULL},
471 {"meter",
472 (getter)Channel_get_meter, NULL,
473 "meter", NULL},
474 {"abspeak",
475 (getter)Channel_get_abspeak, (setter)Channel_set_abspeak,
476 "balance", NULL},
477 {"midi_scale",
478 NULL, (setter)Channel_set_midi_scale,
479 "midi scale", NULL},
480 {"midi_change_callback",
481 (getter)Channel_get_midi_change_callback,
482 (setter)Channel_set_midi_change_callback,
483 "midi change callback", NULL},
484 {"name",
485 (getter)Channel_get_name,
486 (setter)Channel_set_name,
487 "name", NULL},
488 {"balance_midi_cc",
489 (getter)Channel_get_balance_midi_cc,
490 (setter)Channel_set_balance_midi_cc,
491 "Balance MIDI CC", NULL},
492 {"volume_midi_cc",
493 (getter)Channel_get_volume_midi_cc,
494 (setter)Channel_set_volume_midi_cc,
495 "Volume MIDI CC", NULL},
496 {"midi_in_got_events",
497 (getter)Channel_get_midi_in_got_events, NULL,
498 "Got new MIDI IN events", NULL},
499 {NULL}
502 static PyObject*
503 Channel_remove(ChannelObject *self, PyObject *args)
505 if (! PyArg_ParseTuple(args, "")) return NULL;
506 remove_channel(self->channel);
507 Py_INCREF(Py_None);
508 return Py_None;
511 static PyObject*
512 Channel_autoset_midi_cc(ChannelObject *self, PyObject *args)
514 if (! PyArg_ParseTuple(args, "")) return NULL;
515 channel_autoset_midi_cc(self->channel);
516 Py_INCREF(Py_None);
517 return Py_None;
520 static PyMethodDef channel_methods[] = {
521 {"remove", (PyCFunction)Channel_remove, METH_VARARGS, "Remove"},
522 {"autoset_midi_cc", (PyCFunction)Channel_autoset_midi_cc, METH_VARARGS, "Autoset MIDI CC"},
523 {NULL}
526 static PyTypeObject ChannelType = {
527 PyObject_HEAD_INIT(NULL)
528 0, /*ob_size*/
529 "jack_mixer_c.Channel", /*tp_name*/
530 sizeof(ChannelObject), /*tp_basicsize*/
531 0, /*tp_itemsize*/
532 (destructor)Channel_dealloc, /*tp_dealloc*/
533 0, /*tp_print*/
534 0, /*tp_getattr*/
535 0, /*tp_setattr*/
536 0, /*tp_compare*/
537 0, /*tp_repr*/
538 0, /*tp_as_number*/
539 0, /*tp_as_sequence*/
540 0, /*tp_as_mapping*/
541 0, /*tp_hash */
542 0, /*tp_call*/
543 0, /*tp_str*/
544 0, /*tp_getattro*/
545 0, /*tp_setattro*/
546 0, /*tp_as_buffer*/
547 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
548 "Channel objects", /* tp_doc */
549 0, /* tp_traverse */
550 0, /* tp_clear */
551 0, /* tp_richcompare */
552 0, /* tp_weaklistoffset */
553 0, /* tp_iter */
554 0, /* tp_iternext */
555 channel_methods, /* tp_methods */
556 0, /* tp_members */
557 Channel_getseters, /* tp_getset */
558 0, /* tp_base */
559 0, /* tp_dict */
560 0, /* tp_descr_get */
561 0, /* tp_descr_set */
562 0, /* tp_dictoffset */
563 (initproc)Channel_init, /* tp_init */
564 0, /* tp_alloc */
565 Channel_new, /* tp_new */
568 static PyObject*
569 Channel_New(jack_mixer_channel_t channel)
571 ChannelObject *self;
572 self = (ChannelObject*)PyObject_NEW(ChannelObject, &ChannelType);
573 if (self != NULL) {
574 self->channel = channel;
575 self->midi_change_callback = NULL;
577 return (PyObject*)self;
580 /** Output Channel Type **/
582 typedef struct {
583 PyObject_HEAD
584 PyObject *midi_change_callback;
585 jack_mixer_output_channel_t *output_channel;
586 } OutputChannelObject;
588 static int
589 OutputChannel_set_prefader(OutputChannelObject *self, PyObject *value, void *closure)
591 if (value == Py_True) {
592 output_channel_set_prefader(self->output_channel, true);
593 } else {
594 output_channel_set_prefader(self->output_channel, false);
596 return 0;
599 static PyObject*
600 OutputChannel_get_prefader(OutputChannelObject *self, void *closure)
602 PyObject *result;
604 if (output_channel_is_prefader(self->output_channel)) {
605 result = Py_True;
606 } else {
607 result = Py_False;
609 Py_INCREF(result);
610 return result;
613 static PyGetSetDef OutputChannel_getseters[] = {
614 {"prefader",
615 (getter)OutputChannel_get_prefader, (setter)OutputChannel_set_prefader,
616 "prefader", NULL},
617 {NULL}
620 static PyObject*
621 OutputChannel_remove(OutputChannelObject *self, PyObject *args)
623 if (! PyArg_ParseTuple(args, "")) return NULL;
624 remove_output_channel(self->output_channel);
625 Py_INCREF(Py_None);
626 return Py_None;
629 static PyObject*
630 OutputChannel_set_solo(OutputChannelObject *self, PyObject *args)
632 PyObject *channel;
633 unsigned char solo;
635 if (! PyArg_ParseTuple(args, "Ob", &channel, &solo)) return NULL;
637 output_channel_set_solo(self->output_channel,
638 ((ChannelObject*)channel)->channel,
639 solo);
641 Py_INCREF(Py_None);
642 return Py_None;
645 static PyObject*
646 OutputChannel_set_muted(OutputChannelObject *self, PyObject *args)
648 PyObject *channel;
649 unsigned char muted;
651 if (! PyArg_ParseTuple(args, "Ob", &channel, &muted)) return NULL;
653 output_channel_set_muted(self->output_channel,
654 ((ChannelObject*)channel)->channel,
655 muted);
657 Py_INCREF(Py_None);
658 return Py_None;
661 static PyObject*
662 OutputChannel_is_solo(OutputChannelObject *self, PyObject *args)
664 PyObject *channel;
665 PyObject *result;
667 if (! PyArg_ParseTuple(args, "O", &channel)) return NULL;
669 if (output_channel_is_solo(self->output_channel,
670 ((ChannelObject*)channel)->channel)) {
671 result = Py_True;
672 } else {
673 result = Py_False;
676 Py_INCREF(result);
677 return result;
680 static PyObject*
681 OutputChannel_is_muted(OutputChannelObject *self, PyObject *args)
683 PyObject *channel;
684 PyObject *result;
686 if (! PyArg_ParseTuple(args, "O", &channel)) return NULL;
688 if (output_channel_is_muted(self->output_channel,
689 ((ChannelObject*)channel)->channel)) {
690 result = Py_True;
691 } else {
692 result = Py_False;
695 Py_INCREF(result);
696 return result;
699 static PyMethodDef output_channel_methods[] = {
700 {"remove", (PyCFunction)OutputChannel_remove, METH_VARARGS, "Remove"},
701 {"set_solo", (PyCFunction)OutputChannel_set_solo, METH_VARARGS, "Set a channel as solo"},
702 {"set_muted", (PyCFunction)OutputChannel_set_muted, METH_VARARGS, "Set a channel as muted"},
703 {"is_solo", (PyCFunction)OutputChannel_is_solo, METH_VARARGS, "Is a channel set as solo"},
704 {"is_muted", (PyCFunction)OutputChannel_is_muted, METH_VARARGS, "Is a channel set as muted"},
705 {NULL}
708 static PyTypeObject OutputChannelType = {
709 PyObject_HEAD_INIT(NULL)
710 0, /*ob_size*/
711 "jack_mixer_c.OutputChannel", /*tp_name*/
712 sizeof(OutputChannelObject), /*tp_basicsize*/
713 0, /*tp_itemsize*/
714 0, /*tp_dealloc*/
715 0, /*tp_print*/
716 0, /*tp_getattr*/
717 0, /*tp_setattr*/
718 0, /*tp_compare*/
719 0, /*tp_repr*/
720 0, /*tp_as_number*/
721 0, /*tp_as_sequence*/
722 0, /*tp_as_mapping*/
723 0, /*tp_hash */
724 0, /*tp_call*/
725 0, /*tp_str*/
726 0, /*tp_getattro*/
727 0, /*tp_setattro*/
728 0, /*tp_as_buffer*/
729 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
730 "Output Channel objects", /* tp_doc */
731 0, /* tp_traverse */
732 0, /* tp_clear */
733 0, /* tp_richcompare */
734 0, /* tp_weaklistoffset */
735 0, /* tp_iter */
736 0, /* tp_iternext */
737 output_channel_methods, /* tp_methods */
738 0, /* tp_members */
739 OutputChannel_getseters, /* tp_getset */
740 &ChannelType, /* tp_base */
741 0, /* tp_dict */
742 0, /* tp_descr_get */
743 0, /* tp_descr_set */
744 0, /* tp_dictoffset */
745 0, /* tp_init */
746 0, /* tp_alloc */
747 0, /* tp_new */
750 static PyObject*
751 OutputChannel_New(jack_mixer_output_channel_t output_channel)
753 OutputChannelObject *self;
754 self = (OutputChannelObject*)PyObject_NEW(OutputChannelObject, &OutputChannelType);
755 if (self != NULL) {
756 self->midi_change_callback = NULL;
757 self->output_channel = output_channel;
759 return (PyObject*)self;
763 /** Mixer Type **/
765 typedef struct {
766 PyObject_HEAD
767 PyObject *main_mix_channel;
768 jack_mixer_t mixer;
769 } MixerObject;
771 static void
772 Mixer_dealloc(MixerObject *self)
774 Py_XDECREF(self->main_mix_channel);
775 if (self->mixer)
776 destroy(self->mixer);
777 self->ob_type->tp_free((PyObject*)self);
780 static PyObject*
781 Mixer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
783 MixerObject *self;
785 self = (MixerObject*)type->tp_alloc(type, 0);
787 if (self != NULL) {
788 self->main_mix_channel = NULL;
789 self->mixer = NULL;
792 return (PyObject*)self;
795 static int
796 Mixer_init(MixerObject *self, PyObject *args, PyObject *kwds)
798 static char *kwlist[] = {"name", "stereo", NULL};
799 char *name;
800 int stereo = 1;
802 if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|b", kwlist, &name, &stereo))
803 return -1;
805 self->mixer = create(name, (bool)stereo);
806 if (self->mixer == NULL) {
807 PyErr_SetString(PyExc_RuntimeError,
808 "error creating mixer, probably jack is not running");
809 return -1;
812 self->main_mix_channel = Channel_New(get_main_mix_channel(self->mixer));
814 return 0;
817 static PyMemberDef Mixer_members[] = {
818 {"main_mix_channel", T_OBJECT, offsetof(MixerObject, main_mix_channel), 0, "main_mix_channel"},
819 {NULL}
822 static PyObject*
823 Mixer_get_channels_count(MixerObject *self, void *closure)
825 return PyInt_FromLong(get_channels_count(self->mixer));
828 static PyObject*
829 Mixer_get_client_name(MixerObject *self, void *closure)
831 return PyString_FromString(get_client_name(self->mixer));
834 static PyObject*
835 Mixer_get_last_midi_channel(MixerObject *self, void *closure)
837 return PyInt_FromLong(get_last_midi_channel(self->mixer));
841 static PyGetSetDef Mixer_getseters[] = {
842 {"channels_count", (getter)Mixer_get_channels_count, NULL,
843 "channels count", NULL},
844 {"last_midi_channel", (getter)Mixer_get_last_midi_channel, NULL,
845 "last midi channel", NULL},
846 {NULL}
849 static PyObject*
850 Mixer_add_channel(MixerObject *self, PyObject *args)
852 char *name;
853 int stereo;
854 jack_mixer_channel_t channel;
856 if (! PyArg_ParseTuple(args, "si", &name, &stereo)) return NULL;
858 channel = add_channel(self->mixer, name, (bool)stereo);
860 if (channel == NULL) {
861 PyErr_SetString(PyExc_RuntimeError, "error adding channel");
862 return NULL;
865 return Channel_New(channel);
868 static PyObject*
869 Mixer_add_output_channel(MixerObject *self, PyObject *args)
871 char *name;
872 int stereo = 1;
873 int system = 0;
874 jack_mixer_output_channel_t channel;
876 if (! PyArg_ParseTuple(args, "s|bb", &name, &stereo, &system)) return NULL;
878 channel = add_output_channel(self->mixer, name, (bool)stereo, (bool)system);
880 return OutputChannel_New(channel);
883 static PyObject*
884 Mixer_destroy(MixerObject *self, PyObject *args)
886 if (self->mixer) {
887 destroy(self->mixer);
888 self->mixer = NULL;
890 Py_INCREF(Py_None);
891 return Py_None;
894 static PyMethodDef Mixer_methods[] = {
895 {"add_channel", (PyCFunction)Mixer_add_channel, METH_VARARGS, "Add a new channel"},
896 {"add_output_channel", (PyCFunction)Mixer_add_output_channel, METH_VARARGS, "Add a new output channel"},
897 {"destroy", (PyCFunction)Mixer_destroy, METH_VARARGS, "Destroy JACK Mixer"},
898 {"client_name", (PyCFunction)Mixer_get_client_name, METH_VARARGS, "Get jack client name"},
899 // {"remove_channel", (PyCFunction)Mixer_remove_channel, METH_VARARGS, "Remove a channel"},
900 {NULL}
903 static PyTypeObject MixerType = {
904 PyObject_HEAD_INIT(NULL)
905 0, /*ob_size*/
906 "jack_mixer_c.Mixer", /*tp_name*/
907 sizeof(MixerObject), /*tp_basicsize*/
908 0, /*tp_itemsize*/
909 (destructor)Mixer_dealloc, /*tp_dealloc*/
910 0, /*tp_print*/
911 0, /*tp_getattr*/
912 0, /*tp_setattr*/
913 0, /*tp_compare*/
914 0, /*tp_repr*/
915 0, /*tp_as_number*/
916 0, /*tp_as_sequence*/
917 0, /*tp_as_mapping*/
918 0, /*tp_hash */
919 0, /*tp_call*/
920 0, /*tp_str*/
921 0, /*tp_getattro*/
922 0, /*tp_setattro*/
923 0, /*tp_as_buffer*/
924 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
925 "Mixer objects", /* tp_doc */
926 0, /* tp_traverse */
927 0, /* tp_clear */
928 0, /* tp_richcompare */
929 0, /* tp_weaklistoffset */
930 0, /* tp_iter */
931 0, /* tp_iternext */
932 Mixer_methods, /* tp_methods */
933 Mixer_members, /* tp_members */
934 Mixer_getseters, /* tp_getset */
935 0, /* tp_base */
936 0, /* tp_dict */
937 0, /* tp_descr_get */
938 0, /* tp_descr_set */
939 0, /* tp_dictoffset */
940 (initproc)Mixer_init, /* tp_init */
941 0, /* tp_alloc */
942 Mixer_new, /* tp_new */
946 static PyMethodDef jack_mixer_methods[] = {
947 {NULL} /* Sentinel */
952 PyMODINIT_FUNC initjack_mixer_c(void)
954 PyObject *m;
956 if (PyType_Ready(&MixerType) < 0)
957 return;
958 if (PyType_Ready(&ChannelType) < 0)
959 return;
960 if (PyType_Ready(&OutputChannelType) < 0)
961 return;
962 if (PyType_Ready(&ScaleType) < 0)
963 return;
965 m = Py_InitModule3("jack_mixer_c", jack_mixer_methods, "Jack Mixer C Helper Module");
967 Py_INCREF(&MixerType);
968 PyModule_AddObject(m, "Mixer", (PyObject*)&MixerType);
969 Py_INCREF(&ChannelType);
970 PyModule_AddObject(m, "Channel", (PyObject*)&ChannelType);
971 Py_INCREF(&OutputChannelType);
972 PyModule_AddObject(m, "OutputChannel", (PyObject*)&OutputChannelType);
973 Py_INCREF(&ScaleType);
974 PyModule_AddObject(m, "Scale", (PyObject*)&ScaleType);