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.

424 lines
10KB

  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_internal_t *
  52. jack_controller_find_internal(
  53. jackctl_server_t *server,
  54. const char *internal_name)
  55. {
  56. const JSList * node_ptr;
  57. node_ptr = jackctl_server_get_internals_list(server);
  58. while (node_ptr)
  59. {
  60. if (strcmp(jackctl_internal_get_name((jackctl_internal_t *)node_ptr->data), internal_name) == 0)
  61. {
  62. return node_ptr->data;
  63. }
  64. node_ptr = jack_slist_next(node_ptr);
  65. }
  66. return NULL;
  67. }
  68. jackctl_parameter_t *
  69. jack_controller_find_parameter(
  70. const JSList * parameters_list,
  71. const char * parameter_name)
  72. {
  73. while (parameters_list)
  74. {
  75. if (strcmp(jackctl_parameter_get_name((jackctl_parameter_t *)parameters_list->data), parameter_name) == 0)
  76. {
  77. return parameters_list->data;
  78. }
  79. parameters_list = jack_slist_next(parameters_list);
  80. }
  81. return NULL;
  82. }
  83. bool
  84. jack_controller_select_driver(
  85. struct jack_controller * controller_ptr,
  86. const char * driver_name)
  87. {
  88. jackctl_driver_t *driver;
  89. driver = jack_controller_find_driver(controller_ptr->server, driver_name);
  90. if (driver == NULL)
  91. {
  92. return false;
  93. }
  94. jack_info("driver \"%s\" selected", driver_name);
  95. controller_ptr->driver = driver;
  96. return true;
  97. }
  98. static
  99. int
  100. jack_controller_xrun(void * arg)
  101. {
  102. ((struct jack_controller *)arg)->xruns++;
  103. return 0;
  104. }
  105. bool
  106. jack_controller_start_server(
  107. struct jack_controller * controller_ptr,
  108. void *dbus_call_context_ptr)
  109. {
  110. int ret;
  111. jack_info("Starting jack server...");
  112. if (controller_ptr->started)
  113. {
  114. jack_info("Already started.");
  115. return TRUE;
  116. }
  117. if (controller_ptr->driver == NULL)
  118. {
  119. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Select driver first!");
  120. goto fail;
  121. }
  122. controller_ptr->xruns = 0;
  123. if (!jackctl_server_start(
  124. controller_ptr->server,
  125. controller_ptr->driver))
  126. {
  127. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to start server");
  128. goto fail;
  129. }
  130. controller_ptr->client = jack_client_open(
  131. "dbusapi",
  132. JackNoStartServer,
  133. NULL);
  134. if (controller_ptr->client == NULL)
  135. {
  136. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to create dbusapi jack client");
  137. goto fail_stop_server;
  138. }
  139. ret = jack_set_xrun_callback(controller_ptr->client, jack_controller_xrun, controller_ptr);
  140. if (ret != 0)
  141. {
  142. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to set xrun callback. error is %d", ret);
  143. goto fail_close_client;
  144. }
  145. if (!jack_controller_patchbay_init(controller_ptr))
  146. {
  147. jack_error("Failed to initialize patchbay district");
  148. goto fail_close_client;
  149. }
  150. ret = jack_activate(controller_ptr->client);
  151. if (ret != 0)
  152. {
  153. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to activate dbusapi jack client. error is %d", ret);
  154. goto fail_patchbay_uninit;
  155. }
  156. controller_ptr->started = true;
  157. return TRUE;
  158. fail_patchbay_uninit:
  159. jack_controller_patchbay_uninit(controller_ptr);
  160. fail_close_client:
  161. ret = jack_client_close(controller_ptr->client);
  162. if (ret != 0)
  163. {
  164. jack_error("jack_client_close() failed with error %d", ret);
  165. }
  166. controller_ptr->client = NULL;
  167. fail_stop_server:
  168. if (!jackctl_server_stop(controller_ptr->server))
  169. {
  170. jack_error("failed to stop jack server");
  171. }
  172. fail:
  173. return FALSE;
  174. }
  175. bool
  176. jack_controller_stop_server(
  177. struct jack_controller * controller_ptr,
  178. void *dbus_call_context_ptr)
  179. {
  180. int ret;
  181. jack_info("Stopping jack server...");
  182. if (!controller_ptr->started)
  183. {
  184. jack_info("Already stopped.");
  185. return TRUE;
  186. }
  187. ret = jack_deactivate(controller_ptr->client);
  188. if (ret != 0)
  189. {
  190. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to deactivate dbusapi jack client. error is %d", ret);
  191. }
  192. jack_controller_patchbay_uninit(controller_ptr);
  193. ret = jack_client_close(controller_ptr->client);
  194. if (ret != 0)
  195. {
  196. jack_error("jack_client_close() failed with error %d", ret);
  197. }
  198. controller_ptr->client = NULL;
  199. if (!jackctl_server_stop(controller_ptr->server))
  200. {
  201. return FALSE;
  202. }
  203. controller_ptr->started = false;
  204. return TRUE;
  205. }
  206. void *
  207. jack_controller_create(
  208. DBusConnection *connection)
  209. {
  210. struct jack_controller *controller_ptr;
  211. const JSList * node_ptr;
  212. const char ** driver_name_target;
  213. const char ** internal_name_target;
  214. JSList * drivers;
  215. JSList * internals;
  216. DBusObjectPathVTable vtable =
  217. {
  218. jack_dbus_message_handler_unregister,
  219. jack_dbus_message_handler,
  220. NULL
  221. };
  222. controller_ptr = malloc(sizeof(struct jack_controller));
  223. if (!controller_ptr)
  224. {
  225. jack_error("Ran out of memory trying to allocate struct jack_controller");
  226. goto fail;
  227. }
  228. controller_ptr->server = jackctl_server_create();
  229. if (controller_ptr->server == NULL)
  230. {
  231. jack_error("Failed to create server object");
  232. goto fail_free;
  233. }
  234. controller_ptr->client = NULL;
  235. controller_ptr->started = false;
  236. controller_ptr->driver = NULL;
  237. drivers = (JSList *)jackctl_server_get_drivers_list(controller_ptr->server);
  238. controller_ptr->drivers_count = jack_slist_length(drivers);
  239. controller_ptr->driver_names = malloc(controller_ptr->drivers_count * sizeof(const char *));
  240. if (controller_ptr->driver_names == NULL)
  241. {
  242. jack_error("Ran out of memory trying to allocate driver names array");
  243. goto fail_destroy_server;
  244. }
  245. driver_name_target = controller_ptr->driver_names;
  246. node_ptr = jackctl_server_get_drivers_list(controller_ptr->server);
  247. while (node_ptr != NULL)
  248. {
  249. *driver_name_target = jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data);
  250. node_ptr = jack_slist_next(node_ptr);
  251. driver_name_target++;
  252. }
  253. internals = (JSList *)jackctl_server_get_internals_list(controller_ptr->server);
  254. controller_ptr->internals_count = jack_slist_length(internals);
  255. controller_ptr->internal_names = malloc(controller_ptr->internals_count * sizeof(const char *));
  256. if (controller_ptr->internal_names == NULL)
  257. {
  258. jack_error("Ran out of memory trying to allocate internals names array");
  259. goto fail_free_driver_names_array;
  260. }
  261. internal_name_target = controller_ptr->internal_names;
  262. node_ptr = jackctl_server_get_internals_list(controller_ptr->server);
  263. while (node_ptr != NULL)
  264. {
  265. *internal_name_target = jackctl_internal_get_name((jackctl_internal_t *)node_ptr->data);
  266. node_ptr = jack_slist_next(node_ptr);
  267. internal_name_target++;
  268. }
  269. controller_ptr->dbus_descriptor.context = controller_ptr;
  270. controller_ptr->dbus_descriptor.interfaces = g_jackcontroller_interfaces;
  271. if (!dbus_connection_register_object_path(
  272. connection,
  273. JACK_CONTROLLER_OBJECT_PATH,
  274. &vtable,
  275. &controller_ptr->dbus_descriptor))
  276. {
  277. jack_error("Ran out of memory trying to register D-Bus object path");
  278. goto fail_free_internal_names_array;
  279. }
  280. jack_controller_settings_load(controller_ptr);
  281. return controller_ptr;
  282. fail_free_internal_names_array:
  283. free(controller_ptr->internal_names);
  284. fail_free_driver_names_array:
  285. free(controller_ptr->driver_names);
  286. fail_destroy_server:
  287. jackctl_server_destroy(controller_ptr->server);
  288. fail_free:
  289. free(controller_ptr);
  290. fail:
  291. return NULL;
  292. }
  293. bool
  294. jack_controller_load_internal(
  295. struct jack_controller *controller_ptr,
  296. const char * internal_name)
  297. {
  298. jackctl_internal_t *internal;
  299. internal = jack_controller_find_internal(controller_ptr->server, internal_name);
  300. if (internal == NULL)
  301. {
  302. return false;
  303. }
  304. jack_info("internal \"%s\" selected", internal_name);
  305. return jackctl_server_load_internal(controller_ptr->server, internal);
  306. }
  307. bool
  308. jack_controller_unload_internal(
  309. struct jack_controller *controller_ptr,
  310. const char * internal_name)
  311. {
  312. jackctl_internal_t *internal;
  313. internal = jack_controller_find_internal(controller_ptr->server, internal_name);
  314. if (internal == NULL)
  315. {
  316. return false;
  317. }
  318. jack_info("internal \"%s\" selected", internal_name);
  319. return jackctl_server_unload_internal(controller_ptr->server, internal);
  320. }
  321. #define controller_ptr ((struct jack_controller *)context)
  322. void
  323. jack_controller_destroy(
  324. void * context)
  325. {
  326. if (controller_ptr->started)
  327. {
  328. jack_controller_stop_server(controller_ptr, NULL);
  329. }
  330. free(controller_ptr->driver_names);
  331. free(controller_ptr->internal_names);
  332. jackctl_server_destroy(controller_ptr->server);
  333. free(controller_ptr);
  334. }