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);
88 struct xmms_config_St {
91 const gchar *filename;
108 struct xmms_config_property_St {
128 #define XMMS_CONFIG_VERSION 2 160 "Trying to get non-existent property");
177 g_return_val_if_fail (global_config, NULL);
179 g_mutex_lock (global_config->mutex);
180 prop = g_tree_lookup (global_config->properties, path);
181 g_mutex_unlock (global_config->mutex);
194 g_return_val_if_fail (prop, NULL);
209 g_return_if_fail (prop);
210 g_return_if_fail (data);
213 if (prop->value && !strcmp (prop->value, data))
216 g_free (prop->value);
217 prop->value = g_strdup (data);
222 dict = g_tree_new_full (compare_key, NULL,
224 g_tree_insert (dict, (gchar *) prop->name,
232 g_tree_destroy (dict);
248 g_return_val_if_fail (prop, NULL);
260 g_return_val_if_fail (prop, 0);
262 return atoi (prop->value);
275 g_return_val_if_fail (prop, 0.0);
277 return atof (prop->value);
294 g_return_if_fail (prop);
314 g_return_if_fail (prop);
338 const gchar *default_value,
345 g_mutex_lock (global_config->mutex);
347 prop = g_tree_lookup (global_config->properties, path);
349 prop = xmms_config_property_new (g_strdup (path));
352 g_tree_replace (global_config->properties,
353 (gchar *) prop->name, prop);
360 g_mutex_unlock (global_config->mutex);
379 get_current_state (
const gchar *name)
391 for (ptr = lookup; ptr && ptr->name; ptr++) {
392 if (!strcmp (ptr->name, name)) {
409 lookup_attribute (
const gchar **names,
const gchar **values,
412 const gchar **n, **v;
414 for (n = names, v = values; *n && *v; n++, v++) {
415 if (!strcmp ((gchar *) *n, needle)) {
434 xmms_config_parse_start (GMarkupParseContext *ctx,
436 const gchar **attr_name,
437 const gchar **attr_data,
445 state = get_current_state (name);
446 g_queue_push_head (config->states, GINT_TO_POINTER (state));
450 *error = g_error_new (G_MARKUP_ERROR,
451 G_MARKUP_ERROR_UNKNOWN_ELEMENT,
452 "Unknown element '%s'", name);
456 attr = lookup_attribute (attr_name, attr_data,
"version");
458 if (strcmp (attr,
"0.02") == 0) {
461 config->version = atoi (attr);
469 attr = lookup_attribute (attr_name, attr_data,
"name");
471 *error = g_error_new (G_MARKUP_ERROR,
472 G_MARKUP_ERROR_INVALID_CONTENT,
473 "Attribute 'name' missing");
479 g_queue_push_head (config->sections, g_strdup (attr));
483 g_free (config->value_name);
484 config->value_name = g_strdup (attr);
501 xmms_config_parse_end (GMarkupParseContext *ctx,
509 state = GPOINTER_TO_INT (g_queue_pop_head (config->states));
513 g_free (g_queue_pop_head (config->sections));
517 g_free (config->value_name);
518 config->value_name = NULL;
537 xmms_config_parse_text (GMarkupParseContext *ctx,
548 gsize siz =
sizeof (key);
550 state = GPOINTER_TO_INT (g_queue_peek_head (config->states));
556 for (l = config->sections->tail; l; l = l->prev) {
557 g_strlcat (key, l->data, siz);
558 g_strlcat (key,
".", siz);
561 g_strlcat (key, config->value_name, siz);
563 prop = xmms_config_property_new (g_strdup (key));
566 g_tree_replace (config->properties, (gchar *) prop->name, prop);
578 const gchar *key,
const gchar *value,
588 "Trying to set non-existent config property");
619 ret = g_tree_new_full (compare_key, NULL,
622 g_mutex_lock (conf->mutex);
623 g_tree_foreach (conf->properties,
624 (GTraverseFunc) xmms_config_foreach_dict,
626 g_mutex_unlock (conf->mutex);
639 xmms_config_client_get_value (
xmms_config_t *conf,
const gchar *key,
654 g_mutex_free (config->mutex);
656 g_tree_destroy (config->properties);
663 compare_key (gconstpointer a, gconstpointer b, gpointer user_data)
665 return strcmp ((gchar *) a, (gchar *) b);
671 return g_tree_new_full (compare_key, NULL, g_free,
682 g_tree_destroy (config->properties);
683 config->properties = create_tree ();
687 g_free (config->value_name);
688 config->value_name = NULL;
700 GMarkupParseContext *ctx;
703 gboolean parserr = FALSE, eof = FALSE;
706 config->mutex = g_mutex_new ();
707 config->filename = filename;
709 config->properties = create_tree ();
712 global_config = config;
718 memset (&pars, 0,
sizeof (pars));
720 pars.start_element = xmms_config_parse_start;
721 pars.end_element = xmms_config_parse_end;
722 pars.text = xmms_config_parse_text;
724 if (g_file_test (filename, G_FILE_TEST_EXISTS)) {
725 fd = open (filename, O_RDONLY);
729 config->is_parsing = TRUE;
730 config->states = g_queue_new ();
731 config->sections = g_queue_new ();
732 ctx = g_markup_parse_context_new (&pars, 0, config, NULL);
734 while ((!eof) && (!parserr)) {
735 GError *error = NULL;
738 ret = read (fd, buffer, 1024);
740 g_markup_parse_context_end_parse (ctx, &error);
744 g_error_free (error);
751 g_markup_parse_context_parse (ctx, buffer, ret, &error);
755 g_error_free (error);
763 clear_config (config);
769 g_markup_parse_context_free (ctx);
771 while (!g_queue_is_empty (config->sections)) {
772 g_free (g_queue_pop_head (config->sections));
775 g_queue_free (config->states);
776 g_queue_free (config->sections);
778 config->is_parsing = FALSE;
780 xmms_log_info (
"No configfile specified, using default values.");
784 xmms_log_info (
"The config file could not be parsed, reverting to default configuration..");
785 clear_config (config);
817 gchar *prop_name, section[256];
818 gchar *dot = NULL, *current_last_dot, *start = current_key;
820 prop_name = strrchr (current_key,
'.');
827 if (data->prev_key) {
828 gchar *c = current_key, *o = data->prev_key;
834 while (*c && *o && *c == *o) {
857 data->prev_key = NULL;
861 data->indent[--data->indent_level] =
'\0';
863 fprintf (data->fp,
"%s</section>\n", data->indent);
868 dot = strchr (start,
'.');
869 current_last_dot = start - 1;
872 strncpy (section, current_last_dot + 1, dot - current_last_dot + 1);
873 section[dot - current_last_dot - 1] = 0;
875 fprintf (data->fp,
"%s<section name=\"%s\">\n",
876 data->indent, section);
879 g_assert (data->indent_level < 127);
880 data->indent[data->indent_level] =
'\t';
881 data->indent[++data->indent_level] =
'\0';
883 current_last_dot = dot;
884 dot = strchr (dot + 1,
'.');
887 data->prev_key = current_key;
889 fprintf (data->fp,
"%s<property name=\"%s\">%s</property>\n",
890 data->indent, prop_name + 1,
907 g_return_val_if_fail (global_config, FALSE);
910 if (global_config->is_parsing)
913 if (!(fp = fopen (global_config->filename,
"w"))) {
915 global_config->filename);
919 fprintf (fp,
"<?xml version=\"1.0\"?>\n<xmms version=\"%i\">\n",
924 data.prev_key = NULL;
926 strcpy (data.indent,
"\t");
927 data.indent_level = 1;
929 g_tree_foreach (global_config->properties,
930 (GTraverseFunc) dump_tree, &data);
936 while (data.indent_level > 1) {
938 data.indent[--data.indent_level] =
'\0';
940 fprintf (fp,
"%s</section>\n", data.indent);
943 fprintf (fp,
"</xmms>\n");
965 g_free (prop->value);
973 xmms_config_property_new (
const gchar *name)
994 const gchar *def_value,
998 tmp = g_strdup_printf (
"clients.%s", name);
#define XMMS_CMD_FUNC(cmdid)
XMMS_CMD_DEFINE(setvalue, xmms_config_client_set_value, xmms_config_t *, NONE, STRING, STRING)
#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.
void xmms_object_cmd_add(xmms_object_t *object, guint cmdid, const xmms_object_cmd_desc_t *desc)
Add a command that could be called from the client API to a object.
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.
void xmms_ipc_broadcast_register(xmms_object_t *object, xmms_ipc_signals_t signalid)
Register a broadcast signal.
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.
void xmms_ipc_object_unregister(xmms_ipc_objects_t objectid)
Remove a object from the IPC core.
#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_ipc_broadcast_unregister(xmms_ipc_signals_t signalid)
Unregister a broadcast signal.
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_ipc_object_register(xmms_ipc_objects_t objectid, xmms_object_t *object)
Register a object to the IPC core.
void(* xmms_object_handler_t)(xmms_object_t *object, xmmsv_t *data, gpointer userdata)