From 343a0e80693d4e59b507a9e0b3882dacfb5ca450 Mon Sep 17 00:00:00 2001 From: nedko Date: Sun, 17 Apr 2011 18:18:32 +0000 Subject: [PATCH] jackdbus: params store This changeset removes code duplication that was caused by lack of unified access to parameters in the control API. Adding new virtual parameters should be much easier now. git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@4315 0c269be4-1314-0410-8aa9-9f06e86f4224 --- dbus/controller.c | 89 +- dbus/controller_iface_configure.c | 1575 ++++------------------------- dbus/controller_internal.h | 58 +- dbus/params.c | 717 +++++++++++++ dbus/params.h | 110 ++ dbus/wscript | 1 + dbus/xml.c | 376 ++----- dbus/xml_expat.c | 166 ++- dbus/xml_write_raw.c | 162 ++- 9 files changed, 1250 insertions(+), 2004 deletions(-) create mode 100644 dbus/params.c create mode 100644 dbus/params.h diff --git a/dbus/controller.c b/dbus/controller.c index e0abd258..15afe65a 100644 --- a/dbus/controller.c +++ b/dbus/controller.c @@ -1,6 +1,6 @@ /* -*- Mode: C ; c-basic-offset: 4 -*- */ /* - Copyright (C) 2007,2008,2010 Nedko Arnaudov + Copyright (C) 2007,2008,2010,2011 Nedko Arnaudov Copyright (C) 2007-2008 Juuso Alasuutari This program is free software; you can redistribute it and/or modify @@ -159,19 +159,13 @@ jack_controller_select_driver( struct jack_controller * controller_ptr, const char * driver_name) { - jackctl_driver_t *driver; - - driver = jack_controller_find_driver(controller_ptr->server, driver_name); - if (driver == NULL) + if (!jack_params_set_driver(controller_ptr->params, driver_name)) { return false; } jack_info("driver \"%s\" selected", driver_name); - controller_ptr->driver = driver; - controller_ptr->driver_set = true; - return true; } @@ -195,17 +189,11 @@ jack_controller_start_server( assert(!controller_ptr->started); /* should be ensured by caller */ - if (controller_ptr->driver == NULL) - { - jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Select driver first!"); - goto fail; - } - controller_ptr->xruns = 0; if (!jackctl_server_open( controller_ptr->server, - controller_ptr->driver)) + jack_params_get_driver(controller_ptr->params))) { jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to open server"); goto fail; @@ -337,12 +325,13 @@ jack_controller_switch_master( { if (!jackctl_server_switch_master( controller_ptr->server, - controller_ptr->driver)) + jack_params_get_driver(controller_ptr->params))) { jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to switch master"); return FALSE; } + return TRUE; } @@ -413,11 +402,6 @@ jack_controller_create( DBusConnection *connection) { struct jack_controller *controller_ptr; - const JSList * node_ptr; - const char ** driver_name_target; - const char ** internal_name_target; - JSList * drivers; - JSList * internals; DBusObjectPathVTable vtable = { jack_dbus_message_handler_unregister, @@ -439,54 +423,16 @@ jack_controller_create( goto fail_free; } - controller_ptr->client = NULL; - controller_ptr->started = false; - controller_ptr->driver = NULL; - controller_ptr->driver_set = false; - INIT_LIST_HEAD(&controller_ptr->slave_drivers); - - drivers = (JSList *)jackctl_server_get_drivers_list(controller_ptr->server); - controller_ptr->drivers_count = jack_slist_length(drivers); - controller_ptr->driver_names = malloc(controller_ptr->drivers_count * sizeof(const char *)); - if (controller_ptr->driver_names == NULL) + controller_ptr->params = jack_params_create(controller_ptr->server); + if (controller_ptr->params == NULL) { - jack_error("Ran out of memory trying to allocate driver names array"); + jack_error("Failed to initialize parameter tree"); goto fail_destroy_server; } - driver_name_target = controller_ptr->driver_names; - node_ptr = jackctl_server_get_drivers_list(controller_ptr->server); - while (node_ptr != NULL) - { - *driver_name_target = jackctl_driver_get_name((jackctl_driver_t *)node_ptr->data); - - /* select default driver */ - if (controller_ptr->driver == NULL && strcmp(*driver_name_target, DEFAULT_DRIVER) == 0) - { - controller_ptr->driver = (jackctl_driver_t *)node_ptr->data; - } - - node_ptr = jack_slist_next(node_ptr); - driver_name_target++; - } - - internals = (JSList *)jackctl_server_get_internals_list(controller_ptr->server); - controller_ptr->internals_count = jack_slist_length(internals); - controller_ptr->internal_names = malloc(controller_ptr->internals_count * sizeof(const char *)); - if (controller_ptr->internal_names == NULL) - { - jack_error("Ran out of memory trying to allocate internals names array"); - goto fail_free_driver_names_array; - } - - internal_name_target = controller_ptr->internal_names; - node_ptr = jackctl_server_get_internals_list(controller_ptr->server); - while (node_ptr != NULL) - { - *internal_name_target = jackctl_internal_get_name((jackctl_internal_t *)node_ptr->data); - node_ptr = jack_slist_next(node_ptr); - internal_name_target++; - } + controller_ptr->client = NULL; + controller_ptr->started = false; + INIT_LIST_HEAD(&controller_ptr->slave_drivers); controller_ptr->dbus_descriptor.context = controller_ptr; controller_ptr->dbus_descriptor.interfaces = g_jackcontroller_interfaces; @@ -498,18 +444,15 @@ jack_controller_create( &controller_ptr->dbus_descriptor)) { jack_error("Ran out of memory trying to register D-Bus object path"); - goto fail_free_internal_names_array; + goto fail_destroy_params; } jack_controller_settings_load(controller_ptr); return controller_ptr; -fail_free_internal_names_array: - free(controller_ptr->internal_names); - -fail_free_driver_names_array: - free(controller_ptr->driver_names); +fail_destroy_params: + jack_params_destroy(controller_ptr->params); fail_destroy_server: jackctl_server_destroy(controller_ptr->server); @@ -623,9 +566,7 @@ jack_controller_destroy( jack_controller_stop_server(controller_ptr, NULL); } - free(controller_ptr->driver_names); - free(controller_ptr->internal_names); - + jack_params_destroy(controller_ptr->params); jackctl_server_destroy(controller_ptr->server); free(controller_ptr); diff --git a/dbus/controller_iface_configure.c b/dbus/controller_iface_configure.c index f4b6d46f..7e3a8fd9 100644 --- a/dbus/controller_iface_configure.c +++ b/dbus/controller_iface_configure.c @@ -1,6 +1,6 @@ /* -*- Mode: C ; c-basic-offset: 4 -*- */ /* - Copyright (C) 2007,2008 Nedko Arnaudov + Copyright (C) 2007,2008,2011 Nedko Arnaudov Copyright (C) 2007-2008 Juuso Alasuutari This program is free software; you can redistribute it and/or modify @@ -31,24 +31,6 @@ #include "controller_internal.h" #include "xml.h" -#define PTNODE_ENGINE "engine" -#define PTNODE_DRIVER "driver" -#define PTNODE_DRIVERS "drivers" -#define PTNODE_INTERNALS "internals" - -#define ENGINE_DRIVER_PARAMETER_NAME "driver" -#define ENGINE_DRIVER_PARAMETER_TYPE JackParamString -#define ENGINE_DRIVER_PARAMETER_SHORT_DESCR "Driver to use" -#define ENGINE_DRIVER_PARAMETER_LONG_DESCR "" - -struct parameter_info -{ - unsigned char type; - const char * name; - const char * short_decr; - const char * long_descr; -}; - unsigned char jack_controller_dbus_types[JACK_PARAM_MAX] = { [JackParamInt] = DBUS_TYPE_INT32, @@ -238,12 +220,13 @@ jack_controller_dbus_get_parameter_address_ex( index = 0; while ((type = dbus_message_iter_get_arg_type(&array_iter)) != DBUS_TYPE_INVALID) { - if (index == 3) + if (index == PARAM_ADDRESS_SIZE) { jack_dbus_error( call, JACK_DBUS_ERROR_INVALID_ARGS, - "Invalid arguments to method '%s'. Parameter address array must contain not more than three elements.", + "Invalid arguments to method '%s'. Parameter address array must contain not more than %u elements.", + (unsigned int)PARAM_ADDRESS_SIZE, call->method_name); return false; } @@ -267,7 +250,7 @@ jack_controller_dbus_get_parameter_address_ex( index++; } - while (index < 3) + while (index < PARAM_ADDRESS_SIZE) { address_array[index] = NULL; index++; @@ -301,45 +284,9 @@ jack_controller_dbus_get_parameter_address( #define controller_ptr ((struct jack_controller *)call->context) -static -bool -jack_controller_fill_parameter_names( - struct jack_dbus_method_call * call, - DBusMessageIter * iter_ptr, - const char * special_first, - const JSList * parameters_list) +static bool append_node_name(void * context, const char * name) { - DBusMessageIter array_iter; - const char * param_name; - - if (!dbus_message_iter_open_container(iter_ptr, DBUS_TYPE_ARRAY, "s", &array_iter)) - { - return false; - } - - if (special_first != NULL) - { - if (!dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_STRING, &special_first)) - { - dbus_message_iter_close_container(iter_ptr, &array_iter); - return false; - } - } - - /* Append parameter descriptions to the array. */ - while (parameters_list != NULL) - { - param_name = jackctl_parameter_get_name(parameters_list->data); - if (!dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_STRING, ¶m_name)) - { - dbus_message_iter_close_container(iter_ptr, &array_iter); - return false; - } - - parameters_list = jack_slist_next(parameters_list); - } - - return dbus_message_iter_close_container(iter_ptr, &array_iter); + return dbus_message_iter_append_basic(context, DBUS_TYPE_STRING, &name); } static @@ -347,14 +294,10 @@ void jack_controller_dbus_read_container( struct jack_dbus_method_call * call) { - const char * address[3]; + const char * address[PARAM_ADDRESS_SIZE]; dbus_bool_t leaf; DBusMessageIter iter; DBusMessageIter array_iter; - const char * child_name; - unsigned int index; - jackctl_internal_t * internal; - jackctl_driver_t * driver; //jack_info("jack_controller_dbus_read_container() called"); @@ -377,218 +320,37 @@ jack_controller_dbus_read_container( dbus_message_iter_init_append(call->reply, &iter); - if (address[0] == NULL) /* root node */ + if (!jack_params_check_address(controller_ptr->params, address, false)) { - //jack_info("reading root container"); - - leaf = false; - if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &leaf)) - { - goto oom_unref; - } - - if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &array_iter)) - { - goto oom_unref; - } - - child_name = PTNODE_ENGINE; - if (!dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_STRING, &child_name)) - { - goto oom_close_unref; - } - - child_name = PTNODE_DRIVER; - if (!dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_STRING, &child_name)) - { - goto oom_close_unref; - } - - child_name = PTNODE_DRIVERS; - if (!dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_STRING, &child_name)) - { - goto oom_close_unref; - } - - child_name = PTNODE_INTERNALS; - if (!dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_STRING, &child_name)) - { - goto oom_close_unref; - } - - dbus_message_iter_close_container(&iter, &array_iter); - + jack_dbus_error( + call, + JACK_DBUS_ERROR_INVALID_ARGS, + "Invalid container address '%s':'%s':'%s' supplied to method '%s'.", + address[0], + address[1], + address[2], + call->method_name); return; } - if (address[0] != NULL && - address[1] == NULL && - strcmp(address[0], PTNODE_ENGINE) == 0) /* engine parameters requested */ + leaf = jack_params_is_leaf_container(controller_ptr->params, address); + if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &leaf)) { - //jack_info("reading engine params container"); - - leaf = true; - if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &leaf)) - { - goto oom_unref; - } - - if (!jack_controller_fill_parameter_names( - call, - &iter, - ENGINE_DRIVER_PARAMETER_NAME, - jackctl_server_get_parameters(controller_ptr->server))) - { - goto oom_unref; - } - - return; + goto oom_unref; } - if (address[0] != NULL && - address[1] == NULL && - strcmp(address[0], PTNODE_DRIVER) == 0) /* current driver parameters requested */ + if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &array_iter)) { - //jack_info("reading current driver params container"); - - leaf = true; - if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &leaf)) - { - goto oom_unref; - } - - if (!jack_controller_fill_parameter_names( - call, - &iter, - NULL, - jackctl_driver_get_parameters(controller_ptr->driver))) - { - goto oom_unref; - } - - return; + goto oom_unref; } - if (address[0] != NULL && - strcmp(address[0], PTNODE_DRIVERS) == 0) - { - leaf = address[1] != NULL; - if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &leaf)) - { - goto oom_unref; - } - - if (!leaf) /* available drivers requested */ - { - //jack_info("reading drivers container"); - - if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &array_iter)) - { - goto oom_unref; - } - - for (index = 0; index < controller_ptr->drivers_count; index++) - { - if (!dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_STRING, controller_ptr->driver_names + index)) - { - goto oom_close_unref; - } - } - - dbus_message_iter_close_container(&iter, &array_iter); - } - else /* specified driver parameters requested */ - { - //jack_info("reading driver '%s' params container", address[1]); - - driver = jack_controller_find_driver(controller_ptr->server, address[1]); - if (driver == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_INTERNAL, - "Unknown driver '%s'", - address[1]); - return; - } - if (!jack_controller_fill_parameter_names( - call, - &iter, - NULL, - jackctl_driver_get_parameters(driver))) - { - goto oom_unref; - } - } - - return; - } - - if (address[0] != NULL && - strcmp(address[0], PTNODE_INTERNALS) == 0) + if (!jack_params_iterate_container(controller_ptr->params, address, append_node_name, &array_iter)) { - leaf = address[1] != NULL; - if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &leaf)) - { - goto oom_unref; - } - - if (!leaf) /* available internals requested */ - { - //jack_info("reading internals container"); - - if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &array_iter)) - { - goto oom_unref; - } - - for (index = 0; index < controller_ptr->internals_count; index++) - { - if (!dbus_message_iter_append_basic(&array_iter, DBUS_TYPE_STRING, controller_ptr->internal_names + index)) - { - goto oom_close_unref; - } - } - - dbus_message_iter_close_container(&iter, &array_iter); - } - else /* specified driver parameters requested */ - { - //jack_info("reading internal '%s' params container", address[1]); - - internal = jack_controller_find_internal(controller_ptr->server, address[1]); - if (internal == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_INTERNAL, - "Unknown internal '%s'", - address[1]); - return; - } - - if (!jack_controller_fill_parameter_names( - call, - &iter, - NULL, - jackctl_internal_get_parameters(internal))) - { - goto oom_unref; - } - } - - return; + goto oom_close_unref; } - jack_dbus_error( - call, - JACK_DBUS_ERROR_INVALID_ARGS, - "Invalid container address '%s':'%s':'%s' supplied to method '%s'.", - address[0], - address[1], - address[2], - call->method_name); + dbus_message_iter_close_container(&iter, &array_iter); return; @@ -603,60 +365,44 @@ oom: jack_error ("Ran out of memory trying to construct method return"); } -static -void -jack_controller_fill_parameter_info( - jackctl_parameter_t * parameter, - struct parameter_info * info_ptr) -{ - info_ptr->type = jackctl_parameter_get_type(parameter); - info_ptr->name = jackctl_parameter_get_name(parameter); - info_ptr->short_decr = jackctl_parameter_get_short_description(parameter); - info_ptr->long_descr = jackctl_parameter_get_long_description(parameter); -} - -static -bool -jack_controller_append_parameter_info_struct( - DBusMessageIter * iter_ptr, - struct parameter_info * info_ptr) +static bool append_parameter(void * context, const struct jack_parameter * param_ptr) { DBusMessageIter struct_iter; unsigned char type; /* Open the struct. */ - if (!dbus_message_iter_open_container(iter_ptr, DBUS_TYPE_STRUCT, NULL, &struct_iter)) + if (!dbus_message_iter_open_container(context, DBUS_TYPE_STRUCT, NULL, &struct_iter)) { goto fail; } /* Append parameter type. */ - type = PARAM_TYPE_JACK_TO_DBUS(info_ptr->type); + type = PARAM_TYPE_JACK_TO_DBUS(param_ptr->type); if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_BYTE, &type)) { goto fail_close; } /* Append parameter name. */ - if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &info_ptr->name)) + if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, ¶m_ptr->name)) { goto fail_close; } /* Append parameter short description. */ - if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &info_ptr->short_decr)) + if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, ¶m_ptr->short_decr)) { goto fail_close; } /* Append parameter long description. */ - if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &info_ptr->long_descr)) + if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, ¶m_ptr->long_descr)) { goto fail_close; } /* Close the struct. */ - if (!dbus_message_iter_close_container(iter_ptr, &struct_iter)) + if (!dbus_message_iter_close_container(context, &struct_iter)) { goto fail; } @@ -664,7 +410,7 @@ jack_controller_append_parameter_info_struct( return true; fail_close: - dbus_message_iter_close_container(iter_ptr, &struct_iter); + dbus_message_iter_close_container(context, &struct_iter); fail: return false; @@ -672,13 +418,36 @@ fail: static void -jack_controller_get_parameters_info( - struct jack_dbus_method_call * call, - struct parameter_info * special_parameter_info_ptr, - const JSList * parameters_list) +jack_controller_dbus_get_parameters_info( + struct jack_dbus_method_call * call) { + const char * address[PARAM_ADDRESS_SIZE]; DBusMessageIter iter, array_iter; - struct parameter_info info; + + //jack_info("jack_controller_dbus_get_parameters_info() called"); + + if (!jack_controller_dbus_get_parameter_address(call, address)) + { + /* The method call had invalid arguments meaning that + * jack_controller_dbus_get_parameter_address() has + * constructed an error for us. */ + return; + } + + //jack_info("address is '%s':'%s':'%s'", address[0], address[1], address[2]); + + if (!jack_params_check_address(controller_ptr->params, address, true)) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_INVALID_ARGS, + "Invalid container address '%s':'%s':'%s' supplied to method '%s'.", + address[0], + address[1], + address[2], + call->method_name); + return; + } call->reply = dbus_message_new_method_return (call->message); if (!call->reply) @@ -694,24 +463,9 @@ jack_controller_get_parameters_info( goto fail_unref; } - if (special_parameter_info_ptr != NULL) - { - if (!jack_controller_append_parameter_info_struct(&array_iter, special_parameter_info_ptr)) - { - goto fail_close_unref; - } - } - - /* Append parameter descriptions to the array. */ - while (parameters_list != NULL) + if (!jack_params_iterate_params(controller_ptr->params, address, append_parameter, &array_iter)) { - jack_controller_fill_parameter_info(parameters_list->data, &info); - if (!jack_controller_append_parameter_info_struct(&array_iter, &info)) - { - goto fail_close_unref; - } - - parameters_list = jack_slist_next(parameters_list); + goto fail_close_unref; } /* Close the array. */ @@ -735,15 +489,14 @@ fail: static void -jack_controller_dbus_get_parameters_info( +jack_controller_dbus_get_parameter_info( struct jack_dbus_method_call * call) { - const char * address[3]; - jackctl_internal_t * internal; - jackctl_driver_t * driver; - struct parameter_info driver_parameter_info; + const char * address[PARAM_ADDRESS_SIZE]; + const struct jack_parameter * param_ptr; + DBusMessageIter iter; - //jack_info("jack_controller_dbus_get_parameters_info() called"); + //jack_info("jack_controller_dbus_get_parameter_info() called"); if (!jack_controller_dbus_get_parameter_address(call, address)) { @@ -755,101 +508,20 @@ jack_controller_dbus_get_parameters_info( //jack_info("address is '%s':'%s':'%s'", address[0], address[1], address[2]); - if (address[0] != NULL && - address[1] == NULL && - strcmp(address[0], PTNODE_ENGINE) == 0) /* engine parameters requested */ - { - driver_parameter_info.type = ENGINE_DRIVER_PARAMETER_TYPE; - driver_parameter_info.name = ENGINE_DRIVER_PARAMETER_NAME; - driver_parameter_info.short_decr = ENGINE_DRIVER_PARAMETER_SHORT_DESCR; - driver_parameter_info.long_descr = ENGINE_DRIVER_PARAMETER_LONG_DESCR; - - jack_controller_get_parameters_info( - call, - &driver_parameter_info, - jackctl_server_get_parameters(controller_ptr->server)); - - return; - } - - if (address[0] != NULL && - address[1] == NULL && - strcmp(address[0], PTNODE_DRIVER) == 0) /* current driver parameters requested */ - { - jack_controller_get_parameters_info( - call, - NULL, - jackctl_driver_get_parameters(controller_ptr->driver)); - - return; - } - - if (address[0] != NULL && - address[1] != NULL && - address[2] == NULL && - strcmp(address[0], PTNODE_DRIVERS) == 0) - { - driver = jack_controller_find_driver(controller_ptr->server, address[1]); - if (driver == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_INTERNAL, - "Unknown driver '%s'", - address[1]); - return; - } - - jack_controller_get_parameters_info( - call, - NULL, - jackctl_driver_get_parameters(driver)); - - return; - } - - if (address[0] != NULL && - address[1] != NULL && - address[2] == NULL && - strcmp(address[0], PTNODE_INTERNALS) == 0) + param_ptr = jack_params_get_parameter(controller_ptr->params, address); + if (param_ptr == NULL) { - internal = jack_controller_find_internal(controller_ptr->server, address[1]); - if (internal == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_INTERNAL, - "Unknown internal '%s'", - address[1]); - return; - } - - jack_controller_get_parameters_info( + jack_dbus_error( call, - NULL, - jackctl_internal_get_parameters(internal)); - + JACK_DBUS_ERROR_INVALID_ARGS, + "Invalid container address '%s':'%s':'%s' supplied to method '%s'.", + address[0], + address[1], + address[2], + call->method_name); return; } - jack_dbus_error( - call, - JACK_DBUS_ERROR_INVALID_ARGS, - "Invalid container address '%s':'%s':'%s' supplied to method '%s'.", - address[0], - address[1], - address[2], - call->method_name); -} - -static -void -jack_controller_get_parameter_info_ex( - struct jack_dbus_method_call * call, - struct parameter_info * info_ptr) -{ - DBusMessageIter iter; - call->reply = dbus_message_new_method_return(call->message); if (!call->reply) { @@ -858,7 +530,7 @@ jack_controller_get_parameter_info_ex( dbus_message_iter_init_append(call->reply, &iter); - if (!jack_controller_append_parameter_info_struct(&iter, info_ptr)) + if (!append_parameter(&iter, param_ptr)) { goto fail_unref; } @@ -875,28 +547,17 @@ fail: static void -jack_controller_get_parameter_info( - struct jack_dbus_method_call * call, - jackctl_parameter_t * parameter) -{ - struct parameter_info info; - - jack_controller_fill_parameter_info(parameter, &info); - jack_controller_get_parameter_info_ex(call, &info); -} - -static -void -jack_controller_dbus_get_parameter_info( +jack_controller_dbus_get_parameter_constraint( struct jack_dbus_method_call * call) { - const char * address[3]; - jackctl_internal_t * internal; - jackctl_driver_t * driver; - jackctl_parameter_t * parameter; - struct parameter_info driver_parameter_info; + const char * address[PARAM_ADDRESS_SIZE]; + const struct jack_parameter * param_ptr; + uint32_t index; + DBusMessageIter iter, array_iter, struct_iter; + const char * descr; + message_arg_t value; - //jack_info("jack_controller_dbus_get_parameter_info() called"); + //jack_info("jack_controller_dbus_get_parameter_constraint() called"); if (!jack_controller_dbus_get_parameter_address(call, address)) { @@ -908,178 +569,57 @@ jack_controller_dbus_get_parameter_info( //jack_info("address is '%s':'%s':'%s'", address[0], address[1], address[2]); - if (address[0] != NULL && - address[1] != NULL && - address[2] == NULL && - strcmp(address[0], PTNODE_ENGINE) == 0) /* engine parameters requested */ + param_ptr = jack_params_get_parameter(controller_ptr->params, address); + if (param_ptr == NULL) { - if (strcmp(address[1], ENGINE_DRIVER_PARAMETER_NAME) == 0) - { - driver_parameter_info.type = ENGINE_DRIVER_PARAMETER_TYPE; - driver_parameter_info.name = ENGINE_DRIVER_PARAMETER_NAME; - driver_parameter_info.short_decr = ENGINE_DRIVER_PARAMETER_SHORT_DESCR; - driver_parameter_info.long_descr = ENGINE_DRIVER_PARAMETER_LONG_DESCR; - - jack_controller_get_parameter_info_ex(call, &driver_parameter_info); - - return; - } - - parameter = jack_controller_find_parameter(jackctl_server_get_parameters(controller_ptr->server), address[1]); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_PARAMETER, - "Unknown engine parameter '%s'", - address[1]); - return; - } - - jack_controller_get_parameter_info(call, parameter); - + jack_dbus_error( + call, + JACK_DBUS_ERROR_INVALID_ARGS, + "Invalid container address '%s':'%s':'%s' supplied to method '%s'.", + address[0], + address[1], + address[2], + call->method_name); return; } - if (address[0] != NULL && - address[1] != NULL && - address[2] == NULL && - strcmp(address[0], PTNODE_DRIVER) == 0) /* current driver parameters requested */ + call->reply = dbus_message_new_method_return(call->message); + if (!call->reply) { - parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(controller_ptr->driver), address[1]); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_PARAMETER, - "Unknown parameter '%s' for driver '%s'", - address[1], - jackctl_driver_get_name(controller_ptr->driver)); - return; - } + goto fail; + } - jack_controller_get_parameter_info(call, parameter); + dbus_message_iter_init_append(call->reply, &iter); - return; + if ((param_ptr->constraint_flags & JACK_CONSTRAINT_FLAG_VALID) != 0) + { + value.boolean = param_ptr->constraint_range; } - - if (address[0] != NULL && - address[1] != NULL && - address[2] != NULL && - strcmp(address[0], PTNODE_DRIVERS) == 0) + else { - driver = jack_controller_find_driver(controller_ptr->server, address[1]); - if (driver == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_INTERNAL, - "Unknown driver '%s'", - address[1]); - return; - } + value.boolean = false; + } - parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(driver), address[2]); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_PARAMETER, - "Unknown parameter '%s' for driver '%s'", - address[2], - address[1]); - return; - } - - jack_controller_get_parameter_info(call, parameter); - - return; - } - - if (address[0] != NULL && - address[1] != NULL && - address[2] != NULL && - strcmp(address[0], PTNODE_INTERNALS) == 0) + if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &value)) { - internal = jack_controller_find_internal(controller_ptr->server, address[1]); - if (internal == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_INTERNAL, - "Unknown internal '%s'", - address[1]); - return; - } - - parameter = jack_controller_find_parameter(jackctl_internal_get_parameters(internal), address[2]); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_PARAMETER, - "Unknown parameter '%s' for internal '%s'", - address[2], - address[1]); - return; - } - - jack_controller_get_parameter_info(call, parameter); - - return; + goto fail_unref; } - jack_dbus_error( - call, - JACK_DBUS_ERROR_INVALID_ARGS, - "Invalid container address '%s':'%s':'%s' supplied to method '%s'.", - address[0], - address[1], - address[2], - call->method_name); -} - -static -void -jack_controller_get_parameter_constraint( - struct jack_dbus_method_call * call, - jackctl_parameter_t * parameter) -{ - uint32_t index; - uint32_t count; - union jackctl_parameter_value min; - union jackctl_parameter_value max; - union jackctl_parameter_value jackctl_value; - DBusMessageIter iter, array_iter, struct_iter; - const char * descr; - jackctl_param_type_t type; - message_arg_t value; - bool is_range; - - type = jackctl_parameter_get_type(parameter); - - call->reply = dbus_message_new_method_return(call->message); - if (!call->reply) + if ((param_ptr->constraint_flags & JACK_CONSTRAINT_FLAG_VALID) != 0) { - goto fail; + value.boolean = (param_ptr->constraint_flags & JACK_CONSTRAINT_FLAG_STRICT) != 0; } - dbus_message_iter_init_append(call->reply, &iter); - - is_range = jackctl_parameter_has_range_constraint(parameter); - value.boolean = is_range; if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &value)) { goto fail_unref; } - value.boolean = jackctl_parameter_constraint_is_strict(parameter); - if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &value)) + if ((param_ptr->constraint_flags & JACK_CONSTRAINT_FLAG_VALID) != 0) { - goto fail_unref; + value.boolean = (param_ptr->constraint_flags & JACK_CONSTRAINT_FLAG_FAKE_VALUE) != 0; } - value.boolean = jackctl_parameter_constraint_is_fake_value(parameter); if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &value)) { goto fail_unref; @@ -1091,19 +631,26 @@ jack_controller_get_parameter_constraint( goto fail_unref; } - if (is_range) + if ((param_ptr->constraint_flags & JACK_CONSTRAINT_FLAG_VALID) == 0) { - jackctl_parameter_get_range_constraint(parameter, &min, &max); + goto close; + } + if (param_ptr->constraint_range) + { /* Open the struct. */ if (!dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter)) { goto fail_close_unref; } - jack_controller_jack_to_dbus_variant(type, &min, &value); + jack_controller_jack_to_dbus_variant(param_ptr->type, ¶m_ptr->constraint.range.min, &value); - if (!jack_dbus_message_append_variant(&struct_iter, PARAM_TYPE_JACK_TO_DBUS(type), PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(type), &value)) + if (!jack_dbus_message_append_variant( + &struct_iter, + PARAM_TYPE_JACK_TO_DBUS(param_ptr->type), + PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(param_ptr->type), + &value)) { goto fail_close2_unref; } @@ -1127,9 +674,13 @@ jack_controller_get_parameter_constraint( goto fail_close_unref; } - jack_controller_jack_to_dbus_variant(type, &max, &value); + jack_controller_jack_to_dbus_variant(param_ptr->type, ¶m_ptr->constraint.range.max, &value); - if (!jack_dbus_message_append_variant(&struct_iter, PARAM_TYPE_JACK_TO_DBUS(type), PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(type), &value)) + if (!jack_dbus_message_append_variant( + &struct_iter, + PARAM_TYPE_JACK_TO_DBUS(param_ptr->type), + PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(param_ptr->type), + &value)) { goto fail_close2_unref; } @@ -1149,15 +700,12 @@ jack_controller_get_parameter_constraint( } else { - count = jackctl_parameter_get_enum_constraints_count(parameter); - /* Append enum values to the array. */ - for (index = 0 ; index < count ; index++) + for (index = 0 ; index < param_ptr->constraint.enumeration.count ; index++) { - jackctl_value = jackctl_parameter_get_enum_constraint_value(parameter, index); - descr = jackctl_parameter_get_enum_constraint_description(parameter, index); + descr = param_ptr->constraint.enumeration.possible_values_array[index].short_desc; - jack_controller_jack_to_dbus_variant(type, &jackctl_value, &value); + jack_controller_jack_to_dbus_variant(param_ptr->type, ¶m_ptr->constraint.enumeration.possible_values_array[index].value, &value); /* Open the struct. */ if (!dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter)) @@ -1165,7 +713,11 @@ jack_controller_get_parameter_constraint( goto fail_close_unref; } - if (!jack_dbus_message_append_variant(&struct_iter, PARAM_TYPE_JACK_TO_DBUS(type), PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(type), &value)) + if (!jack_dbus_message_append_variant( + &struct_iter, + PARAM_TYPE_JACK_TO_DBUS(param_ptr->type), + PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(param_ptr->type), + &value)) { goto fail_close2_unref; } @@ -1183,6 +735,7 @@ jack_controller_get_parameter_constraint( } } +close: /* Close the array. */ if (!dbus_message_iter_close_container(&iter, &array_iter)) { @@ -1205,315 +758,17 @@ fail: jack_error ("Ran out of memory trying to construct method return"); } -static -void -jack_controller_get_parameter_constraint_engine_driver( - struct jack_dbus_method_call * call) -{ - unsigned int index; - DBusMessageIter iter, array_iter, struct_iter; - jackctl_param_type_t type; - dbus_bool_t bval; - message_arg_t value; - - type = ENGINE_DRIVER_PARAMETER_TYPE; - - call->reply = dbus_message_new_method_return(call->message); - if (!call->reply) - { - goto fail; - } - - dbus_message_iter_init_append(call->reply, &iter); - - /* is_range */ - bval = false; - if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &bval)) - { - goto fail_unref; - } - - /* is_strict */ - bval = true; - if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &bval)) - { - goto fail_unref; - } - - /* is_fake_value */ - bval = true; - if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &bval)) - { - goto fail_unref; - } - - /* Open the array. */ - if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(vs)", &array_iter)) - { - goto fail_unref; - } - - /* Append enum values to the array. */ - for (index = 0 ; index < controller_ptr->drivers_count ; index++) - { - /* Open the struct. */ - if (!dbus_message_iter_open_container(&array_iter, DBUS_TYPE_STRUCT, NULL, &struct_iter)) - { - goto fail_close_unref; - } - - value.string = controller_ptr->driver_names[index]; - if (!jack_dbus_message_append_variant( - &struct_iter, - PARAM_TYPE_JACK_TO_DBUS(type), - PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(type), - &value)) - { - goto fail_close2_unref; - } - - if (!dbus_message_iter_append_basic(&struct_iter, DBUS_TYPE_STRING, &value)) - { - goto fail_close2_unref; - } - - /* Close the struct. */ - if (!dbus_message_iter_close_container(&array_iter, &struct_iter)) - { - goto fail_close_unref; - } - } - - /* Close the array. */ - if (!dbus_message_iter_close_container(&iter, &array_iter)) - { - goto fail_unref; - } - - return; - -fail_close2_unref: - dbus_message_iter_close_container(&array_iter, &struct_iter); - -fail_close_unref: - dbus_message_iter_close_container(&iter, &array_iter); - -fail_unref: - dbus_message_unref(call->reply); - call->reply = NULL; - -fail: - jack_error ("Ran out of memory trying to construct method return"); -} - -static -void -jack_controller_dbus_get_parameter_constraint( +static void +jack_controller_dbus_get_parameter_value( struct jack_dbus_method_call * call) { - const char * address[3]; - jackctl_internal_t * internal; - jackctl_driver_t * driver; - jackctl_parameter_t * parameter; - - //jack_info("jack_controller_dbus_get_parameter_constraint() called"); - - if (!jack_controller_dbus_get_parameter_address(call, address)) - { - /* The method call had invalid arguments meaning that - * jack_controller_dbus_get_parameter_address() has - * constructed an error for us. */ - return; - } - - //jack_info("address is '%s':'%s':'%s'", address[0], address[1], address[2]); - - if (address[0] != NULL && - address[1] != NULL && - address[2] == NULL && - strcmp(address[0], PTNODE_ENGINE) == 0) /* engine parameters requested */ - { - if (strcmp(address[1], ENGINE_DRIVER_PARAMETER_NAME) == 0) - { - jack_controller_get_parameter_constraint_engine_driver(call); - - return; - } - - parameter = jack_controller_find_parameter(jackctl_server_get_parameters(controller_ptr->server), address[1]); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_PARAMETER, - "Unknown engine parameter '%s'", - address[1]); - return; - } - - jack_controller_get_parameter_constraint(call, parameter); - - return; - } - - if (address[0] != NULL && - address[1] != NULL && - address[2] == NULL && - strcmp(address[0], PTNODE_DRIVER) == 0) /* current driver parameters requested */ - { - parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(controller_ptr->driver), address[1]); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_PARAMETER, - "Unknown parameter '%s' for driver '%s'", - address[1], - jackctl_driver_get_name(controller_ptr->driver)); - return; - } - - jack_controller_get_parameter_constraint(call, parameter); - - return; - } - - if (address[0] != NULL && - address[1] != NULL && - address[2] != NULL && - strcmp(address[0], PTNODE_DRIVERS) == 0) - { - driver = jack_controller_find_driver(controller_ptr->server, address[1]); - if (driver == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_INTERNAL, - "Unknown driver '%s'", - address[1]); - return; - } - - parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(driver), address[2]); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_PARAMETER, - "Unknown parameter '%s' for driver '%s'", - address[2], - address[1]); - return; - } - - jack_controller_get_parameter_constraint(call, parameter); - - return; - } - - if (address[0] != NULL && - address[1] != NULL && - address[2] != NULL && - strcmp(address[0], PTNODE_INTERNALS) == 0) - { - internal = jack_controller_find_internal(controller_ptr->server, address[1]); - if (internal == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_INTERNAL, - "Unknown internal '%s'", - address[1]); - return; - } - - parameter = jack_controller_find_parameter(jackctl_internal_get_parameters(internal), address[2]); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_PARAMETER, - "Unknown parameter '%s' for internal '%s'", - address[2], - address[1]); - return; - } - - jack_controller_get_parameter_constraint(call, parameter); - - return; - } - - jack_dbus_error( - call, - JACK_DBUS_ERROR_INVALID_ARGS, - "Invalid container address '%s':'%s':'%s' supplied to method '%s'.", - address[0], - address[1], - address[2], - call->method_name); -} - -static -void -jack_controller_get_parameter_value( - struct jack_dbus_method_call * call, - jackctl_parameter_t * parameter) -{ - int type; + const char * address[PARAM_ADDRESS_SIZE]; + const struct jack_parameter * param_ptr; union jackctl_parameter_value jackctl_value; union jackctl_parameter_value jackctl_default_value; message_arg_t value; message_arg_t default_value; - type = jackctl_parameter_get_type(parameter); - jackctl_default_value = jackctl_parameter_get_default_value(parameter); - jackctl_value = jackctl_parameter_get_value(parameter); - - jack_controller_jack_to_dbus_variant(type, &jackctl_value, &value); - jack_controller_jack_to_dbus_variant(type, &jackctl_default_value, &default_value); - - /* Construct the reply. */ - jack_dbus_construct_method_return_parameter( - call, - (dbus_bool_t)(jackctl_parameter_is_set(parameter) ? TRUE : FALSE), - PARAM_TYPE_JACK_TO_DBUS(type), - PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(type), - default_value, - value); -} - -static -void -jack_controller_get_parameter_value_engine_driver( - struct jack_dbus_method_call * call) -{ - message_arg_t value; - message_arg_t default_value; - - default_value.string = DEFAULT_DRIVER; - value.string = jackctl_driver_get_name(controller_ptr->driver); - - /* Construct the reply. */ - jack_dbus_construct_method_return_parameter( - call, - controller_ptr->driver_set, - DBUS_TYPE_STRING, - DBUS_TYPE_STRING_AS_STRING, - default_value, - value); -} - - -static void -jack_controller_dbus_get_parameter_value( - struct jack_dbus_method_call * call) -{ - const char * address[3]; - jackctl_internal_t * internal; - jackctl_driver_t * driver; - jackctl_parameter_t * parameter; - //jack_info("jack_controller_dbus_get_parameter_value() called"); if (!jack_controller_dbus_get_parameter_address(call, address)) @@ -1526,221 +781,34 @@ jack_controller_dbus_get_parameter_value( //jack_info("address is '%s':'%s':'%s'", address[0], address[1], address[2]); - if (address[0] != NULL && - address[1] != NULL && - address[2] == NULL && - strcmp(address[0], PTNODE_ENGINE) == 0) /* engine parameters requested */ - { - if (strcmp(address[1], ENGINE_DRIVER_PARAMETER_NAME) == 0) - { - jack_controller_get_parameter_value_engine_driver(call); - - return; - } - - parameter = jack_controller_find_parameter(jackctl_server_get_parameters(controller_ptr->server), address[1]); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_PARAMETER, - "Unknown engine parameter '%s'", - address[1]); - return; - } - - jack_controller_get_parameter_value(call, parameter); - - return; - } - - if (address[0] != NULL && - address[1] != NULL && - address[2] == NULL && - strcmp(address[0], PTNODE_DRIVER) == 0) /* current driver parameters requested */ - { - parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(controller_ptr->driver), address[1]); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_PARAMETER, - "Unknown parameter '%s' for driver '%s'", - address[1], - jackctl_driver_get_name(controller_ptr->driver)); - return; - } - - jack_controller_get_parameter_value(call, parameter); - - return; - } - - if (address[0] != NULL && - address[1] != NULL && - address[2] != NULL && - strcmp(address[0], PTNODE_DRIVERS) == 0) - { - driver = jack_controller_find_driver(controller_ptr->server, address[1]); - if (driver == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_INTERNAL, - "Unknown driver '%s'", - address[1]); - return; - } - - parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(driver), address[2]); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_PARAMETER, - "Unknown parameter '%s' for driver '%s'", - address[2], - address[1]); - return; - } - - jack_controller_get_parameter_value(call, parameter); - - return; - } - - if (address[0] != NULL && - address[1] != NULL && - address[2] != NULL && - strcmp(address[0], PTNODE_INTERNALS) == 0) - { - internal = jack_controller_find_internal(controller_ptr->server, address[1]); - if (internal == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_INTERNAL, - "Unknown internal '%s'", - address[1]); - return; - } - - parameter = jack_controller_find_parameter(jackctl_internal_get_parameters(internal), address[2]); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_PARAMETER, - "Unknown parameter '%s' for internal '%s'", - address[2], - address[1]); - return; - } - - jack_controller_get_parameter_value(call, parameter); - - return; - } - - jack_dbus_error( - call, - JACK_DBUS_ERROR_INVALID_ARGS, - "Invalid container address '%s':'%s':'%s' supplied to method '%s'.", - address[0], - address[1], - address[2], - call->method_name); -} - -static -void -jack_controller_set_parameter_value( - struct jack_dbus_method_call * call, - jackctl_parameter_t * parameter, - message_arg_t * arg_ptr, - int arg_type) -{ - jackctl_param_type_t type; - union jackctl_parameter_value value; - - type = jackctl_parameter_get_type(parameter); - - if (PARAM_TYPE_JACK_TO_DBUS(type) != arg_type) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_INVALID_ARGS, - "Parameter value type mismatch: was expecting '%c', got '%c'", - (char)PARAM_TYPE_JACK_TO_DBUS(type), - (char)arg_type); - return; - } - - if (!jack_controller_dbus_to_jack_variant( - arg_type, - arg_ptr, - &value)) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_INVALID_ARGS, - "Cannot convert parameter value"); - return; - } - - jackctl_parameter_set_value(parameter, &value); - - jack_controller_settings_save_auto(controller_ptr); - - jack_dbus_construct_method_return_empty(call); -} - -static -void -jack_controller_set_parameter_value_engine_driver( - struct jack_dbus_method_call * call, - message_arg_t * arg_ptr, - int arg_type) -{ - union jackctl_parameter_value value; - - if (arg_type != DBUS_TYPE_STRING) + param_ptr = jack_params_get_parameter(controller_ptr->params, address); + if (param_ptr == NULL) { jack_dbus_error( call, JACK_DBUS_ERROR_INVALID_ARGS, - "Engine parameter value type mismatch: was expecting '%c', got '%c'", - (char)DBUS_TYPE_STRING, - (char)arg_type); - return; - } - - if (!jack_controller_dbus_to_jack_variant( - arg_type, - arg_ptr, - &value)) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_INVALID_ARGS, - "Cannot convert engine parameter value"); + "Invalid container address '%s':'%s':'%s' supplied to method '%s'.", + address[0], + address[1], + address[2], + call->method_name); return; } - if (!jack_controller_select_driver(controller_ptr, value.str)) - { - /* Couldn't find driver with the specified name. */ - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_DRIVER, - "Unknown driver '%s'", - value.str); - return; - } + jackctl_default_value = param_ptr->vtable.get_default_value(param_ptr->obj); + jackctl_value = param_ptr->vtable.get_value(param_ptr->obj); - jack_controller_settings_save_auto(controller_ptr); + jack_controller_jack_to_dbus_variant(param_ptr->type, &jackctl_value, &value); + jack_controller_jack_to_dbus_variant(param_ptr->type, &jackctl_default_value, &default_value); - jack_dbus_construct_method_return_empty(call); + /* Construct the reply. */ + jack_dbus_construct_method_return_parameter( + call, + (dbus_bool_t)(param_ptr->vtable.is_set(param_ptr->obj) ? TRUE : FALSE), + PARAM_TYPE_JACK_TO_DBUS(param_ptr->type), + PARAM_TYPE_JACK_TO_DBUS_SIGNATURE(param_ptr->type), + default_value, + value); } static @@ -1748,14 +816,13 @@ void jack_controller_dbus_set_parameter_value( struct jack_dbus_method_call * call) { - const char * address[3]; + const char * address[PARAM_ADDRESS_SIZE]; + const struct jack_parameter * param_ptr; DBusMessageIter iter; DBusMessageIter variant_iter; message_arg_t arg; int arg_type; - jackctl_internal_t * internal; - jackctl_driver_t * driver; - jackctl_parameter_t * parameter; + union jackctl_parameter_value value; //jack_info("jack_controller_dbus_set_parameter_value() called"); @@ -1769,6 +836,20 @@ jack_controller_dbus_set_parameter_value( //jack_info("address is '%s':'%s':'%s'", address[0], address[1], address[2]); + param_ptr = jack_params_get_parameter(controller_ptr->params, address); + if (param_ptr == NULL) + { + jack_dbus_error( + call, + JACK_DBUS_ERROR_INVALID_ARGS, + "Invalid container address '%s':'%s':'%s' supplied to method '%s'.", + address[0], + address[1], + address[2], + call->method_name); + return; + } + dbus_message_iter_next(&iter); if (dbus_message_iter_has_next(&iter)) @@ -1797,166 +878,35 @@ jack_controller_dbus_set_parameter_value( //jack_info("argument of type '%c'", arg_type); - if (address[0] != NULL && - address[1] != NULL && - address[2] == NULL && - strcmp(address[0], PTNODE_ENGINE) == 0) /* engine parameters requested */ - { - if (strcmp(address[1], ENGINE_DRIVER_PARAMETER_NAME) == 0) - { - jack_controller_set_parameter_value_engine_driver(call, &arg, arg_type); - - return; - } - - parameter = jack_controller_find_parameter(jackctl_server_get_parameters(controller_ptr->server), address[1]); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_PARAMETER, - "Unknown engine parameter '%s'", - address[1]); - return; - } - - jack_controller_set_parameter_value(call, parameter, &arg, arg_type); - - return; - } - - if (address[0] != NULL && - address[1] != NULL && - address[2] == NULL && - strcmp(address[0], PTNODE_DRIVER) == 0) /* current driver parameters requested */ - { - parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(controller_ptr->driver), address[1]); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_PARAMETER, - "Unknown parameter '%s' for driver '%s'", - address[1], - jackctl_driver_get_name(controller_ptr->driver)); - return; - } - - jack_controller_set_parameter_value(call, parameter, &arg, arg_type); - - return; - } - - if (address[0] != NULL && - address[1] != NULL && - address[2] != NULL && - strcmp(address[0], PTNODE_DRIVERS) == 0) - { - driver = jack_controller_find_driver(controller_ptr->server, address[1]); - if (driver == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_INTERNAL, - "Unknown driver '%s'", - address[1]); - return; - } - - parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(driver), address[2]); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_PARAMETER, - "Unknown parameter '%s' for driver '%s'", - address[2], - address[1]); - return; - } - - jack_controller_set_parameter_value(call, parameter, &arg, arg_type); - - return; - } - - if (address[0] != NULL && - address[1] != NULL && - address[2] != NULL && - strcmp(address[0], PTNODE_INTERNALS) == 0) + if (PARAM_TYPE_JACK_TO_DBUS(param_ptr->type) != arg_type) { - internal = jack_controller_find_internal(controller_ptr->server, address[1]); - if (internal == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_INTERNAL, - "Unknown internal '%s'", - address[1]); - return; - } - - parameter = jack_controller_find_parameter(jackctl_internal_get_parameters(internal), address[2]); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_PARAMETER, - "Unknown parameter '%s' for internal '%s'", - address[2], - address[1]); - return; - } - - jack_controller_set_parameter_value(call, parameter, &arg, arg_type); - + jack_dbus_error( + call, + JACK_DBUS_ERROR_INVALID_ARGS, + "Parameter value type mismatch: was expecting '%c', got '%c'", + (char)PARAM_TYPE_JACK_TO_DBUS(param_ptr->type), + (char)arg_type); return; } - jack_dbus_error( - call, - JACK_DBUS_ERROR_INVALID_ARGS, - "Invalid container address '%s':'%s':'%s' supplied to method '%s'.", - address[0], - address[1], - address[2], - call->method_name); -} - -static -void -jack_controller_reset_parameter_value( - struct jack_dbus_method_call * call, - jackctl_parameter_t * parameter) -{ - jackctl_parameter_reset(parameter); - - jack_controller_settings_save_auto(controller_ptr); - - jack_dbus_construct_method_return_empty(call); -} - -static -void -jack_controller_reset_parameter_value_engine_driver( - struct jack_dbus_method_call * call) -{ - if (!jack_controller_select_driver(controller_ptr, DEFAULT_DRIVER)) + if (!jack_controller_dbus_to_jack_variant( + arg_type, + &arg, + &value)) { - /* Couldn't find driver with the specified name. */ jack_dbus_error( call, - JACK_DBUS_ERROR_UNKNOWN_DRIVER, - "Default driver '%s' is unknown", - DEFAULT_DRIVER); + JACK_DBUS_ERROR_INVALID_ARGS, + "Cannot convert parameter value"); return; } - controller_ptr->driver_set = false; + param_ptr->vtable.set_value(param_ptr->obj, &value); jack_controller_settings_save_auto(controller_ptr); jack_dbus_construct_method_return_empty(call); + } static @@ -1964,10 +914,8 @@ void jack_controller_dbus_reset_parameter_value( struct jack_dbus_method_call * call) { - const char * address[3]; - jackctl_internal_t * internal; - jackctl_driver_t * driver; - jackctl_parameter_t * parameter; + const char * address[PARAM_ADDRESS_SIZE]; + const struct jack_parameter * param_ptr; //jack_info("jack_controller_dbus_reset_parameter_value() called"); @@ -1981,130 +929,25 @@ jack_controller_dbus_reset_parameter_value( //jack_info("address is '%s':'%s':'%s'", address[0], address[1], address[2]); - if (address[0] != NULL && - address[1] != NULL && - address[2] == NULL && - strcmp(address[0], PTNODE_ENGINE) == 0) /* engine parameters requested */ - { - if (strcmp(address[1], ENGINE_DRIVER_PARAMETER_NAME) == 0) - { - jack_controller_reset_parameter_value_engine_driver(call); - - return; - } - - parameter = jack_controller_find_parameter(jackctl_server_get_parameters(controller_ptr->server), address[1]); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_PARAMETER, - "Unknown engine parameter '%s'", - address[1]); - return; - } - - jack_controller_reset_parameter_value(call, parameter); - - return; - } - - if (address[0] != NULL && - address[1] != NULL && - address[2] == NULL && - strcmp(address[0], PTNODE_DRIVER) == 0) /* current driver parameters requested */ - { - parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(controller_ptr->driver), address[1]); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_PARAMETER, - "Unknown parameter '%s' for driver '%s'", - address[1], - jackctl_driver_get_name(controller_ptr->driver)); - return; - } - - jack_controller_reset_parameter_value(call, parameter); - - return; - } - - if (address[0] != NULL && - address[1] != NULL && - address[2] != NULL && - strcmp(address[0], PTNODE_DRIVERS) == 0) + param_ptr = jack_params_get_parameter(controller_ptr->params, address); + if (param_ptr == NULL) { - driver = jack_controller_find_driver(controller_ptr->server, address[1]); - if (driver == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_INTERNAL, - "Unknown driver '%s'", - address[1]); - return; - } - - parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(driver), address[2]); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_PARAMETER, - "Unknown parameter '%s' for driver '%s'", - address[2], - address[1]); - return; - } - - jack_controller_reset_parameter_value(call, parameter); - + jack_dbus_error( + call, + JACK_DBUS_ERROR_INVALID_ARGS, + "Invalid container address '%s':'%s':'%s' supplied to method '%s'.", + address[0], + address[1], + address[2], + call->method_name); return; } - if (address[0] != NULL && - address[1] != NULL && - address[2] != NULL && - strcmp(address[0], PTNODE_INTERNALS) == 0) - { - internal = jack_controller_find_internal(controller_ptr->server, address[1]); - if (internal == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_INTERNAL, - "Unknown internal '%s'", - address[1]); - return; - } + param_ptr->vtable.reset(param_ptr->obj); - parameter = jack_controller_find_parameter(jackctl_internal_get_parameters(internal), address[2]); - if (parameter == NULL) - { - jack_dbus_error( - call, - JACK_DBUS_ERROR_UNKNOWN_PARAMETER, - "Unknown parameter '%s' for internal '%s'", - address[2], - address[1]); - return; - } - - jack_controller_reset_parameter_value(call, parameter); - - return; - } + jack_controller_settings_save_auto(controller_ptr); - jack_dbus_error( - call, - JACK_DBUS_ERROR_INVALID_ARGS, - "Invalid container address '%s':'%s':'%s' supplied to method '%s'.", - address[0], - address[1], - address[2], - call->method_name); + jack_dbus_construct_method_return_empty(call); } #undef controller_ptr diff --git a/dbus/controller_internal.h b/dbus/controller_internal.h index 6bb223a8..ae247c39 100644 --- a/dbus/controller_internal.h +++ b/dbus/controller_internal.h @@ -1,6 +1,6 @@ /* -*- Mode: C ; c-basic-offset: 4 -*- */ /* - Copyright (C) 2007,2008 Nedko Arnaudov + Copyright (C) 2007,2008,2011 Nedko Arnaudov Copyright (C) 2007-2008 Juuso Alasuutari This program is free software; you can redistribute it and/or modify @@ -27,6 +27,7 @@ #include "jack/jack.h" #include "jackdbus.h" #include "list.h" +#include "params.h" struct jack_controller_slave_driver { @@ -38,6 +39,7 @@ struct jack_controller_slave_driver struct jack_controller { jackctl_server_t *server; + jack_params_handle params; void *patchbay_context; @@ -45,14 +47,6 @@ struct jack_controller jack_client_t *client; unsigned int xruns; - const char **driver_names; - unsigned int drivers_count; - - const char **internal_names; - unsigned int internals_count; - - jackctl_driver_t *driver; - bool driver_set; /* whether driver is manually set, if false - DEFAULT_DRIVER is auto set */ struct list_head slave_drivers; struct jack_dbus_object_descriptor dbus_descriptor; @@ -121,47 +115,15 @@ jack_controller_unload_internal( const char * internal_name); void -jack_controller_settings_set_driver_option( - jackctl_driver_t *driver, - const char *option_name, - const char *option_value); - -void -jack_controller_settings_set_internal_option( - jackctl_internal_t *internal, - const char *option_name, - const char *option_value); - -void -jack_controller_settings_set_engine_option( +jack_controller_deserialize_parameter_value( struct jack_controller *controller_ptr, - const char *option_name, - const char *option_value); - -bool -jack_controller_settings_save_engine_options( - void *context, - struct jack_controller *controller_ptr, - void *dbus_call_context_ptr); + const char * const * address, + const char * value); -bool -jack_controller_settings_write_option( - void *context, - const char *name, - const char *content, - void *dbus_call_context_ptr); - -bool -jack_controller_settings_save_driver_options( - void *context, - jackctl_driver_t *driver, - void *dbus_call_context_ptr); - -bool -jack_controller_settings_save_internal_options( - void *context, - jackctl_internal_t *internal, - void *dbus_call_context_ptr); +void +jack_controller_serialize_parameter_value( + const struct jack_parameter * param_ptr, + char * value_buffer); bool jack_controller_patchbay_init( diff --git a/dbus/params.c b/dbus/params.c new file mode 100644 index 00000000..b6f913de --- /dev/null +++ b/dbus/params.c @@ -0,0 +1,717 @@ +/* -*- Mode: C ; c-basic-offset: 4 -*- */ +/* + Copyright (C) 2011 Nedko Arnaudov + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/* + * Parameter addresses: + * + * "engine" + * "engine", "driver" + * "engine", "realtime" + * "engine", ...more engine parameters + * + * "driver", "device" + * "driver", ...more driver parameters + * + * "drivers", "alsa", "device" + * "drivers", "alsa", ...more alsa driver parameters + * + * "drivers", ...more drivers + * + * "internals", "netmanager", "multicast_ip" + * "internals", "netmanager", ...more netmanager parameters + * + * "internals", ...more internals + * + */ + +#include +#include +#include +#include + +#include "params.h" +#include "controller_internal.h" + +#define PTNODE_ENGINE "engine" +#define PTNODE_DRIVER "driver" +#define PTNODE_DRIVERS "drivers" +#define PTNODE_INTERNALS "internals" + +struct jack_parameter_container +{ + struct list_head siblings; + char * name; + struct jack_parameter_container * symlink; + bool leaf; + struct list_head children; + void * obj; +}; + +struct jack_params +{ + jackctl_server_t * server; + struct jack_parameter_container root; + struct list_head * drivers_ptr; + uint32_t drivers_count; + struct jack_parameter_container * driver_ptr; + bool driver_set; /* whether driver is manually set, if false - DEFAULT_DRIVER is auto set */ +}; + +static bool controlapi_parameter_is_set(void * obj) +{ + return jackctl_parameter_is_set((jackctl_parameter_t *)obj); +} + +static bool controlapi_parameter_reset(void * obj) +{ + return jackctl_parameter_reset((jackctl_parameter_t *)obj); +} + +union jackctl_parameter_value controlapi_parameter_get_value(void * obj) +{ + return jackctl_parameter_get_value((jackctl_parameter_t *)obj); +} + +bool controlapi_parameter_set_value(void * obj, const union jackctl_parameter_value * value_ptr) +{ + return jackctl_parameter_set_value((jackctl_parameter_t *)obj, value_ptr); +} + +union jackctl_parameter_value controlapi_parameter_get_default_value(void * obj) +{ + return jackctl_parameter_get_default_value((jackctl_parameter_t *)obj); +} + +static struct jack_parameter_container * create_container(struct list_head * parent_list_ptr, const char * name) +{ + struct jack_parameter_container * container_ptr; + + container_ptr = malloc(sizeof(struct jack_parameter_container)); + if (container_ptr == NULL) + { + jack_error("Ran out of memory trying to allocate struct jack_parameter_container"); + goto fail; + } + + container_ptr->name = strdup(name); + if (container_ptr->name == NULL) + { + jack_error("Ran out of memory trying to strdup parameter container name"); + goto free; + } + + container_ptr->leaf = false; + container_ptr->symlink = NULL; + container_ptr->obj = NULL; + INIT_LIST_HEAD(&container_ptr->children); + list_add_tail(&container_ptr->siblings, parent_list_ptr); + + return container_ptr; + +free: + free(container_ptr); +fail: + return NULL; +} + +static bool add_controlapi_param(struct list_head * parent_list_ptr, jackctl_parameter_t * param) +{ + struct jack_parameter * param_ptr; + uint32_t i; + + param_ptr = malloc(sizeof(struct jack_parameter)); + if (param_ptr == NULL) + { + jack_error("Ran out of memory trying to allocate struct jack_parameter"); + goto fail; + } + + param_ptr->obj = param; + param_ptr->vtable.is_set = controlapi_parameter_is_set; + param_ptr->vtable.reset = controlapi_parameter_reset; + param_ptr->vtable.get_value = controlapi_parameter_get_value; + param_ptr->vtable.set_value = controlapi_parameter_set_value; + param_ptr->vtable.get_default_value = controlapi_parameter_get_default_value; + + param_ptr->type = jackctl_parameter_get_type(param); + param_ptr->name = jackctl_parameter_get_name(param); + param_ptr->short_decr = jackctl_parameter_get_short_description(param); + param_ptr->long_descr = jackctl_parameter_get_long_description(param); + + if (jackctl_parameter_has_range_constraint(param)) + { + param_ptr->constraint_flags = JACK_CONSTRAINT_FLAG_VALID; + param_ptr->constraint_range = true; + jackctl_parameter_get_range_constraint(param, ¶m_ptr->constraint.range.min, ¶m_ptr->constraint.range.max); + } + else if (jackctl_parameter_has_enum_constraint(param)) + { + param_ptr->constraint_flags = JACK_CONSTRAINT_FLAG_VALID; + param_ptr->constraint_range = false; + param_ptr->constraint.enumeration.count = jackctl_parameter_get_enum_constraints_count(param); + param_ptr->constraint.enumeration.possible_values_array = malloc(sizeof(struct jack_parameter_enum) * param_ptr->constraint.enumeration.count); + if (param_ptr->constraint.enumeration.possible_values_array == NULL) + { + goto free; + } + + for (i = 0; i < param_ptr->constraint.enumeration.count; i++) + { + param_ptr->constraint.enumeration.possible_values_array[i].value = jackctl_parameter_get_enum_constraint_value(param, i); + param_ptr->constraint.enumeration.possible_values_array[i].short_desc = jackctl_parameter_get_enum_constraint_description(param, i); + } + } + else + { + param_ptr->constraint_flags = 0; + goto add; + } + + if (jackctl_parameter_constraint_is_strict(param)) + { + param_ptr->constraint_flags |= JACK_CONSTRAINT_FLAG_STRICT; + } + + if (jackctl_parameter_constraint_is_fake_value(param)) + { + param_ptr->constraint_flags |= JACK_CONSTRAINT_FLAG_FAKE_VALUE; + } + +add: + list_add_tail(¶m_ptr->siblings, parent_list_ptr); + return true; + +free: + free(param_ptr); +fail: + return false; +} + +static void free_params(struct list_head * parent_list_ptr) +{ + struct jack_parameter * param_ptr; + + while (!list_empty(parent_list_ptr)) + { + param_ptr = list_entry(parent_list_ptr->next, struct jack_parameter, siblings); + list_del(¶m_ptr->siblings); + + if ((param_ptr->constraint_flags & JACK_CONSTRAINT_FLAG_VALID) != 0 && + !param_ptr->constraint_range && + param_ptr->constraint.enumeration.possible_values_array != NULL) + { + free(param_ptr->constraint.enumeration.possible_values_array); + } + + free(param_ptr); + } +} + +static void free_containers(struct list_head * parent_list_ptr) +{ + struct jack_parameter_container * container_ptr; + + while (!list_empty(parent_list_ptr)) + { + container_ptr = list_entry(parent_list_ptr->next, struct jack_parameter_container, siblings); + list_del(&container_ptr->siblings); + + if (container_ptr->leaf) + { + free_params(&container_ptr->children); + } + else + { + free_containers(&container_ptr->children); + } + + free(container_ptr->name); + free(container_ptr); + } +} + +static struct jack_parameter_container * find_container(struct jack_parameter_container * parent_ptr, const char * const * address, int max_depth) +{ + struct list_head * node_ptr; + struct jack_parameter_container * container_ptr; + + if (max_depth == 0 || *address == NULL) + { + return parent_ptr; + } + + if (parent_ptr->leaf) + { + return NULL; + } + + if (max_depth > 0) + { + max_depth--; + } + + list_for_each(node_ptr, &parent_ptr->children) + { + container_ptr = list_entry(node_ptr, struct jack_parameter_container, siblings); + if (strcmp(container_ptr->name, *address) == 0) + { + if (container_ptr->symlink != NULL) + { + container_ptr = container_ptr->symlink; + } + + return find_container(container_ptr, address + 1, max_depth); + } + } + + return NULL; +} + +static bool init_leaf(struct list_head * parent_list_ptr, const char * name, const JSList * params_list, void * obj) +{ + struct jack_parameter_container * container_ptr; + + container_ptr = create_container(parent_list_ptr, name); + if (container_ptr == NULL) + { + return false; + } + + container_ptr->leaf = true; + container_ptr->obj = obj; + + while (params_list) + { + if (!add_controlapi_param(&container_ptr->children, params_list->data)) + { + return false; + } + + params_list = jack_slist_next(params_list); + } + + return true; +} + +static bool init_engine(struct jack_params * params_ptr) +{ + return init_leaf(¶ms_ptr->root.children, PTNODE_ENGINE, jackctl_server_get_parameters(params_ptr->server), NULL); +} + +static bool init_drivers(struct jack_params * params_ptr) +{ + const JSList * list; + struct jack_parameter_container * container_ptr; + + container_ptr = create_container(¶ms_ptr->root.children, PTNODE_DRIVERS); + if (container_ptr == NULL) + { + return false; + } + + params_ptr->drivers_ptr = &container_ptr->children; + params_ptr->drivers_count = 0; + + list = jackctl_server_get_drivers_list(params_ptr->server); + while (list) + { + if (!init_leaf(&container_ptr->children, jackctl_driver_get_name(list->data), jackctl_driver_get_parameters(list->data), list->data)) + { + return false; + } + + params_ptr->drivers_count++; + + list = jack_slist_next(list); + } + + return true; +} + +static bool init_internals(struct jack_params * params_ptr) +{ + const JSList * list; + struct jack_parameter_container * container_ptr; + + container_ptr = create_container(¶ms_ptr->root.children, PTNODE_INTERNALS); + if (container_ptr == NULL) + { + return false; + } + + list = jackctl_server_get_internals_list(params_ptr->server); + while (list) + { + if (!init_leaf(&container_ptr->children, jackctl_internal_get_name(list->data), jackctl_internal_get_parameters(list->data), NULL)) + { + return false; + } + + list = jack_slist_next(list); + } + + return true; +} + +static bool init_driver(struct jack_params * params_ptr) +{ + struct jack_parameter_container * container_ptr; + + container_ptr = create_container(¶ms_ptr->root.children, PTNODE_DRIVER); + if (container_ptr == NULL) + { + return false; + } + + params_ptr->driver_ptr = container_ptr; + + return true; +} + +#define params_ptr ((struct jack_params *)obj) + +static bool engine_driver_parameter_is_set(void * obj) +{ + return params_ptr->driver_set; +} + +static bool engine_driver_parameter_reset(void * obj) +{ + if (!jack_params_set_driver(obj, DEFAULT_DRIVER)) + { + return false; + } + + params_ptr->driver_set = false; + + return true; +} + +union jackctl_parameter_value engine_driver_parameter_get_value(void * obj) +{ + union jackctl_parameter_value value; + + strcpy(value.str, params_ptr->driver_ptr->symlink->name); + + return value; +} + +bool engine_driver_parameter_set_value(void * obj, const union jackctl_parameter_value * value_ptr) +{ + return jack_params_set_driver(obj, value_ptr->str); +} + +union jackctl_parameter_value engine_driver_parameter_get_default_value(void * obj) +{ + union jackctl_parameter_value value; + + strcpy(value.str, DEFAULT_DRIVER); + + return value; +} + +#undef params_ptr + +static bool add_engine_driver_enum_constraint(void * context, const char * name) +{ + strcpy((*((struct jack_parameter_enum **)context))->value.str, name); + (*((struct jack_parameter_enum **)context))->short_desc = name; + (*((struct jack_parameter_enum **)context))++; + return true; +} + +static bool init_engine_driver_parameter(struct jack_params * params_ptr) +{ + struct jack_parameter * param_ptr; + const char * address[PARAM_ADDRESS_SIZE] = {PTNODE_ENGINE, NULL}; + struct jack_parameter_container * engine_ptr; + struct jack_parameter_enum * possible_value; + + engine_ptr = find_container(¶ms_ptr->root, address, PARAM_ADDRESS_SIZE); + if (engine_ptr == NULL) + { + return false; + } + + param_ptr = malloc(sizeof(struct jack_parameter)); + if (param_ptr == NULL) + { + jack_error("Ran out of memory trying to allocate struct jack_parameter"); + goto fail; + } + + param_ptr->obj = params_ptr; + param_ptr->vtable.is_set = engine_driver_parameter_is_set; + param_ptr->vtable.reset = engine_driver_parameter_reset; + param_ptr->vtable.get_value = engine_driver_parameter_get_value; + param_ptr->vtable.set_value = engine_driver_parameter_set_value; + param_ptr->vtable.get_default_value = engine_driver_parameter_get_default_value; + + param_ptr->type = JackParamString; + param_ptr->name = "driver"; + param_ptr->short_decr = "Driver to use"; + param_ptr->long_descr = ""; + + param_ptr->constraint_flags = JACK_CONSTRAINT_FLAG_VALID | JACK_CONSTRAINT_FLAG_STRICT | JACK_CONSTRAINT_FLAG_FAKE_VALUE; + param_ptr->constraint_range = false; + param_ptr->constraint.enumeration.count = params_ptr->drivers_count; + param_ptr->constraint.enumeration.possible_values_array = malloc(sizeof(struct jack_parameter_enum) * params_ptr->drivers_count); + if (param_ptr->constraint.enumeration.possible_values_array == NULL) + { + goto free; + } + + address[0] = PTNODE_DRIVERS; + possible_value = param_ptr->constraint.enumeration.possible_values_array; + jack_params_iterate_container((jack_params_handle)params_ptr, address, add_engine_driver_enum_constraint, &possible_value); + + list_add(¶m_ptr->siblings, &engine_ptr->children); + return true; + +free: + free(param_ptr); +fail: + return false; +} + +jack_params_handle jack_params_create(jackctl_server_t * server) +{ + struct jack_params * params_ptr; + + params_ptr = malloc(sizeof(struct jack_params)); + if (params_ptr == NULL) + { + jack_error("Ran out of memory trying to allocate struct jack_params"); + return NULL; + } + + params_ptr->server = server; + INIT_LIST_HEAD(¶ms_ptr->root.children); + params_ptr->root.leaf = false; + params_ptr->root.name = NULL; + + if (!init_engine(params_ptr) || + !init_drivers(params_ptr) || + !init_driver(params_ptr) || + !init_engine_driver_parameter(params_ptr) || + !jack_params_set_driver((jack_params_handle)params_ptr, DEFAULT_DRIVER) || + !init_internals(params_ptr)) + { + jack_params_destroy((jack_params_handle)params_ptr); + return NULL; + } + + params_ptr->driver_set = false; + + assert(strcmp(params_ptr->driver_ptr->symlink->name, DEFAULT_DRIVER) == 0); + + return (jack_params_handle)params_ptr; +} + +#define params_ptr ((struct jack_params *)params) + +void jack_params_destroy(jack_params_handle params) +{ + free_containers(¶ms_ptr->root.children); + free(params); +} + +bool jack_params_set_driver(jack_params_handle params, const char * name) +{ + struct list_head * node_ptr; + struct jack_parameter_container * container_ptr; + + list_for_each(node_ptr, params_ptr->drivers_ptr) + { + container_ptr = list_entry(node_ptr, struct jack_parameter_container, siblings); + if (strcmp(container_ptr->name, name) == 0) + { + params_ptr->driver_ptr->symlink = container_ptr; + params_ptr->driver_set = true; + return true; + } + } + + return false; +} + +jackctl_driver_t * jack_params_get_driver(jack_params_handle params) +{ + return params_ptr->driver_ptr->symlink->obj; +} + +bool jack_params_check_address(jack_params_handle params, const char * const * address, bool want_leaf) +{ + struct jack_parameter_container * container_ptr; + + container_ptr = find_container(¶ms_ptr->root, address, PARAM_ADDRESS_SIZE); + if (container_ptr == NULL) + { + return false; + } + + if (want_leaf && !container_ptr->leaf) + { + return false; + } + + return true; +} + +bool jack_params_is_leaf_container(jack_params_handle params, const char * const * address) +{ + struct jack_parameter_container * container_ptr; + + container_ptr = find_container(¶ms_ptr->root, address, PARAM_ADDRESS_SIZE); + if (container_ptr == NULL) + { + assert(false); + return false; + } + + return container_ptr->leaf; +} + +bool +jack_params_iterate_container( + jack_params_handle params, + const char * const * address, + bool (* callback)(void * context, const char * name), + void * context) +{ + struct jack_parameter_container * container_ptr; + struct list_head * node_ptr; + const char * name; + + container_ptr = find_container(¶ms_ptr->root, address, PARAM_ADDRESS_SIZE); + if (container_ptr == NULL) + { + assert(false); + return true; + } + + list_for_each(node_ptr, &container_ptr->children) + { + if (container_ptr->leaf) + { + name = list_entry(node_ptr, struct jack_parameter, siblings)->name; + } + else + { + name = list_entry(node_ptr, struct jack_parameter_container, siblings)->name; + } + + if (!callback(context, name)) + { + return false; + } + } + + return true; +} + +bool +jack_params_iterate_params( + jack_params_handle params, + const char * const * address, + bool (* callback)(void * context, const struct jack_parameter * param_ptr), + void * context) +{ + struct jack_parameter_container * container_ptr; + struct list_head * node_ptr; + struct jack_parameter * param_ptr; + + container_ptr = find_container(¶ms_ptr->root, address, PARAM_ADDRESS_SIZE); + if (container_ptr == NULL || !container_ptr->leaf) + { + assert(false); + return true; + } + + list_for_each(node_ptr, &container_ptr->children) + { + param_ptr = list_entry(node_ptr, struct jack_parameter, siblings); + if (!callback(context, param_ptr)) + { + return false; + } + } + + return true; +} + +const struct jack_parameter * jack_params_get_parameter(jack_params_handle params, const char * const * address) +{ + int depth; + struct jack_parameter_container * container_ptr; + struct list_head * node_ptr; + struct jack_parameter * param_ptr; + + for (depth = 0; depth < PARAM_ADDRESS_SIZE; depth++) + { + if (address[depth] == NULL) + { + break; + } + } + + depth--; + + container_ptr = find_container(¶ms_ptr->root, address, depth); + if (container_ptr == NULL || !container_ptr->leaf) + { + return NULL; + } + + list_for_each(node_ptr, &container_ptr->children) + { + param_ptr = list_entry(node_ptr, struct jack_parameter, siblings); + if (strcmp(param_ptr->name, address[depth]) == 0) + { + return param_ptr; + } + } + + return NULL; +} + +bool 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; + + container_ptr = find_container(¶ms_ptr->root, address, PARAM_ADDRESS_SIZE); + if (container_ptr == NULL || !container_ptr->leaf) + { + assert(false); + return false; + } + + if (end) + { + list_add_tail(¶m_ptr->siblings, &container_ptr->children); + } + else + { + list_add(¶m_ptr->siblings, &container_ptr->children); + } + + return true; +} + +#undef params_ptr diff --git a/dbus/params.h b/dbus/params.h new file mode 100644 index 00000000..d880a7dd --- /dev/null +++ b/dbus/params.h @@ -0,0 +1,110 @@ +/* -*- Mode: C ; c-basic-offset: 4 -*- */ +/* + Copyright (C) 2011 Nedko Arnaudov + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef PARAMS_H__A23EDE06_C1C9_4489_B253_FD1B26B66929__INCLUDED +#define PARAMS_H__A23EDE06_C1C9_4489_B253_FD1B26B66929__INCLUDED + +#include "jack/control.h" +#include "list.h" + +#define PARAM_ADDRESS_SIZE 3 + +#define PTNODE_ENGINE "engine" +#define PTNODE_DRIVER "driver" +#define PTNODE_DRIVERS "drivers" +#define PTNODE_INTERNALS "internals" + +struct jack_parameter_vtable +{ + bool (* is_set)(void * obj); + bool (* reset)(void * obj); + union jackctl_parameter_value (* get_value)(void * obj); + bool (* set_value)(void * obj, const union jackctl_parameter_value * value_ptr); + union jackctl_parameter_value (* get_default_value)(void * obj); +}; + +#define JACK_CONSTRAINT_FLAG_VALID ((uint32_t)1) /**< if not set, there is no constraint */ +#define JACK_CONSTRAINT_FLAG_STRICT ((uint32_t)2) /**< if set, constraint is strict, i.e. supplying non-matching value will not work */ +#define JACK_CONSTRAINT_FLAG_FAKE_VALUE ((uint32_t)4) /**< if set, values have no user meaningful meaning */ + +struct jack_parameter_enum +{ + union jackctl_parameter_value value; + const char * short_desc; +}; + +struct jack_parameter +{ + void * obj; + struct jack_parameter_vtable vtable; + struct list_head siblings; + jackctl_param_type_t type; + const char * name; + const char * short_decr; + const char * long_descr; + + uint32_t constraint_flags; /**< JACK_CONSTRAINT_FLAG_XXX */ + bool constraint_range; /**< if true, constraint is a range (min-max), otherwise it is an enumeration */ + + union + { + struct + { + union jackctl_parameter_value min; + union jackctl_parameter_value max; + } range; /**< valid when JACK_CONSTRAINT_FLAG_RANGE flag is set */ + + struct + { + uint32_t count; + struct jack_parameter_enum * possible_values_array; + } enumeration; /**< valid when JACK_CONSTRAINT_FLAG_RANGE flag is not set */ + } constraint; +}; + +typedef struct _jack_params { int unused; } * jack_params_handle; + +jack_params_handle jack_params_create(jackctl_server_t * server); +void jack_params_destroy(jack_params_handle params); + +bool jack_params_set_driver(jack_params_handle params, const char * name); +jackctl_driver_t * jack_params_get_driver(jack_params_handle params); + +bool jack_params_check_address(jack_params_handle params, const char * const * address, bool want_leaf); +bool jack_params_is_leaf_container(jack_params_handle params, const char * const * address); + +bool +jack_params_iterate_container( + jack_params_handle params, + const char * const * address, + bool (* callback)(void * context, const char * name), + void * context); + +bool +jack_params_iterate_params( + jack_params_handle params, + const char * const * address, + bool (* callback)(void * context, const struct jack_parameter * param_ptr), + void * context); + +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); + +#endif /* #ifndef PARAMS_H__A23EDE06_C1C9_4489_B253_FD1B26B66929__INCLUDED */ diff --git a/dbus/wscript b/dbus/wscript index 6aa716d2..2045c33f 100644 --- a/dbus/wscript +++ b/dbus/wscript @@ -52,6 +52,7 @@ def build(bld): obj.source = [ 'jackdbus.c', 'controller.c', + 'params.c', 'controller_iface_configure.c', 'controller_iface_control.c', 'controller_iface_introspectable.c', diff --git a/dbus/xml.c b/dbus/xml.c index b506c5d5..c7e11377 100644 --- a/dbus/xml.c +++ b/dbus/xml.c @@ -1,6 +1,6 @@ /* -*- Mode: C ; c-basic-offset: 4 -*- */ /* - Copyright (C) 2007,2008 Nedko Arnaudov + Copyright (C) 2007,2008,2011 Nedko Arnaudov This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,358 +25,116 @@ #include #include #include +#include #include #include "controller_internal.h" void -jack_controller_settings_set_bool_option( - const char *value_str, - int *value_ptr) -{ - if (strcmp(value_str, "true") == 0) - { - *value_ptr = true; - } - else if (strcmp(value_str, "false") == 0) - { - *value_ptr = false; - } - else - { - jack_error("ignoring unknown bool value \"%s\"", value_str); - } -} - -void -jack_controller_settings_set_sint_option( - const char *value_str, - int *value_ptr) -{ - *value_ptr = atoi(value_str); -} - -void -jack_controller_settings_set_uint_option( - const char *value_str, - unsigned int *value_ptr) -{ - *value_ptr = strtoul(value_str, NULL, 10); -} - -void -jack_controller_settings_set_char_option( - const char *value_str, - char *value_ptr) -{ - if (value_str[0] == 0 || value_str[1] != 0) - { - jack_error("invalid char option value \"%s\"", value_str); - return; - } - - *value_ptr = *value_str; -} - -void -jack_controller_settings_set_string_option( - const char *value_str, - char *value_ptr, - size_t max_size) -{ - size_t size; - - size = strlen(value_str); - - if (size >= max_size) - { - jack_error("string option value \"%s\" is too long, max is %u chars (including terminating zero)", value_str, (unsigned int)max_size); - return; - } - - strcpy(value_ptr, value_str); -} - -void -jack_controller_settings_set_driver_option( - jackctl_driver_t *driver, - const char *option_name, - const char *option_value) +jack_controller_deserialize_parameter_value( + struct jack_controller *controller_ptr, + const char * const * address, + const char * option_value) { - jackctl_parameter_t *parameter; - jackctl_param_type_t type; - int value_int = 0; - unsigned int value_uint = 0; + const struct jack_parameter * param_ptr; union jackctl_parameter_value value; + size_t size; - jack_info("setting driver option \"%s\" to value \"%s\"", option_name, option_value); - - parameter = jack_controller_find_parameter(jackctl_driver_get_parameters(driver), option_name); - if (parameter == NULL) + param_ptr = jack_params_get_parameter(controller_ptr->params, address); + if (param_ptr == NULL) { - jack_error( - "Unknown parameter \"%s\" of driver \"%s\"", - option_name, - jackctl_driver_get_name(driver)); - return; + jack_error("Unknown parameter"); + goto ignore; } - type = jackctl_parameter_get_type(parameter); + jack_info("setting parameter '%s':'%s':'%s' to value \"%s\"", address[0], address[1], address[2], option_value); - switch (type) + switch (param_ptr->type) { case JackParamInt: - jack_controller_settings_set_sint_option(option_value, &value_int); - value.i = value_int; + value.i = atoi(option_value); break; case JackParamUInt: - jack_controller_settings_set_uint_option(option_value, &value_uint); - value.ui = value_uint; + value.ui = strtoul(option_value, NULL, 10); break; case JackParamChar: - jack_controller_settings_set_char_option(option_value, &value.c); + if (option_value[0] == 0 || option_value[1] != 0) + { + jack_error("invalid char option value \"%s\"", option_value); + goto ignore; + } + value.c = *option_value; break; case JackParamString: - jack_controller_settings_set_string_option(option_value, value.str, sizeof(value.str)); + size = strlen(option_value); + if (size >= sizeof(value.str)) + { + jack_error("string option value \"%s\" is too long, max is %zu chars (including terminating zero)", option_value, sizeof(value.str)); + goto ignore; + } + + strcpy(value.str, option_value); break; case JackParamBool: - jack_controller_settings_set_bool_option(option_value, &value_int); - value.i = value_int; + if (strcmp(option_value, "true") == 0) + { + value.b = true; + } + else if (strcmp(option_value, "false") == 0) + { + value.b = false; + } + else + { + jack_error("ignoring unknown bool value \"%s\"", option_value); + goto ignore; + } break; default: - jack_error("Parameter \"%s\" of driver \"%s\" is of unknown type %d", - jackctl_parameter_get_name(parameter), - jackctl_driver_get_name(driver), - type); + jack_error("Unknown type %d", (int)param_ptr->type); + goto ignore; } - jackctl_parameter_set_value(parameter, &value); -} - -void -jack_controller_settings_set_internal_option( - jackctl_internal_t *internal, - const char *option_name, - const char *option_value) -{ - jackctl_parameter_t *parameter; - jackctl_param_type_t type; - int value_int = 0; - unsigned int value_uint = 0; - union jackctl_parameter_value value; - - jack_info("setting internal option \"%s\" to value \"%s\"", option_name, option_value); - - parameter = jack_controller_find_parameter(jackctl_internal_get_parameters(internal), option_name); - if (parameter == NULL) + if (param_ptr->vtable.set_value(param_ptr->obj, &value)) { - jack_error( - "Unknown parameter \"%s\" of internal \"%s\"", - option_name, - jackctl_internal_get_name(internal)); return; } - type = jackctl_parameter_get_type(parameter); - - switch (type) - { - case JackParamInt: - jack_controller_settings_set_sint_option(option_value, &value_int); - value.i = value_int; - break; - case JackParamUInt: - jack_controller_settings_set_uint_option(option_value, &value_uint); - value.ui = value_uint; - break; - case JackParamChar: - jack_controller_settings_set_char_option(option_value, &value.c); - break; - case JackParamString: - jack_controller_settings_set_string_option(option_value, value.str, sizeof(value.str)); - break; - case JackParamBool: - jack_controller_settings_set_bool_option(option_value, &value_int); - value.i = value_int; - break; - default: - jack_error("Parameter \"%s\" of internal \"%s\" is of unknown type %d", - jackctl_parameter_get_name(parameter), - jackctl_internal_get_name(internal), - type); - } + jack_error("Parameter set failed"); - jackctl_parameter_set_value(parameter, &value); +ignore: + jack_error("Ignoring restore attempt of parameter '%s':'%s':'%s'", address[0], address[1], address[2]); } void -jack_controller_settings_set_engine_option( - struct jack_controller *controller_ptr, - const char *option_name, - const char *option_value) +jack_controller_serialize_parameter_value( + const struct jack_parameter * param_ptr, + char * value_buffer) { - jackctl_parameter_t *parameter; - jackctl_param_type_t type; - int value_int = 0; - unsigned int value_uint = 0; union jackctl_parameter_value value; - jack_info("setting engine option \"%s\" to value \"%s\"", option_name, option_value); + value = param_ptr->vtable.get_value(param_ptr->obj); - if (strcmp(option_name, "driver") == 0) - { - if (!jack_controller_select_driver(controller_ptr, option_value)) - { - jack_error("unknown driver '%s'", option_value); - } - - return; - } - - parameter = jack_controller_find_parameter(jackctl_server_get_parameters(controller_ptr->server), option_name); - if (parameter == NULL) - { - jack_error( - "Unknown engine parameter \"%s\"", - option_name); - return; - } - - type = jackctl_parameter_get_type(parameter); - - switch (type) + switch (param_ptr->type) { case JackParamInt: - jack_controller_settings_set_sint_option(option_value, &value_int); - value.i = value_int; - break; + sprintf(value_buffer, "%d", (int)value.i); + return; case JackParamUInt: - jack_controller_settings_set_uint_option(option_value, &value_uint); - value.ui = value_uint; - break; + sprintf(value_buffer, "%u", (unsigned int)value.ui); + return; case JackParamChar: - jack_controller_settings_set_char_option(option_value, &value.c); - break; + sprintf(value_buffer, "%c", (char)value.c); + return; case JackParamString: - jack_controller_settings_set_string_option(option_value, value.str, sizeof(value.str)); - break; + strcpy(value_buffer, value.str); + return; case JackParamBool: - jack_controller_settings_set_bool_option(option_value, &value_int); - value.i = value_int; - break; - default: - jack_error("Engine parameter \"%s\" is of unknown type %d", - jackctl_parameter_get_name(parameter), - type); - } - - jackctl_parameter_set_value(parameter, &value); -} - -static -bool -jack_controller_settings_save_options( - void *context, - const JSList * parameters_list, - void *dbus_call_context_ptr) -{ - jackctl_parameter_t *parameter; - jackctl_param_type_t type; - union jackctl_parameter_value value; - const char * name; - char value_str[50]; - - while (parameters_list != NULL) - { - parameter = (jackctl_parameter_t *)parameters_list->data; - - if (jackctl_parameter_is_set(parameter)) - { - type = jackctl_parameter_get_type(parameter); - value = jackctl_parameter_get_value(parameter); - name = jackctl_parameter_get_name(parameter); - - switch (type) - { - case JackParamInt: - sprintf(value_str, "%d", (int)value.i); - if (!jack_controller_settings_write_option(context, name, value_str, dbus_call_context_ptr)) - { - return false; - } - break; - case JackParamUInt: - sprintf(value_str, "%u", (unsigned int)value.ui); - if (!jack_controller_settings_write_option(context, name, value_str, dbus_call_context_ptr)) - { - return false; - } - break; - case JackParamChar: - sprintf(value_str, "%c", (char)value.c); - if (!jack_controller_settings_write_option(context, name, value_str, dbus_call_context_ptr)) - { - return false; - } - break; - case JackParamString: - if (!jack_controller_settings_write_option(context, name, value.str, dbus_call_context_ptr)) - { - return false; - } - break; - case JackParamBool: - if (!jack_controller_settings_write_option(context, name, value.b ? "true" : "false", dbus_call_context_ptr)) - { - return false; - } - break; - default: - jack_error("parameter of unknown type %d", type); - } - } - - parameters_list = jack_slist_next(parameters_list); - } - - return true; -} - -bool -jack_controller_settings_save_engine_options( - void *context, - struct jack_controller *controller_ptr, - void *dbus_call_context_ptr) -{ - if (controller_ptr->driver != NULL) - { - if (!jack_controller_settings_write_option( - context, - "driver", - jackctl_driver_get_name(controller_ptr->driver), - dbus_call_context_ptr)) - { - return false; - } + strcpy(value_buffer, value.b ? "true" : "false"); + return; } - return jack_controller_settings_save_options(context, jackctl_server_get_parameters(controller_ptr->server), dbus_call_context_ptr); -} - -bool -jack_controller_settings_save_driver_options( - void *context, - jackctl_driver_t *driver, - void *dbus_call_context_ptr) -{ - return jack_controller_settings_save_options(context, jackctl_driver_get_parameters(driver), dbus_call_context_ptr); -} - -bool -jack_controller_settings_save_internal_options( - void *context, - jackctl_internal_t *internal, - void *dbus_call_context_ptr) -{ - return jack_controller_settings_save_options(context, jackctl_internal_get_parameters(internal), dbus_call_context_ptr); + jack_error("parameter of unknown type %d", (int)param_ptr->type); + assert(false); + *value_buffer = 0; } diff --git a/dbus/xml_expat.c b/dbus/xml_expat.c index 1ee1bd2e..f5a5aa68 100644 --- a/dbus/xml_expat.c +++ b/dbus/xml_expat.c @@ -1,6 +1,6 @@ /* -*- Mode: C ; c-basic-offset: 4 -*- */ /* - Copyright (C) 2007,2008 Nedko Arnaudov + Copyright (C) 2007,2008,2011 Nedko Arnaudov This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -46,27 +47,16 @@ jack_controller_settings_uninit() { } -#define PARSE_CONTEXT_ROOT 0 -#define PARSE_CONTEXT_JACK 1 -#define PARSE_CONTEXT_ENGINE 1 -#define PARSE_CONTEXT_DRIVERS 2 -#define PARSE_CONTEXT_DRIVER 3 -#define PARSE_CONTEXT_OPTION 4 -#define PARSE_CONTEXT_INTERNALS 5 -#define PARSE_CONTEXT_INTERNAL 6 - -#define MAX_STACK_DEPTH 10 - struct parse_context { struct jack_controller *controller_ptr; XML_Bool error; - unsigned int element[MAX_STACK_DEPTH]; - signed int depth; - jackctl_driver_t *driver; - jackctl_internal_t *internal; + bool option_value_capture; char option[JACK_PARAM_STRING_MAX+1]; int option_used; + const char * address[PARAM_ADDRESS_SIZE]; + int address_index; + char * container; char *name; }; @@ -80,7 +70,7 @@ jack_controller_settings_callback_chrdata(void *data, const XML_Char *s, int len return; } - if (context_ptr->element[context_ptr->depth] == PARSE_CONTEXT_OPTION) + if (context_ptr->option_value_capture) { if (context_ptr->option_used + len >= JACK_PARAM_STRING_MAX) { @@ -97,107 +87,69 @@ jack_controller_settings_callback_chrdata(void *data, const XML_Char *s, int len void jack_controller_settings_callback_elstart(void *data, const char *el, const char **attr) { - jackctl_driver_t *driver; - jackctl_internal_t *internal; - if (context_ptr->error) { return; } - if (context_ptr->depth + 1 >= MAX_STACK_DEPTH) + if (context_ptr->address_index >= PARAM_ADDRESS_SIZE) { - jack_error("xml parse max stack depth reached"); + assert(context_ptr->address_index == PARAM_ADDRESS_SIZE); + jack_error("xml param address max depth reached"); context_ptr->error = XML_TRUE; return; } + //jack_info("<%s>", el); + if (strcmp(el, "jack") == 0) { - //jack_info(""); - context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_JACK; return; } - if (strcmp(el, "engine") == 0) + if (strcmp(el, PTNODE_ENGINE) == 0) { - //jack_info(""); - context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_ENGINE; + context_ptr->address[context_ptr->address_index++] = PTNODE_ENGINE; return; } - if (strcmp(el, "drivers") == 0) + if (strcmp(el, PTNODE_DRIVERS) == 0) { - //jack_info(""); - context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_DRIVERS; + context_ptr->address[context_ptr->address_index++] = PTNODE_DRIVERS; return; } - if (strcmp(el, "internals") == 0) + if (strcmp(el, PTNODE_INTERNALS) == 0) { - //jack_info(""); - context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_INTERNALS; + context_ptr->address[context_ptr->address_index++] = PTNODE_INTERNALS; return; } - if (strcmp(el, "driver") == 0) + if (strcmp(el, "driver") == 0 || + strcmp(el, "internal") == 0) { if ((attr[0] == NULL || attr[2] != NULL) || strcmp(attr[0], "name") != 0) { - jack_error(" XML element must contain exactly one attribute, named \"name\""); + jack_error("<%s> XML element must contain exactly one attribute, named \"name\"", el); context_ptr->error = XML_TRUE; return; } - //jack_info(""); - context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_DRIVER; - - driver = jack_controller_find_driver(context_ptr->controller_ptr->server, attr[1]); - if (driver == NULL) - { - jack_error("ignoring settings for unknown driver \"%s\"", attr[1]); - } - else - { - jack_info("setting for driver \"%s\" found", attr[1]); - } - - context_ptr->driver = driver; - - return; - } - - if (strcmp(el, "internal") == 0) - { - if ((attr[0] == NULL || attr[2] != NULL) || strcmp(attr[0], "name") != 0) + context_ptr->container = strdup(attr[1]); + if (context_ptr->container == NULL) { - jack_error(" XML element must contain exactly one attribute, named \"name\""); + jack_error("strdup() failed"); context_ptr->error = XML_TRUE; return; } - //jack_info(""); - context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_INTERNAL; - - internal = jack_controller_find_internal(context_ptr->controller_ptr->server, attr[1]); - if (internal == NULL) - { - jack_error("ignoring settings for unknown internal \"%s\"", attr[1]); - } - else - { - jack_info("setting for internal \"%s\" found", attr[1]); - } - - context_ptr->internal = internal; + context_ptr->address[context_ptr->address_index++] = context_ptr->container; return; } - - + if (strcmp(el, "option") == 0) { - //jack_info("\n", dbus_call_context_ptr)) - { - return false; - } + return + jack_controller_settings_write_string(fd, ctx_ptr->indent, ctx_ptr->call) && + jack_controller_settings_write_string(fd, "\n", ctx_ptr->call); +} - return true; +bool serialize_modules(void * context, const char * name) +{ + ctx_ptr->indent = " "; + ctx_ptr->address[1] = name; + ctx_ptr->address[2] = NULL; + + return + jack_controller_settings_write_string(fd, " <", ctx_ptr->call) && + jack_controller_settings_write_string(fd, ctx_ptr->str, ctx_ptr->call) && + jack_controller_settings_write_string(fd, " name=\"", ctx_ptr->call) && + jack_controller_settings_write_string(fd, name, ctx_ptr->call) && + jack_controller_settings_write_string(fd, "\">\n", ctx_ptr->call) && + jack_params_iterate_params(ctx_ptr->params, ctx_ptr->address, jack_controller_serialize_parameter, ctx_ptr) && + jack_controller_settings_write_string(fd, " call) && + jack_controller_settings_write_string(fd, ctx_ptr->str, ctx_ptr->call) && + jack_controller_settings_write_string(fd, ">\n", ctx_ptr->call); } #undef fd +#undef ctx_ptr bool jack_controller_settings_save( @@ -114,9 +117,9 @@ jack_controller_settings_save( time_t timestamp; char timestamp_str[26]; struct save_context context; - const JSList * node_ptr; - jackctl_driver_t *driver; - jackctl_internal_t *internal; + const char * modules[] = {"driver", "internal", NULL}; + char buffer[100]; + unsigned int i; time(×tamp); ctime_r(×tamp, timestamp_str); @@ -147,6 +150,7 @@ jack_controller_settings_save( } context.fd = fd; + context.call = dbus_call_context_ptr; if (!jack_controller_settings_write_string(fd, "\n", dbus_call_context_ptr)) { @@ -196,7 +200,9 @@ jack_controller_settings_save( } context.indent = " "; - if (!jack_controller_settings_save_engine_options(&context, controller_ptr, dbus_call_context_ptr)) + context.address[0] = PTNODE_ENGINE; + context.address[1] = NULL; + if (!jack_params_iterate_params(controller_ptr->params, context.address, jack_controller_serialize_parameter, &context)) { goto exit_close; } @@ -206,100 +212,50 @@ jack_controller_settings_save( goto exit_close; } - /* drivers */ - - if (!jack_controller_settings_write_string(fd, " \n", dbus_call_context_ptr)) + for (i = 0; modules[i] != NULL; i++) { - goto exit_close; - } - - node_ptr = jackctl_server_get_drivers_list(controller_ptr->server); - - while (node_ptr != NULL) - { - driver = (jackctl_driver_t *)node_ptr->data; - - if (!jack_controller_settings_write_string(fd, " \n", dbus_call_context_ptr)) + if (!jack_controller_settings_write_string(fd, " <", dbus_call_context_ptr)) { goto exit_close; } - context.indent = " "; - - if (!jack_controller_settings_save_driver_options(&context, driver, dbus_call_context_ptr)) + if (!jack_controller_settings_write_string(fd, modules[i], dbus_call_context_ptr)) { goto exit_close; } - if (!jack_controller_settings_write_string(fd, " \n", dbus_call_context_ptr)) + if (!jack_controller_settings_write_string(fd, "s>\n", dbus_call_context_ptr)) { goto exit_close; } - node_ptr = jack_slist_next(node_ptr); - } + context.indent = " "; + context.params = controller_ptr->params; + context.str = modules[i]; + strcpy(buffer, modules[i]); + strcat(buffer, "s"); + context.address[0] = buffer; + context.address[1] = NULL; - if (!jack_controller_settings_write_string(fd, " \n", dbus_call_context_ptr)) - { - goto exit_close; - } - - /* internals */ - - if (!jack_controller_settings_write_string(fd, " \n", dbus_call_context_ptr)) - { - goto exit_close; - } - - node_ptr = jackctl_server_get_internals_list(controller_ptr->server); - - while (node_ptr != NULL) - { - internal = (jackctl_internal_t *)node_ptr->data; - - if (!jack_controller_settings_write_string(fd, " params, context.address, serialize_modules, &context)) { goto exit_close; } - if (!jack_controller_settings_write_string(fd, jackctl_internal_get_name(internal), dbus_call_context_ptr)) + if (!jack_controller_settings_write_string(fd, " \n", dbus_call_context_ptr)) + if (!jack_controller_settings_write_string(fd, modules[i], dbus_call_context_ptr)) { goto exit_close; } - context.indent = " "; - - if (!jack_controller_settings_save_internal_options(&context, internal, dbus_call_context_ptr)) + if (!jack_controller_settings_write_string(fd, "s>\n", dbus_call_context_ptr)) { goto exit_close; } - - if (!jack_controller_settings_write_string(fd, " \n", dbus_call_context_ptr)) - { - goto exit_close; - } - - node_ptr = jack_slist_next(node_ptr); - } - - if (!jack_controller_settings_write_string(fd, " \n", dbus_call_context_ptr)) - { - goto exit_close; } if (!jack_controller_settings_write_string(fd, "\n", dbus_call_context_ptr))