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.

341 lines
8.2KB

  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. #if defined(HAVE_CONFIG_H)
  17. #include "config.h"
  18. #endif
  19. #include <stdint.h>
  20. #include <string.h>
  21. #include <dbus/dbus.h>
  22. #include "controller.h"
  23. #include "controller_internal.h"
  24. #include "xml.h"
  25. struct jack_dbus_interface_descriptor * g_jackcontroller_interfaces[] =
  26. {
  27. &g_jack_controller_iface_introspectable,
  28. &g_jack_controller_iface_control,
  29. &g_jack_controller_iface_configure,
  30. &g_jack_controller_iface_patchbay,
  31. &g_jack_controller_iface_transport,
  32. NULL
  33. };
  34. jackctl_driver_t *
  35. jack_controller_find_driver(
  36. jackctl_server_t *server,
  37. const char *driver_name)
  38. {
  39. const JSList * node_ptr;
  40. node_ptr = jackctl_server_get_drivers_list(server);
  41. while (node_ptr)
  42. {
  43. if (strcmp(jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data), driver_name) == 0)
  44. {
  45. return node_ptr->data;
  46. }
  47. node_ptr = jack_slist_next(node_ptr);
  48. }
  49. return NULL;
  50. }
  51. jackctl_parameter_t *
  52. jack_controller_find_parameter(
  53. const JSList * parameters_list,
  54. const char * parameter_name)
  55. {
  56. while (parameters_list)
  57. {
  58. if (strcmp(jackctl_parameter_get_name((jackctl_parameter_t *)parameters_list->data), parameter_name) == 0)
  59. {
  60. return parameters_list->data;
  61. }
  62. parameters_list = jack_slist_next(parameters_list);
  63. }
  64. return NULL;
  65. }
  66. bool
  67. jack_controller_select_driver(
  68. struct jack_controller * controller_ptr,
  69. const char * driver_name)
  70. {
  71. jackctl_driver_t *driver;
  72. driver = jack_controller_find_driver(controller_ptr->server, driver_name);
  73. if (driver == NULL)
  74. {
  75. return false;
  76. }
  77. jack_info("driver \"%s\" selected", driver_name);
  78. controller_ptr->driver = driver;
  79. return true;
  80. }
  81. static
  82. int
  83. jack_controller_xrun(void * arg)
  84. {
  85. ((struct jack_controller *)arg)->xruns++;
  86. return 0;
  87. }
  88. bool
  89. jack_controller_start_server(
  90. struct jack_controller * controller_ptr,
  91. void *dbus_call_context_ptr)
  92. {
  93. int ret;
  94. jack_info("Starting jack server...");
  95. if (controller_ptr->started)
  96. {
  97. jack_info("Already started.");
  98. return TRUE;
  99. }
  100. if (controller_ptr->driver == NULL)
  101. {
  102. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Select driver first!");
  103. goto fail;
  104. }
  105. controller_ptr->xruns = 0;
  106. if (!jackctl_server_start(
  107. controller_ptr->server,
  108. controller_ptr->driver))
  109. {
  110. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to start server");
  111. goto fail;
  112. }
  113. controller_ptr->client = jack_client_open(
  114. "dbusapi",
  115. JackNoStartServer,
  116. NULL);
  117. if (controller_ptr->client == NULL)
  118. {
  119. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to create dbusapi jack client");
  120. goto fail_stop_server;
  121. }
  122. ret = jack_set_xrun_callback(controller_ptr->client, jack_controller_xrun, controller_ptr);
  123. if (ret != 0)
  124. {
  125. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to set xrun callback. error is %d", ret);
  126. goto fail_close_client;
  127. }
  128. if (!jack_controller_patchbay_init(controller_ptr))
  129. {
  130. jack_error("Failed to initialize patchbay district");
  131. goto fail_close_client;
  132. }
  133. ret = jack_activate(controller_ptr->client);
  134. if (ret != 0)
  135. {
  136. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to activate dbusapi jack client. error is %d", ret);
  137. goto fail_patchbay_uninit;
  138. }
  139. controller_ptr->started = true;
  140. return TRUE;
  141. fail_patchbay_uninit:
  142. jack_controller_patchbay_uninit(controller_ptr);
  143. fail_close_client:
  144. ret = jack_client_close(controller_ptr->client);
  145. if (ret != 0)
  146. {
  147. jack_error("jack_client_close() failed with error %d", ret);
  148. }
  149. controller_ptr->client = NULL;
  150. fail_stop_server:
  151. if (!jackctl_server_stop(controller_ptr->server))
  152. {
  153. jack_error("failed to stop jack server");
  154. }
  155. fail:
  156. return FALSE;
  157. }
  158. bool
  159. jack_controller_stop_server(
  160. struct jack_controller * controller_ptr,
  161. void *dbus_call_context_ptr)
  162. {
  163. int ret;
  164. jack_info("Stopping jack server...");
  165. if (!controller_ptr->started)
  166. {
  167. jack_info("Already stopped.");
  168. return TRUE;
  169. }
  170. ret = jack_deactivate(controller_ptr->client);
  171. if (ret != 0)
  172. {
  173. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to deactivate dbusapi jack client. error is %d", ret);
  174. }
  175. jack_controller_patchbay_uninit(controller_ptr);
  176. ret = jack_client_close(controller_ptr->client);
  177. if (ret != 0)
  178. {
  179. jack_error("jack_client_close() failed with error %d", ret);
  180. }
  181. controller_ptr->client = NULL;
  182. if (!jackctl_server_stop(controller_ptr->server))
  183. {
  184. return FALSE;
  185. }
  186. controller_ptr->started = false;
  187. return TRUE;
  188. }
  189. void *
  190. jack_controller_create(
  191. DBusConnection *connection)
  192. {
  193. struct jack_controller *controller_ptr;
  194. const JSList * node_ptr;
  195. const char ** driver_name_target;
  196. JSList * drivers;
  197. DBusObjectPathVTable vtable =
  198. {
  199. jack_dbus_message_handler_unregister,
  200. jack_dbus_message_handler,
  201. NULL
  202. };
  203. controller_ptr = malloc(sizeof(struct jack_controller));
  204. if (!controller_ptr)
  205. {
  206. jack_error("Ran out of memory trying to allocate struct jack_controller");
  207. goto fail;
  208. }
  209. controller_ptr->server = jackctl_server_create();
  210. if (controller_ptr->server == NULL)
  211. {
  212. jack_error("Failed to create server object");
  213. goto fail_free;
  214. }
  215. controller_ptr->client = NULL;
  216. controller_ptr->started = false;
  217. drivers = (JSList *)jackctl_server_get_drivers_list(controller_ptr->server);
  218. controller_ptr->drivers_count = jack_slist_length(drivers);
  219. controller_ptr->driver_names = malloc(controller_ptr->drivers_count * sizeof(const char *));
  220. if (controller_ptr->driver_names == NULL)
  221. {
  222. jack_error("Ran out of memory trying to allocate driver names array");
  223. goto fail_destroy_server;
  224. }
  225. driver_name_target = controller_ptr->driver_names;
  226. node_ptr = jackctl_server_get_drivers_list(controller_ptr->server);
  227. while (node_ptr != NULL)
  228. {
  229. *driver_name_target = jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data);
  230. node_ptr = jack_slist_next(node_ptr);
  231. driver_name_target++;
  232. }
  233. controller_ptr->dbus_descriptor.context = controller_ptr;
  234. controller_ptr->dbus_descriptor.interfaces = g_jackcontroller_interfaces;
  235. if (!dbus_connection_register_object_path(
  236. connection,
  237. JACK_CONTROLLER_OBJECT_PATH,
  238. &vtable,
  239. &controller_ptr->dbus_descriptor))
  240. {
  241. jack_error("Ran out of memory trying to register D-Bus object path");
  242. goto fail_free_driver_names_array;
  243. }
  244. jack_controller_settings_load(controller_ptr);
  245. return controller_ptr;
  246. fail_free_driver_names_array:
  247. free(controller_ptr->driver_names);
  248. fail_destroy_server:
  249. jackctl_server_destroy(controller_ptr->server);
  250. fail_free:
  251. free(controller_ptr);
  252. fail:
  253. return NULL;
  254. }
  255. #define controller_ptr ((struct jack_controller *)context)
  256. void
  257. jack_controller_destroy(
  258. void * context)
  259. {
  260. if (controller_ptr->started)
  261. {
  262. jack_controller_stop_server(controller_ptr, NULL);
  263. }
  264. free(controller_ptr->driver_names);
  265. jackctl_server_destroy(controller_ptr->server);
  266. free(controller_ptr);
  267. }