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.

879 lines
23KB

  1. /* -*- Mode: C ; c-basic-offset: 4 -*- */
  2. /*
  3. Copyright (C) 2007,2008,2010,2011 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 <assert.h>
  23. #include <unistd.h>
  24. #ifdef __linux__
  25. #include <sys/sysinfo.h>
  26. #elif defined(__APPLE__)
  27. #include <sys/sysctl.h>
  28. #endif
  29. #include <errno.h>
  30. #include "controller.h"
  31. #include "controller_internal.h"
  32. #include "xml.h"
  33. #include "reserve.h"
  34. struct jack_dbus_interface_descriptor * g_jackcontroller_interfaces[] =
  35. {
  36. &g_jack_controller_iface_introspectable,
  37. &g_jack_controller_iface_control,
  38. &g_jack_controller_iface_configure,
  39. &g_jack_controller_iface_patchbay,
  40. &g_jack_controller_iface_session_manager,
  41. &g_jack_controller_iface_transport,
  42. NULL
  43. };
  44. static
  45. jackctl_driver_t *
  46. jack_controller_find_driver(
  47. jackctl_server_t *server,
  48. const char *driver_name)
  49. {
  50. const JSList * node_ptr;
  51. node_ptr = jackctl_server_get_drivers_list(server);
  52. while (node_ptr)
  53. {
  54. if (strcmp(jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data), driver_name) == 0)
  55. {
  56. return node_ptr->data;
  57. }
  58. node_ptr = jack_slist_next(node_ptr);
  59. }
  60. return NULL;
  61. }
  62. static bool jack_controller_check_slave_driver(struct jack_controller * controller_ptr, const char * name)
  63. {
  64. struct list_head * node_ptr;
  65. struct jack_controller_slave_driver * driver_ptr;
  66. list_for_each(node_ptr, &controller_ptr->slave_drivers)
  67. {
  68. driver_ptr = list_entry(node_ptr, struct jack_controller_slave_driver, siblings);
  69. if (strcmp(name, driver_ptr->name) == 0)
  70. {
  71. return true;
  72. }
  73. }
  74. return false;
  75. }
  76. static bool jack_controller_load_slave_drivers(struct jack_controller * controller_ptr)
  77. {
  78. struct list_head * node_ptr;
  79. struct jack_controller_slave_driver * driver_ptr;
  80. list_for_each(node_ptr, &controller_ptr->slave_drivers)
  81. {
  82. driver_ptr = list_entry(node_ptr, struct jack_controller_slave_driver, siblings);
  83. assert(driver_ptr->handle != NULL);
  84. assert(!driver_ptr->loaded);
  85. if (!jackctl_server_add_slave(controller_ptr->server, driver_ptr->handle))
  86. {
  87. jack_error("Driver \"%s\" cannot be loaded", driver_ptr->name);
  88. return false;
  89. }
  90. driver_ptr->loaded = true;
  91. }
  92. return true;
  93. }
  94. static void jack_controller_unload_slave_drivers(struct jack_controller * controller_ptr)
  95. {
  96. struct list_head * node_ptr;
  97. struct jack_controller_slave_driver * driver_ptr;
  98. list_for_each(node_ptr, &controller_ptr->slave_drivers)
  99. {
  100. driver_ptr = list_entry(node_ptr, struct jack_controller_slave_driver, siblings);
  101. if (driver_ptr->loaded)
  102. {
  103. jackctl_server_remove_slave(controller_ptr->server, driver_ptr->handle);
  104. driver_ptr->loaded = false;
  105. }
  106. }
  107. }
  108. static void jack_controller_remove_slave_drivers(struct jack_controller * controller_ptr)
  109. {
  110. struct jack_controller_slave_driver * driver_ptr;
  111. while (!list_empty(&controller_ptr->slave_drivers))
  112. {
  113. driver_ptr = list_entry(controller_ptr->slave_drivers.next, struct jack_controller_slave_driver, siblings);
  114. assert(!driver_ptr->loaded);
  115. list_del(&driver_ptr->siblings);
  116. free(driver_ptr->name);
  117. free(driver_ptr);
  118. }
  119. controller_ptr->slave_drivers_vparam_value.str[0] = 0;
  120. }
  121. static
  122. jackctl_internal_t *
  123. jack_controller_find_internal(
  124. jackctl_server_t *server,
  125. const char *internal_name)
  126. {
  127. const JSList * node_ptr;
  128. node_ptr = jackctl_server_get_internals_list(server);
  129. while (node_ptr)
  130. {
  131. if (strcmp(jackctl_internal_get_name((jackctl_internal_t *)node_ptr->data), internal_name) == 0)
  132. {
  133. return node_ptr->data;
  134. }
  135. node_ptr = jack_slist_next(node_ptr);
  136. }
  137. return NULL;
  138. }
  139. bool
  140. jack_controller_select_driver(
  141. struct jack_controller * controller_ptr,
  142. const char * driver_name)
  143. {
  144. if (!jack_params_set_driver(controller_ptr->params, driver_name))
  145. {
  146. return false;
  147. }
  148. jack_info("driver \"%s\" selected", driver_name);
  149. return true;
  150. }
  151. static
  152. int
  153. jack_controller_xrun(void * arg)
  154. {
  155. ((struct jack_controller *)arg)->xruns++;
  156. return 0;
  157. }
  158. bool
  159. jack_controller_start_server(
  160. struct jack_controller * controller_ptr,
  161. void *dbus_call_context_ptr)
  162. {
  163. int ret;
  164. jack_info("Starting jack server...");
  165. assert(!controller_ptr->started); /* should be ensured by caller */
  166. controller_ptr->xruns = 0;
  167. if (!jackctl_server_open(
  168. controller_ptr->server,
  169. jack_params_get_driver(controller_ptr->params)))
  170. {
  171. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to open server");
  172. goto fail;
  173. }
  174. jack_controller_load_slave_drivers(controller_ptr);
  175. if (!jackctl_server_start(
  176. controller_ptr->server))
  177. {
  178. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to start server");
  179. goto fail_close_server;
  180. }
  181. controller_ptr->client = jack_client_open(
  182. "dbusapi",
  183. JackNoStartServer,
  184. NULL);
  185. if (controller_ptr->client == NULL)
  186. {
  187. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to create dbusapi jack client");
  188. goto fail_stop_server;
  189. }
  190. ret = jack_set_xrun_callback(controller_ptr->client, jack_controller_xrun, controller_ptr);
  191. if (ret != 0)
  192. {
  193. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to set xrun callback. error is %d", ret);
  194. goto fail_close_client;
  195. }
  196. if (!jack_controller_patchbay_init(controller_ptr))
  197. {
  198. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to initialize patchbay district");
  199. goto fail_close_client;
  200. }
  201. ret = jack_activate(controller_ptr->client);
  202. if (ret != 0)
  203. {
  204. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to activate dbusapi jack client. error is %d", ret);
  205. goto fail_patchbay_uninit;
  206. }
  207. controller_ptr->started = true;
  208. return TRUE;
  209. fail_patchbay_uninit:
  210. jack_controller_patchbay_uninit(controller_ptr);
  211. fail_close_client:
  212. ret = jack_client_close(controller_ptr->client);
  213. if (ret != 0)
  214. {
  215. jack_error("jack_client_close() failed with error %d", ret);
  216. }
  217. controller_ptr->client = NULL;
  218. fail_stop_server:
  219. if (!jackctl_server_stop(controller_ptr->server))
  220. {
  221. jack_error("failed to stop jack server");
  222. }
  223. fail_close_server:
  224. jack_controller_unload_slave_drivers(controller_ptr);
  225. if (!jackctl_server_close(controller_ptr->server))
  226. {
  227. jack_error("failed to close jack server");
  228. }
  229. fail:
  230. return FALSE;
  231. }
  232. bool
  233. jack_controller_stop_server(
  234. struct jack_controller * controller_ptr,
  235. void *dbus_call_context_ptr)
  236. {
  237. int ret;
  238. pthread_mutex_lock(&controller_ptr->lock);
  239. if (!list_empty(&controller_ptr->session_pending_commands))
  240. {
  241. pthread_mutex_unlock(&controller_ptr->lock);
  242. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Refusing to stop JACK server because of pending session commands");
  243. return false;
  244. }
  245. pthread_mutex_unlock(&controller_ptr->lock);
  246. jack_info("Stopping jack server...");
  247. assert(controller_ptr->started); /* should be ensured by caller */
  248. ret = jack_deactivate(controller_ptr->client);
  249. if (ret != 0)
  250. {
  251. jack_error("failed to deactivate dbusapi jack client. error is %d", ret);
  252. }
  253. jack_controller_patchbay_uninit(controller_ptr);
  254. ret = jack_client_close(controller_ptr->client);
  255. if (ret != 0)
  256. {
  257. jack_error("jack_client_close() failed with error %d", ret);
  258. }
  259. controller_ptr->client = NULL;
  260. if (!jackctl_server_stop(controller_ptr->server))
  261. {
  262. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to stop server");
  263. return FALSE;
  264. }
  265. jack_controller_unload_slave_drivers(controller_ptr);
  266. if (!jackctl_server_close(controller_ptr->server))
  267. {
  268. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to close server");
  269. return FALSE;
  270. }
  271. controller_ptr->started = false;
  272. return TRUE;
  273. }
  274. bool
  275. jack_controller_switch_master(
  276. struct jack_controller * controller_ptr,
  277. void *dbus_call_context_ptr)
  278. {
  279. assert(controller_ptr->started); /* should be ensured by caller */
  280. if (!jackctl_server_switch_master(
  281. controller_ptr->server,
  282. jack_params_get_driver(controller_ptr->params)))
  283. {
  284. jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to switch master");
  285. controller_ptr->started = false;
  286. return FALSE;
  287. }
  288. return TRUE;
  289. }
  290. #define DEVICE_MAX 2
  291. typedef struct reserved_audio_device {
  292. char device_name[64];
  293. rd_device * reserved_device;
  294. } reserved_audio_device;
  295. int g_device_count = 0;
  296. static reserved_audio_device g_reserved_device[DEVICE_MAX];
  297. static
  298. bool
  299. on_device_acquire(const char * device_name)
  300. {
  301. int ret;
  302. DBusError error;
  303. dbus_error_init(&error);
  304. ret = rd_acquire(
  305. &g_reserved_device[g_device_count].reserved_device,
  306. g_connection,
  307. device_name,
  308. "Jack audio server",
  309. INT32_MAX,
  310. NULL,
  311. &error);
  312. if (ret < 0)
  313. {
  314. jack_error("Failed to acquire device name : %s error : %s", device_name, (error.message ? error.message : strerror(-ret)));
  315. dbus_error_free(&error);
  316. return false;
  317. }
  318. strcpy(g_reserved_device[g_device_count].device_name, device_name);
  319. g_device_count++;
  320. jack_info("Acquired audio card %s", device_name);
  321. return true;
  322. }
  323. static
  324. void
  325. on_device_release(const char * device_name)
  326. {
  327. int i;
  328. // Look for corresponding reserved device
  329. for (i = 0; i < DEVICE_MAX; i++) {
  330. if (strcmp(g_reserved_device[i].device_name, device_name) == 0)
  331. break;
  332. }
  333. if (i < DEVICE_MAX) {
  334. jack_info("Released audio card %s", device_name);
  335. rd_release(g_reserved_device[i].reserved_device);
  336. } else {
  337. jack_error("Audio card %s not found!!", device_name);
  338. }
  339. g_device_count--;
  340. }
  341. #define controller_ptr ((struct jack_controller *)obj)
  342. static bool slave_drivers_parameter_is_set(void * obj)
  343. {
  344. return controller_ptr->slave_drivers_set;
  345. }
  346. static bool slave_drivers_parameter_reset(void * obj)
  347. {
  348. if (controller_ptr->started)
  349. {
  350. jack_error("Cannot modify slave-drivers when server is started");
  351. return false;
  352. }
  353. jack_controller_remove_slave_drivers(controller_ptr);
  354. controller_ptr->slave_drivers_set = false;
  355. return true;
  356. }
  357. static union jackctl_parameter_value slave_drivers_parameter_get_value(void * obj)
  358. {
  359. return controller_ptr->slave_drivers_vparam_value;
  360. }
  361. static bool slave_drivers_parameter_set_value(void * obj, const union jackctl_parameter_value * value_ptr)
  362. {
  363. char * buffer;
  364. char * save;
  365. const char * token;
  366. struct list_head old_list;
  367. struct list_head new_list;
  368. union jackctl_parameter_value old_value;
  369. union jackctl_parameter_value new_value;
  370. bool old_set;
  371. if (controller_ptr->started)
  372. {
  373. jack_error("Cannot modify slave-drivers when server is started");
  374. return false;
  375. }
  376. old_set = controller_ptr->slave_drivers_set;
  377. old_value = controller_ptr->slave_drivers_vparam_value;
  378. controller_ptr->slave_drivers_vparam_value.str[0] = 0;
  379. old_list = controller_ptr->slave_drivers;
  380. INIT_LIST_HEAD(&controller_ptr->slave_drivers);
  381. buffer = strdup(value_ptr->str);
  382. if (buffer == NULL)
  383. {
  384. jack_error("strdup() failed.");
  385. return false;
  386. }
  387. token = strtok_r(buffer, ",", &save);
  388. while (token)
  389. {
  390. //jack_info("slave driver '%s'", token);
  391. if (!jack_controller_add_slave_driver(controller_ptr, token))
  392. {
  393. jack_controller_remove_slave_drivers(controller_ptr);
  394. controller_ptr->slave_drivers = old_list;
  395. controller_ptr->slave_drivers_vparam_value = old_value;
  396. controller_ptr->slave_drivers_set = old_set;
  397. free(buffer);
  398. return false;
  399. }
  400. token = strtok_r(NULL, ",", &save);
  401. }
  402. new_value = controller_ptr->slave_drivers_vparam_value;
  403. new_list = controller_ptr->slave_drivers;
  404. controller_ptr->slave_drivers = old_list;
  405. jack_controller_remove_slave_drivers(controller_ptr);
  406. controller_ptr->slave_drivers_vparam_value = new_value;
  407. controller_ptr->slave_drivers = new_list;
  408. controller_ptr->slave_drivers_set = true;
  409. free(buffer);
  410. return true;
  411. }
  412. static union jackctl_parameter_value slave_drivers_parameter_get_default_value(void * obj)
  413. {
  414. union jackctl_parameter_value value;
  415. value.str[0] = 0;
  416. return value;
  417. }
  418. #undef controller_ptr
  419. void *
  420. jack_controller_create(
  421. DBusConnection *connection)
  422. {
  423. int error;
  424. struct jack_controller *controller_ptr;
  425. const char * address[PARAM_ADDRESS_SIZE];
  426. DBusObjectPathVTable vtable =
  427. {
  428. jack_dbus_message_handler_unregister,
  429. jack_dbus_message_handler,
  430. NULL
  431. };
  432. controller_ptr = malloc(sizeof(struct jack_controller));
  433. if (!controller_ptr)
  434. {
  435. jack_error("Ran out of memory trying to allocate struct jack_controller");
  436. goto fail;
  437. }
  438. error = pthread_mutex_init(&controller_ptr->lock, NULL);
  439. if (error != 0)
  440. {
  441. jack_error("Failed to initialize mutex. error %d", error);
  442. goto fail_free;
  443. }
  444. INIT_LIST_HEAD(&controller_ptr->session_pending_commands);
  445. controller_ptr->server = jackctl_server_create(on_device_acquire, on_device_release);
  446. if (controller_ptr->server == NULL)
  447. {
  448. jack_error("Failed to create server object");
  449. goto fail_uninit_mutex;
  450. }
  451. controller_ptr->params = jack_params_create(controller_ptr->server);
  452. if (controller_ptr->params == NULL)
  453. {
  454. jack_error("Failed to initialize parameter tree");
  455. goto fail_destroy_server;
  456. }
  457. controller_ptr->client = NULL;
  458. controller_ptr->started = false;
  459. controller_ptr->pending_save = 0;
  460. INIT_LIST_HEAD(&controller_ptr->slave_drivers);
  461. controller_ptr->slave_drivers_set = false;
  462. controller_ptr->slave_drivers_vparam_value.str[0] = 0;
  463. controller_ptr->slave_drivers_vparam.obj = controller_ptr;
  464. controller_ptr->slave_drivers_vparam.vtable.is_set = slave_drivers_parameter_is_set;
  465. controller_ptr->slave_drivers_vparam.vtable.reset = slave_drivers_parameter_reset;
  466. controller_ptr->slave_drivers_vparam.vtable.get_value = slave_drivers_parameter_get_value;
  467. controller_ptr->slave_drivers_vparam.vtable.set_value = slave_drivers_parameter_set_value;
  468. controller_ptr->slave_drivers_vparam.vtable.get_default_value = slave_drivers_parameter_get_default_value;
  469. controller_ptr->slave_drivers_vparam.type = JackParamString;
  470. controller_ptr->slave_drivers_vparam.name = "slave-drivers";
  471. controller_ptr->slave_drivers_vparam.short_decr = "Slave drivers to use";
  472. controller_ptr->slave_drivers_vparam.long_descr = "A comma separated list of slave drivers";
  473. controller_ptr->slave_drivers_vparam.constraint_flags = 0;
  474. address[0] = PTNODE_ENGINE;
  475. address[1] = NULL;
  476. jack_params_add_parameter(controller_ptr->params, address, true, &controller_ptr->slave_drivers_vparam);
  477. controller_ptr->dbus_descriptor.context = controller_ptr;
  478. controller_ptr->dbus_descriptor.interfaces = g_jackcontroller_interfaces;
  479. if (!dbus_connection_register_object_path(
  480. connection,
  481. JACK_CONTROLLER_OBJECT_PATH,
  482. &vtable,
  483. &controller_ptr->dbus_descriptor))
  484. {
  485. jack_error("Ran out of memory trying to register D-Bus object path");
  486. goto fail_destroy_params;
  487. }
  488. jack_controller_settings_load(controller_ptr);
  489. return controller_ptr;
  490. fail_destroy_params:
  491. jack_params_destroy(controller_ptr->params);
  492. fail_destroy_server:
  493. jackctl_server_destroy(controller_ptr->server);
  494. fail_uninit_mutex:
  495. pthread_mutex_destroy(&controller_ptr->lock);
  496. fail_free:
  497. free(controller_ptr);
  498. fail:
  499. return NULL;
  500. }
  501. bool
  502. jack_controller_add_slave_driver(
  503. struct jack_controller * controller_ptr,
  504. const char * driver_name)
  505. {
  506. jackctl_driver_t * driver;
  507. struct jack_controller_slave_driver * driver_ptr;
  508. size_t len_old;
  509. size_t len_new;
  510. len_old = strlen(controller_ptr->slave_drivers_vparam_value.str);
  511. len_new = strlen(driver_name);
  512. if (len_old + len_new + 2 > sizeof(controller_ptr->slave_drivers_vparam_value.str))
  513. {
  514. jack_error("No more space for slave drivers.");
  515. return false;
  516. }
  517. driver = jack_controller_find_driver(controller_ptr->server, driver_name);
  518. if (driver == NULL)
  519. {
  520. jack_error("Unknown driver \"%s\"", driver_name);
  521. return false;
  522. }
  523. if (jack_controller_check_slave_driver(controller_ptr, driver_name))
  524. {
  525. jack_info("Driver \"%s\" is already slave", driver_name);
  526. return true;
  527. }
  528. driver_ptr = malloc(sizeof(struct jack_controller_slave_driver));
  529. if (driver_ptr == NULL)
  530. {
  531. jack_error("malloc() failed to allocate jack_controller_slave_driver struct");
  532. return false;
  533. }
  534. driver_ptr->name = strdup(driver_name);
  535. if (driver_ptr->name == NULL)
  536. {
  537. jack_error("strdup() failed for slave driver name \"%s\"", driver_name);
  538. free(driver_ptr);
  539. return false;
  540. }
  541. driver_ptr->handle = driver;
  542. driver_ptr->loaded = false;
  543. jack_info("driver \"%s\" set as slave", driver_name);
  544. list_add_tail(&driver_ptr->siblings, &controller_ptr->slave_drivers);
  545. if (len_old != 0)
  546. {
  547. controller_ptr->slave_drivers_vparam_value.str[len_old++] = ',';
  548. }
  549. memcpy(controller_ptr->slave_drivers_vparam_value.str + len_old, driver_name, len_new + 1);
  550. controller_ptr->slave_drivers_set = true;
  551. return true;
  552. }
  553. bool
  554. jack_controller_remove_slave_driver(
  555. struct jack_controller * controller_ptr,
  556. const char * driver_name)
  557. {
  558. struct list_head * node_ptr;
  559. struct jack_controller_slave_driver * driver_ptr;
  560. list_for_each(node_ptr, &controller_ptr->slave_drivers)
  561. {
  562. driver_ptr = list_entry(node_ptr, struct jack_controller_slave_driver, siblings);
  563. if (strcmp(driver_ptr->name, driver_name) == 0)
  564. {
  565. list_del(&driver_ptr->siblings);
  566. free(driver_ptr->name);
  567. free(driver_ptr);
  568. /* update the slave-drivers param value */
  569. controller_ptr->slave_drivers_vparam_value.str[0] = 0;
  570. list_for_each(node_ptr, &controller_ptr->slave_drivers)
  571. {
  572. driver_ptr = list_entry(node_ptr, struct jack_controller_slave_driver, siblings);
  573. if (controller_ptr->slave_drivers_vparam_value.str[0] != 0)
  574. {
  575. strcat(controller_ptr->slave_drivers_vparam_value.str, ",");
  576. }
  577. strcat(controller_ptr->slave_drivers_vparam_value.str, driver_ptr->name);
  578. }
  579. jack_info("driver \"%s\" is not slave anymore", driver_name);
  580. return true;
  581. }
  582. }
  583. return false;
  584. }
  585. bool
  586. jack_controller_load_internal(
  587. struct jack_controller *controller_ptr,
  588. const char * internal_name)
  589. {
  590. jackctl_internal_t *internal;
  591. internal = jack_controller_find_internal(controller_ptr->server, internal_name);
  592. if (internal == NULL)
  593. {
  594. return false;
  595. }
  596. jack_info("internal \"%s\" selected", internal_name);
  597. return jackctl_server_load_internal(controller_ptr->server, internal);
  598. }
  599. bool
  600. jack_controller_unload_internal(
  601. struct jack_controller *controller_ptr,
  602. const char * internal_name)
  603. {
  604. jackctl_internal_t *internal;
  605. internal = jack_controller_find_internal(controller_ptr->server, internal_name);
  606. if (internal == NULL)
  607. {
  608. return false;
  609. }
  610. jack_info("internal \"%s\" selected", internal_name);
  611. return jackctl_server_unload_internal(controller_ptr->server, internal);
  612. }
  613. #define controller_ptr ((struct jack_controller *)context)
  614. void
  615. jack_controller_destroy(
  616. void * context)
  617. {
  618. if (controller_ptr->started)
  619. {
  620. while (!jack_controller_stop_server(controller_ptr, NULL))
  621. {
  622. jack_info("jack server failed to stop, retrying in 3 seconds...");
  623. usleep(3000000);
  624. }
  625. }
  626. jack_controller_remove_slave_drivers(controller_ptr);
  627. jack_params_destroy(controller_ptr->params);
  628. jackctl_server_destroy(controller_ptr->server);
  629. pthread_mutex_destroy(&controller_ptr->lock);
  630. free(controller_ptr);
  631. }
  632. void
  633. jack_controller_run(
  634. void * context)
  635. {
  636. #ifdef __linux__
  637. struct sysinfo si;
  638. #elif defined(__APPLE__)
  639. int mib[2];
  640. size_t size;
  641. struct timeval boottime;
  642. mib[0] = CTL_KERN;
  643. mib[1] = KERN_BOOTTIME;
  644. size = sizeof(boottime);
  645. #endif
  646. if (controller_ptr->pending_save == 0)
  647. {
  648. return;
  649. }
  650. #ifdef __linux__
  651. if (sysinfo(&si) != 0)
  652. {
  653. jack_error("sysinfo() failed with %d", errno);
  654. }
  655. else if (si.uptime < controller_ptr->pending_save + 2) /* delay save by two seconds */
  656. {
  657. return;
  658. }
  659. #elif defined(__APPLE__)
  660. if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1)
  661. {
  662. jack_error("sysctl() failed with %d", errno);
  663. }
  664. else if (boottime.tv_sec < controller_ptr->pending_save + 2) /* delay save by two seconds */
  665. {
  666. return;
  667. }
  668. #endif
  669. controller_ptr->pending_save = 0;
  670. jack_controller_settings_save_auto(controller_ptr);
  671. }
  672. #undef controller_ptr
  673. void
  674. jack_controller_pending_save(
  675. struct jack_controller * controller_ptr)
  676. {
  677. #ifdef __linux__
  678. struct sysinfo si;
  679. #elif defined(__APPLE__)
  680. int mib[2];
  681. size_t size;
  682. struct timeval boottime;
  683. mib[0] = CTL_KERN;
  684. mib[1] = KERN_BOOTTIME;
  685. size = sizeof(boottime);
  686. #endif
  687. #ifdef __linux__
  688. if (sysinfo(&si) != 0)
  689. #elif defined(__APPLE__)
  690. if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1)
  691. #endif
  692. {
  693. #ifdef __linux__
  694. jack_error("sysinfo() failed with %d.", errno);
  695. #elif defined(__APPLE__)
  696. jack_error("sysctl() failed with %d.", errno);
  697. #endif
  698. controller_ptr->pending_save = 0;
  699. jack_controller_settings_save_auto(controller_ptr);
  700. return;
  701. }
  702. #ifdef __linux__
  703. controller_ptr->pending_save = si.uptime;
  704. #elif defined(__APPLE__)
  705. controller_ptr->pending_save = boottime.tv_sec;
  706. #endif
  707. }