wmgtemp: Add verson 1.1 to repository.
[dockapps.git] / wmgtemp / src / wmgtemp.c
blobb8951c7a4d371ea1797d69efabd9d5add884a572
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <fcntl.h>
5 #include <unistd.h>
6 #include <sys/param.h>
7 #include <sys/types.h>
8 #include <sys/poll.h>
9 #include <time.h>
10 #include <X11/Xlib.h>
11 #include <X11/xpm.h>
12 #include <X11/extensions/shape.h>
13 #include <sensors/sensors.h>
14 #include <sensors/error.h>
15 #include "wmgeneral/wmgeneral.h"
16 #include "wmgeneral/misc.h"
17 #include "wmgtemp-interface.xpm"
18 #include "wmgtemp-interface-mask.xbm"
19 #include <math.h>
20 #include <signal.h>
21 #include <getopt.h>
23 /* Defines */
24 #define BitOff(a,x) ((void)((a) &= ~(1 << (x))))
25 #define BitOn(a,x) ((void)((a) |= (1 << (x))))
26 #define BitFlip(a,x) ((void)((a) ^= (1 << (x))))
27 #define IsOn(a,x) ((a) & (1 << (x)))
29 // Display flags.
30 #define CPU 0
31 #define SYS 1
32 #define WARN_NONE 2
33 #define WARN_WARN 3
34 #define WARN_HIGH 4
35 #define TSCALE_CELCIUS 5
36 #define TSCALE_FAHRENHEIT 6
37 #define TSCALE_KELVIN 7
38 #define GRAPH_LINE 8
39 #define GRAPH_BLOCK 9
40 #define HIGH_CPU 10
41 #define HIGH_SYS 11
43 #define D_MIN 0
44 #define D_MAX 1
46 #define CPU_YPOS 3
47 #define SYS_YPOS 53
49 #define BLOCK 0
50 #define LINE 1
52 #define DEBUG 0 /* 0 disable 1 enable */
54 #define OPT_STRING "g:sS:hH:w:m:M:a:e:u:1:2:c:tq"
56 #define TEMPTOFAHRENHEIT(t) ((int)((t * (1.8) + 32)))
57 #define TEMPTOKELVIN(t) ((int)(t + 273))
58 #define TEMPTOCELCIUS(t) (t)
59 #define TEMPTODISPLAYSCALE(temp, display_flags) (IsOn((display_flags), TSCALE_CELCIUS) ? TEMPTOCELCIUS((temp)) : (IsOn((display_flags), TSCALE_KELVIN) ? TEMPTOKELVIN((temp)) : TEMPTOFAHRENHEIT((temp))))
61 /* Prototypes */
62 int init_sensors();
63 int process_config(int argc, char **argv);
64 int recompute_range(double cpu_high, double cpu_low, double sys_high, double sys_low);
65 void display_usage();
66 void process_xevents();
67 void draw_scale_indicator();
68 void add_to_graph(double temp, int type, short blank, double range, int pos);
69 void draw_range_line(double temp, double range, short type);
70 void update_display();
71 void update_sensor_data();
72 void do_sensors(int val);
73 inline double highest_temp(double *temp_array);
74 inline double lowest_temp(double *temp_array);
75 inline void draw_temp(short value, int type);
76 inline void draw_warning_lights(double current_temp);
77 inline void draw_max(int type);
78 inline void blank_max(int type);
79 inline void draw_type(int type);
80 inline void blank_type(int type);
81 inline void cycle_temptype();
83 /* Globals */
84 int delay = 1;
85 const sensors_chip_name *name;
86 char *exec_app = NULL;
87 char *rc_config = NULL;
89 short SENSOR_DISP = 0;
90 int SUBFEAT_NUM_CPU = 0;
91 int SUBFEAT_NUM_SYS = 0;
93 double cpu_history[59];
94 double sys_history[59];
96 double display_min = 20;
97 double display_max = 35;
99 double range_upper = 35;
100 double range_lower = 20;
101 double range_step = 5.0;
103 double warn_temp = 45;
104 double high_temp = 50;
106 double run_cpu_high = 0;
107 double run_sys_high = 0;
109 double execat = 0;
110 short execed = 0;
111 short swap_types = 0;
113 char *sensor_feature1 = "temp1";
114 char *sensor_feature2 = "temp2";
115 char *sensor_chip = NULL;
117 short quiet = 0;
119 int main(int argc, char **argv) {
120 char *chipname = NULL;
121 int chip_nr = 0;
122 int i = 0;
123 int tmp_swap;
125 const sensors_feature* feature = NULL;
126 const sensors_subfeature* subfeature_cpu = NULL;
127 const sensors_subfeature* subfeature_sys = NULL;
128 short chip_found = -1;
130 BitOn(SENSOR_DISP, WARN_NONE);
131 BitOn(SENSOR_DISP, TSCALE_CELCIUS);
132 BitOn(SENSOR_DISP, GRAPH_LINE);
134 /* *conffname = "/etc/sensors3.conf"; */
136 if(!process_config(argc, argv)) {
137 exit(-1);
140 if(!init_sensors()) {
141 exit(-1);
144 /* Get the chip name */
145 name = sensors_get_detected_chips(NULL, &chip_nr);
146 while(name != NULL && chip_found == -1) {
147 if (!sensor_chip || strcmp(name->prefix, (const char *)sensor_chip) == 0) {
148 i = 0;
149 while ((feature = sensors_get_features(name, &i))) {
150 if(strcmp(feature->name, (const char *)sensor_feature1) == 0) {
151 subfeature_cpu = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_TEMP_INPUT);
152 SUBFEAT_NUM_CPU = subfeature_cpu->number;
153 BitOn(SENSOR_DISP, CPU);
154 chip_found = 1;
156 if(strcmp(feature->name, (const char *)sensor_feature2) == 0) {
157 subfeature_sys = sensors_get_subfeature(name, feature, SENSORS_SUBFEATURE_TEMP_INPUT);
158 SUBFEAT_NUM_SYS = subfeature_sys->number;
159 BitOn(SENSOR_DISP, SYS);
160 chip_found = 1;
165 if(chip_found == 1) {
166 chipname = name->prefix;
168 else {
169 name = sensors_get_detected_chips(NULL, &chip_nr);
172 if(chip_found == -1) {
173 fprintf(stderr,"wmgtemp: Unable to find temperature sensing feature.\n");
174 exit(0);
177 /* output the name of the sensor if found. */
178 if(quiet == 0)
179 printf("wmgtemp: Primary Sensor - %s on %s\n", name->prefix, sensors_get_adapter_name(&name->bus));
181 if(swap_types) {
182 if(quiet == 0)
183 printf("wmgtemp: swapping temps\n");
184 tmp_swap = SUBFEAT_NUM_SYS;
185 SUBFEAT_NUM_SYS = SUBFEAT_NUM_CPU;
186 SUBFEAT_NUM_CPU = tmp_swap;
187 tmp_swap = SENSOR_DISP;
188 if(IsOn(tmp_swap, CPU)) {
189 BitOn(SENSOR_DISP, SYS);
190 } else {
191 BitOff(SENSOR_DISP, SYS);
193 if(IsOn(tmp_swap, SYS)) {
194 BitOn(SENSOR_DISP, CPU);
195 } else {
196 BitOff(SENSOR_DISP, CPU);
200 chip_nr = 0;
202 openXwindow(argc, argv, wmgtemp_interface_xpm, wmgtemp_interface_mask_bits,
203 wmgtemp_interface_mask_width, wmgtemp_interface_mask_height);
205 AddMouseRegion(0, 2, 12, 61, 51); /* Graph area */
206 AddMouseRegion(1, 34, 2, 51, 11); /* CPU temp area */
207 AddMouseRegion(2, 34, 52, 51, 61); /* SYS temp area */
208 AddMouseRegion(3, 10, CPU_YPOS, 28, CPU_YPOS + 7); /* CPU label area */
209 AddMouseRegion(4, 10, SYS_YPOS, 28, SYS_YPOS + 7); /* SYS label area */
210 AddMouseRegion(5, 55, CPU_YPOS, 60, CPU_YPOS + 7); /* CPU C/K/F scale indicator */
211 AddMouseRegion(6, 55, SYS_YPOS, 60, SYS_YPOS + 7); /* SYS C/K/F scale indicator */
213 // Add blanking of SYS and CPU for chip type.
214 // <<==---
215 if(!IsOn(SENSOR_DISP, CPU)) {
216 blank_type(CPU);
218 if(!IsOn(SENSOR_DISP, SYS)) {
219 blank_type(SYS);
222 draw_scale_indicator();
224 // Initialise the temperature arrays.
225 for(i = 0; i < 59; i++) {
226 cpu_history[i] = -1;
227 sys_history[i] = -1;
230 do_sensors(0);
231 RedrawWindow();
233 process_xevents();
235 return 0;
238 void draw_scale_indicator() {
239 if(IsOn(SENSOR_DISP, TSCALE_CELCIUS)) {
240 if(IsOn(SENSOR_DISP, CPU)) {
241 copyXPMArea(61, 65, 5, 7, 55, CPU_YPOS);
242 copyXPMArea(70, 2, 2, 2, 52, CPU_YPOS);
244 if(IsOn(SENSOR_DISP, SYS)) {
245 copyXPMArea(61, 65, 5, 7, 55, SYS_YPOS);
246 copyXPMArea(70, 2, 2, 2, 52, SYS_YPOS);
249 else if(IsOn(SENSOR_DISP, TSCALE_FAHRENHEIT)) {
250 if(IsOn(SENSOR_DISP, CPU)) {
251 copyXPMArea(67, 65, 5, 7, 55, CPU_YPOS);
252 copyXPMArea(70, 2, 2, 2, 52, CPU_YPOS);
254 if(IsOn(SENSOR_DISP, SYS)) {
255 copyXPMArea(67, 65, 5, 7, 55, SYS_YPOS);
256 copyXPMArea(70, 2, 2, 2, 52, SYS_YPOS);
259 else if(IsOn(SENSOR_DISP, TSCALE_KELVIN)) {
260 if(IsOn(SENSOR_DISP, CPU)) {
261 copyXPMArea(73, 65, 5, 7, 55, CPU_YPOS);
262 copyXPMArea(70, 0, 2, 2, 52, CPU_YPOS);
264 if(IsOn(SENSOR_DISP, SYS)) {
265 copyXPMArea(73, 65, 5, 7, 55, SYS_YPOS);
266 copyXPMArea(70, 0, 2, 2, 52, SYS_YPOS);
271 void process_xevents() {
272 int button_area = 0;
273 int* xfds = NULL;
274 int fdcount = 0;
275 struct pollfd* pfds = NULL;
276 XEvent Event;
277 Status ret;
278 time_t lastupdate = 0;
280 ret = XInternalConnectionNumbers(display, &xfds, &fdcount);
281 if(!ret) {
282 fdcount = 0;
283 if(xfds) {
284 XFree(xfds);
286 xfds = NULL;
289 int i;
290 pfds = (struct pollfd*)malloc((fdcount+1)*sizeof(struct pollfd));
291 if(!pfds) {
292 perror("malloc");
293 exit(EXIT_FAILURE);
296 for(i=0; i < fdcount; ++i) {
297 pfds[i].fd = xfds[i];
298 pfds[i].events = POLLIN | POLLPRI;
301 if(xfds) {
302 XFree(xfds);
305 pfds[fdcount].fd = ConnectionNumber(display);
306 pfds[fdcount].events = POLLIN | POLLPRI;
308 while(1) {
309 poll(pfds, fdcount + 1, delay * 1000);
311 if(time(NULL) - lastupdate >= delay) {
312 lastupdate = time(NULL);
313 do_sensors(0);
316 while(XPending(display)) {
317 XNextEvent(display, &Event);
318 switch(Event.type) {
319 case Expose:
320 RedrawWindow();
321 break;
322 case DestroyNotify:
323 XCloseDisplay(display);
324 exit(0);
325 break;
326 case ButtonRelease:
327 button_area = CheckMouseRegion(Event.xbutton.x, Event.xbutton.y);
328 switch(button_area) {
329 case 0:
330 if(IsOn(SENSOR_DISP, GRAPH_LINE)) {
331 BitOff(SENSOR_DISP, GRAPH_LINE);
332 BitOn(SENSOR_DISP, GRAPH_BLOCK);
334 else if(IsOn(SENSOR_DISP, GRAPH_BLOCK)) {
335 BitOff(SENSOR_DISP, GRAPH_BLOCK);
336 BitOn(SENSOR_DISP, GRAPH_LINE);
338 update_display();
339 RedrawWindow();
340 break;
341 case 1:
342 if(IsOn(SENSOR_DISP, HIGH_CPU)) {
343 BitOff(SENSOR_DISP, HIGH_CPU);
344 blank_max(CPU);
346 else {
347 BitOn(SENSOR_DISP, HIGH_CPU);
348 draw_max(CPU);
350 update_display();
351 RedrawWindow();
352 break;
353 case 2:
354 if(IsOn(SENSOR_DISP, HIGH_SYS)) {
355 BitOff(SENSOR_DISP, HIGH_SYS);
356 blank_max(SYS);
358 else {
359 BitOn(SENSOR_DISP, HIGH_SYS);
360 draw_max(SYS);
362 update_display();
363 RedrawWindow();
364 break;
365 case 3:
366 if(SUBFEAT_NUM_CPU) {
367 if(IsOn(SENSOR_DISP, CPU)) {
368 BitOff(SENSOR_DISP, CPU);
369 blank_type(CPU);
371 else {
372 BitOn(SENSOR_DISP, CPU);
373 draw_type(CPU);
374 draw_scale_indicator();
377 update_display();
378 RedrawWindow();
379 break;
380 case 4:
381 if(SUBFEAT_NUM_SYS) {
382 if(IsOn(SENSOR_DISP, SYS)) {
383 BitOff(SENSOR_DISP, SYS);
384 blank_type(SYS);
386 else {
387 BitOn(SENSOR_DISP, SYS);
388 draw_type(SYS);
389 draw_scale_indicator();
392 update_display();
393 RedrawWindow();
394 break;
395 case 5:
396 case 6:
397 cycle_temptype();
398 draw_scale_indicator();
399 update_display();
400 RedrawWindow();
401 break;
403 break;
409 void do_sensors(int val) {
411 update_sensor_data();
412 update_display();
413 RedrawWindow();
415 if(execat != 0 && cpu_history[58] >= execat && !execed) {
416 execed = 1;
417 execCommand(exec_app);
419 if(execat != 0 && cpu_history[58] < execat && execed) {
420 execed = 0;
425 void update_sensor_data() {
426 int i = 0;
427 double cpu_high = highest_temp(cpu_history);
428 double sys_high = highest_temp(sys_history);
430 /* Shift the arrays */
431 for(i = 0; i < 59; i++) {
432 cpu_history[i] = cpu_history[i + 1];
433 sys_history[i] = sys_history[i + 1];
436 // Read the new values from the sensors into the temperature arrays.
437 if(IsOn(SENSOR_DISP, SYS)) sensors_get_value(name, SUBFEAT_NUM_SYS, &sys_history[58]);
438 if(IsOn(SENSOR_DISP, CPU)) sensors_get_value(name, SUBFEAT_NUM_CPU, &cpu_history[58]);
440 // Update the run high/low values.
441 if(cpu_high > run_cpu_high)
442 run_cpu_high = cpu_high;
443 if(sys_high > run_sys_high)
444 run_sys_high = sys_high;
448 void update_display() {
449 int j = 0;
452 // Rescale the display if needed.
453 while(recompute_range(highest_temp(cpu_history), lowest_temp(cpu_history),
454 highest_temp(sys_history), lowest_temp(sys_history)));
456 // Display warning.
457 draw_warning_lights(cpu_history[58]);
459 // ReDraw temperature numbers
460 if(IsOn(SENSOR_DISP, CPU)) {
461 copyXPMArea(78, 65, 5, 7, 34, CPU_YPOS);
462 copyXPMArea(78, 65, 5, 7, 40, CPU_YPOS);
463 copyXPMArea(78, 65, 5, 7, 46, CPU_YPOS);
464 draw_temp(TEMPTODISPLAYSCALE(IsOn(SENSOR_DISP, HIGH_CPU) == 0 ? cpu_history[58] : run_cpu_high, SENSOR_DISP), CPU);
466 if(IsOn(SENSOR_DISP, SYS)) {
467 copyXPMArea(78, 65, 5, 7, 34, SYS_YPOS);
468 copyXPMArea(78, 65, 5, 7, 40, SYS_YPOS);
469 copyXPMArea(78, 65, 5, 7, 46, SYS_YPOS);
470 draw_temp(TEMPTODISPLAYSCALE(IsOn(SENSOR_DISP, HIGH_SYS) == 0 ? sys_history[58] : run_sys_high, SENSOR_DISP), SYS);
474 // ReDraw the graph
475 for(j = 0; j < 59; j++) {
476 // Clear a line
477 copyXPMArea(65, 0, 1, 39, j + 2, 12);
479 if(sys_history[j] < cpu_history[j]) {
480 // Draw the temperatures on the graph.
481 if(IsOn(SENSOR_DISP, CPU)) {
482 add_to_graph(cpu_history[j], CPU, 1, range_upper - range_lower, j + 2);
484 if(IsOn(SENSOR_DISP, SYS)) {
485 add_to_graph(sys_history[j], SYS, 0, range_upper - range_lower, j + 2);
488 else {
489 if(IsOn(SENSOR_DISP, SYS)) {
490 add_to_graph(sys_history[j], SYS, 0, range_upper - range_lower, j + 2);
492 if(IsOn(SENSOR_DISP, CPU)) {
493 add_to_graph(cpu_history[j], CPU, 1, range_upper - range_lower, j + 2);
498 // Draw range lines if needed
499 if(range_upper > display_max) {
500 draw_range_line(display_max, range_upper - range_lower, D_MAX);
502 if(range_lower < display_min) {
503 draw_range_line(display_min, range_upper - range_lower, D_MIN);
507 int recompute_range(double cpu_high, double cpu_low, double sys_high, double sys_low)
509 short modified = 0;
511 if(IsOn(SENSOR_DISP, CPU)) {
512 if(cpu_high > range_upper) {
513 range_upper += range_step;
514 modified = 1;
516 if(cpu_low < range_lower) {
517 range_lower -= range_step;
518 modified = 1;
521 if(IsOn(SENSOR_DISP, SYS)) {
522 if(sys_high > range_upper) {
523 range_upper += range_step;
524 modified = 1;
526 if(sys_low < range_lower) {
527 range_lower -= range_step;
528 modified = 1;
532 // --------
533 if(IsOn(SENSOR_DISP, CPU) && IsOn(SENSOR_DISP, SYS)) {
534 if((cpu_high < (range_upper - range_step) &&
535 sys_high < (range_upper - range_step)) &&
536 (range_upper - range_step) >= display_max) {
537 range_upper -= range_step;
538 modified = 1;
540 if((cpu_low > (range_lower + range_step) &&
541 sys_low > (range_lower + range_step)) &&
542 (range_lower + range_step) <= display_min ) {
543 range_lower += range_step;
544 modified = 1;
547 else if(IsOn(SENSOR_DISP, CPU) && !IsOn(SENSOR_DISP, SYS)) {
548 if(cpu_high < (range_upper - range_step) &&
549 (range_upper - range_step) >= display_max) {
550 range_upper -= range_step;
551 modified = 1;
553 if(cpu_low > (range_lower + range_step) &&
554 (range_lower + range_step) <= display_min) {
555 range_lower += range_step;
556 modified = 1;
559 else if(!IsOn(SENSOR_DISP, CPU) && IsOn(SENSOR_DISP, SYS)) {
560 if(sys_high < (range_upper - range_step) &&
561 (range_upper - range_step) >= display_max) {
562 range_upper -= range_step;
563 modified = 1;
565 if(sys_low > (range_lower + range_step) &&
566 (range_lower + range_step) <= display_min) {
567 range_lower += range_step;
568 modified = 1;
572 return modified;
575 inline double highest_temp(double *temp_array) {
576 int i = 0;
577 double high = 0;
578 for(i = 0; i < 59; i++) {
579 if(temp_array[i] > high)
580 high = temp_array[i];
582 return high;
585 inline double lowest_temp(double *temp_array) {
586 int i = 0;
587 double low = 500;
588 for(i = 0; i < 59; i++) {
589 if((temp_array[i] < low) && (temp_array[i] != -1))
590 low = temp_array[i];
592 return low;
595 void add_to_graph(double temp, int type, short blank, double range, int pos) {
596 double each = (double)39 / range;
597 short length = each * (temp - range_lower);
599 // Draw the graphs
600 // if(IsOn(SENSOR_DISP, GRAPH_BLOCK)) {
601 // copyXPMArea(type == CPU ? 67 : 68, 0, 1, length, pos, 51 - length);
602 // }
603 // else if(IsOn(SENSOR_DISP, GRAPH_LINE)) {
604 // copyXPMArea(type == CPU ? 67 : 68, 0, 1, 1, pos, 51 - length);
605 // }
607 // Do not draw the graphs if the temperature data does not make sense
608 // Orginially used the code above but change supplied to fix issues seen by Ben Spencer.
609 // Couldn't be arsed to find the real cause as I don't use the app myself anymore.
610 // Doesn't seem to break anything though
611 if ((temp >= range_lower) && (temp <= range_upper)) {
612 // Draw the graphs
613 if(IsOn(SENSOR_DISP, GRAPH_BLOCK)) {
614 copyXPMArea(type == CPU ? 67 : 68, 0, 1, length, pos, 51 - length);
616 else if(IsOn(SENSOR_DISP, GRAPH_LINE)) {
617 copyXPMArea(type == CPU ? 67 : 68, 0, 1, 1, pos, 51 - length);
623 inline void draw_temp(short value, int type) {
624 short digit;
626 if(value > 0) {
627 digit = value % 10;
628 copyXPMArea((digit * 6) + 1, 65, 5, 7, 46, type == CPU ? CPU_YPOS : SYS_YPOS);
629 if(value > 9) {
630 digit = ((value % 100) - digit) / 10;
631 copyXPMArea((digit * 6) + 1, 65, 5, 7, 40, type == CPU ? CPU_YPOS : SYS_YPOS);
632 if(value > 99) {
633 digit = (value - (value % 100)) / 100;
634 copyXPMArea((digit * 6) + 1, 65, 5, 7, 34, type == CPU ? CPU_YPOS : SYS_YPOS);
641 inline void draw_clear_temps() {
642 if(IsOn(SENSOR_DISP, CPU)) {
643 copyXPMArea(78, 65, 5, 7, 34, CPU_YPOS);
644 copyXPMArea(78, 65, 5, 7, 40, CPU_YPOS);
645 copyXPMArea(78, 65, 5, 7, 46, CPU_YPOS);
647 if(IsOn(SENSOR_DISP, SYS)) {
648 copyXPMArea(78, 65, 5, 7, 34, SYS_YPOS);
649 copyXPMArea(78, 65, 5, 7, 40, SYS_YPOS);
650 copyXPMArea(78, 65, 5, 7, 46, SYS_YPOS);
654 void draw_range_line(double temp, double range, short type) {
655 double each = (double)39 / range;
656 short length = each * (temp - range_lower);
658 copyXPMArea(0, type == D_MAX ? 73 : 74, 59, 1, 2, 51 - length);
662 int init_sensors() {
663 FILE *config_file;
664 int res;
666 config_file = fopen(rc_config, "r");
668 if(config_file == NULL) {
669 fprintf(stderr, "Error opening %s\n", rc_config);
670 return 0;
673 res = sensors_init(config_file);
675 if(res != 0) {
676 fprintf(stderr,"Error initializing sensors: %s\n", sensors_strerror(res));
677 return 0;
680 if(fclose(config_file))
681 perror("Error closing sensors config");
683 return 1;
686 void display_usage() {
687 printf("wmgtemp v0.9\n" \
688 "Usage: wmgtemp [options]\n" \
689 "Options:\n" \
690 " -S, --sensorconf=PATH Specify sensors config file PATH\n" \
691 " [Default: /etc/sensors.conf]\n" \
692 " -s, --scale=SCALE Display temperatures in SCALE\n" \
693 " SCALE=kelvin, fahrenheit\n" \
694 " [Default: celcius]\n" \
695 " -g, --graph=STYLE Display graph as STYLE\n" \
696 " STYLE=line, block\n" \
697 " [Default: line]\n" \
698 " -H, --high=TEMP Display red warning light at TEMP degrees celcius\n" \
699 " [Default: 50]\n" \
700 " -w, --warn=TEMP Display amber warning light at TEMP degrees celcius\n" \
701 " [Default: 45]\n" \
702 " -u, --update=SEC Update the display every SEC seconds\n" \
703 " [Default: 1]\n" \
704 " -m, --min=TEMP Set lower bound of the graph to TEMP degrees celcius\n" \
705 " [Default: 20]\n" \
706 " -M, --max=TEMP Set upper bound of the graph to TEMP degrees celcius\n" \
707 " [Default: 35]\n" \
708 " -1, --feature1=F1 Set the feature for CPU\n" \
709 " [Default: temp1]\n" \
710 " -2, --feature2=F2 Set the feature for SYS\n" \
711 " [Default: temp2]\n" \
712 " -c, --chip=NAME Use sensor chip matching NAME\n" \
713 " [Default: use any]\n" \
714 " -a, --execat=TEMP Execute a command at TEMP degrees celcius\n" \
715 " -e, --exec=COMMAND Execute COMMAND when 'execat' temperature is reached\n" \
716 " -t, --swap Swap CPU and SYS temps\n" \
717 " -q, --quiet Don't display any messages\n" \
718 " -h, --help Displays this help screen\n");
721 void draw_warning_lights(double current_temp) {
722 if(current_temp >= warn_temp && IsOn(SENSOR_DISP, WARN_NONE)) {
723 // Switch from ok to warning.
724 BitOff(SENSOR_DISP, WARN_NONE);
725 BitOn(SENSOR_DISP, WARN_WARN);
726 copyXPMArea(10, 75, 5, 5, 4, 4);
728 if(current_temp < warn_temp && IsOn(SENSOR_DISP, WARN_WARN)) {
729 // Switch from warning to ok.
730 BitOff(SENSOR_DISP, WARN_WARN);
731 BitOn(SENSOR_DISP, WARN_NONE);
732 copyXPMArea(0, 75, 5, 5, 4, 4);
734 if(current_temp >= high_temp && IsOn(SENSOR_DISP, WARN_WARN)) {
735 // Switch from warning to high.
736 BitOff(SENSOR_DISP, WARN_WARN);
737 BitOn(SENSOR_DISP, WARN_HIGH);
738 copyXPMArea(15, 75, 5, 5, 4, 4);
740 if(current_temp < high_temp && IsOn(SENSOR_DISP, WARN_HIGH)) {
741 // Switch from high to warning.
742 BitOff(SENSOR_DISP, WARN_HIGH);
743 BitOn(SENSOR_DISP, WARN_WARN);
744 copyXPMArea(10, 75, 5, 5, 4, 4);
748 inline void blank_type(int type) {
749 switch(type) {
750 case CPU:
751 copyXPMArea(78, 65, 5, 7, 11, CPU_YPOS);
752 copyXPMArea(78, 65, 5, 7, 17, CPU_YPOS);
753 copyXPMArea(78, 65, 5, 7, 23, CPU_YPOS);
755 copyXPMArea(70, 0, 2, 2, 52, CPU_YPOS);
757 copyXPMArea(78, 65, 5, 7, 34, CPU_YPOS);
758 copyXPMArea(78, 65, 5, 7, 40, CPU_YPOS);
759 copyXPMArea(78, 65, 5, 7, 46, CPU_YPOS);
761 copyXPMArea(78, 65, 5, 7, 55, CPU_YPOS);
762 break;
763 case SYS:
764 copyXPMArea(78, 65, 5, 7, 11, SYS_YPOS);
765 copyXPMArea(78, 65, 5, 7, 17, SYS_YPOS);
766 copyXPMArea(78, 65, 5, 7, 23, SYS_YPOS);
768 copyXPMArea(70, 0, 2, 2, 52, SYS_YPOS);
770 copyXPMArea(78, 65, 5, 7, 34, SYS_YPOS);
771 copyXPMArea(78, 65, 5, 7, 40, SYS_YPOS);
772 copyXPMArea(78, 65, 5, 7, 46, SYS_YPOS);
774 copyXPMArea(78, 65, 5, 7, 55, SYS_YPOS);
775 break;
779 inline void draw_max(int type) {
780 // copyXPMArea(1, 81, 17, 7, 11, type == CPU ? CPU_YPOS : SYS_YPOS);
781 copyXPMArea(24, 75, 4, 3, 29, type == CPU ? CPU_YPOS : SYS_YPOS);
784 inline void blank_max(int type) {
785 // copyXPMArea(1, 81, 17, 7, 11, type == CPU ? CPU_YPOS : SYS_YPOS);
786 copyXPMArea(20, 75, 4, 3, 29, type == CPU ? CPU_YPOS : SYS_YPOS);
789 inline void draw_type(int type) {
790 switch(type) {
791 case CPU:
792 copyXPMArea(65, 40, 17, 7, 11, CPU_YPOS);
793 break;
794 case SYS:
795 copyXPMArea(65, 47, 17, 7, 11, SYS_YPOS);
796 break;
800 inline void cycle_temptype() {
801 if(IsOn(SENSOR_DISP, TSCALE_CELCIUS)) {
802 BitOff(SENSOR_DISP, TSCALE_CELCIUS);
803 BitOn(SENSOR_DISP, TSCALE_KELVIN);
805 else if(IsOn(SENSOR_DISP, TSCALE_KELVIN)) {
806 BitOff(SENSOR_DISP, TSCALE_KELVIN);
807 BitOn(SENSOR_DISP, TSCALE_FAHRENHEIT);
809 else if(IsOn(SENSOR_DISP, TSCALE_FAHRENHEIT)) {
810 BitOff(SENSOR_DISP, TSCALE_FAHRENHEIT);
811 BitOn(SENSOR_DISP, TSCALE_CELCIUS);
816 int process_config(int argc, char **argv) {
817 char *rc_graph = NULL;
818 char *rc_scale = NULL;
819 char *rc_high = NULL;
820 char *rc_warn = NULL;
821 char *rc_min = NULL;
822 char *rc_max = NULL;
823 char *rc_execat = NULL;
824 char *rc_exec = NULL;
825 char *rc_delay = NULL;
826 char *rc_swap = NULL;
827 char *rc_feature1 = NULL;
828 char *rc_feature2 = NULL;
829 char *rc_quiet = NULL;
830 char *rc_chip = NULL;
831 short parse_ok = 1;
832 int opt_index;
833 int opt;
834 char *p;
835 char temp[128];
837 rckeys wmgtemp_keys[] = {
838 { "graph", &rc_graph },
839 { "scale", &rc_scale },
840 { "high", &rc_high },
841 { "warn", &rc_warn },
842 { "min", &rc_min },
843 { "max", &rc_max },
844 { "execat", &rc_execat },
845 { "exec", &rc_exec },
846 { "update", &rc_delay },
847 { "swap", &rc_swap },
848 { "quiet", &rc_quiet },
849 { "feature1", &rc_feature1 },
850 { "feature2", &rc_feature2 },
851 { "chip", &rc_chip },
852 { "sensorconf", &rc_config },
853 { NULL, NULL }
856 static struct option long_options[] = {
857 {"graph", required_argument, 0, 'g'},
858 {"scale", required_argument, 0, 's'},
859 {"high", required_argument, 0, 'H'},
860 {"warn", required_argument, 0, 'w'},
861 {"min", required_argument, 0, 'm'},
862 {"max", required_argument, 0, 'M'},
863 {"execat", required_argument, 0, 'a'},
864 {"exec", required_argument, 0, 'e'},
865 {"update", required_argument, 0, 'u'},
866 {"feature1", required_argument, 0, '1'},
867 {"feature2", required_argument, 0, '2'},
868 {"chip", required_argument, 0, 'c'},
869 {"sensorconf", required_argument, 0, 'S'},
870 {"swap", no_argument, 0, 't'},
871 {"quiet", no_argument, 0, 'q'},
872 {"help", no_argument, 0, 'h'},
873 {0, 0, 0, 0}
876 p = getenv("HOME");
877 strcpy(temp, p);
878 strcat(temp, "/.wmgtemprc");
879 parse_rcfile(temp, wmgtemp_keys);
881 // Do getopt stuff.
882 while ((opt = getopt_long(argc, argv, OPT_STRING, long_options, &opt_index)) != -1) {
883 switch(opt) {
884 case 'g':
885 rc_graph = strdup(optarg);
886 break;
887 case 's':
888 rc_scale = strdup(optarg);
889 break;
890 case 'H':
891 rc_high = strdup(optarg);
892 break;
893 case 'w':
894 rc_warn = strdup(optarg);
895 break;
896 case 'm':
897 rc_min = strdup(optarg);
898 break;
899 case 'M':
900 rc_max = strdup(optarg);
901 break;
902 case 'a':
903 rc_execat = strdup(optarg);
904 break;
905 case 'e':
906 rc_exec = strdup(optarg);
907 break;
908 case 'u':
909 rc_delay = strdup(optarg);
910 break;
911 case '1':
912 rc_feature1 = strdup(optarg);
913 break;
914 case '2':
915 rc_feature2 = strdup(optarg);
916 break;
917 case 'c':
918 rc_chip = strdup(optarg);
919 break;
920 case 'S':
921 rc_config = strdup(optarg);
922 break;
923 case 'q':
924 rc_quiet = "y";
925 break;
926 case 't':
927 rc_swap = "y";
928 break;
929 case 'h':
930 display_usage();
931 exit(0);
932 default:
933 display_usage();
934 exit(-1);
938 if(rc_quiet != NULL) {
939 if(!strncmp(rc_quiet, "y", 1)) {
940 quiet = 1;
944 if(rc_feature1 != NULL) {
945 sensor_feature1 = strdup(rc_feature1);
947 if(rc_feature2 != NULL) {
948 sensor_feature2 = strdup(rc_feature2);
950 if(rc_chip != NULL) {
951 sensor_chip = strdup(rc_chip);
953 if(rc_config == NULL) {
954 rc_config = "/etc/sensors.conf";
957 if(rc_graph != NULL) {
958 if(!strncmp(rc_graph, "l", 1)) {
959 BitOff(SENSOR_DISP, GRAPH_BLOCK);
960 BitOn(SENSOR_DISP, GRAPH_LINE);
962 else if(!strncmp(rc_graph, "b", 1)) {
963 BitOff(SENSOR_DISP, GRAPH_LINE);
964 BitOn(SENSOR_DISP, GRAPH_BLOCK);
966 else {
967 printf("Invalid graph type: %s\n", rc_graph);
968 parse_ok = 0;
971 if(rc_scale != NULL) {
972 if(!strncmp(rc_scale, "c", 1)) {
974 else if(!strncmp(rc_scale, "f", 1)) {
975 BitOff(SENSOR_DISP, TSCALE_KELVIN);
976 BitOff(SENSOR_DISP, TSCALE_CELCIUS);
977 BitOn(SENSOR_DISP, TSCALE_FAHRENHEIT);
979 else if(!strncmp(rc_scale, "k", 1)) {
980 BitOff(SENSOR_DISP, TSCALE_CELCIUS);
981 BitOff(SENSOR_DISP, TSCALE_FAHRENHEIT);
982 BitOn(SENSOR_DISP, TSCALE_KELVIN);
984 else {
985 printf("Invalid scale type: %s\n", rc_scale);
986 parse_ok = 0;
990 if(rc_high != NULL) {
991 high_temp = (double)atoi(rc_high);
992 if(!high_temp) {
993 printf("Invalid temperature\n");
994 parse_ok = 0;
996 else {
997 if(quiet == 0)
998 printf("wmgtemp: high temp set to %d degrees celcius.\n", (int)high_temp);
1001 if(rc_warn != NULL) {
1002 warn_temp = (double)atoi(rc_warn);
1003 if(!warn_temp) {
1004 printf("Invalid temperature\n");
1005 parse_ok = 0;
1007 else {
1008 if(quiet == 0)
1009 printf("wmgtemp: warning temp set to %d degrees celcius.\n", (int)warn_temp);
1012 if(rc_max != NULL) {
1013 display_max = range_upper = (double)atoi(rc_max);
1014 if(!range_upper) {
1015 printf("Invalid temperature\n");
1016 parse_ok = 0;
1018 else {
1019 if(quiet == 0)
1020 printf("wmgtemp: Upper range set to %d degrees celcius.\n", (int)range_upper);
1023 if(rc_min != NULL) {
1024 display_min = range_lower = (double)atoi(rc_min);
1025 if(!range_lower) {
1026 printf("Invalid temperature\n");
1027 parse_ok = 0;
1029 else {
1030 if(quiet == 0)
1031 printf("wmgtemp: Lower range set to %d degrees celcius.\n", (int)range_lower);
1034 if(rc_delay != NULL) {
1035 delay = atoi(rc_delay);
1036 if(!delay) {
1037 printf("Invalid delay\n");
1038 parse_ok = 0;
1040 else {
1041 if(quiet == 0)
1042 printf("wmgtemp: update delay set to %d seconds.\n", delay);
1045 if(rc_execat != NULL) {
1046 execat = (double)atoi(rc_execat);
1047 if(!execat) {
1048 printf("Invalid temperature\n");
1049 parse_ok = 0;
1051 else {
1052 if(rc_exec != NULL) {
1053 if(strcmp(rc_exec, "")) {
1054 exec_app = strdup(rc_exec);
1055 printf("wmgtemp: Executing \"%s\" at %d degrees celcius.\n", exec_app, (int)execat);
1057 else {
1058 printf("You must supply an command to execute\n");
1059 parse_ok = 0;
1062 else {
1063 printf("You must supply an command to execute\n");
1064 parse_ok = 0;
1068 if(rc_swap != NULL) {
1069 if(!strncmp(rc_swap, "y", 1)) {
1070 swap_types = 1;
1072 else if(!strncmp(rc_swap, "n", 1)) {
1073 swap_types = 0;
1075 else {
1076 printf("Supply 'y' or 'n' for swap temps\n");
1077 parse_ok = 0;
1081 return parse_ok;