Restore JACK parameters during studio load. Closes #2
This commit is contained in:
parent
19c46c885c
commit
be4d6f2fdb
323
daemon/studio.c
323
daemon/studio.c
|
@ -31,6 +31,7 @@
|
|||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <expat.h>
|
||||
|
||||
#include "../jack_proxy.h"
|
||||
#include "patchbay.h"
|
||||
|
@ -115,6 +116,26 @@ struct conf_callback_context
|
|||
struct jack_conf_container * parent_ptr;
|
||||
};
|
||||
|
||||
#define PARSE_CONTEXT_ROOT 0
|
||||
#define PARSE_CONTEXT_STUDIO 1
|
||||
#define PARSE_CONTEXT_JACK 2
|
||||
#define PARSE_CONTEXT_CONF 3
|
||||
#define PARSE_CONTEXT_PARAMETER 4
|
||||
|
||||
#define MAX_STACK_DEPTH 10
|
||||
#define MAX_DATA_SIZE 1024
|
||||
|
||||
struct parse_context
|
||||
{
|
||||
void * call_ptr;
|
||||
XML_Bool error;
|
||||
unsigned int element[MAX_STACK_DEPTH];
|
||||
signed int depth;
|
||||
char data[MAX_DATA_SIZE];
|
||||
int data_used;
|
||||
char * path;
|
||||
};
|
||||
|
||||
bool
|
||||
jack_conf_container_create(
|
||||
struct jack_conf_container ** container_ptr_ptr,
|
||||
|
@ -273,7 +294,7 @@ conf_callback(
|
|||
|
||||
if (parent_ptr == NULL && strcmp(child, "drivers") == 0)
|
||||
{
|
||||
lash_info("ignoring drivers branch");
|
||||
lash_debug("ignoring drivers branch");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1065,12 +1086,232 @@ bool studios_iterate(void * call_ptr, void * context, bool (* callback)(void * c
|
|||
return true;
|
||||
}
|
||||
|
||||
#define context_ptr ((struct parse_context *)data)
|
||||
|
||||
static void callback_chrdata(void * data, const XML_Char * s, int len)
|
||||
{
|
||||
if (context_ptr->error)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (context_ptr->element[context_ptr->depth] == PARSE_CONTEXT_PARAMETER)
|
||||
{
|
||||
if (context_ptr->data_used + len >= sizeof(context_ptr->data))
|
||||
{
|
||||
lash_dbus_error(context_ptr->call_ptr, LASH_DBUS_ERROR_GENERIC, "xml parse max char data length reached");
|
||||
context_ptr->error = XML_TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(context_ptr->data + context_ptr->data_used, s, len);
|
||||
context_ptr->data_used += len;
|
||||
}
|
||||
}
|
||||
|
||||
static void callback_elstart(void * data, const char * el, const char ** attr)
|
||||
{
|
||||
if (context_ptr->error)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (context_ptr->depth + 1 >= MAX_STACK_DEPTH)
|
||||
{
|
||||
lash_dbus_error(context_ptr->call_ptr, LASH_DBUS_ERROR_GENERIC, "xml parse max stack depth reached");
|
||||
context_ptr->error = XML_TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(el, "studio") == 0)
|
||||
{
|
||||
//lash_info("<studio>");
|
||||
context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_STUDIO;
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(el, "jack") == 0)
|
||||
{
|
||||
//lash_info("<jack>");
|
||||
context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_JACK;
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(el, "conf") == 0)
|
||||
{
|
||||
//lash_info("<conf>");
|
||||
context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_CONF;
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(el, "parameter") == 0)
|
||||
{
|
||||
//lash_info("<parameter>");
|
||||
if ((attr[0] == NULL || attr[2] != NULL) || strcmp(attr[0], "path") != 0)
|
||||
{
|
||||
lash_dbus_error(context_ptr->call_ptr, LASH_DBUS_ERROR_GENERIC, "<parameter> XML element must contain exactly one attribute, named \"path\"");
|
||||
context_ptr->error = XML_TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
context_ptr->path = strdup(attr[1]);
|
||||
if (context_ptr->path == NULL)
|
||||
{
|
||||
lash_dbus_error(context_ptr->call_ptr, LASH_DBUS_ERROR_GENERIC, "strdup() failed");
|
||||
context_ptr->error = XML_TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_PARAMETER;
|
||||
context_ptr->data_used = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
lash_dbus_error(context_ptr->call_ptr, LASH_DBUS_ERROR_GENERIC, "unknown element \"%s\"", el);
|
||||
context_ptr->error = XML_TRUE;
|
||||
}
|
||||
|
||||
static void callback_elend(void * data, const char * el)
|
||||
{
|
||||
char * src;
|
||||
char * dst;
|
||||
char * address;
|
||||
struct jack_parameter_variant parameter;
|
||||
bool is_set;
|
||||
|
||||
if (context_ptr->error)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//lash_info("element end (depth = %d, element = %u)", context_ptr->depth, context_ptr->element[context_ptr->depth]);
|
||||
|
||||
if (context_ptr->element[context_ptr->depth] == PARSE_CONTEXT_PARAMETER &&
|
||||
context_ptr->depth == 3 &&
|
||||
context_ptr->element[0] == PARSE_CONTEXT_STUDIO &&
|
||||
context_ptr->element[1] == PARSE_CONTEXT_JACK &&
|
||||
context_ptr->element[2] == PARSE_CONTEXT_CONF)
|
||||
{
|
||||
context_ptr->data[context_ptr->data_used] = 0;
|
||||
|
||||
//lash_info("'%s' with value '%s'", context_ptr->path, context_ptr->data);
|
||||
|
||||
/* TODO: unescape */
|
||||
dst = address = strdup(context_ptr->path);
|
||||
src = context_ptr->path + 1;
|
||||
while (*src != 0)
|
||||
{
|
||||
if (*src == '/')
|
||||
{
|
||||
*dst = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*dst = *src;
|
||||
}
|
||||
|
||||
src++;
|
||||
dst++;
|
||||
}
|
||||
dst[0] = 0;
|
||||
dst[1] = 0; /* ASCIZZ */
|
||||
|
||||
if (!jack_proxy_get_parameter_value(address, &is_set, ¶meter))
|
||||
{
|
||||
lash_dbus_error(context_ptr->call_ptr, LASH_DBUS_ERROR_GENERIC, "jack_proxy_get_parameter_value() failed");
|
||||
goto fail_free_address;
|
||||
}
|
||||
|
||||
switch (parameter.type)
|
||||
{
|
||||
case jack_boolean:
|
||||
lash_info("%s value is %s (boolean)", context_ptr->path, context_ptr->data);
|
||||
if (strcmp(context_ptr->data, "true") == 0)
|
||||
{
|
||||
parameter.value.boolean = true;
|
||||
}
|
||||
else if (strcmp(context_ptr->data, "false") == 0)
|
||||
{
|
||||
parameter.value.boolean = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
lash_dbus_error(context_ptr->call_ptr, LASH_DBUS_ERROR_GENERIC, "bad value for a bool jack param");
|
||||
goto fail_free_address;
|
||||
}
|
||||
break;
|
||||
case jack_string:
|
||||
lash_info("%s value is %s (string)", context_ptr->path, context_ptr->data);
|
||||
parameter.value.string = context_ptr->data;
|
||||
break;
|
||||
case jack_byte:
|
||||
lash_debug("%s value is %u/%c (byte/char)", context_ptr->path, *context_ptr->data, *context_ptr->data);
|
||||
if (context_ptr->data[0] == 0 ||
|
||||
context_ptr->data[1] != 0)
|
||||
{
|
||||
lash_dbus_error(context_ptr->call_ptr, LASH_DBUS_ERROR_GENERIC, "bad value for a char jack param");
|
||||
goto fail_free_address;
|
||||
}
|
||||
parameter.value.byte = context_ptr->data[0];
|
||||
break;
|
||||
case jack_uint32:
|
||||
lash_info("%s value is %s (uint32)", context_ptr->path, context_ptr->data);
|
||||
if (sscanf(context_ptr->data, "%" PRIu32, ¶meter.value.uint32) != 1)
|
||||
{
|
||||
lash_dbus_error(context_ptr->call_ptr, LASH_DBUS_ERROR_GENERIC, "bad value for an uint32 jack param");
|
||||
goto fail_free_address;
|
||||
}
|
||||
break;
|
||||
case jack_int32:
|
||||
lash_info("%s value is %s (int32)", context_ptr->path, context_ptr->data);
|
||||
if (sscanf(context_ptr->data, "%" PRIi32, ¶meter.value.int32) != 1)
|
||||
{
|
||||
lash_dbus_error(context_ptr->call_ptr, LASH_DBUS_ERROR_GENERIC, "bad value for an int32 jack param");
|
||||
goto fail_free_address;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
lash_dbus_error(context_ptr->call_ptr, LASH_DBUS_ERROR_GENERIC, "unknown jack parameter type %d of %s", (int)parameter.type, context_ptr->path);
|
||||
goto fail_free_address;
|
||||
}
|
||||
|
||||
if (!jack_proxy_set_parameter_value(address, ¶meter))
|
||||
{
|
||||
lash_dbus_error(context_ptr->call_ptr, LASH_DBUS_ERROR_GENERIC, "jack_proxy_set_parameter_value() failed");
|
||||
goto fail_free_address;
|
||||
}
|
||||
|
||||
free(address);
|
||||
}
|
||||
|
||||
context_ptr->depth--;
|
||||
|
||||
if (context_ptr->path != NULL)
|
||||
{
|
||||
free(context_ptr->path);
|
||||
context_ptr->path = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
fail_free_address:
|
||||
free(address);
|
||||
context_ptr->error = XML_TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
#undef context_ptr
|
||||
|
||||
bool studio_load(void * call_ptr, const char * studio_name)
|
||||
{
|
||||
char * path;
|
||||
struct stat st;
|
||||
|
||||
lash_info("Loading studio '%s'", studio_name);
|
||||
XML_Parser parser;
|
||||
int bytes_read;
|
||||
void * buffer;
|
||||
int fd;
|
||||
enum XML_Status xmls;
|
||||
struct parse_context context;
|
||||
|
||||
/* TODO: unescape */
|
||||
path = catdup3(g_studios_dir, studio_name, ".xml");
|
||||
|
@ -1080,14 +1321,14 @@ bool studio_load(void * call_ptr, const char * studio_name)
|
|||
return false;
|
||||
}
|
||||
|
||||
lash_info("'%s'", path);
|
||||
lash_info("Loading studio... ('%s')", path);
|
||||
|
||||
if (stat(path, &st) != 0)
|
||||
{
|
||||
lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "failed to stat '%s': %d (%s)", path, errno, strerror(errno));
|
||||
free(path);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
studio_clear();
|
||||
|
||||
|
@ -1101,12 +1342,82 @@ bool studio_load(void * call_ptr, const char * studio_name)
|
|||
|
||||
g_studio.filename = path;
|
||||
|
||||
/* TODO: load jack params from xml */
|
||||
if (!jack_reset_all_params())
|
||||
{
|
||||
lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "jack_reset_all_params() failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd == -1)
|
||||
{
|
||||
lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "failed to open '%s': %d (%s)", path, errno, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
parser = XML_ParserCreate(NULL);
|
||||
if (parser == NULL)
|
||||
{
|
||||
lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "XML_ParserCreate() failed to create parser object.");
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
//lash_info("conf file size is %llu bytes", (unsigned long long)st.st_size);
|
||||
|
||||
/* we are expecting that conf file has small enough size to fit in memory */
|
||||
|
||||
buffer = XML_GetBuffer(parser, st.st_size);
|
||||
if (buffer == NULL)
|
||||
{
|
||||
lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "XML_GetBuffer() failed.");
|
||||
XML_ParserFree(parser);
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
bytes_read = read(fd, buffer, st.st_size);
|
||||
if (bytes_read != st.st_size)
|
||||
{
|
||||
lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "read() returned unexpected result.");
|
||||
XML_ParserFree(parser);
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
context.error = XML_FALSE;
|
||||
context.depth = -1;
|
||||
context.path = NULL;
|
||||
context.call_ptr = call_ptr;
|
||||
|
||||
XML_SetElementHandler(parser, callback_elstart, callback_elend);
|
||||
XML_SetCharacterDataHandler(parser, callback_chrdata);
|
||||
XML_SetUserData(parser, &context);
|
||||
|
||||
xmls = XML_ParseBuffer(parser, bytes_read, XML_TRUE);
|
||||
if (xmls == XML_STATUS_ERROR)
|
||||
{
|
||||
if (!context.error) /* if we have initiated the fail, dbus error is already set to better message */
|
||||
{
|
||||
lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "XML_ParseBuffer() failed.");
|
||||
}
|
||||
XML_ParserFree(parser);
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
XML_ParserFree(parser);
|
||||
close(fd);
|
||||
|
||||
lash_info("Studio loaded. ('%s')", path);
|
||||
|
||||
studio_activate();
|
||||
|
||||
lash_info("Starting JACK server.");
|
||||
if (!jack_proxy_start_server())
|
||||
{
|
||||
lash_dbus_error(call_ptr, LASH_DBUS_ERROR_GENERIC, "Failed to start JACK server() failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
2
wscript
2
wscript
|
@ -159,7 +159,7 @@ def build(bld):
|
|||
daemon = bld.new_task_gen('cc', 'program')
|
||||
daemon.target = 'ladishd'
|
||||
daemon.includes = "build/default" # XXX config.h version.h and other generated files
|
||||
daemon.uselib = 'DBUS-1 LIBXML-2.0 UUID'
|
||||
daemon.uselib = 'DBUS-1 LIBXML-2.0 UUID EXPAT'
|
||||
daemon.ver_header = 'version.h'
|
||||
daemon.env.append_value("LINKFLAGS", ["-lutil", "-ldl"])
|
||||
|
||||
|
|
Loading…
Reference in New Issue