start working on gsettings support (int/float/bool properties)
[psensor.git] / src / cfg.c
1 /*
2  * Copyright (C) 2010-2014 jeanfi@gmail.com
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301 USA
18  */
19
20 #include <errno.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <ctype.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27
28 #include <locale.h>
29 #include <libintl.h>
30 #define _(str) gettext(str)
31
32 #include <gio/gio.h>
33
34 #include <cfg.h>
35 #include <pio.h>
36 #include <plog.h>
37
38 /* Properties of each sensor */
39 static const char *ATT_SENSOR_ALARM_ENABLED = "alarm_enabled";
40 static const char *ATT_SENSOR_ALARM_HIGH_THRESHOLD = "alarm_high_threshold";
41 static const char *ATT_SENSOR_ALARM_LOW_THRESHOLD = "alarm_low_threshold";
42 static const char *ATT_SENSOR_COLOR = "color";
43 static const char *ATT_SENSOR_GRAPH_ENABLED = "graph_enabled";
44 static const char *ATT_SENSOR_NAME = "name";
45 static const char *ATT_SENSOR_APPINDICATOR_MENU_DISABLED
46 = "appindicator_menu_disabled";
47 static const char *ATT_SENSOR_APPINDICATOR_LABEL_ENABLED
48 = "appindicator_label_enabled";
49 static const char *ATT_SENSOR_POSITION = "position";
50
51 /* Update interval of the measures of the sensors */
52 static const char *KEY_SENSOR_UPDATE_INTERVAL
53 = "/apps/psensor/sensor/update_interval";
54
55 /* Graph settings */
56 static const char *KEY_GRAPH_UPDATE_INTERVAL = "graph-update-interval";
57
58 static const char *KEY_GRAPH_MONITORING_DURATION = "graph-monitoring-duration";
59
60 static const char *KEY_GRAPH_BACKGROUND_COLOR
61 = "/apps/psensor/graph/background_color";
62
63 static const char *DEFAULT_GRAPH_BACKGROUND_COLOR = "#e8f4e8f4a8f5";
64
65 static const char *KEY_GRAPH_BACKGROUND_ALPHA = "graph-background-alpha";
66
67 static const char *KEY_GRAPH_FOREGROUND_COLOR
68 = "/apps/psensor/graph/foreground_color";
69
70 static const char *DEFAULT_GRAPH_FOREGROUND_COLOR = "#000000000000";
71
72 static const char *KEY_ALPHA_CHANNEL_ENABLED = "graph-alpha-channel-enabled";
73
74 /* Inteface settings */
75 static const char *KEY_INTERFACE_SENSORLIST_POSITION
76 = "interface-sensorlist-position";
77
78 static const char *KEY_INTERFACE_WINDOW_DECORATION_DISABLED
79 = "interface-window-decoration-disabled";
80
81 static const char *KEY_INTERFACE_WINDOW_KEEP_BELOW_ENABLED
82 = "interface-window-keep-below-enabled";
83
84 static const char *KEY_INTERFACE_MENU_BAR_DISABLED
85 = "interface-menu-bar-disabled";
86
87 static const char *KEY_INTERFACE_UNITY_LAUNCHER_COUNT_DISABLED
88 = "interface-unity-launcher-count-disabled";
89
90 static const char *KEY_INTERFACE_HIDE_ON_STARTUP
91 = "interface-hide-on-startup";
92
93 static const char *KEY_INTERFACE_WINDOW_RESTORE_ENABLED
94 = "interface-window-restore-enabled";
95
96 static const char *KEY_INTERFACE_WINDOW_X = "interface-window-x";
97 static const char *KEY_INTERFACE_WINDOW_Y = "interface-window-y";
98 static const char *KEY_INTERFACE_WINDOW_W = "interface-window-w";
99 static const char *KEY_INTERFACE_WINDOW_H = "interface-window-h";
100
101 static const char *KEY_INTERFACE_WINDOW_DIVIDER_POS
102 = "interface-window-divider-pos";
103
104 static const char *KEY_INTERFACE_TEMPERATURE_UNIT
105 = "interface-temperature-unit";
106
107 /* Sensor logging settings */
108 static const char *KEY_SLOG_ENABLED = "/apps/psensor/slog/enabled";
109 static const char *KEY_SLOG_INTERVAL = "/apps/psensor/slog/interval";
110
111 /* Path to the script called when a notification is raised */
112 static const char *KEY_NOTIFICATION_SCRIPT = "/apps/psensor/notif_script";
113
114 static GConfClient *client;
115 static GSettings *settings;
116
117 static char *user_dir;
118
119 static GKeyFile *key_file;
120
121 static char *sensor_config_path;
122
123 static char *get_string(const char *key, const char *default_value)
124 {
125         char *value;
126
127         value = gconf_client_get_string(client, key, NULL);
128
129         if (!value) {
130                 value = strdup(default_value);
131                 gconf_client_set_string(client, key, default_value, NULL);
132         }
133
134         return value;
135 }
136
137 static void set_bool(const char *k, bool b)
138 {
139         g_settings_set_boolean(settings, k, b);
140 }
141
142 static bool get_bool(const char *k)
143 {
144         return g_settings_get_boolean(settings, k);
145 }
146
147 static void set_int(const char *k, int i)
148 {
149         g_settings_set_int(settings, k, i);
150 }
151
152 static double get_double(const char *k)
153 {
154         return g_settings_get_double(settings, k);
155 }
156
157 static void set_double(const char *k, double d)
158 {
159         g_settings_set_double(settings, k, d);
160 }
161
162 static int get_int(const char *k)
163 {
164         return g_settings_get_int(settings, k);
165 }
166
167 char *config_get_notif_script()
168 {
169         char *str;
170
171         str =  gconf_client_get_string(client, KEY_NOTIFICATION_SCRIPT, NULL);
172         if (str && !strlen(str)) {
173                 free(str);
174                 str = NULL;
175         }
176
177         return str;
178 }
179
180 void config_set_notif_script(const char *str)
181 {
182         if (str && strlen(str) > 0)
183                 gconf_client_set_string(client,
184                                         KEY_NOTIFICATION_SCRIPT, str, NULL);
185         else
186                 gconf_client_set_string(client,
187                                         KEY_NOTIFICATION_SCRIPT, "", NULL);
188 }
189
190 static struct color *get_background_color()
191 {
192         char *scolor;
193         struct color *c;
194
195         scolor = get_string(KEY_GRAPH_BACKGROUND_COLOR,
196                             DEFAULT_GRAPH_BACKGROUND_COLOR);
197
198         c = str_to_color(scolor);
199         free(scolor);
200
201         if (!c)
202                 return color_new(0xffff, 0xffff, 0xffff);
203
204         return c;
205 }
206
207 static struct color *get_foreground_color()
208 {
209         char *scolor;
210         struct color *c;
211
212         scolor = get_string(KEY_GRAPH_FOREGROUND_COLOR,
213                             DEFAULT_GRAPH_FOREGROUND_COLOR);
214
215         c = str_to_color(scolor);
216         free(scolor);
217
218         if (!c)
219                 return color_new(0x0000, 0x0000, 0x0000);
220
221         return c;
222 }
223
224 static bool is_alpha_channel_enabled()
225 {
226         return get_bool(KEY_ALPHA_CHANNEL_ENABLED);
227 }
228
229 static void set_alpha_channeld_enabled(bool b)
230 {
231         set_bool(KEY_ALPHA_CHANNEL_ENABLED, b);
232 }
233
234 static enum sensorlist_position get_sensorlist_position()
235 {
236         return get_int(KEY_INTERFACE_SENSORLIST_POSITION);
237 }
238
239 static void set_sensorlist_position(enum sensorlist_position pos)
240 {
241         set_int(KEY_INTERFACE_SENSORLIST_POSITION, pos);
242 }
243
244 static double get_graph_background_alpha()
245 {
246         return get_double(KEY_GRAPH_BACKGROUND_ALPHA);
247 }
248
249 static void set_graph_background_alpha(double alpha)
250 {
251         set_double(KEY_GRAPH_BACKGROUND_ALPHA, alpha);
252 }
253
254 static void set_background_color(const struct color *color)
255 {
256         char *scolor;
257
258         scolor = color_to_str(color);
259         if (!scolor)
260                 scolor = strdup(DEFAULT_GRAPH_BACKGROUND_COLOR);
261
262         gconf_client_set_string(client,
263                                 KEY_GRAPH_BACKGROUND_COLOR, scolor, NULL);
264
265         free(scolor);
266 }
267
268 static void set_foreground_color(const struct color *color)
269 {
270         char *str;
271
272         str = color_to_str(color);
273         if (!str)
274                 str = strdup(DEFAULT_GRAPH_FOREGROUND_COLOR);
275
276         gconf_client_set_string(client, KEY_GRAPH_FOREGROUND_COLOR, str, NULL);
277
278         free(str);
279 }
280
281 bool is_slog_enabled()
282 {
283         return gconf_client_get_bool(client, KEY_SLOG_ENABLED, NULL);
284 }
285
286 static void set_slog_enabled(bool enabled)
287 {
288         gconf_client_set_bool(client, KEY_SLOG_ENABLED, enabled, NULL);
289 }
290
291 void config_slog_enabled_notify_add(GConfClientNotifyFunc cbk, void *data)
292 {
293         log_debug("config_slog_enabled_notify_add");
294         gconf_client_add_dir(client,
295                              KEY_SLOG_ENABLED,
296                              GCONF_CLIENT_PRELOAD_NONE,
297                              NULL);
298         gconf_client_notify_add(client,
299                                 KEY_SLOG_ENABLED,
300                                 cbk,
301                                 data,
302                                 NULL,
303                                 NULL);
304 }
305
306 int config_get_slog_interval()
307 {
308         int res;
309
310         res = gconf_client_get_int(client, KEY_SLOG_INTERVAL, NULL);
311
312         if (res <= 0)
313                 return 300;
314         else
315                 return res;
316 }
317
318 static void set_slog_interval(int interval)
319 {
320         if (interval <= 0)
321                 interval = 300;
322
323         gconf_client_set_int(client, KEY_SLOG_INTERVAL, interval, NULL);
324 }
325
326 static bool is_window_decoration_enabled()
327 {
328         return !get_bool(KEY_INTERFACE_WINDOW_DECORATION_DISABLED);
329 }
330
331 static bool is_window_keep_below_enabled()
332 {
333         return get_bool(KEY_INTERFACE_WINDOW_KEEP_BELOW_ENABLED);
334 }
335
336 static void set_window_decoration_enabled(bool enabled)
337 {
338         set_bool(KEY_INTERFACE_WINDOW_DECORATION_DISABLED, !enabled);
339 }
340
341 static void set_window_keep_below_enabled(bool enabled)
342 {
343         set_bool(KEY_INTERFACE_WINDOW_KEEP_BELOW_ENABLED, enabled);
344 }
345
346 /*
347  * Initializes the GConf client.
348  */
349 static void init()
350 {
351         if (!client)
352                 client = gconf_client_get_default();
353
354         if (!settings)
355                 settings = g_settings_new("psensor");
356 }
357
358 void config_cleanup()
359 {
360         config_sync();
361
362         if (client) {
363                 g_object_unref(client);
364                 client = NULL;
365         }
366
367         if (settings) {
368                 g_settings_sync();
369                 g_object_unref(settings);
370                 settings = NULL;
371         }
372
373         if (user_dir) {
374                 free(user_dir);
375                 user_dir = NULL;
376         }
377
378         if (key_file) {
379                 g_key_file_free(key_file);
380                 key_file = NULL;
381         }
382
383         if (sensor_config_path) {
384                 free(sensor_config_path);
385                 sensor_config_path = NULL;
386         }
387 }
388
389 struct config *config_load()
390 {
391         struct config *c;
392
393         init();
394
395         c = malloc(sizeof(struct config));
396
397         c->graph_bgcolor = get_background_color();
398         c->graph_fgcolor = get_foreground_color();
399         c->graph_bg_alpha = get_graph_background_alpha();
400         c->alpha_channel_enabled = is_alpha_channel_enabled();
401         c->sensorlist_position = get_sensorlist_position();
402         c->window_decoration_enabled = is_window_decoration_enabled();
403         c->window_keep_below_enabled = is_window_keep_below_enabled();
404         c->slog_enabled = is_slog_enabled();
405         c->slog_interval = config_get_slog_interval();
406
407         c->sensor_update_interval
408             = gconf_client_get_int(client, KEY_SENSOR_UPDATE_INTERVAL, NULL);
409         if (c->sensor_update_interval < 1)
410                 c->sensor_update_interval = 1;
411
412         c->graph_update_interval = get_int(KEY_GRAPH_UPDATE_INTERVAL);
413         if (c->graph_update_interval < 1)
414                 c->graph_update_interval = 1;
415
416         c->graph_monitoring_duration = get_int(KEY_GRAPH_MONITORING_DURATION);
417
418         if (c->graph_monitoring_duration < 1)
419                 c->graph_monitoring_duration = 10;
420
421         c->sensor_values_max_length
422             = (c->graph_monitoring_duration * 60) / c->sensor_update_interval;
423
424         if (c->sensor_values_max_length < 3)
425                 c->sensor_values_max_length = 3;
426
427         c->menu_bar_disabled = get_bool(KEY_INTERFACE_MENU_BAR_DISABLED);
428
429         c->unity_launcher_count_disabled
430                 = get_bool(KEY_INTERFACE_UNITY_LAUNCHER_COUNT_DISABLED);
431
432         c->hide_on_startup = get_bool(KEY_INTERFACE_HIDE_ON_STARTUP);
433
434         c->window_restore_enabled
435                 = get_bool(KEY_INTERFACE_WINDOW_RESTORE_ENABLED);
436
437         c->window_x = get_int(KEY_INTERFACE_WINDOW_X);
438         c->window_y = get_int(KEY_INTERFACE_WINDOW_Y);
439         c->window_w = get_int(KEY_INTERFACE_WINDOW_W);
440         c->window_h = get_int(KEY_INTERFACE_WINDOW_H);
441
442         c->window_divider_pos = get_int(KEY_INTERFACE_WINDOW_DIVIDER_POS);
443
444         if (!c->window_restore_enabled || !c->window_w || !c->window_h) {
445                 c->window_w = 800;
446                 c->window_h = 200;
447         }
448
449         c->temperature_unit = get_int(KEY_INTERFACE_TEMPERATURE_UNIT);
450
451         return c;
452 }
453
454 void config_save(const struct config *c)
455 {
456         set_alpha_channeld_enabled(c->alpha_channel_enabled);
457         set_background_color(c->graph_bgcolor);
458         set_foreground_color(c->graph_fgcolor);
459         set_graph_background_alpha(c->graph_bg_alpha);
460         set_sensorlist_position(c->sensorlist_position);
461         set_window_decoration_enabled(c->window_decoration_enabled);
462         set_window_keep_below_enabled(c->window_keep_below_enabled);
463         set_slog_enabled(c->slog_enabled);
464         set_slog_interval(c->slog_interval);
465
466         set_int(KEY_GRAPH_UPDATE_INTERVAL, c->graph_update_interval);
467
468         set_int(KEY_GRAPH_MONITORING_DURATION, c->graph_monitoring_duration);
469
470         gconf_client_set_int(client,
471                              KEY_SENSOR_UPDATE_INTERVAL,
472                              c->sensor_update_interval, NULL);
473
474         set_bool(KEY_INTERFACE_MENU_BAR_DISABLED, c->menu_bar_disabled);
475
476         set_bool(KEY_INTERFACE_UNITY_LAUNCHER_COUNT_DISABLED,
477                  c->unity_launcher_count_disabled);
478
479         set_bool(KEY_INTERFACE_HIDE_ON_STARTUP, c->hide_on_startup);
480
481         set_bool(KEY_INTERFACE_WINDOW_RESTORE_ENABLED,
482                  c->window_restore_enabled);
483
484         set_int(KEY_INTERFACE_WINDOW_X, c->window_x);
485         set_int(KEY_INTERFACE_WINDOW_Y, c->window_y);
486         set_int(KEY_INTERFACE_WINDOW_W, c->window_w);
487         set_int(KEY_INTERFACE_WINDOW_H, c->window_h);
488
489         set_int(KEY_INTERFACE_WINDOW_DIVIDER_POS, c->window_divider_pos);
490
491         set_int(KEY_INTERFACE_TEMPERATURE_UNIT, c->temperature_unit);
492 }
493
494 const char *get_psensor_user_dir()
495 {
496         const char *home;
497
498         log_fct_enter();
499
500         if (!user_dir) {
501                 home = getenv("HOME");
502
503                 if (!home)
504                         return NULL;
505
506                 user_dir = path_append(home, ".psensor");
507
508                 if (mkdir(user_dir, 0700) == -1 && errno != EEXIST) {
509                         log_err(_("Failed to create the directory %s: %s"),
510                                 user_dir,
511                                 strerror(errno));
512
513                         free(user_dir);
514                         user_dir = NULL;
515                 }
516         }
517
518         log_fct_exit();
519
520         return user_dir;
521 }
522
523 static const char *get_sensor_config_path()
524 {
525         const char *dir;
526
527         if (!sensor_config_path) {
528                 dir = get_psensor_user_dir();
529
530                 if (dir)
531                         sensor_config_path = path_append(dir, "psensor.cfg");
532         }
533
534         return sensor_config_path;
535 }
536
537 static GKeyFile *get_sensor_key_file()
538 {
539         int ret;
540         GError *err;
541         const char *path;
542
543         if (!key_file) {
544                 path = get_sensor_config_path();
545
546                 key_file = g_key_file_new();
547
548                 err = NULL;
549                 ret = g_key_file_load_from_file(key_file,
550                                                 path,
551                                                 G_KEY_FILE_KEEP_COMMENTS
552                                                 | G_KEY_FILE_KEEP_TRANSLATIONS,
553                                                 &err);
554
555                 if (!ret) {
556                         if (err->code == G_KEY_FILE_ERROR_NOT_FOUND) {
557                                 log_fct(_("The configuration file "
558                                           "does not exist."));
559                         } else {
560                                 log_err(_("Failed to parse configuration "
561                                           "file: %s"),
562                                         path);
563                         }
564                 }
565         }
566
567         return key_file;
568 }
569
570 static void save_sensor_key_file()
571 {
572         GKeyFile *kfile;
573         const char *path;
574         char *data;
575
576         log_fct_enter();
577
578         kfile = get_sensor_key_file();
579
580         data = g_key_file_to_data(kfile, NULL, NULL);
581
582         path = get_sensor_config_path();
583
584         if (!g_file_set_contents(path, data, -1, NULL))
585                 log_err(_("Failed to save configuration file %s."), path);
586
587         free(data);
588
589         log_fct_exit();
590 }
591
592 void config_sync()
593 {
594         log_fct_enter();
595         if (settings)
596                 g_settings_sync();
597         save_sensor_key_file();
598         log_fct_exit();
599 }
600
601 static void
602 sensor_set_str(const char *sid, const char *att, const char *str)
603 {
604         GKeyFile *kfile;
605
606         kfile = get_sensor_key_file();
607         g_key_file_set_string(kfile, sid, att, str);
608 }
609
610 static char *sensor_get_str(const char *sid, const char *att)
611 {
612         GKeyFile *kfile;
613
614         kfile = get_sensor_key_file();
615         return g_key_file_get_string(kfile, sid, att, NULL);
616 }
617
618 static bool sensor_get_bool(const char *sid, const char *att)
619 {
620         GKeyFile *kfile;
621
622         kfile = get_sensor_key_file();
623         return g_key_file_get_boolean(kfile, sid, att, NULL);
624 }
625
626 static void
627 sensor_set_bool(const char *sid, const char *att, bool enabled)
628 {
629         GKeyFile *kfile;
630
631         kfile = get_sensor_key_file();
632
633         g_key_file_set_boolean(kfile, sid, att, enabled);
634 }
635
636 static int sensor_get_int(const char *sid, const char *att)
637 {
638         GKeyFile *kfile;
639
640         kfile = get_sensor_key_file();
641         return g_key_file_get_integer(kfile, sid, att, NULL);
642 }
643
644 static void sensor_set_int(const char *sid, const char *att, int i)
645 {
646         GKeyFile *kfile;
647
648         kfile = get_sensor_key_file();
649
650         g_key_file_set_integer(kfile, sid, att, i);
651 }
652
653 char *config_get_sensor_name(const char *sid)
654 {
655         return sensor_get_str(sid, ATT_SENSOR_NAME);
656 }
657
658 void config_set_sensor_name(const char *sid, const char *name)
659 {
660         sensor_set_str(sid, ATT_SENSOR_NAME, name);
661 }
662
663 void config_set_sensor_color(const char *sid, const struct color *color)
664 {
665         char *scolor;
666
667         scolor = color_to_str(color);
668
669         sensor_set_str(sid, ATT_SENSOR_COLOR, scolor);
670
671         free(scolor);
672 }
673
674 struct color *
675 config_get_sensor_color(const char *sid, const struct color *dft)
676 {
677         char *scolor;
678         struct color *color;
679
680         scolor = sensor_get_str(sid, ATT_SENSOR_COLOR);
681
682         if (scolor)
683                 color = str_to_color(scolor);
684         else
685                 color = NULL;
686
687         if (!color) {
688                 color = color_new(dft->red, dft->green, dft->blue);
689                 config_set_sensor_color(sid, color);
690         }
691
692         free(scolor);
693
694         return color;
695 }
696
697 bool config_is_sensor_enabled(const char *sid)
698 {
699         return sensor_get_bool(sid, ATT_SENSOR_GRAPH_ENABLED);
700 }
701
702 void config_set_sensor_enabled(const char *sid, bool enabled)
703 {
704         sensor_set_bool(sid, ATT_SENSOR_GRAPH_ENABLED, enabled);
705 }
706
707 int config_get_sensor_alarm_high_threshold(const char *sid)
708 {
709         return sensor_get_int(sid, ATT_SENSOR_ALARM_HIGH_THRESHOLD);
710 }
711
712 void config_set_sensor_alarm_high_threshold(const char *sid, int threshold)
713 {
714         sensor_set_int(sid, ATT_SENSOR_ALARM_HIGH_THRESHOLD, threshold);
715 }
716
717 int config_get_sensor_alarm_low_threshold(const char *sid)
718 {
719         return sensor_get_int(sid, ATT_SENSOR_ALARM_LOW_THRESHOLD);
720 }
721
722 void config_set_sensor_alarm_low_threshold(const char *sid, int threshold)
723 {
724         sensor_set_int(sid, ATT_SENSOR_ALARM_LOW_THRESHOLD, threshold);
725 }
726
727 bool config_is_appindicator_enabled(const char *sid)
728 {
729         return !sensor_get_bool(sid, ATT_SENSOR_APPINDICATOR_MENU_DISABLED);
730 }
731
732 void config_set_appindicator_enabled(const char *sid, bool enabled)
733 {
734         return sensor_set_bool(sid,
735                                ATT_SENSOR_APPINDICATOR_MENU_DISABLED,
736                                !enabled);
737 }
738
739 int config_get_sensor_position(const char *sid)
740 {
741         return sensor_get_int(sid, ATT_SENSOR_POSITION);
742 }
743
744 void config_set_sensor_position(const char *sid, int pos)
745 {
746         return sensor_set_int(sid, ATT_SENSOR_POSITION, pos);
747 }
748
749 bool config_get_sensor_alarm_enabled(const char *sid)
750 {
751         return sensor_get_bool(sid, ATT_SENSOR_ALARM_ENABLED);
752 }
753
754 void config_set_sensor_alarm_enabled(const char *sid, bool enabled)
755 {
756         sensor_set_bool(sid, ATT_SENSOR_ALARM_ENABLED, enabled);
757 }
758
759 bool config_is_appindicator_label_enabled(const char *sid)
760 {
761         return sensor_get_bool(sid, ATT_SENSOR_APPINDICATOR_LABEL_ENABLED);
762 }
763
764 void config_set_appindicator_label_enabled(const char *sid, bool enabled)
765 {
766         sensor_set_bool(sid, ATT_SENSOR_APPINDICATOR_LABEL_ENABLED, enabled);
767 }