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
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 */
44typedef enum {
50
51typedef struct dump_tree_data_St {
52 FILE *fp;
54
55 gchar indent[128];
56 guint indent_level;
57
58 gchar *prev_key;
60
61static GTree *xmms_config_client_list_values (xmms_config_t *conf, xmms_error_t *err);
62static xmms_config_property_t *xmms_config_property_new (const gchar *name);
63static gchar *xmms_config_client_get_value (xmms_config_t *conf, const gchar *key, xmms_error_t *err);
64static gchar *xmms_config_client_register_value (xmms_config_t *config, const gchar *name, const gchar *def_value, xmms_error_t *error);
65static gint compare_key (gconstpointer a, gconstpointer b, gpointer user_data);
66static 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 */
85struct 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 */
105struct 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
120static 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 */
148const 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
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 */
171xmms_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 */
188const 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 */
201void
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 */
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 */
242const 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 */
254gint
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 */
269gfloat
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 */
286void
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 */
306void
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 */
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 */
376get_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 */
405static const gchar *
406lookup_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 */
430static void
431xmms_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 */
497static void
498xmms_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 */
533static void
534xmms_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 */
573static void
574xmms_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 */
596static gboolean
597xmms_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 */
611static GTree *
612xmms_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 */
635static gchar *
636xmms_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 */
646static void
647xmms_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
658static gint
659compare_key (gconstpointer a, gconstpointer b, gpointer user_data)
660{
661 return strcmp ((gchar *) a, (gchar *) b);
662}
663
664static GTree *
665create_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 */
675static void
676clear_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 */
692void
693xmms_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 */
787void
789{
790 xmms_object_unref (global_config);
791
792}
793
794static gboolean
795dump_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 */
882gboolean
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 */
938static void
939xmms_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 */
954xmms_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 */
972static gchar *
973xmms_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/** @} */
gboolean xmms_config_save(void)
Definition: config.c:883
void xmms_config_init(const gchar *filename)
Definition: config.c:693
struct dump_tree_data_St dump_tree_data_t
xmms_configparser_state_t
Definition: config.c:44
@ XMMS_CONFIG_STATE_PROPERTY
Definition: config.c:48
@ XMMS_CONFIG_STATE_SECTION
Definition: config.c:47
@ XMMS_CONFIG_STATE_START
Definition: config.c:46
@ XMMS_CONFIG_STATE_INVALID
Definition: config.c:45
void xmms_config_shutdown()
Definition: config.c:788
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
#define XMMS_CONFIG_VERSION
Config file version.
Definition: config.c:125
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
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
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
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_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
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
xmms_config_property_t * xmms_config_lookup(const gchar *path)
Look up a config key from the global config.
Definition: config.c:171
const gchar * xmms_config_property_get_name(const xmms_config_property_t *prop)
Get the name of a config property.
Definition: config.c:189
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_object_disconnect(xmms_object_t *object, guint32 signalid, xmms_object_handler_t handler, gpointer userdata)
Disconnect from a signal.
Definition: object.c:146
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
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_emit_f(xmms_object_t *object, guint32 signalid, xmmsv_type_t type,...)
Emits a signal on the current object.
Definition: object.c:256
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
xmmsv_t * xmmsv_new_string(const char *s)
Allocates a new string xmmsv_t.
Definition: value.c:180
@ XMMSV_TYPE_DICT
Definition: xmmsv_general.h:43
void __int_xmms_object_unref(xmms_object_t *object)
Definition: object.c:488
struct xmms_config_property_St xmms_config_property_t
Definition: xmms_config.h:26
typedefG_BEGIN_DECLS struct xmms_config_St xmms_config_t
Definition: xmms_config.h:25
#define xmms_log_error(fmt,...)
Definition: xmms_log.h:35
#define xmms_log_info(fmt,...)
Definition: xmms_log.h:34
G_BEGIN_DECLS struct xmms_error_St xmms_error_t
void(* xmms_object_handler_t)(xmms_object_t *object, xmmsv_t *data, gpointer userdata)
Definition: xmms_object.h:66
#define xmms_object_new(objtype, destroyfunc)
Definition: xmms_object.h:115
#define XMMS_OBJECT(p)
Definition: xmms_object.h:77
#define xmms_object_unref(obj)
Definition: xmms_object.h:109
@ XMMS_ERROR_NOENT
@ XMMS_IPC_SIGNAL_CONFIGVALUE_CHANGED