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.

550 lines
13KB

  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. #include "reserve.h"
  26. struct jack_dbus_interface_descriptor * g_jackcontroller_interfaces[] =
  27. {
  28. &g_jack_controller_iface_introspectable,
  29. &g_jack_controller_iface_control,
  30. &g_jack_controller_iface_configure,
  31. &g_jack_controller_iface_patchbay,
  32. &g_jack_controller_iface_transport,
  33. NULL
  34. };
  35. jackctl_driver_t *
  36. jack_controller_find_driver(
  37. jackctl_server_t *server,
  38. const char *driver_name)
  39. {
  40. const JSList * node_ptr;
  41. node_ptr = jackctl_server_get_drivers_list(server);
  42. while (node_ptr)
  43. {
  44. if (strcmp(jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data), driver_name) == 0)
  45. {
  46. return node_ptr->data;
  47. }
  48. node_ptr = jack_slist_next(node_ptr);
  49. }
  50. return NULL;
  51. }
  52. jackctl_internal_t *
  53. jack_controller_find_internal(
  54. jackctl_server_t *server,
  55. const char *internal_name)
  56. {
  57. const JSList * node_ptr;
  58. node_ptr = jackctl_server_get_internals_list(server);
  59. while (node_ptr)
  60. {
  61. if (strcmp(jackctl_internal_get_name((jackctl_internal_t *)node_ptr->data), internal_name) == 0)
  62. {
  63. return node_ptr->data;
  64. }
  65. node_ptr = jack_slist_next(node_ptr);
  66. }
  67. return NULL;
  68. }
  69. jackctl_parameter_t *
  70. jack_controller_find_parameter(
  71. const JSList * parameters_list,
  72. const char * parameter_name)
  73. {
  74. while (parameters_list)
  75. {
  76. if (strcmp(jackctl_parameter_get_name((jackctl_parameter_t *)parameters_list->data), parameter_name) == 0)
  77. {
  78. return parameters_list->data;
  79. }
  80. parameters_list = jack_slist_next(parameters_list);
  81. }
  82. return NULL;
  83. }
  84. bool
  85. jack_controller_select_driver(
  86. struct jack_controller * controller_ptr,
  87. const char * driver_name)
  88. {
  89. jackctl_driver_t *driver;
  90. driver = jack_controller_find_driver(controller_ptr->server, driver_name);
  91. if (driver == NULL)
  92. {
  93. return false;
  94. }
  95. jack_info("driver \"%s\" selected", driver_name);
  96. controller_ptr->driver = driver;
  97. controller_ptr->driver_set = true;
  98. return true;
  99. }
  100. static
  101. int
  102. jack_controller_xrun(void * arg)
  103. {
  104. ((struct jack_controller *)arg)->xruns++;
  105. return 0;
  106. }
  107. bool
  108. jack_controller_start_server(
  109. struct jack_controller * controller_ptr,
  110. void *dbus_call_context_ptr)
  111. {
  112. int ret;
  113. jack_info("Starting jack server...");
  114. if (controller_ptr->started)
  115. {
  116. jack_info("Already started.");
  117. return TRUE;
  118. }
  119. if (controller_ptr->driver == NULL)
  120. {
  121. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Select driver first!");
  122. goto fail;
  123. }
  124. controller_ptr->xruns = 0;
  125. if (!jackctl_server_start(
  126. controller_ptr->server,
  127. controller_ptr->driver))
  128. {
  129. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to start server");
  130. goto fail;
  131. }
  132. controller_ptr->client = jack_client_open(
  133. "dbusapi",
  134. JackNoStartServer,
  135. NULL);
  136. if (controller_ptr->client == NULL)
  137. {
  138. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to create dbusapi jack client");
  139. goto fail_stop_server;
  140. }
  141. ret = jack_set_xrun_callback(controller_ptr->client, jack_controller_xrun, controller_ptr);
  142. if (ret != 0)
  143. {
  144. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to set xrun callback. error is %d", ret);
  145. goto fail_close_client;
  146. }
  147. if (!jack_controller_patchbay_init(controller_ptr))
  148. {
  149. jack_error("Failed to initialize patchbay district");
  150. goto fail_close_client;
  151. }
  152. ret = jack_activate(controller_ptr->client);
  153. if (ret != 0)
  154. {
  155. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to activate dbusapi jack client. error is %d", ret);
  156. goto fail_patchbay_uninit;
  157. }
  158. controller_ptr->started = true;
  159. return TRUE;
  160. fail_patchbay_uninit:
  161. jack_controller_patchbay_uninit(controller_ptr);
  162. fail_close_client:
  163. ret = jack_client_close(controller_ptr->client);
  164. if (ret != 0)
  165. {
  166. jack_error("jack_client_close() failed with error %d", ret);
  167. }
  168. controller_ptr->client = NULL;
  169. fail_stop_server:
  170. if (!jackctl_server_stop(controller_ptr->server))
  171. {
  172. jack_error("failed to stop jack server");
  173. }
  174. fail:
  175. return FALSE;
  176. }
  177. bool
  178. jack_controller_stop_server(
  179. struct jack_controller * controller_ptr,
  180. void *dbus_call_context_ptr)
  181. {
  182. int ret;
  183. jack_info("Stopping jack server...");
  184. if (!controller_ptr->started)
  185. {
  186. jack_info("Already stopped.");
  187. return TRUE;
  188. }
  189. ret = jack_deactivate(controller_ptr->client);
  190. if (ret != 0)
  191. {
  192. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to deactivate dbusapi jack client. error is %d", ret);
  193. }
  194. jack_controller_patchbay_uninit(controller_ptr);
  195. ret = jack_client_close(controller_ptr->client);
  196. if (ret != 0)
  197. {
  198. jack_error("jack_client_close() failed with error %d", ret);
  199. }
  200. controller_ptr->client = NULL;
  201. if (!jackctl_server_stop(controller_ptr->server))
  202. {
  203. return FALSE;
  204. }
  205. controller_ptr->started = false;
  206. return TRUE;
  207. }
  208. bool
  209. jack_controller_switch_master(
  210. struct jack_controller * controller_ptr,
  211. void *dbus_call_context_ptr)
  212. {
  213. if (!jackctl_server_switch_master(
  214. controller_ptr->server,
  215. controller_ptr->driver))
  216. {
  217. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to switch master");
  218. return FALSE;
  219. }
  220. return TRUE;
  221. }
  222. #define DEVICE_MAX 2
  223. typedef struct reserved_audio_device {
  224. char device_name[64];
  225. rd_device * reserved_device;
  226. } reserved_audio_device;
  227. int g_device_count = 0;
  228. static reserved_audio_device g_reserved_device[DEVICE_MAX];
  229. static
  230. bool
  231. on_device_acquire(const char * device_name)
  232. {
  233. int ret;
  234. DBusError error;
  235. ret = rd_acquire(
  236. &g_reserved_device[g_device_count].reserved_device,
  237. g_connection,
  238. device_name,
  239. "Jack audio server",
  240. INT32_MAX,
  241. NULL,
  242. &error);
  243. if (ret < 0)
  244. {
  245. jack_error("Failed to acquire device name : %s error : %s", device_name, (error.message ? error.message : strerror(-ret)));
  246. return false;
  247. }
  248. strcpy(g_reserved_device[g_device_count].device_name, device_name);
  249. g_device_count++;
  250. jack_info("Acquired audio card %s", device_name);
  251. return true;
  252. }
  253. static
  254. void
  255. on_device_release(const char * device_name)
  256. {
  257. int i;
  258. // Look for corresponding reserved device
  259. for (i = 0; i < DEVICE_MAX; i++) {
  260. if (strcmp(g_reserved_device[i].device_name, device_name) == 0)
  261. break;
  262. }
  263. if (i < DEVICE_MAX) {
  264. jack_info("Released audio card %s", device_name);
  265. rd_release(g_reserved_device[i].reserved_device);
  266. } else {
  267. jack_error("Audio card %s not found!!", device_name);
  268. }
  269. g_device_count--;
  270. }
  271. void *
  272. jack_controller_create(
  273. DBusConnection *connection)
  274. {
  275. struct jack_controller *controller_ptr;
  276. const JSList * node_ptr;
  277. const char ** driver_name_target;
  278. const char ** internal_name_target;
  279. JSList * drivers;
  280. JSList * internals;
  281. DBusObjectPathVTable vtable =
  282. {
  283. jack_dbus_message_handler_unregister,
  284. jack_dbus_message_handler,
  285. NULL
  286. };
  287. controller_ptr = malloc(sizeof(struct jack_controller));
  288. if (!controller_ptr)
  289. {
  290. jack_error("Ran out of memory trying to allocate struct jack_controller");
  291. goto fail;
  292. }
  293. controller_ptr->server = jackctl_server_create(on_device_acquire, on_device_release);
  294. if (controller_ptr->server == NULL)
  295. {
  296. jack_error("Failed to create server object");
  297. goto fail_free;
  298. }
  299. controller_ptr->client = NULL;
  300. controller_ptr->started = false;
  301. controller_ptr->driver = NULL;
  302. controller_ptr->driver_set = false;
  303. drivers = (JSList *)jackctl_server_get_drivers_list(controller_ptr->server);
  304. controller_ptr->drivers_count = jack_slist_length(drivers);
  305. controller_ptr->driver_names = malloc(controller_ptr->drivers_count * sizeof(const char *));
  306. if (controller_ptr->driver_names == NULL)
  307. {
  308. jack_error("Ran out of memory trying to allocate driver names array");
  309. goto fail_destroy_server;
  310. }
  311. driver_name_target = controller_ptr->driver_names;
  312. node_ptr = jackctl_server_get_drivers_list(controller_ptr->server);
  313. while (node_ptr != NULL)
  314. {
  315. *driver_name_target = jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data);
  316. /* select default driver */
  317. if (controller_ptr->driver == NULL && strcmp(*driver_name_target, DEFAULT_DRIVER) == 0)
  318. {
  319. controller_ptr->driver = (jackctl_driver_t *)node_ptr->data;
  320. }
  321. node_ptr = jack_slist_next(node_ptr);
  322. driver_name_target++;
  323. }
  324. internals = (JSList *)jackctl_server_get_internals_list(controller_ptr->server);
  325. controller_ptr->internals_count = jack_slist_length(internals);
  326. controller_ptr->internal_names = malloc(controller_ptr->internals_count * sizeof(const char *));
  327. if (controller_ptr->internal_names == NULL)
  328. {
  329. jack_error("Ran out of memory trying to allocate internals names array");
  330. goto fail_free_driver_names_array;
  331. }
  332. internal_name_target = controller_ptr->internal_names;
  333. node_ptr = jackctl_server_get_internals_list(controller_ptr->server);
  334. while (node_ptr != NULL)
  335. {
  336. *internal_name_target = jackctl_internal_get_name((jackctl_internal_t *)node_ptr->data);
  337. node_ptr = jack_slist_next(node_ptr);
  338. internal_name_target++;
  339. }
  340. controller_ptr->dbus_descriptor.context = controller_ptr;
  341. controller_ptr->dbus_descriptor.interfaces = g_jackcontroller_interfaces;
  342. if (!dbus_connection_register_object_path(
  343. connection,
  344. JACK_CONTROLLER_OBJECT_PATH,
  345. &vtable,
  346. &controller_ptr->dbus_descriptor))
  347. {
  348. jack_error("Ran out of memory trying to register D-Bus object path");
  349. goto fail_free_internal_names_array;
  350. }
  351. jack_controller_settings_load(controller_ptr);
  352. return controller_ptr;
  353. fail_free_internal_names_array:
  354. free(controller_ptr->internal_names);
  355. fail_free_driver_names_array:
  356. free(controller_ptr->driver_names);
  357. fail_destroy_server:
  358. jackctl_server_destroy(controller_ptr->server);
  359. fail_free:
  360. free(controller_ptr);
  361. fail:
  362. return NULL;
  363. }
  364. bool
  365. jack_controller_add_slave(
  366. struct jack_controller *controller_ptr,
  367. const char * driver_name)
  368. {
  369. jackctl_driver_t *driver;
  370. driver = jack_controller_find_driver(controller_ptr->server, driver_name);
  371. if (driver == NULL)
  372. {
  373. return false;
  374. }
  375. jack_info("driver \"%s\" selected", driver_name);
  376. return jackctl_server_add_slave(controller_ptr->server, driver);
  377. }
  378. bool
  379. jack_controller_remove_slave(
  380. struct jack_controller *controller_ptr,
  381. const char * driver_name)
  382. {
  383. jackctl_driver_t *driver;
  384. driver = jack_controller_find_driver(controller_ptr->server, driver_name);
  385. if (driver == NULL)
  386. {
  387. return false;
  388. }
  389. jack_info("driver \"%s\" selected", driver_name);
  390. return jackctl_server_remove_slave(controller_ptr->server, driver);
  391. }
  392. bool
  393. jack_controller_load_internal(
  394. struct jack_controller *controller_ptr,
  395. const char * internal_name)
  396. {
  397. jackctl_internal_t *internal;
  398. internal = jack_controller_find_internal(controller_ptr->server, internal_name);
  399. if (internal == NULL)
  400. {
  401. return false;
  402. }
  403. jack_info("internal \"%s\" selected", internal_name);
  404. return jackctl_server_load_internal(controller_ptr->server, internal);
  405. }
  406. bool
  407. jack_controller_unload_internal(
  408. struct jack_controller *controller_ptr,
  409. const char * internal_name)
  410. {
  411. jackctl_internal_t *internal;
  412. internal = jack_controller_find_internal(controller_ptr->server, internal_name);
  413. if (internal == NULL)
  414. {
  415. return false;
  416. }
  417. jack_info("internal \"%s\" selected", internal_name);
  418. return jackctl_server_unload_internal(controller_ptr->server, internal);
  419. }
  420. #define controller_ptr ((struct jack_controller *)context)
  421. void
  422. jack_controller_destroy(
  423. void * context)
  424. {
  425. if (controller_ptr->started)
  426. {
  427. jack_controller_stop_server(controller_ptr, NULL);
  428. }
  429. free(controller_ptr->driver_names);
  430. free(controller_ptr->internal_names);
  431. jackctl_server_destroy(controller_ptr->server);
  432. free(controller_ptr);
  433. }