When JACK server is started, create studio object and store JACK conf as part of it

This commit is contained in:
Nedko Arnaudov 2009-07-26 23:26:29 +03:00
parent 0f9047c699
commit 3f71b1bc2d
8 changed files with 427 additions and 47 deletions

View File

@ -104,12 +104,66 @@ struct studio
struct list_head rooms; /* Rooms connected to the studio */ struct list_head rooms; /* Rooms connected to the studio */
struct list_head clients; /* studio clients (studio guts and room links) */ struct list_head clients; /* studio clients (studio guts and room links) */
struct list_head ports; /* studio ports (studio guts and room links) */ struct list_head ports; /* studio ports (studio guts and room links) */
bool persisted:1; /* Studio has on-disk representation, i.e. can be reloaded from disk */
bool modified:1; /* Studio needs saving */
bool jack_conf_obsolete:1; /* JACK server was stopped during configuration retrieval */
bool jack_conf_stable:1; /* JACK server configuration obtained successfully */
struct list_head jack_conf;
};
struct jack_parameter_variant
{
enum
{
jack_byte,
jack_boolean,
jack_int16,
jack_uint16,
jack_int32,
jack_uint32,
jack_int64,
jack_uint64,
jack_doubl,
jack_string,
} type;
union
{
unsigned char byte;
bool boolean;
int16_t int16;
uint16_t uint16;
int32_t int32;
uint32_t uint32;
int64_t int64;
uint64_t uint64;
double doubl;
char *string;
} value;
};
struct jack_conf_container
{
struct list_head siblings;
char * name;
bool children_leafs; /* if true, children are "jack_conf_parameter"s, if false, children are "jack_conf_container"s */
struct list_head children;
};
struct jack_conf_parameter
{
struct list_head siblings;
char * name;
struct jack_parameter_variant parameter;
}; };
extern service_t * g_dbus_service; extern service_t * g_dbus_service;
#define g_dbus_connection (g_dbus_service->connection) #define g_dbus_connection (g_dbus_service->connection)
extern DBusError g_dbus_error; extern DBusError g_dbus_error;
extern bool g_quit; extern bool g_quit;
extern struct studio * g_studio_ptr;
#define DBUS_CALL_DEFAULT_TIMEOUT 1000 // in milliseconds #define DBUS_CALL_DEFAULT_TIMEOUT 1000 // in milliseconds

View File

