added log file
[psensor.git] / src / main.c
1 /*
2     Copyright (C) 2010-2011 jeanfi@gmail.com
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU 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 <locale.h>
21
22 #include <getopt.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <sys/stat.h>
28 #include <sys/types.h>
29
30 #include <gtk/gtk.h>
31
32 #include "config.h"
33
34 #include "cfg.h"
35 #include "psensor.h"
36 #include "graph.h"
37 #include "ui.h"
38 #include "ui_sensorlist.h"
39 #include "ui_color.h"
40 #include "lmsensor.h"
41 #include "ui_pref.h"
42 #include "ui_graph.h"
43
44 #ifdef HAVE_UNITY
45 #include "ui_unity.h"
46 #endif
47
48 #ifdef HAVE_NVIDIA
49 #include "nvidia.h"
50 #endif
51
52 #ifdef HAVE_LIBATIADL
53 #include "amd.h"
54 #endif
55
56 #ifdef HAVE_REMOTE_SUPPORT
57 #include "rsensor.h"
58 #endif
59
60 #if defined(HAVE_APPINDICATOR) || defined(HAVE_APPINDICATOR_029)
61 #include "ui_appindicator.h"
62 #endif
63
64 #ifdef HAVE_LIBNOTIFY
65 #include "ui_notify.h"
66 #endif
67
68 #ifdef HAVE_GTOP
69 #include "cpu.h"
70 #endif
71
72 #include "compat.h"
73
74 static const char *program_name;
75
76 void print_version()
77 {
78         printf("psensor %s\n", VERSION);
79         printf(_("Copyright (C) %s jeanfi@gmail.com\n\
80 License GPLv2: GNU GPL version 2 or later \
81 <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>\n\
82 This is free software: you are free to change and redistribute it.\n\
83 There is NO WARRANTY, to the extent permitted by law.\n"),
84                "2010-2011");
85 }
86
87 void print_help()
88 {
89         printf(_("Usage: %s [OPTION]...\n"), program_name);
90
91         puts(_("psensor is a GTK application for monitoring hardware sensors, "
92                "including temperatures and fan speeds."));
93
94         puts("");
95         puts(_("Options:"));
96         puts(_("\
97   -h, --help          display this help and exit\n\
98   -v, --version       display version information and exit"));
99
100         puts("");
101
102         puts(_("\
103   -u, --url=URL       \
104 the URL of the psensor-server, example: http://hostname:3131"));
105
106         puts("");
107
108         printf(_("Report bugs to: %s\n"), PACKAGE_BUGREPORT);
109         puts("");
110         printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
111 }
112
113 /*
114   Updates the size of the sensor values if different than the
115   configuration.
116  */
117 void
118 update_psensor_values_size(struct psensor **sensors, struct config *cfg)
119 {
120         struct psensor **cur;
121
122         cur = sensors;
123         while (*cur) {
124                 struct psensor *s = *cur;
125
126                 if (s->values_max_length != cfg->sensor_values_max_length)
127                         psensor_values_resize(s,
128                                               cfg->sensor_values_max_length);
129
130                 cur++;
131         }
132 }
133
134 void update_psensor_measures(struct ui_psensor *ui)
135 {
136         struct psensor **sensors = ui->sensors;
137         struct config *cfg = ui->config;
138
139         while (1) {
140                 g_mutex_lock(ui->sensors_mutex);
141
142                 if (!sensors)
143                         return;
144
145                 update_psensor_values_size(sensors, ui->config);
146
147                 psensor_list_update_measures(sensors);
148 #ifdef HAVE_REMOTE_SUPPORT
149                 remote_psensor_list_update(sensors);
150 #endif
151 #ifdef HAVE_NVIDIA
152                 nvidia_psensor_list_update(sensors);
153 #endif
154 #ifdef HAVE_LIBATIADL
155                 amd_psensor_list_update(sensors);
156 #endif
157                 g_mutex_unlock(ui->sensors_mutex);
158
159                 sleep(cfg->sensor_update_interval);
160         }
161 }
162
163 gboolean ui_refresh_thread(gpointer data)
164 {
165         struct config *cfg;
166         gboolean ret;
167         struct ui_psensor *ui = (struct ui_psensor *)data;
168
169         ret = TRUE;
170         cfg = ui->config;
171
172         g_mutex_lock(ui->sensors_mutex);
173
174         graph_update(ui->sensors, ui->w_graph, ui->config);
175
176         ui_sensorlist_update(ui);
177
178 #if defined(HAVE_APPINDICATOR) || defined(HAVE_APPINDICATOR_029)
179         ui_appindicator_update(ui);
180 #endif
181
182 #ifdef HAVE_UNITY
183         ui_unity_launcher_entry_update(ui->sensors,
184                                        !cfg->unity_launcher_count_disabled);
185 #endif
186
187         if (ui->graph_update_interval != cfg->graph_update_interval) {
188                 ui->graph_update_interval = cfg->graph_update_interval;
189                 ret = FALSE;
190         }
191
192         g_mutex_unlock(ui->sensors_mutex);
193
194         if (ret == FALSE)
195                 g_timeout_add(1000 * ui->graph_update_interval,
196                               ui_refresh_thread, ui);
197
198         return ret;
199 }
200
201 void cb_alarm_raised(struct psensor *sensor, void *data)
202 {
203 #ifdef HAVE_LIBNOTIFY
204         if (sensor->enabled)
205                 ui_notify(sensor, (struct ui_psensor *)data);
206 #endif
207 }
208
209 static void associate_colors(struct psensor **sensors)
210 {
211         /* number of uniq colors */
212 #define COLORS_COUNT 8
213
214         unsigned int colors[COLORS_COUNT][3] = {
215                 {0x0000, 0x0000, 0x0000},       /* black */
216                 {0xffff, 0x0000, 0x0000},       /* red */
217                 {0x0000, 0.0000, 0xffff},       /* blue */
218                 {0x0000, 0xffff, 0x0000},       /* green */
219
220                 {0x7fff, 0x7fff, 0x7fff},       /* grey */
221                 {0x7fff, 0x0000, 0x0000},       /* dark red */
222                 {0x0000, 0x0000, 0x7fff},       /* dark blue */
223                 {0x0000, 0x7fff, 0x0000}        /* dark green */
224         };
225
226         struct psensor **sensor_cur = sensors;
227         int i = 0;
228         while (*sensor_cur) {
229                 struct color default_color;
230                 color_set(&default_color,
231                           colors[i % COLORS_COUNT][0],
232                           colors[i % COLORS_COUNT][1],
233                           colors[i % COLORS_COUNT][2]);
234
235                 (*sensor_cur)->color
236                     = config_get_sensor_color((*sensor_cur)->id,
237                                               &default_color);
238
239                 sensor_cur++;
240                 i++;
241         }
242 }
243
244 static void
245 associate_cb_alarm_raised(struct psensor **sensors, struct ui_psensor *ui)
246 {
247         struct psensor **sensor_cur = sensors;
248         while (*sensor_cur) {
249                 struct psensor *s = *sensor_cur;
250
251                 s->cb_alarm_raised = cb_alarm_raised;
252                 s->cb_alarm_raised_data = ui;
253
254                 if (is_temp_type(s->type)) {
255                         s->alarm_limit
256                             = config_get_sensor_alarm_limit(s->id, 60);
257                         s->alarm_enabled
258                             = config_get_sensor_alarm_enabled(s->id);
259                 } else {
260                         s->alarm_limit = 0;
261                         s->alarm_enabled = 0;
262                 }
263
264                 sensor_cur++;
265         }
266 }
267
268 static void associate_preferences(struct psensor **sensors)
269 {
270         struct psensor **sensor_cur = sensors;
271         while (*sensor_cur) {
272                 char *n;
273                 struct psensor *s = *sensor_cur;
274
275                 s->enabled = config_is_sensor_enabled(s->id);
276
277                 n = config_get_sensor_name(s->id);
278
279                 if (n)
280                         s->name = n;
281
282                 sensor_cur++;
283         }
284 }
285
286 static void log_init()
287 {
288         char *home, *path, *dir;
289
290         home = getenv("HOME");
291
292         if (!home)
293                 return ;
294
295         dir = malloc(strlen(home)+1+strlen(".psensor")+1);
296         sprintf(dir, "%s/%s", home, ".psensor");
297         mkdir(dir, 0777);
298
299         path = malloc(strlen(dir)+1+strlen("log")+1);
300         sprintf(path, "%s/%s", dir, "log");
301
302         log_open(path, LOG_INFO);
303
304         free(dir);
305         free(path);
306 }
307
308 static struct option long_options[] = {
309         {"version", no_argument, 0, 'v'},
310         {"help", no_argument, 0, 'h'},
311         {"url", required_argument, 0, 'u'},
312         {0, 0, 0, 0}
313 };
314
315 int main(int argc, char **argv)
316 {
317         struct ui_psensor ui;
318         GError *error;
319         GThread *thread;
320         int optc;
321         char *url = NULL;
322         int cmdok = 1;
323
324         program_name = argv[0];
325
326         setlocale(LC_ALL, "");
327
328 #if ENABLE_NLS
329         bindtextdomain(PACKAGE, LOCALEDIR);
330         textdomain(PACKAGE);
331 #endif
332
333         while ((optc = getopt_long(argc, argv, "vhu:", long_options,
334                                    NULL)) != -1) {
335                 switch (optc) {
336                 case 'u':
337                         if (optarg)
338                                 url = strdup(optarg);
339                         break;
340                 case 'h':
341                         print_help();
342                         exit(EXIT_SUCCESS);
343                 case 'v':
344                         print_version();
345                         exit(EXIT_SUCCESS);
346                 default:
347                         cmdok = 0;
348                         break;
349                 }
350         }
351
352         if (!cmdok || optind != argc) {
353                 fprintf(stderr, _("Try `%s --help' for more information.\n"),
354                         program_name);
355                 exit(EXIT_FAILURE);
356         }
357
358         log_init();
359
360         g_thread_init(NULL);
361         gdk_threads_init();
362         /* gdk_threads_enter(); */
363
364         gtk_init(NULL, NULL);
365
366 #ifdef HAVE_LIBNOTIFY
367         ui.notification_last_time = NULL;
368 #endif
369
370         ui.sensors_mutex = g_mutex_new();
371
372         config_init();
373
374         ui.config = config_load();
375
376         psensor_init();
377
378         if (url) {
379 #ifdef HAVE_REMOTE_SUPPORT
380                 rsensor_init();
381                 ui.sensors = get_remote_sensors(url, 600);
382 #else
383                 fprintf(stderr,
384                         _("ERROR: Not compiled with remote sensor support.\n"));
385                 exit(EXIT_FAILURE);
386 #endif
387         } else {
388                 ui.sensors = get_all_sensors(600);
389 #ifdef HAVE_NVIDIA
390                 ui.sensors = nvidia_psensor_list_add(ui.sensors, 600);
391 #endif
392 #ifdef HAVE_LIBATIADL
393                 ui.sensors = amd_psensor_list_add(ui.sensors, 600);
394 #endif
395 #ifdef HAVE_GTOP
396                 ui.sensors = cpu_psensor_list_add(ui.sensors, 600);
397 #endif
398         }
399
400         associate_preferences(ui.sensors);
401         associate_colors(ui.sensors);
402         associate_cb_alarm_raised(ui.sensors, &ui);
403
404         /* main window */
405         ui_window_create(&ui);
406         ui.sensor_box = NULL;
407
408         /* drawing box */
409         ui.w_graph = ui_graph_create(&ui);
410
411         /* sensor list */
412         ui_sensorlist_create(&ui);
413
414         ui_window_update(&ui);
415
416         thread = g_thread_create((GThreadFunc) update_psensor_measures,
417                                  &ui, TRUE, &error);
418
419         if (!thread)
420                 g_error_free(error);
421
422         ui.graph_update_interval = ui.config->graph_update_interval;
423
424         g_timeout_add(1000 * ui.graph_update_interval, ui_refresh_thread, &ui);
425
426 #if defined(HAVE_APPINDICATOR) || defined(HAVE_APPINDICATOR_029)
427         ui_appindicator_init(&ui);
428 #endif
429
430         /* main loop */
431         gtk_main();
432
433         g_mutex_lock(ui.sensors_mutex);
434
435         psensor_cleanup();
436
437 #ifdef HAVE_NVIDIA
438         nvidia_cleanup();
439 #endif
440 #ifdef HAVE_LIBATIADL
441         amd_cleanup();
442 #endif
443
444         psensor_list_free(ui.sensors);
445         ui.sensors = NULL;
446
447         g_mutex_unlock(ui.sensors_mutex);
448
449         config_cleanup();
450
451         log_close();
452
453         return 0;
454 }