1 /* GKrellM
2 | Copyright (C) 1999-2019 Bill Wilson
3 |
4 | Author: Bill Wilson billw@gkrellm.net
5 | Latest versions might be found at: http://gkrellm.net
6 |
7 |
8 | GKrellM is free software: you can redistribute it and/or modify it
9 | under the terms of the GNU General Public License as published by
10 | the Free Software Foundation, either version 3 of the License, or
11 | (at your option) any later version.
12 |
13 | GKrellM is distributed in the hope that it will be useful, but WITHOUT
14 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 | License for more details.
17 |
18 | You should have received a copy of the GNU General Public License
19 | along with this program. If not, see http://www.gnu.org/licenses/
20 |
21 |
22 | Additional permission under GNU GPL version 3 section 7
23 |
24 | If you modify this program, or any covered work, by linking or
25 | combining it with the OpenSSL project's OpenSSL library (or a
26 | modified version of that library), containing parts covered by
27 | the terms of the OpenSSL or SSLeay licenses, you are granted
28 | additional permission to convey the resulting work.
29 | Corresponding Source for a non-source form of such a combination
30 | shall include the source code for the parts of OpenSSL used as well
31 | as that of the covered work.
32 */
33
34 #include "gkrellm.h"
35 #include "gkrellm-private.h"
36 #include "gkrellm-sysdeps.h"
37
38 /* Useful info:
39 | http://mbm.livewiredev.com/
40 | Look up boards here for sensor chip and temperature sensor type
41 | so sensor[1,2,3] can be set correctly in sensors.conf.
42 */
43
44 /* On Linux, the sensor id_name includes the parent chip directory, so
45 | "lm78/temp" will be a id_name, and not just "temp". This is to
46 | allow unique identification in case of multiple "temp" files.
47 | ie, more than 1 chip directory, each with a "temp" file.
48 */
49
50 typedef struct _sensor
51 {
52 gchar *name; /* cpuX, mb, Vx name mapped to this sensor */
53 gchar *name_locale; /* gdk_draw compat */
54 gchar *default_label; /* Only voltages have default labels */
55 gchar *path; /* Pathname to sensor data or device file */
56 gchar *id_name; /* Unique sensor identifier for config */
57 gint type;
58
59 gint id;
60 gint iodev;
61 gint inter;
62
63 gint enabled;
64 gint group;
65 gint location; /* default, Proc panel, or cpu panel */
66 gfloat factor, /* Scale sensor reading */
67 offset; /* Add to sensor reading */
68 gfloat default_factor,
69 default_offset;
70 gchar *vref_name;
71 struct _sensor
72 *vref; /* A neg volt may be function of a ref volt */
73
74 gboolean has_config;
75
76 gfloat value,
77 raw_value;
78 gboolean value_valid;
79
80 GkrellmAlert *alert;
81 void (*cb_alert)();
82 gpointer cb_alert_data;
83 gpointer smon;
84 }
85 Sensor;
86
87
88 static GList *sensor_list = NULL;
89
90 static GList *temp_order_list, /* For ordering from the config. */
91 *fan_order_list,
92 *volt_order_list;
93
94 static gboolean using_new_config,
95 need_disk_temperature_update;
96
97 static gboolean (*get_temperature)(gchar *name, gint id,
98 gint iodev, gint inter, gfloat *t);
99 static gboolean (*get_fan)(gchar *name, gint id,
100 gint iodev, gint inter, gfloat *f);
101 static gboolean (*get_voltage)(gchar *name, gint id,
102 gint iodev, gint inter, gfloat *v);
103
104 static void read_sensors_config(void);
105 static gboolean (*config_migrate)(gchar *current_name, gchar *config_name,
106 gint current, gint config);
107
108 static gint sensor_config_version;
109 static gint sensor_current_sysdep_private;
110 static gint sensor_config_sysdep_private;
111
112 void
gkrellm_sensors_client_divert(gboolean (* get_temp_func)(),gboolean (* get_fan_func)(),gboolean (* get_volt_func)())113 gkrellm_sensors_client_divert(gboolean (*get_temp_func)(),
114 gboolean (*get_fan_func)(), gboolean (*get_volt_func)())
115 {
116 get_temperature = get_temp_func;
117 get_fan = get_fan_func;
118 get_voltage = get_volt_func;
119 }
120
121 void
gkrellm_sensors_config_migrate_connect(gboolean (* migrate_func)(),gint sysdep_private)122 gkrellm_sensors_config_migrate_connect(gboolean (*migrate_func)(),
123 gint sysdep_private)
124 {
125 config_migrate = migrate_func;
126 sensor_current_sysdep_private = sysdep_private;
127 }
128
129 static gboolean
setup_sensor_interface(void)130 setup_sensor_interface(void)
131 {
132 if (!get_temperature && !_GK.client_mode && gkrellm_sys_sensors_init())
133 {
134 get_temperature = gkrellm_sys_sensors_get_temperature;
135 get_fan = gkrellm_sys_sensors_get_fan;
136 get_voltage = gkrellm_sys_sensors_get_voltage;
137 }
138 return get_temperature ? TRUE : FALSE;
139 }
140
141 void
gkrellm_sensors_set_group(gpointer sr,gint group)142 gkrellm_sensors_set_group(gpointer sr, gint group)
143 {
144 Sensor *sensor = (Sensor *) sr;
145
146 if (sensor)
147 sensor->group = group;
148 }
149
150 gpointer
gkrellm_sensors_add_sensor(gint type,gchar * sensor_path,gchar * id_name,gint id,gint iodev,gint inter,gfloat factor,gfloat offset,gchar * vref,gchar * default_label)151 gkrellm_sensors_add_sensor(gint type, gchar *sensor_path, gchar *id_name,
152 gint id, gint iodev, gint inter,
153 gfloat factor, gfloat offset, gchar *vref, gchar *default_label)
154 {
155 Sensor *sensor;
156 gchar *r;
157
158 if (!id_name || !*id_name || type < 0 || type > 2)
159 return NULL;
160
161 sensor = g_new0(Sensor, 1);
162 sensor->id_name = g_strdup(id_name);
163
164 if (sensor_path)
165 sensor->path = g_strdup(sensor_path);
166 else
167 sensor->path = g_strdup(id_name);
168 if (!default_label)
169 {
170 r = strrchr(id_name, '/');
171 default_label = r ? r+1 : id_name;
172 }
173 gkrellm_locale_dup_string(&sensor->name, default_label,
174 &sensor->name_locale);
175 sensor->default_label = g_strdup(default_label);
176
177 sensor->default_factor = factor;
178 sensor->factor
179 = (sensor->default_factor != 0.0 ? sensor->default_factor : 1.0);
180 sensor->default_offset = sensor->offset = offset;
181 sensor->type = type;
182 sensor->id = id;
183 sensor->iodev = iodev;
184 sensor->inter = inter;
185 if (type == SENSOR_VOLTAGE && vref)
186 sensor->vref_name = g_strdup(vref);
187 sensor_list = g_list_append(sensor_list, sensor);
188 return (gpointer) sensor;
189 }
190
191 /* ======================================================================== */
192 static gboolean use_threads,
193 thread_data_valid,
194 units_fahrenheit,
195 show_units = TRUE;
196
197 static gboolean thread_busy;
198
199 static gpointer
read_sensors_thread(void * data)200 read_sensors_thread(void *data)
201 {
202 GList *list;
203 Sensor *sensor;
204
205 for (list = sensor_list; list; list = list->next)
206 {
207 sensor = (Sensor *) list->data;
208 if (!sensor->enabled)
209 continue;
210 if (sensor->type == SENSOR_TEMPERATURE && get_temperature)
211 (*get_temperature)(sensor->path, sensor->id,
212 sensor->iodev, sensor->inter, &sensor->raw_value);
213 if (sensor->type == SENSOR_FAN && get_fan)
214 (*get_fan)(sensor->path, sensor->id,
215 sensor->iodev, sensor->inter, &sensor->raw_value);
216 if (sensor->type == SENSOR_VOLTAGE && get_voltage)
217 (*get_voltage)(sensor->path, sensor->id,
218 sensor->iodev, sensor->inter, &sensor->raw_value);
219 }
220 thread_busy = FALSE;
221 return NULL;
222 }
223
224 static void
run_sensors_thread(void)225 run_sensors_thread(void)
226 {
227 GThread *gth;
228
229 if (thread_busy)
230 return;
231 thread_busy = TRUE;
232 gth = g_thread_new("read_sensors", read_sensors_thread, NULL);
233 g_thread_unref(gth);
234 }
235
236 /* Sort so that sensors are ordered: temp, fan, voltage.
237 */
238 static gint
strcmp_sensor_path(Sensor * s1,Sensor * s2)239 strcmp_sensor_path(Sensor *s1, Sensor *s2)
240 {
241 if (s1->type == SENSOR_TEMPERATURE && s2->type != SENSOR_TEMPERATURE)
242 return -1;
243 if (s1->type != SENSOR_TEMPERATURE && s2->type == SENSOR_TEMPERATURE)
244 return 1;
245
246 if (s1->type == SENSOR_FAN && s2->type != SENSOR_FAN)
247 return -1;
248 if (s1->type != SENSOR_FAN && s2->type == SENSOR_FAN)
249 return 1;
250
251 return strcmp(s1->id_name, s2->id_name);
252 }
253
254 static void
append_sensor_to_order_list(Sensor * sr)255 append_sensor_to_order_list(Sensor *sr)
256 {
257 if (sr->type == SENSOR_TEMPERATURE)
258 temp_order_list = g_list_append(temp_order_list, sr);
259 else if (sr->type == SENSOR_FAN)
260 fan_order_list = g_list_append(fan_order_list, sr);
261 else if (sr->type == SENSOR_VOLTAGE)
262 volt_order_list = g_list_append(volt_order_list, sr);
263 }
264
265
266 /* This is called as sensors are read from the config and I will want to
267 | re-order the sensors_list to reflect the config order. Re-ordering is
268 | done by appending found sensors to type specific lists and later the
269 | sensors_list will be rebuilt from the ordered type lists. If the
270 | id_name is found in the sensor_list, assign the label to it.
271 */
272 static Sensor *
map_sensor_label(gchar * label,gchar * name)273 map_sensor_label(gchar *label, gchar *name)
274 {
275 GList *list;
276 Sensor *sr;
277
278 for (list = sensor_list; list; list = list->next)
279 {
280 sr = (Sensor *) list->data;
281 if ( !sr->has_config
282 && ( !strcmp(sr->id_name, name)
283 || ( config_migrate
284 && (*config_migrate)(sr->id_name, name,
285 sensor_current_sysdep_private,
286 sensor_config_sysdep_private)
287 )
288 )
289 )
290 {
291 gkrellm_locale_dup_string(&sr->name, label, &sr->name_locale);
292 append_sensor_to_order_list(sr);
293 sr->has_config = TRUE;
294 return sr;
295 }
296 }
297 return NULL;
298 }
299
300 gboolean
gkrellm_sensors_available(void)301 gkrellm_sensors_available(void)
302 {
303 return (sensor_list || _GK.demo) ? TRUE : FALSE;
304 }
305
306 /* The cpu and proc monitors both need a couple of sensor decals
307 | created on their panels. The left one will only display fan speeds
308 | while the right one will display both fan and temps depending on modes.
309 */
310 void
gkrellm_sensors_create_decals(GkrellmPanel * p,gint style_id,GkrellmDecal ** dsensor,GkrellmDecal ** dfan)311 gkrellm_sensors_create_decals(GkrellmPanel *p, gint style_id,
312 GkrellmDecal **dsensor, GkrellmDecal **dfan)
313 {
314 GkrellmStyle *style;
315 GkrellmMargin *m;
316 GkrellmTextstyle *ts;
317 GkrellmDecal *ds = NULL,
318 *df = NULL;
319 gint w, w_avail;
320
321 if (sensor_list || _GK.demo)
322 {
323 style = gkrellm_panel_style(style_id);
324 m = gkrellm_get_style_margins(style);
325 ts = gkrellm_panel_alt_textstyle(style_id);
326 w_avail = gkrellm_chart_width() - m->left - m->right;
327
328 df = gkrellm_create_decal_text(p, "8888", ts, style, -1, -1, 0);
329
330 /* Sensor decal (fan and/or temp) carves out space remaining to right.
331 | Try to get enough for .1 deg resolution, otherwise what is left.
332 */
333 w = gkrellm_gdk_string_width(ts->font, "188.8F") + ts->effect;
334 if (w > w_avail - df->w - 3)
335 w = gkrellm_gdk_string_width(ts->font, "88.8C") + ts->effect;
336
337 ds = gkrellm_create_decal_text(p, "8.C", ts, style, -1, -1, w);
338 ds->x = w_avail + m->left - w;
339 df->x = m->left;
340 }
341 *dsensor = ds;
342 *dfan = df;
343 }
344
345 void
gkrellm_sensor_draw_fan_decal(GkrellmPanel * p,GkrellmDecal * d,gfloat f)346 gkrellm_sensor_draw_fan_decal(GkrellmPanel *p, GkrellmDecal *d, gfloat f)
347 {
348 gchar buf[8];
349 gint w;
350
351 if (!p || !d)
352 return;
353 snprintf(buf, sizeof(buf), "%.0f", f);
354 w = gkrellm_gdk_string_width(d->text_style.font, buf)
355 + d->text_style.effect;
356 d->x_off = d->w - w;
357 if (d->x_off < 0)
358 d->x_off = 0;
359 gkrellm_draw_decal_text(p, d, buf, 0);
360 }
361
362 void
gkrellm_sensor_draw_temperature_decal(GkrellmPanel * p,GkrellmDecal * d,gfloat t,gchar units)363 gkrellm_sensor_draw_temperature_decal(GkrellmPanel *p, GkrellmDecal *d,
364 gfloat t, gchar units)
365 {
366 gchar *s, buf[8];
367 gint w;
368
369 if (!p || !d)
370 return;
371 snprintf(buf, sizeof(buf), "%.1f%c", t, units);
372 if ((s = strchr(buf, '.')) == NULL)
373 s = strchr(buf, ','); /* Locale may use commas */
374 w = gkrellm_gdk_string_width(d->text_style.font, buf)
375 + d->text_style.effect;
376 if (w > d->w + 1)
377 {
378 snprintf(buf, sizeof(buf), "%.0f%c", t, units);
379 w = gkrellm_gdk_string_width(d->text_style.font, buf)
380 + d->text_style.effect;
381 }
382
383 d->x_off = d->w - w;
384 if (d->x_off < 0)
385 d->x_off = 0;
386 gkrellm_draw_decal_text(p, d, buf, 0 /* no longer used */);
387 }
388
389 static Sensor *
lookup_sensor_from_id_name(gchar * name)390 lookup_sensor_from_id_name(gchar *name)
391 {
392 GList *list;
393 Sensor *s;
394
395 if (!name)
396 return NULL;
397 for (list = sensor_list; list; list = list->next)
398 {
399 s = (Sensor *) list->data;
400 if ( !strcmp(s->id_name, name)
401 || ( config_migrate
402 && (*config_migrate)(s->id_name, name,
403 sensor_current_sysdep_private,
404 sensor_config_sysdep_private)
405 )
406 )
407 return s;
408 }
409 return NULL;
410 }
411
412 /* Given a in0, in1, ... name as a reference to use for a sensor,
413 | find the sensor with that name for the same chip as sr.
414 */
415 static Sensor *
lookup_vref(Sensor * sr,gchar * name)416 lookup_vref(Sensor *sr, gchar *name)
417 {
418 GList *list;
419 Sensor *sv;
420 gchar *s, buf[128];
421
422 snprintf(buf, 96, "%s", sr->id_name);
423 s = strrchr(buf, '/');
424 if (s)
425 ++s;
426 else
427 s = buf;
428 snprintf(s, 31, "%s", name);
429 for (list = sensor_list; list; list = list->next)
430 {
431 sv = (Sensor *) list->data;
432 if ( sv->type == SENSOR_VOLTAGE
433 && !strcmp(sv->id_name, buf)
434 )
435 return sv;
436 }
437 return NULL;
438 }
439
440 static void
cb_command_process(GkrellmAlert * alert,gchar * src,gchar * buf,gint size,Sensor * sensor)441 cb_command_process(GkrellmAlert *alert, gchar *src, gchar *buf, gint size,
442 Sensor *sensor)
443 {
444 gchar c, *s, *fmt;
445 gint len;
446
447 if (!buf || size < 1)
448 return;
449 --size;
450 *buf = '\0';
451 if (!src)
452 return;
453 for (s = src; *s != '\0' && size > 0; ++s)
454 {
455 len = 1;
456 if (*s == '$' && *(s + 1) != '\0')
457 {
458 if ((c = *(s + 1)) == 'H')
459 len = snprintf(buf, size, "%s", gkrellm_sys_get_host_name());
460 else if (c == 's')
461 {
462 if (sensor->type == SENSOR_FAN)
463 fmt = "%.0f";
464 else if (sensor->type == SENSOR_TEMPERATURE)
465 fmt = "%.1f";
466 else /* SENSOR_VOLTAGE */
467 fmt = "%.2f";
468 len = snprintf(buf, size, fmt, sensor->value);
469 }
470 else if (c == 'l' || c == 'L')
471 len = snprintf(buf, size, "%s", sensor->name_locale);
472 ++s;
473 }
474 else
475 *buf = *s;
476 size -= len;
477 buf += len;
478 }
479 *buf = '\0';
480 }
481
482 GkrellmAlert *
gkrellm_sensor_alert(gpointer sr)483 gkrellm_sensor_alert(gpointer sr)
484 {
485 if (!sr)
486 return NULL;
487 return ((Sensor *) sr)->alert;
488 }
489
490 void
gkrellm_sensor_alert_connect(gpointer sr,void (* cb_func)(),gpointer data)491 gkrellm_sensor_alert_connect(gpointer sr, void (*cb_func)(), gpointer data)
492 {
493 Sensor *sensor = (Sensor *) sr;
494
495 if (!sensor)
496 return;
497 sensor->cb_alert = cb_func;
498 sensor->cb_alert_data = data;
499 gkrellm_alert_trigger_connect(sensor->alert, cb_func, data);
500 gkrellm_alert_command_process_connect(sensor->alert,
501 cb_command_process, sensor);
502 gkrellm_reset_alert_soft(sensor->alert);
503 }
504
505 static gboolean
sensor_read_temperature(Sensor * sensor,gfloat * temp,gchar * units)506 sensor_read_temperature(Sensor *sensor, gfloat *temp, gchar *units)
507 {
508 gfloat t = 0;
509 gint found_temp = FALSE;
510
511 if (sensor && get_temperature)
512 {
513 found_temp = thread_data_valid ? TRUE
514 : (*get_temperature)(sensor->path, sensor->id,
515 sensor->iodev, sensor->inter, &sensor->raw_value);
516 sensor->value = sensor->raw_value * sensor->factor + sensor->offset;
517 if (units_fahrenheit)
518 sensor->value = 1.8 * sensor->value + 32.0;
519 t = sensor->value;
520 }
521 if (! found_temp && _GK.demo)
522 {
523 t = 90.0 + (gfloat)(rand() & 0xf);
524 found_temp = TRUE;
525 }
526 if (temp)
527 *temp = t;
528 if (units)
529 {
530 if (show_units)
531 *units = units_fahrenheit ? 'F':'C';
532 else
533 *units = '\0';
534 }
535 if (sensor)
536 gkrellm_debug(DEBUG_SENSORS, "sensor_temp: %s %s t=%.2f\n",
537 sensor->name_locale, sensor->path, sensor->value);
538 if (found_temp && sensor)
539 gkrellm_check_alert(sensor->alert, sensor->value);
540 return found_temp;
541 }
542
543 gboolean
gkrellm_sensor_read_temperature(gpointer sr,gfloat * temp,gchar * units)544 gkrellm_sensor_read_temperature(gpointer sr, gfloat *temp, gchar *units)
545 {
546 return sensor_read_temperature((Sensor *) sr, temp, units);
547 }
548
549
550 static gboolean
sensor_read_fan(Sensor * sensor,gfloat * fan)551 sensor_read_fan(Sensor *sensor, gfloat *fan)
552 {
553 gfloat f = 0;
554 gint found_fan = FALSE;
555
556 if (sensor && get_fan)
557 {
558 found_fan = thread_data_valid ? TRUE
559 : (*get_fan)(sensor->path, sensor->id,
560 sensor->iodev, sensor->inter, &sensor->raw_value);
561 sensor->value = sensor->raw_value * sensor->factor;
562 f = sensor->value;
563 }
564 if (! found_fan && _GK.demo)
565 {
566 f = 4980 + (gfloat)(rand() & 0x3f);
567 found_fan = TRUE;
568 }
569 if (fan)
570 *fan = f;
571 if (sensor)
572 gkrellm_debug(DEBUG_SENSORS, "sensor_fan: %s %s rpm=%.0f\n",
573 sensor->name_locale, sensor->path, sensor->value);
574 if (found_fan && sensor)
575 gkrellm_check_alert(sensor->alert, sensor->value);
576 return found_fan;
577 }
578
579 gboolean
gkrellm_sensor_read_fan(gpointer sr,gfloat * fan)580 gkrellm_sensor_read_fan(gpointer sr, gfloat *fan)
581 {
582 return sensor_read_fan((Sensor *) sr, fan);
583 }
584
585
586 static gboolean
sensor_read_voltage(Sensor * sensor,gfloat * voltage)587 sensor_read_voltage(Sensor *sensor, gfloat *voltage)
588 {
589 gfloat v = 0;
590 gfloat offset;
591 gboolean found_voltage = FALSE;
592
593 if (sensor && get_voltage)
594 {
595 found_voltage = thread_data_valid ? TRUE
596 : (*get_voltage)(sensor->path, sensor->id,
597 sensor->iodev, sensor->inter, &sensor->raw_value);
598 offset = sensor->offset;
599 if (sensor->vref) /* A negative voltage is level shifted by vref */
600 offset *= sensor->vref->value;
601 sensor->value = sensor->raw_value * sensor->factor + offset;
602 v = sensor->value;
603 }
604 if (! found_voltage && _GK.demo)
605 {
606 v = 2.9 + (gfloat)(rand() & 0x7) * 0.1;
607 found_voltage = TRUE;
608 }
609 if (voltage)
610 *voltage = v;
611 if (sensor)
612 gkrellm_debug(DEBUG_SENSORS, "sensor_voltage: %s %s v=%.2f\n",
613 sensor->name_locale, sensor->path, sensor->value);
614 if (found_voltage && sensor)
615 gkrellm_check_alert(sensor->alert, sensor->value);
616 return found_voltage;
617 }
618
619 gboolean
gkrellm_sensor_read_voltage(gpointer sr,gfloat * voltage)620 gkrellm_sensor_read_voltage(gpointer sr, gfloat *voltage)
621 {
622 return sensor_read_voltage((Sensor *) sr, voltage);
623 }
624
625 /* =================================================================== */
626 /* The sensors monitor */
627
628 static void sensor_reset_optionmenu(Sensor *sensor);
629
630 #define SENSOR_STYLE_NAME "sensors"
631
632 /* Temperature and fan sensors can be located on different panels depending
633 | on the sensor group.
634 */
635 #define SENSOR_PANEL_LOCATION 0
636
637 #define PROC_PANEL_LOCATION 1 /* SENSOR_GROUP_MAINBOARD */
638 #define CPU_PANEL_LOCATION 2 /* cpu0 if smp */
639
640 #define DISK_PANEL_LOCATION 1 /* SENSOR_GROUP_DISK */
641
642
643 #define DO_TEMP 1
644 #define DO_FAN 1
645 #define DO_VOLT 1
646
647 typedef struct
648 {
649 GkrellmPanel **panel;
650 GkrellmDecal *name_decal,
651 *sensor_decal;
652 Sensor *sensor;
653 }
654 SensorMon;
655
656 static GtkWidget
657 *temp_vbox,
658 *fan_vbox,
659 *volt_vbox;
660
661 static GList *volt_list,
662 *temperature_list,
663 *fan_list,
664 *disk_temperature_list;
665
666 static GkrellmPanel
667 *pVolt,
668 *pTemp,
669 *pFan;
670
671 static gint style_id;
672 static gint volt_mon_width,
673 volt_mon_height,
674 volt_name_width,
675 volt_bezel_width;
676
677
678 /* Display modes */
679 #define DIGITAL_WITH_LABELS 0
680 #define DIGITAL_NO_LABELS 1
681 #define N_DISPLAY_MODES 2
682
683 #define MONITOR_PAD 6
684 #define NAME_PAD 4
685
686 GkrellmMonitor *mon_sensors;
687 GkrellmMonitor *mon_config_sensors;
688
689 static GkrellmPiximage
690 *bezel_piximage;
691
692 static GkrellmStyle
693 *bezel_style; /* Just for the bezel image border */
694
695 static gint display_mode,
696 have_negative_volts;
697
698 static gint minus_width; /* If will be drawing neg voltages */
699
700 /* If drawing '-' sign, grub a pixel or two to tighten the layout */
701 static gint pixel_grub;
702
703
704 /* Avoid writing decimal values into the config to avoid possible
705 | locale changing decimal point breakage (decimal point can be '.' or ',')
706 */
707 #define SENSOR_FLOAT_FACTOR 10000.0
708 static gfloat sensor_float_factor = 1.0,
709 gkrellm_float_factor = 1.0;
710
711 gboolean
gkrellm_sensor_reset_location(gpointer sr)712 gkrellm_sensor_reset_location(gpointer sr)
713 {
714 GList *list;
715 Sensor *sensor;
716 gboolean result = FALSE;
717
718 if (sr)
719 {
720 for (list = sensor_list; list; list = list->next)
721 {
722 sensor = (Sensor *) list->data;
723 if (sr == sensor)
724 {
725 sensor->location = SENSOR_PANEL_LOCATION;
726 sensor_reset_optionmenu(sensor);
727 result = TRUE;
728 break;
729 }
730 }
731 }
732 return result;
733 }
734
735
736 static void
sensor_relocation_error(gchar * pname)737 sensor_relocation_error(gchar *pname)
738 {
739 gchar *msg;
740
741 msg = g_strdup_printf(
742 _("Can't find a %s panel to relocate sensor to."),
743 pname ? pname : "?");
744 gkrellm_config_message_dialog(NULL, msg);
745 g_free(msg);
746 }
747
748 /* When moving off some other panel, reset that panel.
749 */
750 static void
sensor_reset_location(Sensor * sr)751 sensor_reset_location(Sensor *sr)
752 {
753 if (sr->group == SENSOR_GROUP_MAINBOARD)
754 {
755 if (sr->location == PROC_PANEL_LOCATION)
756 gkrellm_proc_set_sensor(NULL, sr->type);
757 else if (sr->location >= CPU_PANEL_LOCATION)
758 gkrellm_cpu_set_sensor(NULL, sr->type,
759 sr->location - CPU_PANEL_LOCATION);
760 }
761 else if (sr->group == SENSOR_GROUP_DISK)
762 {
763 if (sr->location == DISK_PANEL_LOCATION)
764 gkrellm_disk_temperature_remove(sr->id_name);
765 }
766 }
767
768 void
gkrellm_sensors_interface_remove(gint _interface)769 gkrellm_sensors_interface_remove(gint _interface)
770 {
771 GList *list;
772 Sensor *sensor;
773 gboolean removed_one;
774
775 do
776 {
777 removed_one = FALSE;
778 for (list = sensor_list; list; list = list->next)
779 {
780 sensor = (Sensor *) list->data;
781 if (sensor->inter == _interface)
782 {
783 sensor_reset_location(sensor);
784 g_free(sensor->id_name);
785 g_free(sensor->path);
786 g_free(sensor->name);
787 g_free(sensor->default_label);
788 g_free(sensor->vref_name);
789 sensor_list = g_list_remove(sensor_list, sensor);
790 g_free(sensor);
791 removed_one = TRUE;
792 break;
793 }
794 }
795 }
796 while (removed_one);
797 }
798
799 static void
add_sensor_monitor(Sensor * sr,GkrellmPanel ** p,GList ** smon_list)800 add_sensor_monitor(Sensor *sr, GkrellmPanel **p, GList **smon_list)
801 {
802 SensorMon *smon;
803 gfloat t;
804 gchar units;
805 gboolean set_loc = FALSE;
806
807 sr->smon = NULL;
808 if (!sr->enabled)
809 return;
810
811 if (sr->location != SENSOR_PANEL_LOCATION)
812 {
813 if (sr->group == SENSOR_GROUP_MAINBOARD)
814 {
815 if (sr->location == PROC_PANEL_LOCATION)
816 set_loc = gkrellm_proc_set_sensor(sr, sr->type);
817 else
818 set_loc = gkrellm_cpu_set_sensor(sr, sr->type,
819 sr->location - CPU_PANEL_LOCATION);
820 }
821 else if (sr->group == SENSOR_GROUP_DISK)
822 {
823 if (sr->location == DISK_PANEL_LOCATION)
824 {
825 gkrellm_freeze_alert(sr->alert);
826 sensor_read_temperature(sr, &t, &units);
827 gkrellm_thaw_alert(sr->alert);
828 set_loc = gkrellm_disk_temperature_display((gpointer) sr,
829 sr->id_name, t, units);
830 if (set_loc)
831 disk_temperature_list =
832 g_list_append(disk_temperature_list, sr);
833 }
834 }
835 if (set_loc)
836 return;
837 sr->location = SENSOR_PANEL_LOCATION;
838 }
839 smon = g_new0(SensorMon, 1);
840 smon->sensor = sr;
841 smon->panel = p; /* Alerts need a GkrellmPanel ** */
842 *smon_list = g_list_append(*smon_list, smon);
843 sr->smon = (gpointer) smon;
844 }
845
846 static void
make_sensor_monitor_lists(gboolean do_temp,gboolean do_fan,gboolean do_volt)847 make_sensor_monitor_lists(gboolean do_temp, gboolean do_fan, gboolean do_volt)
848 {
849 GList *list;
850 Sensor *sr;
851
852 if (do_temp)
853 {
854 gkrellm_free_glist_and_data(&temperature_list);
855 g_list_free(disk_temperature_list);
856 disk_temperature_list = NULL;
857 }
858 if (do_fan)
859 gkrellm_free_glist_and_data(&fan_list);
860 if (do_volt)
861 gkrellm_free_glist_and_data(&volt_list);
862
863 for (list = sensor_list; list; list = list->next)
864 {
865 sr = (Sensor *) list->data;
866 if (do_temp && sr->type == SENSOR_TEMPERATURE)
867 add_sensor_monitor(sr, &pTemp, &temperature_list);
868 if (do_fan && sr->type == SENSOR_FAN)
869 add_sensor_monitor(sr, &pFan, &fan_list);
870 if (do_volt && sr->type == SENSOR_VOLTAGE)
871 {
872 if (!sr->has_config && sr->vref_name)
873 sr->vref = lookup_vref(sr, sr->vref_name);
874 add_sensor_monitor(sr, &pVolt, &volt_list);
875 }
876 }
877 }
878
879 #include "pixmaps/sensors/bg_volt.xpm"
880
881 static void
cb_alert_trigger(GkrellmAlert * alert,SensorMon * smon)882 cb_alert_trigger(GkrellmAlert *alert, SensorMon *smon)
883 {
884 GkrellmAlertdecal *ad;
885 GkrellmDecal *d;
886
887 ad = &alert->ad;
888 alert->panel = *smon->panel;
889
890 /* Make the GkrellmAlertdecal show up under the sensor decal
891 */
892 d = smon->sensor_decal;
893 if (d)
894 {
895 ad->x = d->x - 2;
896 ad->y = d->y - 2;
897 ad->w = d->w + 3;
898 ad->h = d->h + 4;
899 gkrellm_render_default_alert_decal(alert);
900 }
901 }
902
903
904 static void
draw_bezels(GkrellmPanel * p,GList * smon_list,gint w,gint h,gint x_adjust)905 draw_bezels(GkrellmPanel *p, GList *smon_list, gint w, gint h, gint x_adjust)
906 {
907 GList *list;
908 GkrellmBorder *b = &bezel_style->border;
909 SensorMon *smon;
910 GkrellmDecal *dv;
911 gint x;
912
913 if (!bezel_piximage)
914 return;
915 for (list = smon_list; list; list = list->next)
916 {
917 smon = (SensorMon *) list->data;
918 dv = smon->sensor_decal;
919 x = dv->x + x_adjust;
920 if (w == 0)
921 w = b->left + dv->w + b->right - x_adjust;
922 if (h == 0)
923 h = b->top + b->bottom + dv->h;
924 gkrellm_paste_piximage(bezel_piximage, p->bg_pixmap,
925 x - b->left, dv->y - b->top, w, h);
926 gkrellm_paste_piximage(bezel_piximage, p->pixmap,
927 x - b->left, dv->y - b->top, w, h);
928 }
929 gdk_draw_drawable(p->bg_text_layer_pixmap, _GK.draw1_GC, p->bg_pixmap,
930 0, 0, 0, 0, p->w, p->h);
931 }
932
933
934 static gboolean
any_negative_volts(void)935 any_negative_volts(void)
936 {
937 GList *list;
938 Sensor *s;
939 SensorMon *volt;
940 gfloat v;
941 gboolean tmp, result = FALSE;
942
943 /* This routine can be called before any volt decals exist, but reading
944 | voltages can trigger alerts which expect to find decals. Hence freeze.
945 */
946 tmp = thread_data_valid;
947 thread_data_valid = FALSE; /* Need results immediately */
948 for (list = volt_list; list; list = list->next)
949 {
950 volt = (SensorMon *) list->data;
951 gkrellm_freeze_alert(volt->sensor->alert);
952 s = volt->sensor->vref;
953 if (s && s->value == 0)
954 sensor_read_voltage(s, &v);
955 sensor_read_voltage(volt->sensor, &v);
956 gkrellm_thaw_alert(volt->sensor->alert);
957 if (v < 0.0)
958 {
959 result = TRUE;
960 break;
961 }
962 }
963 thread_data_valid = tmp;
964 return result;
965 }
966
967 static void
make_volt_decals(GkrellmPanel * p,GkrellmStyle * style)968 make_volt_decals(GkrellmPanel *p, GkrellmStyle *style)
969 {
970 GList *list;
971 GkrellmBorder *b = &bezel_style->border;
972 Sensor *sensor;
973 SensorMon *volt;
974 GkrellmDecal *dv, *dn;
975 GkrellmTextstyle *ts_volt, *ts_name;
976 gchar *fmt;
977 gint w_volt;
978
979 ts_name = gkrellm_meter_alt_textstyle(style_id);
980 ts_volt = gkrellm_meter_textstyle(style_id);
981
982 volt_mon_width = 0;
983 volt_mon_height = 0;
984 volt_name_width = 0;
985 w_volt = 0;
986
987 minus_width = 0;
988 have_negative_volts = FALSE;
989 fmt = "8.88";
990 if (any_negative_volts())
991 {
992 have_negative_volts = TRUE;
993 minus_width = 1;
994 fmt = "-8.88";
995 }
996
997 for (list = volt_list; list; list = list->next)
998 {
999 volt = (SensorMon *) list->data;
1000 sensor = volt->sensor;
1001 if (display_mode == DIGITAL_WITH_LABELS)
1002 {
1003 volt->name_decal = dn = gkrellm_create_decal_text(p,
1004 volt->sensor->name_locale, ts_name, style, 0, 0, 0);
1005 if (dn->w > volt_name_width)
1006 volt_name_width = dn->w;
1007 }
1008 dv = gkrellm_create_decal_text(p, fmt, ts_volt, style, 0, 0, 0);
1009 volt->sensor_decal = dv;
1010 if (minus_width == 1)
1011 minus_width = gkrellm_gdk_string_width(dv->text_style.font, "-");
1012 w_volt = dv->w; /* Same for all volt decals */
1013 if (dv->h > volt_mon_height)
1014 volt_mon_height = dv->h;
1015
1016 sensor->cb_alert = cb_alert_trigger;
1017 sensor->cb_alert_data = volt;
1018 gkrellm_alert_trigger_connect(sensor->alert, cb_alert_trigger, volt);
1019 gkrellm_alert_command_process_connect(sensor->alert,
1020 cb_command_process, sensor);
1021 gkrellm_reset_alert_soft(sensor->alert);
1022 }
1023 pixel_grub = minus_width ? 1 : 0;
1024 volt_bezel_width = b->left + w_volt + b->right - pixel_grub;
1025 volt_mon_height += b->top + b->bottom;
1026
1027 /* If name decal I let bezel left border encroach into NAME_PAD space
1028 */
1029 if (volt_name_width)
1030 volt_mon_width = volt_name_width + NAME_PAD + w_volt + b->right;
1031 else
1032 volt_mon_width = w_volt; /* borders encroach into MONITOR_PAD */
1033 }
1034
1035 static void
layout_volt_decals(GkrellmPanel * p,GkrellmStyle * style)1036 layout_volt_decals(GkrellmPanel *p, GkrellmStyle *style)
1037 {
1038 GList *list;
1039 SensorMon *volt;
1040 GkrellmDecal *dv, *dn;
1041 GkrellmMargin *m;
1042 gint x, y, w, c, n, cols;
1043
1044 m = gkrellm_get_style_margins(style);
1045 w = gkrellm_chart_width() - m->left - m->right;
1046 cols = (w + MONITOR_PAD) / (volt_mon_width + MONITOR_PAD);
1047 if (cols < 1)
1048 cols = 1;
1049 n = g_list_length(volt_list);
1050 if (cols > n)
1051 cols = n;;
1052 volt_mon_width = w / cols; /* spread them out */
1053 x = (w - cols * volt_mon_width) / 2 + m->left;
1054
1055 gkrellm_get_top_bottom_margins(style, &y, NULL);
1056 c = 0;
1057 for (list = volt_list; list; list = list->next)
1058 {
1059 volt = (SensorMon *) list->data;
1060 dn = volt->name_decal;
1061 dv = volt->sensor_decal;
1062 /* Right justify the volt decal in each volt_mon field
1063 */
1064 dv->x = x + (c+1) * volt_mon_width - dv->w - bezel_style->border.right;
1065 if (cols > 1 && !dn)
1066 dv->x -= (volt_mon_width - volt_bezel_width) / 2;
1067 dv->y = y + bezel_style->border.top;
1068 if (dn)
1069 {
1070 if (cols == 1)
1071 dn->x = m->left;
1072 else
1073 dn->x = dv->x - volt_name_width - NAME_PAD;
1074 dn->y = y + bezel_style->border.top;
1075 if (dn->h < dv->h)
1076 dn->y += (dv->h - dn->h + 1) / 2;
1077 }
1078 if (++c >= cols)
1079 {
1080 c = 0;
1081 y += volt_mon_height;
1082 }
1083 }
1084 }
1085
1086 static void
update_disk_temperatures(void)1087 update_disk_temperatures(void)
1088 {
1089 GList *list;
1090 Sensor *sr;
1091 gfloat t;
1092 gchar units;
1093 gboolean display_failed = FALSE;
1094
1095 for (list = disk_temperature_list; list; list = list->next)
1096 {
1097 sr = (Sensor *) list->data;
1098 sensor_read_temperature(sr, &t, &units);
1099 if (!gkrellm_disk_temperature_display((gpointer) sr, sr->id_name,
1100 t, units))
1101 {
1102 /* disk panel was disabled, so put temp back on sensors panel
1103 */
1104 display_failed = TRUE;
1105 sr->location = SENSOR_PANEL_LOCATION;
1106 sensor_reset_optionmenu(sr);
1107 }
1108 }
1109 if (display_failed)
1110 gkrellm_sensors_rebuild(TRUE, FALSE, FALSE);
1111 }
1112
1113 /* Squeeze name decal text into a smaller font if it would overlap the
1114 | sensor decal. With smaller fonts, the y_ink value may be smaller which
1115 | would bump the text upward. So adjust decal offset by difference in
1116 | y_ink value. (GKrellM text decal heights don't include the y_ink
1117 | space).
1118 */
1119 static gchar *
name_text_fit(Sensor * s,GkrellmDecal * dn,GkrellmDecal * ds)1120 name_text_fit(Sensor *s, GkrellmDecal *dn, GkrellmDecal *ds)
1121 {
1122 gchar *string;
1123 gint x_limit, w0, w1, y_ink0, y_ink1, h0, h1;
1124
1125 x_limit = ds->x;
1126
1127 /* Check for '<' in case user is doing his own markup
1128 */
1129 if (*(s->name_locale) != '<' && dn->x + dn->w > x_limit)
1130 {
1131 gkrellm_text_markup_extents(dn->text_style.font, s->name_locale,
1132 strlen(s->name_locale), &w0, NULL, NULL, &y_ink0);
1133 string = g_strdup_printf("<small>%s</small>", s->name_locale);
1134 gkrellm_text_markup_extents(dn->text_style.font, string,
1135 strlen(string), &w1, &h0, NULL, &y_ink1);
1136 h1 = h0;
1137 if (dn->x + w1 > x_limit)
1138 {
1139 g_free(string);
1140 string = g_strdup_printf("<small><small>%s</small></small>",
1141 s->name_locale);
1142 gkrellm_text_markup_extents(dn->text_style.font, string,
1143 strlen(string), &w1, &h1, NULL, &y_ink1);
1144 }
1145 gkrellm_decal_text_set_offset(dn, 0,
1146 y_ink0 - y_ink1 + (h0 - h1 + 1) / 2);
1147 }
1148 else
1149 {
1150 gkrellm_decal_text_set_offset(dn, 0, 0);
1151 string = g_strdup(s->name_locale);
1152 }
1153 return string;
1154 }
1155
1156
1157 static void
draw_temperatures(gboolean draw_name)1158 draw_temperatures(gboolean draw_name)
1159 {
1160 GList *list;
1161 SensorMon *smon;
1162 Sensor *sensor;
1163 gfloat t;
1164 gchar *name, units;
1165
1166 if (!pTemp)
1167 return;
1168 for (list = temperature_list; list; list = list->next)
1169 {
1170 smon = (SensorMon *) list->data;
1171 sensor = smon->sensor;
1172
1173 if (draw_name && smon->name_decal)
1174 {
1175 name = name_text_fit(sensor, smon->name_decal, smon->sensor_decal);
1176 gkrellm_draw_decal_markup(pTemp, smon->name_decal, name);
1177 g_free(name);
1178 }
1179 if (smon->sensor_decal)
1180 {
1181 sensor_read_temperature(sensor, &t, &units);
1182 gkrellm_sensor_draw_temperature_decal(pTemp, smon->sensor_decal,
1183 t, units);
1184 }
1185 }
1186 gkrellm_draw_panel_layers(pTemp);
1187 }
1188
1189 static void
draw_fans(gboolean draw_name)1190 draw_fans(gboolean draw_name)
1191 {
1192 GList *list;
1193 SensorMon *smon;
1194 Sensor *sensor;
1195 gchar *name;
1196 gfloat f;
1197
1198 if (!pFan)
1199 return;
1200 for (list = fan_list; list; list = list->next)
1201 {
1202 smon = (SensorMon *) list->data;
1203 sensor = smon->sensor;
1204
1205 if (draw_name && smon->name_decal)
1206 {
1207 name = name_text_fit(sensor, smon->name_decal, smon->sensor_decal);
1208 gkrellm_draw_decal_markup(pFan, smon->name_decal, name);
1209 g_free(name);
1210 }
1211 if (smon->sensor_decal)
1212 {
1213 sensor_read_fan(sensor, &f);
1214 gkrellm_sensor_draw_fan_decal(pFan, smon->sensor_decal, f);
1215 }
1216 }
1217 gkrellm_draw_panel_layers(pFan);
1218 }
1219
1220 /* If s is NULL, draw 'em all
1221 */
1222 static void
draw_voltages(Sensor * s,gint do_names)1223 draw_voltages(Sensor *s, gint do_names)
1224 {
1225 GList *list;
1226 SensorMon *volt;
1227 Sensor *sensor;
1228 GkrellmDecal *ds, *dn;
1229 gchar *name, *fmt, buf[32];
1230 gfloat v;
1231
1232 if (!pVolt)
1233 return;
1234 for (list = volt_list; list; list = list->next)
1235 {
1236 volt = (SensorMon *) list->data;
1237 sensor = volt->sensor;
1238 if (s && s != sensor)
1239 continue;
1240 sensor->value_valid = FALSE; /* In case vref monitoring stops */
1241 dn = volt->name_decal;
1242 ds = volt->sensor_decal;
1243 if (do_names && dn)
1244 {
1245 name = name_text_fit(sensor, dn, ds);
1246 gkrellm_draw_decal_markup(pVolt, dn, name);
1247 g_free(name);
1248 }
1249 if (ds)
1250 {
1251 if (sensor->vref && !sensor->vref->value_valid)
1252 sensor_read_voltage(sensor->vref, NULL);
1253 sensor_read_voltage(sensor, &v);
1254 sensor->value_valid = TRUE;
1255 if ((v < 10.0 && v > 0.0) || (v > -10.0 && v < 0.0))
1256 fmt = "%.2f";
1257 else
1258 fmt = "%.1f";
1259 snprintf(buf, sizeof(buf), fmt, v);
1260 ds->x_off = (v < 0.0) ? 0 : minus_width;
1261 gkrellm_draw_decal_text(pVolt, ds, buf, -1);
1262 }
1263 }
1264 gkrellm_draw_panel_layers(pVolt);
1265 }
1266
1267 static void
update_sensors(void)1268 update_sensors(void)
1269 {
1270 static gboolean first_time_done;
1271
1272 if (!GK.five_second_tick && first_time_done)
1273 {
1274 if (need_disk_temperature_update) /* delayed until disks created */
1275 update_disk_temperatures();
1276 need_disk_temperature_update = FALSE;
1277 return;
1278 }
1279 if (use_threads)
1280 {
1281 thread_data_valid = TRUE;
1282 run_sensors_thread();
1283 }
1284 draw_temperatures(FALSE);
1285 draw_fans(FALSE);
1286 draw_voltages(NULL, FALSE);
1287 update_disk_temperatures();
1288 first_time_done = TRUE;
1289 }
1290
1291 static gint
expose_event(GtkWidget * widget,GdkEventExpose * ev,GkrellmPanel * p)1292 expose_event(GtkWidget *widget, GdkEventExpose *ev, GkrellmPanel *p)
1293 {
1294 gdk_draw_drawable(widget->window, gkrellm_draw_GC(1), p->pixmap,
1295 ev->area.x, ev->area.y, ev->area.x, ev->area.y,
1296 ev->area.width, ev->area.height);
1297 return FALSE;
1298 }
1299
1300 static gint
cb_panel_press(GtkWidget * widget,GdkEventButton * ev,GkrellmPanel * p)1301 cb_panel_press(GtkWidget *widget, GdkEventButton *ev, GkrellmPanel *p)
1302 {
1303 if (ev->button == 3)
1304 gkrellm_open_config_window(mon_config_sensors);
1305 return FALSE;
1306 }
1307
1308 static GkrellmBorder default_bezel_border = {1,1,1,1};
1309
1310 static void
assign_textstyles(GList * smon_list,GkrellmTextstyle ** ts_name,GkrellmTextstyle ** ts_sensor,gchar * format)1311 assign_textstyles(GList *smon_list, GkrellmTextstyle **ts_name, GkrellmTextstyle **ts_sensor,
1312 gchar *format)
1313 {
1314 GList *list;
1315 GkrellmStyle *style;
1316 GkrellmMargin *margin;
1317 Sensor *sensor;
1318 SensorMon *smon;
1319 GkrellmTextstyle *ts, *ts_alt;
1320 gint w, w_name, w_sensor;
1321
1322 style = gkrellm_meter_style(style_id);
1323 margin = gkrellm_get_style_margins(style);
1324 ts = gkrellm_copy_textstyle(gkrellm_meter_textstyle(style_id));
1325 ts_alt = gkrellm_copy_textstyle(gkrellm_meter_alt_textstyle(style_id));
1326 w = gkrellm_chart_width() - margin->left - margin->right;
1327 w_sensor = gkrellm_gdk_string_width(ts->font, format);
1328 w_sensor += bezel_style->border.left + bezel_style->border.right;
1329 for (list = smon_list; list; list = list->next)
1330 {
1331 smon = (SensorMon *)list->data;
1332 sensor = smon->sensor;
1333 w_name = gkrellm_gdk_string_width(ts_alt->font, sensor->name_locale);
1334 if (w_name + w_sensor > w - 2)
1335 {
1336 ts->font = ts_alt->font; /* downsize the sensor font */
1337 break;
1338 }
1339 }
1340 *ts_name = ts_alt; /* Caller must free these */
1341 *ts_sensor = ts;
1342 }
1343
1344 static gint
adjust_decal_positions(SensorMon * smon)1345 adjust_decal_positions(SensorMon *smon)
1346 {
1347 gint y, d, h_pad;
1348
1349 h_pad = bezel_style->border.top + bezel_style->border.bottom;
1350 d = smon->sensor_decal->h - smon->name_decal->h;
1351 y = smon->sensor_decal->y + smon->sensor_decal->h + h_pad;
1352 if (d >= 0)
1353 smon->name_decal->y += (d + 1) / 2;
1354 else
1355 {
1356 if (h_pad < -d)
1357 y = smon->name_decal->y + smon->name_decal->h;
1358 smon->sensor_decal->y += -d / 2;
1359 }
1360 return y;
1361 }
1362
1363 static void
make_temperature_panel(GtkWidget * vbox,gint first_create)1364 make_temperature_panel(GtkWidget *vbox, gint first_create)
1365 {
1366 Sensor *sensor;
1367 SensorMon *smon = NULL;
1368 GkrellmStyle *style;
1369 GkrellmMargin *m;
1370 GkrellmDecal *d;
1371 GList *list;
1372 GkrellmTextstyle *ts_sensor, *ts_name;
1373 gchar *format;
1374 gint y;
1375
1376 if (!pTemp)
1377 return;
1378 style = gkrellm_meter_style(style_id);
1379 m = gkrellm_get_style_margins(style);
1380 if (show_units)
1381 format = units_fahrenheit ? "188.8F" : "88.8C";
1382 else
1383 format = units_fahrenheit ? "188.8" : "88.8";
1384 assign_textstyles(temperature_list, &ts_name, &ts_sensor, format);
1385 gkrellm_get_top_bottom_margins(style, &y, NULL);
1386 y += bezel_style->border.top;
1387 for (list = temperature_list; list; list = list->next)
1388 {
1389 smon = (SensorMon *) list->data;
1390 sensor = smon->sensor;
1391 d = gkrellm_create_decal_text(pTemp, format,
1392 ts_sensor, style, -1, y, 0);
1393 d->x = gkrellm_chart_width() - d->w - m->right - 1;
1394 smon->sensor_decal = d;
1395
1396 smon->name_decal = gkrellm_create_decal_text(pTemp,
1397 sensor->name_locale, ts_name, style, -1, y, 0);
1398 y = adjust_decal_positions(smon);
1399 sensor->cb_alert = cb_alert_trigger;
1400 sensor->cb_alert_data = smon;
1401 gkrellm_alert_trigger_connect(sensor->alert, cb_alert_trigger, smon);
1402 gkrellm_alert_command_process_connect(sensor->alert,
1403 cb_command_process, sensor);
1404 gkrellm_reset_alert_soft(sensor->alert);
1405 }
1406 g_free(ts_name);
1407 g_free(ts_sensor);
1408 gkrellm_panel_configure(pTemp, NULL, style);
1409 if (smon && smon->sensor_decal->y + smon->sensor_decal->h >
1410 smon->name_decal->y + smon->name_decal->h - bezel_style->border.bottom
1411 )
1412 gkrellm_panel_configure_add_height(pTemp, bezel_style->border.bottom);
1413 gkrellm_panel_create(vbox, mon_sensors, pTemp);
1414 draw_bezels(pTemp, temperature_list, 0, 0, 1);
1415 if (first_create)
1416 {
1417 g_signal_connect(G_OBJECT(pTemp->drawing_area), "expose_event",
1418 G_CALLBACK(expose_event), pTemp);
1419 g_signal_connect(G_OBJECT(pTemp->drawing_area), "button_press_event",
1420 G_CALLBACK(cb_panel_press), pTemp);
1421 }
1422 draw_temperatures(TRUE);
1423 }
1424
1425 static void
make_fan_panel(GtkWidget * vbox,gint first_create)1426 make_fan_panel(GtkWidget *vbox, gint first_create)
1427 {
1428 Sensor *sensor;
1429 SensorMon *smon = NULL;
1430 GkrellmStyle *style;
1431 GkrellmMargin *m;
1432 GkrellmDecal *d;
1433 GList *list;
1434 GkrellmTextstyle *ts_sensor, *ts_name;
1435 gchar *format;
1436 gint y;
1437
1438 if (!pFan)
1439 return;
1440 style = gkrellm_meter_style(style_id);
1441 m = gkrellm_get_style_margins(style);
1442 format = "8888";
1443 assign_textstyles(temperature_list, &ts_name, &ts_sensor, format);
1444 gkrellm_get_top_bottom_margins(style, &y, NULL);
1445 y += bezel_style->border.top;
1446 for (list = fan_list; list; list = list->next)
1447 {
1448 smon = (SensorMon *) list->data;
1449 sensor = smon->sensor;
1450 d = gkrellm_create_decal_text(pFan, format,
1451 ts_sensor, style, -1, y, 0);
1452 d->x = gkrellm_chart_width() - d->w - m->right - 1;
1453 smon->sensor_decal = d;
1454
1455 smon->name_decal = gkrellm_create_decal_text(pFan, sensor->name_locale,
1456 ts_name, style, -1, y, 0);
1457 y = adjust_decal_positions(smon);
1458 sensor->cb_alert = cb_alert_trigger;
1459 sensor->cb_alert_data = smon;
1460 gkrellm_alert_trigger_connect(sensor->alert, cb_alert_trigger, smon);
1461 gkrellm_alert_command_process_connect(sensor->alert,
1462 cb_command_process, sensor);
1463 gkrellm_reset_alert_soft(sensor->alert);
1464 }
1465 g_free(ts_name);
1466 g_free(ts_sensor);
1467 gkrellm_panel_configure(pFan, NULL, style);
1468 if (smon && smon->sensor_decal->y + smon->sensor_decal->h >
1469 smon->name_decal->y + smon->name_decal->h - bezel_style->border.bottom
1470 )
1471 gkrellm_panel_configure_add_height(pFan, bezel_style->border.bottom);
1472 gkrellm_panel_create(vbox, mon_sensors, pFan);
1473 draw_bezels(pFan, fan_list, 0, 0, 0);
1474 if (first_create)
1475 {
1476 g_signal_connect(G_OBJECT(pFan->drawing_area), "expose_event",
1477 G_CALLBACK(expose_event), pFan);
1478 g_signal_connect(G_OBJECT(pFan->drawing_area), "button_press_event",
1479 G_CALLBACK(cb_panel_press), pFan);
1480 }
1481 draw_fans(TRUE);
1482 }
1483
1484 static void
make_volt_panel(GtkWidget * vbox,gint first_create)1485 make_volt_panel(GtkWidget *vbox, gint first_create)
1486 {
1487 GkrellmStyle *style;
1488
1489 if (!pVolt)
1490 return;
1491 style = gkrellm_meter_style(style_id);
1492 make_volt_decals(pVolt, style);
1493 layout_volt_decals(pVolt, style);
1494
1495 gkrellm_panel_configure(pVolt, NULL, style);
1496
1497 /* Make the bottom margin reference against the bottom volt decals
1498 | bezel image. The volt decal height does not include the bezel so
1499 | gkrellm_panel_configure() did not account for the bezel.
1500 */
1501 gkrellm_panel_configure_add_height(pVolt, bezel_style->border.bottom);
1502 gkrellm_panel_create(vbox, mon_sensors, pVolt);
1503
1504 draw_bezels(pVolt, volt_list,
1505 volt_bezel_width, volt_mon_height, pixel_grub);
1506
1507 if (first_create)
1508 {
1509 g_signal_connect(G_OBJECT(pVolt->drawing_area), "expose_event",
1510 G_CALLBACK(expose_event), pVolt);
1511 g_signal_connect(G_OBJECT(pVolt->drawing_area), "button_press_event",
1512 G_CALLBACK(cb_panel_press), pVolt);
1513 }
1514 draw_voltages(NULL, TRUE);
1515 }
1516
1517
1518 static void
destroy_sensors_monitor(gboolean do_temp,gboolean do_fan,gboolean do_volt)1519 destroy_sensors_monitor(gboolean do_temp, gboolean do_fan, gboolean do_volt)
1520 {
1521 if (do_temp)
1522 {
1523 gkrellm_panel_destroy(pTemp);
1524 pTemp = NULL;
1525 }
1526 if (do_fan)
1527 {
1528 gkrellm_panel_destroy(pFan);
1529 pFan = NULL;
1530 }
1531 if (do_volt)
1532 {
1533 gkrellm_panel_destroy(pVolt);
1534 pVolt = NULL;
1535 }
1536 }
1537
1538 static void
create_sensors_monitor(gboolean do_temp,gboolean do_fan,gboolean do_volt,gboolean first_create)1539 create_sensors_monitor(gboolean do_temp, gboolean do_fan, gboolean do_volt,
1540 gboolean first_create)
1541 {
1542 make_sensor_monitor_lists(do_temp, do_fan, do_volt);
1543 if (do_temp && temperature_list)
1544 {
1545 if (!pTemp)
1546 pTemp = gkrellm_panel_new0();
1547 make_temperature_panel(temp_vbox, first_create);
1548 }
1549 if (do_fan && fan_list)
1550 {
1551 if (!pFan)
1552 pFan = gkrellm_panel_new0();
1553 make_fan_panel(fan_vbox, first_create);
1554 }
1555 if (do_volt && volt_list)
1556 {
1557 if (!pVolt)
1558 pVolt = gkrellm_panel_new0();
1559 make_volt_panel(volt_vbox, first_create);
1560 }
1561 if (temperature_list || fan_list || volt_list)
1562 gkrellm_spacers_show(mon_sensors);
1563 else
1564 gkrellm_spacers_hide(mon_sensors);
1565 }
1566
1567 void
gkrellm_sensors_rebuild(gboolean do_temp,gboolean do_fan,gboolean do_volt)1568 gkrellm_sensors_rebuild(gboolean do_temp, gboolean do_fan, gboolean do_volt)
1569 {
1570 destroy_sensors_monitor(do_temp, do_fan, do_volt);
1571 create_sensors_monitor(do_temp, do_fan, do_volt, TRUE);
1572 }
1573
1574 static void
create_sensors(GtkWidget * vbox,gint first_create)1575 create_sensors(GtkWidget *vbox, gint first_create)
1576 {
1577 gchar **xpm;
1578 static gboolean config_loaded;
1579
1580 if (!config_loaded)
1581 read_sensors_config();
1582 if (first_create)
1583 {
1584 temp_vbox = gtk_vbox_new(FALSE, 0);
1585 gtk_box_pack_start(GTK_BOX(vbox), temp_vbox, FALSE, FALSE, 0);
1586 gtk_widget_show(temp_vbox);
1587
1588 fan_vbox = gtk_vbox_new(FALSE, 0);
1589 gtk_box_pack_start(GTK_BOX(vbox), fan_vbox, FALSE, FALSE, 0);
1590 gtk_widget_show(fan_vbox);
1591
1592 volt_vbox = gtk_vbox_new(FALSE, 0);
1593 gtk_box_pack_start(GTK_BOX(vbox), volt_vbox, FALSE, FALSE, 0);
1594 gtk_widget_show(volt_vbox);
1595
1596 bezel_style = gkrellm_style_new0();
1597 }
1598 else /* To be done after disk panels created */
1599 need_disk_temperature_update = TRUE;
1600
1601 config_loaded = TRUE;
1602
1603 /* Here is where I define the volt panel theme image extensions. I ask
1604 | for a theme extension image:
1605 | THEME_DIR/sensors/bg_volt.png
1606 | and for a border for it from the gkrellmrc in the format:
1607 | set_piximage_border sensors_bg_volt l,r,t,b
1608 | There is no default for bg_volt image, ie it may end up being NULL.
1609 */
1610 xpm = gkrellm_using_default_theme() ? bg_volt_xpm : NULL;
1611 if (bezel_piximage)
1612 gkrellm_destroy_piximage(bezel_piximage);
1613 bezel_piximage = NULL;
1614 gkrellm_load_piximage("bg_volt", xpm, &bezel_piximage, SENSOR_STYLE_NAME);
1615 if (!gkrellm_set_gkrellmrc_piximage_border("sensors_bg_volt", bezel_piximage, bezel_style))
1616 bezel_style->border = default_bezel_border;
1617
1618 create_sensors_monitor(DO_TEMP, DO_FAN, DO_VOLT, first_create);
1619 }
1620
1621 /* FIXME: monitor_sensors and monitor_config_sensors should be combined,
1622 | but the issue is apply_sensors_config() must be called before the CPU
1623 | and Proc apply, and I want create_sensors() called after the CPU and Proc
1624 | create. So for now, two GkrellmMonitor structs and have two sensor
1625 | monitor add_builtins() in main.c.
1626 */
1627 static GkrellmMonitor monitor_sensors =
1628 {
1629 N_("Sensors"), /* Voltage config handled in Sensors tab */
1630 MON_VOLTAGE, /* Id, 0 if a plugin */
1631 create_sensors, /* The create function */
1632 update_sensors, /* The update function */
1633 NULL, /* The config tab create function */
1634 NULL, /* Voltage apply handled in sensors apply */
1635
1636 NULL, /* Voltage save config is in sensors save */
1637 NULL, /* Voltage load config is in sensors load */
1638 NULL, /* config keyword - use sensors */
1639
1640 NULL, /* Undef 2 */
1641 NULL, /* Undef 1 */
1642 NULL, /* Undef 0 */
1643
1644 0, /* insert_before_id - place plugin before this mon */
1645
1646 NULL, /* Handle if a plugin, filled in by GKrellM */
1647 NULL /* path if a plugin, filled in by GKrellM */
1648 };
1649
1650 GkrellmMonitor *
gkrellm_init_sensor_monitor(void)1651 gkrellm_init_sensor_monitor(void)
1652 {
1653 if (!sensor_list)
1654 return NULL;
1655 monitor_sensors.name = _(monitor_sensors.name);
1656 style_id = gkrellm_add_meter_style(&monitor_sensors, SENSOR_STYLE_NAME);
1657 mon_sensors = &monitor_sensors;
1658 return &monitor_sensors;
1659 }
1660
1661 /* =================================================================== */
1662 /* Config for sensors monitor */
1663
1664 /* Don't use the user-config. Save into sensors-config and only if there
1665 | is a sensor_list. This preserves configs across a possible sensors
1666 | modules load screw up.
1667 |
1668 | 2.2.3 sets sensor_config_version to 1 to allow sensor relocation
1669 | to composite CPU on a SMP machine.
1670 |
1671 | 2.1.15 scales sensor factor/offset values by SENSOR_FLOAT_FACTOR to avoid
1672 | writing decimal points in the config. This is not backwards compatible
1673 | with the pre 2.1.15 sensor_config format hence the config file name
1674 | change to sensor-config. But sensor_config is forward compatible
1675 | since the float factor defaults to 1.0.
1676 */
1677 #define SENSOR_CONFIG_VERSION 1
1678
1679 #define SENSOR_CONFIG_KEYWORD "sensor"
1680 #define SENSOR_CONFIG_FILE "sensor-config"
1681 #define SENSOR_2_1_14_CONFIG_FILE "sensors_config"
1682
1683 typedef struct
1684 {
1685 gchar *config_keyword,
1686 *config_label;
1687 gboolean value;
1688 void (*func)(gboolean value);
1689 }
1690 SysdepOption;
1691
1692 static void cb_alert_config(GkrellmAlert *ap, Sensor *sr);
1693
1694 static GList *sysdep_option_list;
1695
1696 static void
create_sensor_alert(Sensor * s)1697 create_sensor_alert(Sensor *s)
1698 {
1699 if (s->type == SENSOR_VOLTAGE)
1700 s->alert = gkrellm_alert_create(NULL, s->name,
1701 _("Sensor Volt Limits"),
1702 TRUE, TRUE, TRUE, 20, -20, 0.01, 0.5, 2);
1703 else if (s->type == SENSOR_TEMPERATURE)
1704 s->alert = gkrellm_alert_create(NULL, s->name,
1705 _("Sensor Temperature Limits (in displayed degree units)"),
1706 TRUE, FALSE, TRUE, 300, 0, 1.0, 5.0, 1);
1707 else if (s->type == SENSOR_FAN)
1708 s->alert = gkrellm_alert_create(NULL, s->name,
1709 _("Sensor Fan RPM Limits"),
1710 FALSE, TRUE, TRUE, 20000, 0, 100, 1000, 0);
1711 else
1712 return;
1713 gkrellm_alert_delay_config(s->alert, 5, 60, 0);
1714 gkrellm_alert_trigger_connect(s->alert, s->cb_alert, s->cb_alert_data);
1715 gkrellm_alert_command_process_connect(s->alert, cb_command_process, s);
1716 gkrellm_alert_config_connect(s->alert, cb_alert_config, s);
1717 }
1718
1719 void
gkrellm_sensors_sysdep_option(gchar * keyword,gchar * label,void (* func)())1720 gkrellm_sensors_sysdep_option(gchar *keyword, gchar *label, void (*func)())
1721 {
1722 SysdepOption *so = NULL;
1723
1724 so = g_new0(SysdepOption, 1);
1725 sysdep_option_list = g_list_append(sysdep_option_list, so);
1726 so->config_keyword = g_strdup(keyword);
1727 so->config_label = g_strdup(label);
1728 so->func = func;
1729 }
1730
1731 static void
save_sensors_config(FILE * f_not_used)1732 save_sensors_config(FILE *f_not_used)
1733 {
1734 FILE *f;
1735 GList *list;
1736 Sensor *s;
1737 SysdepOption *so;
1738 gchar *config, quoted_name[128], buf[128];
1739 gfloat factor, offset;
1740
1741 if (!sensor_list || _GK.no_config)
1742 return;
1743 snprintf(buf, sizeof(buf), "%s/%s", GKRELLM_DIR, SENSOR_CONFIG_FILE);
1744 config = gkrellm_make_config_file_name(gkrellm_homedir(), buf);
1745 f = g_fopen(config, "w");
1746 g_free(config);
1747 if (!f)
1748 return;
1749
1750 fprintf(f, "%s sensor_config_version %d\n",
1751 SENSOR_CONFIG_KEYWORD, SENSOR_CONFIG_VERSION);
1752 fprintf(f, "%s sensor_sysdep_private %d\n",
1753 SENSOR_CONFIG_KEYWORD, sensor_current_sysdep_private);
1754 fprintf(f, "%s sensor_float_factor %.0f\n",
1755 SENSOR_CONFIG_KEYWORD, SENSOR_FLOAT_FACTOR);
1756 fprintf(f, "%s gkrellm_float_factor %.0f\n",
1757 SENSOR_CONFIG_KEYWORD, GKRELLM_FLOAT_FACTOR);
1758 for (list = sysdep_option_list; list; list = list->next)
1759 {
1760 so = (SysdepOption *) list->data;
1761 fprintf(f, "%s sysdep_option %s %d\n", SENSOR_CONFIG_KEYWORD,
1762 so->config_keyword, so->value);
1763 }
1764
1765 for (list = sensor_list; list; list = list->next)
1766 {
1767 s = (Sensor *) list->data;
1768 if (s->name && *(s->name))
1769 {
1770 snprintf(quoted_name, sizeof(quoted_name), "\"%s\"", s->id_name);
1771 factor = (s->default_factor != 0.0 ? s->factor : 0.0);
1772 offset = (s->default_factor != 0.0 ? s->offset : 0.0);
1773 fprintf(f, "%s \"%s\" %s %.0f %.0f %d %d\n",
1774 SENSOR_CONFIG_KEYWORD,
1775 s->name, quoted_name,
1776 factor * SENSOR_FLOAT_FACTOR,
1777 offset * SENSOR_FLOAT_FACTOR,
1778 s->enabled, s->location);
1779 if (s->alert)
1780 gkrellm_save_alertconfig(f, s->alert,
1781 SENSOR_CONFIG_KEYWORD, quoted_name);
1782 }
1783 }
1784 for (list = sensor_list; list; list = list->next)
1785 {
1786 s = (Sensor *) list->data;
1787 if (s->vref)
1788 fprintf(f, "%s vref \"%s\" \"%s\"\n", SENSOR_CONFIG_KEYWORD,
1789 s->id_name, s->vref->id_name);
1790 }
1791
1792 fprintf(f, "%s units_fahrenheit %d\n", SENSOR_CONFIG_KEYWORD,
1793 units_fahrenheit);
1794 fprintf(f, "%s show_units %d\n", SENSOR_CONFIG_KEYWORD,
1795 show_units);
1796 fprintf(f, "%s volt_display_mode %d\n", SENSOR_CONFIG_KEYWORD,
1797 display_mode);
1798 /* _GK.mbmon_port is handled in config.c so that the port can be
1799 | loaded early for sensor initialization.
1800 */
1801 fclose(f);
1802 }
1803
1804 static void
load_sensors_config(gchar * arg)1805 load_sensors_config(gchar *arg)
1806 {
1807 Sensor *s;
1808 SysdepOption *so;
1809 GList *list;
1810 gchar config[32], item[CFG_BUFSIZE], item1[CFG_BUFSIZE];
1811 gchar label[64], id_name[CFG_BUFSIZE];
1812 gint n;
1813 gfloat f = 1.0,
1814 o = 0.0;
1815 gint e = 0,
1816 location = 0;
1817 gfloat save_factor;
1818
1819 n = sscanf(arg, "%31s %[^\n]", config, item);
1820 if (n != 2)
1821 return;
1822 gkrellm_debug(DEBUG_SENSORS, "load_sensors_config: <%s> <%s>\n", config,
1823 item);
1824 if (!strcmp(config, "sensor_config_version"))
1825 sscanf(item, "%d", &sensor_config_version);
1826 else if (!strcmp(config, "sensor_sysdep_private"))
1827 sscanf(item, "%d", &sensor_config_sysdep_private);
1828 else if (!strcmp(config, "units_fahrenheit"))
1829 sscanf(item, "%d", &units_fahrenheit);
1830 else if (!strcmp(config, "show_units"))
1831 sscanf(item, "%d", &show_units);
1832 else if (!strcmp(config, "volt_display_mode"))
1833 sscanf(item, "%d", &display_mode);
1834 else if (!strcmp(config, "sensor_float_factor"))
1835 sscanf(item, "%f", &sensor_float_factor);
1836 else if (!strcmp(config, "gkrellm_float_factor"))
1837 sscanf(item, "%f", &gkrellm_float_factor);
1838 else if (!strcmp(config, "vref"))
1839 {
1840 if ( sscanf(item, "\"%63[^\"]\" \"%64[^\"]\"", id_name, item1) == 2
1841 && (s = lookup_sensor_from_id_name(id_name)) != NULL
1842 )
1843 s->vref = lookup_sensor_from_id_name(item1);
1844 }
1845 else if (!strcmp(config, "sysdep_option"))
1846 {
1847 if (sscanf(item, "%63s %[^\n]", id_name, item1) == 2)
1848 {
1849 so = NULL;
1850 for (list = sysdep_option_list; list; list = list->next)
1851 {
1852 so = (SysdepOption *) list->data;
1853 if (!strcmp(so->config_keyword, id_name))
1854 break;
1855 so = NULL;
1856 }
1857 if (so && so->func)
1858 {
1859 so->value = atoi(item1);
1860 (*so->func)(so->value);
1861 }
1862 }
1863 }
1864 else if (!strcmp(config, GKRELLM_ALERTCONFIG_KEYWORD))
1865 {
1866 if ( sscanf(item, "\"%63[^\"]\" %[^\n]", id_name, item1) == 2
1867 && (s = lookup_sensor_from_id_name(id_name)) != NULL
1868 )
1869 {
1870 /* Since config files may be copied around, make sure to use the
1871 | gkrellm float factor in effect when the sensors config was
1872 | created.
1873 */
1874 save_factor = _GK.float_factor;
1875 _GK.float_factor = gkrellm_float_factor;
1876 if (!s->alert)
1877 create_sensor_alert(s);
1878 gkrellm_load_alertconfig(&s->alert, item1);
1879 _GK.float_factor = save_factor;
1880 }
1881 }
1882 else if ( sscanf(arg, "\"%63[^\"]\" \"%[^\"]\" %f %f %d %d",
1883 label, id_name, &f, &o, &e, &location) > 1
1884 && (s = map_sensor_label(label, id_name)) != NULL
1885 )
1886 {
1887 if (f != 0.0 && s->default_factor != 0.0)
1888 {
1889 s->factor = f / sensor_float_factor;
1890 s->offset = o / sensor_float_factor;
1891 }
1892 s->enabled = e;
1893
1894 if (s->type == SENSOR_VOLTAGE)
1895 s->location = 0;
1896 else
1897 {
1898 s->location = location;
1899 if ( sensor_config_version == 0 && gkrellm_smp_cpus() > 0
1900 && location > PROC_PANEL_LOCATION
1901 )
1902 /* gkrellm < 2.2.3 did not allow relocating to composite
1903 | CPU if on a SMP machine. But with hyperthreading, user
1904 | may want to do this.
1905 */
1906 s->location += 1;
1907 }
1908 if (!using_new_config && s->type != SENSOR_VOLTAGE)
1909 s->enabled = TRUE; /* Old config enabled with a label */
1910 }
1911 if (display_mode < 0 || display_mode >= N_DISPLAY_MODES)
1912 display_mode = N_DISPLAY_MODES - 1;
1913 }
1914
1915 static void
read_sensors_config(void)1916 read_sensors_config(void)
1917 {
1918 FILE *f;
1919 Sensor *sr;
1920 GList *list;
1921 gchar *config;
1922 gchar buf[CFG_BUFSIZE];
1923
1924 snprintf(buf, sizeof(buf), "%s/%s", GKRELLM_DIR, SENSOR_CONFIG_FILE);
1925 config = gkrellm_make_config_file_name(gkrellm_homedir(), buf);
1926 f = g_fopen(config, "r");
1927 g_free(config);
1928
1929 if (!f)
1930 {
1931 snprintf(buf, sizeof(buf), "%s/%s", GKRELLM_DIR, SENSOR_2_1_14_CONFIG_FILE);
1932 config = gkrellm_make_config_file_name(gkrellm_homedir(), buf);
1933 f = g_fopen(config, "r");
1934 g_free(config);
1935 }
1936 if (f)
1937 {
1938 using_new_config = TRUE;
1939 while (fgets(buf, sizeof(buf), f))
1940 load_sensors_config(buf + strlen(SENSOR_CONFIG_KEYWORD) + 1);
1941 fclose(f);
1942 }
1943
1944 /* In case not all sensors are in sensor_config (user edited?)
1945 */
1946 for (list = sensor_list; list; list = list->next)
1947 {
1948 sr = (Sensor *) list->data;
1949 if (sr->has_config) /* Was in sensor_config and is already */
1950 continue; /* appended to an order_list */
1951 append_sensor_to_order_list(sr);
1952 }
1953 g_list_free(sensor_list);
1954 sensor_list = temp_order_list;
1955 sensor_list = g_list_concat(sensor_list, fan_order_list);
1956 sensor_list = g_list_concat(sensor_list, volt_order_list);
1957 }
1958
1959 enum
1960 {
1961 NAME_COLUMN,
1962 ENABLE_COLUMN,
1963 LABEL_COLUMN,
1964 SENSOR_COLUMN,
1965 VISIBLE_COLUMN,
1966 IMAGE_COLUMN,
1967 N_COLUMNS
1968 };
1969
1970 static GtkTreeModel *sensor_model;
1971 static GtkTreeView *treeview;
1972 static GtkTreeRowReference *row_reference;
1973 static GtkTreeSelection *selection;
1974
1975
1976 static GtkWidget *optionmenu;
1977
1978 static GtkWidget *display_mode_button[2];
1979 static GtkWidget *factor_spin_button,
1980 *offset_spin_button;
1981 static GtkWidget *alert_button,
1982 *mbmon_port_entry;
1983
1984 static Sensor *dragged_sensor;
1985
1986 static gint sensor_last_group;
1987
1988 static gboolean (*original_row_drop_possible)();
1989
1990
1991
1992 static void
set_tree_store_model_data(GtkTreeStore * tree,GtkTreeIter * iter,Sensor * s)1993 set_tree_store_model_data(GtkTreeStore *tree, GtkTreeIter *iter, Sensor *s)
1994 {
1995 if (!s)
1996 return;
1997 gtk_tree_store_set(tree, iter,
1998 NAME_COLUMN, s->id_name ? s->id_name : "??",
1999 ENABLE_COLUMN, s->enabled,
2000 LABEL_COLUMN, s->name ? s->name : "??",
2001 SENSOR_COLUMN, s,
2002 VISIBLE_COLUMN, TRUE,
2003 -1);
2004 if (s->alert)
2005 gtk_tree_store_set(tree, iter,
2006 IMAGE_COLUMN, gkrellm_alert_pixbuf(),
2007 -1);
2008 }
2009
2010 static void
append_sensors_to_model(GtkTreeStore * tree,GtkTreeIter * citer,GtkTreeIter * iter,gint type)2011 append_sensors_to_model(GtkTreeStore *tree, GtkTreeIter *citer,
2012 GtkTreeIter *iter, gint type)
2013 {
2014 GList *list;
2015 Sensor *s;
2016
2017 for (list = sensor_list; list; list = list->next)
2018 {
2019 s = (Sensor *) list->data;
2020 if (s->type != type)
2021 continue;
2022 gtk_tree_store_append(tree, citer, iter);
2023 set_tree_store_model_data(tree, citer, s);
2024 }
2025 }
2026
2027 static GtkTreeModel *
create_model(void)2028 create_model(void)
2029 {
2030 GtkTreeStore *tree;
2031 GtkTreeIter iter, citer;
2032
2033 tree = gtk_tree_store_new(N_COLUMNS,
2034 G_TYPE_STRING,
2035 G_TYPE_BOOLEAN,
2036 G_TYPE_STRING,
2037 G_TYPE_POINTER,
2038 G_TYPE_BOOLEAN,
2039 GDK_TYPE_PIXBUF
2040 );
2041
2042 gtk_tree_store_append(tree, &iter, NULL);
2043 gtk_tree_store_set(tree, &iter,
2044 NAME_COLUMN, _("Temperatures"),
2045 VISIBLE_COLUMN, FALSE,
2046 -1);
2047 append_sensors_to_model(tree, &citer, &iter, SENSOR_TEMPERATURE);
2048
2049 gtk_tree_store_append(tree, &iter, NULL);
2050 gtk_tree_store_set(tree, &iter,
2051 NAME_COLUMN, _("Fans"),
2052 VISIBLE_COLUMN, FALSE,
2053 -1);
2054 append_sensors_to_model(tree, &citer, &iter, SENSOR_FAN);
2055
2056 gtk_tree_store_append(tree, &iter, NULL);
2057 gtk_tree_store_set(tree, &iter,
2058 NAME_COLUMN, _("Voltages"),
2059 VISIBLE_COLUMN, FALSE,
2060 -1);
2061 append_sensors_to_model(tree, &citer, &iter, SENSOR_VOLTAGE);
2062 return GTK_TREE_MODEL(tree);
2063 }
2064
2065 void
gkrellm_sensors_model_update(void)2066 gkrellm_sensors_model_update(void)
2067 {
2068 GtkTreeModel *model;
2069
2070 if (!gkrellm_config_window_shown())
2071 return;
2072 model = sensor_model;
2073 sensor_model = create_model();
2074 gtk_tree_view_set_model(treeview, sensor_model);
2075 if (model)
2076 g_object_unref(G_OBJECT(model));
2077 }
2078
2079 static void
change_row_reference(GtkTreeModel * model,GtkTreePath * path)2080 change_row_reference(GtkTreeModel *model, GtkTreePath *path)
2081 {
2082 gtk_tree_row_reference_free(row_reference);
2083 if (model && path)
2084 row_reference = gtk_tree_row_reference_new(model, path);
2085 else
2086 row_reference = NULL;
2087 }
2088
2089 static Sensor *
get_referenced_sensor(void)2090 get_referenced_sensor(void)
2091 {
2092 GtkTreeModel *model;
2093 GtkTreePath *path;
2094 GtkTreeIter iter;
2095 Sensor *s;
2096
2097 if (!row_reference)
2098 return NULL;
2099 model = gtk_tree_view_get_model(treeview);
2100 path = gtk_tree_row_reference_get_path(row_reference);
2101 gtk_tree_model_get_iter(model, &iter, path);
2102 gtk_tree_model_get(model, &iter,
2103 SENSOR_COLUMN, &s, -1);
2104 return s;
2105 }
2106
2107 static gboolean
get_child_iter(GtkTreeModel * model,gchar * parent_node,GtkTreeIter * citer)2108 get_child_iter(GtkTreeModel *model, gchar *parent_node, GtkTreeIter *citer)
2109 {
2110 GtkTreePath *path;
2111 GtkTreeIter iter;
2112
2113 path = gtk_tree_path_new_from_string(parent_node);
2114 gtk_tree_model_get_iter(model, &iter, path);
2115 gtk_tree_path_free(path);
2116 return gtk_tree_model_iter_children(model, citer, &iter);
2117 }
2118
2119
2120 /* Callback for a created or destroyed alert. Find the sensor in the model
2121 | and set the IMAGE_COLUMN.
2122 */
2123 static void
cb_alert_config(GkrellmAlert * ap,Sensor * sr)2124 cb_alert_config(GkrellmAlert *ap, Sensor *sr)
2125 {
2126 GtkTreeModel *model;
2127 GtkTreeIter iter;
2128 Sensor *s;
2129 GdkPixbuf *pixbuf;
2130 gchar node[2];
2131 gint i;
2132
2133 if (!gkrellm_config_window_shown())
2134 return;
2135 model = gtk_tree_view_get_model(treeview);
2136 pixbuf = ap->activated ? gkrellm_alert_pixbuf() : NULL;
2137 for (i = 0; i < 3; ++i)
2138 {
2139 node[0] = '0' + i; /* toplevel temp, fan, or volt node */
2140 node[1] = '\0';
2141 if (get_child_iter(model, node, &iter))
2142 do
2143 {
2144 gtk_tree_model_get(model, &iter, SENSOR_COLUMN, &s, -1);
2145 if (s != sr)
2146 continue;
2147 gtk_tree_store_set(GTK_TREE_STORE(model), &iter,
2148 IMAGE_COLUMN, pixbuf, -1);
2149 return;
2150 }
2151 while (gtk_tree_model_iter_next(model, &iter));
2152 }
2153 }
2154
2155 /* Allow destination drops only on depth 2 paths and don't allow drops from
2156 | source depths of 1 (top level nodes). Also disallow drags from one sensor
2157 | type to another. Note: from some reason if I allow drops on depth 3 nodes
2158 | (destination is on top of a second level node) I am not getting
2159 | "drag_end" callbacks.
2160 */
2161 static gboolean
row_drop_possible(GtkTreeDragDest * drag_dest,GtkTreePath * path,GtkSelectionData * selection_data)2162 row_drop_possible(GtkTreeDragDest *drag_dest, GtkTreePath *path,
2163 GtkSelectionData *selection_data)
2164 {
2165 gint *src_indices, *dst_indices;
2166 GtkTreePath *src_path;
2167
2168 if (!row_reference)
2169 return FALSE;
2170
2171 src_path = gtk_tree_row_reference_get_path(row_reference);
2172 src_indices = gtk_tree_path_get_indices(src_path);
2173 dst_indices = gtk_tree_path_get_indices(path);
2174 //g_debug("drop path: indices=[%d,%d]:%d, path=%s\n",
2175 // dst_indices[0], dst_indices[1], gtk_tree_path_get_depth(path),
2176 // gtk_tree_path_to_string(path));
2177
2178 if ( gtk_tree_path_get_depth(src_path) == 1 /* Dragging top level */
2179 || gtk_tree_path_get_depth(path) != 2
2180 || src_indices[0] != dst_indices[0] /* sensor types don't match */
2181 )
2182 return FALSE;
2183
2184 return (*original_row_drop_possible)(drag_dest, path,
2185 selection_data);
2186 }
2187
2188 /* At each drag, divert the original Gtk row_drop_possible function to my
2189 | custom row_drop_possible so I can control tree structure. The original
2190 | row_drop_possible function must be restored at "drag_end" else other
2191 | monitors doing drag n' drop could get screwed.
2192 */
2193 static gboolean
cb_drag_begin(GtkWidget * widget,GdkDragContext * context,gpointer data)2194 cb_drag_begin(GtkWidget *widget, GdkDragContext *context, gpointer data)
2195 {
2196 GtkTreeModel *model;
2197 GtkTreePath *path;
2198 GtkTreeIter iter;
2199 GtkTreeDragDestIface *dest_iface;
2200
2201 model = gtk_tree_view_get_model(treeview);
2202 dest_iface = GTK_TREE_DRAG_DEST_GET_IFACE(GTK_TREE_DRAG_DEST(model));
2203 if (!original_row_drop_possible)
2204 original_row_drop_possible = dest_iface->row_drop_possible;
2205 dest_iface->row_drop_possible = row_drop_possible;
2206
2207 if (row_reference)
2208 {
2209 path = gtk_tree_row_reference_get_path(row_reference);
2210 gtk_tree_model_get_iter(model, &iter, path);
2211 gtk_tree_model_get(model, &iter, SENSOR_COLUMN, &dragged_sensor, -1);
2212 }
2213 else
2214 dragged_sensor = NULL;
2215 return FALSE;
2216 }
2217
2218 static gboolean
cb_drag_end(GtkWidget * widget,GdkDragContext * context,gpointer data)2219 cb_drag_end(GtkWidget *widget, GdkDragContext *context, gpointer data)
2220 {
2221 GtkTreeModel *model;
2222 GtkTreeIter iter;
2223 GtkTreeDragDestIface *dest_iface;
2224 Sensor *s;
2225 gchar node[2];
2226 gint i, type = -1;
2227
2228 model = gtk_tree_view_get_model(treeview);
2229 dest_iface = GTK_TREE_DRAG_DEST_GET_IFACE(GTK_TREE_DRAG_DEST(model));
2230 dest_iface->row_drop_possible = original_row_drop_possible;
2231
2232 change_row_reference(NULL, NULL);
2233 gtk_tree_selection_unselect_all(selection);
2234
2235 g_list_free(sensor_list);
2236 sensor_list = NULL;
2237
2238 /* Re-order the sensors list to match the model.
2239 */
2240 model = gtk_tree_view_get_model(treeview);
2241 for (i = 0; i < 3; ++i)
2242 {
2243 node[0] = '0' + i; /* toplevel temp, fan, or volt node */
2244 node[1] = '\0';
2245 if (get_child_iter(model, node, &iter))
2246 {
2247 do
2248 {
2249 gtk_tree_model_get(model, &iter, SENSOR_COLUMN, &s, -1);
2250 sensor_list = g_list_append(sensor_list, s);
2251 }
2252 while (gtk_tree_model_iter_next(model, &iter));
2253 }
2254 }
2255
2256 if (dragged_sensor)
2257 type = dragged_sensor->type;
2258 dragged_sensor = NULL;
2259
2260 if (type < 0)
2261 gkrellm_sensors_rebuild(DO_TEMP, DO_FAN, DO_VOLT);
2262 else
2263 gkrellm_sensors_rebuild(type == SENSOR_TEMPERATURE,
2264 type == SENSOR_FAN, type == SENSOR_VOLTAGE);
2265
2266 return FALSE;
2267 }
2268
2269 static void
sensor_reset_optionmenu(Sensor * sensor)2270 sensor_reset_optionmenu(Sensor *sensor)
2271 {
2272 Sensor *sr;
2273
2274 if (!optionmenu)
2275 return;
2276 sr = get_referenced_sensor();
2277 if (sr == sensor)
2278 gtk_combo_box_set_active(GTK_COMBO_BOX(optionmenu),
2279 SENSOR_PANEL_LOCATION);
2280 }
2281
2282 static void
cb_location_menu(GtkComboBox * om,gpointer data)2283 cb_location_menu(GtkComboBox *om, gpointer data)
2284 {
2285 GList *list;
2286 Sensor *sr, *s;
2287 gchar *pname = NULL;
2288 gint location;
2289
2290 location = gtk_combo_box_get_active(om);
2291 sr = get_referenced_sensor();
2292 if (!sr || !sr->enabled || sr->location == location)
2293 return;
2294
2295 /* If trying to relocate, get a dst panel name so can report failures.
2296 */
2297 if (location != SENSOR_PANEL_LOCATION)
2298 {
2299 if (sr->group == SENSOR_GROUP_MAINBOARD)
2300 pname = (location == PROC_PANEL_LOCATION)
2301 ? gkrellm_proc_get_sensor_panel_label()
2302 : gkrellm_cpu_get_sensor_panel_label(
2303 location - CPU_PANEL_LOCATION);
2304 else if (sr->group == SENSOR_GROUP_DISK)
2305 pname = _("Disk");
2306 }
2307
2308 /* If moving off some other panel, reset that panel.
2309 */
2310 sensor_reset_location(sr);
2311
2312 /* For mainboard sensor group, if relocating to a panel with some other
2313 | sensor of same type on it, auto restore the other sensor to the sensor
2314 | panel. Disk sensor group should never conflict.
2315 */
2316 sr->location = location;
2317 if ( location != SENSOR_PANEL_LOCATION
2318 && sr->group == SENSOR_GROUP_MAINBOARD
2319 )
2320 for (list = sensor_list; list; list = list->next)
2321 {
2322 s = (Sensor *) list->data;
2323 if ( s->group == SENSOR_GROUP_MAINBOARD
2324 && s != sr
2325 && s->type == sr->type
2326 && s->location == sr->location
2327 )
2328 s->location = SENSOR_PANEL_LOCATION; /* is being replaced */
2329 }
2330 gkrellm_sensors_rebuild(DO_TEMP, DO_FAN, FALSE);
2331
2332 if (sr->location != location) /* location failed */
2333 {
2334 gtk_combo_box_set_active(GTK_COMBO_BOX(optionmenu),
2335 SENSOR_PANEL_LOCATION);
2336 sensor_relocation_error(pname);
2337 }
2338 }
2339
2340
2341 static void
create_location_menu(gint group)2342 create_location_menu(gint group)
2343 {
2344 gchar *label;
2345 gint n, n_cpus;
2346
2347 if (group == sensor_last_group)
2348 return;
2349 sensor_last_group = group;
2350
2351 gtk_combo_box_append_text(GTK_COMBO_BOX(optionmenu), "default");
2352
2353 if (group == SENSOR_GROUP_MAINBOARD)
2354 {
2355 label = gkrellm_proc_get_sensor_panel_label();
2356 if (label)
2357 gtk_combo_box_append_text(GTK_COMBO_BOX(optionmenu), label);
2358
2359 n_cpus = gkrellm_smp_cpus() + 1;
2360 for (n = 0; n < n_cpus; ++n)
2361 {
2362 label = gkrellm_cpu_get_sensor_panel_label(n);
2363 if (label)
2364 gtk_combo_box_append_text(GTK_COMBO_BOX(optionmenu), label);
2365 }
2366 }
2367 else if (group == SENSOR_GROUP_DISK)
2368 {
2369 gtk_combo_box_append_text(GTK_COMBO_BOX(optionmenu), _("Disk"));
2370 }
2371 g_signal_connect(G_OBJECT(optionmenu), "changed",
2372 G_CALLBACK(cb_location_menu), NULL);
2373 }
2374
2375 static void
set_sensor_widget_states(Sensor * s)2376 set_sensor_widget_states(Sensor *s)
2377 {
2378 gboolean f_sensitive = FALSE,
2379 o_sensitive = FALSE,
2380 p_sensitive = FALSE;
2381 gfloat factor = 1.0,
2382 offset = 0.0;
2383 gint location = SENSOR_PANEL_LOCATION;
2384
2385 if (s && s->enabled)
2386 {
2387 f_sensitive = TRUE;
2388 if (s->type != SENSOR_FAN)
2389 {
2390 o_sensitive = TRUE;
2391 offset = s->offset;
2392 }
2393 factor = s->factor;
2394 if (s->type != SENSOR_VOLTAGE)
2395 {
2396 location = s->location;
2397 p_sensitive = TRUE;
2398 }
2399 }
2400 create_location_menu(s ? s->group : 0);
2401 gtk_combo_box_set_active(GTK_COMBO_BOX(optionmenu), location);
2402 gtk_spin_button_set_value(GTK_SPIN_BUTTON(factor_spin_button), factor);
2403 gtk_spin_button_set_value(GTK_SPIN_BUTTON(offset_spin_button), offset);
2404 gtk_widget_set_sensitive(optionmenu, p_sensitive);
2405 gtk_widget_set_sensitive(alert_button, f_sensitive);
2406
2407 if (s && s->default_factor == 0.0)
2408 f_sensitive = o_sensitive = FALSE;
2409
2410 gtk_widget_set_sensitive(factor_spin_button, f_sensitive);
2411 gtk_widget_set_sensitive(offset_spin_button, o_sensitive);
2412 }
2413
2414 static void
cb_correction_modified(void)2415 cb_correction_modified(void)
2416 {
2417 Sensor *s;
2418
2419 s = get_referenced_sensor();
2420 if (!s || !s->enabled)
2421 return;
2422 s->factor = gtk_spin_button_get_value(GTK_SPIN_BUTTON(factor_spin_button));
2423 s->offset = gtk_spin_button_get_value(GTK_SPIN_BUTTON(offset_spin_button));
2424
2425 if (s->factor == 0)
2426 {
2427 s->factor = s->default_factor;
2428 s->offset = s->default_offset;
2429 gtk_spin_button_set_value(GTK_SPIN_BUTTON(factor_spin_button),
2430 s->factor);
2431 gtk_spin_button_set_value(GTK_SPIN_BUTTON(offset_spin_button),
2432 s->offset);
2433 }
2434 if (s->type == SENSOR_VOLTAGE)
2435 draw_voltages(s, FALSE);
2436 else
2437 {
2438 gkrellm_cpu_draw_sensors(s);
2439 gkrellm_proc_draw_sensors(s);
2440 draw_temperatures(FALSE);
2441 }
2442 }
2443
2444 static void
cb_tree_selection_changed(GtkTreeSelection * selection,gpointer data)2445 cb_tree_selection_changed(GtkTreeSelection *selection, gpointer data)
2446 {
2447 GtkTreeIter iter;
2448 GtkTreeModel *model;
2449 GtkTreePath *path;
2450 Sensor *s;
2451 gint depth;
2452
2453 if (!gtk_tree_selection_get_selected(selection, &model, &iter))
2454 {
2455 change_row_reference(NULL, NULL);
2456 set_sensor_widget_states(NULL);
2457 return;
2458 }
2459 path = gtk_tree_model_get_path(model, &iter);
2460 depth = gtk_tree_path_get_depth(path);
2461 change_row_reference(model, path);
2462 gtk_tree_path_free(path);
2463
2464 if (depth == 1)
2465 {
2466 set_sensor_widget_states(NULL);
2467 return;
2468 }
2469 s = get_referenced_sensor();
2470 set_sensor_widget_states(s);
2471 }
2472
2473 static void
label_edited_cb(GtkCellRendererText * cell,gchar * path_string,gchar * new_label,gpointer data)2474 label_edited_cb(GtkCellRendererText *cell, gchar *path_string,
2475 gchar *new_label, gpointer data)
2476 {
2477 GtkTreeModel *model;
2478 GtkTreeIter iter;
2479 GtkTreePath *path;
2480 Sensor *s;
2481
2482 model = sensor_model;
2483 path = gtk_tree_path_new_from_string(path_string);
2484 gtk_tree_model_get_iter(model, &iter, path);
2485 gtk_tree_path_free(path);
2486
2487 gtk_tree_model_get(model, &iter,
2488 SENSOR_COLUMN, &s,
2489 -1);
2490 if (!*new_label)
2491 new_label = s->default_label;
2492
2493 gtk_tree_store_set(GTK_TREE_STORE(model), &iter,
2494 LABEL_COLUMN, new_label, -1);
2495
2496 if (gkrellm_locale_dup_string(&s->name, new_label, &s->name_locale))
2497 {
2498 gkrellm_sensors_rebuild(s->type == SENSOR_TEMPERATURE,
2499 s->type == SENSOR_FAN, s->type == SENSOR_VOLTAGE);
2500 if (s->alert)
2501 {
2502 g_free(s->alert->name);
2503 s->alert->name = g_strdup(s->name);
2504 // gkrellm_reset_alert(s->alert);
2505 }
2506 }
2507 }
2508
2509 static void
enable_cb(GtkCellRendererText * cell,gchar * path_string,gpointer data)2510 enable_cb(GtkCellRendererText *cell, gchar *path_string, gpointer data)
2511 {
2512 GtkTreeModel *model;
2513 GtkTreeIter iter;
2514 GtkTreePath *path;
2515 Sensor *s;
2516 gboolean enabled;
2517
2518 model = sensor_model;
2519 path = gtk_tree_path_new_from_string(path_string);
2520 gtk_tree_model_get_iter(model, &iter, path);
2521
2522 gtk_tree_model_get(model, &iter,
2523 ENABLE_COLUMN, &enabled,
2524 SENSOR_COLUMN, &s,
2525 -1);
2526 s->enabled = !enabled;
2527 gtk_tree_store_set(GTK_TREE_STORE(model), &iter,
2528 ENABLE_COLUMN, s->enabled,
2529 -1);
2530 change_row_reference(model, path);
2531 gtk_tree_path_free(path);
2532
2533 gkrellm_sensors_rebuild(s->type == SENSOR_TEMPERATURE,
2534 s->type == SENSOR_FAN, s->type == SENSOR_VOLTAGE);
2535
2536 set_sensor_widget_states(s);
2537 }
2538
2539 static void
fix_temp_alert(Sensor * s)2540 fix_temp_alert(Sensor *s)
2541 {
2542 GkrellmAlert *a = s->alert;
2543
2544 if (s->type != SENSOR_TEMPERATURE || !a)
2545 return;
2546 if (units_fahrenheit)
2547 {
2548 if (a->high.warn_limit > 0)
2549 a->high.warn_limit = a->high.warn_limit * 9.0 / 5.0 + 32.0;
2550 if (a->high.alarm_limit > 0)
2551 a->high.alarm_limit = a->high.alarm_limit * 9.0 / 5.0 + 32.0;
2552 }
2553 else
2554 {
2555 if (a->high.warn_limit > 0)
2556 a->high.warn_limit = (a->high.warn_limit - 32.0) * 5.0 / 9.0;
2557 if (a->high.alarm_limit > 0)
2558 a->high.alarm_limit = (a->high.alarm_limit - 32.0) * 5.0 / 9.0;
2559 }
2560 gkrellm_alert_window_destroy(&s->alert);
2561 }
2562
2563 static void
sysdep_option_cb(GtkWidget * button,SysdepOption * so)2564 sysdep_option_cb(GtkWidget *button, SysdepOption *so)
2565 {
2566 if (!so)
2567 return;
2568 so->value = GTK_TOGGLE_BUTTON(button)->active;
2569 }
2570
2571 static void
cb_temperature_units(GtkWidget * button,gpointer data)2572 cb_temperature_units(GtkWidget *button, gpointer data)
2573 {
2574 GList *list;
2575 gint units;
2576
2577 units = GTK_TOGGLE_BUTTON(button)->active;
2578 if (units == units_fahrenheit)
2579 return;
2580 units_fahrenheit = units;
2581
2582 for (list = sensor_list; list; list = list->next)
2583 fix_temp_alert((Sensor *) list->data);
2584
2585 gkrellm_sensors_rebuild(DO_TEMP, FALSE, FALSE);
2586 gkrellm_cpu_draw_sensors(NULL);
2587 gkrellm_proc_draw_sensors(NULL);
2588 }
2589
2590 static void
cb_show_units(GtkWidget * button,gpointer data)2591 cb_show_units(GtkWidget *button, gpointer data)
2592 {
2593 gint show;
2594
2595 show = GTK_TOGGLE_BUTTON(button)->active;
2596 if (show == show_units)
2597 return;
2598 show_units = show;
2599
2600 gkrellm_sensors_rebuild(DO_TEMP, FALSE, FALSE);
2601 gkrellm_cpu_draw_sensors(NULL);
2602 gkrellm_proc_draw_sensors(NULL);
2603 }
2604
2605 static void
cb_voltages_display(GtkWidget * entry,gpointer data)2606 cb_voltages_display(GtkWidget *entry, gpointer data)
2607 {
2608 gint i;
2609
2610 for (i = 0; i < N_DISPLAY_MODES; ++i)
2611 if (GTK_TOGGLE_BUTTON(display_mode_button[i])->active)
2612 display_mode = i;
2613 gkrellm_sensors_rebuild(FALSE, FALSE, DO_VOLT);
2614 }
2615
2616 static void
cb_set_alert(GtkWidget * widget,gpointer data)2617 cb_set_alert(GtkWidget *widget, gpointer data)
2618 {
2619 Sensor *s;
2620
2621 s = get_referenced_sensor();
2622 if (!s || !s->enabled)
2623 return;
2624 if (!s->alert)
2625 create_sensor_alert(s);
2626 gkrellm_alert_config_window(&s->alert);
2627 }
2628
2629
2630 static void
sensors_apply(void)2631 sensors_apply(void)
2632 {
2633 gchar *str;
2634 gint port;
2635
2636 if (mbmon_port_entry)
2637 {
2638 str = gkrellm_gtk_entry_get_text(&mbmon_port_entry);
2639 if (isdigit((unsigned char)*str))
2640 {
2641 port = atoi(str);
2642 if (_GK.mbmon_port != port)
2643 {
2644 if (!gkrellm_sys_sensors_mbmon_port_change(port) && port > 0)
2645 gkrellm_message_dialog(NULL,
2646 _("Can't read sensor data from mbmon daemon.\n"
2647 "Check mbmon port number and '-r' option.\n"
2648 "Run gkrellm -d 0x80 for debug output.\n"));
2649 }
2650 }
2651 }
2652 }
2653
2654 static void
mbmon_port_entry_activate_cb(GtkWidget * widget,gpointer data)2655 mbmon_port_entry_activate_cb(GtkWidget *widget, gpointer data)
2656 {
2657 sensors_apply();
2658 }
2659
2660 static void
cb_config_deleted(gpointer data)2661 cb_config_deleted(gpointer data)
2662 {
2663 treeview = NULL;
2664 }
2665
2666 static gchar *sensor_info_text0[] =
2667 {
2668 N_("<b>No sensors detected.\n"),
2669 "\n",
2670 };
2671
2672 static gchar *sensor_info_text1[] =
2673 {
2674 N_("<h>Setup\n"),
2675 N_("Enter data scaling factors and offsets for the sensors if the default\n"
2676 "values are not correct for your motherboard. Do a man gkrellm or\n"
2677 "see the GKrellM README for more information.\n"),
2678 N_("Enter a zero factor and a blank label to restore default values.\n"),
2679 "\n",
2680 N_("Drag and drop sensor rows to change the displayed order.\n"),
2681 "\n",
2682 N_("Temperature offset values must be in centigrade units.\n"),
2683 "\n",
2684 N_("If you use Pango markup for any custom labels, do not use double quotes.\n"),
2685 N_("For example, to set a colored CPU label, use single quotes:\n"),
2686 N_(" <span foreground='cyan'>CPU</span>\n"),
2687 "\n",
2688 N_("Substitution variables may be used in alert commands.\n"),
2689 N_("\t$s current sensor value.\n"),
2690 N_("\t$l sensor label.\n"),
2691 };
2692
2693 static void
sensors_tab_destroy(GtkWidget * w,gpointer data)2694 sensors_tab_destroy(GtkWidget *w, gpointer data)
2695 {
2696 optionmenu = NULL;
2697 }
2698
2699 static void
create_sensors_tab(GtkWidget * tab_vbox)2700 create_sensors_tab(GtkWidget *tab_vbox)
2701 {
2702 GtkWidget *tabs;
2703 GtkWidget *button;
2704 GtkWidget *text;
2705 GtkWidget *vbox, *vbox1, *hbox, *box;
2706 GtkWidget *scrolled;
2707 GtkWidget *image;
2708 GtkWidget *label, *entry;
2709 GtkTreeModel *model;
2710 GtkCellRenderer *renderer;
2711 GList *list;
2712 SysdepOption *so;
2713 gchar buf[32];
2714 gint i;
2715
2716 row_reference = NULL;
2717 sensor_last_group = -1;
2718
2719 tabs = gtk_notebook_new();
2720 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(tabs), GTK_POS_TOP);
2721 gtk_box_pack_start(GTK_BOX(tab_vbox), tabs, TRUE, TRUE, 0);
2722
2723 g_signal_connect(GTK_OBJECT(tabs), "destroy",
2724 G_CALLBACK(sensors_tab_destroy), NULL);
2725
2726 /* --Setup tab */
2727 vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Setup"));
2728 hbox = gtk_hbox_new(FALSE, 2);
2729 gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
2730 vbox1 = gtk_vbox_new(FALSE, 0);
2731 gtk_box_pack_end(GTK_BOX(hbox), vbox1, FALSE, FALSE, 5);
2732
2733 scrolled = gtk_scrolled_window_new(NULL, NULL);
2734 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2735 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2736 gtk_box_pack_start(GTK_BOX(hbox), scrolled, TRUE, TRUE, 0);
2737
2738 model = create_model();
2739 sensor_model = model;
2740
2741 treeview = GTK_TREE_VIEW(gtk_tree_view_new_with_model(model));
2742 gtk_tree_view_set_rules_hint(treeview, TRUE);
2743 gtk_tree_view_set_reorderable(treeview, TRUE);
2744 g_signal_connect(G_OBJECT(treeview), "drag_begin",
2745 G_CALLBACK(cb_drag_begin), NULL);
2746 g_signal_connect(G_OBJECT(treeview), "drag_end",
2747 G_CALLBACK(cb_drag_end), NULL);
2748 g_signal_connect(G_OBJECT(treeview), "delete_event",
2749 G_CALLBACK(cb_config_deleted), NULL);
2750
2751 renderer = gtk_cell_renderer_text_new();
2752 gtk_tree_view_insert_column_with_attributes(treeview, -1, _("Sensor"),
2753 renderer,
2754 "text", NAME_COLUMN,
2755 NULL);
2756
2757 renderer = gtk_cell_renderer_toggle_new();
2758 gtk_tree_view_insert_column_with_attributes(treeview, -1, _("Enable"),
2759 renderer,
2760 "active", ENABLE_COLUMN,
2761 "visible", VISIBLE_COLUMN,
2762 NULL);
2763 g_signal_connect(G_OBJECT(renderer), "toggled",
2764 G_CALLBACK(enable_cb), NULL);
2765
2766 renderer = gtk_cell_renderer_text_new();
2767 gtk_tree_view_insert_column_with_attributes(treeview, -1, _("Label"),
2768 renderer,
2769 "text", LABEL_COLUMN,
2770 "editable", TRUE,
2771 "visible", VISIBLE_COLUMN,
2772 NULL);
2773 g_signal_connect(G_OBJECT(renderer), "edited",
2774 G_CALLBACK(label_edited_cb), NULL);
2775
2776 renderer = gtk_cell_renderer_pixbuf_new();
2777 gtk_tree_view_insert_column_with_attributes(treeview, -1, "",
2778 renderer,
2779 "pixbuf", IMAGE_COLUMN,
2780 NULL);
2781
2782
2783 gtk_container_add(GTK_CONTAINER(scrolled), GTK_WIDGET(treeview));
2784
2785 selection = gtk_tree_view_get_selection(treeview);
2786 gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
2787 g_signal_connect(G_OBJECT(selection), "changed",
2788 G_CALLBACK(cb_tree_selection_changed), NULL);
2789
2790 box = gkrellm_gtk_framed_vbox(vbox1, _("Factor"), 4, FALSE, 0, 2);
2791 gkrellm_gtk_spin_button(box, &factor_spin_button, 1.0,
2792 -1000.0, 1000.0, 0.01, 1.0, 4, 60,
2793 cb_correction_modified, NULL, FALSE, NULL);
2794
2795 box = gkrellm_gtk_framed_vbox(vbox1, _("Offset"), 4, FALSE, 0, 2);
2796 gkrellm_gtk_spin_button(box, &offset_spin_button, 0.0,
2797 -10000.0, 10000.0, 1.0, 5.0, 3, 60,
2798 cb_correction_modified, NULL, FALSE, NULL);
2799
2800 box = gkrellm_gtk_framed_vbox(vbox1, _("Location"), 2, FALSE, 0, 2);
2801
2802 optionmenu = gtk_combo_box_new_text();
2803
2804 gtk_box_pack_start(GTK_BOX(box), optionmenu, FALSE, FALSE, 4);
2805
2806 box = gtk_hbox_new(FALSE, 0);
2807 gtk_container_set_border_width(GTK_CONTAINER(box), 2);
2808 image = gtk_image_new_from_pixbuf(gkrellm_alert_pixbuf());
2809 label = gtk_label_new(_("Alerts"));
2810 gtk_box_pack_start(GTK_BOX(box), image, FALSE, FALSE, 3);
2811 gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 3);
2812 alert_button = gtk_button_new();
2813 g_signal_connect(G_OBJECT(alert_button), "clicked",
2814 G_CALLBACK(cb_set_alert), NULL);
2815 gtk_widget_show_all(box);
2816 gtk_container_add(GTK_CONTAINER(alert_button), box);
2817 gtk_box_pack_end(GTK_BOX(vbox1), alert_button, FALSE, FALSE, 4);
2818
2819 // gkrellm_gtk_button_connected(vbox1, &alert_button, FALSE, FALSE, -5,
2820 // cb_set_alert, NULL, "Alerts");
2821
2822 set_sensor_widget_states(NULL);
2823
2824 /* -- Options tab */
2825 vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Options"));
2826 // box = gkrellm_gtk_framed_vbox(vbox, _("Temperatures"), 4, FALSE, 0, 2);
2827 box = gkrellm_gtk_category_vbox(vbox, _("Temperatures"), 4, 0, TRUE);
2828 gkrellm_gtk_check_button_connected(box, &button,
2829 units_fahrenheit, FALSE, FALSE, 0,
2830 cb_temperature_units, NULL,
2831 _("Display fahrenheit"));
2832 gkrellm_gtk_check_button_connected(box, &button,
2833 show_units, FALSE, FALSE, 0,
2834 cb_show_units, NULL,
2835 _("Show units"));
2836 if (!sensor_list)
2837 gtk_widget_set_sensitive(button, FALSE);
2838
2839 // box = gkrellm_gtk_framed_vbox(vbox, _("Voltages"), 6, FALSE, 0, 2);
2840 box = gkrellm_gtk_category_vbox(vbox, _("Voltages"), 4, 0, TRUE);
2841 button = gtk_radio_button_new_with_label(NULL,
2842 _("Normal with labels"));
2843 gtk_box_pack_start(GTK_BOX(box), button, FALSE, TRUE, 0);
2844 display_mode_button[DIGITAL_WITH_LABELS] = button;
2845 g_signal_connect(G_OBJECT(button), "toggled",
2846 G_CALLBACK(cb_voltages_display), NULL);
2847 if (!sensor_list)
2848 gtk_widget_set_sensitive(button, FALSE);
2849
2850 button = gtk_radio_button_new_with_label(
2851 gtk_radio_button_get_group(GTK_RADIO_BUTTON (button)),
2852 _("Compact with no labels"));
2853 gtk_box_pack_start(GTK_BOX(box), button, FALSE, TRUE, 0);
2854 display_mode_button[DIGITAL_NO_LABELS] = button;
2855 if (!sensor_list)
2856 gtk_widget_set_sensitive(button, FALSE);
2857
2858 if (sysdep_option_list)
2859 {
2860 box = gkrellm_gtk_category_vbox(vbox, _("Options"), 4, 0, TRUE);
2861 for (list = sysdep_option_list; list; list = list->next)
2862 {
2863 so= (SysdepOption *) list->data;
2864 if (so->config_label)
2865 gkrellm_gtk_check_button_connected(box, NULL,
2866 so->value, FALSE, FALSE, 0,
2867 sysdep_option_cb, so,
2868 so->config_label);
2869 }
2870 }
2871
2872 button = display_mode_button[display_mode];
2873 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
2874
2875 if (gkrellm_sys_sensors_mbmon_supported())
2876 {
2877 box = gkrellm_gtk_category_vbox(vbox, _("MBmon Daemon Port"),
2878 4, 0, TRUE);
2879 label = gtk_label_new("");
2880 gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
2881 gtk_label_set_markup(GTK_LABEL(label),
2882 _("<small>Daemon command must be: <b>mbmon -r -P port</b>\n"
2883 "where 'port' must match the port number entered here:</small>"));
2884 gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0);
2885 hbox = gtk_hbox_new(FALSE, 2);
2886 gtk_box_pack_start(GTK_BOX(box), hbox, TRUE, TRUE, 0);
2887 entry = gtk_entry_new();
2888 gtk_entry_set_max_length(GTK_ENTRY(entry), 6);
2889 mbmon_port_entry = entry;
2890 if (_GK.mbmon_port > 0)
2891 {
2892 snprintf(buf, sizeof(buf), "%d", _GK.mbmon_port);
2893 gtk_entry_set_text(GTK_ENTRY(entry), buf);
2894 }
2895 gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 4);
2896 label = gtk_label_new(
2897 _("See the README or do a \"man gkrellm\" for more information.\n"));
2898 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
2899 gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 4);
2900
2901 g_signal_connect(G_OBJECT(mbmon_port_entry), "activate",
2902 G_CALLBACK(mbmon_port_entry_activate_cb), NULL);
2903 }
2904
2905 /* --Info tab */
2906 vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Info"));
2907 text = gkrellm_gtk_scrolled_text_view(vbox, NULL,
2908 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2909
2910 if (!sensor_list)
2911 for (i = 0; i < sizeof(sensor_info_text0) / sizeof(gchar *); ++i)
2912 gkrellm_gtk_text_view_append(text, _(sensor_info_text0[i]));
2913
2914 for (i = 0; i < sizeof(sensor_info_text1) / sizeof(gchar *); ++i)
2915 gkrellm_gtk_text_view_append(text, _(sensor_info_text1[i]));
2916
2917 /* Present as instant apply, but still get our apply function called.
2918 */
2919 gkrellm_config_instant_apply(mon_config_sensors);
2920 }
2921
2922 GkrellmMonitor *
gkrellm_get_sensors_mon(void)2923 gkrellm_get_sensors_mon(void)
2924 {
2925 return mon_config_sensors;
2926 }
2927
2928 static GkrellmMonitor monitor_config_sensors =
2929 {
2930 N_("Sensors"), /* Name, for config tab. */
2931 -1, /* Id, 0 if a plugin */
2932 NULL, /* The create function */
2933 NULL, /* The update function */
2934 create_sensors_tab, /* The config tab create function */
2935 sensors_apply,
2936
2937 save_sensors_config, /* Save user conifg */
2938 load_sensors_config, /* Load user config */
2939 SENSOR_CONFIG_KEYWORD, /* config keyword */
2940
2941 NULL, /* Undef 2 */
2942 NULL, /* Undef 1 */
2943 NULL, /* Undef 0 */
2944
2945 0, /* insert_before_id - place plugin before this mon */
2946
2947 NULL, /* Handle if a plugin, filled in by GKrellM */
2948 NULL /* path if a plugin, filled in by GKrellM */
2949 };
2950
2951 GkrellmMonitor *
gkrellm_init_sensors_config_monitor(void)2952 gkrellm_init_sensors_config_monitor(void)
2953 {
2954 if (!setup_sensor_interface() && !_GK.demo)
2955 return NULL;
2956 if (!_GK.client_mode)
2957 use_threads = TRUE;
2958 sensor_list = g_list_sort(sensor_list, (GCompareFunc) strcmp_sensor_path);
2959 monitor_config_sensors.name = _(monitor_config_sensors.name);
2960 mon_config_sensors = &monitor_config_sensors;
2961 return &monitor_config_sensors;
2962 }
2963
2964