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 (¶ms[0], G_OBJECT_TYPE (config));
188 g_value_set_object (¶ms[0], G_OBJECT (config));
189 g_value_init (¶ms[1], G_TYPE_STRING);
190 g_value_set_string (¶ms[1], group);
191 g_value_init (¶ms[2], G_TYPE_STRING);
192 g_value_set_string (¶ms[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 (¶ms[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