jack.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. #include <python2.7/Python.h>
  2. #include <jack/jack.h>
  3. typedef struct {
  4. PyObject_HEAD
  5. jack_client_t* client;
  6. PyObject* registration_callback;
  7. } Client;
  8. typedef struct {
  9. PyObject_HEAD
  10. jack_port_t* port;
  11. } Port;
  12. static PyObject* error;
  13. static PyObject* failure;
  14. static PyTypeObject port_type = {
  15. PyObject_HEAD_INIT(NULL)
  16. };
  17. static void jack_registration_callback(jack_port_id_t port_id, int registered, void* arg)
  18. {
  19. // register: non-zero if the port is being registered, zero if the port is being unregistered
  20. Client* client = (Client*)arg;
  21. if(client->registration_callback) {
  22. // Ensure that the current thread is ready to call the Python API.
  23. PyGILState_STATE gil_state = PyGILState_Ensure();
  24. Port* port = PyObject_New(Port, &port_type);
  25. port->port = jack_port_by_id(client->client, port_id);
  26. PyObject* callback_argument_list = Py_BuildValue("(O,i)", (PyObject*)port, registered);
  27. PyObject* result = PyObject_CallObject(client->registration_callback, callback_argument_list);
  28. Py_DECREF(callback_argument_list);
  29. if(!result) {
  30. PyErr_PrintEx(0);
  31. } else {
  32. Py_DECREF(result);
  33. }
  34. // Release the thread. No Python API calls are allowed beyond this point.
  35. PyGILState_Release(gil_state);
  36. }
  37. }
  38. static PyObject* client___new__(PyTypeObject* type, PyObject* args, PyObject* kwargs)
  39. {
  40. Client* self = (Client*)type->tp_alloc(type, 0);
  41. if(self) {
  42. const char* name;
  43. if(!PyArg_ParseTuple(args, "s", &name)) {
  44. return NULL;
  45. }
  46. jack_status_t status;
  47. self->client = jack_client_open(name, JackNullOption, &status);
  48. if(!self->client) {
  49. if(status & JackFailure) {
  50. PyErr_SetString(failure, "Overall operation failed.");
  51. }
  52. return NULL;
  53. }
  54. self->registration_callback = NULL;
  55. int error_code = jack_set_port_registration_callback(
  56. self->client,
  57. jack_registration_callback,
  58. (void*)self
  59. );
  60. if(error_code) {
  61. PyErr_SetString(error, "Could not set port registration callback.");
  62. return NULL;
  63. }
  64. }
  65. return (PyObject*)self;
  66. }
  67. static PyObject* client_activate(Client* self) {
  68. int error_code = jack_activate(self->client);
  69. if(error_code) {
  70. PyErr_SetString(error, "");
  71. return NULL;
  72. } else {
  73. Py_INCREF(Py_None);
  74. return Py_None;
  75. }
  76. }
  77. static PyObject* client_get_name(Client* self)
  78. {
  79. return (PyObject*)PyString_FromString(jack_get_client_name(self->client));
  80. }
  81. static PyObject* client_set_port_registration_callback(Client* self, PyObject* args)
  82. {
  83. PyObject* callback;
  84. if(!PyArg_ParseTuple(args, "O", &callback)) {
  85. return NULL;
  86. }
  87. if(!PyCallable_Check(callback)) {
  88. PyErr_SetString(PyExc_TypeError, "Parameter must be callable.");
  89. return NULL;
  90. }
  91. Py_XINCREF(callback);
  92. Py_XDECREF(self->registration_callback);
  93. self->registration_callback = callback;
  94. Py_INCREF(Py_None);
  95. return Py_None;
  96. }
  97. static void client_dealloc(Client* self)
  98. {
  99. jack_client_close(self->client);
  100. self->ob_type->tp_free((PyObject*)self);
  101. }
  102. static PyMethodDef client_methods[] = {
  103. {
  104. "activate",
  105. (PyCFunction)client_activate,
  106. METH_NOARGS,
  107. "Tell the Jack server that the program is ready to start processing audio.",
  108. },
  109. {
  110. "get_name",
  111. (PyCFunction)client_get_name,
  112. METH_NOARGS,
  113. "Return client's actual name.",
  114. },
  115. {
  116. "set_port_registration_callback",
  117. (PyCFunction)client_set_port_registration_callback,
  118. METH_VARARGS,
  119. "Tell the JACK server to call a function whenever a port is registered or unregistered.",
  120. },
  121. {NULL},
  122. };
  123. static PyObject* port_get_name(Port* self)
  124. {
  125. return (PyObject*)PyString_FromString(jack_port_name(self->port));
  126. }
  127. static PyObject* port___repr__(Port* self)
  128. {
  129. static PyObject* format;
  130. if(!format) {
  131. format = PyString_FromString("jack.Port(name = '%s')");
  132. }
  133. PyObject* name = PyString_FromString(jack_port_name(self->port));
  134. PyObject* repr = PyString_Format(format, name);
  135. Py_DECREF(name);
  136. return repr;
  137. }
  138. static PyMethodDef port_methods[] = {
  139. {
  140. "get_name",
  141. (PyCFunction)port_get_name,
  142. METH_NOARGS,
  143. "Return port's name.",
  144. },
  145. {NULL},
  146. };
  147. PyMODINIT_FUNC initjack()
  148. {
  149. // Initialize and acquire the global interpreter lock.
  150. // This must be done in the main thread before creating engaging in any thread operations.
  151. PyEval_InitThreads();
  152. PyObject* module = Py_InitModule("jack", NULL);
  153. if(!module) {
  154. return;
  155. }
  156. error = PyErr_NewException((char*)"jack.Error", NULL, NULL);
  157. Py_INCREF(error);
  158. PyModule_AddObject(module, "Error", error);
  159. failure = PyErr_NewException((char*)"jack.Failure", error, NULL);
  160. Py_INCREF(failure);
  161. PyModule_AddObject(module, "Failure", failure);
  162. static PyTypeObject client_type = {
  163. PyObject_HEAD_INIT(NULL)
  164. };
  165. client_type.tp_name = "jack.Client";
  166. client_type.tp_basicsize = sizeof(Client);
  167. client_type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
  168. client_type.tp_new = client___new__;
  169. client_type.tp_dealloc = (destructor)client_dealloc;
  170. client_type.tp_methods = client_methods;
  171. if(PyType_Ready(&client_type) < 0) {
  172. return;
  173. }
  174. Py_INCREF(&client_type);
  175. PyModule_AddObject(module, "Client", (PyObject*)&client_type);
  176. port_type.tp_name = "jack.Port";
  177. port_type.tp_basicsize = sizeof(Port);
  178. port_type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
  179. // Forbid direct instantiation.
  180. port_type.tp_new = NULL;
  181. port_type.tp_repr = (reprfunc)port___repr__;
  182. port_type.tp_methods = port_methods;
  183. if(PyType_Ready(&port_type) < 0) {
  184. return;
  185. }
  186. Py_INCREF(&port_type);
  187. PyModule_AddObject(module, "Port", (PyObject*)&port_type);
  188. }