@ -8,6 +8,142 @@
#include "jack.h" #include "jack.h"
#include "jack_proxy.h" #include "jack_proxy.h"
#include "studio.h"
bool
jack_conf_container_create(
struct jack_conf_container ** container_ptr_ptr,
const char * name)
{
struct jack_conf_container * container_ptr;
container_ptr = malloc(sizeof(struct jack_conf_container));
if (container_ptr == NULL)
{
lash_error("malloc() failed to allocate struct jack_conf_container");
goto fail;
}
container_ptr->name = strdup(name);
if (container_ptr->name == NULL)
{
lash_error("strdup() failed to duplicate \"%s\"", name);
goto fail_free;
}
INIT_LIST_HEAD(&container_ptr->children);
container_ptr->children_leafs = false;
*container_ptr_ptr = container_ptr;
return true;
fail_free:
free(container_ptr);
fail:
return false;
}
void
jack_conf_container_destroy(
struct jack_conf_container * container_ptr)
{
struct list_head * node_ptr;
//lash_info("\"%s\" jack_conf_parameter destroy", container_ptr->name);
if (!container_ptr->children_leafs)
{
while (!list_empty(&container_ptr->children))
{
node_ptr = container_ptr->children.next;
list_del(node_ptr);
jack_conf_container_destroy(list_entry(node_ptr, struct jack_conf_container, siblings));
}
}
else
{
while (!list_empty(&container_ptr->children))
{
node_ptr = container_ptr->children.next;
list_del(node_ptr);
jack_conf_parameter_destroy(list_entry(node_ptr, struct jack_conf_parameter, siblings));
}
}
free(container_ptr->name);
free(container_ptr);
}
bool
jack_conf_parameter_create(
struct jack_conf_parameter ** parameter_ptr_ptr,
const char * name)
{
struct jack_conf_parameter * parameter_ptr;
parameter_ptr = malloc(sizeof(struct jack_conf_parameter));
if (parameter_ptr == NULL)
{
lash_error("malloc() failed to allocate struct jack_conf_parameter");
goto fail;
}
parameter_ptr->name = strdup(name);
if (parameter_ptr->name == NULL)
{
lash_error("strdup() failed to duplicate \"%s\"", name);
goto fail_free;
}
*parameter_ptr_ptr = parameter_ptr;
return true;
fail_free:
free(parameter_ptr);
fail:
return false;
}
void
jack_conf_parameter_destroy(
struct jack_conf_parameter * parameter_ptr)
{
#if 0
lash_info("jack_conf_parameter destroy");
switch (parameter_ptr->parameter.type)
{
case jack_boolean:
lash_info("%s value is %s (boolean)", parameter_ptr->name, parameter_ptr->parameter.value.boolean ? "true" : "false");
break;
case jack_string:
lash_info("%s value is %s (string)", parameter_ptr->name, parameter_ptr->parameter.value.string);
break;
case jack_byte:
lash_info("%s value is %u/%c (byte/char)", parameter_ptr->name, parameter_ptr->parameter.value.byte, (char)parameter_ptr->parameter.value.byte);
break;
case jack_uint32:
lash_info("%s value is %u (uint32)", parameter_ptr->name, (unsigned int)parameter_ptr->parameter.value.uint32);
break;
case jack_int32:
lash_info("%s value is %u (int32)", parameter_ptr->name, (signed int)parameter_ptr->parameter.value.int32);
break;
default:
lash_error("unknown jack parameter_ptr->parameter type %d (%s)", (int)parameter_ptr->parameter.type, parameter_ptr->name);
break;
}
#endif
if (parameter_ptr->parameter.type == jack_string)
{
free(parameter_ptr->parameter.value.string);
}
free(parameter_ptr->name);
free(parameter_ptr);
}
bool bool
jack_init( jack_init(
@ -81,6 +217,16 @@ on_jack_ports_disconnected(
lash_info("JACK ports disconnected."); lash_info("JACK ports disconnected.");
} }
struct conf_callback_context
{
char address[1024];
struct list_head * container_ptr;
struct studio * studio_ptr;
struct jack_conf_container * parent_ptr;
};
#define context_ptr ((struct conf_callback_context *)context)
bool bool
conf_callback( conf_callback(
void * context, void * context,
@ -92,8 +238,20 @@ conf_callback(
const char * component; const char * component;
char * dst; char * dst;
size_t len; size_t len;
struct jack_parameter_variant parameter;
bool is_set; bool is_set;
struct jack_conf_container * parent_ptr;
struct jack_conf_container * container_ptr;
struct jack_conf_parameter * parameter_ptr;
if (context_ptr->studio_ptr->jack_conf_obsolete)
{
context_ptr->studio_ptr = NULL;
return false;
}
assert(context_ptr->studio_ptr);
parent_ptr = context_ptr->parent_ptr;
dst = path; dst = path;
component = address; component = address;
@ -109,7 +267,7 @@ conf_callback(
strcpy(dst, child); strcpy(dst, child);
/* address always is same buffer as the one supplied through context pointer */ /* address always is same buffer as the one supplied through context pointer */
assert(context == address); assert(context_ptr->address == address);
dst = (char *)component; dst = (char *)component;
len = strlen(child) + 1; len = strlen(child) + 1;
@ -120,7 +278,30 @@ conf_callback(
{ {
lash_debug("%s (leaf)", path); lash_debug("%s (leaf)", path);
if (!jack_proxy_get_parameter_value(context, &is_set, &parameter)) if (parent_ptr == NULL)
{
lash_error("jack conf parameters can't appear in root container");
return false;
}
if (!parent_ptr->children_leafs)
{
if (!list_empty(&parent_ptr->children))
{
lash_error("jack conf parameters cant be mixed with containers at same hierarchy level");
return false;
}
parent_ptr->children_leafs = true;
}
if (!jack_conf_parameter_create(&parameter_ptr, child))
{
lash_error("jack_conf_parameter_create() failed");
return false;
}
if (!jack_proxy_get_parameter_value(context_ptr->address, &is_set, &parameter_ptr->parameter))
{ {
lash_error("cannot get value of %s", path); lash_error("cannot get value of %s", path);
return false; return false;
@ -128,42 +309,70 @@ conf_callback(
if (is_set) if (is_set)
{ {
switch (parameter.type) switch (parameter_ptr->parameter.type)
{ {
case jack_boolean: case jack_boolean:
lash_info("%s value is %s (boolean)", path, parameter.value.boolean ? "true" : "false"); lash_info("%s value is %s (boolean)", path, parameter_ptr->parameter.value.boolean ? "true" : "false");
break; break;
case jack_string: case jack_string:
lash_info("%s value is %s (string)", path, parameter.value.string); lash_info("%s value is %s (string)", path, parameter_ptr->parameter.value.string);
break; break;
case jack_byte: case jack_byte:
lash_info("%s value is %u/%c (byte/char)", path, parameter.value.byte, (char)parameter.value.byte); lash_info("%s value is %u/%c (byte/char)", path, parameter_ptr->parameter.value.byte, (char)parameter_ptr->parameter.value.byte);
break; break;
case jack_uint32: case jack_uint32:
lash_info("%s value is %u (uint32)", path, (unsigned int)parameter.value.uint32); lash_info("%s value is %u (uint32)", path, (unsigned int)parameter_ptr->parameter.value.uint32);
break; break;
case jack_int32: case jack_int32:
lash_info("%s value is %u (int32)", path, (signed int)parameter.value.int32); lash_info("%s value is %u (int32)", path, (signed int)parameter_ptr->parameter.value.int32);
break; break;
default: default:
lash_error("ignoring unknown jack parameter type %d (%s)", (int)parameter.type, path); lash_error("unknown jack parameter_ptr->parameter type %d (%s)", (int)parameter_ptr->parameter.type, path);
jack_conf_parameter_destroy(parameter_ptr);
return false;
} }
}
if (parameter.type == jack_string) list_add_tail(&parameter_ptr->siblings, &parent_ptr->children);
}
else
{ {
free(parameter.value.string); jack_conf_parameter_destroy(parameter_ptr);
} }
} }
else else
{ {
lash_debug("%s (container)", path); lash_debug("%s (container)", path);
if (!jack_proxy_read_conf_container(context, context, conf_callback)) if (parent_ptr != NULL && parent_ptr->children_leafs)
{
lash_error("jack conf containers cant be mixed with parameters at same hierarchy level");
return false;
}
if (!jack_conf_container_create(&container_ptr, child))
{
lash_error("jack_conf_container_create() failed");
return false;
}
if (parent_ptr == NULL)
{
list_add_tail(&container_ptr->siblings, &context_ptr->studio_ptr->jack_conf);
}
else
{
list_add_tail(&container_ptr->siblings, &parent_ptr->children);
}
context_ptr->parent_ptr = container_ptr;
if (!jack_proxy_read_conf_container(context_ptr->address, context, conf_callback))
{ {
lash_error("cannot read container %s", path); lash_error("cannot read container %s", path);
return false; return false;
} }
context_ptr->parent_ptr = parent_ptr;
} }
*dst = 0; *dst = 0;
@ -171,17 +380,47 @@ conf_callback(
return true; return true;
} }
#undef context_ptr
void void
on_jack_server_started( on_jack_server_started(
void) void)
{ {
char buffer[1024] = ""; struct conf_callback_context context;
lash_info("JACK server start detected."); lash_info("JACK server start detected.");
if (!jack_proxy_read_conf_container(buffer, buffer, conf_callback)) if (g_studio_ptr == NULL)
{
if (!studio_create(&g_studio_ptr))
{
lash_error("failed to create studio object");
return;
}
}
context.address[0] = 0;
context.container_ptr = &g_studio_ptr->jack_conf;
context.studio_ptr = g_studio_ptr;
context.parent_ptr = NULL;
if (jack_proxy_read_conf_container(context.address, &context, conf_callback))
{
if (g_studio_ptr == context.studio_ptr &&
!g_studio_ptr->jack_conf_obsolete)
{
g_studio_ptr->jack_conf_stable = true;
lash_info("jack conf successfully retrieved");
return;
}
}
else
{ {
lash_error("jack_proxy_read_conf_container() failed."); lash_error("jack_proxy_read_conf_container() failed.");
g_studio_ptr = NULL;
} }
studio_destroy(context.studio_ptr);
} }
void void
@ -189,6 +428,22 @@ on_jack_server_stopped(
void) void)
{ {
lash_info("JACK server stop detected."); lash_info("JACK server stop detected.");
if (g_studio_ptr == NULL)
{
return;
}
g_studio_ptr->jack_conf_obsolete = true;
if (!g_studio_ptr->persisted)
{
studio_destroy(g_studio_ptr);
g_studio_ptr = NULL;
return;
}
/* TODO: if user wants, restart jack server and reconnect all jack apps to it */
} }
void void

View File

@ -19,4 +19,12 @@ void
jack_uninit( jack_uninit(
void); void);
void
jack_conf_container_destroy(
struct jack_conf_container * container_ptr);
void
jack_conf_parameter_destroy(
struct jack_conf_parameter * parameter_ptr);
#endif /* #ifndef JACK_H__1C44BAEA_280C_4235_94AB_839499BDE47F__INCLUDED */ #endif /* #ifndef JACK_H__1C44BAEA_280C_4235_94AB_839499BDE47F__INCLUDED */

View File

@ -11,37 +11,6 @@
#include "common.h" #include "common.h"
struct jack_parameter_variant
{
enum
{
jack_byte,
jack_boolean,
jack_int16,
jack_uint16,
jack_int32,
jack_uint32,
jack_int64,
jack_uint64,
jack_doubl,
jack_string,
} type;
union
{
unsigned char byte;
bool boolean;
int16_t int16;
uint16_t uint16;
int32_t int32;
uint32_t uint32;
int64_t int64;
uint64_t uint64;
double doubl;
char *string;
} value;
};
bool bool
jack_proxy_init( jack_proxy_init(
void); void);

View File

@ -32,10 +32,12 @@
#include "sigsegv.h" #include "sigsegv.h"
#include "dbus_iface_control.h" #include "dbus_iface_control.h"
#include "jack.h" #include "jack.h"
#include "studio.h"
bool g_quit; bool g_quit;
service_t * g_dbus_service; service_t * g_dbus_service;
DBusError g_dbus_error; DBusError g_dbus_error;
struct studio * g_studio_ptr;
#if 0 #if 0
static DBusHandlerResult lashd_client_disconnect_handler(DBusConnection * connection, DBusMessage * message, void * data) static DBusHandlerResult lashd_client_disconnect_handler(DBusConnection * connection, DBusMessage * message, void * data)
@ -228,6 +230,11 @@ int main(int argc, char ** argv, char ** envp)
loader_run(); loader_run();
} }
if (g_studio_ptr != NULL)
{
studio_destroy(g_studio_ptr);
}
ret = EXIT_SUCCESS; ret = EXIT_SUCCESS;
lash_debug("Finished, cleaning up"); lash_debug("Finished, cleaning up");

64
daemon/studio.c Normal file
View File

@ -0,0 +1,64 @@
/* -*- Mode: C ; c-basic-offset: 2 -*- */
/*****************************************************************************
*
* DESCRIPTION:
* Studio object helpers
*
*****************************************************************************/
#include "common.h"
#include "jack.h"
bool
studio_create(
struct studio ** studio_ptr_ptr)
{
struct studio * studio_ptr;
lash_info("studio object construct");
studio_ptr = malloc(sizeof(struct studio));
if (studio_ptr == NULL)
{
lash_error("malloc() failed to allocate struct studio");
return false;
}
INIT_LIST_HEAD(&studio_ptr->all_connections);
INIT_LIST_HEAD(&studio_ptr->all_ports);
INIT_LIST_HEAD(&studio_ptr->all_clients);
INIT_LIST_HEAD(&studio_ptr->jack_connections);
INIT_LIST_HEAD(&studio_ptr->jack_ports);
INIT_LIST_HEAD(&studio_ptr->jack_clients);
INIT_LIST_HEAD(&studio_ptr->rooms);
INIT_LIST_HEAD(&studio_ptr->clients);
INIT_LIST_HEAD(&studio_ptr->ports);
studio_ptr->modified = false;
studio_ptr->persisted = false;
studio_ptr->jack_conf_obsolete = false;
studio_ptr->jack_conf_stable = false;
INIT_LIST_HEAD(&studio_ptr->jack_conf);
*studio_ptr_ptr = studio_ptr;
return true;
}
void
studio_destroy(
struct studio * studio_ptr)
{
struct list_head * node_ptr;
while (!list_empty(&studio_ptr->jack_conf))
{
node_ptr = studio_ptr->jack_conf.next;
list_del(node_ptr);
jack_conf_container_destroy(list_entry(node_ptr, struct jack_conf_container, siblings));
}
free(studio_ptr);
lash_info("studio object destroy");
}

22
daemon/studio.h Normal file
View File

@ -0,0 +1,22 @@
/* -*- Mode: C ; c-basic-offset: 2 -*- */
/*****************************************************************************
*
* DESCRIPTION:
* Studio object helpers
*
*****************************************************************************/
#ifndef STUDIO_H__0BEDE85E_4FB3_4D74_BC08_C373A22409C0__INCLUDED
#define STUDIO_H__0BEDE85E_4FB3_4D74_BC08_C373A22409C0__INCLUDED
#include "common.h"
bool
studio_create(
struct studio ** studio_ptr_ptr);
void
studio_destroy(
struct studio * studio_ptr);
#endif /* #ifndef STUDIO_H__0BEDE85E_4FB3_4D74_BC08_C373A22409C0__INCLUDED */

View File

@ -173,6 +173,7 @@ def build(bld):
'dbus_iface_control.c', 'dbus_iface_control.c',
'jack_proxy.c', 'jack_proxy.c',
'jack.c', 'jack.c',
'studio.c',
]: ]:
daemon.source.append(os.path.join("daemon", source)) daemon.source.append(os.path.join("daemon", source))