]> git.0d.be Git - jack_mixer.git/blob - jack_mixer_c.c
Remove main mix channel
[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         self->ob_type->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         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 */
150 };
151
152
153 /** Channel Type **/
154
155 typedef struct {
156         PyObject_HEAD
157         PyObject *midi_change_callback;
158         jack_mixer_channel_t channel;
159 } ChannelObject;
160
161 static void
162 Channel_dealloc(ChannelObject *self)
163 {
164         Py_XDECREF(self->midi_change_callback);
165         self->ob_type->tp_free((PyObject*)self);
166 }
167
168 static int
169 Channel_init(ChannelObject *self, PyObject *args, PyObject *kwds)
170 {
171         self->midi_change_callback = NULL;
172         return 0;
173 }
174
175 static PyObject*
176 Channel_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
177 {
178         ChannelObject *self;
179
180         self = (ChannelObject*)type->tp_alloc(type, 0);
181
182         if (self != NULL) {
183                 self->channel = NULL;
184                 self->midi_change_callback = NULL;
185         }
186
187         return (PyObject*)self;
188 }
189
190 static PyObject*
191 Channel_get_is_stereo(ChannelObject *self, void *closure)
192 {
193         PyObject *result;
194
195         bool is_stereo = channel_is_stereo(self->channel);
196         if (is_stereo) {
197                 result = Py_True;
198         } else {
199                 result = Py_False;
200         }
201         Py_INCREF(result);
202         return result;
203 }
204
205 static PyObject*
206 Channel_get_volume(ChannelObject *self, void *closure)
207 {
208         return PyFloat_FromDouble(channel_volume_read(self->channel));
209 }
210
211 static int
212 Channel_set_volume(ChannelObject *self, PyObject *value, void *closure)
213 {
214         if (self->channel == NULL) {
215                 PyErr_SetString(PyExc_RuntimeError, "unitialized channel");
216                 return -1;
217         }
218         channel_volume_write(self->channel, PyFloat_AsDouble(value));
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         return 0;
233 }
234
235 static PyObject*
236 Channel_get_out_mute(ChannelObject *self, void *closure)
237 {
238         PyObject *result;
239
240     if (channel_is_out_muted(self->channel)) {
241                 result = Py_True;
242         } else {
243                 result = Py_False;
244         }
245         Py_INCREF(result);
246         return result;
247 }
248
249 static int
250 Channel_set_out_mute(ChannelObject *self, PyObject *value, void *closure)
251 {
252         if (value == Py_True) {
253                 channel_out_mute(self->channel);
254         } else {
255                 channel_out_unmute(self->channel);
256         }
257         return 0;
258 }
259
260 static PyObject*
261 Channel_get_meter(ChannelObject *self, void *closure)
262 {
263         PyObject *result;
264         double left, right;
265
266         if (channel_is_stereo(self->channel)) {
267                 result = PyTuple_New(2);
268                 channel_stereo_meter_read(self->channel, &left, &right);
269                 PyTuple_SetItem(result, 0, PyFloat_FromDouble(left));
270                 PyTuple_SetItem(result, 1, PyFloat_FromDouble(right));
271         } else {
272                 result = PyTuple_New(1);
273                 channel_mono_meter_read(self->channel, &left);
274                 PyTuple_SetItem(result, 0, PyFloat_FromDouble(left));
275         }
276         return result;
277 }
278
279 static PyObject*
280 Channel_get_abspeak(ChannelObject *self, void *closure)
281 {
282         return PyFloat_FromDouble(channel_abspeak_read(self->channel));
283 }
284
285 static int
286 Channel_set_abspeak(ChannelObject *self, PyObject *value, void *closure)
287 {
288         if (value != Py_None) {
289                 fprintf(stderr, "abspeak can only be reset (set to None)\n");
290                 return -1;
291         }
292         channel_abspeak_reset(self->channel);
293         return 0;
294 }
295
296 static int
297 Channel_set_midi_scale(ChannelObject *self, PyObject *value, void *closure)
298 {
299         ScaleObject *scale_object = (ScaleObject*)value; /* XXX: check */
300
301         channel_set_midi_scale(self->channel, scale_object->scale);
302         return 0;
303 }
304
305
306 static PyObject*
307 Channel_get_midi_change_callback(ChannelObject *self, void *closure)
308 {
309         if (self->midi_change_callback) {
310                 Py_INCREF(self->midi_change_callback);
311                 return self->midi_change_callback;
312         } else {
313                 Py_INCREF(Py_None);
314                 return Py_None;
315         }
316 }
317
318 static void
319 channel_midi_callback(void *userdata)
320 {
321         ChannelObject *self = (ChannelObject*)userdata;
322         PyGILState_STATE gstate;
323
324         gstate = PyGILState_Ensure();
325         PyObject_CallObject(self->midi_change_callback, NULL);
326         PyGILState_Release(gstate);
327 }
328
329 static int
330 Channel_set_midi_change_callback(ChannelObject *self, PyObject *value, void *closure)
331 {
332         if (value == Py_None) {
333                 self->midi_change_callback = NULL;
334                 channel_set_midi_change_callback(self->channel, NULL, NULL);
335         } else {
336                 if (!PyCallable_Check(value)) {
337                         PyErr_SetString(PyExc_TypeError, "value must be callable");
338                         return -1;
339                 }
340                 if (self->midi_change_callback) {
341                         Py_XDECREF(self->midi_change_callback);
342                 }
343                 Py_INCREF(value);
344                 self->midi_change_callback = value;
345                 channel_set_midi_change_callback(self->channel,
346                                 channel_midi_callback, self);
347         }
348
349         return 0;
350 }
351
352 static PyObject*
353 Channel_get_name(ChannelObject *self, void *closure)
354 {
355         return PyString_FromString(channel_get_name(self->channel));
356 }
357
358 static int
359 Channel_set_name(ChannelObject *self, PyObject *value, void *closure)
360 {
361         channel_rename(self->channel, PyString_AsString(value));
362         return 0;
363 }
364
365 static PyObject*
366 Channel_get_balance_midi_cc(ChannelObject *self, void *closure)
367 {
368         return PyInt_FromLong(channel_get_balance_midi_cc(self->channel));
369 }
370
371 static int
372 Channel_set_balance_midi_cc(ChannelObject *self, PyObject *value, void *closure)
373 {
374         unsigned int new_cc;
375         unsigned int result;
376
377         new_cc = PyInt_AsLong(value);
378         result = channel_set_balance_midi_cc(self->channel, new_cc);
379         if (result == 0) {
380                 return 0;
381         }
382         if (result == 1) {
383                 PyErr_SetString(PyExc_RuntimeError, "value already in use");
384         } else if (result == 2) {
385                 PyErr_SetString(PyExc_RuntimeError, "value out of range");
386         }
387         return -1;
388 }
389
390 static PyObject*
391 Channel_get_volume_midi_cc(ChannelObject *self, void *closure)
392 {
393         return PyInt_FromLong(channel_get_volume_midi_cc(self->channel));
394 }
395
396 static int
397 Channel_set_volume_midi_cc(ChannelObject *self, PyObject *value, void *closure)
398 {
399         unsigned int new_cc;
400         unsigned int result;
401
402         new_cc = PyInt_AsLong(value);
403         result = channel_set_volume_midi_cc(self->channel, new_cc);
404         if (result == 0) {
405                 return 0;
406         }
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");
411         }
412         return -1;
413 }
414
415 static PyObject*
416 Channel_get_midi_in_got_events(ChannelObject *self, void *closure)
417 {
418         PyObject *result;
419
420         if (channel_get_midi_in_got_events(self->channel)) {
421                 result = Py_True;
422         } else {
423                 result = Py_False;
424         }
425         Py_INCREF(result);
426         return result;
427 }
428
429
430 static PyGetSetDef Channel_getseters[] = {
431         {"is_stereo",
432                 (getter)Channel_get_is_stereo, NULL,
433                 "mono/stereo", NULL},
434         {"volume",
435                 (getter)Channel_get_volume, (setter)Channel_set_volume,
436                 "volume", NULL},
437         {"balance",
438                 (getter)Channel_get_balance, (setter)Channel_set_balance,
439                 "balance", NULL},
440         {"out_mute",
441                 (getter)Channel_get_out_mute, (setter)Channel_set_out_mute,
442                 "out_mute", NULL},
443         {"meter",
444                 (getter)Channel_get_meter, NULL,
445                 "meter", NULL},
446         {"abspeak",
447                 (getter)Channel_get_abspeak, (setter)Channel_set_abspeak,
448                 "balance", NULL},
449         {"midi_scale",
450                 NULL, (setter)Channel_set_midi_scale,
451                 "midi scale", NULL},
452         {"midi_change_callback",
453                 (getter)Channel_get_midi_change_callback,
454                 (setter)Channel_set_midi_change_callback,
455                 "midi change callback", NULL},
456         {"name",
457                 (getter)Channel_get_name,
458                 (setter)Channel_set_name,
459                 "name", NULL},
460         {"balance_midi_cc",
461                 (getter)Channel_get_balance_midi_cc,
462                 (setter)Channel_set_balance_midi_cc,
463                 "Balance MIDI CC", NULL},
464         {"volume_midi_cc",
465                 (getter)Channel_get_volume_midi_cc,
466                 (setter)Channel_set_volume_midi_cc,
467                 "Volume MIDI CC", NULL},
468         {"midi_in_got_events",
469                 (getter)Channel_get_midi_in_got_events, NULL,
470                 "Got new MIDI IN events", NULL},
471         {NULL}
472 };
473
474 static PyObject*
475 Channel_remove(ChannelObject *self, PyObject *args)
476 {
477         if (! PyArg_ParseTuple(args, "")) return NULL;
478         remove_channel(self->channel);
479         Py_INCREF(Py_None);
480         return Py_None;
481 }
482
483 static PyObject*
484 Channel_autoset_midi_cc(ChannelObject *self, PyObject *args)
485 {
486         if (! PyArg_ParseTuple(args, "")) return NULL;
487         channel_autoset_midi_cc(self->channel);
488         Py_INCREF(Py_None);
489         return Py_None;
490 }
491
492 static PyMethodDef channel_methods[] = {
493         {"remove", (PyCFunction)Channel_remove, METH_VARARGS, "Remove"},
494         {"autoset_midi_cc", (PyCFunction)Channel_autoset_midi_cc, METH_VARARGS, "Autoset MIDI CC"},
495         {NULL}
496 };
497
498 static PyTypeObject ChannelType = {
499         PyObject_HEAD_INIT(NULL)
500         0,       /*ob_size*/
501         "jack_mixer_c.Channel",    /*tp_name*/
502         sizeof(ChannelObject), /*tp_basicsize*/
503         0,       /*tp_itemsize*/
504         (destructor)Channel_dealloc,       /*tp_dealloc*/
505         0,       /*tp_print*/
506         0,       /*tp_getattr*/
507         0,       /*tp_setattr*/
508         0,       /*tp_compare*/
509         0,       /*tp_repr*/
510         0,       /*tp_as_number*/
511         0,       /*tp_as_sequence*/
512         0,       /*tp_as_mapping*/
513         0,       /*tp_hash */
514         0,       /*tp_call*/
515         0,       /*tp_str*/
516         0,       /*tp_getattro*/
517         0,       /*tp_setattro*/
518         0,       /*tp_as_buffer*/
519         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,  /*tp_flags*/
520         "Channel objects",           /* tp_doc */
521         0,                         /* tp_traverse */
522         0,                         /* tp_clear */
523         0,                         /* tp_richcompare */
524         0,                         /* tp_weaklistoffset */
525         0,                         /* tp_iter */
526         0,                         /* tp_iternext */
527         channel_methods,           /* tp_methods */
528         0,             /* tp_members */
529         Channel_getseters,           /* tp_getset */
530         0,                         /* tp_base */
531         0,                         /* tp_dict */
532         0,                         /* tp_descr_get */
533         0,                         /* tp_descr_set */
534         0,                         /* tp_dictoffset */
535         (initproc)Channel_init,    /* tp_init */
536         0,                         /* tp_alloc */
537         Channel_new,                 /* tp_new */
538 };
539
540 static PyObject*
541 Channel_New(jack_mixer_channel_t channel)
542 {
543         ChannelObject *self;
544         self = (ChannelObject*)PyObject_NEW(ChannelObject, &ChannelType);
545         if (self != NULL) {
546                 self->channel = channel;
547                 self->midi_change_callback = NULL;
548         }
549         return (PyObject*)self;
550 }
551
552 /** Output Channel Type **/
553
554 typedef struct {
555         PyObject_HEAD
556         PyObject *midi_change_callback;
557         jack_mixer_output_channel_t *output_channel;
558 } OutputChannelObject;
559
560 static int
561 OutputChannel_set_prefader(OutputChannelObject *self, PyObject *value, void *closure)
562 {
563         if (value == Py_True) {
564                 output_channel_set_prefader(self->output_channel, true);
565         } else {
566                 output_channel_set_prefader(self->output_channel, false);
567         }
568         return 0;
569 }
570
571 static PyObject*
572 OutputChannel_get_prefader(OutputChannelObject *self, void *closure)
573 {
574         PyObject *result;
575
576         if (output_channel_is_prefader(self->output_channel)) {
577                 result = Py_True;
578         } else {
579                 result = Py_False;
580         }
581         Py_INCREF(result);
582         return result;
583 }
584
585 static PyGetSetDef OutputChannel_getseters[] = {
586         {"prefader",
587                 (getter)OutputChannel_get_prefader, (setter)OutputChannel_set_prefader,
588                 "prefader", NULL},
589         {NULL}
590 };
591
592 static PyObject*
593 OutputChannel_remove(OutputChannelObject *self, PyObject *args)
594 {
595         if (! PyArg_ParseTuple(args, "")) return NULL;
596         remove_output_channel(self->output_channel);
597         Py_INCREF(Py_None);
598         return Py_None;
599 }
600
601 static PyObject*
602 OutputChannel_set_solo(OutputChannelObject *self, PyObject *args)
603 {
604         PyObject *channel;
605         unsigned char solo;
606
607         if (! PyArg_ParseTuple(args, "Ob", &channel, &solo)) return NULL;
608
609         output_channel_set_solo(self->output_channel,
610                         ((ChannelObject*)channel)->channel,
611                         solo);
612
613         Py_INCREF(Py_None);
614         return Py_None;
615 }
616
617 static PyObject*
618 OutputChannel_set_muted(OutputChannelObject *self, PyObject *args)
619 {
620         PyObject *channel;
621         unsigned char muted;
622
623         if (! PyArg_ParseTuple(args, "Ob", &channel, &muted)) return NULL;
624
625         output_channel_set_muted(self->output_channel,
626                         ((ChannelObject*)channel)->channel,
627                         muted);
628
629         Py_INCREF(Py_None);
630         return Py_None;
631 }
632
633 static PyObject*
634 OutputChannel_is_solo(OutputChannelObject *self, PyObject *args)
635 {
636         PyObject *channel;
637         PyObject *result;
638
639         if (! PyArg_ParseTuple(args, "O", &channel)) return NULL;
640
641         if (output_channel_is_solo(self->output_channel,
642                         ((ChannelObject*)channel)->channel)) {
643                 result = Py_True;
644         } else {
645                 result = Py_False;
646         }
647
648         Py_INCREF(result);
649         return result;
650 }
651
652 static PyObject*
653 OutputChannel_is_muted(OutputChannelObject *self, PyObject *args)
654 {
655         PyObject *channel;
656         PyObject *result;
657
658         if (! PyArg_ParseTuple(args, "O", &channel)) return NULL;
659
660         if (output_channel_is_muted(self->output_channel,
661                         ((ChannelObject*)channel)->channel)) {
662                 result = Py_True;
663         } else {
664                 result = Py_False;
665         }
666
667         Py_INCREF(result);
668         return result;
669 }
670
671 static PyMethodDef output_channel_methods[] = {
672         {"remove", (PyCFunction)OutputChannel_remove, METH_VARARGS, "Remove"},
673         {"set_solo", (PyCFunction)OutputChannel_set_solo, METH_VARARGS, "Set a channel as solo"},
674         {"set_muted", (PyCFunction)OutputChannel_set_muted, METH_VARARGS, "Set a channel as muted"},
675         {"is_solo", (PyCFunction)OutputChannel_is_solo, METH_VARARGS, "Is a channel set as solo"},
676         {"is_muted", (PyCFunction)OutputChannel_is_muted, METH_VARARGS, "Is a channel set as muted"},
677         {NULL}
678 };
679
680 static PyTypeObject OutputChannelType = {
681         PyObject_HEAD_INIT(NULL)
682         0,       /*ob_size*/
683         "jack_mixer_c.OutputChannel",    /*tp_name*/
684         sizeof(OutputChannelObject), /*tp_basicsize*/
685         0,       /*tp_itemsize*/
686         0,       /*tp_dealloc*/
687         0,       /*tp_print*/
688         0,       /*tp_getattr*/
689         0,       /*tp_setattr*/
690         0,       /*tp_compare*/
691         0,       /*tp_repr*/
692         0,       /*tp_as_number*/
693         0,       /*tp_as_sequence*/
694         0,       /*tp_as_mapping*/
695         0,       /*tp_hash */
696         0,       /*tp_call*/
697         0,       /*tp_str*/
698         0,       /*tp_getattro*/
699         0,       /*tp_setattro*/
700         0,       /*tp_as_buffer*/
701         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,  /*tp_flags*/
702         "Output Channel objects",           /* tp_doc */
703         0,                         /* tp_traverse */
704         0,                         /* tp_clear */
705         0,                         /* tp_richcompare */
706         0,                         /* tp_weaklistoffset */
707         0,                         /* tp_iter */
708         0,                         /* tp_iternext */
709         output_channel_methods,    /* tp_methods */
710         0,             /* tp_members */
711         OutputChannel_getseters,   /* tp_getset */
712         &ChannelType,              /* tp_base */
713         0,                         /* tp_dict */
714         0,                         /* tp_descr_get */
715         0,                         /* tp_descr_set */
716         0,                         /* tp_dictoffset */
717         0,                         /* tp_init */
718         0,                         /* tp_alloc */
719         0,                         /* tp_new */
720 };
721
722 static PyObject*
723 OutputChannel_New(jack_mixer_output_channel_t output_channel)
724 {
725         OutputChannelObject *self;
726         self = (OutputChannelObject*)PyObject_NEW(OutputChannelObject, &OutputChannelType);
727         if (self != NULL) {
728                 self->midi_change_callback = NULL;
729                 self->output_channel = output_channel;
730         }
731         return (PyObject*)self;
732 }
733
734
735 /** Mixer Type **/
736
737 typedef struct {
738         PyObject_HEAD
739         jack_mixer_t mixer;
740 } MixerObject;
741
742 static void
743 Mixer_dealloc(MixerObject *self)
744 {
745         if (self->mixer)
746                 destroy(self->mixer);
747         self->ob_type->tp_free((PyObject*)self);
748 }
749
750 static PyObject*
751 Mixer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
752 {
753         MixerObject *self;
754
755         self = (MixerObject*)type->tp_alloc(type, 0);
756
757         if (self != NULL) {
758                 self->mixer = NULL;
759         }
760
761         return (PyObject*)self;
762 }
763
764 static int
765 Mixer_init(MixerObject *self, PyObject *args, PyObject *kwds)
766 {
767         static char *kwlist[] = {"name", "stereo", NULL};
768         char *name;
769         int stereo = 1;
770
771         if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|b", kwlist, &name, &stereo))
772                 return -1;
773
774         self->mixer = create(name, (bool)stereo);
775         if (self->mixer == NULL) {
776                 PyErr_SetString(PyExc_RuntimeError,
777                                 "error creating mixer, probably jack is not running");
778                 return -1;
779         }
780
781         return 0;
782 }
783
784 static PyMemberDef Mixer_members[] = {
785         {NULL}
786 };
787
788 static PyObject*
789 Mixer_get_channels_count(MixerObject *self, void *closure)
790 {
791         return PyInt_FromLong(get_channels_count(self->mixer));
792 }
793
794 static PyObject*
795 Mixer_get_client_name(MixerObject *self, void *closure)
796 {
797         return PyString_FromString(get_client_name(self->mixer));
798 }
799
800 static PyObject*
801 Mixer_get_last_midi_channel(MixerObject *self, void *closure)
802 {
803         return PyInt_FromLong(get_last_midi_channel(self->mixer));
804 }
805
806
807 static PyGetSetDef Mixer_getseters[] = {
808         {"channels_count", (getter)Mixer_get_channels_count, NULL,
809                 "channels count", NULL},
810         {"last_midi_channel", (getter)Mixer_get_last_midi_channel, NULL,
811                 "last midi channel", NULL},
812         {NULL}
813 };
814
815 static PyObject*
816 Mixer_add_channel(MixerObject *self, PyObject *args)
817 {
818         char *name;
819         int stereo;
820         jack_mixer_channel_t channel;
821
822         if (! PyArg_ParseTuple(args, "si", &name, &stereo)) return NULL;
823
824         channel = add_channel(self->mixer, name, (bool)stereo);
825
826         if (channel == NULL) {
827                 PyErr_SetString(PyExc_RuntimeError, "error adding channel");
828                 return NULL;
829         }
830
831         return Channel_New(channel);
832 }
833
834 static PyObject*
835 Mixer_add_output_channel(MixerObject *self, PyObject *args)
836 {
837         char *name;
838         int stereo = 1;
839         int system = 0;
840         jack_mixer_output_channel_t channel;
841
842         if (! PyArg_ParseTuple(args, "s|bb", &name, &stereo, &system)) return NULL;
843
844         channel = add_output_channel(self->mixer, name, (bool)stereo, (bool)system);
845
846         return OutputChannel_New(channel);
847 }
848
849 static PyObject*
850 Mixer_destroy(MixerObject *self, PyObject *args)
851 {
852         if (self->mixer) {
853                 destroy(self->mixer);
854                 self->mixer = NULL;
855         }
856         Py_INCREF(Py_None);
857         return Py_None;
858 }
859
860 static PyMethodDef Mixer_methods[] = {
861         {"add_channel", (PyCFunction)Mixer_add_channel, METH_VARARGS, "Add a new channel"},
862         {"add_output_channel", (PyCFunction)Mixer_add_output_channel, METH_VARARGS, "Add a new output channel"},
863         {"destroy", (PyCFunction)Mixer_destroy, METH_VARARGS, "Destroy JACK Mixer"},
864         {"client_name", (PyCFunction)Mixer_get_client_name, METH_VARARGS, "Get jack client name"},
865 //      {"remove_channel", (PyCFunction)Mixer_remove_channel, METH_VARARGS, "Remove a channel"},
866         {NULL}
867 };
868
869 static PyTypeObject MixerType = {
870         PyObject_HEAD_INIT(NULL)
871         0,       /*ob_size*/
872         "jack_mixer_c.Mixer",    /*tp_name*/
873         sizeof(MixerObject), /*tp_basicsize*/
874         0,       /*tp_itemsize*/
875         (destructor)Mixer_dealloc,       /*tp_dealloc*/
876         0,       /*tp_print*/
877         0,       /*tp_getattr*/
878         0,       /*tp_setattr*/
879         0,       /*tp_compare*/
880         0,       /*tp_repr*/
881         0,       /*tp_as_number*/
882         0,       /*tp_as_sequence*/
883         0,       /*tp_as_mapping*/
884         0,       /*tp_hash */
885         0,       /*tp_call*/
886         0,       /*tp_str*/
887         0,       /*tp_getattro*/
888         0,       /*tp_setattro*/
889         0,       /*tp_as_buffer*/
890         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,  /*tp_flags*/
891         "Mixer objects",           /* tp_doc */
892         0,                         /* tp_traverse */
893         0,                         /* tp_clear */
894         0,                         /* tp_richcompare */
895         0,                         /* tp_weaklistoffset */
896         0,                         /* tp_iter */
897         0,                         /* tp_iternext */
898         Mixer_methods,             /* tp_methods */
899         Mixer_members,             /* tp_members */
900         Mixer_getseters,           /* tp_getset */
901         0,                         /* tp_base */
902         0,                         /* tp_dict */
903         0,                         /* tp_descr_get */
904         0,                         /* tp_descr_set */
905         0,                         /* tp_dictoffset */
906         (initproc)Mixer_init,      /* tp_init */
907         0,                         /* tp_alloc */
908         Mixer_new,                 /* tp_new */
909 };
910
911
912 static PyMethodDef jack_mixer_methods[] = {
913         {NULL}  /* Sentinel */
914 };
915
916
917
918 PyMODINIT_FUNC initjack_mixer_c(void)
919 {
920         PyObject *m;
921
922         if (PyType_Ready(&MixerType) < 0)
923                 return;
924         if (PyType_Ready(&ChannelType) < 0)
925                 return;
926         if (PyType_Ready(&OutputChannelType) < 0)
927                 return;
928         if (PyType_Ready(&ScaleType) < 0)
929                 return;
930
931         m = Py_InitModule3("jack_mixer_c", jack_mixer_methods, "Jack Mixer C Helper Module");
932
933         Py_INCREF(&MixerType);
934         PyModule_AddObject(m, "Mixer", (PyObject*)&MixerType);
935         Py_INCREF(&ChannelType);
936         PyModule_AddObject(m, "Channel", (PyObject*)&ChannelType);
937         Py_INCREF(&OutputChannelType);
938         PyModule_AddObject(m, "OutputChannel", (PyObject*)&OutputChannelType);
939         Py_INCREF(&ScaleType);
940         PyModule_AddObject(m, "Scale", (PyObject*)&ScaleType);
941 }
942