25 #include <sys/types.h> 51 typedef struct dump_tree_data_St {
64 static gchar *xmms_config_client_register_value (
xmms_config_t *config,
const gchar *name,
const gchar *def_value,
xmms_error_t *error);
65 static gint compare_key (gconstpointer a, gconstpointer b, gpointer user_data);
68 #include "config_ipc.c" 85 struct xmms_config_St {
88 const gchar *filename;
105 struct xmms_config_property_St {
125 #define XMMS_CONFIG_VERSION 2 157 "Trying to get non-existent property");
174 g_return_val_if_fail (global_config, NULL);
176 g_mutex_lock (global_config->mutex);
177 prop = g_tree_lookup (global_config->properties, path);
178 g_mutex_unlock (global_config->mutex);
191 g_return_val_if_fail (prop, NULL);
206 g_return_if_fail (prop);
207 g_return_if_fail (data);
210 if (prop->value && !strcmp (prop->value, data))
213 g_free (prop->value);
214 prop->value = g_strdup (data);
219 dict = g_tree_new_full (compare_key, NULL,
221 g_tree_insert (dict, (gchar *) prop->name,
229 g_tree_destroy (dict);
245 g_return_val_if_fail (prop, NULL);
257 g_return_val_if_fail (prop, 0);
259 return atoi (prop->value);
272 g_return_val_if_fail (prop, 0.0);
274 return atof (prop->value);
291 g_return_if_fail (prop);
311 g_return_if_fail (prop);
335 const gchar *default_value,
342 g_mutex_lock (global_config->mutex);
344 prop = g_tree_lookup (global_config->properties, path);
346 prop = xmms_config_property_new (g_strdup (path));
349 g_tree_replace (global_config->properties,
350 (gchar *) prop->name, prop);
357 g_mutex_unlock (global_config->mutex);
376 get_current_state (
const gchar *name)
388 for (ptr = lookup; ptr && ptr->name; ptr++) {
389 if (!strcmp (ptr->name, name)) {
406 lookup_attribute (
const gchar **names,
const gchar **values,
409 const gchar **n, **v;
411 for (n = names, v = values; *n && *v; n++, v++) {
412 if (!strcmp ((gchar *) *n, needle)) {
431 xmms_config_parse_start (GMarkupParseContext *ctx,
433 const gchar **attr_name,
434 const gchar **attr_data,
442 state = get_current_state (name);
443 g_queue_push_head (config->states, GINT_TO_POINTER (state));
447 *error = g_error_new (G_MARKUP_ERROR,
448 G_MARKUP_ERROR_UNKNOWN_ELEMENT,
449 "Unknown element '%s'", name);
453 attr = lookup_attribute (attr_name, attr_data,
"version");
455 if (strcmp (attr,
"0.02") == 0) {
458 config->version = atoi (attr);
466 attr = lookup_attribute (attr_name, attr_data,
"name");
468 *error = g_error_new (G_MARKUP_ERROR,
469 G_MARKUP_ERROR_INVALID_CONTENT,
470 "Attribute 'name' missing");
476 g_queue_push_head (config->sections, g_strdup (attr));
480 g_free (config->value_name);
481 config->value_name = g_strdup (attr);
498 xmms_config_parse_end (GMarkupParseContext *ctx,
506 state = GPOINTER_TO_INT (g_queue_pop_head (config->states));
510 g_free (g_queue_pop_head (config->sections));
514 g_free (config->value_name);
515 config->value_name = NULL;
534 xmms_config_parse_text (GMarkupParseContext *ctx,
545 gsize siz =
sizeof (key);
547 state = GPOINTER_TO_INT (g_queue_peek_head (config->states));
553 for (l = config->sections->tail; l; l = l->prev) {
554 g_strlcat (key, l->data, siz);
555 g_strlcat (key,
".", siz);
558 g_strlcat (key, config->value_name, siz);
560 prop = xmms_config_property_new (g_strdup (key));
563 g_tree_replace (config->properties, (gchar *) prop->name, prop);
575 const gchar *key,
const gchar *value,
585 "Trying to set non-existent config property");
616 ret = g_tree_new_full (compare_key, NULL,
619 g_mutex_lock (conf->mutex);
620 g_tree_foreach (conf->properties,
621 (GTraverseFunc) xmms_config_foreach_dict,
623 g_mutex_unlock (conf->mutex);
636 xmms_config_client_get_value (
xmms_config_t *conf,
const gchar *key,
651 g_mutex_free (config->mutex);
653 g_tree_destroy (config->properties);
655 xmms_config_unregister_ipc_commands ();
659 compare_key (gconstpointer a, gconstpointer b, gpointer user_data)
661 return strcmp ((gchar *) a, (gchar *) b);
667 return g_tree_new_full (compare_key, NULL, g_free,
678 g_tree_destroy (config->properties);
679 config->properties = create_tree ();
683 g_free (config->value_name);
684 config->value_name = NULL;
696 GMarkupParseContext *ctx;
699 gboolean parserr = FALSE, eof = FALSE;
702 config->mutex = g_mutex_new ();
703 config->filename = filename;
705 config->properties = create_tree ();
708 global_config = config;
710 xmms_config_register_ipc_commands (
XMMS_OBJECT (config));
712 memset (&pars, 0,
sizeof (pars));
714 pars.start_element = xmms_config_parse_start;
715 pars.end_element = xmms_config_parse_end;
716 pars.text = xmms_config_parse_text;
718 if (g_file_test (filename, G_FILE_TEST_EXISTS)) {
719 fd = open (filename, O_RDONLY);
723 config->is_parsing = TRUE;
724 config->states = g_queue_new ();
725 config->sections = g_queue_new ();
726 ctx = g_markup_parse_context_new (&pars, 0, config, NULL);
728 while ((!eof) && (!parserr)) {
729 GError *error = NULL;
732 ret = read (fd, buffer, 1024);
734 g_markup_parse_context_end_parse (ctx, &error);
738 g_error_free (error);
745 g_markup_parse_context_parse (ctx, buffer, ret, &error);
749 g_error_free (error);
757 clear_config (config);
763 g_markup_parse_context_free (ctx);
765 while (!g_queue_is_empty (config->sections)) {
766 g_free (g_queue_pop_head (config->sections));
769 g_queue_free (config->states);
770 g_queue_free (config->sections);
772 config->is_parsing = FALSE;
774 xmms_log_info (
"No configfile specified, using default values.");
778 xmms_log_info (
"The config file could not be parsed, reverting to default configuration..");
779 clear_config (config);
798 gchar *prop_name, section[256];
799 gchar *dot = NULL, *current_last_dot, *start = current_key;
801 prop_name = strrchr (current_key,
'.');
808 if (data->prev_key) {
809 gchar *c = current_key, *o = data->prev_key;
815 while (*c && *o && *c == *o) {
838 data->prev_key = NULL;
842 data->indent[--data->indent_level] =
'\0';
844 fprintf (data->fp,
"%s</section>\n", data->indent);
849 dot = strchr (start,
'.');
850 current_last_dot = start - 1;
853 strncpy (section, current_last_dot + 1, dot - current_last_dot + 1);
854 section[dot - current_last_dot - 1] = 0;
856 fprintf (data->fp,
"%s<section name=\"%s\">\n",
857 data->indent, section);
860 g_assert (data->indent_level < 127);
861 data->indent[data->indent_level] =
'\t';
862 data->indent[++data->indent_level] =
'\0';
864 current_last_dot = dot;
865 dot = strchr (dot + 1,
'.');
868 data->prev_key = current_key;
870 fprintf (data->fp,
"%s<property name=\"%s\">%s</property>\n",
871 data->indent, prop_name + 1,
888 g_return_val_if_fail (global_config, FALSE);
891 if (global_config->is_parsing)
894 if (!(fp = fopen (global_config->filename,
"w"))) {
896 global_config->filename);
900 fprintf (fp,
"<?xml version=\"1.0\"?>\n<xmms version=\"%i\">\n",
905 data.prev_key = NULL;
907 strcpy (data.indent,
"\t");
908 data.indent_level = 1;
910 g_tree_foreach (global_config->properties,
911 (GTraverseFunc) dump_tree, &data);
917 while (data.indent_level > 1) {
919 data.indent[--data.indent_level] =
'\0';
921 fprintf (fp,
"%s</section>\n", data.indent);
924 fprintf (fp,
"</xmms>\n");
946 g_free (prop->value);
954 xmms_config_property_new (
const gchar *name)
975 const gchar *def_value,
979 tmp = g_strdup_printf (
"clients.%s", name);
#define XMMS_CONFIG_VERSION
Config file version.
void xmmsv_unref(xmmsv_t *val)
Decreases the references for the xmmsv_t When the number of references reaches 0 it will be freed...
#define xmms_object_unref(obj)
gfloat xmms_config_property_get_float(const xmms_config_property_t *prop)
Return the value of a config property as a float.
void xmms_config_property_callback_remove(xmms_config_property_t *prop, xmms_object_handler_t cb, gpointer userdata)
Remove a callback from a config property.
const gchar * xmms_config_property_get_name(const xmms_config_property_t *prop)
Get the name of a config property.
xmms_config_property_t * xmms_config_lookup(const gchar *path)
Look up a config key from the global config.
xmmsv_t * xmmsv_new_string(const char *s)
Allocates a new string xmmsv_t.
xmms_configparser_state_t
gboolean xmms_config_save(void)
void xmms_config_init(const gchar *filename)
gint xmms_config_property_get_int(const xmms_config_property_t *prop)
Return the value of a config property as an int.
struct dump_tree_data_St dump_tree_data_t
void xmms_config_property_set_data(xmms_config_property_t *prop, const gchar *data)
Set the data of the config property to a new value.
void xmms_object_emit(xmms_object_t *object, guint32 signalid, xmmsv_t *data)
Emit a signal and thus call all the handlers that are connected.
#define xmms_log_error(fmt,...)
void xmms_config_property_callback_set(xmms_config_property_t *prop, xmms_object_handler_t cb, gpointer userdata)
Set a callback function for a config property.
void xmms_object_emit_f(xmms_object_t *object, guint32 signalid, xmmsv_type_t type,...)
Emits a signal on the current object.
typedefG_BEGIN_DECLS struct xmms_config_St xmms_config_t
void __int_xmms_object_unref(xmms_object_t *object)
const gchar * xmms_config_property_get_string(const xmms_config_property_t *prop)
Return the value of a config property as a string.
#define xmms_log_info(fmt,...)
void xmms_object_connect(xmms_object_t *object, guint32 signalid, xmms_object_handler_t handler, gpointer userdata)
Connect to a signal that is emitted by this object.
void xmms_object_disconnect(xmms_object_t *object, guint32 signalid, xmms_object_handler_t handler, gpointer userdata)
Disconnect from a signal.
const gchar * xmms_config_property_lookup_get_string(xmms_config_t *conf, const gchar *key, xmms_error_t *err)
Config functions.
void xmms_config_shutdown()
#define xmms_object_new(objtype, destroyfunc)
G_BEGIN_DECLS struct xmms_error_St xmms_error_t
xmms_config_property_t * xmms_config_property_register(const gchar *path, const gchar *default_value, xmms_object_handler_t cb, gpointer userdata)
Register a new config property.
struct xmms_config_property_St xmms_config_property_t
void(* xmms_object_handler_t)(xmms_object_t *object, xmmsv_t *data, gpointer userdata)