@@ -28,12 +28,12 @@ namespace Jack | |||||
int JackFreewheelDriver::Process() | int JackFreewheelDriver::Process() | ||||
{ | { | ||||
int res = 0; | |||||
int res = 0; | |||||
jack_log("JackFreewheelDriver::Process master %lld", fEngineControl->fTimeOutUsecs); | |||||
JackDriver::CycleTakeBeginTime(); | |||||
jack_log("JackFreewheelDriver::Process master %lld", fEngineControl->fTimeOutUsecs); | |||||
JackDriver::CycleTakeBeginTime(); | |||||
if (fEngine->Process(fBeginDateUst, fEndDateUst)) { | |||||
if (fEngine->Process(fBeginDateUst, fEndDateUst)) { | |||||
if (fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable)) { // Signal all clients | if (fGraphManager->ResumeRefNum(&fClientControl, fSynchroTable)) { // Signal all clients | ||||
jack_error("JackFreewheelDriver::Process: ResumeRefNum error"); | jack_error("JackFreewheelDriver::Process: ResumeRefNum error"); | ||||
@@ -46,10 +46,10 @@ int JackFreewheelDriver::Process() | |||||
return 0; | return 0; | ||||
} | } | ||||
} else { // Graph not finished: do not activate it | |||||
} else { // Graph not finished: do not activate it | |||||
jack_error("JackFreewheelDriver::Process: Process error"); | jack_error("JackFreewheelDriver::Process: Process error"); | ||||
res = -1; | res = -1; | ||||
} | |||||
} | |||||
return res; | return res; | ||||
} | } | ||||
@@ -124,7 +124,8 @@ namespace Jack | |||||
bool JackNetDriver::Initialize() | bool JackNetDriver::Initialize() | ||||
{ | { | ||||
jack_log("JackNetDriver::Initialize() "); | |||||
jack_log("JackNetDriver::Initialize()"); | |||||
FreePorts(); | |||||
//new loading, but existing socket, restart the driver | //new loading, but existing socket, restart the driver | ||||
if (fSocket.IsSocket()) { | if (fSocket.IsSocket()) { | ||||
@@ -373,29 +374,33 @@ namespace Jack | |||||
int JackNetDriver::FreePorts() | int JackNetDriver::FreePorts() | ||||
{ | { | ||||
jack_log ( "JackNetDriver::FreePorts" ); | |||||
jack_log("JackNetDriver::FreePorts"); | |||||
for (int audio_port_index = 0; audio_port_index < fCaptureChannels; audio_port_index++) { | for (int audio_port_index = 0; audio_port_index < fCaptureChannels; audio_port_index++) { | ||||
if (fCapturePortList[audio_port_index] > 0) { | if (fCapturePortList[audio_port_index] > 0) { | ||||
fGraphManager->ReleasePort ( fClientControl.fRefNum, fCapturePortList[audio_port_index]); | |||||
fGraphManager->ReleasePort(fClientControl.fRefNum, fCapturePortList[audio_port_index]); | |||||
fCapturePortList[audio_port_index] = 0; | |||||
} | } | ||||
} | } | ||||
for (int audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++) { | for (int audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++) { | ||||
if (fPlaybackPortList[audio_port_index] > 0) { | if (fPlaybackPortList[audio_port_index] > 0) { | ||||
fGraphManager->ReleasePort ( fClientControl.fRefNum, fPlaybackPortList[audio_port_index]); | |||||
fGraphManager->ReleasePort(fClientControl.fRefNum, fPlaybackPortList[audio_port_index]); | |||||
fPlaybackPortList[audio_port_index] = 0; | |||||
} | } | ||||
} | } | ||||
for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) { | for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) { | ||||
if (fMidiCapturePortList && fMidiCapturePortList[midi_port_index] > 0) { | if (fMidiCapturePortList && fMidiCapturePortList[midi_port_index] > 0) { | ||||
fGraphManager->ReleasePort ( fClientControl.fRefNum, fMidiCapturePortList[midi_port_index]); | |||||
fGraphManager->ReleasePort(fClientControl.fRefNum, fMidiCapturePortList[midi_port_index]); | |||||
fMidiCapturePortList[midi_port_index] = 0; | |||||
} | } | ||||
} | } | ||||
for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) { | for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) { | ||||
if (fMidiPlaybackPortList && fMidiPlaybackPortList[midi_port_index] > 0) { | if (fMidiPlaybackPortList && fMidiPlaybackPortList[midi_port_index] > 0) { | ||||
fGraphManager->ReleasePort ( fClientControl.fRefNum, fMidiPlaybackPortList[midi_port_index]); | |||||
fGraphManager->ReleasePort(fClientControl.fRefNum, fMidiPlaybackPortList[midi_port_index]); | |||||
fMidiPlaybackPortList[midi_port_index] = 0; | |||||
} | } | ||||
} | } | ||||
// Clear MIDI channels | // Clear MIDI channels | ||||
@@ -64,7 +64,7 @@ class SERVER_EXPORT JackWaitThreadedDriver : public JackThreadedDriver | |||||
// JackRunnableInterface interface | // JackRunnableInterface interface | ||||
bool Execute() | bool Execute() | ||||
{ | { | ||||
// Blocks until decorated driver is started (that is when it's Init method returns). | |||||
// Blocks until decorated driver is started (that is when it's Initialize method returns). | |||||
if (fDriver->Initialize()) { | if (fDriver->Initialize()) { | ||||
fRunning = true; | fRunning = true; | ||||
} else { | } else { | ||||
@@ -57,7 +57,11 @@ static void __attribute__((constructor)) tryload_libjack() | |||||
#ifdef __APPLE__ | #ifdef __APPLE__ | ||||
libjack_handle = dlopen("libjack.0.dylib", RTLD_LAZY); | libjack_handle = dlopen("libjack.0.dylib", RTLD_LAZY); | ||||
#elif defined(WIN32) | #elif defined(WIN32) | ||||
libjack_handle = LoadLibrary("libjack.dll"); | |||||
#ifdef _WIN64 | |||||
libjack_handle = LoadLibrary("libjack64.dll"); | |||||
#else | |||||
libjack_handle = LoadLibrary("libjack.dll"); | |||||
#endif | |||||
#else | #else | ||||
libjack_handle = dlopen("libjack.so.0", RTLD_LAZY); | libjack_handle = dlopen("libjack.so.0", RTLD_LAZY); | ||||
#endif | #endif | ||||
@@ -540,12 +540,15 @@ int main(int argc, char* argv[]) | |||||
// Slave drivers | // Slave drivers | ||||
for (it = slaves_list.begin(); it != slaves_list.end(); it++) { | for (it = slaves_list.begin(); it != slaves_list.end(); it++) { | ||||
jackctl_driver_t * slave_driver_ctl = jackctl_server_get_driver(server_ctl, *it); | jackctl_driver_t * slave_driver_ctl = jackctl_server_get_driver(server_ctl, *it); | ||||
jackctl_server_remove_slave(server_ctl, slave_driver_ctl); | |||||
if (slave_driver_ctl) | |||||
jackctl_server_remove_slave(server_ctl, slave_driver_ctl); | |||||
} | } | ||||
// Internal clients | // Internal clients | ||||
for (it = internals_list.begin(); it != internals_list.end(); it++) { | for (it = internals_list.begin(); it != internals_list.end(); it++) { | ||||
jackctl_internal_t * internal_driver_ctl = jackctl_server_get_internal(server_ctl, *it); | jackctl_internal_t * internal_driver_ctl = jackctl_server_get_internal(server_ctl, *it); | ||||
jackctl_server_unload_internal(server_ctl, internal_driver_ctl); | |||||
if (internal_driver_ctl) | |||||
jackctl_server_unload_internal(server_ctl, internal_driver_ctl); | |||||
} | } | ||||
jackctl_server_close(server_ctl); | jackctl_server_close(server_ctl); | ||||
destroy_server: | destroy_server: | ||||
@@ -1,6 +1,6 @@ | |||||
/* -*- Mode: C ; c-basic-offset: 4 -*- */ | /* -*- 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 | Copyright (C) 2007-2008 Juuso Alasuutari | ||||
This program is free software; you can redistribute it and/or modify | This program is free software; you can redistribute it and/or modify | ||||
@@ -42,6 +42,7 @@ struct jack_dbus_interface_descriptor * g_jackcontroller_interfaces[] = | |||||
NULL | NULL | ||||
}; | }; | ||||
static | |||||
jackctl_driver_t * | jackctl_driver_t * | ||||
jack_controller_find_driver( | jack_controller_find_driver( | ||||
jackctl_server_t *server, | jackctl_server_t *server, | ||||
@@ -114,6 +115,7 @@ jack_controller_remove_slave_drivers( | |||||
} | } | ||||
} | } | ||||
static | |||||
jackctl_internal_t * | jackctl_internal_t * | ||||
jack_controller_find_internal( | jack_controller_find_internal( | ||||
jackctl_server_t *server, | jackctl_server_t *server, | ||||
@@ -136,42 +138,18 @@ jack_controller_find_internal( | |||||
return NULL; | return NULL; | ||||
} | } | ||||
jackctl_parameter_t * | |||||
jack_controller_find_parameter( | |||||
const JSList * parameters_list, | |||||
const char * parameter_name) | |||||
{ | |||||
while (parameters_list) | |||||
{ | |||||
if (strcmp(jackctl_parameter_get_name((jackctl_parameter_t *)parameters_list->data), parameter_name) == 0) | |||||
{ | |||||
return parameters_list->data; | |||||
} | |||||
parameters_list = jack_slist_next(parameters_list); | |||||
} | |||||
return NULL; | |||||
} | |||||
bool | bool | ||||
jack_controller_select_driver( | jack_controller_select_driver( | ||||
struct jack_controller * controller_ptr, | struct jack_controller * controller_ptr, | ||||
const char * driver_name) | 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; | return false; | ||||
} | } | ||||
jack_info("driver \"%s\" selected", driver_name); | jack_info("driver \"%s\" selected", driver_name); | ||||
controller_ptr->driver = driver; | |||||
controller_ptr->driver_set = true; | |||||
return true; | return true; | ||||
} | } | ||||
@@ -195,17 +173,11 @@ jack_controller_start_server( | |||||
assert(!controller_ptr->started); /* should be ensured by caller */ | 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; | controller_ptr->xruns = 0; | ||||
if (!jackctl_server_open( | if (!jackctl_server_open( | ||||
controller_ptr->server, | 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"); | jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to open server"); | ||||
goto fail; | goto fail; | ||||
@@ -337,12 +309,13 @@ jack_controller_switch_master( | |||||
{ | { | ||||
if (!jackctl_server_switch_master( | if (!jackctl_server_switch_master( | ||||
controller_ptr->server, | 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"); | jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Failed to switch master"); | ||||
return FALSE; | return FALSE; | ||||
} | } | ||||
return TRUE; | return TRUE; | ||||
} | } | ||||
@@ -413,11 +386,6 @@ jack_controller_create( | |||||
DBusConnection *connection) | DBusConnection *connection) | ||||
{ | { | ||||
struct jack_controller *controller_ptr; | 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 = | DBusObjectPathVTable vtable = | ||||
{ | { | ||||
jack_dbus_message_handler_unregister, | jack_dbus_message_handler_unregister, | ||||
@@ -439,54 +407,16 @@ jack_controller_create( | |||||
goto fail_free; | 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; | 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.context = controller_ptr; | ||||
controller_ptr->dbus_descriptor.interfaces = g_jackcontroller_interfaces; | controller_ptr->dbus_descriptor.interfaces = g_jackcontroller_interfaces; | ||||
@@ -498,18 +428,15 @@ jack_controller_create( | |||||
&controller_ptr->dbus_descriptor)) | &controller_ptr->dbus_descriptor)) | ||||
{ | { | ||||
jack_error("Ran out of memory trying to register D-Bus object path"); | 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); | jack_controller_settings_load(controller_ptr); | ||||
return 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: | fail_destroy_server: | ||||
jackctl_server_destroy(controller_ptr->server); | jackctl_server_destroy(controller_ptr->server); | ||||
@@ -623,9 +550,7 @@ jack_controller_destroy( | |||||
jack_controller_stop_server(controller_ptr, NULL); | 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); | jackctl_server_destroy(controller_ptr->server); | ||||
free(controller_ptr); | free(controller_ptr); | ||||
@@ -127,8 +127,6 @@ jack_control_run_method( | |||||
assert(call->reply != NULL); | assert(call->reply != NULL); | ||||
return true; | return true; | ||||
} | } | ||||
jack_controller_control_send_signal_server_stopped(); | |||||
} | } | ||||
else if (strcmp (call->method_name, "GetLoad") == 0) | else if (strcmp (call->method_name, "GetLoad") == 0) | ||||
{ | { | ||||
@@ -1,6 +1,6 @@ | |||||
/* -*- Mode: C ; c-basic-offset: 4 -*- */ | /* -*- 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 | Copyright (C) 2007-2008 Juuso Alasuutari | ||||
This program is free software; you can redistribute it and/or modify | This program is free software; you can redistribute it and/or modify | ||||
@@ -27,6 +27,7 @@ | |||||
#include "jack/jack.h" | #include "jack/jack.h" | ||||
#include "jackdbus.h" | #include "jackdbus.h" | ||||
#include "list.h" | #include "list.h" | ||||
#include "params.h" | |||||
struct jack_controller_slave_driver | struct jack_controller_slave_driver | ||||
{ | { | ||||
@@ -38,6 +39,7 @@ struct jack_controller_slave_driver | |||||
struct jack_controller | struct jack_controller | ||||
{ | { | ||||
jackctl_server_t *server; | jackctl_server_t *server; | ||||
jack_params_handle params; | |||||
void *patchbay_context; | void *patchbay_context; | ||||
@@ -45,14 +47,6 @@ struct jack_controller | |||||
jack_client_t *client; | jack_client_t *client; | ||||
unsigned int xruns; | 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 list_head slave_drivers; | ||||
struct jack_dbus_object_descriptor dbus_descriptor; | struct jack_dbus_object_descriptor dbus_descriptor; | ||||
@@ -65,21 +59,6 @@ struct jack_controller | |||||
"You probably don't want to edit this because\n" \ | "You probably don't want to edit this because\n" \ | ||||
"it will be overwritten next time jackdbus saves.\n" | "it will be overwritten next time jackdbus saves.\n" | ||||
jackctl_driver_t * | |||||
jack_controller_find_driver( | |||||
jackctl_server_t *server, | |||||
const char *driver_name); | |||||
jackctl_internal_t * | |||||
jack_controller_find_internal( | |||||
jackctl_server_t *server, | |||||
const char *internal_name); | |||||
jackctl_parameter_t * | |||||
jack_controller_find_parameter( | |||||
const JSList *parameters_list, | |||||
const char *parameter_name); | |||||
bool | bool | ||||
jack_controller_start_server( | jack_controller_start_server( | ||||
struct jack_controller *controller_ptr, | struct jack_controller *controller_ptr, | ||||
@@ -121,47 +100,15 @@ jack_controller_unload_internal( | |||||
const char * internal_name); | const char * internal_name); | ||||
void | 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( | |||||
struct jack_controller *controller_ptr, | |||||
const char *option_name, | |||||
const char *option_value); | |||||
bool | |||||
jack_controller_settings_save_engine_options( | |||||
void *context, | |||||
jack_controller_deserialize_parameter_value( | |||||
struct jack_controller *controller_ptr, | struct jack_controller *controller_ptr, | ||||
void *dbus_call_context_ptr); | |||||
bool | |||||
jack_controller_settings_write_option( | |||||
void *context, | |||||
const char *name, | |||||
const char *content, | |||||
void *dbus_call_context_ptr); | |||||
const char * const * address, | |||||
const char * value); | |||||
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 | bool | ||||
jack_controller_patchbay_init( | jack_controller_patchbay_init( | ||||
@@ -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, ¶m_ptr->constraint.range.min, ¶m_ptr->constraint.range.max); | |||||
} | |||||
else if (jackctl_parameter_has_enum_constraint(param)) | |||||
{ | |||||
param_ptr->constraint_flags = JACK_CONSTRAINT_FLAG_VALID; | |||||
param_ptr->constraint_range = false; | |||||
param_ptr->constraint.enumeration.count = jackctl_parameter_get_enum_constraints_count(param); | |||||
param_ptr->constraint.enumeration.possible_values_array = malloc(sizeof(struct jack_parameter_enum) * param_ptr->constraint.enumeration.count); | |||||
if (param_ptr->constraint.enumeration.possible_values_array == NULL) | |||||
{ | |||||
goto free; | |||||
} | |||||
for (i = 0; i < param_ptr->constraint.enumeration.count; i++) | |||||
{ | |||||
param_ptr->constraint.enumeration.possible_values_array[i].value = jackctl_parameter_get_enum_constraint_value(param, i); | |||||
param_ptr->constraint.enumeration.possible_values_array[i].short_desc = jackctl_parameter_get_enum_constraint_description(param, i); | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
param_ptr->constraint_flags = 0; | |||||
goto add; | |||||
} | |||||
if (jackctl_parameter_constraint_is_strict(param)) | |||||
{ | |||||
param_ptr->constraint_flags |= JACK_CONSTRAINT_FLAG_STRICT; | |||||
} | |||||
if (jackctl_parameter_constraint_is_fake_value(param)) | |||||
{ | |||||
param_ptr->constraint_flags |= JACK_CONSTRAINT_FLAG_FAKE_VALUE; | |||||
} | |||||
add: | |||||
list_add_tail(¶m_ptr->siblings, parent_list_ptr); | |||||
return true; | |||||
free: | |||||
free(param_ptr); | |||||
fail: | |||||
return false; | |||||
} | |||||
static void free_params(struct list_head * parent_list_ptr) | |||||
{ | |||||
struct jack_parameter * param_ptr; | |||||
while (!list_empty(parent_list_ptr)) | |||||
{ | |||||
param_ptr = list_entry(parent_list_ptr->next, struct jack_parameter, siblings); | |||||
list_del(¶m_ptr->siblings); | |||||
if ((param_ptr->constraint_flags & JACK_CONSTRAINT_FLAG_VALID) != 0 && | |||||
!param_ptr->constraint_range && | |||||
param_ptr->constraint.enumeration.possible_values_array != NULL) | |||||
{ | |||||
free(param_ptr->constraint.enumeration.possible_values_array); | |||||
} | |||||
free(param_ptr); | |||||
} | |||||
} | |||||
static void free_containers(struct list_head * parent_list_ptr) | |||||
{ | |||||
struct jack_parameter_container * container_ptr; | |||||
while (!list_empty(parent_list_ptr)) | |||||
{ | |||||
container_ptr = list_entry(parent_list_ptr->next, struct jack_parameter_container, siblings); | |||||
list_del(&container_ptr->siblings); | |||||
if (container_ptr->leaf) | |||||
{ | |||||
free_params(&container_ptr->children); | |||||
} | |||||
else | |||||
{ | |||||
free_containers(&container_ptr->children); | |||||
} | |||||
free(container_ptr->name); | |||||
free(container_ptr); | |||||
} | |||||
} | |||||
static struct jack_parameter_container * find_container(struct jack_parameter_container * parent_ptr, const char * const * address, int max_depth) | |||||
{ | |||||
struct list_head * node_ptr; | |||||
struct jack_parameter_container * container_ptr; | |||||
if (max_depth == 0 || *address == NULL) | |||||
{ | |||||
return parent_ptr; | |||||
} | |||||
if (parent_ptr->leaf) | |||||
{ | |||||
return NULL; | |||||
} | |||||
if (max_depth > 0) | |||||
{ | |||||
max_depth--; | |||||
} | |||||
list_for_each(node_ptr, &parent_ptr->children) | |||||
{ | |||||
container_ptr = list_entry(node_ptr, struct jack_parameter_container, siblings); | |||||
if (strcmp(container_ptr->name, *address) == 0) | |||||
{ | |||||
if (container_ptr->symlink != NULL) | |||||
{ | |||||
container_ptr = container_ptr->symlink; | |||||
} | |||||
return find_container(container_ptr, address + 1, max_depth); | |||||
} | |||||
} | |||||
return NULL; | |||||
} | |||||
static bool init_leaf(struct list_head * parent_list_ptr, const char * name, const JSList * params_list, void * obj) | |||||
{ | |||||
struct jack_parameter_container * container_ptr; | |||||
container_ptr = create_container(parent_list_ptr, name); | |||||
if (container_ptr == NULL) | |||||
{ | |||||
return false; | |||||
} | |||||
container_ptr->leaf = true; | |||||
container_ptr->obj = obj; | |||||
while (params_list) | |||||
{ | |||||
if (!add_controlapi_param(&container_ptr->children, params_list->data)) | |||||
{ | |||||
return false; | |||||
} | |||||
params_list = jack_slist_next(params_list); | |||||
} | |||||
return true; | |||||
} | |||||
static bool init_engine(struct jack_params * params_ptr) | |||||
{ | |||||
return init_leaf(¶ms_ptr->root.children, PTNODE_ENGINE, jackctl_server_get_parameters(params_ptr->server), NULL); | |||||
} | |||||
static bool init_drivers(struct jack_params * params_ptr) | |||||
{ | |||||
const JSList * list; | |||||
struct jack_parameter_container * container_ptr; | |||||
container_ptr = create_container(¶ms_ptr->root.children, PTNODE_DRIVERS); | |||||
if (container_ptr == NULL) | |||||
{ | |||||
return false; | |||||
} | |||||
params_ptr->drivers_ptr = &container_ptr->children; | |||||
params_ptr->drivers_count = 0; | |||||
list = jackctl_server_get_drivers_list(params_ptr->server); | |||||
while (list) | |||||
{ | |||||
if (!init_leaf(&container_ptr->children, jackctl_driver_get_name(list->data), jackctl_driver_get_parameters(list->data), list->data)) | |||||
{ | |||||
return false; | |||||
} | |||||
params_ptr->drivers_count++; | |||||
list = jack_slist_next(list); | |||||
} | |||||
return true; | |||||
} | |||||
static bool init_internals(struct jack_params * params_ptr) | |||||
{ | |||||
const JSList * list; | |||||
struct jack_parameter_container * container_ptr; | |||||
container_ptr = create_container(¶ms_ptr->root.children, PTNODE_INTERNALS); | |||||
if (container_ptr == NULL) | |||||
{ | |||||
return false; | |||||
} | |||||
list = jackctl_server_get_internals_list(params_ptr->server); | |||||
while (list) | |||||
{ | |||||
if (!init_leaf(&container_ptr->children, jackctl_internal_get_name(list->data), jackctl_internal_get_parameters(list->data), NULL)) | |||||
{ | |||||
return false; | |||||
} | |||||
list = jack_slist_next(list); | |||||
} | |||||
return true; | |||||
} | |||||
static bool init_driver(struct jack_params * params_ptr) | |||||
{ | |||||
struct jack_parameter_container * container_ptr; | |||||
container_ptr = create_container(¶ms_ptr->root.children, PTNODE_DRIVER); | |||||
if (container_ptr == NULL) | |||||
{ | |||||
return false; | |||||
} | |||||
params_ptr->driver_ptr = container_ptr; | |||||
return true; | |||||
} | |||||
#define params_ptr ((struct jack_params *)obj) | |||||
static bool engine_driver_parameter_is_set(void * obj) | |||||
{ | |||||
return params_ptr->driver_set; | |||||
} | |||||
static bool engine_driver_parameter_reset(void * obj) | |||||
{ | |||||
if (!jack_params_set_driver(obj, DEFAULT_DRIVER)) | |||||
{ | |||||
return false; | |||||
} | |||||
params_ptr->driver_set = false; | |||||
return true; | |||||
} | |||||
union jackctl_parameter_value engine_driver_parameter_get_value(void * obj) | |||||
{ | |||||
union jackctl_parameter_value value; | |||||
strcpy(value.str, params_ptr->driver_ptr->symlink->name); | |||||
return value; | |||||
} | |||||
bool engine_driver_parameter_set_value(void * obj, const union jackctl_parameter_value * value_ptr) | |||||
{ | |||||
return jack_params_set_driver(obj, value_ptr->str); | |||||
} | |||||
union jackctl_parameter_value engine_driver_parameter_get_default_value(void * obj) | |||||
{ | |||||
union jackctl_parameter_value value; | |||||
strcpy(value.str, DEFAULT_DRIVER); | |||||
return value; | |||||
} | |||||
#undef params_ptr | |||||
static bool add_engine_driver_enum_constraint(void * context, const char * name) | |||||
{ | |||||
strcpy((*((struct jack_parameter_enum **)context))->value.str, name); | |||||
(*((struct jack_parameter_enum **)context))->short_desc = name; | |||||
(*((struct jack_parameter_enum **)context))++; | |||||
return true; | |||||
} | |||||
static bool init_engine_driver_parameter(struct jack_params * params_ptr) | |||||
{ | |||||
struct jack_parameter * param_ptr; | |||||
const char * address[PARAM_ADDRESS_SIZE] = {PTNODE_ENGINE, NULL}; | |||||
struct jack_parameter_container * engine_ptr; | |||||
struct jack_parameter_enum * possible_value; | |||||
engine_ptr = find_container(¶ms_ptr->root, address, PARAM_ADDRESS_SIZE); | |||||
if (engine_ptr == NULL) | |||||
{ | |||||
return false; | |||||
} | |||||
param_ptr = malloc(sizeof(struct jack_parameter)); | |||||
if (param_ptr == NULL) | |||||
{ | |||||
jack_error("Ran out of memory trying to allocate struct jack_parameter"); | |||||
goto fail; | |||||
} | |||||
param_ptr->obj = params_ptr; | |||||
param_ptr->vtable.is_set = engine_driver_parameter_is_set; | |||||
param_ptr->vtable.reset = engine_driver_parameter_reset; | |||||
param_ptr->vtable.get_value = engine_driver_parameter_get_value; | |||||
param_ptr->vtable.set_value = engine_driver_parameter_set_value; | |||||
param_ptr->vtable.get_default_value = engine_driver_parameter_get_default_value; | |||||
param_ptr->type = JackParamString; | |||||
param_ptr->name = "driver"; | |||||
param_ptr->short_decr = "Driver to use"; | |||||
param_ptr->long_descr = ""; | |||||
param_ptr->constraint_flags = JACK_CONSTRAINT_FLAG_VALID | JACK_CONSTRAINT_FLAG_STRICT | JACK_CONSTRAINT_FLAG_FAKE_VALUE; | |||||
param_ptr->constraint_range = false; | |||||
param_ptr->constraint.enumeration.count = params_ptr->drivers_count; | |||||
param_ptr->constraint.enumeration.possible_values_array = malloc(sizeof(struct jack_parameter_enum) * params_ptr->drivers_count); | |||||
if (param_ptr->constraint.enumeration.possible_values_array == NULL) | |||||
{ | |||||
goto free; | |||||
} | |||||
address[0] = PTNODE_DRIVERS; | |||||
possible_value = param_ptr->constraint.enumeration.possible_values_array; | |||||
jack_params_iterate_container((jack_params_handle)params_ptr, address, add_engine_driver_enum_constraint, &possible_value); | |||||
list_add(¶m_ptr->siblings, &engine_ptr->children); | |||||
return true; | |||||
free: | |||||
free(param_ptr); | |||||
fail: | |||||
return false; | |||||
} | |||||
jack_params_handle jack_params_create(jackctl_server_t * server) | |||||
{ | |||||
struct jack_params * params_ptr; | |||||
params_ptr = malloc(sizeof(struct jack_params)); | |||||
if (params_ptr == NULL) | |||||
{ | |||||
jack_error("Ran out of memory trying to allocate struct jack_params"); | |||||
return NULL; | |||||
} | |||||
params_ptr->server = server; | |||||
INIT_LIST_HEAD(¶ms_ptr->root.children); | |||||
params_ptr->root.leaf = false; | |||||
params_ptr->root.name = NULL; | |||||
if (!init_engine(params_ptr) || | |||||
!init_drivers(params_ptr) || | |||||
!init_driver(params_ptr) || | |||||
!init_engine_driver_parameter(params_ptr) || | |||||
!jack_params_set_driver((jack_params_handle)params_ptr, DEFAULT_DRIVER) || | |||||
!init_internals(params_ptr)) | |||||
{ | |||||
jack_params_destroy((jack_params_handle)params_ptr); | |||||
return NULL; | |||||
} | |||||
params_ptr->driver_set = false; | |||||
assert(strcmp(params_ptr->driver_ptr->symlink->name, DEFAULT_DRIVER) == 0); | |||||
return (jack_params_handle)params_ptr; | |||||
} | |||||
#define params_ptr ((struct jack_params *)params) | |||||
void jack_params_destroy(jack_params_handle params) | |||||
{ | |||||
free_containers(¶ms_ptr->root.children); | |||||
free(params); | |||||
} | |||||
bool jack_params_set_driver(jack_params_handle params, const char * name) | |||||
{ | |||||
struct list_head * node_ptr; | |||||
struct jack_parameter_container * container_ptr; | |||||
list_for_each(node_ptr, params_ptr->drivers_ptr) | |||||
{ | |||||
container_ptr = list_entry(node_ptr, struct jack_parameter_container, siblings); | |||||
if (strcmp(container_ptr->name, name) == 0) | |||||
{ | |||||
params_ptr->driver_ptr->symlink = container_ptr; | |||||
params_ptr->driver_set = true; | |||||
return true; | |||||
} | |||||
} | |||||
return false; | |||||
} | |||||
jackctl_driver_t * jack_params_get_driver(jack_params_handle params) | |||||
{ | |||||
return params_ptr->driver_ptr->symlink->obj; | |||||
} | |||||
bool jack_params_check_address(jack_params_handle params, const char * const * address, bool want_leaf) | |||||
{ | |||||
struct jack_parameter_container * container_ptr; | |||||
container_ptr = find_container(¶ms_ptr->root, address, PARAM_ADDRESS_SIZE); | |||||
if (container_ptr == NULL) | |||||
{ | |||||
return false; | |||||
} | |||||
if (want_leaf && !container_ptr->leaf) | |||||
{ | |||||
return false; | |||||
} | |||||
return true; | |||||
} | |||||
bool jack_params_is_leaf_container(jack_params_handle params, const char * const * address) | |||||
{ | |||||
struct jack_parameter_container * container_ptr; | |||||
container_ptr = find_container(¶ms_ptr->root, address, PARAM_ADDRESS_SIZE); | |||||
if (container_ptr == NULL) | |||||
{ | |||||
assert(false); | |||||
return false; | |||||
} | |||||
return container_ptr->leaf; | |||||
} | |||||
bool | |||||
jack_params_iterate_container( | |||||
jack_params_handle params, | |||||
const char * const * address, | |||||
bool (* callback)(void * context, const char * name), | |||||
void * context) | |||||
{ | |||||
struct jack_parameter_container * container_ptr; | |||||
struct list_head * node_ptr; | |||||
const char * name; | |||||
container_ptr = find_container(¶ms_ptr->root, address, PARAM_ADDRESS_SIZE); | |||||
if (container_ptr == NULL) | |||||
{ | |||||
assert(false); | |||||
return true; | |||||
} | |||||
list_for_each(node_ptr, &container_ptr->children) | |||||
{ | |||||
if (container_ptr->leaf) | |||||
{ | |||||
name = list_entry(node_ptr, struct jack_parameter, siblings)->name; | |||||
} | |||||
else | |||||
{ | |||||
name = list_entry(node_ptr, struct jack_parameter_container, siblings)->name; | |||||
} | |||||
if (!callback(context, name)) | |||||
{ | |||||
return false; | |||||
} | |||||
} | |||||
return true; | |||||
} | |||||
bool | |||||
jack_params_iterate_params( | |||||
jack_params_handle params, | |||||
const char * const * address, | |||||
bool (* callback)(void * context, const struct jack_parameter * param_ptr), | |||||
void * context) | |||||
{ | |||||
struct jack_parameter_container * container_ptr; | |||||
struct list_head * node_ptr; | |||||
struct jack_parameter * param_ptr; | |||||
container_ptr = find_container(¶ms_ptr->root, address, PARAM_ADDRESS_SIZE); | |||||
if (container_ptr == NULL || !container_ptr->leaf) | |||||
{ | |||||
assert(false); | |||||
return true; | |||||
} | |||||
list_for_each(node_ptr, &container_ptr->children) | |||||
{ | |||||
param_ptr = list_entry(node_ptr, struct jack_parameter, siblings); | |||||
if (!callback(context, param_ptr)) | |||||
{ | |||||
return false; | |||||
} | |||||
} | |||||
return true; | |||||
} | |||||
const struct jack_parameter * jack_params_get_parameter(jack_params_handle params, const char * const * address) | |||||
{ | |||||
int depth; | |||||
struct jack_parameter_container * container_ptr; | |||||
struct list_head * node_ptr; | |||||
struct jack_parameter * param_ptr; | |||||
for (depth = 0; depth < PARAM_ADDRESS_SIZE; depth++) | |||||
{ | |||||
if (address[depth] == NULL) | |||||
{ | |||||
break; | |||||
} | |||||
} | |||||
depth--; | |||||
container_ptr = find_container(¶ms_ptr->root, address, depth); | |||||
if (container_ptr == NULL || !container_ptr->leaf) | |||||
{ | |||||
return NULL; | |||||
} | |||||
list_for_each(node_ptr, &container_ptr->children) | |||||
{ | |||||
param_ptr = list_entry(node_ptr, struct jack_parameter, siblings); | |||||
if (strcmp(param_ptr->name, address[depth]) == 0) | |||||
{ | |||||
return param_ptr; | |||||
} | |||||
} | |||||
return NULL; | |||||
} | |||||
bool jack_params_add_parameter(jack_params_handle params, const char * const * address, bool end, struct jack_parameter * param_ptr) | |||||
{ | |||||
struct jack_parameter_container * container_ptr; | |||||
container_ptr = find_container(¶ms_ptr->root, address, PARAM_ADDRESS_SIZE); | |||||
if (container_ptr == NULL || !container_ptr->leaf) | |||||
{ | |||||
assert(false); | |||||
return false; | |||||
} | |||||
if (end) | |||||
{ | |||||
list_add_tail(¶m_ptr->siblings, &container_ptr->children); | |||||
} | |||||
else | |||||
{ | |||||
list_add(¶m_ptr->siblings, &container_ptr->children); | |||||
} | |||||
return true; | |||||
} | |||||
#undef params_ptr |
@@ -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 */ |
@@ -52,6 +52,7 @@ def build(bld): | |||||
obj.source = [ | obj.source = [ | ||||
'jackdbus.c', | 'jackdbus.c', | ||||
'controller.c', | 'controller.c', | ||||
'params.c', | |||||
'controller_iface_configure.c', | 'controller_iface_configure.c', | ||||
'controller_iface_control.c', | 'controller_iface_control.c', | ||||
'controller_iface_introspectable.c', | 'controller_iface_introspectable.c', | ||||
@@ -59,7 +60,6 @@ def build(bld): | |||||
'controller_iface_transport.c', | 'controller_iface_transport.c', | ||||
'xml.c', | 'xml.c', | ||||
'xml_expat.c', | 'xml_expat.c', | ||||
#'xml_libxml.c', | |||||
#'xml_nop.c', | #'xml_nop.c', | ||||
'xml_write_raw.c', | 'xml_write_raw.c', | ||||
'sigsegv.c', | 'sigsegv.c', | ||||
@@ -1,6 +1,6 @@ | |||||
/* -*- Mode: C ; c-basic-offset: 4 -*- */ | /* -*- 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 | 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 | it under the terms of the GNU General Public License as published by | ||||
@@ -25,358 +25,116 @@ | |||||
#include <stdint.h> | #include <stdint.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <assert.h> | |||||
#include <dbus/dbus.h> | #include <dbus/dbus.h> | ||||
#include "controller_internal.h" | #include "controller_internal.h" | ||||
void | 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; | 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: | case JackParamInt: | ||||
jack_controller_settings_set_sint_option(option_value, &value_int); | |||||
value.i = value_int; | |||||
value.i = atoi(option_value); | |||||
break; | break; | ||||
case JackParamUInt: | case JackParamUInt: | ||||
jack_controller_settings_set_uint_option(option_value, &value_uint); | |||||
value.ui = value_uint; | |||||
value.ui = strtoul(option_value, NULL, 10); | |||||
break; | break; | ||||
case JackParamChar: | 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; | break; | ||||
case JackParamString: | 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; | break; | ||||
case JackParamBool: | 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; | break; | ||||
default: | 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; | 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 | 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; | 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: | 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: | 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: | case JackParamChar: | ||||
jack_controller_settings_set_char_option(option_value, &value.c); | |||||
break; | |||||
sprintf(value_buffer, "%c", (char)value.c); | |||||
return; | |||||
case JackParamString: | case JackParamString: | ||||
jack_controller_settings_set_string_option(option_value, value.str, sizeof(value.str)); | |||||
break; | |||||
strcpy(value_buffer, value.str); | |||||
return; | |||||
case JackParamBool: | 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; | |||||
} | } |
@@ -1,6 +1,6 @@ | |||||
/* -*- Mode: C ; c-basic-offset: 4 -*- */ | /* -*- 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 | 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 | it under the terms of the GNU General Public License as published by | ||||
@@ -29,6 +29,7 @@ | |||||
#include <fcntl.h> | #include <fcntl.h> | ||||
#include <errno.h> | #include <errno.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <assert.h> | |||||
#include <expat.h> | #include <expat.h> | ||||
#include <dbus/dbus.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 parse_context | ||||
{ | { | ||||
struct jack_controller *controller_ptr; | struct jack_controller *controller_ptr; | ||||
XML_Bool error; | 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]; | char option[JACK_PARAM_STRING_MAX+1]; | ||||
int option_used; | int option_used; | ||||
const char * address[PARAM_ADDRESS_SIZE]; | |||||
int address_index; | |||||
char * container; | |||||
char *name; | char *name; | ||||
}; | }; | ||||
@@ -80,7 +70,7 @@ jack_controller_settings_callback_chrdata(void *data, const XML_Char *s, int len | |||||
return; | 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) | 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 | void | ||||
jack_controller_settings_callback_elstart(void *data, const char *el, const char **attr) | 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) | if (context_ptr->error) | ||||
{ | { | ||||
return; | 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; | context_ptr->error = XML_TRUE; | ||||
return; | return; | ||||
} | } | ||||
//jack_info("<%s>", el); | |||||
if (strcmp(el, "jack") == 0) | if (strcmp(el, "jack") == 0) | ||||
{ | { | ||||
//jack_info("<jack>"); | |||||
context_ptr->element[++context_ptr->depth] = PARSE_CONTEXT_JACK; | |||||
return; | 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; | 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; | 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; | 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) | 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; | context_ptr->error = XML_TRUE; | ||||
return; | 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; | context_ptr->error = XML_TRUE; | ||||
return; | 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; | return; | ||||
} | } | ||||
if (strcmp(el, "option") == 0) | if (strcmp(el, "option") == 0) | ||||
{ | { | ||||
//jack_info("<option>"); | |||||
if ((attr[0] == NULL || attr[2] != NULL) || strcmp(attr[0], "name") != 0) | if ((attr[0] == NULL || attr[2] != NULL) || strcmp(attr[0], "name") != 0) | ||||
{ | { | ||||
jack_error("<option> XML element must contain exactly one attribute, named \"name\""); | 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; | 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; | context_ptr->option_used = 0; | ||||
return; | return; | ||||
} | } | ||||
@@ -225,49 +178,48 @@ jack_controller_settings_callback_elstart(void *data, const char *el, const char | |||||
void | void | ||||
jack_controller_settings_callback_elend(void *data, const char *el) | jack_controller_settings_callback_elend(void *data, const char *el) | ||||
{ | { | ||||
int i; | |||||
if (context_ptr->error) | if (context_ptr->error) | ||||
{ | { | ||||
return; | 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; | 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); | free(context_ptr->name); | ||||
context_ptr->name = NULL; | 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.controller_ptr = controller_ptr; | ||||
context.error = XML_FALSE; | context.error = XML_FALSE; | ||||
context.depth = -1; | |||||
context.option_value_capture = false; | |||||
context.address_index = 0; | |||||
context.name = NULL; | context.name = NULL; | ||||
context.container = NULL; | |||||
XML_SetElementHandler(parser, jack_controller_settings_callback_elstart, jack_controller_settings_callback_elend); | XML_SetElementHandler(parser, jack_controller_settings_callback_elstart, jack_controller_settings_callback_elend); | ||||
XML_SetCharacterDataHandler(parser, jack_controller_settings_callback_chrdata); | XML_SetCharacterDataHandler(parser, jack_controller_settings_callback_chrdata); | ||||
XML_SetUserData(parser, &context); | XML_SetUserData(parser, &context); | ||||
xmls = XML_ParseBuffer(parser, bytes_read, XML_TRUE); | xmls = XML_ParseBuffer(parser, bytes_read, XML_TRUE); | ||||
free(context.name); | |||||
free(context.container); | |||||
if (xmls == XML_STATUS_ERROR) | if (xmls == XML_STATUS_ERROR) | ||||
{ | { | ||||
jack_error("XML_ParseBuffer() failed."); | jack_error("XML_ParseBuffer() failed."); | ||||
@@ -1,797 +0,0 @@ | |||||
/* -*- Mode: C ; c-basic-offset: 4 -*- */ | |||||
/* | |||||
Copyright (C) 2007,2008 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. | |||||
*/ | |||||
#if defined(HAVE_CONFIG_H) | |||||
#include "config.h" | |||||
#endif | |||||
#include <stdbool.h> | |||||
#include <string.h> | |||||
#include <dbus/dbus.h> | |||||
#include <libxml/xmlwriter.h> | |||||
#include <libxml/parser.h> | |||||
#include <libxml/xpath.h> | |||||
#include <jack/driver.h> | |||||
#include <jack/engine.h> | |||||
#include "controller_internal.h" | |||||
#include "dbus.h" | |||||
/* XPath expression used for engine options selection */ | |||||
#define XPATH_ENGINE_OPTIONS_EXPRESSION "/jack/engine/option" | |||||
/* XPath expression used for drivers selection */ | |||||
#define XPATH_DRIVERS_EXPRESSION "/jack/drivers/driver" | |||||
/* XPath expression used for driver options selection */ | |||||
#define XPATH_DRIVER_OPTIONS_EXPRESSION "/jack/drivers/driver[@name = '%s']/option" | |||||
bool | |||||
jack_controller_settings_init() | |||||
{ | |||||
/* | |||||
* this initialize the library and check potential ABI mismatches | |||||
* between the version it was compiled for and the actual shared | |||||
* library used. | |||||
*/ | |||||
LIBXML_TEST_VERSION; | |||||
return true; | |||||
} | |||||
void | |||||
jack_controller_settings_uninit() | |||||
{ | |||||
} | |||||
#define writer ((xmlTextWriterPtr)context) | |||||
bool | |||||
jack_controller_settings_write_option( | |||||
void *context, | |||||
const char *name, | |||||
const char *content, | |||||
void *dbus_call_context_ptr) | |||||
{ | |||||
if (xmlTextWriterStartElement(writer, BAD_CAST "option") == -1) | |||||
{ | |||||
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterStartElement() failed."); | |||||
return false; | |||||
} | |||||
if (xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST name) == -1) | |||||
{ | |||||
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterWriteAttribute() failed."); | |||||
return false; | |||||
} | |||||
if (xmlTextWriterWriteString(writer, BAD_CAST content) == -1) | |||||
{ | |||||
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterWriteString() failed."); | |||||
return false; | |||||
} | |||||
if (xmlTextWriterEndElement(writer) == -1) | |||||
{ | |||||
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterEndElement() failed."); | |||||
return false; | |||||
} | |||||
return true; | |||||
} | |||||
#undef writer | |||||
bool | |||||
jack_controller_settings_write_engine( | |||||
struct jack_controller * controller_ptr, | |||||
xmlTextWriterPtr writer, | |||||
void *dbus_call_context_ptr) | |||||
{ | |||||
/* jack_info("engine settings begin"); */ | |||||
/* if (xmlTextWriterWriteComment(writer, BAD_CAST "engine parameters") == -1) */ | |||||
/* { */ | |||||
/* jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterWriteComment() failed."); */ | |||||
/* return false; */ | |||||
/* } */ | |||||
if (xmlTextWriterStartElement(writer, BAD_CAST "engine") == -1) | |||||
{ | |||||
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterStartElement() failed."); | |||||
return false; | |||||
} | |||||
if (!jack_controller_settings_save_engine_options(writer, controller_ptr, dbus_call_context_ptr)) | |||||
{ | |||||
return false; | |||||
} | |||||
if (xmlTextWriterEndElement(writer) == -1) | |||||
{ | |||||
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterEndElement() failed."); | |||||
return false; | |||||
} | |||||
/* jack_info("engine settings end"); */ | |||||
return true; | |||||
} | |||||
bool | |||||
jack_controller_settings_write_driver( | |||||
struct jack_controller * controller_ptr, | |||||
xmlTextWriterPtr writer, | |||||
jackctl_driver driver, | |||||
void *dbus_call_context_ptr) | |||||
{ | |||||
/* if (xmlTextWriterWriteComment(writer, BAD_CAST "driver parameters") == -1) */ | |||||
/* { */ | |||||
/* jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterWriteComment() failed."); */ | |||||
/* return false; */ | |||||
/* } */ | |||||
if (xmlTextWriterStartElement(writer, BAD_CAST "driver") == -1) | |||||
{ | |||||
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterStartElement() failed."); | |||||
return false; | |||||
} | |||||
if (xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST jackctl_driver_get_name(driver)) == -1) | |||||
{ | |||||
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterWriteAttribute() failed."); | |||||
return false; | |||||
} | |||||
if (!jack_controller_settings_save_driver_options(writer, driver, dbus_call_context_ptr)) | |||||
{ | |||||
return false; | |||||
} | |||||
if (xmlTextWriterEndElement(writer) == -1) | |||||
{ | |||||
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterEndElement() failed."); | |||||
return false; | |||||
} | |||||
return true; | |||||
} | |||||
bool | |||||
jack_controller_settings_write_drivers( | |||||
struct jack_controller * controller_ptr, | |||||
xmlTextWriterPtr writer, | |||||
void *dbus_call_context_ptr) | |||||
{ | |||||
const JSList * node_ptr; | |||||
jackctl_driver driver; | |||||
if (xmlTextWriterStartElement(writer, BAD_CAST "drivers") == -1) | |||||
{ | |||||
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterStartElement() failed."); | |||||
return false; | |||||
} | |||||
node_ptr = jackctl_server_get_drivers_list(controller_ptr->server); | |||||
while (node_ptr != NULL) | |||||
{ | |||||
driver = (jackctl_driver)node_ptr->data; | |||||
if (!jack_controller_settings_write_driver( | |||||
controller_ptr, | |||||
writer, | |||||
driver, | |||||
dbus_call_context_ptr)) | |||||
{ | |||||
return false; | |||||
} | |||||
node_ptr = jack_slist_next(node_ptr); | |||||
} | |||||
if (xmlTextWriterEndElement(writer) == -1) | |||||
{ | |||||
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterEndElement() failed."); | |||||
return false; | |||||
} | |||||
return true; | |||||
} | |||||
bool | |||||
jack_controller_settings_write_internal( | |||||
struct jack_controller * controller_ptr, | |||||
xmlTextWriterPtr writer, | |||||
jackctl_internal internal, | |||||
void *dbus_call_context_ptr) | |||||
{ | |||||
/* if (xmlTextWriterWriteComment(writer, BAD_CAST "driver parameters") == -1) */ | |||||
/* { */ | |||||
/* jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterWriteComment() failed."); */ | |||||
/* return false; */ | |||||
/* } */ | |||||
if (xmlTextWriterStartElement(writer, BAD_CAST "internal") == -1) | |||||
{ | |||||
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterStartElement() failed."); | |||||
return false; | |||||
} | |||||
if (xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST jackctl_internal_get_name(driver)) == -1) | |||||
{ | |||||
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterWriteAttribute() failed."); | |||||
return false; | |||||
} | |||||
if (!jack_controller_settings_save_internal_options(writer, internal, dbus_call_context_ptr)) | |||||
{ | |||||
return false; | |||||
} | |||||
if (xmlTextWriterEndElement(writer) == -1) | |||||
{ | |||||
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterEndElement() failed."); | |||||
return false; | |||||
} | |||||
return true; | |||||
} | |||||
bool | |||||
jack_controller_settings_write_internals( | |||||
struct jack_controller * controller_ptr, | |||||
xmlTextWriterPtr writer, | |||||
void *dbus_call_context_ptr) | |||||
{ | |||||
const JSList * node_ptr; | |||||
jackctl_driver internal; | |||||
if (xmlTextWriterStartElement(writer, BAD_CAST "internals") == -1) | |||||
{ | |||||
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterStartElement() failed."); | |||||
return false; | |||||
} | |||||
node_ptr = jackctl_server_get_internals_list(controller_ptr->server); | |||||
while (node_ptr != NULL) | |||||
{ | |||||
internal = (jackctl_internal)node_ptr->data; | |||||
if (!jack_controller_settings_write_internal( | |||||
controller_ptr, | |||||
writer, | |||||
internal, | |||||
dbus_call_context_ptr)) | |||||
{ | |||||
return false; | |||||
} | |||||
node_ptr = jack_slist_next(node_ptr); | |||||
} | |||||
if (xmlTextWriterEndElement(writer) == -1) | |||||
{ | |||||
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterEndElement() failed."); | |||||
return false; | |||||
} | |||||
return true; | |||||
} | |||||
bool | |||||
jack_controller_settings_save( | |||||
struct jack_controller * controller_ptr, | |||||
void *dbus_call_context_ptr) | |||||
{ | |||||
xmlTextWriterPtr writer; | |||||
char *filename; | |||||
size_t conf_len; | |||||
bool ret; | |||||
time_t timestamp; | |||||
char timestamp_str[28]; | |||||
time(×tamp); | |||||
timestamp_str[0] = ' '; | |||||
ctime_r(×tamp, timestamp_str + 1); | |||||
timestamp_str[25] = ' '; | |||||
ret = false; | |||||
conf_len = strlen(JACKDBUS_CONF); | |||||
filename = malloc(g_jackdbus_dir_len + conf_len + 1); | |||||
if (filename == NULL) | |||||
{ | |||||
jack_error("Out of memory."); | |||||
goto fail; | |||||
} | |||||
memcpy(filename, g_jackdbus_dir, g_jackdbus_dir_len); | |||||
memcpy(filename + g_jackdbus_dir_len, JACKDBUS_CONF, conf_len); | |||||
filename[g_jackdbus_dir_len + conf_len] = 0; | |||||
jack_info("saving settings to \"%s\"", filename); | |||||
writer = xmlNewTextWriterFilename(filename, 0); | |||||
if (writer == NULL) | |||||
{ | |||||
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "Error creating the xml writer."); | |||||
goto fail_free_filename; | |||||
} | |||||
if (xmlTextWriterSetIndent(writer, 1) == -1) | |||||
{ | |||||
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterSetIndent() failed."); | |||||
goto fail_free_writter; | |||||
} | |||||
if (xmlTextWriterStartDocument(writer, NULL, NULL, NULL) == -1) | |||||
{ | |||||
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterStartDocument() failed."); | |||||
goto fail_free_writter; | |||||
} | |||||
if (xmlTextWriterWriteComment(writer, BAD_CAST "\n" JACK_CONF_HEADER_TEXT) == -1) | |||||
{ | |||||
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterWriteComment() failed."); | |||||
goto fail_free_writter; | |||||
} | |||||
if (xmlTextWriterWriteComment(writer, BAD_CAST timestamp_str) == -1) | |||||
{ | |||||
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterWriteComment() failed."); | |||||
goto fail_free_writter; | |||||
} | |||||
if (xmlTextWriterStartElement(writer, BAD_CAST "jack") == -1) | |||||
{ | |||||
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterStartElement() failed."); | |||||
goto fail_free_writter; | |||||
} | |||||
if (!jack_controller_settings_write_engine(controller_ptr, writer, dbus_call_context_ptr)) | |||||
{ | |||||
goto fail_free_writter; | |||||
} | |||||
if (!jack_controller_settings_write_drivers(controller_ptr, writer, dbus_call_context_ptr)) | |||||
{ | |||||
goto fail_free_writter; | |||||
} | |||||
if (!jack_controller_settings_write_internals(controller_ptr, writer, dbus_call_context_ptr)) | |||||
{ | |||||
goto fail_free_writter; | |||||
} | |||||
if (xmlTextWriterEndElement(writer) == -1) | |||||
{ | |||||
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterStartElement() failed."); | |||||
goto fail_free_writter; | |||||
} | |||||
if (xmlTextWriterEndDocument(writer) == -1) | |||||
{ | |||||
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "xmlTextWriterEndDocument() failed."); | |||||
goto fail_free_writter; | |||||
} | |||||
ret = true; | |||||
fail_free_writter: | |||||
xmlFreeTextWriter(writer); | |||||
fail_free_filename: | |||||
free(filename); | |||||
fail: | |||||
return ret; | |||||
} | |||||
void | |||||
jack_controller_settings_read_engine( | |||||
struct jack_controller * controller_ptr, | |||||
xmlXPathContextPtr xpath_ctx_ptr) | |||||
{ | |||||
xmlXPathObjectPtr xpath_obj_ptr; | |||||
xmlBufferPtr content_buffer_ptr; | |||||
int i; | |||||
const char *option_name; | |||||
const char *option_value; | |||||
/* Evaluate xpath expression */ | |||||
xpath_obj_ptr = xmlXPathEvalExpression((const xmlChar *)XPATH_ENGINE_OPTIONS_EXPRESSION, xpath_ctx_ptr); | |||||
if (xpath_obj_ptr == NULL) | |||||
{ | |||||
jack_error("Unable to evaluate XPath expression \"%s\"", XPATH_ENGINE_OPTIONS_EXPRESSION); | |||||
goto exit; | |||||
} | |||||
if (xpath_obj_ptr->nodesetval == NULL || xpath_obj_ptr->nodesetval->nodeNr == 0) | |||||
{ | |||||
jack_error("XPath \"%s\" evaluation returned no data", XPATH_ENGINE_OPTIONS_EXPRESSION); | |||||
goto free_xpath_obj; | |||||
} | |||||
content_buffer_ptr = xmlBufferCreate(); | |||||
if (content_buffer_ptr == NULL) | |||||
{ | |||||
jack_error("xmlBufferCreate() failed."); | |||||
goto free_xpath_obj; | |||||
} | |||||
for (i = 0 ; i < xpath_obj_ptr->nodesetval->nodeNr ; i++) | |||||
{ | |||||
//jack_info("engine option \"%s\" at index %d", xmlGetProp(xpath_obj_ptr->nodesetval->nodeTab[i], BAD_CAST "name"), i); | |||||
if (xmlNodeBufGetContent(content_buffer_ptr, xpath_obj_ptr->nodesetval->nodeTab[i]) == -1) | |||||
{ | |||||
jack_error("xmlNodeBufGetContent() failed."); | |||||
goto next_option; | |||||
} | |||||
option_name = (const char *)xmlGetProp(xpath_obj_ptr->nodesetval->nodeTab[i], BAD_CAST "name"); | |||||
option_value = (const char *)xmlBufferContent(content_buffer_ptr); | |||||
jack_controller_settings_set_engine_option(controller_ptr, option_name, option_value); | |||||
next_option: | |||||
xmlBufferEmpty(content_buffer_ptr); | |||||
} | |||||
//free_buffer: | |||||
xmlBufferFree(content_buffer_ptr); | |||||
free_xpath_obj: | |||||
xmlXPathFreeObject(xpath_obj_ptr); | |||||
exit: | |||||
return; | |||||
} | |||||
void | |||||
jack_controller_settings_read_driver( | |||||
struct jack_controller * controller_ptr, | |||||
xmlXPathContextPtr xpath_ctx_ptr, | |||||
jackctl_driver driver) | |||||
{ | |||||
char *xpath; | |||||
size_t xpath_len; | |||||
xmlXPathObjectPtr xpath_obj_ptr; | |||||
xmlBufferPtr content_buffer_ptr; | |||||
int i; | |||||
const char *option_name; | |||||
const char *option_value; | |||||
const char *driver_name; | |||||
driver_name = jackctl_driver_get_name(driver); | |||||
jack_info("reading options for driver \"%s\"", driver_name); | |||||
xpath_len = snprintf(NULL, 0, XPATH_DRIVER_OPTIONS_EXPRESSION, driver_name); | |||||
xpath = malloc(xpath_len); | |||||
if (xpath == NULL) | |||||
{ | |||||
jack_error("Out of memory."); | |||||
goto exit; | |||||
} | |||||
snprintf(xpath, xpath_len, XPATH_DRIVER_OPTIONS_EXPRESSION, driver_name); | |||||
//jack_info("xpath = \"%s\"", xpath); | |||||
/* Evaluate xpath expression */ | |||||
xpath_obj_ptr = xmlXPathEvalExpression((const xmlChar *)xpath, xpath_ctx_ptr); | |||||
if (xpath_obj_ptr == NULL) | |||||
{ | |||||
jack_error("Unable to evaluate XPath expression \"%s\"", xpath); | |||||
goto free_xpath; | |||||
} | |||||
if (xpath_obj_ptr->nodesetval == NULL || xpath_obj_ptr->nodesetval->nodeNr == 0) | |||||
{ | |||||
//jack_info("XPath \"%s\" evaluation returned no data", xpath); | |||||
goto free_xpath_obj; | |||||
} | |||||
content_buffer_ptr = xmlBufferCreate(); | |||||
if (content_buffer_ptr == NULL) | |||||
{ | |||||
jack_error("xmlBufferCreate() failed."); | |||||
goto free_xpath_obj; | |||||
} | |||||
for (i = 0 ; i < xpath_obj_ptr->nodesetval->nodeNr ; i++) | |||||
{ | |||||
//jack_info("driver option \"%s\" at index %d", xmlGetProp(xpath_obj_ptr->nodesetval->nodeTab[i], BAD_CAST "name"), i); | |||||
if (xmlNodeBufGetContent(content_buffer_ptr, xpath_obj_ptr->nodesetval->nodeTab[i]) == -1) | |||||
{ | |||||
jack_error("xmlNodeBufGetContent() failed."); | |||||
goto next_option; | |||||
} | |||||
option_name = (const char *)xmlGetProp(xpath_obj_ptr->nodesetval->nodeTab[i], BAD_CAST "name"); | |||||
option_value = (const char *)xmlBufferContent(content_buffer_ptr); | |||||
jack_controller_settings_set_driver_option(driver, option_name, option_value); | |||||
next_option: | |||||
xmlBufferEmpty(content_buffer_ptr); | |||||
} | |||||
//free_buffer: | |||||
xmlBufferFree(content_buffer_ptr); | |||||
free_xpath_obj: | |||||
xmlXPathFreeObject(xpath_obj_ptr); | |||||
free_xpath: | |||||
free(xpath); | |||||
exit: | |||||
return; | |||||
} | |||||
void | |||||
jack_controller_settings_read_internal( | |||||
struct jack_controller * controller_ptr, | |||||
xmlXPathContextPtr xpath_ctx_ptr, | |||||
jackctl_internal internal) | |||||
{ | |||||
char *xpath; | |||||
size_t xpath_len; | |||||
xmlXPathObjectPtr xpath_obj_ptr; | |||||
xmlBufferPtr content_buffer_ptr; | |||||
int i; | |||||
const char *option_name; | |||||
const char *option_value; | |||||
const char *internal_name; | |||||
internal_name = jackctl_internal_get_name(internal); | |||||
jack_info("reading options for internal \"%s\"", internal_name); | |||||
xpath_len = snprintf(NULL, 0, XPATH_DRIVER_OPTIONS_EXPRESSION, internal_name); | |||||
xpath = malloc(xpath_len); | |||||
if (xpath == NULL) | |||||
{ | |||||
jack_error("Out of memory."); | |||||
goto exit; | |||||
} | |||||
snprintf(xpath, xpath_len, XPATH_DRIVER_OPTIONS_EXPRESSION, internal_name); | |||||
//jack_info("xpath = \"%s\"", xpath); | |||||
/* Evaluate xpath expression */ | |||||
xpath_obj_ptr = xmlXPathEvalExpression((const xmlChar *)xpath, xpath_ctx_ptr); | |||||
if (xpath_obj_ptr == NULL) | |||||
{ | |||||
jack_error("Unable to evaluate XPath expression \"%s\"", xpath); | |||||
goto free_xpath; | |||||
} | |||||
if (xpath_obj_ptr->nodesetval == NULL || xpath_obj_ptr->nodesetval->nodeNr == 0) | |||||
{ | |||||
//jack_info("XPath \"%s\" evaluation returned no data", xpath); | |||||
goto free_xpath_obj; | |||||
} | |||||
content_buffer_ptr = xmlBufferCreate(); | |||||
if (content_buffer_ptr == NULL) | |||||
{ | |||||
jack_error("xmlBufferCreate() failed."); | |||||
goto free_xpath_obj; | |||||
} | |||||
for (i = 0 ; i < xpath_obj_ptr->nodesetval->nodeNr ; i++) | |||||
{ | |||||
//jack_info("driver option \"%s\" at index %d", xmlGetProp(xpath_obj_ptr->nodesetval->nodeTab[i], BAD_CAST "name"), i); | |||||
if (xmlNodeBufGetContent(content_buffer_ptr, xpath_obj_ptr->nodesetval->nodeTab[i]) == -1) | |||||
{ | |||||
jack_error("xmlNodeBufGetContent() failed."); | |||||
goto next_option; | |||||
} | |||||
option_name = (const char *)xmlGetProp(xpath_obj_ptr->nodesetval->nodeTab[i], BAD_CAST "name"); | |||||
option_value = (const char *)xmlBufferContent(content_buffer_ptr); | |||||
jack_controller_settings_set_internal_option(internal, option_name, option_value); | |||||
next_option: | |||||
xmlBufferEmpty(content_buffer_ptr); | |||||
} | |||||
//free_buffer: | |||||
xmlBufferFree(content_buffer_ptr); | |||||
free_xpath_obj: | |||||
xmlXPathFreeObject(xpath_obj_ptr); | |||||
free_xpath: | |||||
free(xpath); | |||||
exit: | |||||
return; | |||||
} | |||||
void | |||||
jack_controller_settings_read_drivers( | |||||
struct jack_controller * controller_ptr, | |||||
xmlXPathContextPtr xpath_ctx_ptr) | |||||
{ | |||||
xmlXPathObjectPtr xpath_obj_ptr; | |||||
int i; | |||||
const char *driver_name; | |||||
jackctl_driver driver; | |||||
/* Evaluate xpath expression */ | |||||
xpath_obj_ptr = xmlXPathEvalExpression((const xmlChar *)XPATH_DRIVERS_EXPRESSION, xpath_ctx_ptr); | |||||
if (xpath_obj_ptr == NULL) | |||||
{ | |||||
jack_error("Unable to evaluate XPath expression \"%s\"", XPATH_DRIVERS_EXPRESSION); | |||||
goto exit; | |||||
} | |||||
if (xpath_obj_ptr->nodesetval == NULL || xpath_obj_ptr->nodesetval->nodeNr == 0) | |||||
{ | |||||
jack_error("XPath \"%s\" evaluation returned no data", XPATH_DRIVERS_EXPRESSION); | |||||
goto free_xpath_obj; | |||||
} | |||||
for (i = 0 ; i < xpath_obj_ptr->nodesetval->nodeNr ; i++) | |||||
{ | |||||
driver_name = (const char *)xmlGetProp(xpath_obj_ptr->nodesetval->nodeTab[i], BAD_CAST "name"); | |||||
driver = jack_controller_find_driver(controller_ptr->server, driver_name); | |||||
if (driver == NULL) | |||||
{ | |||||
jack_error("ignoring settings for unknown driver \"%s\"", driver_name); | |||||
} | |||||
else | |||||
{ | |||||
jack_info("setting for driver \"%s\" found", driver_name); | |||||
jack_controller_settings_read_driver(controller_ptr, xpath_ctx_ptr, driver); | |||||
} | |||||
} | |||||
free_xpath_obj: | |||||
xmlXPathFreeObject(xpath_obj_ptr); | |||||
exit: | |||||
return; | |||||
} | |||||
void | |||||
jack_controller_settings_read_internals( | |||||
struct jack_controller * controller_ptr, | |||||
xmlXPathContextPtr xpath_ctx_ptr) | |||||
{ | |||||
xmlXPathObjectPtr xpath_obj_ptr; | |||||
int i; | |||||
const char *internal_name; | |||||
jackctl_internal internal; | |||||
/* Evaluate xpath expression */ | |||||
xpath_obj_ptr = xmlXPathEvalExpression((const xmlChar *)XPATH_DRIVERS_EXPRESSION, xpath_ctx_ptr); | |||||
if (xpath_obj_ptr == NULL) | |||||
{ | |||||
jack_error("Unable to evaluate XPath expression \"%s\"", XPATH_DRIVERS_EXPRESSION); | |||||
goto exit; | |||||
} | |||||
if (xpath_obj_ptr->nodesetval == NULL || xpath_obj_ptr->nodesetval->nodeNr == 0) | |||||
{ | |||||
jack_error("XPath \"%s\" evaluation returned no data", XPATH_DRIVERS_EXPRESSION); | |||||
goto free_xpath_obj; | |||||
} | |||||
for (i = 0 ; i < xpath_obj_ptr->nodesetval->nodeNr ; i++) | |||||
{ | |||||
internal_name = (const char *)xmlGetProp(xpath_obj_ptr->nodesetval->nodeTab[i], BAD_CAST "name"); | |||||
driver = jack_controller_find_internal(controller_ptr->server, driver_name); | |||||
if (driver == NULL) | |||||
{ | |||||
jack_error("ignoring settings for unknown internal \"%s\"", internal_name); | |||||
} | |||||
else | |||||
{ | |||||
jack_info("setting for internal \"%s\" found", internal_name); | |||||
jack_controller_settings_read_internal(controller_ptr, xpath_ctx_ptr, driver); | |||||
} | |||||
} | |||||
free_xpath_obj: | |||||
xmlXPathFreeObject(xpath_obj_ptr); | |||||
exit: | |||||
return; | |||||
} | |||||
void | |||||
jack_controller_settings_load( | |||||
struct jack_controller * controller_ptr) | |||||
{ | |||||
char *filename; | |||||
size_t conf_len; | |||||
xmlDocPtr doc_ptr; | |||||
xmlXPathContextPtr xpath_ctx_ptr; | |||||
conf_len = strlen(JACKDBUS_CONF); | |||||
filename = malloc(g_jackdbus_dir_len + conf_len + 1); | |||||
if (filename == NULL) | |||||
{ | |||||
jack_error("Out of memory."); | |||||
goto exit; | |||||
} | |||||
memcpy(filename, g_jackdbus_dir, g_jackdbus_dir_len); | |||||
memcpy(filename + g_jackdbus_dir_len, JACKDBUS_CONF, conf_len); | |||||
filename[g_jackdbus_dir_len + conf_len] = 0; | |||||
jack_info("loading settings from \"%s\"", filename); | |||||
doc_ptr = xmlParseFile(filename); | |||||
if (doc_ptr == NULL) | |||||
{ | |||||
jack_error("Failed to parse \"%s\"", filename); | |||||
goto free_filename; | |||||
} | |||||
/* Create xpath evaluation context */ | |||||
xpath_ctx_ptr = xmlXPathNewContext(doc_ptr); | |||||
if (xpath_ctx_ptr == NULL) | |||||
{ | |||||
jack_error("Unable to create new XPath context"); | |||||
goto free_doc; | |||||
} | |||||
jack_controller_settings_read_engine(controller_ptr, xpath_ctx_ptr); | |||||
jack_controller_settings_read_drivers(controller_ptr, xpath_ctx_ptr); | |||||
jack_controller_settings_read_internals(controller_ptr, xpath_ctx_ptr); | |||||
xmlXPathFreeContext(xpath_ctx_ptr); | |||||
free_doc: | |||||
xmlFreeDoc(doc_ptr); | |||||
free_filename: | |||||
free(filename); | |||||
exit: | |||||
return; | |||||
} | |||||
void | |||||
jack_controller_settings_save_auto( | |||||
struct jack_controller * controller_ptr) | |||||
{ | |||||
jack_controller_settings_save(controller_ptr, NULL); | |||||
} |
@@ -53,54 +53,57 @@ jack_controller_settings_write_string(int fd, const char * string, void *dbus_ca | |||||
struct save_context | struct save_context | ||||
{ | { | ||||
void * call; | |||||
int fd; | 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 fd | ||||
#undef ctx_ptr | |||||
bool | bool | ||||
jack_controller_settings_save( | jack_controller_settings_save( | ||||
@@ -114,9 +117,9 @@ jack_controller_settings_save( | |||||
time_t timestamp; | time_t timestamp; | ||||
char timestamp_str[26]; | char timestamp_str[26]; | ||||
struct save_context context; | struct save_context context; | ||||
const JSList * node_ptr; | |||||
jackctl_driver_t *driver; | |||||
jackctl_internal_t *internal; | |||||
const char * modules[] = {"driver", "internal", NULL}; | |||||
char buffer[100]; | |||||
unsigned int i; | |||||
time(×tamp); | time(×tamp); | ||||
ctime_r(×tamp, timestamp_str); | ctime_r(×tamp, timestamp_str); | ||||
@@ -147,6 +150,7 @@ jack_controller_settings_save( | |||||
} | } | ||||
context.fd = fd; | 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)) | 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 = " "; | 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; | goto exit_close; | ||||
} | } | ||||
@@ -206,100 +212,50 @@ jack_controller_settings_save( | |||||
goto exit_close; | 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; | 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; | 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; | 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; | 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; | 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; | 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; | 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)) | if (!jack_controller_settings_write_string(fd, "</jack>\n", dbus_call_context_ptr)) | ||||
@@ -35,7 +35,7 @@ showtime () | |||||
transport_state = jack_transport_query (client, ¤t); | transport_state = jack_transport_query (client, ¤t); | ||||
frame_time = jack_frame_time (client); | frame_time = jack_frame_time (client); | ||||
printf ("frame = %u frame_time = %u usecs = %lld \t", current.frame, frame_time, current.usecs); | |||||
printf ("frame = %u frame_time = %u usecs = %ld \t", current.frame, frame_time, current.usecs); | |||||
switch (transport_state) { | switch (transport_state) { | ||||
case JackTransportStopped: | case JackTransportStopped: | ||||
@@ -54,7 +54,7 @@ static const double twoRaisedTo32Reciprocal = 1. / twoRaisedTo32; | |||||
#include "windows.h" | #include "windows.h" | ||||
#include "mmsystem.h" | #include "mmsystem.h" | ||||
#ifdef _WIN64 | #ifdef _WIN64 | ||||
#define JACK_ROUTER "JackRouter64.dll" | |||||
#define JACK_ROUTER "JackRouter.dll" | |||||
#include <psapi.h> | #include <psapi.h> | ||||
#else | #else | ||||
#define JACK_ROUTER "JackRouter.dll" | #define JACK_ROUTER "JackRouter.dll" | ||||
@@ -242,7 +242,7 @@ | |||||
<SuppressStartupBanner>true</SuppressStartupBanner> | <SuppressStartupBanner>true</SuppressStartupBanner> | ||||
<LinkDLL>true</LinkDLL> | <LinkDLL>true</LinkDLL> | ||||
<SubSystem>Windows</SubSystem> | <SubSystem>Windows</SubSystem> | ||||
<OutputFile>.\Release\JackRouter64.dll</OutputFile> | |||||
<OutputFile>.\x64\Release\JackRouter.dll</OutputFile> | |||||
<ImportLibrary>.\Release\JackRouter64.lib</ImportLibrary> | <ImportLibrary>.\Release\JackRouter64.lib</ImportLibrary> | ||||
<AdditionalDependencies>odbc32.lib;odbccp32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies> | <AdditionalDependencies>odbc32.lib;odbccp32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies> | ||||
<ModuleDefinitionFile>.\JackRouter.def</ModuleDefinitionFile> | <ModuleDefinitionFile>.\JackRouter.def</ModuleDefinitionFile> | ||||
@@ -53,7 +53,6 @@ | |||||
<bgfoot> </> | <bgfoot> </> | ||||
<bgback> </> | <bgback> </> | ||||
<files listview > | <files listview > | ||||
<_><src>.\src\vcredist_2010_x86.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | |||||
<_><src>..\Release\bin\libjack.a</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></> | <_><src>..\Release\bin\libjack.a</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></> | ||||
<_><src>..\Release\bin\libjack.lib</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></> | <_><src>..\Release\bin\libjack.lib</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></> | ||||
<_><src>..\Release\bin\libjack.def</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></> | <_><src>..\Release\bin\libjack.def</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></> | ||||
@@ -95,8 +94,10 @@ | |||||
<_><src>..\..\common\jack\systemdeps.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>1</></> | <_><src>..\..\common\jack\systemdeps.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>1</></> | ||||
<_><src>..\..\common\jack\weakjack.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>1</></> | <_><src>..\..\common\jack\weakjack.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>1</></> | ||||
<_><src>..\..\common\jack\weakmacros.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>1</></> | <_><src>..\..\common\jack\weakmacros.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>1</></> | ||||
<_><src>.\JackRouter.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | |||||
<_><src>.\JackRouter.ini</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | |||||
<_><src>.\src\32bits\JackRouter.dll</><dest>inst</><custom>32bits</><ifexist>overnewer</><recurs>0</></> | |||||
<_><src>.\src\32bits\JackRouter.ini</><dest>inst</><custom>32bits</><ifexist>overnewer</><recurs>0</></> | |||||
<_><src>.\src\32bits\msvcr100.dll</><dest>inst</><custom>32bits</><ifexist>overnewer</><recurs>0</></> | |||||
<_><src>.\src\32bits\msvcp100.dll</><dest>inst</><custom>32bits</><ifexist>overnewer</><recurs>0</></> | |||||
<_><src>.\qjackctl\mingwm10.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | <_><src>.\qjackctl\mingwm10.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | ||||
<_><src>.\qjackctl\qjackctl.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | <_><src>.\qjackctl\qjackctl.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | ||||
<_><src>.\qjackctl\QtCore4.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | <_><src>.\qjackctl\QtCore4.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | ||||
@@ -107,7 +108,6 @@ | |||||
</files> | </files> | ||||
<runx listview > | <runx listview > | ||||
<_><type>app</><path>inst</><file>vcredist_2010_x86.exe</><cmdline></><wait>1</><workdir>inst</><custdir></><when>end</></> | |||||
</runx> | </runx> | ||||
<registry listview > | <registry listview > | ||||
@@ -126,7 +126,7 @@ | |||||
</copy> | </copy> | ||||
<activex listview > | <activex listview > | ||||
<_><path>inst</><name>JackRouter.dll</></> | |||||
<_><path>inst</><name>32bits\JackRouter.dll</></> | |||||
</activex> | </activex> | ||||
<font listview > | <font listview > | ||||
@@ -53,8 +53,6 @@ | |||||
<bgfoot> </> | <bgfoot> </> | ||||
<bgback> </> | <bgback> </> | ||||
<files listview > | <files listview > | ||||
<_><src>.\src\vcredist_2010_x86.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | |||||
<_><src>.\src\vcredist_2010_x64.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | |||||
<_><src>..\Release64\bin\libjack64.a</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></> | <_><src>..\Release64\bin\libjack64.a</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></> | ||||
<_><src>..\Release64\bin\libjack64.lib</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></> | <_><src>..\Release64\bin\libjack64.lib</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></> | ||||
<_><src>..\Release64\bin\libjack64.def</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></> | <_><src>..\Release64\bin\libjack64.def</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></> | ||||
@@ -71,6 +69,7 @@ | |||||
<_><src>..\Release\bin\libjackserver.lib</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></> | <_><src>..\Release\bin\libjackserver.lib</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></> | ||||
<_><src>..\Release\bin\libjackserver.def</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></> | <_><src>..\Release\bin\libjackserver.def</><dest>inst</><custom>lib</><ifexist>overnewer</><recurs>0</></> | ||||
<_><src>..\Release\bin\libjackserver.dll</><dest>sys</><custom></><ifexist>overnewer</><recurs>0</></> | <_><src>..\Release\bin\libjackserver.dll</><dest>sys</><custom></><ifexist>overnewer</><recurs>0</></> | ||||
<_><src>..\Release\bin\portaudio_x86.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | |||||
<_><src>..\Release64\bin\jack_connect.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | <_><src>..\Release64\bin\jack_connect.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | ||||
<_><src>..\Release64\bin\jack_disconnect.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | <_><src>..\Release64\bin\jack_disconnect.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | ||||
<_><src>..\Release64\bin\jack_load.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | <_><src>..\Release64\bin\jack_load.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | ||||
@@ -81,7 +80,6 @@ | |||||
<_><src>..\Release64\bin\jackd.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | <_><src>..\Release64\bin\jackd.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | ||||
<_><src>..\Release64\bin\libsamplerate_x86_64.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | <_><src>..\Release64\bin\libsamplerate_x86_64.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | ||||
<_><src>..\Release64\bin\portaudio_x86_64.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | <_><src>..\Release64\bin\portaudio_x86_64.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | ||||
<_><src>..\Release\bin\portaudio_x86.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | |||||
<_><src>..\Release64\bin\jack\jack_net.dll</><dest>inst</><custom>jack</><ifexist>overnewer</><recurs>0</></> | <_><src>..\Release64\bin\jack\jack_net.dll</><dest>inst</><custom>jack</><ifexist>overnewer</><recurs>0</></> | ||||
<_><src>..\Release64\bin\jack\jack_netone.dll</><dest>inst</><custom>jack</><ifexist>overnewer</><recurs>0</></> | <_><src>..\Release64\bin\jack\jack_netone.dll</><dest>inst</><custom>jack</><ifexist>overnewer</><recurs>0</></> | ||||
<_><src>..\Release64\bin\jack_netsource.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | <_><src>..\Release64\bin\jack_netsource.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | ||||
@@ -105,9 +103,14 @@ | |||||
<_><src>..\..\common\jack\systemdeps.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>1</></> | <_><src>..\..\common\jack\systemdeps.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>1</></> | ||||
<_><src>..\..\common\jack\weakjack.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>1</></> | <_><src>..\..\common\jack\weakjack.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>1</></> | ||||
<_><src>..\..\common\jack\weakmacros.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>1</></> | <_><src>..\..\common\jack\weakmacros.h</><dest>inst</><custom>includes\jack</><ifexist>overnewer</><recurs>1</></> | ||||
<_><src>.\JackRouter.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | |||||
<_><src>.\JackRouter64.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | |||||
<_><src>.\JackRouter.ini</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | |||||
<_><src>.\src\32bits\JackRouter.dll</><dest>inst</><custom>32bits</><ifexist>overnewer</><recurs>0</></> | |||||
<_><src>.\src\32bits\JackRouter.ini</><dest>inst</><custom>32bits</><ifexist>overnewer</><recurs>0</></> | |||||
<_><src>.\src\32bits\msvcr100.dll</><dest>inst</><custom>32bits</><ifexist>overnewer</><recurs>0</></> | |||||
<_><src>.\src\32bits\msvcp100.dll</><dest>inst</><custom>32bits</><ifexist>overnewer</><recurs>0</></> | |||||
<_><src>.\src\64bits\JackRouter.dll</><dest>inst</><custom>64bits</><ifexist>overnewer</><recurs>0</></> | |||||
<_><src>.\src\64bits\JackRouter.ini</><dest>inst</><custom>64bits</><ifexist>overnewer</><recurs>0</></> | |||||
<_><src>.\src\64bits\msvcr100.dll</><dest>inst</><custom>64bits</><ifexist>overnewer</><recurs>0</></> | |||||
<_><src>.\src\64bits\msvcp100.dll</><dest>inst</><custom>64bits</><ifexist>overnewer</><recurs>0</></> | |||||
<_><src>.\qjackctl\mingwm10.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | <_><src>.\qjackctl\mingwm10.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | ||||
<_><src>.\qjackctl\qjackctl.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | <_><src>.\qjackctl\qjackctl.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | ||||
<_><src>.\qjackctl\QtCore4.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | <_><src>.\qjackctl\QtCore4.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | ||||
@@ -118,9 +121,7 @@ | |||||
</files> | </files> | ||||
<runx listview > | <runx listview > | ||||
<_><type>app</><path>inst</><file>vcredist_2010_x86.exe</><cmdline></><wait>1</><workdir>inst</><custdir></><when>end</></> | |||||
<_><type>app</><path>inst</><file>vcredist_2010_x64.exe</><cmdline></><wait>1</><workdir>inst</><custdir></><when>end</></> | |||||
</runx> | |||||
</runx> | |||||
<registry listview > | <registry listview > | ||||
</registry> | </registry> | ||||
@@ -138,8 +139,8 @@ | |||||
</copy> | </copy> | ||||
<activex listview > | <activex listview > | ||||
<_><path>inst</><name>JackRouter.dll</></> | |||||
<_><path>inst</><name>JackRouter64.dll</></> | |||||
<_><path>inst</><name>32bits\JackRouter.dll</></> | |||||
<_><path>inst</><name>64bits\JackRouter.dll</></> | |||||
</activex> | </activex> | ||||
<font listview > | <font listview > | ||||
@@ -0,0 +1,7 @@ | |||||
[IO] | |||||
input=4 | |||||
output=4 | |||||
[AUTO_CONNECT] | |||||
input=1 | |||||
output=1 |
@@ -0,0 +1,7 @@ | |||||
[IO] | |||||
input=4 | |||||
output=4 | |||||
[AUTO_CONNECT] | |||||
input=1 | |||||
output=1 |
@@ -50,7 +50,7 @@ namespace Jack | |||||
int out_max = 0; | int out_max = 0; | ||||
fInputDevice = Pa_GetDefaultInputDevice(); | fInputDevice = Pa_GetDefaultInputDevice(); | ||||
fOutputDevice = Pa_GetDefaultOutputDevice(); | |||||
fOutputDevice = Pa_GetDefaultOutputDevice(); | |||||
for (node = params; node; node = jack_slist_next(node)) | for (node = params; node; node = jack_slist_next(node)) | ||||
{ | { | ||||
@@ -117,22 +117,19 @@ namespace Jack | |||||
//set adapter interface channels | //set adapter interface channels | ||||
SetInputs ( fCaptureChannels ); | SetInputs ( fCaptureChannels ); | ||||
SetOutputs ( fPlaybackChannels ); | |||||
SetOutputs ( fPlaybackChannels ); | |||||
} | } | ||||
int JackPortAudioAdapter::Open() | int JackPortAudioAdapter::Open() | ||||
{ | { | ||||
PaError err; | PaError err; | ||||
PaStreamParameters inputParameters; | PaStreamParameters inputParameters; | ||||
PaStreamParameters outputParameters; | |||||
if (fInputDevice == paNoDevice && fOutputDevice == paNoDevice) { | |||||
jack_error("No input and output device!!"); | |||||
return -1; | |||||
} | |||||
PaStreamParameters outputParameters; | |||||
if ( JackAudioAdapterInterface::Open() < 0 ) | |||||
if (fInputDevice == paNoDevice && fOutputDevice == paNoDevice) { | |||||
jack_error("No input and output device!!"); | |||||
return -1; | return -1; | ||||
} | |||||
jack_log("JackPortAudioAdapter::Open fInputDevice = %d DeviceName %s", fInputDevice, fPaDevices.GetFullName(fInputDevice).c_str()); | jack_log("JackPortAudioAdapter::Open fInputDevice = %d DeviceName %s", fInputDevice, fPaDevices.GetFullName(fInputDevice).c_str()); | ||||
jack_log("JackPortAudioAdapter::Open fOutputDevice = %d DeviceName %s", fOutputDevice, fPaDevices.GetFullName(fOutputDevice).c_str()); | jack_log("JackPortAudioAdapter::Open fOutputDevice = %d DeviceName %s", fOutputDevice, fPaDevices.GetFullName(fOutputDevice).c_str()); | ||||
@@ -191,7 +188,7 @@ namespace Jack | |||||
jack_log ( "JackPortAudioAdapter:: Pa_StopStream" ); | jack_log ( "JackPortAudioAdapter:: Pa_StopStream" ); | ||||
Pa_CloseStream ( fStream ); | Pa_CloseStream ( fStream ); | ||||
jack_log ( "JackPortAudioAdapter:: Pa_CloseStream" ); | jack_log ( "JackPortAudioAdapter:: Pa_CloseStream" ); | ||||
return JackAudioAdapterInterface::Close(); | |||||
return 0; | |||||
} | } | ||||
int JackPortAudioAdapter::SetSampleRate ( jack_nframes_t sample_rate ) | int JackPortAudioAdapter::SetSampleRate ( jack_nframes_t sample_rate ) | ||||
@@ -314,3 +311,4 @@ extern "C" | |||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
} | } | ||||
#endif | #endif | ||||