Adjust asciidoc command-line for ladoc-py
[jackdbus.git] / dbus / controller.c
blobf1639b610ac7f1aa7b1aab41302b3d4d3df87f4a
1 /* -*- Mode: C ; c-basic-offset: 4 -*- */
2 /*
3 Copyright (C) 2007,2008,2010,2011 Nedko Arnaudov
4 Copyright (C) 2007-2008 Juuso Alasuutari
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #if defined(HAVE_CONFIG_H)
22 #include "config.h"
23 #endif
25 #include <stdint.h>
26 #include <string.h>
27 #include <dbus/dbus.h>
28 #include <assert.h>
29 #include <unistd.h>
30 #include <errno.h>
32 #include "controller.h"
33 #include "controller_internal.h"
34 #include "xml.h"
35 #include "reserve.h"
36 #include "uptime.h"
38 struct jack_dbus_interface_descriptor * g_jackcontroller_interfaces[] =
40 &g_jack_controller_iface_introspectable,
41 &g_jack_controller_iface_control,
42 &g_jack_controller_iface_configure,
43 &g_jack_controller_iface_patchbay,
44 &g_jack_controller_iface_session_manager,
45 &g_jack_controller_iface_transport,
46 NULL
49 static
50 jackctl_driver_t *
51 jack_controller_find_driver(
52 jackctl_server_t *server,
53 const char *driver_name)
55 const JSList * node_ptr;
57 node_ptr = jackctl_server_get_drivers_list(server);
59 while (node_ptr)
61 if (strcmp(jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data), driver_name) == 0)
63 return node_ptr->data;
66 node_ptr = jack_slist_next(node_ptr);
69 return NULL;
72 static bool jack_controller_check_slave_driver(struct jack_controller * controller_ptr, const char * name)
74 struct list_head * node_ptr;
75 struct jack_controller_slave_driver * driver_ptr;
77 list_for_each(node_ptr, &controller_ptr->slave_drivers)
79 driver_ptr = list_entry(node_ptr, struct jack_controller_slave_driver, siblings);
80 if (strcmp(name, driver_ptr->name) == 0)
82 return true;
86 return false;
89 static bool jack_controller_load_slave_drivers(struct jack_controller * controller_ptr)
91 struct list_head * node_ptr;
92 struct jack_controller_slave_driver * driver_ptr;
94 list_for_each(node_ptr, &controller_ptr->slave_drivers)
96 driver_ptr = list_entry(node_ptr, struct jack_controller_slave_driver, siblings);
98 assert(driver_ptr->handle != NULL);
99 assert(!driver_ptr->loaded);
101 if (!jackctl_server_add_slave(controller_ptr->server, driver_ptr->handle))
103 jack_error("Driver \"%s\" cannot be loaded", driver_ptr->name);
104 return false;
107 driver_ptr->loaded = true;
110 return true;
113 static void jack_controller_unload_slave_drivers(struct jack_controller * controller_ptr)
115 struct list_head * node_ptr;
116 struct jack_controller_slave_driver * driver_ptr;
118 list_for_each(node_ptr, &controller_ptr->slave_drivers)
120 driver_ptr = list_entry(node_ptr, struct jack_controller_slave_driver, siblings);
121 if (driver_ptr->loaded)
123 jackctl_server_remove_slave(controller_ptr->server, driver_ptr->handle);
124 driver_ptr->loaded = false;
129 static void jack_controller_remove_slave_drivers(struct jack_controller * controller_ptr)
131 struct jack_controller_slave_driver * driver_ptr;
133 while (!list_empty(&controller_ptr->slave_drivers))
135 driver_ptr = list_entry(controller_ptr->slave_drivers.next, struct jack_controller_slave_driver, siblings);
136 assert(!driver_ptr->loaded);
137 list_del(&driver_ptr->siblings);
138 free(driver_ptr->name);
139 free(driver_ptr);
142 controller_ptr->slave_drivers_vparam_value.str[0] = 0;
145 static
146 jackctl_internal_t *
147 jack_controller_find_internal(
148 jackctl_server_t *server,
149 const char *internal_name)
151 const JSList * node_ptr;
153 node_ptr = jackctl_server_get_internals_list(server);
155 while (node_ptr)
157 if (strcmp(jackctl_internal_get_name((jackctl_internal_t *)node_ptr->data), internal_name) == 0)
159 return node_ptr->data;
162 node_ptr = jack_slist_next(node_ptr);
165 return NULL;
168 bool
169 jack_controller_select_driver(
170 struct jack_controller * controller_ptr,
171 const char * driver_name)
173 if (!jack_params_set_driver(controller_ptr->params, driver_name))
175 return false;
178 jack_info("driver \"%s\" selected", driver_name);
180 return true;
183 static
185 jack_controller_xrun(void * arg)
187 ((struct jack_controller *)arg)->xruns++;
189 return 0;
192 bool
193 jack_controller_start_server(
194 struct jack_controller * controller_ptr,
195 void *dbus_call_context_ptr)
197 int ret;
199 jack_info("Starting jack server...");
201 assert(!controller_ptr->started); /* should be ensured by caller */
203 controller_ptr->xruns = 0;
205 if (!jackctl_server_open(
206 controller_ptr->server,
207 jack_params_get_driver(controller_ptr->params)))
209 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to open server");
210 goto fail;
213 jack_controller_load_slave_drivers(controller_ptr);
215 if (!jackctl_server_start(
216 controller_ptr->server))
218 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to start server");
219 goto fail_close_server;
222 controller_ptr->client = jack_client_open(
223 "dbusapi",
224 JackNoStartServer,
225 NULL);
226 if (controller_ptr->client == NULL)
228 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to create dbusapi jack client");
229 goto fail_stop_server;
232 ret = jack_set_xrun_callback(controller_ptr->client, jack_controller_xrun, controller_ptr);
233 if (ret != 0)
235 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to set xrun callback. error is %d", ret);
236 goto fail_close_client;
239 if (!jack_controller_patchbay_init(controller_ptr))
241 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to initialize patchbay district");
242 goto fail_close_client;
245 ret = jack_activate(controller_ptr->client);
246 if (ret != 0)
248 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to activate dbusapi jack client. error is %d", ret);
249 goto fail_patchbay_uninit;
252 controller_ptr->started = true;
254 return TRUE;
256 fail_patchbay_uninit:
257 jack_controller_patchbay_uninit(controller_ptr);
259 fail_close_client:
260 ret = jack_client_close(controller_ptr->client);
261 if (ret != 0)
263 jack_error("jack_client_close() failed with error %d", ret);
266 controller_ptr->client = NULL;
268 fail_stop_server:
269 if (!jackctl_server_stop(controller_ptr->server))
271 jack_error("failed to stop jack server");
274 fail_close_server:
275 jack_controller_unload_slave_drivers(controller_ptr);
277 if (!jackctl_server_close(controller_ptr->server))
279 jack_error("failed to close jack server");
282 fail:
283 return FALSE;
286 bool
287 jack_controller_stop_server(
288 struct jack_controller * controller_ptr,
289 void *dbus_call_context_ptr)
291 int ret;
293 pthread_mutex_lock(&controller_ptr->lock);
294 if (!list_empty(&controller_ptr->session_pending_commands))
296 pthread_mutex_unlock(&controller_ptr->lock);
297 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Refusing to stop JACK server because of pending session commands");
298 return false;
300 pthread_mutex_unlock(&controller_ptr->lock);
302 jack_info("Stopping jack server...");
304 assert(controller_ptr->started); /* should be ensured by caller */
306 ret = jack_deactivate(controller_ptr->client);
307 if (ret != 0)
309 jack_error("failed to deactivate dbusapi jack client. error is %d", ret);
312 jack_controller_patchbay_uninit(controller_ptr);
314 ret = jack_client_close(controller_ptr->client);
315 if (ret != 0)
317 jack_error("jack_client_close() failed with error %d", ret);
320 controller_ptr->client = NULL;
322 if (!jackctl_server_stop(controller_ptr->server))
324 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to stop server");
325 return FALSE;
328 jack_controller_unload_slave_drivers(controller_ptr);
330 if (!jackctl_server_close(controller_ptr->server))
332 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to close server");
333 return FALSE;
336 controller_ptr->started = false;
338 return TRUE;
341 bool
342 jack_controller_switch_master(
343 struct jack_controller * controller_ptr,
344 void *dbus_call_context_ptr)
346 assert(controller_ptr->started); /* should be ensured by caller */
348 if (!jackctl_server_switch_master(
349 controller_ptr->server,
350 jack_params_get_driver(controller_ptr->params)))
352 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to switch master");
353 controller_ptr->started = false;
354 return FALSE;
357 return TRUE;
360 #define DEVICE_MAX 2
362 typedef struct reserved_audio_device {
364 char device_name[64];
365 rd_device * reserved_device;
367 } reserved_audio_device;
370 int g_device_count = 0;
371 static reserved_audio_device g_reserved_device[DEVICE_MAX];
373 static
374 bool
375 on_device_acquire(const char * device_name)
377 int ret;
378 DBusError error;
380 dbus_error_init(&error);
382 ret = rd_acquire(
383 &g_reserved_device[g_device_count].reserved_device,
384 g_connection,
385 device_name,
386 "Jack audio server",
387 INT32_MAX,
388 NULL,
389 &error);
390 if (ret < 0)
392 jack_error("Failed to acquire device name : %s error : %s", device_name, (error.message ? error.message : strerror(-ret)));
393 dbus_error_free(&error);
394 return false;
397 strcpy(g_reserved_device[g_device_count].device_name, device_name);
398 g_device_count++;
399 jack_info("Acquired audio card %s", device_name);
400 return true;
403 static
404 void
405 on_device_release(const char * device_name)
407 int i;
409 // Look for corresponding reserved device
410 for (i = 0; i < DEVICE_MAX; i++) {
411 if (strcmp(g_reserved_device[i].device_name, device_name) == 0)
412 break;
415 if (i < DEVICE_MAX) {
416 jack_info("Released audio card %s", device_name);
417 rd_release(g_reserved_device[i].reserved_device);
418 } else {
419 jack_error("Audio card %s not found!!", device_name);
422 g_device_count--;
425 #define controller_ptr ((struct jack_controller *)obj)
427 static bool slave_drivers_parameter_is_set(void * obj)
429 return controller_ptr->slave_drivers_set;
432 static bool slave_drivers_parameter_reset(void * obj)
434 if (controller_ptr->started)
436 jack_error("Cannot modify slave-drivers when server is started");
437 return false;
440 jack_controller_remove_slave_drivers(controller_ptr);
441 controller_ptr->slave_drivers_set = false;
442 return true;
445 static union jackctl_parameter_value slave_drivers_parameter_get_value(void * obj)
447 return controller_ptr->slave_drivers_vparam_value;
450 static bool slave_drivers_parameter_set_value(void * obj, const union jackctl_parameter_value * value_ptr)
452 char * buffer;
453 char * save;
454 const char * token;
455 struct list_head old_list;
456 struct list_head new_list;
457 union jackctl_parameter_value old_value;
458 union jackctl_parameter_value new_value;
459 bool old_set;
461 if (controller_ptr->started)
463 jack_error("Cannot modify slave-drivers when server is started");
464 return false;
467 old_set = controller_ptr->slave_drivers_set;
468 old_value = controller_ptr->slave_drivers_vparam_value;
469 controller_ptr->slave_drivers_vparam_value.str[0] = 0;
470 old_list = controller_ptr->slave_drivers;
471 INIT_LIST_HEAD(&controller_ptr->slave_drivers);
473 buffer = strdup(value_ptr->str);
474 if (buffer == NULL)
476 jack_error("strdup() failed.");
477 return false;
480 token = strtok_r(buffer, ",", &save);
481 while (token)
483 //jack_info("slave driver '%s'", token);
484 if (!jack_controller_add_slave_driver(controller_ptr, token))
486 jack_controller_remove_slave_drivers(controller_ptr);
487 controller_ptr->slave_drivers = old_list;
488 controller_ptr->slave_drivers_vparam_value = old_value;
489 controller_ptr->slave_drivers_set = old_set;
491 free(buffer);
493 return false;
496 token = strtok_r(NULL, ",", &save);
499 new_value = controller_ptr->slave_drivers_vparam_value;
500 new_list = controller_ptr->slave_drivers;
501 controller_ptr->slave_drivers = old_list;
502 jack_controller_remove_slave_drivers(controller_ptr);
503 controller_ptr->slave_drivers_vparam_value = new_value;
504 controller_ptr->slave_drivers = new_list;
505 controller_ptr->slave_drivers_set = true;
507 free(buffer);
509 return true;
512 static union jackctl_parameter_value slave_drivers_parameter_get_default_value(void * obj)
514 union jackctl_parameter_value value;
515 value.str[0] = 0;
516 return value;
519 #undef controller_ptr
521 void *
522 jack_controller_create(
523 DBusConnection *connection)
525 int error;
526 struct jack_controller *controller_ptr;
527 const char * address[PARAM_ADDRESS_SIZE];
528 DBusObjectPathVTable vtable =
530 jack_dbus_message_handler_unregister,
531 jack_dbus_message_handler,
532 NULL
535 controller_ptr = malloc(sizeof(struct jack_controller));
536 if (!controller_ptr)
538 jack_error("Ran out of memory trying to allocate struct jack_controller");
539 goto fail;
542 error = pthread_mutex_init(&controller_ptr->lock, NULL);
543 if (error != 0)
545 jack_error("Failed to initialize mutex. error %d", error);
546 goto fail_free;
549 INIT_LIST_HEAD(&controller_ptr->session_pending_commands);
551 controller_ptr->server = jackctl_server_create2(on_device_acquire, on_device_release, NULL);
552 if (controller_ptr->server == NULL)
554 jack_error("Failed to create server object");
555 goto fail_uninit_mutex;
558 controller_ptr->params = jack_params_create(controller_ptr->server);
559 if (controller_ptr->params == NULL)
561 jack_error("Failed to initialize parameter tree");
562 goto fail_destroy_server;
565 controller_ptr->client = NULL;
566 controller_ptr->started = false;
568 controller_ptr->pending_save = 0;
570 INIT_LIST_HEAD(&controller_ptr->slave_drivers);
571 controller_ptr->slave_drivers_set = false;
572 controller_ptr->slave_drivers_vparam_value.str[0] = 0;
574 controller_ptr->slave_drivers_vparam.obj = controller_ptr;
576 controller_ptr->slave_drivers_vparam.vtable.is_set = slave_drivers_parameter_is_set;
577 controller_ptr->slave_drivers_vparam.vtable.reset = slave_drivers_parameter_reset;
578 controller_ptr->slave_drivers_vparam.vtable.get_value = slave_drivers_parameter_get_value;
579 controller_ptr->slave_drivers_vparam.vtable.set_value = slave_drivers_parameter_set_value;
580 controller_ptr->slave_drivers_vparam.vtable.get_default_value = slave_drivers_parameter_get_default_value;
582 controller_ptr->slave_drivers_vparam.type = JackParamString;
583 controller_ptr->slave_drivers_vparam.name = "slave-drivers";
584 controller_ptr->slave_drivers_vparam.short_decr = "Slave drivers to use";
585 controller_ptr->slave_drivers_vparam.long_descr = "A comma separated list of slave drivers";
586 controller_ptr->slave_drivers_vparam.constraint_flags = 0;
588 address[0] = PTNODE_ENGINE;
589 address[1] = NULL;
590 jack_params_add_parameter(controller_ptr->params, address, true, &controller_ptr->slave_drivers_vparam);
592 controller_ptr->dbus_descriptor.context = controller_ptr;
593 controller_ptr->dbus_descriptor.interfaces = g_jackcontroller_interfaces;
595 if (!dbus_connection_register_object_path(
596 connection,
597 JACK_CONTROLLER_OBJECT_PATH,
598 &vtable,
599 &controller_ptr->dbus_descriptor))
601 jack_error("Ran out of memory trying to register D-Bus object path");
602 goto fail_destroy_params;
605 jack_controller_settings_load(controller_ptr);
607 return controller_ptr;
609 fail_destroy_params:
610 jack_params_destroy(controller_ptr->params);
612 fail_destroy_server:
613 jackctl_server_destroy(controller_ptr->server);
615 fail_uninit_mutex:
616 pthread_mutex_destroy(&controller_ptr->lock);
618 fail_free:
619 free(controller_ptr);
621 fail:
622 return NULL;
625 bool
626 jack_controller_add_slave_driver(
627 struct jack_controller * controller_ptr,
628 const char * driver_name)
630 jackctl_driver_t * driver;
631 struct jack_controller_slave_driver * driver_ptr;
632 size_t len_old;
633 size_t len_new;
635 len_old = strlen(controller_ptr->slave_drivers_vparam_value.str);
636 len_new = strlen(driver_name);
637 if (len_old + len_new + 2 > sizeof(controller_ptr->slave_drivers_vparam_value.str))
639 jack_error("No more space for slave drivers.");
640 return false;
643 driver = jack_controller_find_driver(controller_ptr->server, driver_name);
644 if (driver == NULL)
646 jack_error("Unknown driver \"%s\"", driver_name);
647 return false;
650 if (jack_controller_check_slave_driver(controller_ptr, driver_name))
652 jack_info("Driver \"%s\" is already slave", driver_name);
653 return true;
656 driver_ptr = malloc(sizeof(struct jack_controller_slave_driver));
657 if (driver_ptr == NULL)
659 jack_error("malloc() failed to allocate jack_controller_slave_driver struct");
660 return false;
663 driver_ptr->name = strdup(driver_name);
664 if (driver_ptr->name == NULL)
666 jack_error("strdup() failed for slave driver name \"%s\"", driver_name);
667 free(driver_ptr);
668 return false;
671 driver_ptr->handle = driver;
672 driver_ptr->loaded = false;
674 jack_info("driver \"%s\" set as slave", driver_name);
676 list_add_tail(&driver_ptr->siblings, &controller_ptr->slave_drivers);
678 if (len_old != 0)
680 controller_ptr->slave_drivers_vparam_value.str[len_old++] = ',';
683 memcpy(controller_ptr->slave_drivers_vparam_value.str + len_old, driver_name, len_new + 1);
684 controller_ptr->slave_drivers_set = true;
686 return true;
689 bool
690 jack_controller_remove_slave_driver(
691 struct jack_controller * controller_ptr,
692 const char * driver_name)
694 struct list_head * node_ptr;
695 struct jack_controller_slave_driver * driver_ptr;
697 list_for_each(node_ptr, &controller_ptr->slave_drivers)
699 driver_ptr = list_entry(node_ptr, struct jack_controller_slave_driver, siblings);
700 if (strcmp(driver_ptr->name, driver_name) == 0)
702 list_del(&driver_ptr->siblings);
703 free(driver_ptr->name);
704 free(driver_ptr);
706 /* update the slave-drivers param value */
707 controller_ptr->slave_drivers_vparam_value.str[0] = 0;
708 list_for_each(node_ptr, &controller_ptr->slave_drivers)
710 driver_ptr = list_entry(node_ptr, struct jack_controller_slave_driver, siblings);
711 if (controller_ptr->slave_drivers_vparam_value.str[0] != 0)
713 strcat(controller_ptr->slave_drivers_vparam_value.str, ",");
716 strcat(controller_ptr->slave_drivers_vparam_value.str, driver_ptr->name);
719 jack_info("driver \"%s\" is not slave anymore", driver_name);
721 return true;
725 return false;
728 bool
729 jack_controller_load_internal(
730 struct jack_controller *controller_ptr,
731 const char * internal_name)
733 jackctl_internal_t *internal;
735 internal = jack_controller_find_internal(controller_ptr->server, internal_name);
736 if (internal == NULL)
738 return false;
741 jack_info("internal \"%s\" selected", internal_name);
743 return jackctl_server_load_internal(controller_ptr->server, internal);
746 bool
747 jack_controller_unload_internal(
748 struct jack_controller *controller_ptr,
749 const char * internal_name)
751 jackctl_internal_t *internal;
753 internal = jack_controller_find_internal(controller_ptr->server, internal_name);
754 if (internal == NULL)
756 return false;
759 jack_info("internal \"%s\" selected", internal_name);
761 return jackctl_server_unload_internal(controller_ptr->server, internal);
764 #define controller_ptr ((struct jack_controller *)context)
766 void
767 jack_controller_destroy(
768 void * context)
770 if (controller_ptr->started)
772 while (!jack_controller_stop_server(controller_ptr, NULL))
774 jack_info("jack server failed to stop, retrying in 3 seconds...");
775 usleep(3000000);
779 jack_controller_remove_slave_drivers(controller_ptr);
780 jack_params_destroy(controller_ptr->params);
781 jackctl_server_destroy(controller_ptr->server);
782 pthread_mutex_destroy(&controller_ptr->lock);
783 free(controller_ptr);
786 void
787 jack_controller_run(
788 void * context)
790 long ut;
792 if (controller_ptr->pending_save == 0)
794 return;
797 if ((ut = uptime()) < 0)
799 jack_error(UPTIME_FUNCTION_NAME "() failed with %d", errno);
801 else if (ut < controller_ptr->pending_save + 2) /* delay save by two seconds */
803 return;
806 controller_ptr->pending_save = 0;
807 jack_controller_settings_save_auto(controller_ptr);
810 #undef controller_ptr
812 void
813 jack_controller_pending_save(
814 struct jack_controller * controller_ptr)
816 long ut;
818 if ((ut = uptime()) < 0)
820 jack_error(UPTIME_FUNCTION_NAME "() failed with %d.", errno);
821 controller_ptr->pending_save = 0;
822 jack_controller_settings_save_auto(controller_ptr);
823 return;
826 controller_ptr->pending_save = ut;