]> git.0d.be Git - jack_mixer.git/blob - jack_mixer_c.c
Set version to 14 in preparation for next release
[jack_mixer.git] / jack_mixer_c.c
1 /*
2  * This file is part of jack_mixer
3  *
4  * Copyright (C) 2009 Frederic Peters <fpeters@0d.be>
5  *
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
9  *
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.
14  *
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.
18  */
19
20 #include <Python.h>
21
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stdbool.h>
25
26 #include <structmember.h>
27
28 #include "jack_mixer.h"
29
30
31 /** Scale Type **/
32
33 typedef struct {
34         PyObject_HEAD
35         jack_mixer_scale_t scale;
36 } ScaleObject;
37
38 static void
39 Scale_dealloc(ScaleObject *self)
40 {
41         if (self->scale)
42                 scale_destroy(self->scale);
43         Py_TYPE(self)->tp_free((PyObject*)self);
44 }
45
46 static int
47 Scale_init(ScaleObject *self, PyObject *args, PyObject *kwds)
48 {
49         self->scale = scale_create();
50         return 0;
51 }
52
53 static PyObject*
54 Scale_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
55 {
56         ScaleObject *self;
57
58         self = (ScaleObject*)type->tp_alloc(type, 0);
59
60         return (PyObject*)self;
61 }
62
63 static PyObject*
64 Scale_add_threshold(ScaleObject *self, PyObject *args)
65 {
66         float db, scale_value;
67
68         if (! PyArg_ParseTuple(args, "ff", &db, &scale_value)) return NULL;
69
70         scale_add_threshold(self->scale, db, scale_value);
71
72         Py_INCREF(Py_None);
73         return Py_None;
74 }
75
76 static PyObject*
77 Scale_calculate_coefficients(ScaleObject *self, PyObject *args)
78 {
79         if (! PyArg_ParseTuple(args, "")) return NULL;
80         scale_calculate_coefficients(self->scale);
81         Py_INCREF(Py_None);
82         return Py_None;
83 }
84
85 static PyObject*
86 Scale_db_to_scale(ScaleObject *self, PyObject *args)
87 {
88         double db;
89         if (! PyArg_ParseTuple(args, "d", &db)) return NULL;
90         return PyFloat_FromDouble(scale_db_to_scale(self->scale, db));
91 }
92
93 static PyObject*
94 Scale_scale_to_db(ScaleObject *self, PyObject *args)
95 {
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));
99 }
100
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}
108 };
109
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 */
149 };
150
151
152 /** Channel Type **/
153
154 typedef struct {
155         PyObject_HEAD
156         PyObject *midi_change_callback;
157         jack_mixer_channel_t channel;
158 } ChannelObject;
159
160 static void
161 Channel_dealloc(ChannelObject *self)
162 {
163         Py_XDECREF(self->midi_change_callback);
164         Py_TYPE(self)->tp_free((PyObject*)self);
165 }
166
167 static int
168 Channel_init(ChannelObject *self, PyObject *args, PyObject *kwds)
169 {
170         self->midi_change_callback = NULL;
171         return 0;
172 }
173
174 static PyObject*
175 Channel_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
176 {
177         ChannelObject *self;
178
179         self = (ChannelObject*)type->tp_alloc(type, 0);
180
181         if (self != NULL) {
182                 self->channel = NULL;
183                 self->midi_change_callback = NULL;
184         }
185
186         return (PyObject*)self;
187 }
188
189 static PyObject*
190 Channel_get_is_stereo(ChannelObject *self, void *closure)
191 {
192         PyObject *result;
193
194         bool is_stereo = channel_is_stereo(self->channel);
195         if (is_stereo) {
196                 result = Py_True;
197         } else {
198                 result = Py_False;
199         }
200         Py_INCREF(result);
201         return result;
202 }
203
204 static PyObject*
205 Channel_get_volume(ChannelObject *self, void *closure)
206 {
207         return PyFloat_FromDouble(channel_volume_read(self->channel));
208 }
209
210 static int
211 Channel_set_volume(ChannelObject *self, PyObject *value, void *closure)
212 {
213         if (self->channel == NULL) {
214                 PyErr_SetString(PyExc_RuntimeError, "unitialized channel");
215                 return -1;
216         }
217         channel_volume_write(self->channel, PyFloat_AsDouble(value));
218         channel_set_midi_cc_volume_picked_up(self->channel, false);
219         return 0;
220 }
221
222 static PyObject*
223 Channel_get_balance(ChannelObject *self, void *closure)
224 {
225         return PyFloat_FromDouble(channel_balance_read(self->channel));
226 }
227
228 static int
229 Channel_set_balance(ChannelObject *self, PyObject *value, void *closure)
230 {
231         channel_balance_write(self->channel, PyFloat_AsDouble(value));
232         channel_set_midi_cc_balance_picked_up(self->channel, false);
233         return 0;
234 }
235
236 static PyObject*
237 Channel_get_out_mute(ChannelObject *self, void *closure)
238 {
239         PyObject *result;
240
241         if (channel_is_out_muted(self->channel)) {
242                 result = Py_True;
243         } else {
244                 result = Py_False;
245         }
246         Py_INCREF(result);
247         return result;
248 }
249
250 static int
251 Channel_set_out_mute(ChannelObject *self, PyObject *value, void *closure)
252 {
253         if (value == Py_True) {
254                 channel_out_mute(self->channel);
255         } else {
256                 channel_out_unmute(self->channel);
257         }
258         return 0;
259 }
260
261 static PyObject*
262 Channel_get_solo(ChannelObject *self, void *closure)
263 {
264         PyObject *result;
265
266         if (channel_is_soloed(self->channel)) {
267                 result = Py_True;
268         } else {
269                 result = Py_False;
270         }
271         Py_INCREF(result);
272         return result;
273 }
274
275 static int
276 Channel_set_solo(ChannelObject *self, PyObject *value, void *closure)
277 {
278         if (value == Py_True) {
279                 channel_solo(self->channel);
280         } else {
281                 channel_unsolo(self->channel);
282         }
283         return 0;
284 }
285
286 static PyObject*
287 Channel_get_meter(ChannelObject *self, void *closure)
288 {
289         PyObject *result;
290         double left, right;
291
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));
301         }
302         return result;
303 }
304
305 static PyObject*
306 Channel_get_abspeak(ChannelObject *self, void *closure)
307 {
308         return PyFloat_FromDouble(channel_abspeak_read(self->channel));
309 }
310
311 static int
312 Channel_set_abspeak(ChannelObject *self, PyObject *value, void *closure)
313 {
314         if (value != Py_None) {
315                 fprintf(stderr, "abspeak can only be reset (set to None)\n");
316                 return -1;
317         }
318         channel_abspeak_reset(self->channel);
319         return 0;
320 }
321
322 static int
323 Channel_set_midi_scale(ChannelObject *self, PyObject *value, void *closure)
324 {
325         ScaleObject *scale_object = (ScaleObject*)value; /* XXX: check */
326
327         channel_set_midi_scale(self->channel, scale_object->scale);
328         return 0;
329 }
330
331
332 static PyObject*
333 Channel_get_midi_change_callback(ChannelObject *self, void *closure)
334 {
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;
341         }
342 }
343
344 static void
345 channel_midi_callback(void *userdata)
346 {
347         ChannelObject *self = (ChannelObject*)userdata;
348         PyGILState_STATE gstate;
349
350         gstate = PyGILState_Ensure();
351         PyObject_CallObject(self->midi_change_callback, NULL);
352         PyGILState_Release(gstate);
353 }
354
355 static int
356 Channel_set_midi_change_callback(ChannelObject *self, PyObject *value, void *closure)
357 {
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;
365                 }
366                 if (self->midi_change_callback) {
367                         Py_XDECREF(self->midi_change_callback);
368                 }
369                 Py_INCREF(value);
370                 self->midi_change_callback = value;
371                 channel_set_midi_change_callback(self->channel,
372                                 channel_midi_callback, self);
373         }
374
375         return 0;
376 }
377
378 static PyObject*
379 Channel_get_name(ChannelObject *self, void *closure)
380 {
381         return PyUnicode_FromString(channel_get_name(self->channel));
382 }
383
384 static int
385 Channel_set_name(ChannelObject *self, PyObject *value, void *closure)
386 {
387         channel_rename(self->channel, PyUnicode_AsUTF8(value));
388         return 0;
389 }
390
391 static PyObject*
392 Channel_get_balance_midi_cc(ChannelObject *self, void *closure)
393 {
394         return PyLong_FromLong(channel_get_balance_midi_cc(self->channel));
395 }
396
397 static int
398 Channel_set_balance_midi_cc(ChannelObject *self, PyObject *value, void *closure)
399 {
400         int new_cc;
401         unsigned int result;
402
403         new_cc = PyLong_AsLong(value);
404         result = channel_set_balance_midi_cc(self->channel, new_cc);
405         if (result == 0) {
406                 return 0;
407         }
408         if (result == 2) {
409                 PyErr_SetString(PyExc_RuntimeError, "value out of range");
410         }
411         return -1;
412 }
413
414 static PyObject*
415 Channel_get_volume_midi_cc(ChannelObject *self, void *closure)
416 {
417         return PyLong_FromLong(channel_get_volume_midi_cc(self->channel));
418 }
419
420 static int
421 Channel_set_volume_midi_cc(ChannelObject *self, PyObject *value, void *closure)
422 {
423         int new_cc;
424         unsigned int result;
425
426         new_cc = PyLong_AsLong(value);
427         result = channel_set_volume_midi_cc(self->channel, new_cc);
428         if (result == 0) {
429                 return 0;
430         }
431         if (result == 2) {
432                 PyErr_SetString(PyExc_RuntimeError, "value out of range");
433         }
434         return -1;
435 }
436
437 static PyObject*
438 Channel_get_mute_midi_cc(ChannelObject *self, void *closure)
439 {
440         return PyLong_FromLong(channel_get_mute_midi_cc(self->channel));
441 }
442
443 static int
444 Channel_set_mute_midi_cc(ChannelObject *self, PyObject *value, void *closure)
445 {
446         int new_cc;
447         unsigned int result;
448
449         new_cc = PyLong_AsLong(value);
450         result = channel_set_mute_midi_cc(self->channel, new_cc);
451         if (result == 0) {
452                 return 0;
453         }
454         if (result == 2) {
455                 PyErr_SetString(PyExc_RuntimeError, "value out of range");
456         }
457         return -1;
458 }
459
460 static PyObject*
461 Channel_get_solo_midi_cc(ChannelObject *self, void *closure)
462 {
463         return PyLong_FromLong(channel_get_solo_midi_cc(self->channel));
464 }
465
466 static int
467 Channel_set_solo_midi_cc(ChannelObject *self, PyObject *value, void *closure)
468 {
469         int new_cc;
470         unsigned int result;
471
472         new_cc = PyLong_AsLong(value);
473         result = channel_set_solo_midi_cc(self->channel, new_cc);
474         if (result == 0) {
475                 return 0;
476         }
477         if (result == 2) {
478                 PyErr_SetString(PyExc_RuntimeError, "value out of range");
479         }
480         return -1;
481 }
482
483 static PyObject*
484 Channel_get_midi_in_got_events(ChannelObject *self, void *closure)
485 {
486         PyObject *result;
487
488         if (channel_get_midi_in_got_events(self->channel)) {
489                 result = Py_True;
490         } else {
491                 result = Py_False;
492         }
493         Py_INCREF(result);
494         return result;
495 }
496
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}
550 };
551
552 static PyObject*
553 Channel_remove(ChannelObject *self, PyObject *args)
554 {
555         if (! PyArg_ParseTuple(args, "")) return NULL;
556         remove_channel(self->channel);
557         Py_INCREF(Py_None);
558         return Py_None;
559 }
560
561 static PyObject*
562 Channel_autoset_volume_midi_cc(ChannelObject *self, PyObject *args)
563 {
564         if (! PyArg_ParseTuple(args, "")) return NULL;
565         channel_autoset_volume_midi_cc(self->channel);
566         Py_INCREF(Py_None);
567         return Py_None;
568 }
569
570 static PyObject*
571 Channel_autoset_balance_midi_cc(ChannelObject *self, PyObject *args)
572 {
573         if (! PyArg_ParseTuple(args, "")) return NULL;
574         channel_autoset_balance_midi_cc(self->channel);
575         Py_INCREF(Py_None);
576         return Py_None;
577 }
578
579 static PyObject*
580 Channel_autoset_mute_midi_cc(ChannelObject *self, PyObject *args)
581 {
582         if (! PyArg_ParseTuple(args, "")) return NULL;
583         channel_autoset_mute_midi_cc(self->channel);
584         Py_INCREF(Py_None);
585         return Py_None;
586 }
587
588 static PyObject*
589 Channel_autoset_solo_midi_cc(ChannelObject *self, PyObject *args)
590 {
591         if (! PyArg_ParseTuple(args, "")) return NULL;
592         channel_autoset_solo_midi_cc(self->channel);
593         Py_INCREF(Py_None);
594         return Py_None;
595 }
596
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}
608 };
609
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 */
649 };
650
651 static PyObject*
652 Channel_New(jack_mixer_channel_t channel)
653 {
654         ChannelObject *self;
655         self = (ChannelObject*)PyObject_NEW(ChannelObject, &ChannelType);
656         if (self != NULL) {
657                 self->channel = channel;
658                 self->midi_change_callback = NULL;
659         }
660         return (PyObject*)self;
661 }
662
663 /** Output Channel Type **/
664
665 typedef struct {
666         PyObject_HEAD
667         PyObject *midi_change_callback;
668         jack_mixer_output_channel_t *output_channel;
669 } OutputChannelObject;
670
671 static int
672 OutputChannel_set_prefader(OutputChannelObject *self, PyObject *value, void *closure)
673 {
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);
678         }
679         return 0;
680 }
681
682 static PyObject*
683 OutputChannel_get_prefader(OutputChannelObject *self, void *closure)
684 {
685         PyObject *result;
686
687         if (output_channel_is_prefader(self->output_channel)) {
688                 result = Py_True;
689         } else {
690                 result = Py_False;
691         }
692         Py_INCREF(result);
693         return result;
694 }
695
696 static PyGetSetDef OutputChannel_getseters[] = {
697         {"prefader",
698                 (getter)OutputChannel_get_prefader, (setter)OutputChannel_set_prefader,
699                 "prefader", NULL},
700         {NULL}
701 };
702
703 static PyObject*
704 OutputChannel_remove(OutputChannelObject *self, PyObject *args)
705 {
706         if (! PyArg_ParseTuple(args, "")) return NULL;
707         remove_output_channel(self->output_channel);
708         Py_INCREF(Py_None);
709         return Py_None;
710 }
711
712 static PyObject*
713 OutputChannel_set_solo(OutputChannelObject *self, PyObject *args)
714 {
715         PyObject *channel;
716         unsigned char solo;
717
718         if (! PyArg_ParseTuple(args, "Ob", &channel, &solo)) return NULL;
719
720         output_channel_set_solo(self->output_channel,
721                         ((ChannelObject*)channel)->channel,
722                         solo);
723
724         Py_INCREF(Py_None);
725         return Py_None;
726 }
727
728 static PyObject*
729 OutputChannel_set_muted(OutputChannelObject *self, PyObject *args)
730 {
731         PyObject *channel;
732         unsigned char muted;
733
734         if (! PyArg_ParseTuple(args, "Ob", &channel, &muted)) return NULL;
735
736         output_channel_set_muted(self->output_channel,
737                         ((ChannelObject*)channel)->channel,
738                         muted);
739
740         Py_INCREF(Py_None);
741         return Py_None;
742 }
743
744 static PyObject*
745 OutputChannel_is_solo(OutputChannelObject *self, PyObject *args)
746 {
747         PyObject *channel;
748         PyObject *result;
749
750         if (! PyArg_ParseTuple(args, "O", &channel)) return NULL;
751
752         if (output_channel_is_solo(self->output_channel,
753                         ((ChannelObject*)channel)->channel)) {
754                 result = Py_True;
755         } else {
756                 result = Py_False;
757         }
758
759         Py_INCREF(result);
760         return result;
761 }
762
763 static PyObject*
764 OutputChannel_is_muted(OutputChannelObject *self, PyObject *args)
765 {
766         PyObject *channel;
767         PyObject *result;
768
769         if (! PyArg_ParseTuple(args, "O", &channel)) return NULL;
770
771         if (output_channel_is_muted(self->output_channel,
772                         ((ChannelObject*)channel)->channel)) {
773                 result = Py_True;
774         } else {
775                 result = Py_False;
776         }
777
778         Py_INCREF(result);
779         return result;
780 }
781
782 static PyObject*
783 OutputChannel_set_in_prefader(OutputChannelObject *self, PyObject *args)
784 {
785         PyObject *channel;
786         unsigned char prefader;
787
788         if (! PyArg_ParseTuple(args, "Ob", &channel, &prefader)) return NULL;
789
790         output_channel_set_in_prefader(self->output_channel,
791                         ((ChannelObject*)channel)->channel,
792                         prefader);
793
794         Py_INCREF(Py_None);
795         return Py_None;
796 }
797
798 static PyObject*
799 OutputChannel_is_in_prefader(OutputChannelObject *self, PyObject *args)
800 {
801         PyObject *channel;
802         PyObject *result;
803
804         if (! PyArg_ParseTuple(args, "O", &channel)) return NULL;
805
806         if (output_channel_is_in_prefader(self->output_channel,
807                         ((ChannelObject*)channel)->channel)) {
808                 result = Py_True;
809         } else {
810                 result = Py_False;
811         }
812
813         Py_INCREF(result);
814         return result;
815 }
816
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}
826 };
827
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 */
867 };
868
869 static PyObject*
870 OutputChannel_New(jack_mixer_output_channel_t output_channel)
871 {
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;
877         }
878         return (PyObject*)self;
879 }
880
881
882 /** Mixer Type **/
883
884 typedef struct {
885         PyObject_HEAD
886         jack_mixer_t mixer;
887 } MixerObject;
888
889 static void
890 Mixer_dealloc(MixerObject *self)
891 {
892         if (self->mixer)
893                 destroy(self->mixer);
894         Py_TYPE(self)->tp_free((PyObject*)self);
895 }
896
897 static PyObject*
898 Mixer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
899 {
900         MixerObject *self;
901
902         self = (MixerObject*)type->tp_alloc(type, 0);
903
904         if (self != NULL) {
905                 self->mixer = NULL;
906         }
907
908         return (PyObject*)self;
909 }
910
911 static int
912 Mixer_init(MixerObject *self, PyObject *args, PyObject *kwds)
913 {
914         static char *kwlist[] = {"name", "stereo", NULL};
915         char *name;
916         int stereo = 1;
917
918         if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|b", kwlist, &name, &stereo))
919                 return -1;
920
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;
926         }
927
928         return 0;
929 }
930
931 static PyMemberDef Mixer_members[] = {
932         {NULL}
933 };
934
935 static PyObject*
936 Mixer_get_channels_count(MixerObject *self, void *closure)
937 {
938         return PyLong_FromLong(get_channels_count(self->mixer));
939 }
940
941 static PyObject*
942 Mixer_get_client_name(MixerObject *self, void *closure)
943 {
944         return PyUnicode_FromString(get_client_name(self->mixer));
945 }
946
947 static PyObject*
948 Mixer_get_last_midi_channel(MixerObject *self, void *closure)
949 {
950         return PyLong_FromLong(get_last_midi_channel(self->mixer));
951 }
952
953 static int
954 Mixer_set_last_midi_channel(MixerObject *self, PyObject *value, void *closure)
955 {
956         int new_channel;
957         unsigned int result;
958
959         new_channel = PyLong_AsLong(value);
960         result = set_last_midi_channel(self->mixer, new_channel);
961         if (result == 0) {
962                 return 0;
963         }
964         return -1;
965 }
966
967 static PyObject*
968 Mixer_get_midi_behavior_mode(MixerObject *self, void *closure)
969 {
970         return PyLong_FromLong(get_midi_behavior_mode(self->mixer));
971 }
972
973 static int
974 Mixer_set_midi_behavior_mode(MixerObject *self, PyObject *value, void *closure)
975 {
976         int mode;
977         unsigned int result;
978         
979         mode = PyLong_AsLong(value);
980         result = set_midi_behavior_mode(self->mixer, mode);
981         if (result == 0) {
982                 return 0;
983         }
984         return -1;
985 }
986
987
988
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}
997 };
998
999 static PyObject*
1000 Mixer_add_channel(MixerObject *self, PyObject *args)
1001 {
1002         char *name;
1003         int stereo;
1004         jack_mixer_channel_t channel;
1005
1006         if (! PyArg_ParseTuple(args, "si", &name, &stereo)) return NULL;
1007
1008         channel = add_channel(self->mixer, name, (bool)stereo);
1009
1010         if (channel == NULL) {
1011                 PyErr_SetString(PyExc_RuntimeError, "error adding channel");
1012                 return NULL;
1013         }
1014
1015         return Channel_New(channel);
1016 }
1017
1018 static PyObject*
1019 Mixer_add_output_channel(MixerObject *self, PyObject *args)
1020 {
1021         char *name;
1022         int stereo = 1;
1023         int system = 0;
1024         jack_mixer_output_channel_t channel;
1025
1026         if (! PyArg_ParseTuple(args, "s|bb", &name, &stereo, &system)) return NULL;
1027
1028         channel = add_output_channel(self->mixer, name, (bool)stereo, (bool)system);
1029
1030         return OutputChannel_New(channel);
1031 }
1032
1033 static PyObject*
1034 Mixer_destroy(MixerObject *self, PyObject *args)
1035 {
1036         if (self->mixer) {
1037                 destroy(self->mixer);
1038                 self->mixer = NULL;
1039         }
1040         Py_INCREF(Py_None);
1041         return Py_None;
1042 }
1043
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}
1051 };
1052
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 */
1092 };
1093
1094
1095 static PyMethodDef jack_mixer_methods[] = {
1096         {NULL, NULL, 0, NULL}  /* Sentinel */
1097 };
1098
1099
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 */
1110 };
1111
1112 PyMODINIT_FUNC PyInit_jack_mixer_c(void)
1113 {
1114         PyObject *m;
1115
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;
1124                 
1125         m = PyModule_Create(&moduledef);
1126         //m = Py_InitModule3("jack_mixer_c", jack_mixer_methods, "module doc");
1127         
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);
1136         
1137         return m;
1138 }
1139