Browse Source

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
tags/1.9.8
nedko 13 years ago
parent
commit
343a0e8069
9 changed files with 1250 additions and 2004 deletions
  1. +15
    -74
      dbus/controller.c
  2. +209
    -1366
      dbus/controller_iface_configure.c
  3. +10
    -48
      dbus/controller_internal.h
  4. +717
    -0
      dbus/params.c
  5. +110
    -0
      dbus/params.h
  6. +1
    -0
      dbus/wscript
  7. +67
    -309
      dbus/xml.c
  8. +62
    -104
      dbus/xml_expat.c
  9. +59
    -103
      dbus/xml_write_raw.c

+ 15
- 74
dbus/controller.c View File

@@ -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);


+ 209
- 1366
dbus/controller_iface_configure.c
File diff suppressed because it is too large
View File


+ 10
- 48
dbus/controller_internal.h View File

@@ -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(


+ 717
- 0
dbus/params.c View File

@@ -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 <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->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, &param_ptr->constraint.range.min, &param_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(&param_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(&param_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(&params_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(&params_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(&params_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(&params_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(&params_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(&param_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(&params_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(&params_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(&params_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(&params_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(&params_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(&params_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(&params_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(&params_ptr->root, address, PARAM_ADDRESS_SIZE);
if (container_ptr == NULL || !container_ptr->leaf)
{
assert(false);
return false;
}

if (end)
{
list_add_tail(&param_ptr->siblings, &container_ptr->children);
}
else
{
list_add(&param_ptr->siblings, &container_ptr->children);
}

return true;
}

#undef params_ptr

+ 110
- 0
dbus/params.h View File

@@ -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 */

+ 1
- 0
dbus/wscript View File

@@ -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',


+ 67
- 309
dbus/xml.c View File

@@ -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 <stdint.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <dbus/dbus.h>

#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;
}

+ 62
- 104
dbus/xml_expat.c View File

@@ -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 <fcntl.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
#include <expat.h>
#include <dbus/dbus.h>

@@ -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("<jack>");
context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_JACK;
return;
}

if (strcmp(el, "engine") == 0)
if (strcmp(el, PTNODE_ENGINE) == 0)
{
//jack_info("<engine>");
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("<drivers>");
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("<internals>");
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("<driver> 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("<driver>");
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("<internal> XML element must contain exactly one attribute, named \"name\"");
jack_error("strdup() failed");
context_ptr->error = XML_TRUE;
return;
}

//jack_info("<internal>");
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("<option>");
if ((attr[0] == NULL || attr[2] != NULL) || strcmp(attr[0], "name") != 0)
{
jack_error("<option> XML element must contain exactly one attribute, named \"name\"");
@@ -213,7 +165,8 @@ jack_controller_settings_callback_elstart(void *data, const char *el, const char
return;
}

context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_OPTION;
context_ptr->address[context_ptr->address_index++] = context_ptr->name;
context_ptr->option_value_capture = true;
context_ptr->option_used = 0;
return;
}
@@ -225,49 +178,48 @@ jack_controller_settings_callback_elstart(void *data, const char *el, const char
void
jack_controller_settings_callback_elend(void *data, const char *el)
{
int i;

if (context_ptr->error)
{
return;
}

//jack_info("element end (depth = %d, element = %u)", context_ptr->depth, context_ptr->element[context_ptr->depth]);
//jack_info("</%s> (depth = %d)", el, context_ptr->address_index);

if (context_ptr->element[context_ptr->depth] == PARSE_CONTEXT_OPTION)
if (strcmp(el, "option") == 0)
{
assert(context_ptr->option_value_capture);
context_ptr->option[context_ptr->option_used] = 0;

if (context_ptr->depth == 2 &&
context_ptr->element[0] == PARSE_CONTEXT_JACK &&
context_ptr->element[1] == PARSE_CONTEXT_ENGINE)
for (i = context_ptr->address_index; i < PARAM_ADDRESS_SIZE; i++)
{
jack_controller_settings_set_engine_option(context_ptr->controller_ptr, context_ptr->name, context_ptr->option);
context_ptr->address[context_ptr->address_index] = NULL;
}

if (context_ptr->depth == 3 &&
context_ptr->element[0] == PARSE_CONTEXT_JACK &&
context_ptr->element[1] == PARSE_CONTEXT_DRIVERS &&
context_ptr->element[2] == PARSE_CONTEXT_DRIVER &&
context_ptr->driver != NULL)
{
jack_controller_settings_set_driver_option(context_ptr->driver, context_ptr->name, context_ptr->option);
}
if (context_ptr->depth == 3 &&
context_ptr->element[0] == PARSE_CONTEXT_JACK &&
context_ptr->element[1] == PARSE_CONTEXT_INTERNALS &&
context_ptr->element[2] == PARSE_CONTEXT_INTERNAL &&
context_ptr->internal != NULL)
{
jack_controller_settings_set_internal_option(context_ptr->internal, context_ptr->name, context_ptr->option);
}
}
jack_controller_deserialize_parameter_value(context_ptr->controller_ptr, context_ptr->address, context_ptr->option);

context_ptr->depth--;

if (context_ptr->name != NULL)
{
free(context_ptr->name);
context_ptr->name = NULL;
context_ptr->option_value_capture = false;
context_ptr->address_index--;
}
else if (context_ptr->container != NULL)
{
//jack_info("'%s'", context_ptr->container);
free(context_ptr->container);
context_ptr->container = NULL;
context_ptr->address_index--;
}
else if (strcmp(el, PTNODE_ENGINE) == 0 ||
strcmp(el, PTNODE_DRIVERS) == 0 ||
strcmp(el, PTNODE_INTERNALS) == 0)
{
context_ptr->address_index--;
}
else
{
//jack_info("no depth decrement");
}
}

@@ -341,14 +293,20 @@ jack_controller_settings_load(

context.controller_ptr = controller_ptr;
context.error = XML_FALSE;
context.depth = -1;
context.option_value_capture = false;
context.address_index = 0;
context.name = NULL;
context.container = NULL;

XML_SetElementHandler(parser, jack_controller_settings_callback_elstart, jack_controller_settings_callback_elend);
XML_SetCharacterDataHandler(parser, jack_controller_settings_callback_chrdata);
XML_SetUserData(parser, &context);

xmls = XML_ParseBuffer(parser, bytes_read, XML_TRUE);

free(context.name);
free(context.container);

if (xmls == XML_STATUS_ERROR)
{
jack_error("XML_ParseBuffer() failed.");


+ 59
- 103
dbus/xml_write_raw.c View File

@@ -53,54 +53,57 @@ jack_controller_settings_write_string(int fd, const char * string, void *dbus_ca

struct save_context
{
void * call;
int fd;
const char *indent;
const char * indent;
jack_params_handle params;
const char * address[PARAM_ADDRESS_SIZE];
const char * str;
};

#define save_context_ptr ((struct save_context *)context)
#define fd (save_context_ptr->fd)
#define ctx_ptr ((struct save_context *)context)
#define fd (ctx_ptr->fd)

bool
jack_controller_settings_write_option(
void *context,
const char *name,
const char *content,
void *dbus_call_context_ptr)
static bool jack_controller_serialize_parameter(void * context, const struct jack_parameter * param_ptr)
{
if (!jack_controller_settings_write_string(fd, save_context_ptr->indent, dbus_call_context_ptr))
{
return false;
}

if (!jack_controller_settings_write_string(fd, "<option name=\"", dbus_call_context_ptr))
{
return false;
}
char value[JACK_PARAM_STRING_MAX + 1];

if (!jack_controller_settings_write_string(fd, name, dbus_call_context_ptr))
if (!param_ptr->vtable.is_set(param_ptr->obj))
{
return false;
return true;
}

if (!jack_controller_settings_write_string(fd, "\">", dbus_call_context_ptr))
{
return false;
}
jack_controller_serialize_parameter_value(param_ptr, value);

if (!jack_controller_settings_write_string(fd, content, dbus_call_context_ptr))
{
return false;
}

if (!jack_controller_settings_write_string(fd, "</option>\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, "<option name=\"", ctx_ptr->call) &&
jack_controller_settings_write_string(fd, param_ptr->name, ctx_ptr->call) &&
jack_controller_settings_write_string(fd, "\">", ctx_ptr->call) &&
jack_controller_settings_write_string(fd, value, ctx_ptr->call) &&
jack_controller_settings_write_string(fd, "</option>\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, " </", ctx_ptr->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(&timestamp);
ctime_r(&timestamp, 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, "<?xml version=\"1.0\"?>\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, " <drivers>\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, " <driver name=\"", dbus_call_context_ptr))
{
goto exit_close;
}

if (!jack_controller_settings_write_string(fd, jackctl_driver_get_name(driver), 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, " <", 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, " </driver>\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, " </drivers>\n", dbus_call_context_ptr))
{
goto exit_close;
}
/* internals */
if (!jack_controller_settings_write_string(fd, " <internals>\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, " <internal name=\"", dbus_call_context_ptr))
if (!jack_params_iterate_container(controller_ptr->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, " </", 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, 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, " </internal>\n", dbus_call_context_ptr))
{
goto exit_close;
}

node_ptr = jack_slist_next(node_ptr);
}

if (!jack_controller_settings_write_string(fd, " </internals>\n", dbus_call_context_ptr))
{
goto exit_close;
}

if (!jack_controller_settings_write_string(fd, "</jack>\n", dbus_call_context_ptr))


Loading…
Cancel
Save