XMMS2
config.c
Go to the documentation of this file.
1 /* XMMS2 - X Music Multiplexer System
2  * Copyright (C) 2003-2011 XMMS2 Team
3  *
4  * PLUGINS ARE NOT CONSIDERED TO BE DERIVED WORK !!!
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  */
17 
18 #include <glib.h>
19 
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <fcntl.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 
28 #include "xmmsc/xmmsc_idnumbers.h"
29 #include "xmmspriv/xmms_config.h"
30 #include "xmmspriv/xmms_utils.h"
31 #include "xmms/xmms_ipc.h"
32 #include "xmms/xmms_log.h"
33 
34 /*
35 #include "xmms/util.h"
36 #include "xmms/xmms.h"
37 #include "xmms/object.h"
38 #include "xmms/signal_xmms.h"
39 #include "xmms/plugin.h"
40 #include "xmms/ipc.h"
41 */
42 
43 /** @internal */
44 typedef enum {
50 
51 typedef struct dump_tree_data_St {
52  FILE *fp;
54 
55  gchar indent[128];
56  guint indent_level;
57 
58  gchar *prev_key;
60 
61 static GTree *xmms_config_client_list_values (xmms_config_t *conf, xmms_error_t *err);
62 static xmms_config_property_t *xmms_config_property_new (const gchar *name);
63 static gchar *xmms_config_client_get_value (xmms_config_t *conf, const gchar *key, xmms_error_t *err);
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);
66 static void xmms_config_client_set_value (xmms_config_t *conf, const gchar *key, const gchar *value, xmms_error_t *err);
67 
68 #include "config_ipc.c"
69 
70 /**
71  * @defgroup Config Config
72  * @brief Controls configuration for the server.
73  *
74  * The configuration is saved to, and loaded from an XML file. It's split into
75  * plugin, client and core parts. This documents the configuration for parts
76  * inside the server. For plugin config see each server object's documentation.
77  *
78  * @ingroup XMMSServer
79  * @{
80  */
81 
82 /**
83  * Global parsed config
84  */
85 struct xmms_config_St {
86  xmms_object_t obj;
87 
88  const gchar *filename;
89  GTree *properties;
90 
91  /* Lock on globals are great! */
92  GMutex *mutex;
93 
94  /* parsing */
95  gboolean is_parsing;
96  GQueue *states;
97  GQueue *sections;
98  gchar *value_name;
99  guint version;
100 };
101 
102 /**
103  * A config property in the configuration file
104  */
105 struct xmms_config_property_St {
106  xmms_object_t obj;
107 
108  /** Name of the config directive */
109  const gchar *name;
110  /** The data */
111  gchar *value;
112 };
113 
114 /**
115  * Global config
116  * Since there can only be one configuration per server
117  * we can have the convenience of having it as a global variable.
118  */
119 
120 static xmms_config_t *global_config;
121 
122 /**
123  * Config file version
124  */
125 #define XMMS_CONFIG_VERSION 2
126 
127 /**
128  * @}
129  * @addtogroup Config
130  * @{
131  */
132 
133 /**
134  * Config functions
135  */
136 
137 /**
138  * Lookup config key and return its associated value as a string.
139  * This is a convenient function to make it easier to get a configuration value
140  * rather than having to call #xmms_config_property_get_string separately.
141  *
142  * @param conf Global config
143  * @param key Configuration property to lookup
144  * @param err if error occurs this will be filled in
145  *
146  * @return A string with the value. If the value is an int it will return NULL
147  */
148 const gchar *
150  xmms_error_t *err)
151 {
153 
154  prop = xmms_config_lookup (key);
155  if (!prop) {
156  xmms_error_set (err, XMMS_ERROR_NOENT,
157  "Trying to get non-existent property");
158  return NULL;
159  }
160 
161  return xmms_config_property_get_string (prop);
162 }
163 
164 /**
165  * Look up a config key from the global config
166  * @param path A configuration path. Could be core.myconfig or
167  * effect.foo.myconfig
168  * @return An #xmms_config_property_t
169  */
171 xmms_config_lookup (const gchar *path)
172 {
174  g_return_val_if_fail (global_config, NULL);
175 
176  g_mutex_lock (global_config->mutex);
177  prop = g_tree_lookup (global_config->properties, path);
178  g_mutex_unlock (global_config->mutex);
179 
180  return prop;
181 }
182 
183 /**
184  * Get the name of a config property.
185  * @param prop The config property
186  * @return Name of config property
187  */
188 const gchar *
190 {
191  g_return_val_if_fail (prop, NULL);
192 
193  return prop->name;
194 }
195 
196 /**
197  * Set the data of the config property to a new value
198  * @param prop The config property
199  * @param data The value to set
200  */
201 void
203 {
204  GTree *dict;
205 
206  g_return_if_fail (prop);
207  g_return_if_fail (data);
208 
209  /* check whether the value changed at all */
210  if (prop->value && !strcmp (prop->value, data))
211  return;
212 
213  g_free (prop->value);
214  prop->value = g_strdup (data);
217  (gpointer) data);
218 
219  dict = g_tree_new_full (compare_key, NULL,
220  NULL, (GDestroyNotify) xmmsv_unref);
221  g_tree_insert (dict, (gchar *) prop->name,
222  xmmsv_new_string (prop->value));
223 
224  xmms_object_emit_f (XMMS_OBJECT (global_config),
227  dict);
228 
229  g_tree_destroy (dict);
230 
231  /* save the database to disk, so we don't lose any data
232  * if the daemon crashes
233  */
234  xmms_config_save ();
235 }
236 
237 /**
238  * Return the value of a config property as a string
239  * @param prop The config property
240  * @return value as string
241  */
242 const gchar *
244 {
245  g_return_val_if_fail (prop, NULL);
246  return prop->value;
247 }
248 
249 /**
250  * Return the value of a config property as an int
251  * @param prop The config property
252  * @return value as int
253  */
254 gint
256 {
257  g_return_val_if_fail (prop, 0);
258  if (prop->value)
259  return atoi (prop->value);
260 
261  return 0;
262 }
263 
264 /**
265  * Return the value of a config property as a float
266  * @param prop The config property
267  * @return value as float
268  */
269 gfloat
271 {
272  g_return_val_if_fail (prop, 0.0);
273  if (prop->value)
274  return atof (prop->value);
275 
276  return 0.0;
277 }
278 
279 /**
280  * Set a callback function for a config property.
281  * This will be called each time the property's value changes.
282  * @param prop The config property
283  * @param cb The callback to set
284  * @param userdata Data to pass on to the callback
285  */
286 void
289  gpointer userdata)
290 {
291  g_return_if_fail (prop);
292 
293  if (!cb)
294  return;
295 
298  (xmms_object_handler_t) cb, userdata);
299 }
300 
301 /**
302  * Remove a callback from a config property
303  * @param prop The config property
304  * @param cb The callback to remove
305  */
306 void
309  gpointer userdata)
310 {
311  g_return_if_fail (prop);
312 
313  if (!cb)
314  return;
315 
318 }
319 
320 /**
321  * Register a new config property. This should be called from the init code
322  * as XMMS2 won't allow set/get on properties that haven't been registered.
323  *
324  * @param path The path in the config tree.
325  * @param default_value If the value was not found in the configfile, what
326  * should we use?
327  * @param cb A callback function that will be called if the value is changed by
328  * the client. Can be set to NULL.
329  * @param userdata Data to pass to the callback function.
330  * @return A newly allocated #xmms_config_property_t for the registered
331  * property.
332  */
334 xmms_config_property_register (const gchar *path,
335  const gchar *default_value,
337  gpointer userdata)
338 {
339 
341 
342  g_mutex_lock (global_config->mutex);
343 
344  prop = g_tree_lookup (global_config->properties, path);
345  if (!prop) {
346  prop = xmms_config_property_new (g_strdup (path));
347 
348  xmms_config_property_set_data (prop, (gchar *) default_value);
349  g_tree_replace (global_config->properties,
350  (gchar *) prop->name, prop);
351  }
352 
353  if (cb) {
354  xmms_config_property_callback_set (prop, cb, userdata);
355  }
356 
357  g_mutex_unlock (global_config->mutex);
358 
359  return prop;
360 }
361 
362 /**
363  * @}
364  *
365  * @if internal
366  * @addtogroup Config
367  * @{
368  */
369 
370 /**
371  * @internal Get the current parser state for the given element name
372  * @param[in] name Element name to match to a state
373  * @return Parser state matching element name
374  */
376 get_current_state (const gchar *name)
377 {
378  static struct {
379  const gchar *name;
381  } *ptr, lookup[] = {
382  {"xmms", XMMS_CONFIG_STATE_START},
383  {"section", XMMS_CONFIG_STATE_SECTION},
384  {"property", XMMS_CONFIG_STATE_PROPERTY},
386  };
387 
388  for (ptr = lookup; ptr && ptr->name; ptr++) {
389  if (!strcmp (ptr->name, name)) {
390  return ptr->state;
391  }
392  }
393 
395 }
396 
397 /**
398  * @internal Look for the value associated with an attribute name, given lists
399  * of attribute names and attribute values.
400  * @param[in] names List of attribute names
401  * @param[in] values List of attribute values matching up to names
402  * @param[in] needle Attribute name to look for
403  * @return The attribute value, or NULL if not found
404  */
405 static const gchar *
406 lookup_attribute (const gchar **names, const gchar **values,
407  const gchar *needle)
408 {
409  const gchar **n, **v;
410 
411  for (n = names, v = values; *n && *v; n++, v++) {
412  if (!strcmp ((gchar *) *n, needle)) {
413  return *v;
414  }
415  }
416 
417  return NULL;
418 }
419 
420 /**
421  * @internal Parse start tag in config file. This function is called whenever
422  * a start tag is encountered by the GMarkupParser from #xmms_config_init
423  * @param ctx The parser context.
424  * @param name The name of the element encountered
425  * @param attr_name List of attribute names in tag
426  * @param attr_data List of attribute data in tag
427  * @param userdata User data - In this case, the global config
428  * @param error GError to be filled in if an error is encountered
429  */
430 static void
431 xmms_config_parse_start (GMarkupParseContext *ctx,
432  const gchar *name,
433  const gchar **attr_name,
434  const gchar **attr_data,
435  gpointer userdata,
436  GError **error)
437 {
438  xmms_config_t *config = userdata;
440  const gchar *attr;
441 
442  state = get_current_state (name);
443  g_queue_push_head (config->states, GINT_TO_POINTER (state));
444 
445  switch (state) {
447  *error = g_error_new (G_MARKUP_ERROR,
448  G_MARKUP_ERROR_UNKNOWN_ELEMENT,
449  "Unknown element '%s'", name);
450  return;
452  /* check config version here */
453  attr = lookup_attribute (attr_name, attr_data, "version");
454  if (attr) {
455  if (strcmp (attr, "0.02") == 0) {
456  config->version = 2;
457  } else {
458  config->version = atoi (attr);
459  }
460  }
461  return;
462  default:
463  break;
464  }
465 
466  attr = lookup_attribute (attr_name, attr_data, "name");
467  if (!attr) {
468  *error = g_error_new (G_MARKUP_ERROR,
469  G_MARKUP_ERROR_INVALID_CONTENT,
470  "Attribute 'name' missing");
471  return;
472  }
473 
474  switch (state) {
476  g_queue_push_head (config->sections, g_strdup (attr));
477 
478  break;
480  g_free (config->value_name);
481  config->value_name = g_strdup (attr);
482 
483  break;
484  default:
485  break;
486  }
487 }
488 
489 /**
490  * @internal Parse end tag in config file. This function is called whenever
491  * an end tag is encountered by the GMarkupParser from #xmms_config_init
492  * @param ctx The parser context.
493  * @param name The name of the element encountered
494  * @param userdata User data - In this case, the global config
495  * @param error GError to be filled in if an error is encountered
496  */
497 static void
498 xmms_config_parse_end (GMarkupParseContext *ctx,
499  const gchar *name,
500  gpointer userdata,
501  GError **error)
502 {
503  xmms_config_t *config = userdata;
505 
506  state = GPOINTER_TO_INT (g_queue_pop_head (config->states));
507 
508  switch (state) {
510  g_free (g_queue_pop_head (config->sections));
511 
512  break;
514  g_free (config->value_name);
515  config->value_name = NULL;
516 
517  break;
518  default:
519  break;
520  }
521 }
522 
523 /**
524  * @internal Parse text in config file. This function is called whenever
525  * text (anything between start and end tags) is encountered by the
526  * GMarkupParser from #xmms_config_init
527  * @param ctx The parser context.
528  * @param text The text
529  * @param text_len Length of the text
530  * @param userdata User data - In this case, the global config
531  * @param error GError to be filled in if an error is encountered
532  */
533 static void
534 xmms_config_parse_text (GMarkupParseContext *ctx,
535  const gchar *text,
536  gsize text_len,
537  gpointer userdata,
538  GError **error)
539 {
540  xmms_config_t *config = userdata;
543  GList *l;
544  gchar key[256] = "";
545  gsize siz = sizeof (key);
546 
547  state = GPOINTER_TO_INT (g_queue_peek_head (config->states));
548 
549  if (state != XMMS_CONFIG_STATE_PROPERTY)
550  return;
551 
552  /* assemble the config key, based on the traversed sections */
553  for (l = config->sections->tail; l; l = l->prev) {
554  g_strlcat (key, l->data, siz);
555  g_strlcat (key, ".", siz);
556  }
557 
558  g_strlcat (key, config->value_name, siz);
559 
560  prop = xmms_config_property_new (g_strdup (key));
561  xmms_config_property_set_data (prop, (gchar *) text);
562 
563  g_tree_replace (config->properties, (gchar *) prop->name, prop);
564 }
565 
566 /**
567  * @internal Set a key to a new value
568  * @param conf The config
569  * @param key The key to look for
570  * @param value The value to set the key to
571  * @param err To be filled in if an error occurs
572  */
573 static void
574 xmms_config_client_set_value (xmms_config_t *conf,
575  const gchar *key, const gchar *value,
576  xmms_error_t *err)
577 {
579 
580  prop = xmms_config_lookup (key);
581  if (prop) {
582  xmms_config_property_set_data (prop, value);
583  } else {
584  xmms_error_set (err, XMMS_ERROR_NOENT,
585  "Trying to set non-existent config property");
586  }
587 
588 }
589 
590 /**
591  * @internal Convert global config properties dict to a normal dict
592  * @param key The dict key
593  * @param property An xmms_config_property_t
594  * @param udata The dict to store configvals
595  */
596 static gboolean
597 xmms_config_foreach_dict (gpointer key, xmms_config_property_t *prop,
598  GTree *dict)
599 {
600  g_tree_insert (dict, g_strdup (key), xmmsv_new_string (prop->value));
601 
602  return FALSE; /* keep going */
603 }
604 
605 /**
606  * @internal List all keys and values in the config.
607  * @param conf The config
608  * @param err To be filled in if an error occurs
609  * @return a dict with config properties and values
610  */
611 static GTree *
612 xmms_config_client_list_values (xmms_config_t *conf, xmms_error_t *err)
613 {
614  GTree *ret;
615 
616  ret = g_tree_new_full (compare_key, NULL,
617  g_free, (GDestroyNotify)xmmsv_unref);
618 
619  g_mutex_lock (conf->mutex);
620  g_tree_foreach (conf->properties,
621  (GTraverseFunc) xmms_config_foreach_dict,
622  (gpointer) ret);
623  g_mutex_unlock (conf->mutex);
624 
625  return ret;
626 }
627 
628 /**
629  * @internal Look for a key in the config and return its value as a string
630  * @param conf The config
631  * @param key The key to look for
632  * @param err To be filled in if an error occurs
633  * @return The value of the key, or NULL if not found
634  */
635 static gchar *
636 xmms_config_client_get_value (xmms_config_t *conf, const gchar *key,
637  xmms_error_t *err)
638 {
639  return g_strdup (xmms_config_property_lookup_get_string (conf, key, err));
640 }
641 
642 /**
643  * @internal Destroy a config object
644  * @param object The object to destroy
645  */
646 static void
647 xmms_config_destroy (xmms_object_t *object)
648 {
649  xmms_config_t *config = (xmms_config_t *)object;
650 
651  g_mutex_free (config->mutex);
652 
653  g_tree_destroy (config->properties);
654 
655  xmms_config_unregister_ipc_commands ();
656 }
657 
658 static gint
659 compare_key (gconstpointer a, gconstpointer b, gpointer user_data)
660 {
661  return strcmp ((gchar *) a, (gchar *) b);
662 }
663 
664 static GTree *
665 create_tree (void)
666 {
667  return g_tree_new_full (compare_key, NULL, g_free,
668  (GDestroyNotify) __int_xmms_object_unref);
669 }
670 
671 /**
672  * @internal Clear data in a config object
673  * @param config The config object to clear
674  */
675 static void
676 clear_config (xmms_config_t *config)
677 {
678  g_tree_destroy (config->properties);
679  config->properties = create_tree ();
680 
681  config->version = XMMS_CONFIG_VERSION;
682 
683  g_free (config->value_name);
684  config->value_name = NULL;
685 }
686 
687 /**
688  * @internal Initialize and parse the config file. Resets to default config
689  * on parse error.
690  * @param[in] filename The absolute path to a config file as a string.
691  */
692 void
693 xmms_config_init (const gchar *filename)
694 {
695  GMarkupParser pars;
696  GMarkupParseContext *ctx;
697  xmms_config_t *config;
698  int ret, fd = -1;
699  gboolean parserr = FALSE, eof = FALSE;
700 
701  config = xmms_object_new (xmms_config_t, xmms_config_destroy);
702  config->mutex = g_mutex_new ();
703  config->filename = filename;
704 
705  config->properties = create_tree ();
706 
707  config->version = 0;
708  global_config = config;
709 
710  xmms_config_register_ipc_commands (XMMS_OBJECT (config));
711 
712  memset (&pars, 0, sizeof (pars));
713 
714  pars.start_element = xmms_config_parse_start;
715  pars.end_element = xmms_config_parse_end;
716  pars.text = xmms_config_parse_text;
717 
718  if (g_file_test (filename, G_FILE_TEST_EXISTS)) {
719  fd = open (filename, O_RDONLY);
720  }
721 
722  if (fd > -1) {
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);
727 
728  while ((!eof) && (!parserr)) {
729  GError *error = NULL;
730  gchar buffer[1024];
731 
732  ret = read (fd, buffer, 1024);
733  if (ret < 1) {
734  g_markup_parse_context_end_parse (ctx, &error);
735  if (error) {
736  xmms_log_error ("Cannot parse config file: %s",
737  error->message);
738  g_error_free (error);
739  error = NULL;
740  parserr = TRUE;
741  }
742  eof = TRUE;
743  }
744 
745  g_markup_parse_context_parse (ctx, buffer, ret, &error);
746  if (error) {
747  xmms_log_error ("Cannot parse config file: %s",
748  error->message);
749  g_error_free (error);
750  error = NULL;
751  parserr = TRUE;
752  }
753  /* check config file version, assumes that g_markup_context_parse
754  * above managed to parse the <xmms> element during the first
755  * iteration of this loop */
756  if (XMMS_CONFIG_VERSION > config->version) {
757  clear_config (config);
758  break;
759  }
760  }
761 
762  close (fd);
763  g_markup_parse_context_free (ctx);
764 
765  while (!g_queue_is_empty (config->sections)) {
766  g_free (g_queue_pop_head (config->sections));
767  }
768 
769  g_queue_free (config->states);
770  g_queue_free (config->sections);
771 
772  config->is_parsing = FALSE;
773  } else {
774  xmms_log_info ("No configfile specified, using default values.");
775  }
776 
777  if (parserr) {
778  xmms_log_info ("The config file could not be parsed, reverting to default configuration..");
779  clear_config (config);
780  }
781 }
782 
783 /**
784  * @internal Shut down the config layer - free memory from the global
785  * configuration.
786  */
787 void
789 {
790  xmms_object_unref (global_config);
791 
792 }
793 
794 static gboolean
795 dump_tree (gchar *current_key, xmms_config_property_t *prop,
796  dump_tree_data_t *data)
797 {
798  gchar *prop_name, section[256];
799  gchar *dot = NULL, *current_last_dot, *start = current_key;
800 
801  prop_name = strrchr (current_key, '.');
802 
803  /* check whether we need to open a new section.
804  * this is always the case if data->prev_key == NULL.
805  * but if the sections of the last key and the current key differ,
806  * we also need to do that.
807  */
808  if (data->prev_key) {
809  gchar *c = current_key, *o = data->prev_key;
810  gsize dots = 0;
811 
812  /* position c and o at the respective ends of the common
813  * prefixes of the previous and the current key.
814  */
815  while (*c && *o && *c == *o) {
816  c++;
817  o++;
818 
819  if (*c == '.')
820  start = c + 1;
821  };
822 
823  /* from this position on, count the number of dots in the
824  * previous key (= number of dots that are present in the
825  * previous key, but no the current key).
826  */
827  while (*o) {
828  if (*o == '.')
829  dots++;
830 
831  o++;
832  };
833 
834  /* we'll close the previous key's sections now, so we don't
835  * have to worry about it next time this function is called.
836  */
837  if (dots)
838  data->prev_key = NULL;
839 
840  while (dots--) {
841  /* decrease indent level */
842  data->indent[--data->indent_level] = '\0';
843 
844  fprintf (data->fp, "%s</section>\n", data->indent);
845  }
846  }
847 
848  /* open section tags */
849  dot = strchr (start, '.');
850  current_last_dot = start - 1;
851 
852  while (dot) {
853  strncpy (section, current_last_dot + 1, dot - current_last_dot + 1);
854  section[dot - current_last_dot - 1] = 0;
855 
856  fprintf (data->fp, "%s<section name=\"%s\">\n",
857  data->indent, section);
858 
859  /* increase indent level */
860  g_assert (data->indent_level < 127);
861  data->indent[data->indent_level] = '\t';
862  data->indent[++data->indent_level] = '\0';
863 
864  current_last_dot = dot;
865  dot = strchr (dot + 1, '.');
866  };
867 
868  data->prev_key = current_key;
869 
870  fprintf (data->fp, "%s<property name=\"%s\">%s</property>\n",
871  data->indent, prop_name + 1,
873 
874  return FALSE; /* keep going */
875 }
876 
877 /**
878  * @internal Save the global configuration to disk.
879  * @param file Absolute path to configfile. This will be overwritten.
880  * @return TRUE on success.
881  */
882 gboolean
884 {
885  FILE *fp = NULL;
886  dump_tree_data_t data;
887 
888  g_return_val_if_fail (global_config, FALSE);
889 
890  /* don't try to save config while it's being read */
891  if (global_config->is_parsing)
892  return FALSE;
893 
894  if (!(fp = fopen (global_config->filename, "w"))) {
895  xmms_log_error ("Couldn't open %s for writing.",
896  global_config->filename);
897  return FALSE;
898  }
899 
900  fprintf (fp, "<?xml version=\"1.0\"?>\n<xmms version=\"%i\">\n",
902 
903  data.fp = fp;
904  data.state = XMMS_CONFIG_STATE_START;
905  data.prev_key = NULL;
906 
907  strcpy (data.indent, "\t");
908  data.indent_level = 1;
909 
910  g_tree_foreach (global_config->properties,
911  (GTraverseFunc) dump_tree, &data);
912 
913  /* close the remaining section tags. the final indent level
914  * was started with the opening xmms tag, so the loop condition
915  * is '> 1' here rather than '> 0'.
916  */
917  while (data.indent_level > 1) {
918  /* decrease indent level */
919  data.indent[--data.indent_level] = '\0';
920 
921  fprintf (fp, "%s</section>\n", data.indent);
922  }
923 
924  fprintf (fp, "</xmms>\n");
925  fclose (fp);
926 
927  return TRUE;
928 }
929 
930 /*
931  * Value manipulation
932  */
933 
934 /**
935  * @internal Destroy a config value
936  * @param object The object to destroy
937  */
938 static void
939 xmms_config_property_destroy (xmms_object_t *object)
940 {
942 
943  /* don't free val->name here, it's taken care of in
944  * xmms_config_destroy()
945  */
946  g_free (prop->value);
947 }
948 
949 /**
950  * @internal Create a new config value
951  * @param name The name of the new config value
952  */
953 static xmms_config_property_t *
954 xmms_config_property_new (const gchar *name)
955 {
957 
958  ret = xmms_object_new (xmms_config_property_t, xmms_config_property_destroy);
959  ret->name = name;
960 
961  return ret;
962 }
963 
964 /**
965  * @internal Register a client config value
966  * @param config The config
967  * @param name The name of the config value
968  * @param def_value The default value to use
969  * @param error To be filled in if an error occurs
970  * @return The full path to the config value registered
971  */
972 static gchar *
973 xmms_config_client_register_value (xmms_config_t *config,
974  const gchar *name,
975  const gchar *def_value,
976  xmms_error_t *error)
977 {
978  gchar *tmp;
979  tmp = g_strdup_printf ("clients.%s", name);
980  xmms_config_property_register (tmp, def_value, NULL, NULL);
981  return tmp;
982 }
983 
984 /** @} */
#define XMMS_OBJECT(p)
Definition: xmms_object.h:77
#define XMMS_CONFIG_VERSION
Config file version.
Definition: config.c:125
void xmmsv_unref(xmmsv_t *val)
Decreases the references for the xmmsv_t When the number of references reaches 0 it will be freed...
Definition: value.c:303
#define xmms_object_unref(obj)
Definition: xmms_object.h:109
gfloat xmms_config_property_get_float(const xmms_config_property_t *prop)
Return the value of a config property as a float.
Definition: config.c:270
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.
Definition: config.c:307
const gchar * xmms_config_property_get_name(const xmms_config_property_t *prop)
Get the name of a config property.
Definition: config.c:189
xmms_config_property_t * xmms_config_lookup(const gchar *path)
Look up a config key from the global config.
Definition: config.c:171
xmmsv_t * xmmsv_new_string(const char *s)
Allocates a new string xmmsv_t.
Definition: value.c:180
xmms_configparser_state_t
Definition: config.c:44
gboolean xmms_config_save(void)
Definition: config.c:883
void xmms_config_init(const gchar *filename)
Definition: config.c:693
gint xmms_config_property_get_int(const xmms_config_property_t *prop)
Return the value of a config property as an int.
Definition: config.c:255
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.
Definition: config.c:202
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.
Definition: object.c:195
#define xmms_log_error(fmt,...)
Definition: xmms_log.h:35
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.
Definition: config.c:287
void xmms_object_emit_f(xmms_object_t *object, guint32 signalid, xmmsv_type_t type,...)
Emits a signal on the current object.
Definition: object.c:256
typedefG_BEGIN_DECLS struct xmms_config_St xmms_config_t
Definition: xmms_config.h:25
void __int_xmms_object_unref(xmms_object_t *object)
Definition: object.c:488
const gchar * xmms_config_property_get_string(const xmms_config_property_t *prop)
Return the value of a config property as a string.
Definition: config.c:243
#define xmms_log_info(fmt,...)
Definition: xmms_log.h:34
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.
Definition: object.c:115
void xmms_object_disconnect(xmms_object_t *object, guint32 signalid, xmms_object_handler_t handler, gpointer userdata)
Disconnect from a signal.
Definition: object.c:146
const gchar * xmms_config_property_lookup_get_string(xmms_config_t *conf, const gchar *key, xmms_error_t *err)
Config functions.
Definition: config.c:149
void xmms_config_shutdown()
Definition: config.c:788
#define xmms_object_new(objtype, destroyfunc)
Definition: xmms_object.h:115
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.
Definition: config.c:334
struct xmms_config_property_St xmms_config_property_t
Definition: xmms_config.h:26
void(* xmms_object_handler_t)(xmms_object_t *object, xmmsv_t *data, gpointer userdata)
Definition: xmms_object.h:66