jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

337 lines
8.1KB

  1. /* -*- Mode: C ; c-basic-offset: 4 -*- */
  2. /*
  3. Copyright (C) 2007,2008 Nedko Arnaudov
  4. Copyright (C) 2007-2008 Juuso Alasuutari
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. */
  16. #include <stdint.h>
  17. #include <string.h>
  18. #include <dbus/dbus.h>
  19. #include "controller.h"
  20. #include "controller_internal.h"
  21. #include "xml.h"
  22. struct jack_dbus_interface_descriptor * g_jackcontroller_interfaces[] =
  23. {
  24. &g_jack_controller_iface_introspectable,
  25. &g_jack_controller_iface_control,
  26. &g_jack_controller_iface_configure,
  27. &g_jack_controller_iface_patchbay,
  28. &g_jack_controller_iface_transport,
  29. NULL
  30. };
  31. jackctl_driver_t *
  32. jack_controller_find_driver(
  33. jackctl_server_t *server,
  34. const char *driver_name)
  35. {
  36. const JSList * node_ptr;
  37. node_ptr = jackctl_server_get_drivers_list(server);
  38. while (node_ptr)
  39. {
  40. if (strcmp(jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data), driver_name) == 0)
  41. {
  42. return node_ptr->data;
  43. }
  44. node_ptr = jack_slist_next(node_ptr);
  45. }
  46. return NULL;
  47. }
  48. jackctl_parameter_t *
  49. jack_controller_find_parameter(
  50. const JSList * parameters_list,
  51. const char * parameter_name)
  52. {
  53. while (parameters_list)
  54. {
  55. if (strcmp(jackctl_parameter_get_name((jackctl_parameter_t *)parameters_list->data), parameter_name) == 0)
  56. {
  57. return parameters_list->data;
  58. }
  59. parameters_list = jack_slist_next(parameters_list);
  60. }
  61. return NULL;
  62. }
  63. bool
  64. jack_controller_select_driver(
  65. struct jack_controller * controller_ptr,
  66. const char * driver_name)
  67. {
  68. jackctl_driver_t *driver;
  69. driver = jack_controller_find_driver(controller_ptr->server, driver_name);
  70. if (driver == NULL)
  71. {
  72. return false;
  73. }
  74. jack_info("driver \"%s\" selected", driver_name);
  75. controller_ptr->driver = driver;
  76. return true;
  77. }
  78. static
  79. int
  80. jack_controller_xrun(void * arg)
  81. {
  82. ((struct jack_controller *)arg)->xruns++;
  83. return 0;
  84. }
  85. bool
  86. jack_controller_start_server(
  87. struct jack_controller * controller_ptr,
  88. void *dbus_call_context_ptr)
  89. {
  90. int ret;
  91. jack_info("Starting jack server...");
  92. if (controller_ptr->started)
  93. {
  94. jack_info("Already started.");
  95. return TRUE;
  96. }
  97. if (controller_ptr->driver == NULL)
  98. {
  99. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Select driver first!");
  100. goto fail;
  101. }
  102. controller_ptr->xruns = 0;
  103. if (!jackctl_server_start(
  104. controller_ptr->server,
  105. controller_ptr->driver))
  106. {
  107. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to start server");
  108. goto fail;
  109. }
  110. controller_ptr->client = jack_client_open(
  111. "dbusapi",
  112. JackNoStartServer,
  113. NULL);
  114. if (controller_ptr->client == NULL)
  115. {
  116. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to create dbusapi jack client");
  117. goto fail_stop_server;
  118. }
  119. ret = jack_set_xrun_callback(controller_ptr->client, jack_controller_xrun, controller_ptr);
  120. if (ret != 0)
  121. {
  122. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to set xrun callback. error is %d", ret);
  123. goto fail_close_client;
  124. }
  125. if (!jack_controller_patchbay_init(controller_ptr))
  126. {
  127. jack_error("Failed to initialize patchbay district");
  128. goto fail_close_client;
  129. }
  130. ret = jack_activate(controller_ptr->client);
  131. if (ret != 0)
  132. {
  133. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to activate dbusapi jack client. error is %d", ret);
  134. goto fail_patchbay_uninit;
  135. }
  136. controller_ptr->started = true;
  137. return TRUE;
  138. fail_patchbay_uninit:
  139. jack_controller_patchbay_uninit(controller_ptr);
  140. fail_close_client:
  141. ret = jack_client_close(controller_ptr->client);
  142. if (ret != 0)
  143. {
  144. jack_error("jack_client_close() failed with error %d", ret);
  145. }
  146. controller_ptr->client = NULL;
  147. fail_stop_server:
  148. if (!jackctl_server_stop(controller_ptr->server))
  149. {
  150. jack_error("failed to stop jack server");
  151. }
  152. fail:
  153. return FALSE;
  154. }
  155. bool
  156. jack_controller_stop_server(
  157. struct jack_controller * controller_ptr,
  158. void *dbus_call_context_ptr)
  159. {
  160. int ret;
  161. jack_info("Stopping jack server...");
  162. if (!controller_ptr->started)
  163. {
  164. jack_info("Already stopped.");
  165. return TRUE;
  166. }
  167. ret = jack_deactivate(controller_ptr->client);
  168. if (ret != 0)
  169. {
  170. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to deactivate dbusapi jack client. error is %d", ret);
  171. }
  172. jack_controller_patchbay_uninit(controller_ptr);
  173. ret = jack_client_close(controller_ptr->client);
  174. if (ret != 0)
  175. {
  176. jack_error("jack_client_close() failed with error %d", ret);
  177. }
  178. controller_ptr->client = NULL;
  179. if (!jackctl_server_stop(controller_ptr->server))
  180. {
  181. return FALSE;
  182. }
  183. controller_ptr->started = false;
  184. return TRUE;
  185. }
  186. void *
  187. jack_controller_create(
  188. DBusConnection *connection)
  189. {
  190. struct jack_controller *controller_ptr;
  191. const JSList * node_ptr;
  192. const char ** driver_name_target;
  193. JSList * drivers;
  194. DBusObjectPathVTable vtable =
  195. {
  196. jack_dbus_message_handler_unregister,
  197. jack_dbus_message_handler,
  198. NULL
  199. };
  200. controller_ptr = malloc(sizeof(struct jack_controller));
  201. if (!controller_ptr)
  202. {
  203. jack_error("Ran out of memory trying to allocate struct jack_controller");
  204. goto fail;
  205. }
  206. controller_ptr->server = jackctl_server_create();
  207. if (controller_ptr->server == NULL)
  208. {
  209. jack_error("Failed to create server object");
  210. goto fail_free;
  211. }
  212. controller_ptr->client = NULL;
  213. controller_ptr->started = false;
  214. drivers = (JSList *)jackctl_server_get_drivers_list(controller_ptr->server);
  215. controller_ptr->drivers_count = jack_slist_length(drivers);
  216. controller_ptr->driver_names = malloc(controller_ptr->drivers_count * sizeof(const char *));
  217. if (controller_ptr->driver_names == NULL)
  218. {
  219. jack_error("Ran out of memory trying to allocate driver names array");
  220. goto fail_destroy_server;
  221. }
  222. driver_name_target = controller_ptr->driver_names;
  223. node_ptr = jackctl_server_get_drivers_list(controller_ptr->server);
  224. while (node_ptr != NULL)
  225. {
  226. *driver_name_target = jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data);
  227. node_ptr = jack_slist_next(node_ptr);
  228. driver_name_target++;
  229. }
  230. controller_ptr->dbus_descriptor.context = controller_ptr;
  231. controller_ptr->dbus_descriptor.interfaces = g_jackcontroller_interfaces;
  232. if (!dbus_connection_register_object_path(
  233. connection,
  234. JACK_CONTROLLER_OBJECT_PATH,
  235. &vtable,
  236. &controller_ptr->dbus_descriptor))
  237. {
  238. jack_error("Ran out of memory trying to register D-Bus object path");
  239. goto fail_free_driver_names_array;
  240. }
  241. jack_controller_settings_load(controller_ptr);
  242. return controller_ptr;
  243. fail_free_driver_names_array:
  244. free(controller_ptr->driver_names);
  245. fail_destroy_server:
  246. jackctl_server_destroy(controller_ptr->server);
  247. fail_free:
  248. free(controller_ptr);
  249. fail:
  250. return NULL;
  251. }
  252. #define controller_ptr ((struct jack_controller *)context)
  253. void
  254. jack_controller_destroy(
  255. void * context)
  256. {
  257. if (controller_ptr->started)
  258. {
  259. jack_controller_stop_server(controller_ptr, NULL);
  260. }
  261. free(controller_ptr->driver_names);
  262. jackctl_server_destroy(controller_ptr->server);
  263. free(controller_ptr);
  264. }