| 
							- /* -*- 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 <stdbool.h>
 - #include <string.h>
 - #include <assert.h>
 - #include <dbus/dbus.h>
 - 
 - #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->ext = false;
 -     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->ext)
 -         {
 -             continue;
 -         }
 - 
 -         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->ext = false;
 -     param_ptr->obj = params_ptr;
 -     param_ptr->vtable.is_set = engine_driver_parameter_is_set;
 -     param_ptr->vtable.reset = engine_driver_parameter_reset;
 -     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;
 - }
 - 
 - void jack_params_add_parameter(jack_params_handle params, const char * const * address, bool end, struct jack_parameter * param_ptr)
 - {
 -     struct jack_parameter_container * container_ptr;
 - 
 -     container_ptr = find_container(¶ms_ptr->root, address, PARAM_ADDRESS_SIZE);
 -     if (container_ptr == NULL || !container_ptr->leaf)
 -     {
 -         assert(false);
 -         return;
 -     }
 - 
 -     param_ptr->ext = true;
 - 
 -     if (end)
 -     {
 -         list_add_tail(¶m_ptr->siblings, &container_ptr->children);
 -     }
 -     else
 -     {
 -         list_add(¶m_ptr->siblings, &container_ptr->children);
 -     }
 - 
 -     return;
 - }
 - 
 - #undef params_ptr
 
 
  |