Remove trailing whitespace.
[dockapps.git] / wmpower / src / wmpower.c
blob568528e6dbcd84ec619b9b62a5234f7b1ff97e08
1 /***************************************************************************
2 wmpower.c - description
3 -------------------
4 begin : Feb 10 2003
5 copyright : (C) 2003,2004,2005 by Noberasco Michele
6 e-mail : noberasco.gnu@disi.unige.it
7 ***************************************************************************/
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License for more details. *
20 * *
21 * You should have received a copy of the GNU General Public License *
22 * along with this program; if not, write to the *
23 * Free Software Foundation, Inc., *
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
25 * *
26 ***************************************************************************/
28 /***************************************************************************
29 Many thanks to Filippo Panessa for his wmab...
30 it's code was the base for this program
31 ***************************************************************************/
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36 #include <string.h>
37 #include <time.h>
38 #include <X11/X.h>
39 #include <X11/xpm.h>
41 #include "open_syslog_on_stderr.h"
42 #include "power_management.h"
43 #include "dockapp.h"
44 #include "wmpower_master.xpm"
45 #include "wmpower_master_LowColor.xpm"
46 #include "wmpower_mask.xbm"
48 void ParseCMDLine (int argc, char *argv[]);
49 void ShowACstatus(int ac_on_line);
50 void ShowFanStatus(int fanstatus);
51 void ShowTemperature(int temp, int is_celsius);
52 void ShowChargeStatus(int charging);
53 void ShowBatteryTime(int time, int percentage, int charging, int ac_on_line);
54 void ShowBatteryPercentage(int percentage);
55 void ShowBatteryLed(int present, int percentage, int ac_on_line);
57 int no_meddling = 0; /* Should we stop managing power status? */
58 int no_full_battery = 0; /* Should we always use max power when plugged? */
60 int CriticalLevel = 10; /* Battery critical level */
61 int LowLevel = 40; /* Battery low level */
63 #define CMDLINELEN 512
64 int WarnTime = 2; /* When to execute the warn command */
65 char WarnCommand[CMDLINELEN] = ""; /* The warn command to execute */
67 float BlinkRate = 3.00; /* blinks per second */
69 /* Controls beeping when you get to critical */
70 /* battery level: Off by default */
71 int Beep = 0; /* to beep or not to beep? */
72 int Volume = 50; /* ring bell at 50% volume */
74 /* Mouse wheel */
75 unsigned int wheel_button_up = 4;
76 unsigned int wheel_button_down = 5;
78 /* Monitor first battery by default */
79 int our_battery = 1;
81 /* Use a lower number of colors for the poor saps on */
82 /* 8-bit displays -- common on laptops! */
83 int UseLowColorPixmap = 0;
85 int main (int argc, char *argv[])
87 pm_status power_status;
88 XEvent event;
89 int fbc_toggle=1, fbc_auto=1;
90 int old_battery_charging;
91 time_t polling = 0;
92 struct timespec delay; /* pause between interface updates */
93 char Command[CMDLINELEN+3];
94 int warned = 0;
96 delay.tv_sec = 0;
97 delay.tv_nsec = 500000000;
99 BlinkRate = (BlinkRate >= 0.0) ? BlinkRate : -1.0 * BlinkRate;
100 waittime = 0; /* /proc polling interval */
101 minBrightness = -1;
102 maxBrightness = -1;
104 fprintf(stderr, "\nWelcome to wmpower version %s...\n", VERSION);
106 cpufreq_online_governor = NULL;
107 cpufreq_offline_governor = NULL;
109 /* Parse any command line arguments. */
110 ParseCMDLine (argc, argv);
112 /* Check for Power Management support */
113 if (!pm_support(our_battery))
115 fprintf (stderr, "\nNo power management support...\n");
116 return EXIT_FAILURE;
119 /* Create window of the program */
120 if (UseLowColorPixmap) openXwindow (argc, argv, wmpower_master_LowColor, (char *) wmpower_mask_bits, wmpower_mask_width, wmpower_mask_height);
121 else openXwindow (argc, argv, wmpower_master, (char *) wmpower_mask_bits, wmpower_mask_width, wmpower_mask_height);
123 /* Loop until we die... */
124 while (1)
126 /* Get current power status */
127 old_battery_charging = power_status.battery_charging;
128 if (!waittime) get_power_status(&power_status);
129 else if ((time(NULL)-polling) >= waittime)
131 get_power_status(&power_status);
132 polling = time(NULL);
135 /* Manage power features only if function is not disabled */
136 if (!no_meddling)
138 /* Re-enable auto power mode switching whan battery status changes */
139 if (old_battery_charging != power_status.battery_charging) fbc_auto = 1;
141 /* Enable fast battery charge mode if on AC and batt is charging */
142 if (!no_full_battery && power_status.ac_on_line && power_status.battery_charging && fbc_auto && !fbc_toggle && !(power_status.battery_percentage == 100))
144 fast_battery_charge(1);
145 fbc_toggle = 1;
146 fbc_auto = 1;
149 /* Adjust variables value when battery reaches 100% */
150 if (fbc_toggle && (power_status.battery_percentage == 100))
152 fast_battery_charge(0);
153 fbc_toggle = 0;
154 fbc_auto = 1;
157 /* If battery not present and fast charge mode, disable it */
158 if (fbc_toggle && !(power_status.battery_present))
160 fast_battery_charge(0);
161 fbc_toggle = 0;
162 fbc_auto = 1;
165 /* Set various pm features whenever applicable */
166 set_pm_features();
169 /* Execute the warning command, if needed */
170 if (WarnCommand && *WarnCommand && !power_status.ac_on_line && !warned
171 && power_status.battery_time <= WarnTime)
173 warned = 1;
174 sprintf(Command, "%s &", WarnCommand);
175 system(Command);
177 if (power_status.ac_on_line)
178 warned = 0;
180 /* Show AC status led */
181 ShowACstatus(power_status.ac_on_line);
183 /* Display FAN status. */
184 ShowFanStatus(power_status.fan_status);
186 /* Display temperature. */
187 ShowTemperature(power_status.temperature, power_status.temp_is_celsius);
189 /* Display charge status */
190 ShowChargeStatus(power_status.battery_charging);
192 /* Display the "Time Left" */
193 ShowBatteryTime(power_status.battery_time, power_status.battery_percentage, power_status.battery_charging, power_status.ac_on_line);
195 /* Display battery percentage */
196 ShowBatteryPercentage(power_status.battery_percentage);
198 /* Display battery status led */
199 ShowBatteryLed(power_status.battery_present, power_status.battery_percentage, power_status.ac_on_line);
201 /* Process any pending X events. */
202 while (XPending (display))
204 XNextEvent (display, &event);
205 switch (event.type)
207 case Expose:
208 RedrawWindow ();
209 continue;
210 case ButtonPress:
211 if (no_meddling)
213 fprintf(stderr, "You cannot change PM status in '-no-meddling' mode of operation\n");
214 continue;
216 if (event.xbutton.button == wheel_button_up)
218 lcdBrightness_UpOneStep();
219 continue;
221 if (event.xbutton.button == wheel_button_down)
223 lcdBrightness_DownOneStep();
224 continue;
226 fbc_toggle = !get_fast_battery_charge_mode();
227 fbc_auto = 0;
228 fast_battery_charge(fbc_toggle);
229 continue;
230 case ButtonRelease:
231 continue;
235 /* Redraw and wait for next update */
236 RedrawWindow ();
237 nanosleep(&delay, NULL);
242 /* Show AC status led */
243 void ShowACstatus(int ac_on_line)
245 /* Check AC status. */
246 if (ac_on_line)
247 /* AC on-line. I.e. we are "plugged-in". */
248 copyXPMArea (68, 6, 12, 7, 31, 35);
249 else
250 /* AC off-line. I.e. we are using battery. */
251 copyXPMArea (68, 20, 12, 7, 31, 35);
256 /* Display fan status */
257 void ShowFanStatus(int fan_status)
259 if (fan_status == PM_Error)
261 /* Plot the red - Symbol */
262 copyXPMArea (165, 60, 6, 7, 23, 50);
263 return;
266 /* Plot fan status: 0 not active, 1 running */
267 copyXPMArea (fan_status * 6 + 4, 69, 6, 7, 23, 50);
272 /* Display charge status */
273 void ShowChargeStatus(int charging)
275 /* Paste up the default charge status and time */
276 copyXPMArea ( 83, 93, 41, 9, 15, 7);
277 copyXPMArea (104, 6, 5, 7, 6, 7);
279 /* Check to see if we are charging. */
280 if (charging)
281 /* Battery Status: Charging. */
282 copyXPMArea (82, 68, 7, 9, 6, 7);
283 else
284 /* Battery Status: NOT Charging. */
285 copyXPMArea (88, 68, 7, 9, 6, 7);
290 /* Display battery status led */
291 void ShowBatteryLed(int present, int percentage, int ac_on_line)
293 static int Toggle; /* Switch for battery led blinking */
295 if (!present)
297 copyXPMArea (95, 19, 16, 10, 43, 34);
298 return;
301 /* Battery Status: Critical. */
302 /* Blink the red led on/off... */
303 if (percentage <= CriticalLevel && !ac_on_line)
305 if (Toggle || (BlinkRate == 0.0))
307 if (Beep && !ac_on_line) XBell (display, Volume);
308 Toggle = 0;
309 copyXPMArea (4, 105, 16, 10, 43, 34);
311 else
313 Toggle = 1;
314 copyXPMArea (58, 105, 16, 10, 43, 34);
316 return;
319 /* Battery Status: Low. */
320 /* Fixed yellow led */
321 if (percentage <= LowLevel)
323 copyXPMArea (22, 105, 16, 10, 43, 34);
324 return;
327 /* Battery Status: Normal. */
328 /* Fixed blue led */
329 copyXPMArea (40, 105, 16, 10, 43, 34);
334 /* Display Temperature */
335 void ShowTemperature(int temp, int temp_is_celsius)
337 /* PM_Error getting temperature value */
338 /* or value out of range */
339 if ( (temp < 0) || (temp > 99) )
341 /* Plot PM_Error message */
342 copyXPMArea (165, 60, 6, 7, 33, 50);
343 copyXPMArea (165, 60, 6, 7, 39, 50);
344 copyXPMArea (135, 60, 6, 7, 45, 50);
345 copyXPMArea ( 68, 69, 6, 7, 51, 50);
346 return;
349 /* Plot temperature */
350 if (temp < 10) copyXPMArea ((temp) * 6 + 4, 69, 6, 7, 39, 50);
351 else
353 copyXPMArea ((temp / 10) * 6 + 4, 69, 6, 7, 33, 50);
354 copyXPMArea ((temp % 10) * 6 + 4, 69, 6, 7, 39, 50);
357 /* Plot the ° Symbol */
358 copyXPMArea (135, 60, 6, 7, 45, 50);
360 /* Plot the C Symbol */
361 if (temp_is_celsius) copyXPMArea (68, 69, 6, 7, 51, 50);
366 /* Display the "Time Left". This time means: */
367 /* If not charging: Time left before battery drains to 0% */
368 /* If charging: Time left before battery gets to maximum */
369 void ShowBatteryTime(int time, int percentage, int charging, int ac_on_line)
371 int battery_time=time;
372 int hour, min;
374 if ( (battery_time < -1) || ((battery_time == 0)&&(percentage == 0)) || (ac_on_line&&(percentage == 100)) )
376 /* In case battery is fully charged and we are on AC power,
377 * or there is some problem reading battery time
378 * we display a "null" indicator (--:--)
380 copyXPMArea (83, 106, 41, 9, 15, 7);
381 return;
384 /* Now we are sure battery time is consistent */
385 if (percentage == 100) battery_time = 0;
386 hour = battery_time / 60;
387 min = battery_time % 60;
389 /* show '-' sign when charging, '+' otherwise */
390 if (charging)
391 copyXPMArea (83, 106, 41, 9, 15, 7);
392 else
393 copyXPMArea (83, 93, 41, 9, 15, 7);
395 /* Show 10's (hour) */
396 copyXPMArea ((hour / 10) * 7 + 5, 93, 7, 9, 21, 7);
398 /* Show 1's (hour) */
399 copyXPMArea ((hour % 10) * 7 + 5, 93, 7, 9, 29, 7);
401 /* colon */
402 copyXPMArea (76, 93, 2, 9, 38, 7);
404 /* Show 10's (min) */
405 copyXPMArea ((min / 10) * 7 + 5, 93, 7, 9, 42, 7);
407 /* Show 1's (min) */
408 copyXPMArea ((min % 10) * 7 + 5, 93, 7, 9, 50, 7);
413 /* Display battery percentage */
414 void ShowBatteryPercentage(int percentage)
416 int k;
418 copyXPMArea (76, 81, 19, 7, 7, 34); /* Show Default % */
419 copyXPMArea (66, 31, 49, 9, 7, 21); /* Show Default Meter */
421 if (percentage == 100)
423 /* If 100%, show 100% */
424 copyXPMArea (15, 81, 1, 7, 7, 34);
425 copyXPMArea ( 5, 81, 6, 7, 9, 34);
426 copyXPMArea ( 5, 81, 6, 7, 15, 34);
427 copyXPMArea (64, 81, 7, 7, 21, 34); /* Show '%' */
429 /* Show rainbow battery bar */
430 copyXPMArea (66, 52, 49, 9, 7, 21);
432 return;
434 /* Show 10's */
435 if (percentage >= 10) copyXPMArea ((percentage / 10) * 6 + 4, 81, 6, 7, 9, 34);
437 /* Show 1's */
438 copyXPMArea ((percentage % 10) * 6 + 4, 81, 6, 7, 15, 34);
440 /* Show '%' */
441 copyXPMArea (64, 81, 7, 7, 21, 34);
443 /* Show Meter */
444 k = percentage * 49 / 100;
446 /* Show rainbow battery bar */
447 copyXPMArea (66, 52, k, 9, 7, 21);
448 if (k % 2) copyXPMArea (66 + k - 1, 52, 1, 9, 7 + k - 1, 21);
449 else copyXPMArea (66 + k, 52, 1, 9, 7 + k, 21);
454 /* Show message about usage */
455 void message(void)
457 printf("\nwmpower is a tool for checking and setting power management status for");
458 printf("\nlaptop computers. Right now is supports both APM and APCI enabled");
459 printf("\nkernels, plus special support for Toshiba and Compal hardware.");
460 printf("\n\nUsage: wmpower [options]\n");
461 printf("\n\nOptions:\n");
462 printf("\t-no-meddling\t\tDon't manage power status, just show info.\n");
463 printf("\t-no-full-battery\tDon't wait for 100%% battery before going back\n");
464 printf("\t\t\t\tto full power.\n");
465 printf("\t-no-cpufreq\t\tDon't scale CPU frequency according to power status.\n");
466 printf("\t-no-noflushd\t\tDisable use of \"noflushd\" daemon:\n");
467 printf("\t\t\t\tnoflushd is a tool for managing spin-down\n");
468 printf("\t\t\t\tof hard disks after a certain amount of time\n");
469 printf("\t\t\t\tsee <http://noflushd.sourceforge.net> for details.\n");
470 printf("\t-no-toshiba\t\tDisable direct access to toshiba hardware,\n");
471 printf("\t\t\t\tuse only generic ACPI/APM calls instead.\n");
472 printf("\t\t\t\tThis is recommended on newer toshibas.\n");
473 printf("\t-battery <num>\t\tMonitor your nth battery instead of first one.\n");
474 printf("\t-display <display>\tUse alternate display.\n");
475 printf("\t-geometry <geometry>\twmpower window geometry.\n");
476 printf("\t-l\t\t\tUse a low-color pixmap.\n");
477 printf("\t-L <LowLevel>\t\tDefine level at which yellow LED turns on.\n");
478 printf("\t-C <CriticalLevel>\tDefine level at which red LED turns on.\n");
479 printf("\t-B <Volume>\t\tBeep at Critical Level (-100%% to 100%%).\n");
480 printf("\t-w <command>\t\tWarn command to run when remaining time is low.\n");
481 printf("\t-W <minutes>\t\tMinutes of remaining time when to run warn command.\n");
482 printf("\t-u <seconds>\t\tSet wmpower polling interval.\n");
483 printf("\t-m <brightness>\t\tUse this LCD brightness value while running on battery power.\n");
484 printf("\t-M <brightness>\t\tUse this LCD brightness value while running on AC power.\n");
485 printf("\t-g <governor>\t\tUse this CPUFreq scaling governor while running on battery power.\n");
486 printf("\t-G <governor>\t\tUse this CPUFreq scaling governor while running on AC power.\n");
487 printf("\t-s\t\t\tMake wmpower log to syslog instead of standard error.\n");
488 printf("\t-h\t\t\tDisplay this help screen.\n");
489 printf("\nClicking on program window at run-time overrides any option,");
490 printf("\nthus switching between low-power and full-power modes.");
491 printf("\nYou can use the mouse wheel to adjust your lcd brightness.\n\n");
493 exit(EXIT_FAILURE);
497 /* Parse command line arguments */
498 void ParseCMDLine (int argc, char *argv[])
500 char *cmdline;
501 int i;
503 for (i = 1; i < argc; i++)
505 cmdline = argv[i];
506 if (cmdline[0] == '-')
508 switch (cmdline[1])
510 case 'b':
511 if (!strcmp(cmdline, "-battery"))
513 if (argc == i+1) message();
514 our_battery = atoi(argv[++i]);
515 if (our_battery < 1) message();
517 else message();
518 break;
519 case 'd':
520 ++i;
521 break;
522 case 'C':
523 if (cmdline[2] != '\0') message();
524 if (argc == i+1) message();
525 CriticalLevel = atoi (argv[++i]);
526 break;
527 case 'g':
528 if ( !strcmp(cmdline, "-geometry"))
530 extern char *Geometry;
531 if ( argc == i+1 ) message();
532 Geometry = argv[++i];
533 break;
535 if (cmdline[2] != '\0') message();
536 cpufreq_offline_governor = argv[++i];
537 break;
538 case 'G':
539 if (cmdline[2] != '\0') message();
540 cpufreq_online_governor = argv[++i];
541 break;
542 case 'L':
543 if (cmdline[2] != '\0') message();
544 if (argc == i+1) message();
545 LowLevel = atoi (argv[++i]);
546 break;
547 case 'l':
548 if (cmdline[2] != '\0') message();
549 UseLowColorPixmap = 1;
550 break;
551 case 'u':
552 if (cmdline[2] != '\0') message();
553 if (argc == i+1) message();
554 waittime = atoi (argv[++i]);
555 if (waittime <= 0) message();
556 fprintf(stderr, "Polling time: %d second%s.\n", waittime, (waittime == 1)? "" : "s");
557 break;
558 case 'B':
559 if (cmdline[2] != '\0') message();
560 if (argc == i+1) message();
561 Beep = 1;
562 Volume = atoi (argv[++i]);
563 break;
564 case 'm':
565 if (cmdline[2] != '\0') message();
566 if (argc == i+1) message();
567 minBrightness = atoi (argv[++i]);
568 break;
569 case 'M':
570 if (cmdline[2] != '\0') message();
571 if (argc == i+1) message();
572 maxBrightness = atoi (argv[++i]);
573 break;
574 case 'w':
575 if (cmdline[2] != '\0') message();
576 if (argc == i+1) message();
577 strncpy(WarnCommand, argv[++i], CMDLINELEN-1);
578 break;
579 case 'W':
580 if (cmdline[2] != '\0') message();
581 if (argc == i+1) message();
582 WarnTime = atoi (argv[++i]);
583 break;
584 case 's':
585 if (cmdline[2] != '\0') message();
586 fprintf(stderr, "Switching to syslog logging...\n");
587 open_syslog_on_stderr();
588 break;
589 case 'n':
590 if (!strcmp(cmdline, "-no-meddling")) {no_meddling = 1; break;}
591 if (!strcmp(cmdline, "-no-full-battery")) {no_full_battery = 1; break;}
592 if (!strcmp(cmdline, "-no-noflushd")) {set_noflushd_use(0); break;}
593 if (!strcmp(cmdline, "-no-toshiba")) {set_toshiba_hardware_use(0); break;}
594 if (!strcmp(cmdline, "-no-cpufreq")) {set_cpufreq_use(0); break;}
595 default:
596 message();
599 else message();