1 #include <Python.h>
2 #include "ttl.h"
3 #include "ttldata.h"
4 #include <list>
5 #include <map>
6 #include <iostream>
7 #include <fstream>
8 #include <jack/jack.h>
9 
10 //////////////////////////////////////////////////// PyJackClient
11 
12 struct PyJackPort;
13 
14 typedef std::map<jack_port_t *, PyJackPort *> PortHandleMap;
15 
16 struct AsyncOperationInfo
17 {
18     enum OpCode { INVALID_OP, PORT_REGISTERED, PORT_UNREGISTERED, PORTS_CONNECTED, PORTS_DISCONNECTED };
19 
20     OpCode opcode;
21     jack_port_id_t port, port2;
22 
AsyncOperationInfoAsyncOperationInfo23     AsyncOperationInfo() { opcode = INVALID_OP; }
AsyncOperationInfoAsyncOperationInfo24     AsyncOperationInfo(OpCode _opcode, jack_port_id_t _port, jack_port_id_t _port2 = 0)
25     : opcode(_opcode), port(_port), port2(_port2) {}
argcAsyncOperationInfo26     inline int argc() {
27         if (opcode == PORT_REGISTERED || opcode == PORT_UNREGISTERED) return 1;
28         if (opcode == PORTS_CONNECTED || opcode == PORTS_DISCONNECTED) return 2;
29         return 0;
30     }
31 };
32 
33 typedef std::list<AsyncOperationInfo> PortOperationList;
34 
35 struct PyJackClient
36 {
37     PyObject_HEAD
38     jack_client_t *client;
39     PortHandleMap *port_handle_map;
40     pthread_mutex_t port_op_mutex;
41     PortOperationList *port_op_queue;
42 };
43 
44 static PyTypeObject jackclient_type = {
45     PyObject_HEAD_INIT(NULL)
46     0,                         /*ob_size*/
47     "calfpytools.JackClient",  /*tp_name*/
48     sizeof(PyJackClient),      /*tp_basicsize*/
49 };
50 
51 struct PyJackPort
52 {
53     PyObject_HEAD
54     PyJackClient *client;
55     jack_port_t *port;
56 };
57 
58 static PyTypeObject jackport_type = {
59     PyObject_HEAD_INIT(NULL)
60     0,                         /*ob_size*/
61     "calfpytools.JackPort",  /*tp_name*/
62     sizeof(PyJackPort),      /*tp_basicsize*/
63 };
64 
register_cb(jack_port_id_t port,int registered,void * arg)65 static void register_cb(jack_port_id_t port, int registered, void *arg)
66 {
67     PyJackClient *self = (PyJackClient *)arg;
68     pthread_mutex_lock(&self->port_op_mutex);
69     self->port_op_queue->push_back(AsyncOperationInfo(registered ? AsyncOperationInfo::PORT_REGISTERED : AsyncOperationInfo::PORT_UNREGISTERED, port));
70     pthread_mutex_unlock(&self->port_op_mutex);
71 }
72 
connect_cb(jack_port_id_t port1,jack_port_id_t port2,int connected,void * arg)73 static void connect_cb(jack_port_id_t port1, jack_port_id_t port2, int connected, void *arg)
74 {
75     PyJackClient *self = (PyJackClient *)arg;
76     pthread_mutex_lock(&self->port_op_mutex);
77     self->port_op_queue->push_back(AsyncOperationInfo(connected ? AsyncOperationInfo::PORTS_CONNECTED : AsyncOperationInfo::PORTS_DISCONNECTED, port1, port2));
78     pthread_mutex_unlock(&self->port_op_mutex);
79 }
80 
jackclient_open(PyJackClient * self,PyObject * args)81 static PyObject *jackclient_open(PyJackClient *self, PyObject *args)
82 {
83     const char *name;
84     int options = 0;
85     jack_status_t status = (jack_status_t)0;
86 
87     if (!PyArg_ParseTuple(args, "s|i:open", &name, &options))
88         return NULL;
89 
90     self->client = jack_client_open(name, (jack_options_t)options, &status);
91     self->port_handle_map = new PortHandleMap;
92     pthread_mutexattr_t attr;
93     pthread_mutexattr_init(&attr);
94     pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
95     pthread_mutex_init(&self->port_op_mutex, &attr);
96     self->port_op_queue = new PortOperationList;
97 
98     jack_set_port_registration_callback(self->client, register_cb, self);
99     jack_set_port_connect_callback(self->client, connect_cb, self);
100     jack_activate(self->client);
101 
102     return Py_BuildValue("i", status);
103 }
104 
jackclient_dealloc(PyJackPort * self)105 static int jackclient_dealloc(PyJackPort *self)
106 {
107     if (self->client)
108     {
109         PyObject_CallMethod((PyObject *)self, strdup("close"), NULL);
110         assert(!self->client);
111     }
112 
113     return 0;
114 }
115 
116 #define CHECK_CLIENT if (!self->client) { PyErr_SetString(PyExc_ValueError, "Client not opened"); return NULL; }
117 
118 
jackclient_get_name(PyJackClient * self,PyObject * args)119 static PyObject *jackclient_get_name(PyJackClient *self, PyObject *args)
120 {
121     if (!PyArg_ParseTuple(args, ":get_name"))
122         return NULL;
123 
124     CHECK_CLIENT
125 
126     return Py_BuildValue("s", jack_get_client_name(self->client));
127 }
128 
create_jack_port(PyJackClient * client,jack_port_t * port)129 static PyObject *create_jack_port(PyJackClient *client, jack_port_t *port)
130 {
131     PortHandleMap::iterator it = client->port_handle_map->find(port);
132     if (it != client->port_handle_map->end())
133     {
134         Py_INCREF(it->second);
135         return Py_BuildValue("O", it->second);
136     }
137     if (port)
138     {
139         PyObject *cobj = PyCObject_FromVoidPtr(port, NULL);
140         PyObject *args = Py_BuildValue("OO", client, cobj);
141         PyObject *newobj = _PyObject_New(&jackport_type);
142         jackport_type.tp_init(newobj, args, NULL);
143         (*client->port_handle_map)[port] = (PyJackPort *)newobj;
144         Py_DECREF(args);
145         return newobj;
146     }
147     Py_INCREF(Py_None);
148     return Py_None;
149 }
150 
jackclient_register_port(PyJackClient * self,PyObject * args)151 static PyObject *jackclient_register_port(PyJackClient *self, PyObject *args)
152 {
153     const char *name, *type = JACK_DEFAULT_AUDIO_TYPE;
154     unsigned long flags = 0, buffer_size = 0;
155     if (!PyArg_ParseTuple(args, "s|sii:register_port", &name, &type, &flags, &buffer_size))
156         return NULL;
157 
158     CHECK_CLIENT
159 
160     jack_port_t *port = jack_port_register(self->client, name, type, flags, buffer_size);
161     return create_jack_port(self, port);
162 }
163 
jackclient_get_port(PyJackClient * self,PyObject * args)164 static PyObject *jackclient_get_port(PyJackClient *self, PyObject *args)
165 {
166     const char *name;
167     if (!PyArg_ParseTuple(args, "s:get_port", &name))
168         return NULL;
169 
170     CHECK_CLIENT
171 
172     jack_port_t *port = jack_port_by_name(self->client, name);
173     return create_jack_port(self, port);
174 }
175 
jackclient_get_cobj(PyJackClient * self,PyObject * args)176 static PyObject *jackclient_get_cobj(PyJackClient *self, PyObject *args)
177 {
178     if (!PyArg_ParseTuple(args, ":get_cobj"))
179         return NULL;
180 
181     CHECK_CLIENT
182 
183     return PyCObject_FromVoidPtr((void *)self->client, NULL);
184 }
185 
jackclient_get_ports(PyJackClient * self,PyObject * args)186 static PyObject *jackclient_get_ports(PyJackClient *self, PyObject *args)
187 {
188     const char *name = NULL, *type = NULL;
189     unsigned long flags = 0;
190     if (!PyArg_ParseTuple(args, "|ssi:get_ports", &name, &type, &flags))
191         return NULL;
192 
193     CHECK_CLIENT
194 
195     const char **p = jack_get_ports(self->client, name, type, flags);
196     PyObject *res = PyList_New(0);
197     if (!p)
198         return res;
199 
200     for (const char **q = p; *q; q++)
201     {
202         PyList_Append(res, PyString_FromString(*q));
203         // free(q);
204     }
205     free(p);
206 
207     return res;
208 }
209 
jackclient_connect(PyJackClient * self,PyObject * args)210 static PyObject *jackclient_connect(PyJackClient *self, PyObject *args)
211 {
212     char *from_port = NULL, *to_port = NULL;
213     if (!PyArg_ParseTuple(args, "ss:connect", &from_port, &to_port))
214         return NULL;
215 
216     CHECK_CLIENT
217 
218     int result = jack_connect(self->client, from_port, to_port);
219 
220     switch(result)
221     {
222         case 0:
223             Py_INCREF(Py_True);
224             return Py_True;
225         case EEXIST:
226             Py_INCREF(Py_False);
227             return Py_False;
228         default:
229             PyErr_SetString(PyExc_RuntimeError, "Connection error");
230             return NULL;
231     }
232 }
233 
create_jack_port_by_id(PyJackClient * self,jack_port_id_t id)234 static PyObject *create_jack_port_by_id(PyJackClient *self, jack_port_id_t id)
235 {
236     return create_jack_port(self, jack_port_by_id(self->client, id));
237 }
238 
jackclient_get_message(PyJackClient * self,PyObject * args)239 static PyObject *jackclient_get_message(PyJackClient *self, PyObject *args)
240 {
241     if (!PyArg_ParseTuple(args, ":get_message"))
242         return NULL;
243 
244     CHECK_CLIENT
245 
246     PyObject *obj = NULL;
247     AsyncOperationInfo info;
248     pthread_mutex_lock(&self->port_op_mutex);
249     if (self->port_op_queue->empty())
250     {
251         obj = Py_None;
252         Py_INCREF(Py_None);
253     }
254     else
255     {
256         info = self->port_op_queue->front();
257         self->port_op_queue->pop_front();
258     }
259     pthread_mutex_unlock(&self->port_op_mutex);
260     if (!obj)
261     {
262         if (info.argc() == 1)
263             obj = Py_BuildValue("iO", info.opcode, create_jack_port_by_id(self, info.port));
264         else
265         if (info.argc() == 2)
266             obj = Py_BuildValue("iOO", info.opcode, create_jack_port_by_id(self, info.port), create_jack_port_by_id(self, info.port2));
267     }
268     return obj;
269 }
270 
jackclient_disconnect(PyJackClient * self,PyObject * args)271 static PyObject *jackclient_disconnect(PyJackClient *self, PyObject *args)
272 {
273     char *from_port = NULL, *to_port = NULL;
274     if (!PyArg_ParseTuple(args, "ss:disconnect", &from_port, &to_port))
275         return NULL;
276 
277     CHECK_CLIENT
278 
279     int result = jack_disconnect(self->client, from_port, to_port);
280 
281     switch(result)
282     {
283         case 0:
284             Py_INCREF(Py_None);
285             return Py_None;
286         default:
287             PyErr_SetString(PyExc_RuntimeError, "Disconnection error");
288             return NULL;
289     }
290 }
291 
jackclient_close(PyJackClient * self,PyObject * args)292 static PyObject *jackclient_close(PyJackClient *self, PyObject *args)
293 {
294     if (!PyArg_ParseTuple(args, ":close"))
295         return NULL;
296 
297     CHECK_CLIENT
298 
299     jack_deactivate(self->client);
300     jack_client_close(self->client);
301     self->client = NULL;
302     delete self->port_handle_map;
303     delete self->port_op_queue;
304     pthread_mutex_destroy(&self->port_op_mutex);
305 
306     Py_INCREF(Py_None);
307     return Py_None;
308 }
309 
310 static PyMethodDef jackclient_methods[] = {
311     {"open", (PyCFunction)jackclient_open, METH_VARARGS, "Open a client"},
312     {"close", (PyCFunction)jackclient_close, METH_VARARGS, "Close a client"},
313     {"get_name", (PyCFunction)jackclient_get_name, METH_VARARGS, "Retrieve client name"},
314     {"get_port", (PyCFunction)jackclient_get_port, METH_VARARGS, "Create port object from name of existing JACK port"},
315     {"get_ports", (PyCFunction)jackclient_get_ports, METH_VARARGS, "Get a list of port names based on specified name, type and flag filters"},
316     {"register_port", (PyCFunction)jackclient_register_port, METH_VARARGS, "Register a new port and return an object that represents it"},
317     {"get_cobj", (PyCFunction)jackclient_get_cobj, METH_VARARGS, "Retrieve jack_client_t pointer for the client as CObject"},
318     {"get_message", (PyCFunction)jackclient_get_message, METH_VARARGS, "Retrieve next port registration/connection message from the message queue"},
319     {"connect", (PyCFunction)jackclient_connect, METH_VARARGS, "Connect two ports with given names"},
320     {"disconnect", (PyCFunction)jackclient_disconnect, METH_VARARGS, "Disconnect two ports with given names"},
321     {NULL, NULL, 0, NULL}
322 };
323 
324 //////////////////////////////////////////////////// PyJackPort
325 
jackport_init(PyJackPort * self,PyObject * args,PyObject * kwds)326 static int jackport_init(PyJackPort *self, PyObject *args, PyObject *kwds)
327 {
328     PyJackClient *client = NULL;
329     PyObject *cobj = NULL;
330 
331     if (!PyArg_ParseTuple(args, "O!O:__init__", &jackclient_type, &client, &cobj))
332         return 0;
333     if (!PyCObject_Check(cobj))
334     {
335         PyErr_SetString(PyExc_TypeError, "Port constructor cannot be called explicitly");
336         return 0;
337     }
338     Py_INCREF(client);
339 
340     self->client = client;
341     self->port = (jack_port_t *)PyCObject_AsVoidPtr(cobj);
342 
343     return 0;
344 }
345 
jackport_dealloc(PyJackPort * self)346 static int jackport_dealloc(PyJackPort *self)
347 {
348     // if not unregistered, decref (unregister decrefs automatically)
349     if (self->client) {
350         self->client->port_handle_map->erase(self->port);
351         Py_DECREF(self->client);
352     }
353 
354     return 0;
355 }
356 
357 #define CHECK_PORT_CLIENT if (!self->client || !self->client->client) { PyErr_SetString(PyExc_ValueError, "Client not opened"); return NULL; }
358 #define CHECK_PORT if (!self->port) { PyErr_SetString(PyExc_ValueError, "The port is not valid"); return NULL; }
359 
jackport_strrepr(PyJackPort * self,int quotes)360 static PyObject *jackport_strrepr(PyJackPort *self, int quotes)
361 {
362     CHECK_PORT_CLIENT
363     CHECK_PORT
364 
365     int flags = jack_port_flags(self->port);
366     int flags_io = flags & (JackPortIsInput | JackPortIsOutput);
367     return PyString_FromFormat("<calfpytools.JackPort, name=%s%s%s, flags=%s%s%s%s>",
368         quotes ? "\"" : "",
369         jack_port_name(self->port),
370         quotes ? "\"" : "",
371         (flags_io == JackPortIsInput) ? "in" : (flags_io == JackPortIsOutput ? "out" : "?"),
372         flags & JackPortIsPhysical ? "|physical" : "",
373         flags & JackPortCanMonitor ? "|can_monitor" : "",
374         flags & JackPortIsTerminal ? "|terminal" : "");
375 }
376 
jackport_str(PyJackPort * self)377 static PyObject *jackport_str(PyJackPort *self)
378 {
379     return jackport_strrepr(self, 0);
380 }
381 
jackport_repr(PyJackPort * self)382 static PyObject *jackport_repr(PyJackPort *self)
383 {
384     return jackport_strrepr(self, 1);
385 }
386 
jackport_get_full_name(PyJackPort * self,PyObject * args)387 static PyObject *jackport_get_full_name(PyJackPort *self, PyObject *args)
388 {
389     if (!PyArg_ParseTuple(args, ":get_full_name"))
390         return NULL;
391 
392     CHECK_PORT_CLIENT
393     CHECK_PORT
394 
395     return Py_BuildValue("s", jack_port_name(self->port));
396 }
397 
jackport_get_flags(PyJackPort * self,PyObject * args)398 static PyObject *jackport_get_flags(PyJackPort *self, PyObject *args)
399 {
400     if (!PyArg_ParseTuple(args, ":get_flags"))
401         return NULL;
402 
403     CHECK_PORT_CLIENT
404     CHECK_PORT
405 
406     return PyInt_FromLong(jack_port_flags(self->port));
407 }
408 
jackport_is_valid(PyJackPort * self,PyObject * args)409 static PyObject *jackport_is_valid(PyJackPort *self, PyObject *args)
410 {
411     if (!PyArg_ParseTuple(args, ":is_valid"))
412         return NULL;
413 
414     return PyBool_FromLong(self->client && self->client->client && self->port);
415 }
416 
jackport_is_mine(PyJackPort * self,PyObject * args)417 static PyObject *jackport_is_mine(PyJackPort *self, PyObject *args)
418 {
419     if (!PyArg_ParseTuple(args, ":is_mine"))
420         return NULL;
421 
422     CHECK_PORT_CLIENT
423     CHECK_PORT
424 
425     return PyBool_FromLong(self->client && self->client->client && self->port && jack_port_is_mine(self->client->client, self->port));
426 }
427 
jackport_get_name(PyJackPort * self,PyObject * args)428 static PyObject *jackport_get_name(PyJackPort *self, PyObject *args)
429 {
430     if (!PyArg_ParseTuple(args, ":get_name"))
431         return NULL;
432 
433     CHECK_PORT_CLIENT
434     CHECK_PORT
435 
436     return Py_BuildValue("s", jack_port_short_name(self->port));
437 }
438 
jackport_get_type(PyJackPort * self,PyObject * args)439 static PyObject *jackport_get_type(PyJackPort *self, PyObject *args)
440 {
441     if (!PyArg_ParseTuple(args, ":get_type"))
442         return NULL;
443 
444     CHECK_PORT_CLIENT
445     CHECK_PORT
446 
447     return Py_BuildValue("s", jack_port_type(self->port));
448 }
449 
jackport_get_cobj(PyJackPort * self,PyObject * args)450 static PyObject *jackport_get_cobj(PyJackPort *self, PyObject *args)
451 {
452     if (!PyArg_ParseTuple(args, ":get_cobj"))
453         return NULL;
454 
455     CHECK_PORT_CLIENT
456     CHECK_PORT
457 
458     return PyCObject_FromVoidPtr((void *)self->port, NULL);
459 }
460 
jackport_get_aliases(PyJackPort * self,PyObject * args)461 static PyObject *jackport_get_aliases(PyJackPort *self, PyObject *args)
462 {
463     if (!PyArg_ParseTuple(args, ":get_aliases"))
464         return NULL;
465 
466     CHECK_PORT_CLIENT
467     CHECK_PORT
468 
469     char buf1[256], buf2[256];
470     char *const aliases[2] = { buf1, buf2 };
471     int count = jack_port_get_aliases(self->port, aliases);
472 
473     PyObject *alist = PyList_New(0);
474     for (int i = 0; i < count; i++)
475         PyList_Append(alist, PyString_FromString(aliases[i]));
476     return alist;
477 }
478 
jackport_get_connections(PyJackPort * self,PyObject * args)479 static PyObject *jackport_get_connections(PyJackPort *self, PyObject *args)
480 {
481     if (!PyArg_ParseTuple(args, ":get_aliases"))
482         return NULL;
483 
484     CHECK_PORT_CLIENT
485     CHECK_PORT
486 
487     const char **conns = jack_port_get_all_connections(self->client->client, self->port);
488 
489     PyObject *res = PyList_New(0);
490     if (conns)
491     {
492         for (const char **p = conns; *p; p++)
493             PyList_Append(res, PyString_FromString(*p));
494     }
495 
496     return res;
497 }
498 
jackport_set_name(PyJackPort * self,PyObject * args)499 static PyObject *jackport_set_name(PyJackPort *self, PyObject *args)
500 {
501     const char *name;
502     if (!PyArg_ParseTuple(args, "s:set_name", &name))
503         return NULL;
504 
505     CHECK_PORT
506 
507     jack_port_set_name(self->port, name);
508 
509     return Py_BuildValue("s", jack_port_short_name(self->port));
510 }
511 
jackport_unregister(PyJackPort * self,PyObject * args)512 static PyObject *jackport_unregister(PyJackPort *self, PyObject *args)
513 {
514     if (!PyArg_ParseTuple(args, ":unregister"))
515         return NULL;
516 
517     CHECK_PORT
518 
519     PyJackClient *client = self->client;
520 
521     client->port_handle_map->erase(self->port);
522     jack_port_unregister(self->client->client, self->port);
523     self->port = NULL;
524     self->client = NULL;
525 
526     Py_DECREF(client);
527     client = NULL;
528     Py_INCREF(Py_None);
529     return Py_None;
530 }
531 
532 static PyMethodDef jackport_methods[] = {
533     {"unregister", (PyCFunction)jackport_unregister, METH_VARARGS, "Unregister a port"},
534     {"is_valid", (PyCFunction)jackport_is_valid, METH_VARARGS, "Checks if the port object is valid (registered)"},
535     {"is_mine", (PyCFunction)jackport_is_mine, METH_VARARGS, "Checks if the port object is valid (registered)"},
536     {"get_full_name", (PyCFunction)jackport_get_full_name, METH_VARARGS, "Retrieve full port name (including client name)"},
537     {"get_name", (PyCFunction)jackport_get_name, METH_VARARGS, "Retrieve short port name (without client name)"},
538     {"get_type", (PyCFunction)jackport_get_type, METH_VARARGS, "Retrieve port type name"},
539     {"get_flags", (PyCFunction)jackport_get_flags, METH_VARARGS, "Retrieve port flags (defined in module, ie. calfpytools.JackPortIsInput)"},
540     {"set_name", (PyCFunction)jackport_set_name, METH_VARARGS, "Set short port name"},
541     {"get_aliases", (PyCFunction)jackport_get_aliases, METH_VARARGS, "Retrieve a list of port aliases"},
542     {"get_connections", (PyCFunction)jackport_get_connections, METH_VARARGS, "Retrieve a list of ports the port is connected to"},
543     {"get_cobj", (PyCFunction)jackport_get_cobj, METH_VARARGS, "Retrieve jack_port_t pointer for the port"},
544     {NULL, NULL, 0, NULL}
545 };
546 
547 
548 //////////////////////////////////////////////////// calfpytools
549 
calfpytools_scan_ttl_file(PyObject * self,PyObject * args)550 static PyObject *calfpytools_scan_ttl_file(PyObject *self, PyObject *args)
551 {
552     char *ttl_name = NULL;
553     if (!PyArg_ParseTuple(args, "s:scan_ttl_file", &ttl_name))
554         return NULL;
555 
556     std::ifstream istr(ttl_name, std::ifstream::in);
557     TTLLexer lexer(&istr);
558     lexer.yylex();
559     return lexer.grab();
560 }
561 
calfpytools_scan_ttl_string(PyObject * self,PyObject * args)562 static PyObject *calfpytools_scan_ttl_string(PyObject *self, PyObject *args)
563 {
564     char *data = NULL;
565     if (!PyArg_ParseTuple(args, "s:scan_ttl_string", &data))
566         return NULL;
567 
568     std::string data_str = data;
569     std::stringstream str(data_str);
570     TTLLexer lexer(&str);
571     lexer.yylex();
572     return lexer.grab();
573 }
574 
575 static PyMethodDef module_methods[] = {
576     {"scan_ttl_file", calfpytools_scan_ttl_file, METH_VARARGS, "Scan a TTL file, return a list of token tuples"},
577     {"scan_ttl_string", calfpytools_scan_ttl_string, METH_VARARGS, "Scan a TTL string, return a list of token tuples"},
578     {NULL, NULL, 0, NULL}
579 };
580 
initcalfpytools()581 PyMODINIT_FUNC initcalfpytools()
582 {
583     jackclient_type.tp_new = PyType_GenericNew;
584     jackclient_type.tp_flags = Py_TPFLAGS_DEFAULT;
585     jackclient_type.tp_doc = "JACK client object";
586     jackclient_type.tp_methods = jackclient_methods;
587     jackclient_type.tp_dealloc = (destructor)jackclient_dealloc;
588     if (PyType_Ready(&jackclient_type) < 0)
589         return;
590 
591     jackport_type.tp_new = PyType_GenericNew;
592     jackport_type.tp_flags = Py_TPFLAGS_DEFAULT;
593     jackport_type.tp_doc = "JACK port object (created by client)";
594     jackport_type.tp_methods = jackport_methods;
595     jackport_type.tp_init = (initproc)jackport_init;
596     jackport_type.tp_dealloc = (destructor)jackport_dealloc;
597     jackport_type.tp_str = (reprfunc)jackport_str;
598     jackport_type.tp_repr = (reprfunc)jackport_repr;
599     if (PyType_Ready(&jackport_type) < 0)
600         return;
601 
602     PyObject *mod = Py_InitModule3("calfpytools", module_methods, "Python utilities for Calf");
603     Py_INCREF(&jackclient_type);
604     Py_INCREF(&jackport_type);
605     PyModule_AddObject(mod, "JackClient", (PyObject *)&jackclient_type);
606     PyModule_AddObject(mod, "JackPort", (PyObject *)&jackport_type);
607 
608     PyModule_AddObject(mod, "JackPortIsInput", PyInt_FromLong(JackPortIsInput));
609     PyModule_AddObject(mod, "JackPortIsOutput", PyInt_FromLong(JackPortIsOutput));
610     PyModule_AddObject(mod, "JackPortIsPhysical", PyInt_FromLong(JackPortIsPhysical));
611     PyModule_AddObject(mod, "JackPortCanMonitor", PyInt_FromLong(JackPortCanMonitor));
612     PyModule_AddObject(mod, "JackPortIsTerminal", PyInt_FromLong(JackPortIsTerminal));
613     PyModule_AddObject(mod, "JACK_DEFAULT_AUDIO_TYPE", PyString_FromString(JACK_DEFAULT_AUDIO_TYPE));
614     PyModule_AddObject(mod, "JACK_DEFAULT_MIDI_TYPE", PyString_FromString(JACK_DEFAULT_MIDI_TYPE));
615 }
616