[SF#679]X11 library uses unsigned long as cardinal-32 data, not uint32_t.
[lxde/lxpanel.git] / plugins / thermal / thermal.c
CommitLineData
c03f7bd0
DK
1/**
2 * Thermal plugin to lxpanel
3 *
4 * Copyright (C) 2007 by Daniel Kesler <kesler.daniel@gmail.com>
b840f7cc 5 * 2014 by Andriy Grytsenko <andrej@rep.kiev.ua>
c03f7bd0
DK
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
9746f003
FC
22
23#include <sys/types.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <glib/gi18n.h>
27
28#include <string.h>
29
6adfd706 30#include "plugin.h"
9746f003 31#include "misc.h"
9746f003
FC
32
33#include "dbg.h"
34
266c072d
HG
35#define PROC_THERMAL_DIRECTORY "/proc/acpi/thermal_zone/" /* must be slash-terminated */
36#define PROC_THERMAL_TEMPF "temperature"
37#define PROC_THERMAL_TRIP "trip_points"
38#define PROC_TRIP_CRITICAL "critical (S5):"
9746f003 39
f990feeb
HG
40#define SYSFS_THERMAL_DIRECTORY "/sys/class/thermal/" /* must be slash-terminated */
41#define SYSFS_THERMAL_SUBDIR_PREFIX "thermal_zone"
266c072d
HG
42#define SYSFS_THERMAL_TEMPF "temp"
43#define SYSFS_THERMAL_TRIP "trip_point_0_temp"
44
b90ba1d1
HG
45#define MAX_NUM_SENSORS 10
46#define MAX_AUTOMATIC_CRITICAL_TEMP 150 /* in degrees Celsius */
47
06e29ce1
AG
48#if !GLIB_CHECK_VERSION(2, 40, 0)
49# define g_info(...) g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, __VA_ARGS__)
50#endif
51
13cf6185 52typedef gint (*GetTempFunc)(char const *);
266c072d
HG
53
54typedef struct thermal {
a7bd16a4 55 LXPanel *panel;
6adfd706 56 config_setting_t *settings;
9746f003 57 GtkWidget *namew;
bdecea07 58 GString *tip;
9746f003
FC
59 int warning1;
60 int warning2;
83af5cab 61 int not_custom_levels, auto_sensor;
9746f003
FC
62 char *sensor,
63 *str_cl_normal,
64 *str_cl_warning1,
65 *str_cl_warning2;
66 unsigned int timer;
67 GdkColor cl_normal,
68 cl_warning1,
69 cl_warning2;
b90ba1d1
HG
70 int numsensors;
71 char *sensor_array[MAX_NUM_SENSORS];
9fae7098 72 char *sensor_name[MAX_NUM_SENSORS];
13cf6185
AG
73 GetTempFunc get_temperature[MAX_NUM_SENSORS];
74 GetTempFunc get_critical[MAX_NUM_SENSORS];
bdecea07 75 gint temperature[MAX_NUM_SENSORS];
4a4374a0 76 gint critical[MAX_NUM_SENSORS];
9746f003
FC
77} thermal;
78
266c072d 79
9746f003 80static gint
b90ba1d1 81proc_get_critical(char const* sensor_path){
9746f003
FC
82 FILE *state;
83 char buf[ 256 ], sstmp [ 100 ];
84 char* pstr;
85
b90ba1d1 86 if(sensor_path == NULL) return -1;
9746f003 87
aea0add7 88 snprintf(sstmp,sizeof(sstmp),"%s%s",sensor_path,PROC_THERMAL_TRIP);
9746f003
FC
89
90 if (!(state = fopen( sstmp, "r"))) {
06e29ce1 91 g_warning("thermal: cannot open %s", sstmp);
9746f003
FC
92 return -1;
93 }
94
95 while( fgets(buf, 256, state) &&
266c072d 96 ! ( pstr = strstr(buf, PROC_TRIP_CRITICAL) ) );
9746f003
FC
97 if( pstr )
98 {
266c072d 99 pstr += strlen(PROC_TRIP_CRITICAL);
9746f003
FC
100 while( *pstr && *pstr == ' ' )
101 ++pstr;
102
103 pstr[strlen(pstr)-3] = '\0';
9746f003
FC
104 fclose(state);
105 return atoi(pstr);
106 }
107
108 fclose(state);
109 return -1;
110}
111
112static gint
b90ba1d1 113proc_get_temperature(char const* sensor_path){
9746f003
FC
114 FILE *state;
115 char buf[ 256 ], sstmp [ 100 ];
116 char* pstr;
117
b90ba1d1 118 if(sensor_path == NULL) return -1;
9746f003 119
aea0add7 120 snprintf(sstmp,sizeof(sstmp),"%s%s",sensor_path,PROC_THERMAL_TEMPF);
9746f003
FC
121
122 if (!(state = fopen( sstmp, "r"))) {
06e29ce1 123 g_warning("thermal: cannot open %s", sstmp);
9746f003
FC
124 return -1;
125 }
126
127 while( fgets(buf, 256, state) &&
128 ! ( pstr = strstr(buf, "temperature:") ) );
129 if( pstr )
130 {
131 pstr += 12;
132 while( *pstr && *pstr == ' ' )
133 ++pstr;
134
135 pstr[strlen(pstr)-3] = '\0';
136 fclose(state);
137 return atoi(pstr);
138 }
139
140 fclose(state);
141 return -1;
142}
143
4a4374a0 144static gint _get_reading(const char *path, gboolean quiet)
9fae7098 145{
266c072d 146 FILE *state;
9fae7098 147 char buf[256];
266c072d
HG
148 char* pstr;
149
9fae7098 150 if (!(state = fopen(path, "r"))) {
4a4374a0
AG
151 if (!quiet)
152 g_warning("thermal: cannot open %s", path);
266c072d
HG
153 return -1;
154 }
155
156 while( fgets(buf, 256, state) &&
157 ! ( pstr = buf ) );
158 if( pstr )
159 {
266c072d
HG
160 fclose(state);
161 return atoi(pstr)/1000;
162 }
163
164 fclose(state);
165 return -1;
166}
167
168static gint
9fae7098
AG
169sysfs_get_critical(char const* sensor_path){
170 char sstmp [ 100 ];
266c072d 171
b90ba1d1 172 if(sensor_path == NULL) return -1;
266c072d 173
9fae7098 174 snprintf(sstmp,sizeof(sstmp),"%s%s",sensor_path,SYSFS_THERMAL_TRIP);
266c072d 175
4a4374a0 176 return _get_reading(sstmp, TRUE);
9fae7098 177}
266c072d 178
9fae7098
AG
179static gint
180sysfs_get_temperature(char const* sensor_path){
181 char sstmp [ 100 ];
266c072d 182
9fae7098
AG
183 if(sensor_path == NULL) return -1;
184
185 snprintf(sstmp,sizeof(sstmp),"%s%s",sensor_path,SYSFS_THERMAL_TEMPF);
186
4a4374a0 187 return _get_reading(sstmp, FALSE);
266c072d
HG
188}
189
13cf6185 190static gint
9fae7098
AG
191hwmon_get_critical(char const* sensor_path)
192{
193 char sstmp [ 100 ];
13cf6185 194 int spl;
266c072d 195
13cf6185
AG
196 if(sensor_path == NULL) return -1;
197
198 spl = strlen(sensor_path) - 6;
199 if (spl < 17 || spl > 94)
200 return -1;
201
202 snprintf(sstmp, sizeof(sstmp), "%.*s_crit", spl, sensor_path);
203
4a4374a0 204 return _get_reading(sstmp, TRUE);
b90ba1d1
HG
205}
206
13cf6185 207static gint
9fae7098
AG
208hwmon_get_temperature(char const* sensor_path)
209{
13cf6185
AG
210 if(sensor_path == NULL) return -1;
211
4a4374a0 212 return _get_reading(sensor_path, FALSE);
b90ba1d1
HG
213}
214
4a4374a0 215static gint get_temperature(thermal *th, gint *warn)
b90ba1d1
HG
216{
217 gint max = -273;
4a4374a0 218 gint cur, i, w = 0;
b90ba1d1
HG
219
220 for(i = 0; i < th->numsensors; i++){
221 cur = th->get_temperature[i](th->sensor_array[i]);
4a4374a0
AG
222 if (w == 2) ; /* already warning2 */
223 else if (th->critical[i] > 0 && cur >= th->critical[i] - 5)
224 w = 2;
225 else if ((!th->not_custom_levels || th->critical[i] < 0) &&
226 cur >= th->warning2)
227 w = 2;
228 else if (w == 1) ; /* already warning1 */
229 else if (th->critical[i] > 0 && cur >= th->critical[i] - 10)
230 w = 1;
231 else if ((!th->not_custom_levels || th->critical[i] < 0) &&
232 cur >= th->warning1)
233 w = 1;
b90ba1d1
HG
234 if (cur > max)
235 max = cur;
bdecea07 236 th->temperature[i] = cur;
b90ba1d1 237 }
4a4374a0 238 *warn = w;
b90ba1d1
HG
239
240 return max;
241}
242
243static gint get_critical(thermal *th)
244{
245 gint min = MAX_AUTOMATIC_CRITICAL_TEMP;
4a4374a0 246 gint i;
b90ba1d1
HG
247
248 for(i = 0; i < th->numsensors; i++){
4a4374a0
AG
249 th->critical[i] = th->get_critical[i](th->sensor_array[i]);
250 if (th->critical[i] > 0 && th->critical[i] < min)
251 min = th->critical[i];
266c072d 252 }
b90ba1d1
HG
253
254 return min;
266c072d
HG
255}
256
031db029 257static void
9746f003
FC
258update_display(thermal *th)
259{
260 char buffer [60];
bdecea07 261 int i;
251cfd3e 262 int temp;
9746f003 263 GdkColor color;
bdecea07 264 gchar *separator;
9746f003 265
4a4374a0
AG
266 temp = get_temperature(th, &i);
267 if (i >= 2)
9746f003 268 color = th->cl_warning2;
4a4374a0 269 else if (i >= 1)
9746f003
FC
270 color = th->cl_warning1;
271 else
272 color = th->cl_normal;
273
9746f003 274 if(temp == -1)
a7bd16a4 275 lxpanel_draw_label_text(th->panel, th->namew, "NA", TRUE, 1, TRUE);
9746f003 276 else
2918994e 277 {
aea0add7
AG
278 snprintf(buffer, sizeof(buffer), "<span color=\"#%06x\"><b>%02d</b></span>",
279 gcolor2rgb24(&color), temp);
2918994e 280 gtk_label_set_markup (GTK_LABEL(th->namew), buffer) ;
281 }
9746f003 282
bdecea07
HG
283 g_string_truncate(th->tip, 0);
284 separator = "";
285 for (i = 0; i < th->numsensors; i++){
9fae7098 286 g_string_append_printf(th->tip, "%s%s:\t%2d°C", separator, th->sensor_name[i], th->temperature[i]);
bdecea07
HG
287 separator = "\n";
288 }
289 gtk_widget_set_tooltip_text(th->namew, th->tip->str);
9746f003
FC
290}
291
031db029
AG
292static gboolean update_display_timeout(gpointer user_data)
293{
294 if (g_source_is_destroyed(g_main_current_source()))
295 return FALSE;
296 update_display(user_data);
297 return TRUE; /* repeat later */
298}
f990feeb 299
b90ba1d1 300static int
9fae7098
AG
301add_sensor(thermal* th, char const* sensor_path, const char *sensor_name,
302 GetTempFunc get_temp, GetTempFunc get_crit)
6877b461 303{
b90ba1d1 304 if (th->numsensors + 1 > MAX_NUM_SENSORS){
06e29ce1 305 g_warning("thermal: Too many sensors (max %d), ignoring '%s'",
b90ba1d1
HG
306 MAX_NUM_SENSORS, sensor_path);
307 return -1;
308 }
6877b461 309
b90ba1d1 310 th->sensor_array[th->numsensors] = g_strdup(sensor_path);
9fae7098 311 th->sensor_name[th->numsensors] = g_strdup(sensor_name);
13cf6185
AG
312 th->get_critical[th->numsensors] = get_crit;
313 th->get_temperature[th->numsensors] = get_temp;
b90ba1d1
HG
314 th->numsensors++;
315
06e29ce1 316 g_debug("thermal: Added sensor %s", sensor_path);
b90ba1d1
HG
317
318 return 0;
6877b461
HG
319}
320
321/* find_sensors():
f990feeb
HG
322 * - Get the sensor directory, and store it in '*sensor'.
323 * - It is searched for in 'directory'.
324 * - Only the subdirectories starting with 'subdir_prefix' are accepted as sensors.
325 * - 'subdir_prefix' may be NULL, in which case any subdir is considered a sensor. */
9746f003 326static void
13cf6185
AG
327find_sensors(thermal* th, char const* directory, char const* subdir_prefix,
328 GetTempFunc get_temp, GetTempFunc get_crit)
9746f003
FC
329{
330 GDir *sensorsDirectory;
331 const char *sensor_name;
332 char sensor_path[100];
333
f990feeb 334 if (! (sensorsDirectory = g_dir_open(directory, 0, NULL)))
9746f003 335 return;
9746f003
FC
336
337 /* Scan the thermal_zone directory for available sensors */
338 while ((sensor_name = g_dir_read_name(sensorsDirectory))) {
6877b461
HG
339 if (sensor_name[0] == '.')
340 continue;
341 if (subdir_prefix) {
342 if (strncmp(sensor_name, subdir_prefix, strlen(subdir_prefix)) != 0)
343 continue;
9746f003 344 }
aea0add7 345 snprintf(sensor_path,sizeof(sensor_path),"%s%s/", directory, sensor_name);
9fae7098 346 add_sensor(th, sensor_path, sensor_name, get_temp, get_crit);
9746f003
FC
347 }
348 g_dir_close(sensorsDirectory);
349}
350
bdfaf67b 351static gboolean try_hwmon_sensors(thermal* th, const char *path)
13cf6185
AG
352{
353 GDir *sensorsDirectory;
354 const char *sensor_name;
9fae7098
AG
355 char sensor_path[100], buf[256];
356 FILE *fp;
13cf6185 357
bdfaf67b
AG
358 if (!(sensorsDirectory = g_dir_open(path, 0, NULL)))
359 return FALSE;
13cf6185
AG
360 /* FIXME: do scanning hwmonX other than 0 */
361
362 while ((sensor_name = g_dir_read_name(sensorsDirectory)))
363 {
364 if (strncmp(sensor_name, "temp", 4) == 0 &&
365 strcmp(&sensor_name[5], "_input") == 0)
366 {
bdfaf67b
AG
367 snprintf(sensor_path, sizeof(sensor_path), "%s/temp%c_label", path,
368 sensor_name[4]);
9fae7098
AG
369 fp = fopen(sensor_path, "r");
370 buf[0] = '\0';
371 if (fp)
372 {
373 if (fgets(buf, 256, fp))
374 {
375 char *pp = strchr(buf, '\n');
376 if (pp)
377 *pp = '\0';
378 }
379 fclose(fp);
380 }
bdfaf67b 381 snprintf(sensor_path, sizeof(sensor_path), "%s/%s", path, sensor_name);
9fae7098
AG
382 add_sensor(th, sensor_path, buf[0] ? buf : sensor_name,
383 hwmon_get_temperature, hwmon_get_critical);
13cf6185
AG
384 }
385 }
386 g_dir_close(sensorsDirectory);
bdfaf67b
AG
387 return TRUE;
388}
389
390static void find_hwmon_sensors(thermal* th)
391{
392 char dir_path[100];
393 char *c;
394 int i; /* sensor type num, we'll try up to 4 */
395
396 for (i = 0; i < 4; i++)
397 {
398 snprintf(dir_path, sizeof(dir_path), "/sys/class/hwmon/hwmon%d/device", i);
399 if (try_hwmon_sensors(th, dir_path))
400 continue;
401 c = strrchr(dir_path, '/');
402 *c = '\0';
403 try_hwmon_sensors(th, dir_path);
404 }
13cf6185
AG
405}
406
407
f990feeb 408static void
b90ba1d1 409remove_all_sensors(thermal *th)
f990feeb 410{
b90ba1d1 411 int i;
f990feeb 412
06e29ce1 413 g_debug("thermal: Removing all sensors (%d)", th->numsensors);
1093a9d8 414
b90ba1d1 415 for (i = 0; i < th->numsensors; i++)
9fae7098 416 {
b90ba1d1 417 g_free(th->sensor_array[i]);
9fae7098
AG
418 g_free(th->sensor_name[i]);
419 }
f990feeb 420
b90ba1d1
HG
421 th->numsensors = 0;
422}
423
424static void
425check_sensors( thermal *th )
426{
13cf6185
AG
427 find_sensors(th, PROC_THERMAL_DIRECTORY, NULL, proc_get_temperature, proc_get_critical);
428 find_sensors(th, SYSFS_THERMAL_DIRECTORY, SYSFS_THERMAL_SUBDIR_PREFIX, sysfs_get_temperature, sysfs_get_critical);
429 if (th->numsensors == 0)
430 find_hwmon_sensors(th);
06e29ce1 431 g_info("thermal: Found %d sensors", th->numsensors);
f990feeb
HG
432}
433
434
6adfd706 435static gboolean applyConfig(gpointer p)
176a0002 436{
6adfd706 437 thermal *th = lxpanel_plugin_get_data(p);
4a4374a0 438 int critical;
176a0002
HG
439 ENTER;
440
441 if (th->str_cl_normal) gdk_color_parse(th->str_cl_normal, &th->cl_normal);
442 if (th->str_cl_warning1) gdk_color_parse(th->str_cl_warning1, &th->cl_warning1);
443 if (th->str_cl_warning2) gdk_color_parse(th->str_cl_warning2, &th->cl_warning2);
444
b90ba1d1 445 remove_all_sensors(th);
176a0002
HG
446 if(th->sensor == NULL) th->auto_sensor = TRUE;
447 if(th->auto_sensor) check_sensors(th);
13cf6185 448 else if (strncmp(th->sensor, "/sys/", 5) != 0)
9fae7098 449 add_sensor(th, th->sensor, th->sensor, proc_get_temperature, proc_get_critical);
13cf6185 450 else if (strncmp(th->sensor, "/sys/class/hwmon/", 17) != 0)
9fae7098 451 add_sensor(th, th->sensor, th->sensor, sysfs_get_temperature, sysfs_get_critical);
13cf6185 452 else
9fae7098 453 add_sensor(th, th->sensor, th->sensor, hwmon_get_temperature, hwmon_get_critical);
176a0002 454
4a4374a0 455 critical = get_critical(th);
176a0002
HG
456
457 if(th->not_custom_levels){
4a4374a0
AG
458 th->warning1 = critical - 10;
459 th->warning2 = critical - 5;
176a0002
HG
460 }
461
6adfd706
AG
462 config_group_set_string(th->settings, "NormalColor", th->str_cl_normal);
463 config_group_set_string(th->settings, "Warning1Color", th->str_cl_warning1);
464 config_group_set_string(th->settings, "Warning2Color", th->str_cl_warning2);
d60a7f42
AG
465 config_group_set_int(th->settings, "AutomaticLevels", th->not_custom_levels);
466 /* TODO: clean obsolete setting
467 config_setting_remove(th->settings, "CustomLevels"); */
6adfd706
AG
468 config_group_set_int(th->settings, "Warning1Temp", th->warning1);
469 config_group_set_int(th->settings, "Warning2Temp", th->warning2);
470 config_group_set_int(th->settings, "AutomaticSensor", th->auto_sensor);
471 config_group_set_string(th->settings, "Sensor", th->sensor);
472 RET(FALSE);
176a0002
HG
473}
474
6adfd706
AG
475static void
476thermal_destructor(gpointer user_data)
477{
478 thermal *th = (thermal *)user_data;
479
480 ENTER;
481 remove_all_sensors(th);
482 g_string_free(th->tip, TRUE);
483 g_free(th->sensor);
484 g_free(th->str_cl_normal);
485 g_free(th->str_cl_warning1);
486 g_free(th->str_cl_warning2);
487 g_source_remove(th->timer);
488 g_free(th);
489 RET();
490}
491
492static GtkWidget *
a7bd16a4 493thermal_constructor(LXPanel *panel, config_setting_t *settings)
9746f003
FC
494{
495 thermal *th;
6adfd706
AG
496 GtkWidget *p;
497 const char *tmp;
9746f003
FC
498
499 ENTER;
500 th = g_new0(thermal, 1);
6adfd706
AG
501 th->panel = panel;
502 th->settings = settings;
9746f003 503
6adfd706
AG
504 p = gtk_event_box_new();
505 lxpanel_plugin_set_data(p, th, thermal_destructor);
09fa171b 506 gtk_widget_set_has_window(p, FALSE);
6adfd706 507 gtk_container_set_border_width( GTK_CONTAINER(p), 2 );
9746f003
FC
508
509 th->namew = gtk_label_new("ww");
6adfd706 510 gtk_container_add(GTK_CONTAINER(p), th->namew);
9746f003 511
bdecea07 512 th->tip = g_string_new(NULL);
9746f003 513
815f98f7
HG
514 /* By default, use automatic, that is, "not custom" temperature levels. If
515 * we were using custom levels, they would be 0°C at startup, so we would
516 * display in warning colors by default. */
517 th->not_custom_levels = TRUE;
518
6adfd706
AG
519 if (config_setting_lookup_string(settings, "NormalColor", &tmp))
520 th->str_cl_normal = g_strdup(tmp);
521 if (config_setting_lookup_string(settings, "Warning1Color", &tmp))
522 th->str_cl_warning1 = g_strdup(tmp);
523 if (config_setting_lookup_string(settings, "Warning2Color", &tmp))
524 th->str_cl_warning2 = g_strdup(tmp);
525 config_setting_lookup_int(settings, "AutomaticSensor", &th->auto_sensor);
d60a7f42 526 /* backward compatibility for wrong variable */
6adfd706 527 config_setting_lookup_int(settings, "CustomLevels", &th->not_custom_levels);
d60a7f42 528 config_setting_lookup_int(settings, "AutomaticLevels", &th->not_custom_levels);
6adfd706
AG
529 if (config_setting_lookup_string(settings, "Sensor", &tmp))
530 th->sensor = g_strdup(tmp);
531 config_setting_lookup_int(settings, "Warning1Temp", &th->warning1);
532 config_setting_lookup_int(settings, "Warning2Temp", &th->warning2);
9746f003
FC
533
534 if(!th->str_cl_normal)
535 th->str_cl_normal = g_strdup("#00ff00");
536 if(!th->str_cl_warning1)
537 th->str_cl_warning1 = g_strdup("#fff000");
538 if(!th->str_cl_warning2)
539 th->str_cl_warning2 = g_strdup("#ff0000");
540
176a0002 541 applyConfig(p);
9746f003 542
c03f7bd0
DK
543 gtk_widget_show(th->namew);
544
9746f003 545 update_display(th);
031db029 546 th->timer = g_timeout_add_seconds(3, (GSourceFunc) update_display_timeout, (gpointer)th);
9746f003 547
6adfd706 548 RET(p);
9746f003
FC
549}
550
752ee4e2 551static GtkWidget *config(LXPanel *panel, GtkWidget *p)
6adfd706 552{
9746f003
FC
553 ENTER;
554
555 GtkWidget *dialog;
6adfd706
AG
556 thermal *th = lxpanel_plugin_get_data(p);
557 dialog = lxpanel_generic_config_dlg(_("Temperature Monitor"),
558 panel, applyConfig, p,
289d2688
AG
559 _("Normal color"), &th->str_cl_normal, CONF_TYPE_STR,
560 _("Warning1 color"), &th->str_cl_warning1, CONF_TYPE_STR,
561 _("Warning2 color"), &th->str_cl_warning2, CONF_TYPE_STR,
e2957bd2
HJYP
562 _("Automatic sensor location"), &th->auto_sensor, CONF_TYPE_BOOL,
563 _("Sensor"), &th->sensor, CONF_TYPE_STR,
83af5cab 564 _("Automatic temperature levels"), &th->not_custom_levels, CONF_TYPE_BOOL,
289d2688
AG
565 _("Warning1 temperature"), &th->warning1, CONF_TYPE_INT,
566 _("Warning2 temperature"), &th->warning2, CONF_TYPE_INT,
9746f003 567 NULL);
9746f003 568
6adfd706 569 RET(dialog);
9746f003
FC
570}
571
6adfd706 572FM_DEFINE_MODULE(lxpanel_gtk, thermal)
9746f003 573
6adfd706 574LXPanelPluginInit fm_module_init_lxpanel_gtk = {
3c3e9c9e 575 .name = N_("Temperature Monitor"),
3c3e9c9e
HG
576 .description = N_("Display system temperature"),
577
6adfd706 578 .new_instance = thermal_constructor,
3c3e9c9e 579 .config = config,
9746f003 580};
b90ba1d1
HG
581
582
583/* vim: set sw=4 sts=4 et : */