]> git.0d.be Git - jack_mixer.git/blobdiff - jack_mixer_c.c
Set version to 14 in preparation for next release
[jack_mixer.git] / jack_mixer_c.c
index 67bb6c207ea16f7f99c73b963ffcb7e2c30e1c9e..f19a5b56e18d04c31d3a9fa99931e766a8c04b48 100644 (file)
@@ -40,7 +40,7 @@ Scale_dealloc(ScaleObject *self)
 {
        if (self->scale)
                scale_destroy(self->scale);
-       self->ob_type->tp_free((PyObject*)self);
+       Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static int
@@ -108,8 +108,7 @@ static PyMethodDef Scale_methods[] = {
 };
 
 static PyTypeObject ScaleType = {
-       PyObject_HEAD_INIT(NULL)
-       0,       /*ob_size*/
+       PyVarObject_HEAD_INIT(NULL, 0)
        "jack_mixer_c.Scale",    /*tp_name*/
        sizeof(ScaleObject), /*tp_basicsize*/
        0,       /*tp_itemsize*/
@@ -162,7 +161,7 @@ static void
 Channel_dealloc(ChannelObject *self)
 {
        Py_XDECREF(self->midi_change_callback);
-       self->ob_type->tp_free((PyObject*)self);
+       Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static int
@@ -211,7 +210,12 @@ Channel_get_volume(ChannelObject *self, void *closure)
 static int
 Channel_set_volume(ChannelObject *self, PyObject *value, void *closure)
 {
+       if (self->channel == NULL) {
+               PyErr_SetString(PyExc_RuntimeError, "unitialized channel");
+               return -1;
+       }
        channel_volume_write(self->channel, PyFloat_AsDouble(value));
+       channel_set_midi_cc_volume_picked_up(self->channel, false);
        return 0;
 }
 
@@ -225,15 +229,16 @@ static int
 Channel_set_balance(ChannelObject *self, PyObject *value, void *closure)
 {
        channel_balance_write(self->channel, PyFloat_AsDouble(value));
+       channel_set_midi_cc_balance_picked_up(self->channel, false);
        return 0;
 }
 
 static PyObject*
-Channel_get_mute(ChannelObject *self, void *closure)
+Channel_get_out_mute(ChannelObject *self, void *closure)
 {
        PyObject *result;
 
-       if (channel_is_muted(self->channel)) {
+       if (channel_is_out_muted(self->channel)) {
                result = Py_True;
        } else {
                result = Py_False;
@@ -243,12 +248,12 @@ Channel_get_mute(ChannelObject *self, void *closure)
 }
 
 static int
-Channel_set_mute(ChannelObject *self, PyObject *value, void *closure)
+Channel_set_out_mute(ChannelObject *self, PyObject *value, void *closure)
 {
        if (value == Py_True) {
-               channel_mute(self->channel);
+               channel_out_mute(self->channel);
        } else {
-               channel_unmute(self->channel);
+               channel_out_unmute(self->channel);
        }
        return 0;
 }
@@ -297,6 +302,28 @@ Channel_get_meter(ChannelObject *self, void *closure)
        return result;
 }
 
+static PyObject*
+Channel_get_kmeter(ChannelObject *self, void *closure)
+{
+       PyObject *result;
+       double peak_left, peak_right, rms_left, rms_right;
+
+       if (channel_is_stereo(self->channel)) {
+               result = PyTuple_New(4);
+               channel_stereo_kmeter_read(self->channel, &peak_left, &peak_right, &rms_left, &rms_right);
+               PyTuple_SetItem(result, 0, PyFloat_FromDouble(peak_left));
+               PyTuple_SetItem(result, 1, PyFloat_FromDouble(peak_right));
+               PyTuple_SetItem(result, 2, PyFloat_FromDouble(rms_left));
+               PyTuple_SetItem(result, 3, PyFloat_FromDouble(rms_right));
+       } else {
+               result = PyTuple_New(2);
+               channel_mono_kmeter_read(self->channel, &peak_left, &rms_left);
+               PyTuple_SetItem(result, 0, PyFloat_FromDouble(peak_left));
+               PyTuple_SetItem(result, 1, PyFloat_FromDouble(rms_left));
+       }
+       return result;
+}
+
 static PyObject*
 Channel_get_abspeak(ChannelObject *self, void *closure)
 {
@@ -373,36 +400,34 @@ Channel_set_midi_change_callback(ChannelObject *self, PyObject *value, void *clo
 static PyObject*
 Channel_get_name(ChannelObject *self, void *closure)
 {
-       return PyString_FromString(channel_get_name(self->channel));
+       return PyUnicode_FromString(channel_get_name(self->channel));
 }
 
 static int
 Channel_set_name(ChannelObject *self, PyObject *value, void *closure)
 {
-       channel_rename(self->channel, PyString_AsString(value));
+       channel_rename(self->channel, PyUnicode_AsUTF8(value));
        return 0;
 }
 
 static PyObject*
 Channel_get_balance_midi_cc(ChannelObject *self, void *closure)
 {
-       return PyInt_FromLong(channel_get_balance_midi_cc(self->channel));
+       return PyLong_FromLong(channel_get_balance_midi_cc(self->channel));
 }
 
 static int
 Channel_set_balance_midi_cc(ChannelObject *self, PyObject *value, void *closure)
 {
-       unsigned int new_cc;
+       int new_cc;
        unsigned int result;
 
-       new_cc = PyInt_AsLong(value);
+       new_cc = PyLong_AsLong(value);
        result = channel_set_balance_midi_cc(self->channel, new_cc);
        if (result == 0) {
                return 0;
        }
-       if (result == 1) {
-               PyErr_SetString(PyExc_RuntimeError, "value already in use");
-       } else if (result == 2) {
+       if (result == 2) {
                PyErr_SetString(PyExc_RuntimeError, "value out of range");
        }
        return -1;
@@ -411,48 +436,109 @@ Channel_set_balance_midi_cc(ChannelObject *self, PyObject *value, void *closure)
 static PyObject*
 Channel_get_volume_midi_cc(ChannelObject *self, void *closure)
 {
-       return PyInt_FromLong(channel_get_volume_midi_cc(self->channel));
+       return PyLong_FromLong(channel_get_volume_midi_cc(self->channel));
 }
 
 static int
 Channel_set_volume_midi_cc(ChannelObject *self, PyObject *value, void *closure)
 {
-       unsigned int new_cc;
+       int new_cc;
        unsigned int result;
 
-       new_cc = PyInt_AsLong(value);
+       new_cc = PyLong_AsLong(value);
        result = channel_set_volume_midi_cc(self->channel, new_cc);
        if (result == 0) {
                return 0;
        }
-       if (result == 1) {
-               PyErr_SetString(PyExc_RuntimeError, "value already in use");
-       } else if (result == 2) {
+       if (result == 2) {
+               PyErr_SetString(PyExc_RuntimeError, "value out of range");
+       }
+       return -1;
+}
+
+static PyObject*
+Channel_get_mute_midi_cc(ChannelObject *self, void *closure)
+{
+       return PyLong_FromLong(channel_get_mute_midi_cc(self->channel));
+}
+
+static int
+Channel_set_mute_midi_cc(ChannelObject *self, PyObject *value, void *closure)
+{
+       int new_cc;
+       unsigned int result;
+
+       new_cc = PyLong_AsLong(value);
+       result = channel_set_mute_midi_cc(self->channel, new_cc);
+       if (result == 0) {
+               return 0;
+       }
+       if (result == 2) {
+               PyErr_SetString(PyExc_RuntimeError, "value out of range");
+       }
+       return -1;
+}
+
+static PyObject*
+Channel_get_solo_midi_cc(ChannelObject *self, void *closure)
+{
+       return PyLong_FromLong(channel_get_solo_midi_cc(self->channel));
+}
+
+static int
+Channel_set_solo_midi_cc(ChannelObject *self, PyObject *value, void *closure)
+{
+       int new_cc;
+       unsigned int result;
+
+       new_cc = PyLong_AsLong(value);
+       result = channel_set_solo_midi_cc(self->channel, new_cc);
+       if (result == 0) {
+               return 0;
+       }
+       if (result == 2) {
                PyErr_SetString(PyExc_RuntimeError, "value out of range");
        }
        return -1;
 }
 
+static PyObject*
+Channel_get_midi_in_got_events(ChannelObject *self, void *closure)
+{
+       PyObject *result;
+
+       if (channel_get_midi_in_got_events(self->channel)) {
+               result = Py_True;
+       } else {
+               result = Py_False;
+       }
+       Py_INCREF(result);
+       return result;
+}
+
 static PyGetSetDef Channel_getseters[] = {
-       {"is_stereo", 
+       {"is_stereo",
                (getter)Channel_get_is_stereo, NULL,
                "mono/stereo", NULL},
-       {"volume", 
+       {"volume",
                (getter)Channel_get_volume, (setter)Channel_set_volume,
                "volume", NULL},
-       {"balance", 
+       {"balance",
                (getter)Channel_get_balance, (setter)Channel_set_balance,
                "balance", NULL},
-       {"mute", 
-               (getter)Channel_get_mute, (setter)Channel_set_mute,
-               "mute", NULL},
-       {"solo", 
+       {"out_mute",
+               (getter)Channel_get_out_mute, (setter)Channel_set_out_mute,
+               "out_mute", NULL},
+       {"solo",
                (getter)Channel_get_solo, (setter)Channel_set_solo,
                "solo", NULL},
        {"meter",
                (getter)Channel_get_meter, NULL,
                "meter", NULL},
-       {"abspeak", 
+       {"kmeter",
+               (getter)Channel_get_kmeter, NULL,
+               "kmeter", NULL},
+       {"abspeak",
                (getter)Channel_get_abspeak, (setter)Channel_set_abspeak,
                "balance", NULL},
        {"midi_scale",
@@ -474,6 +560,17 @@ static PyGetSetDef Channel_getseters[] = {
                (getter)Channel_get_volume_midi_cc,
                (setter)Channel_set_volume_midi_cc,
                "Volume MIDI CC", NULL},
+       {"mute_midi_cc",
+               (getter)Channel_get_mute_midi_cc,
+               (setter)Channel_set_mute_midi_cc,
+               "Mute MIDI CC", NULL},
+       {"solo_midi_cc",
+               (getter)Channel_get_solo_midi_cc,
+               (setter)Channel_set_solo_midi_cc,
+               "Mute MIDI CC", NULL},
+       {"midi_in_got_events",
+               (getter)Channel_get_midi_in_got_events, NULL,
+               "Got new MIDI IN events", NULL},
        {NULL}
 };
 
@@ -486,15 +583,57 @@ Channel_remove(ChannelObject *self, PyObject *args)
        return Py_None;
 }
 
+static PyObject*
+Channel_autoset_volume_midi_cc(ChannelObject *self, PyObject *args)
+{
+       if (! PyArg_ParseTuple(args, "")) return NULL;
+       channel_autoset_volume_midi_cc(self->channel);
+       Py_INCREF(Py_None);
+       return Py_None;
+}
+
+static PyObject*
+Channel_autoset_balance_midi_cc(ChannelObject *self, PyObject *args)
+{
+       if (! PyArg_ParseTuple(args, "")) return NULL;
+       channel_autoset_balance_midi_cc(self->channel);
+       Py_INCREF(Py_None);
+       return Py_None;
+}
+
+static PyObject*
+Channel_autoset_mute_midi_cc(ChannelObject *self, PyObject *args)
+{
+       if (! PyArg_ParseTuple(args, "")) return NULL;
+       channel_autoset_mute_midi_cc(self->channel);
+       Py_INCREF(Py_None);
+       return Py_None;
+}
+
+static PyObject*
+Channel_autoset_solo_midi_cc(ChannelObject *self, PyObject *args)
+{
+       if (! PyArg_ParseTuple(args, "")) return NULL;
+       channel_autoset_solo_midi_cc(self->channel);
+       Py_INCREF(Py_None);
+       return Py_None;
+}
 
 static PyMethodDef channel_methods[] = {
        {"remove", (PyCFunction)Channel_remove, METH_VARARGS, "Remove"},
+       {"autoset_volume_midi_cc",
+               (PyCFunction)Channel_autoset_volume_midi_cc, METH_VARARGS, "Autoset Volume MIDI CC"},
+       {"autoset_balance_midi_cc",
+               (PyCFunction)Channel_autoset_balance_midi_cc, METH_VARARGS, "Autoset Balance MIDI CC"},
+       {"autoset_mute_midi_cc",
+               (PyCFunction)Channel_autoset_mute_midi_cc, METH_VARARGS, "Autoset Mute MIDI CC"},
+       {"autoset_solo_midi_cc",
+               (PyCFunction)Channel_autoset_solo_midi_cc, METH_VARARGS, "Autoset Solo MIDI CC"},
        {NULL}
 };
 
 static PyTypeObject ChannelType = {
-       PyObject_HEAD_INIT(NULL)
-       0,       /*ob_size*/
+       PyVarObject_HEAD_INIT(NULL, 0)
        "jack_mixer_c.Channel",    /*tp_name*/
        sizeof(ChannelObject), /*tp_basicsize*/
        0,       /*tp_itemsize*/
@@ -554,6 +693,38 @@ typedef struct {
        jack_mixer_output_channel_t *output_channel;
 } OutputChannelObject;
 
+static int
+OutputChannel_set_prefader(OutputChannelObject *self, PyObject *value, void *closure)
+{
+       if (value == Py_True) {
+               output_channel_set_prefader(self->output_channel, true);
+       } else {
+               output_channel_set_prefader(self->output_channel, false);
+       }
+       return 0;
+}
+
+static PyObject*
+OutputChannel_get_prefader(OutputChannelObject *self, void *closure)
+{
+       PyObject *result;
+
+       if (output_channel_is_prefader(self->output_channel)) {
+               result = Py_True;
+       } else {
+               result = Py_False;
+       }
+       Py_INCREF(result);
+       return result;
+}
+
+static PyGetSetDef OutputChannel_getseters[] = {
+       {"prefader",
+               (getter)OutputChannel_get_prefader, (setter)OutputChannel_set_prefader,
+               "prefader", NULL},
+       {NULL}
+};
+
 static PyObject*
 OutputChannel_remove(OutputChannelObject *self, PyObject *args)
 {
@@ -564,27 +735,123 @@ OutputChannel_remove(OutputChannelObject *self, PyObject *args)
 }
 
 static PyObject*
-OutputChannel_add_channel(OutputChannelObject *self, PyObject *args)
+OutputChannel_set_solo(OutputChannelObject *self, PyObject *args)
+{
+       PyObject *channel;
+       unsigned char solo;
+
+       if (! PyArg_ParseTuple(args, "Ob", &channel, &solo)) return NULL;
+
+       output_channel_set_solo(self->output_channel,
+                       ((ChannelObject*)channel)->channel,
+                       solo);
+
+       Py_INCREF(Py_None);
+       return Py_None;
+}
+
+static PyObject*
+OutputChannel_set_muted(OutputChannelObject *self, PyObject *args)
+{
+       PyObject *channel;
+       unsigned char muted;
+
+       if (! PyArg_ParseTuple(args, "Ob", &channel, &muted)) return NULL;
+
+       output_channel_set_muted(self->output_channel,
+                       ((ChannelObject*)channel)->channel,
+                       muted);
+
+       Py_INCREF(Py_None);
+       return Py_None;
+}
+
+static PyObject*
+OutputChannel_is_solo(OutputChannelObject *self, PyObject *args)
+{
+       PyObject *channel;
+       PyObject *result;
+
+       if (! PyArg_ParseTuple(args, "O", &channel)) return NULL;
+
+       if (output_channel_is_solo(self->output_channel,
+                       ((ChannelObject*)channel)->channel)) {
+               result = Py_True;
+       } else {
+               result = Py_False;
+       }
+
+       Py_INCREF(result);
+       return result;
+}
+
+static PyObject*
+OutputChannel_is_muted(OutputChannelObject *self, PyObject *args)
 {
        PyObject *channel;
+       PyObject *result;
 
        if (! PyArg_ParseTuple(args, "O", &channel)) return NULL;
 
-       output_channel_add_channel(self->output_channel, ((ChannelObject*)channel)->channel);
+       if (output_channel_is_muted(self->output_channel,
+                       ((ChannelObject*)channel)->channel)) {
+               result = Py_True;
+       } else {
+               result = Py_False;
+       }
+
+       Py_INCREF(result);
+       return result;
+}
+
+static PyObject*
+OutputChannel_set_in_prefader(OutputChannelObject *self, PyObject *args)
+{
+       PyObject *channel;
+       unsigned char prefader;
+
+       if (! PyArg_ParseTuple(args, "Ob", &channel, &prefader)) return NULL;
+
+       output_channel_set_in_prefader(self->output_channel,
+                       ((ChannelObject*)channel)->channel,
+                       prefader);
 
        Py_INCREF(Py_None);
        return Py_None;
 }
 
+static PyObject*
+OutputChannel_is_in_prefader(OutputChannelObject *self, PyObject *args)
+{
+       PyObject *channel;
+       PyObject *result;
+
+       if (! PyArg_ParseTuple(args, "O", &channel)) return NULL;
+
+       if (output_channel_is_in_prefader(self->output_channel,
+                       ((ChannelObject*)channel)->channel)) {
+               result = Py_True;
+       } else {
+               result = Py_False;
+       }
+
+       Py_INCREF(result);
+       return result;
+}
+
 static PyMethodDef output_channel_methods[] = {
        {"remove", (PyCFunction)OutputChannel_remove, METH_VARARGS, "Remove"},
-       {"add_channel", (PyCFunction)OutputChannel_add_channel, METH_VARARGS, "Add channel"},
+       {"set_solo", (PyCFunction)OutputChannel_set_solo, METH_VARARGS, "Set a channel as solo"},
+       {"set_muted", (PyCFunction)OutputChannel_set_muted, METH_VARARGS, "Set a channel as muted"},
+       {"is_solo", (PyCFunction)OutputChannel_is_solo, METH_VARARGS, "Is a channel set as solo"},
+       {"is_muted", (PyCFunction)OutputChannel_is_muted, METH_VARARGS, "Is a channel set as muted"},
+       {"set_in_prefader", (PyCFunction)OutputChannel_set_in_prefader, METH_VARARGS, "Set a channel as prefader"},
+       {"is_in_prefader", (PyCFunction)OutputChannel_is_in_prefader, METH_VARARGS, "Is a channel set as prefader"},
        {NULL}
 };
 
 static PyTypeObject OutputChannelType = {
-       PyObject_HEAD_INIT(NULL)
-       0,       /*ob_size*/
+       PyVarObject_HEAD_INIT(NULL, 0)
        "jack_mixer_c.OutputChannel",    /*tp_name*/
        sizeof(OutputChannelObject), /*tp_basicsize*/
        0,       /*tp_itemsize*/
@@ -613,7 +880,7 @@ static PyTypeObject OutputChannelType = {
        0,                         /* tp_iternext */
        output_channel_methods,    /* tp_methods */
        0,             /* tp_members */
-       0,           /* tp_getset */
+       OutputChannel_getseters,   /* tp_getset */
        &ChannelType,              /* tp_base */
        0,                         /* tp_dict */
        0,                         /* tp_descr_get */
@@ -630,6 +897,7 @@ OutputChannel_New(jack_mixer_output_channel_t output_channel)
        OutputChannelObject *self;
        self = (OutputChannelObject*)PyObject_NEW(OutputChannelObject, &OutputChannelType);
        if (self != NULL) {
+               self->midi_change_callback = NULL;
                self->output_channel = output_channel;
        }
        return (PyObject*)self;
@@ -640,17 +908,15 @@ OutputChannel_New(jack_mixer_output_channel_t output_channel)
 
 typedef struct {
        PyObject_HEAD
-       PyObject *main_mix_channel;
        jack_mixer_t mixer;
 } MixerObject;
 
 static void
 Mixer_dealloc(MixerObject *self)
 {
-       Py_XDECREF(self->main_mix_channel);
        if (self->mixer)
                destroy(self->mixer);
-       self->ob_type->tp_free((PyObject*)self);
+       Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject*
@@ -661,7 +927,6 @@ Mixer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
        self = (MixerObject*)type->tp_alloc(type, 0);
 
        if (self != NULL) {
-               self->main_mix_channel = NULL;
                self->mixer = NULL;
        }
 
@@ -671,45 +936,88 @@ Mixer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 static int
 Mixer_init(MixerObject *self, PyObject *args, PyObject *kwds)
 {
-       static char *kwlist[] = {"name", NULL};
+       static char *kwlist[] = {"name", "stereo", NULL};
        char *name;
+       int stereo = 1;
 
-       if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &name))
+       if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|b", kwlist, &name, &stereo))
                return -1;
-       
-       self->mixer = create(name);
+
+       self->mixer = create(name, (bool)stereo);
        if (self->mixer == NULL) {
+               PyErr_SetString(PyExc_RuntimeError,
+                               "error creating mixer, probably jack is not running");
                return -1;
        }
 
-       self->main_mix_channel = Channel_New(get_main_mix_channel(self->mixer));
-
        return 0;
 }
 
 static PyMemberDef Mixer_members[] = {
-       {"main_mix_channel", T_OBJECT, offsetof(MixerObject, main_mix_channel), 0, "main_mix_channel"},
        {NULL}
 };
 
 static PyObject*
 Mixer_get_channels_count(MixerObject *self, void *closure)
 {
-       return PyInt_FromLong(get_channels_count(self->mixer));
+       return PyLong_FromLong(get_channels_count(self->mixer));
+}
+
+static PyObject*
+Mixer_get_client_name(MixerObject *self, void *closure)
+{
+       return PyUnicode_FromString(get_client_name(self->mixer));
 }
 
 static PyObject*
 Mixer_get_last_midi_channel(MixerObject *self, void *closure)
 {
-       return PyInt_FromLong(get_last_midi_channel(self->mixer));
+       return PyLong_FromLong(get_last_midi_channel(self->mixer));
 }
 
+static int
+Mixer_set_last_midi_channel(MixerObject *self, PyObject *value, void *closure)
+{
+       int new_channel;
+       unsigned int result;
+
+       new_channel = PyLong_AsLong(value);
+       result = set_last_midi_channel(self->mixer, new_channel);
+       if (result == 0) {
+               return 0;
+       }
+       return -1;
+}
+
+static PyObject*
+Mixer_get_midi_behavior_mode(MixerObject *self, void *closure)
+{
+       return PyLong_FromLong(get_midi_behavior_mode(self->mixer));
+}
+
+static int
+Mixer_set_midi_behavior_mode(MixerObject *self, PyObject *value, void *closure)
+{
+       int mode;
+       unsigned int result;
+       
+       mode = PyLong_AsLong(value);
+       result = set_midi_behavior_mode(self->mixer, mode);
+       if (result == 0) {
+               return 0;
+       }
+       return -1;
+}
+
+
 
 static PyGetSetDef Mixer_getseters[] = {
        {"channels_count", (getter)Mixer_get_channels_count, NULL,
                "channels count", NULL},
-       {"last_midi_channel", (getter)Mixer_get_last_midi_channel, NULL,
+       {"last_midi_channel", (getter)Mixer_get_last_midi_channel, (setter)Mixer_set_last_midi_channel,
                "last midi channel", NULL},
+       {"midi_behavior_mode", (getter)Mixer_get_midi_behavior_mode, (setter)Mixer_set_midi_behavior_mode,
+               "midi behavior mode", NULL},
        {NULL}
 };
 
@@ -720,10 +1028,15 @@ Mixer_add_channel(MixerObject *self, PyObject *args)
        int stereo;
        jack_mixer_channel_t channel;
 
-       if (! PyArg_ParseTuple(args, "sb", &name, &stereo)) return NULL;
+       if (! PyArg_ParseTuple(args, "si", &name, &stereo)) return NULL;
 
        channel = add_channel(self->mixer, name, (bool)stereo);
 
+       if (channel == NULL) {
+               PyErr_SetString(PyExc_RuntimeError, "error adding channel");
+               return NULL;
+       }
+
        return Channel_New(channel);
 }
 
@@ -742,17 +1055,28 @@ Mixer_add_output_channel(MixerObject *self, PyObject *args)
        return OutputChannel_New(channel);
 }
 
+static PyObject*
+Mixer_destroy(MixerObject *self, PyObject *args)
+{
+       if (self->mixer) {
+               destroy(self->mixer);
+               self->mixer = NULL;
+       }
+       Py_INCREF(Py_None);
+       return Py_None;
+}
 
 static PyMethodDef Mixer_methods[] = {
        {"add_channel", (PyCFunction)Mixer_add_channel, METH_VARARGS, "Add a new channel"},
        {"add_output_channel", (PyCFunction)Mixer_add_output_channel, METH_VARARGS, "Add a new output channel"},
+       {"destroy", (PyCFunction)Mixer_destroy, METH_VARARGS, "Destroy JACK Mixer"},
+       {"client_name", (PyCFunction)Mixer_get_client_name, METH_VARARGS, "Get jack client name"},
 //     {"remove_channel", (PyCFunction)Mixer_remove_channel, METH_VARARGS, "Remove a channel"},
        {NULL}
 };
 
 static PyTypeObject MixerType = {
-       PyObject_HEAD_INIT(NULL)
-       0,       /*ob_size*/
+       PyVarObject_HEAD_INIT(NULL, 0)
        "jack_mixer_c.Mixer",    /*tp_name*/
        sizeof(MixerObject), /*tp_basicsize*/
        0,       /*tp_itemsize*/
@@ -794,26 +1118,38 @@ static PyTypeObject MixerType = {
 
 
 static PyMethodDef jack_mixer_methods[] = {
-       {NULL}  /* Sentinel */
+       {NULL, NULL, 0, NULL}  /* Sentinel */
 };
 
 
+static struct PyModuleDef moduledef = {
+       PyModuleDef_HEAD_INIT,
+       "jack_mixer_c",                /* m_name */
+       "Jack Mixer C Helper Module",  /* m_doc */
+       -1,                            /* m_size */
+       jack_mixer_methods,            /* m_methods */
+       NULL,                          /* m_reload */
+       NULL,                          /* m_traverse */
+       NULL,                          /* m_clear */
+       NULL,                          /* m_free */
+};
 
-PyMODINIT_FUNC initjack_mixer_c(void)
+PyMODINIT_FUNC PyInit_jack_mixer_c(void)
 {
        PyObject *m;
 
        if (PyType_Ready(&MixerType) < 0)
-               return;
+               return NULL;
        if (PyType_Ready(&ChannelType) < 0)
-               return;
+               return NULL;
        if (PyType_Ready(&OutputChannelType) < 0)
-               return;
+               return NULL;
        if (PyType_Ready(&ScaleType) < 0)
-               return;
+               return NULL;
+               
+       m = PyModule_Create(&moduledef);
+       //m = Py_InitModule3("jack_mixer_c", jack_mixer_methods, "module doc");
        
-       m = Py_InitModule3("jack_mixer_c", jack_mixer_methods, "Jack Mixer C Helper Module");
-
        Py_INCREF(&MixerType);
        PyModule_AddObject(m, "Mixer", (PyObject*)&MixerType);
        Py_INCREF(&ChannelType);
@@ -822,5 +1158,7 @@ PyMODINIT_FUNC initjack_mixer_c(void)
        PyModule_AddObject(m, "OutputChannel", (PyObject*)&OutputChannelType);
        Py_INCREF(&ScaleType);
        PyModule_AddObject(m, "Scale", (PyObject*)&ScaleType);
+       
+       return m;
 }