284 lines
7.7 KiB
C
284 lines
7.7 KiB
C
/* -*- 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 <stdint.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <dbus/dbus.h>
|
|
#include <time.h>
|
|
|
|
#include "controller_internal.h"
|
|
#include "jackdbus.h"
|
|
|
|
bool
|
|
jack_controller_settings_write_string(int fd, const char * string, void *dbus_call_context_ptr)
|
|
{
|
|
size_t len;
|
|
|
|
len = strlen(string);
|
|
|
|
if (write(fd, string, len) != (ssize_t)len)
|
|
{
|
|
jack_dbus_error(dbus_call_context_ptr, JACK_DBUS_ERROR_GENERIC, "write() failed to write config file.");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
struct save_context
|
|
{
|
|
void * call;
|
|
int fd;
|
|
const char * indent;
|
|
jack_params_handle params;
|
|
const char * address[PARAM_ADDRESS_SIZE];
|
|
const char * str;
|
|
};
|
|
|
|
#define ctx_ptr ((struct save_context *)context)
|
|
#define fd (ctx_ptr->fd)
|
|
|
|
static bool jack_controller_serialize_parameter(void * context, const struct jack_parameter * param_ptr)
|
|
{
|
|
char value[JACK_PARAM_STRING_MAX + 1];
|
|
|
|
if (!param_ptr->vtable.is_set(param_ptr->obj))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
jack_controller_serialize_parameter_value(param_ptr, value);
|
|
|
|
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);
|
|
}
|
|
|
|
bool serialize_modules(void * context, const char * name)
|
|
{
|
|
ctx_ptr->indent = " ";
|
|
ctx_ptr->address[1] = name;
|
|
ctx_ptr->address[2] = NULL;
|
|
|
|
return
|
|
jack_controller_settings_write_string(fd, " <", ctx_ptr->call) &&
|
|
jack_controller_settings_write_string(fd, ctx_ptr->str, ctx_ptr->call) &&
|
|
jack_controller_settings_write_string(fd, " name=\"", ctx_ptr->call) &&
|
|
jack_controller_settings_write_string(fd, name, ctx_ptr->call) &&
|
|
jack_controller_settings_write_string(fd, "\">\n", ctx_ptr->call) &&
|
|
jack_params_iterate_params(ctx_ptr->params, ctx_ptr->address, jack_controller_serialize_parameter, ctx_ptr) &&
|
|
jack_controller_settings_write_string(fd, " </", ctx_ptr->call) &&
|
|
jack_controller_settings_write_string(fd, ctx_ptr->str, ctx_ptr->call) &&
|
|
jack_controller_settings_write_string(fd, ">\n", ctx_ptr->call);
|
|
}
|
|
|
|
#undef fd
|
|
#undef ctx_ptr
|
|
|
|
bool
|
|
jack_controller_settings_save(
|
|
struct jack_controller * controller_ptr,
|
|
void *dbus_call_context_ptr)
|
|
{
|
|
char *filename;
|
|
size_t conf_len;
|
|
int fd;
|
|
bool ret;
|
|
time_t timestamp;
|
|
char timestamp_str[26];
|
|
struct save_context context;
|
|
const char * modules[] = {"driver", "internal", NULL};
|
|
char buffer[100];
|
|
unsigned int i;
|
|
|
|
time(×tamp);
|
|
ctime_r(×tamp, timestamp_str);
|
|
timestamp_str[24] = 0;
|
|
|
|
ret = false;
|
|
|
|
conf_len = strlen(JACKDBUS_CONF);
|
|
|
|
filename = malloc(g_jackdbus_config_dir_len + conf_len + 1);
|
|
if (filename == NULL)
|
|
{
|
|
jack_error("Out of memory.");
|
|
goto exit;
|
|
}
|
|
|
|
memcpy(filename, g_jackdbus_config_dir, g_jackdbus_config_dir_len);
|
|
memcpy(filename + g_jackdbus_config_dir_len, JACKDBUS_CONF, conf_len);
|
|
filename[g_jackdbus_config_dir_len + conf_len] = 0;
|
|
|
|
jack_info("Saving settings to \"%s\" ...", filename);
|
|
|
|
fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
|
if (fd == -1)
|
|
{
|
|
jack_error("open() failed to open conf filename. error is %d (%s)", errno, strerror(errno));
|
|
goto exit_free_filename;
|
|
}
|
|
|
|
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))
|
|
{
|
|
goto exit_close;
|
|
}
|
|
|
|
if (!jack_controller_settings_write_string(fd, "<!--\n", dbus_call_context_ptr))
|
|
{
|
|
goto exit_close;
|
|
}
|
|
|
|
if (!jack_controller_settings_write_string(fd, JACK_CONF_HEADER_TEXT, dbus_call_context_ptr))
|
|
{
|
|
goto exit_close;
|
|
}
|
|
|
|
if (!jack_controller_settings_write_string(fd, "-->\n", dbus_call_context_ptr))
|
|
{
|
|
goto exit_close;
|
|
}
|
|
|
|
if (!jack_controller_settings_write_string(fd, "<!-- ", dbus_call_context_ptr))
|
|
{
|
|
goto exit_close;
|
|
}
|
|
|
|
if (!jack_controller_settings_write_string(fd, timestamp_str, dbus_call_context_ptr))
|
|
{
|
|
goto exit_close;
|
|
}
|
|
|
|
if (!jack_controller_settings_write_string(fd, " -->\n", dbus_call_context_ptr))
|
|
{
|
|
goto exit_close;
|
|
}
|
|
|
|
if (!jack_controller_settings_write_string(fd, "<jack>\n", dbus_call_context_ptr))
|
|
{
|
|
goto exit_close;
|
|
}
|
|
|
|
/* engine */
|
|
|
|
if (!jack_controller_settings_write_string(fd, " <engine>\n", dbus_call_context_ptr))
|
|
{
|
|
goto exit_close;
|
|
}
|
|
|
|
context.indent = " ";
|
|
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;
|
|
}
|
|
|
|
if (!jack_controller_settings_write_string(fd, " </engine>\n", dbus_call_context_ptr))
|
|
{
|
|
goto exit_close;
|
|
}
|
|
|
|
for (i = 0; modules[i] != NULL; i++)
|
|
{
|
|
if (!jack_controller_settings_write_string(fd, " <", dbus_call_context_ptr))
|
|
{
|
|
goto exit_close;
|
|
}
|
|
|
|
if (!jack_controller_settings_write_string(fd, modules[i], dbus_call_context_ptr))
|
|
{
|
|
goto exit_close;
|
|
}
|
|
|
|
if (!jack_controller_settings_write_string(fd, "s>\n", dbus_call_context_ptr))
|
|
{
|
|
goto exit_close;
|
|
}
|
|
|
|
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_params_iterate_container(controller_ptr->params, context.address, serialize_modules, &context))
|
|
{
|
|
goto exit_close;
|
|
}
|
|
|
|
if (!jack_controller_settings_write_string(fd, " </", dbus_call_context_ptr))
|
|
{
|
|
goto exit_close;
|
|
}
|
|
|
|
if (!jack_controller_settings_write_string(fd, modules[i], dbus_call_context_ptr))
|
|
{
|
|
goto exit_close;
|
|
}
|
|
|
|
if (!jack_controller_settings_write_string(fd, "s>\n", dbus_call_context_ptr))
|
|
{
|
|
goto exit_close;
|
|
}
|
|
}
|
|
|
|
if (!jack_controller_settings_write_string(fd, "</jack>\n", dbus_call_context_ptr))
|
|
{
|
|
goto exit_close;
|
|
}
|
|
|
|
ret = true;
|
|
|
|
exit_close:
|
|
close(fd);
|
|
|
|
exit_free_filename:
|
|
free(filename);
|
|
|
|
exit:
|
|
return ret;
|
|
}
|
|
|
|
void
|
|
jack_controller_settings_save_auto(
|
|
struct jack_controller * controller_ptr)
|
|
{
|
|
jack_controller_settings_save(controller_ptr, NULL);
|
|
}
|