jack.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  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_get_ports(Client* self)
  82. {
  83. PyObject* ports = PyList_New(0);
  84. if(!ports) {
  85. return NULL;
  86. }
  87. const char** port_names = jack_get_ports(self->client, NULL, NULL, 0);
  88. int port_index;
  89. for(port_index = 0; port_names[port_index] != NULL; port_index++) {
  90. Port* port = PyObject_New(Port, &port_type);
  91. port->port = jack_port_by_name(self->client, port_names[port_index]);
  92. if(PyList_Append(ports, (PyObject*)port)) {
  93. return NULL;
  94. }
  95. }
  96. jack_free(port_names);
  97. return ports;
  98. }
  99. static PyObject* client_set_port_registration_callback(Client* self, PyObject* args)
  100. {
  101. PyObject* callback;
  102. if(!PyArg_ParseTuple(args, "O", &callback)) {
  103. return NULL;
  104. }
  105. if(!PyCallable_Check(callback)) {
  106. PyErr_SetString(PyExc_TypeError, "Parameter must be callable.");
  107. return NULL;
  108. }
  109. Py_XINCREF(callback);
  110. Py_XDECREF(self->registration_callback);
  111. self->registration_callback = callback;
  112. Py_INCREF(Py_None);
  113. return Py_None;
  114. }
  115. static void client_dealloc(Client* self)
  116. {
  117. jack_client_close(self->client);
  118. self->ob_type->tp_free((PyObject*)self);
  119. }
  120. static PyMethodDef client_methods[] = {
  121. {
  122. "activate",
  123. (PyCFunction)client_activate,
  124. METH_NOARGS,
  125. "Tell the Jack server that the program is ready to start processing audio.",
  126. },
  127. {
  128. "get_name",
  129. (PyCFunction)client_get_name,
  130. METH_NOARGS,
  131. "Return client's actual name.",
  132. },
  133. {
  134. "get_ports",
  135. (PyCFunction)client_get_ports,
  136. METH_NOARGS,
  137. "Return list of ports.",
  138. },
  139. {
  140. "set_port_registration_callback",
  141. (PyCFunction)client_set_port_registration_callback,
  142. METH_VARARGS,
  143. "Tell the JACK server to call a function whenever a port is registered or unregistered.",
  144. },
  145. {NULL},
  146. };
  147. static PyObject* port_get_name(Port* self)
  148. {
  149. return (PyObject*)PyString_FromString(jack_port_name(self->port));
  150. }
  151. static PyObject* port___repr__(Port* self)
  152. {
  153. static PyObject* format;
  154. if(!format) {
  155. format = PyString_FromString("jack.Port(name = '%s')");
  156. }
  157. PyObject* name = PyString_FromString(jack_port_name(self->port));
  158. PyObject* repr = PyString_Format(format, name);
  159. Py_DECREF(name);
  160. return repr;
  161. }
  162. static PyMethodDef port_methods[] = {
  163. {
  164. "get_name",
  165. (PyCFunction)port_get_name,
  166. METH_NOARGS,
  167. "Return port's name.",
  168. },
  169. {NULL},
  170. };
  171. PyMODINIT_FUNC initjack()
  172. {
  173. // Initialize and acquire the global interpreter lock.
  174. // This must be done in the main thread before creating engaging in any thread operations.
  175. PyEval_InitThreads();
  176. PyObject* module = Py_InitModule("jack", NULL);
  177. if(!module) {
  178. return;
  179. }
  180. error = PyErr_NewException((char*)"jack.Error", NULL, NULL);
  181. Py_INCREF(error);
  182. PyModule_AddObject(module, "Error", error);
  183. failure = PyErr_NewException((char*)"jack.Failure", error, NULL);
  184. Py_INCREF(failure);
  185. PyModule_AddObject(module, "Failure", failure);
  186. static PyTypeObject client_type = {
  187. PyObject_HEAD_INIT(NULL)
  188. };
  189. client_type.tp_name = "jack.Client";
  190. client_type.tp_basicsize = sizeof(Client);
  191. client_type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
  192. client_type.tp_new = client___new__;
  193. client_type.tp_dealloc = (destructor)client_dealloc;
  194. client_type.tp_methods = client_methods;
  195. if(PyType_Ready(&client_type) < 0) {
  196. return;
  197. }
  198. Py_INCREF(&client_type);
  199. PyModule_AddObject(module, "Client", (PyObject*)&client_type);
  200. port_type.tp_name = "jack.Port";
  201. port_type.tp_basicsize = sizeof(Port);
  202. port_type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
  203. // Forbid direct instantiation.
  204. port_type.tp_new = NULL;
  205. port_type.tp_repr = (reprfunc)port___repr__;
  206. port_type.tp_methods = port_methods;
  207. if(PyType_Ready(&port_type) < 0) {
  208. return;
  209. }
  210. Py_INCREF(&port_type);
  211. PyModule_AddObject(module, "Port", (PyObject*)&port_type);
  212. }