jackdbus: implement session command queue
[jack2.git] / dbus / controller.c
blob14d28e5cf994b402dc0cd586998f2f572c854030
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>
31 #include "controller.h"
32 #include "controller_internal.h"
33 #include "xml.h"
34 #include "reserve.h"
36 struct jack_dbus_interface_descriptor * g_jackcontroller_interfaces[] =
38 &g_jack_controller_iface_introspectable,
39 &g_jack_controller_iface_control,
40 &g_jack_controller_iface_configure,
41 &g_jack_controller_iface_patchbay,
42 &g_jack_controller_iface_session_manager,
43 &g_jack_controller_iface_transport,
44 NULL
47 static
48 jackctl_driver_t *
49 jack_controller_find_driver(
50 jackctl_server_t *server,
51 const char *driver_name)
53 const JSList * node_ptr;
55 node_ptr = jackctl_server_get_drivers_list(server);
57 while (node_ptr)
59 if (strcmp(jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data), driver_name) == 0)
61 return node_ptr->data;
64 node_ptr = jack_slist_next(node_ptr);
67 return NULL;
70 static bool jack_controller_check_slave_driver(struct jack_controller * controller_ptr, const char * name)
72 struct list_head * node_ptr;
73 struct jack_controller_slave_driver * driver_ptr;
75 list_for_each(node_ptr, &controller_ptr->slave_drivers)
77 driver_ptr = list_entry(node_ptr, struct jack_controller_slave_driver, siblings);
78 if (strcmp(name, driver_ptr->name) == 0)
80 return true;
84 return false;
87 static bool jack_controller_load_slave_drivers(struct jack_controller * controller_ptr)
89 struct list_head * node_ptr;
90 struct jack_controller_slave_driver * driver_ptr;
92 list_for_each(node_ptr, &controller_ptr->slave_drivers)
94 driver_ptr = list_entry(node_ptr, struct jack_controller_slave_driver, siblings);
96 assert(driver_ptr->handle != NULL);
97 assert(!driver_ptr->loaded);
99 if (!jackctl_server_add_slave(controller_ptr->server, driver_ptr->handle))
101 jack_error("Driver \"%s\" cannot be loaded", driver_ptr->name);
102 return false;
105 driver_ptr->loaded = true;
108 return true;
111 static void jack_controller_unload_slave_drivers(struct jack_controller * controller_ptr)
113 struct list_head * node_ptr;
114 struct jack_controller_slave_driver * driver_ptr;
116 list_for_each(node_ptr, &controller_ptr->slave_drivers)
118 driver_ptr = list_entry(node_ptr, struct jack_controller_slave_driver, siblings);
119 if (driver_ptr->loaded)
121 jackctl_server_remove_slave(controller_ptr->server, driver_ptr->handle);
122 driver_ptr->loaded = false;
127 static void jack_controller_remove_slave_drivers(struct jack_controller * controller_ptr)
129 struct jack_controller_slave_driver * driver_ptr;
131 while (!list_empty(&controller_ptr->slave_drivers))
133 driver_ptr = list_entry(controller_ptr->slave_drivers.next, struct jack_controller_slave_driver, siblings);
134 assert(!driver_ptr->loaded);
135 list_del(&driver_ptr->siblings);
136 free(driver_ptr->name);
137 free(driver_ptr);
140 controller_ptr->slave_drivers_vparam_value.str[0] = 0;
143 static
144 jackctl_internal_t *
145 jack_controller_find_internal(
146 jackctl_server_t *server,
147 const char *internal_name)
149 const JSList * node_ptr;
151 node_ptr = jackctl_server_get_internals_list(server);
153 while (node_ptr)
155 if (strcmp(jackctl_internal_get_name((jackctl_internal_t *)node_ptr->data), internal_name) == 0)
157 return node_ptr->data;
160 node_ptr = jack_slist_next(node_ptr);
163 return NULL;
166 bool
167 jack_controller_select_driver(
168 struct jack_controller * controller_ptr,
169 const char * driver_name)
171 if (!jack_params_set_driver(controller_ptr->params, driver_name))
173 return false;
176 jack_info("driver \"%s\" selected", driver_name);
178 return true;
181 static
183 jack_controller_xrun(void * arg)
185 ((struct jack_controller *)arg)->xruns++;
187 return 0;
190 bool
191 jack_controller_start_server(
192 struct jack_controller * controller_ptr,
193 void *dbus_call_context_ptr)
195 int ret;
197 jack_info("Starting jack server...");
199 assert(!controller_ptr->started); /* should be ensured by caller */
201 controller_ptr->xruns = 0;
203 if (!jackctl_server_open(
204 controller_ptr->server,
205 jack_params_get_driver(controller_ptr->params)))
207 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to open server");
208 goto fail;
211 jack_controller_load_slave_drivers(controller_ptr);
213 if (!jackctl_server_start(
214 controller_ptr->server))
216 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to start server");
217 goto fail_close_server;
220 controller_ptr->client = jack_client_open(
221 "dbusapi",
222 JackNoStartServer,
223 NULL);
224 if (controller_ptr->client == NULL)
226 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to create dbusapi jack client");
227 goto fail_stop_server;
230 ret = jack_set_xrun_callback(controller_ptr->client, jack_controller_xrun, controller_ptr);
231 if (ret != 0)
233 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to set xrun callback. error is %d", ret);
234 goto fail_close_client;
237 if (!jack_controller_patchbay_init(controller_ptr))
239 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to initialize patchbay district");
240 goto fail_close_client;
243 ret = jack_activate(controller_ptr->client);
244 if (ret != 0)
246 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "failed to activate dbusapi jack client. error is %d", ret);
247 goto fail_patchbay_uninit;
250 controller_ptr->started = true;
252 return TRUE;
254 fail_patchbay_uninit:
255 jack_controller_patchbay_uninit(controller_ptr);
257 fail_close_client:
258 ret = jack_client_close(controller_ptr->client);
259 if (ret != 0)
261 jack_error("jack_client_close() failed with error %d", ret);
264 controller_ptr->client = NULL;
266 fail_stop_server:
267 if (!jackctl_server_stop(controller_ptr->server))
269 jack_error("failed to stop jack server");
272 fail_close_server:
273 jack_controller_unload_slave_drivers(controller_ptr);
275 if (!jackctl_server_close(controller_ptr->server))
277 jack_error("failed to close jack server");
280 fail:
281 return FALSE;
284 bool
285 jack_controller_stop_server(
286 struct jack_controller * controller_ptr,
287 void *dbus_call_context_ptr)
289 int ret;
291 pthread_mutex_lock(&controller_ptr->lock);
292 if (!list_empty(&controller_ptr->session_pending_commands))
294 pthread_mutex_unlock(&controller_ptr->lock);
295 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Refusing to stop JACK server because of pending session commands");
296 return false;
298 pthread_mutex_unlock(&controller_ptr->lock);
300 jack_info("Stopping jack server...");
302 assert(controller_ptr->started); /* should be ensured by caller */
304 ret = jack_deactivate(controller_ptr->client);
305 if (ret != 0)
307 jack_error("failed to deactivate dbusapi jack client. error is %d", ret);
310 jack_controller_patchbay_uninit(controller_ptr);
312 ret = jack_client_close(controller_ptr->client);
313 if (ret != 0)
315 jack_error("jack_client_close() failed with error %d", ret);
318 controller_ptr->client = NULL;
320 if (!jackctl_server_stop(controller_ptr->server))
322 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to stop server");
323 return FALSE;
326 jack_controller_unload_slave_drivers(controller_ptr);
328 if (!jackctl_server_close(controller_ptr->server))
330 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to close server");
331 return FALSE;
334 controller_ptr->started = false;
336 return TRUE;
339 bool
340 jack_controller_switch_master(
341 struct jack_controller * controller_ptr,
342 void *dbus_call_context_ptr)
344 assert(controller_ptr->started); /* should be ensured by caller */
346 if (!jackctl_server_switch_master(
347 controller_ptr->server,
348 jack_params_get_driver(controller_ptr->params)))
350 jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to switch master");
351 controller_ptr->started = false;
352 return FALSE;
355 return TRUE;
358 #define DEVICE_MAX 2
360 typedef struct reserved_audio_device {
362 char device_name[64];
363 rd_device * reserved_device;
365 } reserved_audio_device;
368 int g_device_count = 0;
369 static reserved_audio_device g_reserved_device[DEVICE_MAX];
371 static
372 bool
373 on_device_acquire(const char * device_name)
375 int ret;
376 DBusError error;
378 ret = rd_acquire(
379 &g_reserved_device[g_device_count].reserved_device,
380 g_connection,
381 device_name,
382 "Jack audio server",
383 INT32_MAX,
384 NULL,
385 &error);
386 if (ret < 0)
388 jack_error("Failed to acquire device name : %s error : %s", device_name, (error.message ? error.message : strerror(-ret)));
389 return false;
392 strcpy(g_reserved_device[g_device_count].device_name, device_name);
393 g_device_count++;
394 jack_info("Acquired audio card %s", device_name);
395 return true;
398 static
399 void
400 on_device_release(const char * device_name)
402 int i;
404 // Look for corresponding reserved device
405 for (i = 0; i < DEVICE_MAX; i++) {
406 if (strcmp(g_reserved_device[i].device_name, device_name) == 0)
407 break;
410 if (i < DEVICE_MAX) {
411 jack_info("Released audio card %s", device_name);
412 rd_release(g_reserved_device[i].reserved_device);
413 } else {
414 jack_error("Audio card %s not found!!", device_name);
417 g_device_count--;
420 #define controller_ptr ((struct jack_controller *)obj)
422 static bool slave_drivers_parameter_is_set(void * obj)
424 return controller_ptr->slave_drivers_set;
427 static bool slave_drivers_parameter_reset(void * obj)
429 if (controller_ptr->started)
431 jack_error("Cannot modify slave-drivers when server is started");
432 return false;
435 jack_controller_remove_slave_drivers(controller_ptr);
436 controller_ptr->slave_drivers_set = false;
437 return true;
440 static union jackctl_parameter_value slave_drivers_parameter_get_value(void * obj)
442 return controller_ptr->slave_drivers_vparam_value;
445 static bool slave_drivers_parameter_set_value(void * obj, const union jackctl_parameter_value * value_ptr)
447 char * buffer;
448 char * save;
449 const char * token;
450 struct list_head old_list;
451 struct list_head new_list;
452 union jackctl_parameter_value old_value;
453 union jackctl_parameter_value new_value;
454 bool old_set;
456 if (controller_ptr->started)
458 jack_error("Cannot modify slave-drivers when server is started");
459 return false;
462 old_set = controller_ptr->slave_drivers_set;
463 old_value = controller_ptr->slave_drivers_vparam_value;
464 controller_ptr->slave_drivers_vparam_value.str[0] = 0;
465 old_list = controller_ptr->slave_drivers;
466 INIT_LIST_HEAD(&controller_ptr->slave_drivers);
468 buffer = strdup(value_ptr->str);
469 if (buffer == NULL)
471 jack_error("strdup() failed.");
472 return false;
475 token = strtok_r(buffer, ",", &save);
476 while (token)
478 //jack_info("slave driver '%s'", token);
479 if (!jack_controller_add_slave_driver(controller_ptr, token))
481 jack_controller_remove_slave_drivers(controller_ptr);
482 controller_ptr->slave_drivers = old_list;
483 controller_ptr->slave_drivers_vparam_value = old_value;
484 controller_ptr->slave_drivers_set = old_set;
486 free(buffer);
488 return false;
491 token = strtok_r(NULL, ",", &save);
494 new_value = controller_ptr->slave_drivers_vparam_value;
495 new_list = controller_ptr->slave_drivers;
496 controller_ptr->slave_drivers = old_list;
497 jack_controller_remove_slave_drivers(controller_ptr);
498 controller_ptr->slave_drivers_vparam_value = new_value;
499 controller_ptr->slave_drivers = new_list;
500 controller_ptr->slave_drivers_set = true;
502 free(buffer);
504 return true;
507 static union jackctl_parameter_value slave_drivers_parameter_get_default_value(void * obj)
509 union jackctl_parameter_value value;
510 value.str[0] = 0;
511 return value;
514 #undef controller_ptr
516 void *
517 jack_controller_create(
518 DBusConnection *connection)
520 int error;
521 struct jack_controller *controller_ptr;
522 const char * address[PARAM_ADDRESS_SIZE];
523 DBusObjectPathVTable vtable =
525 jack_dbus_message_handler_unregister,
526 jack_dbus_message_handler,
527 NULL
530 controller_ptr = malloc(sizeof(struct jack_controller));
531 if (!controller_ptr)
533 jack_error("Ran out of memory trying to allocate struct jack_controller");
534 goto fail;
537 error = pthread_mutex_init(&controller_ptr->lock, NULL);
538 if (error != 0)
540 jack_error("Failed to initialize mutex. error %d", error);
541 goto fail_free;
544 INIT_LIST_HEAD(&controller_ptr->session_pending_commands);
546 controller_ptr->server = jackctl_server_create(on_device_acquire, on_device_release);
547 if (controller_ptr->server == NULL)
549 jack_error("Failed to create server object");
550 goto fail_uninit_mutex;
553 controller_ptr->params = jack_params_create(controller_ptr->server);
554 if (controller_ptr->params == NULL)
556 jack_error("Failed to initialize parameter tree");
557 goto fail_destroy_server;
560 controller_ptr->client = NULL;
561 controller_ptr->started = false;
563 INIT_LIST_HEAD(&controller_ptr->slave_drivers);
564 controller_ptr->slave_drivers_set = false;
565 controller_ptr->slave_drivers_vparam_value.str[0] = 0;
567 controller_ptr->slave_drivers_vparam.obj = controller_ptr;
569 controller_ptr->slave_drivers_vparam.vtable.is_set = slave_drivers_parameter_is_set;
570 controller_ptr->slave_drivers_vparam.vtable.reset = slave_drivers_parameter_reset;
571 controller_ptr->slave_drivers_vparam.vtable.get_value = slave_drivers_parameter_get_value;
572 controller_ptr->slave_drivers_vparam.vtable.set_value = slave_drivers_parameter_set_value;
573 controller_ptr->slave_drivers_vparam.vtable.get_default_value = slave_drivers_parameter_get_default_value;
575 controller_ptr->slave_drivers_vparam.type = JackParamString;
576 controller_ptr->slave_drivers_vparam.name = "slave-drivers";
577 controller_ptr->slave_drivers_vparam.short_decr = "Slave drivers to use";
578 controller_ptr->slave_drivers_vparam.long_descr = "A comma separated list of slave drivers";
579 controller_ptr->slave_drivers_vparam.constraint_flags = 0;
581 address[0] = PTNODE_ENGINE;
582 address[1] = NULL;
583 jack_params_add_parameter(controller_ptr->params, address, true, &controller_ptr->slave_drivers_vparam);
585 controller_ptr->dbus_descriptor.context = controller_ptr;
586 controller_ptr->dbus_descriptor.interfaces = g_jackcontroller_interfaces;
588 if (!dbus_connection_register_object_path(
589 connection,
590 JACK_CONTROLLER_OBJECT_PATH,
591 &vtable,
592 &controller_ptr->dbus_descriptor))
594 jack_error("Ran out of memory trying to register D-Bus object path");
595 goto fail_destroy_params;
598 jack_controller_settings_load(controller_ptr);
600 return controller_ptr;
602 fail_destroy_params:
603 jack_params_destroy(controller_ptr->params);
605 fail_destroy_server:
606 jackctl_server_destroy(controller_ptr->server);
608 fail_uninit_mutex:
609 pthread_mutex_destroy(&controller_ptr->lock);
611 fail_free:
612 free(controller_ptr);
614 fail:
615 return NULL;
618 bool
619 jack_controller_add_slave_driver(
620 struct jack_controller * controller_ptr,
621 const char * driver_name)
623 jackctl_driver_t * driver;
624 struct jack_controller_slave_driver * driver_ptr;
625 size_t len_old;
626 size_t len_new;
628 len_old = strlen(controller_ptr->slave_drivers_vparam_value.str);
629 len_new = strlen(driver_name);
630 if (len_old + len_new + 2 > sizeof(controller_ptr->slave_drivers_vparam_value.str))
632 jack_error("No more space for slave drivers.");
633 return false;
636 driver = jack_controller_find_driver(controller_ptr->server, driver_name);
637 if (driver == NULL)
639 jack_error("Unknown driver \"%s\"", driver_name);
640 return false;
643 if (jack_controller_check_slave_driver(controller_ptr, driver_name))
645 jack_info("Driver \"%s\" is already slave", driver_name);
646 return true;
649 driver_ptr = malloc(sizeof(struct jack_controller_slave_driver));
650 if (driver_ptr == NULL)
652 jack_error("malloc() failed to allocate jack_controller_slave_driver struct");
653 return false;
656 driver_ptr->name = strdup(driver_name);
657 if (driver_ptr->name == NULL)
659 jack_error("strdup() failed for slave driver name \"%s\"", driver_name);
660 free(driver_ptr);
661 return false;
664 driver_ptr->handle = driver;
665 driver_ptr->loaded = false;
667 jack_info("driver \"%s\" set as slave", driver_name);
669 list_add_tail(&driver_ptr->siblings, &controller_ptr->slave_drivers);
671 if (len_old != 0)
673 controller_ptr->slave_drivers_vparam_value.str[len_old++] = ',';
676 memcpy(controller_ptr->slave_drivers_vparam_value.str + len_old, driver_name, len_new + 1);
677 controller_ptr->slave_drivers_set = true;
679 return true;
682 bool
683 jack_controller_remove_slave_driver(
684 struct jack_controller * controller_ptr,
685 const char * driver_name)
687 struct list_head * node_ptr;
688 struct jack_controller_slave_driver * driver_ptr;
690 list_for_each(node_ptr, &controller_ptr->slave_drivers)
692 driver_ptr = list_entry(node_ptr, struct jack_controller_slave_driver, siblings);
693 if (strcmp(driver_ptr->name, driver_name) == 0)
695 list_del(&driver_ptr->siblings);
696 free(driver_ptr->name);
697 free(driver_ptr);
699 /* update the slave-drivers param value */
700 controller_ptr->slave_drivers_vparam_value.str[0] = 0;
701 list_for_each(node_ptr, &controller_ptr->slave_drivers)
703 driver_ptr = list_entry(node_ptr, struct jack_controller_slave_driver, siblings);
704 if (controller_ptr->slave_drivers_vparam_value.str[0] != 0)
706 strcat(controller_ptr->slave_drivers_vparam_value.str, ",");
709 strcat(controller_ptr->slave_drivers_vparam_value.str, driver_ptr->name);
712 jack_info("driver \"%s\" is not slave anymore", driver_name);
714 return true;
718 return false;
721 bool
722 jack_controller_load_internal(
723 struct jack_controller *controller_ptr,
724 const char * internal_name)
726 jackctl_internal_t *internal;
728 internal = jack_controller_find_internal(controller_ptr->server, internal_name);
729 if (internal == NULL)
731 return false;
734 jack_info("internal \"%s\" selected", internal_name);
736 return jackctl_server_load_internal(controller_ptr->server, internal);
739 bool
740 jack_controller_unload_internal(
741 struct jack_controller *controller_ptr,
742 const char * internal_name)
744 jackctl_internal_t *internal;
746 internal = jack_controller_find_internal(controller_ptr->server, internal_name);
747 if (internal == NULL)
749 return false;
752 jack_info("internal \"%s\" selected", internal_name);
754 return jackctl_server_unload_internal(controller_ptr->server, internal);
757 #define controller_ptr ((struct jack_controller *)context)
759 void
760 jack_controller_destroy(
761 void * context)
763 if (controller_ptr->started)
765 while (!jack_controller_stop_server(controller_ptr, NULL))
767 jack_info("jack server failed to stop, retrying in 3 seconds...");
768 usleep(3000000);
772 jack_controller_remove_slave_drivers(controller_ptr);
773 jack_params_destroy(controller_ptr->params);
774 jackctl_server_destroy(controller_ptr->server);
775 pthread_mutex_destroy(&controller_ptr->lock);
776 free(controller_ptr);