1 /* Gnome Music Player Client (GMPC)
2 * Copyright (C) 2004-2011 Qball Cow <qball@sarine.nl>
3 * Project homepage: http://gmpc.wikia.com/
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 #include <glib/gstdio.h>
26 #include <sys/types.h>
31 #define LOG_DOMAIN "Config"
33 typedef enum _ConfigNodeType
43 typedef struct _config_node
45 struct _config_node
*next
;
46 struct _config_node
*prev
;
47 struct _config_node
*parent
;
50 /* Save some extra memory by using a union
51 * It is actually effective because we build a resonable large tree using this
56 struct _config_node
*children
;
57 gchar
*value
; /* TYPE_ITEM* */
61 typedef struct _config_obj
70 static void __int_cfg_set_single_value_as_string(config_obj
* cfg
, const char *class, const char *sclass
,
71 const char *ssclass
, const char *key
, const char *value
);
72 static gboolean
cfg_save_real(config_obj
*);
73 static void __int_cfg_remove_node(config_obj
*, config_node
*);
74 static config_node
*cfg_get_class_multiple(config_obj
* cfg
, config_node
* root
, const char *class);
75 static void __int_cfg_do_special_cleanup(config_obj
* cfg
, config_node
* node
);
76 static config_node
*cfg_add_class(config_obj
*, config_node
*, const char *);
77 static config_node
*cfg_new_node(void);
78 static void cfg_add_child(config_node
*, config_node
*);
79 static void cfg_save_delayed(config_obj
* cfg
);
81 static void cfg_open_parse_file(config_obj
* cfgo
, FILE * fp
)
86 config_node
*cur
= NULL
;
87 config_node
*multiple
= NULL
;
89 while ((c
= fgetc(fp
)) != EOF
)
91 if (c
== '2' && !firstchar
)
100 while (c
!= ']' && c
!= EOF
&& len
< 1023)
107 if (len
> 0 && len
< 256)
109 // printf("add class: %s -> %s\n", buffer, (cur )?cur->name:"");
110 cur
= cfg_add_class(cfgo
, (version
< 2) ? NULL
: cur
, buffer
);
121 /* seek end of line */
122 while (c
!= EOF
&& c
!= '\n')
129 while (c
!= '}' && c
!= EOF
&& len
< 1023)
136 if (len
> 0 && len
< 256)
138 config_node
*child
= cfg_new_node();
139 child
->type
= TYPE_ITEM_MULTIPLE
;
140 child
->name
= g_strndup(buffer
, len
);
142 child
->children
= NULL
;
143 cfg_add_child(cur
, child
);
145 cfgo
->total_size
+= len
+ sizeof(config_node
);
152 /* seek end of line */
153 while (c
!= EOF
&& c
!= '\n')
157 /* next, ignore commants and there must be a category */
158 else if (cur
&& (c
== '#' || c
== '/' || c
== '\n' || c
== ';'))
160 while (c
!= EOF
&& c
!= '\n')
164 config_node
*new = NULL
;
166 while (c
!= '=' && c
!= EOF
)
172 if (len
< 256 && len
> 0)
177 new = cfg_new_node();
179 new->type
= TYPE_ITEM
;
180 new->name
= g_strndup(buffer
, len
);
181 cfgo
->total_size
+= len
+ sizeof(config_node
);
185 while ((c
= fgetc(fp
)) == ' ') ;
186 /* we got a quoted string */
194 /* add escaped char */
208 /* We have a quoted string, and the closing quote comes */
209 else if (c
== '"' && quote
)
217 } while ((c
!= '\n' || quote
) && c
!= EOF
&& quote
>= 0 && len
< 1023);
218 new->value
= g_strndup(buffer
, len
);
219 cfgo
->total_size
+= len
;
222 cfg_add_child(multiple
, new);
225 cfg_add_child(cur
, new);
228 /* seek end of line */
229 while (c
!= EOF
&& c
!= '\n')
232 while (c
!= EOF
&& c
!= '\n')
239 config_obj
*cfg_open(gchar
* url
)
241 config_obj
*cfgo
= NULL
;
242 /* check if there is an url passed */
248 cfgo
= g_malloc(sizeof(config_obj
));
249 /* check if malloc went ok */
254 /* cfgo->lock = g_mutex_new();
255 g_mutex_lock(cfgo->lock);
257 cfgo
->url
= g_strdup(url
);
259 cfgo
->total_size
= sizeof(config_obj
) /*+sizeof(&cfgo->lock) */ + strlen(cfgo
->url
);
260 cfgo
->save_timeout
= 0;
262 if (g_file_test(cfgo
->url
, G_FILE_TEST_EXISTS
))
264 FILE *fp
= g_fopen(cfgo
->url
, "r");
267 cfg_open_parse_file(cfgo
, fp
);
271 g_log(LOG_DOMAIN
, G_LOG_LEVEL_DEBUG
, "Config %s: allocated: %i\n", cfgo
->url
, cfgo
->total_size
);
273 g_mutex_unlock(cfgo->lock);
279 void cfg_close(config_obj
* cfgo
)
286 g_log(LOG_DOMAIN
, G_LOG_LEVEL_DEBUG
, "Closing config '%s' with %i bytes allocated\n", cfgo
->url
, cfgo
->total_size
);
288 g_mutex_lock(cfgo->lock);
290 if (cfgo
->url
!= NULL
)
292 cfgo
->total_size
-= strlen(cfgo
->url
);
293 cfg_free_string(cfgo
->url
);
296 __int_cfg_remove_node(cfgo
, cfgo
->root
);
298 g_mutex_unlock(cfgo->lock);
300 cfgo
->total_size
-= /*sizeof(&cfgo->lock)+ */ sizeof(config_obj
);
301 /* g_mutex_free(cfgo->lock);*/
302 g_log(LOG_DOMAIN
, G_LOG_LEVEL_DEBUG
, "Memory remaining: %i\n", cfgo
->total_size
);
308 static config_node
*cfg_new_node(void)
310 config_node
*newnode
= g_slice_new(config_node
);
311 newnode
->type
= TYPE_CATEGORY
;
312 newnode
->name
= NULL
;
313 newnode
->next
= NULL
;
314 newnode
->prev
= NULL
;
315 newnode
->parent
= NULL
;
316 newnode
->value
= NULL
;
317 newnode
->children
= NULL
;
322 static config_node
*cfg_add_class(config_obj
* cfg
, config_node
* parent
, const char *class)
324 config_node
*newnode
= cfg_new_node();
325 newnode
->type
= TYPE_CATEGORY
;
326 newnode
->name
= g_strdup(class);
327 newnode
->parent
= parent
;
328 cfg
->total_size
+= sizeof(config_node
) + strlen(class);
331 if (cfg
->root
== NULL
)
336 config_node
*temp
= cfg
->root
;
337 while (temp
->next
!= NULL
)
339 temp
->next
= newnode
;
340 newnode
->prev
= temp
;
344 if (parent
->children
== NULL
)
346 parent
->children
= newnode
;
349 config_node
*temp
= parent
->children
;
351 while (temp
->next
!= NULL
)
353 temp
->next
= newnode
;
354 newnode
->prev
= temp
;
362 void cfg_add_child(config_node
* parent
, config_node
* child
)
364 if (parent
== NULL
|| child
== NULL
)
366 if (parent
->type
== TYPE_ITEM
)
368 if (parent
->children
== NULL
)
370 parent
->children
= child
;
371 child
->parent
= parent
;
374 config_node
*temp
= parent
->children
;
377 while (temp
->next
!= NULL
)
381 child
->parent
= parent
;
386 static void cfg_save_category(config_obj
* cfg
, config_node
* node
, FILE * fp
)
388 config_node
*temp
= NULL
;
393 while (node
->prev
!= NULL
)
395 /* save some stuff */
396 for (temp
= node
; temp
!= NULL
; temp
= temp
->next
)
398 if (temp
->type
== TYPE_CATEGORY
)
401 fputs(temp
->name
, fp
);
403 cfg_save_category(cfg
, temp
->children
, fp
);
406 if (temp
->type
== TYPE_ITEM_MULTIPLE
)
409 fputs(temp
->name
, fp
);
411 cfg_save_category(cfg
, temp
->children
, fp
);
413 } else if (temp
->type
== TYPE_ITEM
)
416 int length
= (temp
->value
) ? strlen(temp
->value
) : 0;
417 fputs(temp
->name
, fp
);
419 for (i
= 0; i
< length
; i
++)
421 if (temp
->value
[i
] == '"')
424 } else if (temp
->value
[i
] == '\\')
427 } else if (temp
->value
[i
] == '\n')
432 putc(temp
->value
[i
], fp
);
441 static gboolean
cfg_save_real(config_obj
* cfgo
)
448 if (cfgo
->save_timeout
)
450 g_source_remove(cfgo
->save_timeout
);
451 cfgo
->save_timeout
= 0;
456 g_log(LOG_DOMAIN
, G_LOG_LEVEL_DEBUG
, "Save triggered:%s", cfgo
->url
);
457 g_log(LOG_DOMAIN
, G_LOG_LEVEL_DEBUG
, "Saving config file: %s (%i bytes)", cfgo
->url
, cfgo
->total_size
);
458 if (cfgo
->root
!= NULL
)
460 FILE *fp
= g_fopen(cfgo
->url
, "w");
464 cfg_save_category(cfgo
, cfgo
->root
, fp
);
467 chmod(cfgo
->url
, 0600);
475 static config_node
*cfg_get_class(config_obj
* cfg
, const char *class)
477 return cfg_get_class_multiple(cfg
, NULL
, class);
481 static config_node
*cfg_get_class_multiple(config_obj
* cfg
, config_node
* root
, const char *class)
483 config_node
*node
= NULL
;
486 node
= root
->children
;
495 while (node
->prev
!= NULL
)
498 for (; node
!= NULL
; node
= node
->next
)
500 if (node
->type
== TYPE_CATEGORY
&& !strcmp(node
->name
, class))
510 static config_node
*cfg_get_single_value(config_obj
* cfg
, const char *class, const char *sclass
, const char *ssclass
,
514 config_node
*cur
= NULL
;
515 cur
= cfg_get_class(cfg
, class);
516 if (cur
== NULL
|| cur
->children
== NULL
)
522 cur
= cfg_get_class_multiple(cfg
, cur
, sclass
);
523 if (cur
== NULL
|| cur
->children
== NULL
)
528 cur
= cfg_get_class_multiple(cfg
, cur
, ssclass
);
529 if (cur
== NULL
|| cur
->children
== NULL
)
533 for (; cur
!= NULL
; cur
= cur
->next
)
535 if (!strcmp(cur
->name
, key
))
544 /*void cfg_free_string(char *string)
552 static char *__int_cfg_get_single_value_as_string(config_obj
* cfg
, const char *class, const char *sclass
,
553 const char *ssclass
, const char *key
)
555 config_node
*cur
= cfg_get_single_value(cfg
, class, sclass
, ssclass
, key
);
558 if (cur
->type
== TYPE_ITEM
)
560 return g_strdup((char *)cur
->value
);
567 char *cfg_get_single_value_as_string(config_obj
* cfg
, const char *class, const char *key
)
569 return cfg_get_single_value_as_string_mm(cfg
, class, NULL
, NULL
, key
);
573 char *cfg_get_single_value_as_string_with_default(config_obj
* cfg
, const char *class, const char *key
, const char *def
)
575 return cfg_get_single_value_as_string_with_default_mm(cfg
, class, NULL
, NULL
, key
, def
);
579 static int __int_cfg_get_single_value_as_int_mm(config_obj
* cfg
, const char *class, const char *sclass
,
580 const char *ssclass
, const char *key
)
582 config_node
*cur
= NULL
;
583 int retv
= CFG_INT_NOT_DEFINED
;
585 cur
= cfg_get_single_value(cfg
, class, sclass
, ssclass
, key
);
588 if (cur
->type
== TYPE_ITEM
)
590 retv
= (int)g_ascii_strtoull(cur
->value
, NULL
, 0);
598 int cfg_get_single_value_as_int(config_obj
* cfg
, const char *class, const char *key
)
601 /* g_mutex_lock(cfg->lock);*/
602 retv
= __int_cfg_get_single_value_as_int_mm(cfg
, class, NULL
, NULL
, key
);
603 /* g_mutex_unlock(cfg->lock);*/
608 void cfg_set_single_value_as_int(config_obj
* cfg
, const char *class, const char *key
, int value
)
610 cfg_set_single_value_as_int_mm(cfg
, class, NULL
, NULL
, key
, value
);
614 static void __int_cfg_set_single_value_as_int(config_obj
* cfg
, const char *class, const char *sclass
,
615 const char *ssclass
, const char *key
, int value
)
618 temp
= g_strdup_printf("%i", value
);
619 __int_cfg_set_single_value_as_string(cfg
, class, sclass
, ssclass
, key
, temp
);
620 cfg_free_string(temp
);
624 int cfg_get_single_value_as_int_with_default(config_obj
* cfg
, const char *class, const char *key
, int def
)
626 return cfg_get_single_value_as_int_with_default_mm(cfg
, class, NULL
, NULL
, key
, def
);
631 static float __int_cfg_get_single_value_as_float(config_obj
* cfg
, const char *class, const char *sclass
,
632 const char *ssclass
, const char *key
)
635 config_node
*cur
= NULL
;
636 cur
= cfg_get_single_value(cfg
, class, sclass
, ssclass
, key
);
640 return CFG_INT_NOT_DEFINED
;
642 /* make it return an error */
643 result
= g_ascii_strtod(cur
->value
, NULL
);
648 float cfg_get_single_value_as_float(config_obj
* cfg
, const char *class, const char *key
)
651 /* g_mutex_lock(cfg->lock);*/
652 retv
= __int_cfg_get_single_value_as_float(cfg
, class, NULL
, NULL
, key
);
653 /* g_mutex_unlock(cfg->lock);*/
658 float cfg_get_single_value_as_float_mm(config_obj
* cfg
, const char *class, const char *sclass
, const char *ssclass
,
662 /* g_mutex_lock(cfg->lock);*/
663 retv
= __int_cfg_get_single_value_as_float(cfg
, class, sclass
, ssclass
, key
);
664 /* g_mutex_unlock(cfg->lock);*/
669 void cfg_set_single_value_as_float(config_obj
* cfg
, const char *class, const char *key
, float value
)
672 /* g_mutex_lock(cfg->lock);*/
673 value1
= g_strdup_printf("%f", value
);
674 __int_cfg_set_single_value_as_string(cfg
, class, NULL
, NULL
, key
, value1
);
675 cfg_free_string(value1
);
676 /* g_mutex_unlock(cfg->lock);*/
680 float cfg_get_single_value_as_float_with_default(config_obj
* cfg
, const char *class, const char *key
, float def
)
683 /* g_mutex_lock(cfg->lock);*/
684 retv
= __int_cfg_get_single_value_as_float(cfg
, class, NULL
, NULL
, key
);
685 if (retv
== CFG_INT_NOT_DEFINED
)
687 char *value1
= g_strdup_printf("%f", def
);
688 __int_cfg_set_single_value_as_string(cfg
, class, NULL
, NULL
, key
, value1
);
689 cfg_free_string(value1
);
690 retv
= __int_cfg_get_single_value_as_float(cfg
, class, NULL
, NULL
, key
);
692 /* g_mutex_unlock(cfg->lock);*/
693 /* make it return an error */
698 static void __int_cfg_remove_node(config_obj
* cfg
, config_node
* node
)
700 if (node
->type
!= TYPE_ITEM
)
702 while (node
->children
)
704 __int_cfg_remove_node(cfg
, node
->children
);
707 /* only child, and I have a parent */
708 if (node
->next
== NULL
&& node
->prev
== NULL
&& node
->parent
)
710 /* remove from list */
711 if (node
->parent
->type
!= TYPE_ITEM
)
713 node
->parent
->children
= NULL
;
716 /* remove node from linked list */
717 if (node
->prev
!= NULL
)
719 if (node
->parent
&& node
->parent
->children
== node
)
721 node
->parent
->children
= node
->prev
;
723 node
->prev
->next
= node
->next
;
725 if (node
->next
!= NULL
)
727 if (node
->parent
&& node
->parent
->children
== node
)
729 node
->parent
->children
= node
->next
;
731 node
->next
->prev
= node
->prev
;
733 if (node
== cfg
->root
)
737 cfg
->root
= node
->prev
;
738 } else if (node
->next
)
740 cfg
->root
= node
->next
;
746 cfg
->total_size
-= sizeof(config_node
);
749 cfg
->total_size
-= strlen(node
->name
);
750 cfg_free_string(node
->name
);
754 cfg
->total_size
-= strlen(node
->value
);
755 cfg_free_string(node
->value
);
757 g_slice_free(config_node
, node
);
761 void cfg_del_single_value_mm(config_obj
* cfg
, const char *class, const char *sclass
, const char *ssclass
,
764 config_node
*node
= NULL
;
765 /* g_mutex_lock(cfg->lock);*/
766 node
= cfg_get_single_value(cfg
, class, sclass
, ssclass
, key
);
769 __int_cfg_remove_node(cfg
, node
);
770 cfg_save_delayed(cfg
);
771 g_log(LOG_DOMAIN
, G_LOG_LEVEL_DEBUG
, "triggered save delay: del: %s, %s", class, key
);
773 /* g_mutex_unlock(cfg->lock);*/
777 void cfg_del_single_value(config_obj
* cfg
, const char *class, const char *key
)
779 cfg_del_single_value_mm(cfg
, class, NULL
, NULL
, key
);
783 void cfg_remove_class(config_obj
* cfg
, const char *class)
785 config_node
*node
= NULL
;
786 if (cfg
== NULL
|| class == NULL
)
789 /* g_mutex_lock(cfg->lock);*/
790 node
= cfg_get_class(cfg
, class);
793 __int_cfg_remove_node(cfg
, node
);
795 cfg_save_delayed(cfg
);
796 g_log(LOG_DOMAIN
, G_LOG_LEVEL_DEBUG
, "triggered save delay: del: %s", class);
797 /* g_mutex_unlock(cfg->lock);*/
801 static void __int_cfg_set_single_value_as_string(config_obj
* cfg
, const char *class, const char *sclass
,
802 const char *ssclass
, const char *key
, const char *value
)
804 config_node
*newnode
= cfg_get_single_value(cfg
, class, sclass
, ssclass
, key
);
807 config_node
*node
= cfg_get_class(cfg
, class);
810 node
= cfg_add_class(cfg
, NULL
, class);
816 config_node
*nnode
= cfg_get_class_multiple(cfg
, node
, sclass
);
819 nnode
= cfg_add_class(cfg
, node
, sclass
);
827 config_node
*nnode
= cfg_get_class_multiple(cfg
, node
, ssclass
);
830 nnode
= cfg_add_class(cfg
, node
, ssclass
);
836 newnode
= cfg_new_node();
837 newnode
->name
= g_strdup(key
);
838 cfg
->total_size
+= sizeof(config_node
) + strlen(key
);
839 cfg_add_child(node
, newnode
);
841 } else if ((value
== NULL
&& newnode
->value
== NULL
) ||
842 (value
!= NULL
&& newnode
->value
!= NULL
&& strlen(newnode
->value
) == strlen(value
)
843 && !memcmp(newnode
->value
, value
, strlen(newnode
->value
))))
845 /* Check if the content is the same, if it is, do nothing */
848 newnode
->type
= TYPE_ITEM
;
851 cfg
->total_size
-= strlen(newnode
->value
);
852 cfg_free_string(newnode
->value
);
856 newnode
->value
= g_strdup(value
);
857 cfg
->total_size
+= strlen(value
);
860 newnode
->value
= NULL
;
862 cfg_save_delayed(cfg
);
863 g_log(LOG_DOMAIN
, G_LOG_LEVEL_DEBUG
, "triggered save delay: set: %s,%s -> %s", class, key
, value
);
867 void cfg_set_single_value_as_string(config_obj
* cfg
, const char *class, const char *key
, const char *value
)
869 /* g_mutex_lock(cfg->lock);*/
870 __int_cfg_set_single_value_as_string(cfg
, class, NULL
, NULL
, key
, value
);
871 /* g_mutex_unlock(cfg->lock);*/
875 /* multiple values */
877 static config_node
*cfg_get_multiple_value(config_obj
* cfg
, const char *class, const char *key
, const char *id
)
879 config_node
*node
= cfg_get_single_value(cfg
, class, NULL
, NULL
, key
);
884 if (node
->type
!= TYPE_ITEM_MULTIPLE
)
888 if (node
->children
== NULL
)
893 node
= node
->children
;
894 while (node
->prev
!= NULL
)
897 for (; node
!= NULL
; node
= node
->next
)
899 if (!strcmp(node
->name
, id
))
908 void cfg_del_multiple_value(config_obj
* cfg
, const char *class, const char *key
, const char *id
)
910 config_node
*cur
= NULL
;
911 /* g_mutex_lock(cfg->lock);*/
912 cur
= cfg_get_multiple_value(cfg
, class, key
, id
);
915 __int_cfg_remove_node(cfg
, cur
);
916 cfg_save_delayed(cfg
);
918 /* g_mutex_unlock(cfg->lock);*/
922 void cfg_set_multiple_value_as_string(config_obj
* cfg
, const char *class, const char *key
, const char *id
,
925 config_node
*cur
= NULL
;
926 /* g_mutex_lock(cfg->lock);*/
927 cur
= cfg_get_multiple_value(cfg
, class, key
, id
);
930 if (strlen(cur
->value
) == strlen(value
) && !memcmp(cur
->value
, value
, strlen(cur
->value
)))
936 cfg
->total_size
-= strlen(cur
->value
);
937 cfg_free_string(cur
->value
);
940 cur
->value
= g_strdup(value
);
941 cfg
->total_size
+= strlen(cur
->value
);
942 cfg_save_delayed(cfg
);
945 config_node
*node
= cfg_get_single_value(cfg
, class, NULL
, NULL
, key
);
948 node
= cfg_get_class(cfg
, class);
951 node
= cfg_add_class(cfg
, NULL
, class);
953 cur
= cfg_new_node();
954 cur
->name
= g_strdup(key
);
955 cur
->type
= TYPE_ITEM_MULTIPLE
;
956 cfg_add_child(node
, cur
);
957 cfg
->total_size
+= sizeof(config_node
) + strlen(key
);
960 if (node
->type
!= TYPE_ITEM_MULTIPLE
)
962 cur
= cfg_new_node();
963 cur
->type
= TYPE_ITEM
;
964 cur
->name
= g_strdup(id
);
965 cur
->value
= g_strdup(value
);
966 cfg
->total_size
+= sizeof(config_node
) + strlen(id
) + strlen(value
);;
967 cfg_add_child(node
, cur
);
968 cfg_save_delayed(cfg
);
970 /* g_mutex_unlock(cfg->lock);*/
974 conf_mult_obj
*cfg_get_multiple_as_string(config_obj
* cfg
, const char *class, const char *key
)
976 conf_mult_obj
*list
= NULL
;
977 config_node
*cur
= NULL
;
978 /* g_mutex_lock(cfg->lock);*/
979 cur
= cfg_get_single_value(cfg
, class, NULL
, NULL
, key
);
980 if (cur
&& cur
->type
== TYPE_ITEM_MULTIPLE
&& cur
->children
!= NULL
)
984 while (cur
->prev
!= NULL
)
988 conf_mult_obj
*temp
= g_slice_new0(conf_mult_obj
);
989 temp
->value
= g_strdup(cur
->value
);
990 temp
->key
= g_strdup(cur
->name
);
993 temp
->next
->prev
= temp
;
996 } while (cur
!= NULL
);
998 /* g_mutex_unlock(cfg->lock);*/
1003 void cfg_free_multiple(conf_mult_obj
* data
)
1005 conf_mult_obj
*list
= data
;
1009 while (list
->prev
!= NULL
)
1013 while (list
!= NULL
)
1016 cfg_free_string(list
->value
);
1018 cfg_free_string(list
->key
);
1019 if (list
->next
!= NULL
)
1022 g_slice_free(conf_mult_obj
, list
->prev
);
1026 g_slice_free(conf_mult_obj
, list
->prev
);
1027 g_slice_free(conf_mult_obj
, list
);
1034 conf_mult_obj
*cfg_get_class_list(config_obj
* data
)
1036 conf_mult_obj
*list
= NULL
;
1037 config_node
*root
= NULL
;
1042 /* g_mutex_lock(data->lock);*/
1044 while (root
->prev
!= NULL
)
1048 if (root
->type
== TYPE_CATEGORY
)
1050 conf_mult_obj
*temp
= g_slice_new0(conf_mult_obj
);
1052 temp
->key
= g_strdup(root
->name
);
1055 temp
->next
->prev
= temp
;
1059 } while (root
!= NULL
);
1060 while (list
->prev
!= NULL
)
1062 /* g_mutex_unlock(data->lock);*/
1068 conf_mult_obj
*cfg_get_key_list(config_obj
* data
, const char *class)
1070 conf_mult_obj
*list
= NULL
;
1071 config_node
*root
= NULL
;
1074 if (data
->root
== NULL
)
1076 /* g_mutex_lock(data->lock);*/
1077 root
= cfg_get_class(data
, class);
1078 if (!root
|| !root
->children
)
1080 /* g_mutex_unlock(data->lock);*/
1083 root
= root
->children
;
1084 while (root
->prev
!= NULL
)
1088 if (root
->type
== TYPE_ITEM
)
1090 conf_mult_obj
*temp
= g_slice_new0(conf_mult_obj
);
1091 temp
->value
= g_strdup(root
->value
);
1092 temp
->key
= g_strdup(root
->name
);
1095 temp
->next
->prev
= temp
;
1099 } while (root
!= NULL
);
1100 while (list
&& list
->prev
!= NULL
)
1102 /* g_mutex_unlock(data->lock);*/
1107 static void __int_cfg_do_special_cleanup(config_obj
* cfg
, config_node
* node
)
1109 config_node
*item
, *root
= NULL
;
1110 if (!cfg
|| !cfg
->root
)
1120 if (root
->type
== TYPE_CATEGORY
)
1123 __int_cfg_do_special_cleanup(cfg
, root
->children
);
1124 if (root
->children
== NULL
)
1129 else if (root
->next
)
1131 __int_cfg_remove_node(cfg
, root
);
1135 } else if (root
->type
== TYPE_ITEM
)
1137 if (root
->value
== NULL
|| root
->value
[0] == '\0' || strlen(root
->value
) == 0)
1139 config_node
*inode
= root
;
1143 __int_cfg_remove_node(cfg
, inode
);
1154 void cfg_do_special_cleanup(config_obj
* cfg
)
1156 if (!cfg
|| !cfg
->root
)
1159 /* g_mutex_lock(cfg->lock);*/
1160 __int_cfg_do_special_cleanup(cfg
, NULL
);
1161 cfg_save_delayed(cfg
);
1162 /* g_mutex_unlock(cfg->lock);*/
1167 * Full api for use with metadata
1173 void cfg_set_single_value_as_string_mm(config_obj
* cfg
, const char *class, const char *sclass
, const char *ssclass
,
1174 const char *key
, const char *value
)
1176 /* g_mutex_lock(cfg->lock);*/
1177 __int_cfg_set_single_value_as_string(cfg
, class, sclass
, ssclass
, key
, value
);
1178 /* g_mutex_unlock(cfg->lock);*/
1182 char *cfg_get_single_value_as_string_mm(config_obj
* cfg
, const char *class, const char *sclass
, const char *ssclass
,
1186 /* g_mutex_lock(cfg->lock);*/
1187 retv
= __int_cfg_get_single_value_as_string(cfg
, class, sclass
, ssclass
, key
);
1188 /* g_mutex_unlock(cfg->lock);*/
1193 char *cfg_get_single_value_as_string_with_default_mm(config_obj
* cfg
, const char *class, const char *sclass
,
1194 const char *ssclass
, const char *key
, const char *def
)
1197 /* g_mutex_lock(cfg->lock);*/
1198 retv
= __int_cfg_get_single_value_as_string(cfg
, class, sclass
, ssclass
, key
);
1201 __int_cfg_set_single_value_as_string(cfg
, class, sclass
, ssclass
, key
, def
);
1202 retv
= __int_cfg_get_single_value_as_string(cfg
, class, sclass
, ssclass
, key
);
1204 /* g_mutex_unlock(cfg->lock);*/
1212 void cfg_set_single_value_as_int_mm(config_obj
* cfg
, const char *class, const char *sclass
, const char *ssclass
,
1213 const char *key
, int value
)
1216 /* g_mutex_lock(cfg->lock);*/
1217 temp
= g_strdup_printf("%i", value
);
1218 __int_cfg_set_single_value_as_string(cfg
, class, sclass
, ssclass
, key
, temp
);
1219 cfg_free_string(temp
);
1220 /* g_mutex_unlock(cfg->lock);*/
1224 int cfg_get_single_value_as_int_with_default_mm(config_obj
* cfg
, const char *class, const char *sclass
,
1225 const char *ssclass
, const char *key
, int def
)
1227 int retv
= CFG_INT_NOT_DEFINED
;
1228 /* g_mutex_lock(cfg->lock); */
1229 retv
= __int_cfg_get_single_value_as_int_mm(cfg
, class, sclass
, ssclass
, key
);
1230 if (retv
== CFG_INT_NOT_DEFINED
)
1232 __int_cfg_set_single_value_as_int(cfg
, class, sclass
, ssclass
, key
, def
);
1233 retv
= __int_cfg_get_single_value_as_int_mm(cfg
, class, sclass
, ssclass
, key
);
1235 /* g_mutex_unlock(cfg->lock); */
1240 static void cfg_save_delayed(config_obj
* cfg
)
1242 if (cfg
->save_timeout
)
1244 g_source_remove(cfg
->save_timeout
);
1245 cfg
->save_timeout
= 0;
1247 cfg
->save_timeout
= g_timeout_add_seconds(5, (GSourceFunc
) cfg_save_real
, cfg
);