1 /* -*- mode: C; c-basic-offset: 2; indent-tabs-mode: nil; -*- */
2 /*
3  * Copyright (C) 2009-2011  Tiger Soldier
4  *
5  * This file is part of OSD Lyrics.
6  * OSD Lyrics is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * OSD Lyrics 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
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with OSD Lyrics.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 #include <assert.h>
20 #include <stdio.h>
21 #include <glib-object.h>
22 #include "config.h"
23 #include "ol_config.h"
24 #include "ol_config_property.h"
25 #include "ol_utils.h"
26 #include "ol_marshal.h"
27 #include "ol_debug.h"
28 
29 #define OL_CONFIG_GET_PRIVATE(obj)   (G_TYPE_INSTANCE_GET_PRIVATE \
30                                       ((obj),                     \
31                                        OL_TYPE_CONFIG,            \
32                                        OlConfigPrivate))
33 #define SAVE_SCHEDULE_TIME 5000
34 const char CONFIG_FILE_NAME[] = PACKAGE_NAME ".conf";
35 G_DEFINE_TYPE (OlConfig, ol_config, G_TYPE_OBJECT);
36 
37 static void ol_config_despose (GObject *obj);
38 static void ol_config_finalize (GObject *object);
39 static void ol_config_emit_change (OlConfig *config,
40                                    const char *group,
41                                    const char *name);
42 static OlConfig* ol_config_new (void);
43 static const char* ol_config_get_path (void);
44 static gboolean ol_config_real_save (OlConfig *config);
45 
46 static OlConfig* instance = NULL;
47 
48 typedef struct _OlConfigPrivate OlConfigPrivate;
49 
50 struct _OlConfigPrivate
51 {
52   GKeyFile *config;
53   guint save_timer;
54 };
55 
56 static void
ol_config_init(OlConfig * self)57 ol_config_init (OlConfig *self)
58 {
59   OlConfigPrivate *priv = OL_CONFIG_GET_PRIVATE (self);
60   priv->config = g_key_file_new ();
61   if (!g_key_file_load_from_file (priv->config, ol_config_get_path (),
62                                   G_KEY_FILE_KEEP_COMMENTS, NULL))
63   {
64   }
65   int i;
66   for (i = 0; i < ol_get_array_len (config_bool); i++)
67   {
68     if (!g_key_file_has_key (priv->config, config_bool[i].group, config_bool[i].name, NULL))
69     {
70       g_key_file_set_boolean (priv->config, config_bool[i].group, config_bool[i].name,
71                               config_bool[i].default_value);
72     }
73   }
74   for (i = 0; i < ol_get_array_len (config_int); i++)
75   {
76     if (!g_key_file_has_key (priv->config, config_int[i].group, config_int[i].name, NULL))
77     {
78       g_key_file_set_integer (priv->config, config_int[i].group, config_int[i].name,
79                               config_int[i].default_value);
80     }
81   }
82   for (i = 0; i < ol_get_array_len (config_double); i++)
83   {
84     if (!g_key_file_has_key (priv->config, config_double[i].group, config_double[i].name, NULL))
85     {
86       g_key_file_set_double (priv->config, config_double[i].group, config_double[i].name,
87                               config_double[i].default_value);
88     }
89   }
90   for (i = 0; i < ol_get_array_len (config_str); i++)
91   {
92     if (!g_key_file_has_key (priv->config, config_str[i].group, config_str[i].name, NULL))
93     {
94       g_key_file_set_string (priv->config, config_str[i].group, config_str[i].name,
95                               config_str[i].default_value);
96     }
97   }
98   for (i = 0; i < ol_get_array_len (config_str_list); i++)
99   {
100     ol_debugf ("%s\n", config_str_list[i].name);
101     if (!g_key_file_has_key (priv->config, config_str_list[i].group, config_str_list[i].name, NULL))
102     {
103       int len = 0;
104       if (config_str_list[i].len > 0)
105       {
106         len = config_str_list[i].len;
107       }
108       else
109       {
110         while (config_str_list[i].default_value[len] != NULL)
111           len++;
112       }
113       ol_debugf ("name:%s len:%d\n", config_str_list[i].name, len);
114       g_key_file_set_string_list (priv->config,
115                                   config_str_list[i].group,
116                                   config_str_list[i].name,
117                                   config_str_list[i].default_value,
118                                   len);
119     }
120   }
121   priv->save_timer = 0;
122 }
123 
124 static void
ol_config_class_init(OlConfigClass * klass)125 ol_config_class_init (OlConfigClass *klass)
126 {
127   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
128 
129 
130   ol_config_parent_class = g_type_class_peek_parent (klass);
131 
132   g_type_class_add_private (klass, sizeof (OlConfigPrivate));
133 
134   gobject_class->dispose = ol_config_despose;
135   gobject_class->finalize = ol_config_finalize;
136   /* initialize singals */
137   GType signal_type[2];
138   /* signal_type[0] = OL_TYPE_CONFIG; */
139   signal_type[0] = G_TYPE_STRING;
140   signal_type[1] = G_TYPE_STRING;
141   klass->signals[CHANGED] =
142     g_signal_newv ("changed",
143                    G_TYPE_FROM_CLASS (gobject_class),
144                    G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
145                    NULL /* closure */,
146                    NULL /* accumulator */,
147                    NULL /* accumulator data */,
148                    ol_marshal_VOID__STRING_STRING,
149                    G_TYPE_NONE /* return_type */,
150                    2     /* n_params */,
151                    signal_type  /* param_types */);
152   ol_debugf ("id of changed signal is: %d\n", klass->signals[CHANGED]);
153 }
154 
155 static void
ol_config_despose(GObject * obj)156 ol_config_despose (GObject *obj)
157 {
158   OlConfigPrivate *priv = OL_CONFIG_GET_PRIVATE (obj);
159   if (priv->config != NULL)
160   {
161     /* g_hash_table_destroy (priv->config); */
162     g_key_file_free (priv->config);
163     priv->config = NULL;
164   }
165   G_OBJECT_CLASS (ol_config_parent_class)->dispose (obj);
166 }
167 
168 static void
ol_config_finalize(GObject * object)169 ol_config_finalize (GObject *object)
170 {
171   OlConfigPrivate *priv = OL_CONFIG_GET_PRIVATE (OL_CONFIG (object));
172   if (priv->config != NULL)
173   {
174     g_key_file_free (priv->config);
175     priv->config = NULL;
176   }
177   G_OBJECT_CLASS (ol_config_parent_class)->finalize (object);
178 }
179 
180 static void
ol_config_emit_change(OlConfig * config,const char * group,const char * name)181 ol_config_emit_change (OlConfig *config,
182                        const char *group,
183                        const char *name)
184 {
185   int i;
186   GValue params[3] = {{0}, {0}, {0}};
187   g_value_init (&params[0], G_OBJECT_TYPE (config));
188   g_value_set_object (&params[0], G_OBJECT (config));
189   g_value_init (&params[1], G_TYPE_STRING);
190   g_value_set_string (&params[1], group);
191   g_value_init (&params[2], G_TYPE_STRING);
192   g_value_set_string (&params[2], name);
193   g_signal_emitv (params, OL_CONFIG_GET_CLASS (config)->signals[CHANGED],
194                   0, NULL);
195   for (i = 0; i < 3; i++)
196     g_value_reset (&params[i]);
197 }
198 
199 static OlConfig*
ol_config_new()200 ol_config_new ()
201 {
202   return g_object_new (OL_TYPE_CONFIG, NULL);
203 }
204 
205 OlConfig*
ol_config_get_instance()206 ol_config_get_instance ()
207 {
208   if (instance == NULL)
209   {
210     instance = ol_config_new ();
211     g_object_ref_sink (instance);
212   }
213   return instance;
214 }
215 
216 gboolean
ol_config_set_bool(OlConfig * config,const char * group,const char * name,gboolean value)217 ol_config_set_bool (OlConfig *config, const char *group, const char *name, gboolean value)
218 {
219   ol_assert_ret (config != NULL, FALSE);
220   ol_assert_ret (name != NULL, FALSE);
221   g_key_file_set_boolean (OL_CONFIG_GET_PRIVATE (config)->config, group, name, value);
222   ol_config_emit_change (config, group, name);
223   ol_config_save (config);
224   return TRUE;
225 }
226 
227 gboolean
ol_config_set_int_no_emit(OlConfig * config,const char * group,const char * name,int value)228 ol_config_set_int_no_emit (OlConfig *config,
229                            const char *group,
230                            const char *name,
231                            int value)
232 {
233   ol_assert_ret (config != NULL, FALSE);
234   ol_assert_ret (name != NULL && group != NULL, FALSE);
235   g_key_file_set_integer (OL_CONFIG_GET_PRIVATE (config)->config, group, name, value);
236   ol_config_save (config);
237   return TRUE;
238 }
239 
240 gboolean
ol_config_set_int(OlConfig * config,const char * group,const char * name,int value)241 ol_config_set_int (OlConfig *config, const char *group, const char *name, int value)
242 {
243   ol_assert_ret (config != NULL, FALSE);
244   ol_assert_ret (name != NULL && group != NULL, FALSE);
245   g_key_file_set_integer (OL_CONFIG_GET_PRIVATE (config)->config, group, name, value);
246   ol_config_emit_change (config, group, name);
247   ol_config_save (config);
248   return TRUE;
249 }
250 
251 gboolean
ol_config_set_double(OlConfig * config,const char * group,const char * name,double value)252 ol_config_set_double (OlConfig *config, const char *group, const char *name, double value)
253 {
254   ol_assert_ret (config != NULL, FALSE);
255   ol_assert_ret (name != NULL, FALSE);
256   g_key_file_set_double (OL_CONFIG_GET_PRIVATE (config)->config, group, name, value);
257   ol_config_emit_change (config, group, name);
258   ol_config_save (config);
259   return TRUE;
260 }
261 
262 gboolean
ol_config_set_string(OlConfig * config,const char * group,const char * name,const char * value)263 ol_config_set_string (OlConfig *config, const char *group, const char *name, const char* value)
264 {
265   ol_assert_ret (config != NULL, FALSE);
266   ol_assert_ret (name != NULL, FALSE);
267   g_key_file_set_string (OL_CONFIG_GET_PRIVATE (config)->config, group, name, value);
268   ol_config_emit_change (config, group, name);
269   ol_config_save (config);
270   return TRUE;
271 }
272 
273 gboolean
ol_config_set_str_list(OlConfig * config,const char * group,const char * name,const char ** value,gsize len)274 ol_config_set_str_list (OlConfig *config,
275                         const char *group,
276                         const char *name,
277                         const char **value,
278                         gsize len)
279 {
280   ol_assert_ret (config != NULL, FALSE);
281   ol_assert_ret (name != NULL, FALSE);
282   g_key_file_set_string_list (OL_CONFIG_GET_PRIVATE (config)->config, group, name, value, len);
283   ol_config_emit_change (config, group, name);
284   ol_config_save (config);
285   return TRUE;
286 }
287 
288 gboolean
ol_config_get_bool(OlConfig * config,const char * group,const char * name)289 ol_config_get_bool (OlConfig *config, const char *group, const char *name)
290 {
291   ol_assert_ret (config != NULL, 0);
292   ol_assert_ret (name != NULL, 0);
293   gboolean value = g_key_file_get_boolean (OL_CONFIG_GET_PRIVATE (config)->config,
294                                            group,
295                                            name,
296                                            NULL);
297   ol_debugf ("[%s]%s:%d\n", group, name, value);
298   return value;
299 }
300 
301 int
ol_config_get_int(OlConfig * config,const char * group,const char * name)302 ol_config_get_int (OlConfig *config, const char *group, const char *name)
303 {
304   ol_assert_ret (config != NULL, 0);
305   ol_assert_ret (name != NULL, 0);
306   gint value = g_key_file_get_integer (OL_CONFIG_GET_PRIVATE (config)->config,
307                                        group,
308                                        name,
309                                        NULL);
310   ol_debugf ("[%s]%s:%d\n", group, name, value);
311   return value;
312 }
313 
314 double
ol_config_get_double(OlConfig * config,const char * group,const char * name)315 ol_config_get_double (OlConfig *config, const char *group, const char *name)
316 {
317   ol_assert_ret (config != NULL, 0.0);
318   ol_assert_ret (name != NULL, 0.0);
319   double value = g_key_file_get_double (OL_CONFIG_GET_PRIVATE (config)->config,
320                                         group,
321                                         name,
322                                         NULL);
323   ol_debugf ("[%s]%s:%lf\n", group, name, value);
324   return value;
325 }
326 
327 char*
ol_config_get_string(OlConfig * config,const char * group,const char * name)328 ol_config_get_string (OlConfig *config, const char *group, const char *name)
329 {
330   ol_assert_ret (config != NULL, NULL);
331   ol_assert_ret (name != NULL, NULL);
332   char *value = g_key_file_get_string (OL_CONFIG_GET_PRIVATE (config)->config,
333                                         group,
334                                         name,
335                                         NULL);
336   ol_debugf ("[%s]%s:%s\n", group, name, value);
337   return value;
338 }
339 
340 char**
ol_config_get_str_list(OlConfig * config,const char * group,const char * name,gsize * len)341 ol_config_get_str_list (OlConfig *config,
342                         const char *group,
343                         const char *name,
344                         gsize *len)
345 {
346   ol_assert_ret (config != NULL, NULL);
347   ol_assert_ret (name != NULL, NULL);
348   char **value = g_key_file_get_string_list (OL_CONFIG_GET_PRIVATE (config)->config,
349                                              group,
350                                              name,
351                                              len,
352                                              NULL);
353   return value;
354 }
355 
356 const char*
ol_config_get_path()357 ol_config_get_path ()
358 {
359   static char* path = NULL;
360   if (path == NULL)
361   {
362     path = g_strdup_printf ("%s/%s/%s", g_get_user_config_dir (), PACKAGE_NAME, CONFIG_FILE_NAME);
363     ol_debugf ("config path: %s\n", path);
364     char *dir = g_strdup_printf ("%s/%s/", g_get_user_config_dir (), PACKAGE_NAME);
365     g_mkdir_with_parents (dir, 0755);
366     g_free (dir);
367   }
368   return path;
369 }
370 
371 void
ol_config_save(OlConfig * config)372 ol_config_save (OlConfig *config)
373 {
374   ol_assert (config != NULL);
375   OlConfigPrivate *priv = OL_CONFIG_GET_PRIVATE (config);
376   if (priv->save_timer != 0)
377     return;
378   priv->save_timer = g_timeout_add (SAVE_SCHEDULE_TIME,
379                                     (GSourceFunc) ol_config_real_save,
380                                     config);
381 }
382 
383 static gboolean
ol_config_real_save(OlConfig * config)384 ol_config_real_save (OlConfig *config)
385 {
386   ol_assert_ret (config != NULL, TRUE);
387   OlConfigPrivate *priv = OL_CONFIG_GET_PRIVATE (config);
388   gsize len;
389   char *file_content = g_key_file_to_data (priv->config, &len, NULL);
390   g_file_set_contents (ol_config_get_path (), file_content, len, NULL);
391   priv->save_timer = 0;
392   g_free (file_content);
393   return FALSE;
394 }
395 
396 void
ol_config_unload()397 ol_config_unload ()
398 {
399   if (instance == NULL)
400   {
401     OlConfigPrivate *priv = OL_CONFIG_GET_PRIVATE (instance);
402     if (priv->save_timer != 0)
403     {
404       ol_config_real_save (instance);
405       g_source_remove (priv->save_timer);
406       priv->save_timer = 0;
407     }
408     g_object_unref (instance);
409   }
410 }
411