diff --git a/dbus/controller.c b/dbus/controller.c index 002e3cf5..033fb65e 100644 --- a/dbus/controller.c +++ b/dbus/controller.c @@ -65,9 +65,7 @@ jack_controller_find_driver( return NULL; } -bool -jack_controller_add_slave_drivers( - struct jack_controller * controller_ptr) +static bool jack_controller_check_slave_driver(struct jack_controller * controller_ptr, const char * name) { struct list_head * node_ptr; struct jack_controller_slave_driver * driver_ptr; @@ -75,31 +73,40 @@ jack_controller_add_slave_drivers( list_for_each(node_ptr, &controller_ptr->slave_drivers) { driver_ptr = list_entry(node_ptr, struct jack_controller_slave_driver, siblings); - driver_ptr->handle = jack_controller_find_driver(controller_ptr->server, driver_ptr->name); - - if (driver_ptr->handle == NULL) + if (strcmp(name, driver_ptr->name) == 0) { - jack_error("Unknown driver \"%s\"", driver_ptr->name); - goto fail; + return true; } + } + + return false; +} + +static bool jack_controller_load_slave_drivers(struct jack_controller * controller_ptr) +{ + struct list_head * node_ptr; + struct jack_controller_slave_driver * driver_ptr; + + list_for_each(node_ptr, &controller_ptr->slave_drivers) + { + driver_ptr = list_entry(node_ptr, struct jack_controller_slave_driver, siblings); + + assert(driver_ptr->handle != NULL); + assert(!driver_ptr->loaded); if (!jackctl_server_add_slave(controller_ptr->server, driver_ptr->handle)) { jack_error("Driver \"%s\" cannot be loaded", driver_ptr->name); - goto fail; + return false; } + + driver_ptr->loaded = true; } return true; - -fail: - driver_ptr->handle = NULL; - return false; } -void -jack_controller_remove_slave_drivers( - struct jack_controller * controller_ptr) +static void jack_controller_unload_slave_drivers(struct jack_controller * controller_ptr) { struct list_head * node_ptr; struct jack_controller_slave_driver * driver_ptr; @@ -107,14 +114,30 @@ jack_controller_remove_slave_drivers( list_for_each(node_ptr, &controller_ptr->slave_drivers) { driver_ptr = list_entry(node_ptr, struct jack_controller_slave_driver, siblings); - if (driver_ptr->handle != NULL) + if (driver_ptr->loaded) { jackctl_server_remove_slave(controller_ptr->server, driver_ptr->handle); - driver_ptr->handle = NULL; + driver_ptr->loaded = false; } } } +static void jack_controller_remove_slave_drivers(struct jack_controller * controller_ptr) +{ + struct jack_controller_slave_driver * driver_ptr; + + while (!list_empty(&controller_ptr->slave_drivers)) + { + driver_ptr = list_entry(controller_ptr->slave_drivers.next, struct jack_controller_slave_driver, siblings); + assert(!driver_ptr->loaded); + list_del(&driver_ptr->siblings); + free(driver_ptr->name); + free(driver_ptr); + } + + controller_ptr->slave_drivers_vparam_value.str[0] = 0; +} + static jackctl_internal_t * jack_controller_find_internal( @@ -183,7 +206,7 @@ jack_controller_start_server( goto fail; } - jack_controller_add_slave_drivers(controller_ptr); + jack_controller_load_slave_drivers(controller_ptr); if (!jackctl_server_start( controller_ptr->server)) @@ -245,7 +268,7 @@ fail_stop_server: } fail_close_server: - jack_controller_remove_slave_drivers(controller_ptr); + jack_controller_unload_slave_drivers(controller_ptr); if (!jackctl_server_close(controller_ptr->server)) { @@ -289,7 +312,7 @@ jack_controller_stop_server( return FALSE; } - jack_controller_remove_slave_drivers(controller_ptr); + jack_controller_unload_slave_drivers(controller_ptr); if (!jackctl_server_close(controller_ptr->server)) { @@ -381,11 +404,108 @@ on_device_release(const char * device_name) g_device_count--; } +#define controller_ptr ((struct jack_controller *)obj) + +static bool slave_drivers_parameter_is_set(void * obj) +{ + return controller_ptr->slave_drivers_set; +} + +static bool slave_drivers_parameter_reset(void * obj) +{ + if (controller_ptr->started) + { + jack_error("Cannot modify slave-drivers when server is started"); + return false; + } + + jack_controller_remove_slave_drivers(controller_ptr); + controller_ptr->slave_drivers_set = false; + return true; +} + +static union jackctl_parameter_value slave_drivers_parameter_get_value(void * obj) +{ + return controller_ptr->slave_drivers_vparam_value; +} + +static bool slave_drivers_parameter_set_value(void * obj, const union jackctl_parameter_value * value_ptr) +{ + char * buffer; + char * save; + const char * token; + struct list_head old_list; + struct list_head new_list; + union jackctl_parameter_value old_value; + union jackctl_parameter_value new_value; + bool old_set; + + if (controller_ptr->started) + { + jack_error("Cannot modify slave-drivers when server is started"); + return false; + } + + old_set = controller_ptr->slave_drivers_set; + old_value = controller_ptr->slave_drivers_vparam_value; + controller_ptr->slave_drivers_vparam_value.str[0] = 0; + old_list = controller_ptr->slave_drivers; + INIT_LIST_HEAD(&controller_ptr->slave_drivers); + + buffer = strdup(value_ptr->str); + if (buffer == NULL) + { + jack_error("strdup() failed."); + return false; + } + + token = strtok_r(buffer, ",", &save); + while (token) + { + //jack_info("slave driver '%s'", token); + if (!jack_controller_add_slave_driver(controller_ptr, token)) + { + jack_controller_remove_slave_drivers(controller_ptr); + controller_ptr->slave_drivers = old_list; + controller_ptr->slave_drivers_vparam_value = old_value; + controller_ptr->slave_drivers_set = old_set; + + free(buffer); + + return false; + } + + token = strtok_r(NULL, ",", &save); + } + + new_value = controller_ptr->slave_drivers_vparam_value; + new_list = controller_ptr->slave_drivers; + controller_ptr->slave_drivers = old_list; + jack_controller_remove_slave_drivers(controller_ptr); + controller_ptr->slave_drivers_vparam_value = new_value; + controller_ptr->slave_drivers = new_list; + controller_ptr->slave_drivers_set = true; + + free(buffer); + + return true; +} + +static union jackctl_parameter_value slave_drivers_parameter_get_default_value(void * obj) +{ + union jackctl_parameter_value value; + value.str[0] = 0; + return value; +} + +#undef controller_ptr + void * jack_controller_create( DBusConnection *connection) { struct jack_controller *controller_ptr; + const char * address[PARAM_ADDRESS_SIZE]; DBusObjectPathVTable vtable = { jack_dbus_message_handler_unregister, @@ -416,7 +536,28 @@ jack_controller_create( controller_ptr->client = NULL; controller_ptr->started = false; + INIT_LIST_HEAD(&controller_ptr->slave_drivers); + controller_ptr->slave_drivers_set = false; + controller_ptr->slave_drivers_vparam_value.str[0] = 0; + + controller_ptr->slave_drivers_vparam.obj = controller_ptr; + + controller_ptr->slave_drivers_vparam.vtable.is_set = slave_drivers_parameter_is_set; + controller_ptr->slave_drivers_vparam.vtable.reset = slave_drivers_parameter_reset; + controller_ptr->slave_drivers_vparam.vtable.get_value = slave_drivers_parameter_get_value; + controller_ptr->slave_drivers_vparam.vtable.set_value = slave_drivers_parameter_set_value; + controller_ptr->slave_drivers_vparam.vtable.get_default_value = slave_drivers_parameter_get_default_value; + + controller_ptr->slave_drivers_vparam.type = JackParamString; + controller_ptr->slave_drivers_vparam.name = "slave-drivers"; + controller_ptr->slave_drivers_vparam.short_decr = "Slave drivers to use"; + controller_ptr->slave_drivers_vparam.long_descr = "A comma separated list of slave drivers"; + controller_ptr->slave_drivers_vparam.constraint_flags = 0; + + address[0] = PTNODE_ENGINE; + address[1] = NULL; + jack_params_add_parameter(controller_ptr->params, address, true, &controller_ptr->slave_drivers_vparam); controller_ptr->dbus_descriptor.context = controller_ptr; controller_ptr->dbus_descriptor.interfaces = g_jackcontroller_interfaces; @@ -453,7 +594,31 @@ jack_controller_add_slave_driver( struct jack_controller * controller_ptr, const char * driver_name) { + jackctl_driver_t * driver; struct jack_controller_slave_driver * driver_ptr; + size_t len_old; + size_t len_new; + + len_old = strlen(controller_ptr->slave_drivers_vparam_value.str); + len_new = strlen(driver_name); + if (len_old + len_new + 2 > sizeof(controller_ptr->slave_drivers_vparam_value.str)) + { + jack_error("No more space for slave drivers."); + return false; + } + + driver = jack_controller_find_driver(controller_ptr->server, driver_name); + if (driver == NULL) + { + jack_error("Unknown driver \"%s\"", driver_name); + return false; + } + + if (jack_controller_check_slave_driver(controller_ptr, driver_name)) + { + jack_info("Driver \"%s\" is already slave", driver_name); + return true; + } driver_ptr = malloc(sizeof(struct jack_controller_slave_driver)); if (driver_ptr == NULL) @@ -470,12 +635,21 @@ jack_controller_add_slave_driver( return false; } - driver_ptr->handle = NULL; + driver_ptr->handle = driver; + driver_ptr->loaded = false; - jack_info("slave driver \"%s\" added", driver_name); + jack_info("driver \"%s\" set as slave", driver_name); list_add_tail(&driver_ptr->siblings, &controller_ptr->slave_drivers); + if (len_old != 0) + { + controller_ptr->slave_drivers_vparam_value.str[len_old++] = ','; + } + + memcpy(controller_ptr->slave_drivers_vparam_value.str + len_old, driver_name, len_new + 1); + controller_ptr->slave_drivers_set = true; + return true; } @@ -492,10 +666,25 @@ jack_controller_remove_slave_driver( driver_ptr = list_entry(node_ptr, struct jack_controller_slave_driver, siblings); if (strcmp(driver_ptr->name, driver_name) == 0) { - jack_info("slave driver \"%s\" removed", driver_name); list_del(&driver_ptr->siblings); free(driver_ptr->name); free(driver_ptr); + + /* update the slave-drivers param value */ + controller_ptr->slave_drivers_vparam_value.str[0] = 0; + list_for_each(node_ptr, &controller_ptr->slave_drivers) + { + driver_ptr = list_entry(node_ptr, struct jack_controller_slave_driver, siblings); + if (controller_ptr->slave_drivers_vparam_value.str[0] != 0) + { + strcat(controller_ptr->slave_drivers_vparam_value.str, ","); + } + + strcat(controller_ptr->slave_drivers_vparam_value.str, driver_ptr->name); + } + + jack_info("driver \"%s\" is not slave anymore", driver_name); + return true; } } @@ -550,6 +739,7 @@ jack_controller_destroy( jack_controller_stop_server(controller_ptr, NULL); } + jack_controller_remove_slave_drivers(controller_ptr); jack_params_destroy(controller_ptr->params); jackctl_server_destroy(controller_ptr->server); diff --git a/dbus/controller_iface_control.c b/dbus/controller_iface_control.c index d38df3c6..a82cbcd7 100644 --- a/dbus/controller_iface_control.c +++ b/dbus/controller_iface_control.c @@ -30,6 +30,7 @@ #include "jackdbus.h" #include "controller_internal.h" +#include "xml.h" #define JACK_DBUS_IFACE_NAME "org.jackaudio.JackControl" @@ -244,12 +245,17 @@ jack_control_run_method( goto exit; } - if (!jack_controller_add_slave_driver(controller_ptr, driver_name)) { + if (!jack_controller_add_slave_driver(controller_ptr, driver_name)) + { jack_dbus_error( call, JACK_DBUS_ERROR_GENERIC, "jack_controller_add_slave_driver failed for driver (%s)", driver_name); } + else + { + jack_controller_settings_save_auto(controller_ptr); + } } else if (strcmp (call->method_name, "RemoveSlaveDriver") == 0) { @@ -268,12 +274,17 @@ jack_control_run_method( goto exit; } - if (!jack_controller_remove_slave_driver(controller_ptr, driver_name)) { + if (!jack_controller_remove_slave_driver(controller_ptr, driver_name)) + { jack_dbus_error( call, JACK_DBUS_ERROR_GENERIC, "jack_controller_remove_slave_driver failed for driver (%s)", driver_name); } + else + { + jack_controller_settings_save_auto(controller_ptr); + } } else if (strcmp (call->method_name, "UnloadInternal") == 0) { diff --git a/dbus/controller_internal.h b/dbus/controller_internal.h index e01b2c09..1b9c7129 100644 --- a/dbus/controller_internal.h +++ b/dbus/controller_internal.h @@ -34,6 +34,7 @@ struct jack_controller_slave_driver struct list_head siblings; char * name; jackctl_driver_t * handle; + bool loaded; }; struct jack_controller @@ -48,6 +49,9 @@ struct jack_controller unsigned int xruns; struct list_head slave_drivers; + bool slave_drivers_set; + struct jack_parameter slave_drivers_vparam; + union jackctl_parameter_value slave_drivers_vparam_value; struct jack_dbus_object_descriptor dbus_descriptor; }; diff --git a/dbus/params.c b/dbus/params.c index b6f913de..5acbe19b 100644 --- a/dbus/params.c +++ b/dbus/params.c @@ -142,6 +142,7 @@ static bool add_controlapi_param(struct list_head * parent_list_ptr, jackctl_par goto fail; } + param_ptr->ext = false; param_ptr->obj = param; param_ptr->vtable.is_set = controlapi_parameter_is_set; param_ptr->vtable.reset = controlapi_parameter_reset; @@ -212,6 +213,11 @@ static void free_params(struct list_head * parent_list_ptr) param_ptr = list_entry(parent_list_ptr->next, struct jack_parameter, siblings); list_del(¶m_ptr->siblings); + if (param_ptr->ext) + { + continue; + } + if ((param_ptr->constraint_flags & JACK_CONSTRAINT_FLAG_VALID) != 0 && !param_ptr->constraint_range && param_ptr->constraint.enumeration.possible_values_array != NULL) @@ -456,6 +462,7 @@ static bool init_engine_driver_parameter(struct jack_params * params_ptr) goto fail; } + param_ptr->ext = false; param_ptr->obj = params_ptr; param_ptr->vtable.is_set = engine_driver_parameter_is_set; param_ptr->vtable.reset = engine_driver_parameter_reset; @@ -691,7 +698,7 @@ const struct jack_parameter * jack_params_get_parameter(jack_params_handle param return NULL; } -bool jack_params_add_parameter(jack_params_handle params, const char * const * address, bool end, struct jack_parameter * param_ptr) +void jack_params_add_parameter(jack_params_handle params, const char * const * address, bool end, struct jack_parameter * param_ptr) { struct jack_parameter_container * container_ptr; @@ -699,9 +706,11 @@ bool jack_params_add_parameter(jack_params_handle params, const char * const * a if (container_ptr == NULL || !container_ptr->leaf) { assert(false); - return false; + return; } + param_ptr->ext = true; + if (end) { list_add_tail(¶m_ptr->siblings, &container_ptr->children); @@ -711,7 +720,7 @@ bool jack_params_add_parameter(jack_params_handle params, const char * const * a list_add(¶m_ptr->siblings, &container_ptr->children); } - return true; + return; } #undef params_ptr diff --git a/dbus/params.h b/dbus/params.h index d880a7dd..ad9b727b 100644 --- a/dbus/params.h +++ b/dbus/params.h @@ -54,6 +54,7 @@ struct jack_parameter void * obj; struct jack_parameter_vtable vtable; struct list_head siblings; + bool ext; jackctl_param_type_t type; const char * name; const char * short_decr; @@ -105,6 +106,6 @@ jack_params_iterate_params( const struct jack_parameter * jack_params_get_parameter(jack_params_handle params, const char * const * address); -bool jack_params_add_parameter(jack_params_handle params, const char * const * address, bool end, struct jack_parameter * param_ptr); +void jack_params_add_parameter(jack_params_handle params, const char * const * address, bool end, struct jack_parameter * param_ptr); #endif /* #ifndef PARAMS_H__A23EDE06_C1C9_4489_B253_FD1B26B66929__INCLUDED */