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.

487 lines
12KB

  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. controller_ptr->driver_set = true;
  97. return true;
  98. }
  99. static
  100. int
  101. jack_controller_xrun(void * arg)
  102. {
  103. ((struct jack_controller *)arg)->xruns++;
  104. return 0;
  105. }
  106. bool
  107. jack_controller_start_server(
  108. struct jack_controller * controller_ptr,
  109. void *dbus_call_context_ptr)
  110. {
  111. int ret;
  112. jack_info("Starting jack server...");
  113. if (controller_ptr->started)
  114. {
  115. jack_info("Already started.");
  116. return TRUE;
  117. }
  118. if (controller_ptr->driver == NULL)
  119. {
  120. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Select driver first!");
  121. goto fail;
  122. }
  123. controller_ptr->xruns = 0;
  124. if (!jackctl_server_start(
  125. controller_ptr->server,
  126. controller_ptr->driver))
  127. {
  128. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to start server");
  129. goto fail;
  130. }
  131. controller_ptr->client = jack_client_open(
  132. "dbusapi",
  133. JackNoStartServer,
  134. NULL);
  135. if (controller_ptr->client == NULL)
  136. {
  137. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to create dbusapi jack client");
  138. goto fail_stop_server;
  139. }
  140. ret = jack_set_xrun_callback(controller_ptr->client, jack_controller_xrun, controller_ptr);
  141. if (ret != 0)
  142. {
  143. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to set xrun callback. error is %d", ret);
  144. goto fail_close_client;
  145. }
  146. if (!jack_controller_patchbay_init(controller_ptr))
  147. {
  148. jack_error("Failed to initialize patchbay district");
  149. goto fail_close_client;
  150. }
  151. ret = jack_activate(controller_ptr->client);
  152. if (ret != 0)
  153. {
  154. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to activate dbusapi jack client. error is %d", ret);
  155. goto fail_patchbay_uninit;
  156. }
  157. controller_ptr->started = true;
  158. return TRUE;
  159. fail_patchbay_uninit:
  160. jack_controller_patchbay_uninit(controller_ptr);
  161. fail_close_client:
  162. ret = jack_client_close(controller_ptr->client);
  163. if (ret != 0)
  164. {
  165. jack_error("jack_client_close() failed with error %d", ret);
  166. }
  167. controller_ptr->client = NULL;
  168. fail_stop_server:
  169. if (!jackctl_server_stop(controller_ptr->server))
  170. {
  171. jack_error("failed to stop jack server");
  172. }
  173. fail:
  174. return FALSE;
  175. }
  176. bool
  177. jack_controller_stop_server(
  178. struct jack_controller * controller_ptr,
  179. void *dbus_call_context_ptr)
  180. {
  181. int ret;
  182. jack_info("Stopping jack server...");
  183. if (!controller_ptr->started)
  184. {
  185. jack_info("Already stopped.");
  186. return TRUE;
  187. }
  188. ret = jack_deactivate(controller_ptr->client);
  189. if (ret != 0)
  190. {
  191. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to deactivate dbusapi jack client. error is %d", ret);
  192. }
  193. jack_controller_patchbay_uninit(controller_ptr);
  194. ret = jack_client_close(controller_ptr->client);
  195. if (ret != 0)
  196. {
  197. jack_error("jack_client_close() failed with error %d", ret);
  198. }
  199. controller_ptr->client = NULL;
  200. if (!jackctl_server_stop(controller_ptr->server))
  201. {
  202. return FALSE;
  203. }
  204. controller_ptr->started = false;
  205. return TRUE;
  206. }
  207. bool
  208. jack_controller_switch_master(
  209. struct jack_controller * controller_ptr,
  210. void *dbus_call_context_ptr)
  211. {
  212. if (!jackctl_server_switch_master(
  213. controller_ptr->server,
  214. controller_ptr->driver))
  215. {
  216. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to switch master");
  217. return FALSE;
  218. }
  219. return TRUE;
  220. }
  221. void *
  222. jack_controller_create(
  223. DBusConnection *connection)
  224. {
  225. struct jack_controller *controller_ptr;
  226. const JSList * node_ptr;
  227. const char ** driver_name_target;
  228. const char ** internal_name_target;
  229. JSList * drivers;
  230. JSList * internals;
  231. DBusObjectPathVTable vtable =
  232. {
  233. jack_dbus_message_handler_unregister,
  234. jack_dbus_message_handler,
  235. NULL
  236. };
  237. controller_ptr = malloc(sizeof(struct jack_controller));
  238. if (!controller_ptr)
  239. {
  240. jack_error("Ran out of memory trying to allocate struct jack_controller");
  241. goto fail;
  242. }
  243. controller_ptr->server = jackctl_server_create();
  244. if (controller_ptr->server == NULL)
  245. {
  246. jack_error("Failed to create server object");
  247. goto fail_free;
  248. }
  249. controller_ptr->client = NULL;
  250. controller_ptr->started = false;
  251. controller_ptr->driver = NULL;
  252. controller_ptr->driver_set = false;
  253. drivers = (JSList *)jackctl_server_get_drivers_list(controller_ptr->server);
  254. controller_ptr->drivers_count = jack_slist_length(drivers);
  255. controller_ptr->driver_names = malloc(controller_ptr->drivers_count * sizeof(const char *));
  256. if (controller_ptr->driver_names == NULL)
  257. {
  258. jack_error("Ran out of memory trying to allocate driver names array");
  259. goto fail_destroy_server;
  260. }
  261. driver_name_target = controller_ptr->driver_names;
  262. node_ptr = jackctl_server_get_drivers_list(controller_ptr->server);
  263. while (node_ptr != NULL)
  264. {
  265. *driver_name_target = jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data);
  266. /* select default driver */
  267. if (controller_ptr->driver == NULL && strcmp(*driver_name_target, DEFAULT_DRIVER) == 0)
  268. {
  269. controller_ptr->driver = (jackctl_driver_t *)node_ptr->data;
  270. }
  271. node_ptr = jack_slist_next(node_ptr);
  272. driver_name_target++;
  273. }
  274. internals = (JSList *)jackctl_server_get_internals_list(controller_ptr->server);
  275. controller_ptr->internals_count = jack_slist_length(internals);
  276. controller_ptr->internal_names = malloc(controller_ptr->internals_count * sizeof(const char *));
  277. if (controller_ptr->internal_names == NULL)
  278. {
  279. jack_error("Ran out of memory trying to allocate internals names array");
  280. goto fail_free_driver_names_array;
  281. }
  282. internal_name_target = controller_ptr->internal_names;
  283. node_ptr = jackctl_server_get_internals_list(controller_ptr->server);
  284. while (node_ptr != NULL)
  285. {
  286. *internal_name_target = jackctl_internal_get_name((jackctl_internal_t *)node_ptr->data);
  287. node_ptr = jack_slist_next(node_ptr);
  288. internal_name_target++;
  289. }
  290. controller_ptr->dbus_descriptor.context = controller_ptr;
  291. controller_ptr->dbus_descriptor.interfaces = g_jackcontroller_interfaces;
  292. if (!dbus_connection_register_object_path(
  293. connection,
  294. JACK_CONTROLLER_OBJECT_PATH,
  295. &vtable,
  296. &controller_ptr->dbus_descriptor))
  297. {
  298. jack_error("Ran out of memory trying to register D-Bus object path");
  299. goto fail_free_internal_names_array;
  300. }
  301. jack_controller_settings_load(controller_ptr);
  302. return controller_ptr;
  303. fail_free_internal_names_array:
  304. free(controller_ptr->internal_names);
  305. fail_free_driver_names_array:
  306. free(controller_ptr->driver_names);
  307. fail_destroy_server:
  308. jackctl_server_destroy(controller_ptr->server);
  309. fail_free:
  310. free(controller_ptr);
  311. fail:
  312. return NULL;
  313. }
  314. bool
  315. jack_controller_add_slave(
  316. struct jack_controller *controller_ptr,
  317. const char * driver_name)
  318. {
  319. jackctl_driver_t *driver;
  320. driver = jack_controller_find_driver(controller_ptr->server, driver_name);
  321. if (driver == NULL)
  322. {
  323. return false;
  324. }
  325. jack_info("driver \"%s\" selected", driver_name);
  326. return jackctl_server_add_slave(controller_ptr->server, driver);
  327. }
  328. bool
  329. jack_controller_remove_slave(
  330. struct jack_controller *controller_ptr,
  331. const char * driver_name)
  332. {
  333. jackctl_driver_t *driver;
  334. driver = jack_controller_find_driver(controller_ptr->server, driver_name);
  335. if (driver == NULL)
  336. {
  337. return false;
  338. }
  339. jack_info("driver \"%s\" selected", driver_name);
  340. return jackctl_server_remove_slave(controller_ptr->server, driver);
  341. }
  342. bool
  343. jack_controller_load_internal(
  344. struct jack_controller *controller_ptr,
  345. const char * internal_name)
  346. {
  347. jackctl_internal_t *internal;
  348. internal = jack_controller_find_internal(controller_ptr->server, internal_name);
  349. if (internal == NULL)
  350. {
  351. return false;
  352. }
  353. jack_info("internal \"%s\" selected", internal_name);
  354. return jackctl_server_load_internal(controller_ptr->server, internal);
  355. }
  356. bool
  357. jack_controller_unload_internal(
  358. struct jack_controller *controller_ptr,
  359. const char * internal_name)
  360. {
  361. jackctl_internal_t *internal;
  362. internal = jack_controller_find_internal(controller_ptr->server, internal_name);
  363. if (internal == NULL)
  364. {
  365. return false;
  366. }
  367. jack_info("internal \"%s\" selected", internal_name);
  368. return jackctl_server_unload_internal(controller_ptr->server, internal);
  369. }
  370. #define controller_ptr ((struct jack_controller *)context)
  371. void
  372. jack_controller_destroy(
  373. void * context)
  374. {
  375. if (controller_ptr->started)
  376. {
  377. jack_controller_stop_server(controller_ptr, NULL);
  378. }
  379. free(controller_ptr->driver_names);
  380. free(controller_ptr->internal_names);
  381. jackctl_server_destroy(controller_ptr->server);
  382. free(controller_ptr);
  383. }