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