2 * wmbatteries - A dockapp to monitor ACPI status of two batteries
3 * Copyright (C) 2003 Florian Krohs <krohs@uni.de>
5 * Based on work by Thomas Nemeth <tnemeth@free.fr>
6 * Copyright (C) 2002 Thomas Nemeth <tnemeth@free.fr>
7 * and on work by Seiichi SATO <ssato@sh.rim.or.jp>
8 * Copyright (C) 2001,2002 Seiichi SATO <ssato@sh.rim.or.jp>
9 * and on work by Mark Staggs <me@markstaggs.net>
10 * Copyright (C) 2002 Mark Staggs <me@markstaggs.net>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 #include "backlight_on.xpm"
36 #include "backlight_off.xpm"
48 #define WMBATTERIES_VERSION "0.1.3"
50 #define FREE(data) {if (data) free (data); data = NULL;}
52 #define RATE_HISTORY 10
53 #define BLINK_ONLOADING_TIMEOUT 500
56 #define WINDOWED_BG ". c #AEAAAE"
57 #define MAX_HISTORY 16
58 #define CPUNUM_NONE -1
67 #define DEFAULT_UPDATE_INTERVAL 5
78 #define DEBUGSTRING(STRING) printf("DEBUG: %s\n",STRING);
82 #define DEBUGSTRING(STRING)
86 # define ACPIDEV "/proc/acpi/info"
89 typedef struct AcpiInfos {
90 const char driver_version[10];
92 int battery_status[2];
93 int battery_percentage[2];
104 typedef struct RateListElem {
106 struct RateListElem *next;
109 typedef enum { LIGHTOFF, LIGHTON } light;
117 static char *display_name = "";
118 static char light_color[256] = ""; /* back-light color */
119 char tmp_string[256];
120 static char *config_file = NULL; /* name of configfile */
121 static unsigned update_interval = DEFAULT_UPDATE_INTERVAL;
122 static light backlight = LIGHTOFF;
123 static unsigned switch_authorized = True;
124 static unsigned alarm_level = 20;
125 static unsigned alarm_level_temp = 70;
126 static char *notif_cmd = NULL;
127 static char *suspend_cmd = NULL;
128 static char *standby_cmd = NULL;
129 static int mode = TEMP;
130 static int togglemode = TOGGLEMODE;
131 static int togglespeed = TOGGLESPEED;
132 static int animationspeed = 500;
133 static AcpiInfos cur_acpi_infos;
134 static number_of_batteries = 2;
135 static char state_files[2][256]={BAT0_STATE_FILE,BAT1_STATE_FILE};
136 static char info_files[2][256]={BAT0_INFO_FILE,BAT1_INFO_FILE};
137 static char thermal[256]=THERMAL_FILE;
138 static char ac_state[256]=AC_STATE_FILE;
139 static int history_size = RATE_HISTORY;
141 static RateListElem *rateElements;
142 static RateListElem *firstRateElem;
145 # ifndef ACPI_32_BIT_SUPPORT
146 # define ACPI_32_BIT_SUPPORT 0x0002
152 static void parse_config_file(char *config);
153 static void update();
154 static void switch_light();
155 static void draw_remaining_time(AcpiInfos infos);
156 static void draw_batt(AcpiInfos infos);
157 static void draw_low();
158 static void draw_rate(AcpiInfos infos);
159 static void draw_temp(AcpiInfos infos);
160 static void draw_statusdigit(AcpiInfos infos);
161 static void draw_pcgraph(AcpiInfos infos);
162 static void parse_arguments(int argc, char **argv);
163 static void print_help(char *prog);
164 static void acpi_getinfos(AcpiInfos *infos);
165 static int acpi_exists();
166 static int my_system (char *cmd);
167 static void blink_batt();
168 static void draw_all();
170 static void debug(char *debug_string);
172 int acpi_read(AcpiInfos *i);
173 int init_stats(AcpiInfos *k);
179 static void debug(char *debug_string){
180 printf("DEBUG: %s\n",debug_string);
183 int main(int argc, char **argv) {
186 XpmColorSymbol colors[2] = { {"Back0", NULL, 0}, {"Back1", NULL, 0} };
192 long togglecounter=0;
193 long animationcounter=0;
195 sa.sa_handler = SIG_IGN;
197 sa.sa_flags = SA_NOCLDWAIT;
203 printf("wmbatteries %s (c) Florian Krohs\n"
204 "<florian.krohs@informatik.uni-oldenburg.de>\n\n"
205 "This Software comes with absolut no warranty.\n"
206 "Use at your own risk!\n\n",WMBATTERIES_VERSION);
208 sigemptyset(&sa.sa_mask);
209 sigaction(SIGCHLD, &sa, NULL);
211 /* Parse CommandLine */
212 parse_arguments(argc, argv);
214 /* Check for ACPI support */
215 if (!acpi_exists()) {
217 fprintf(stderr, "No ACPI support in kernel\n");
219 fprintf(stderr, "Unable to access ACPI info\n");
224 /* Initialize Application */
226 init_stats(&cur_acpi_infos);
227 //acpi_getinfos(&cur_acpi_infos);
229 dockapp_open_window(display_name, PACKAGE, SIZE, SIZE, argc, argv);
230 dockapp_set_eventmask(ButtonPressMask);
232 if (strcmp(light_color,"")) {
233 colors[0].pixel = dockapp_getcolor(light_color);
234 colors[1].pixel = dockapp_blendedcolor(light_color, -24, -24, -24, 1.0);
238 /* change raw xpm data to pixmap */
239 if (dockapp_iswindowed)
240 backlight_on_xpm[1] = backlight_off_xpm[1] = WINDOWED_BG;
242 if (!dockapp_xpm2pixmap(backlight_on_xpm, &backdrop_on, &mask, colors, ncolor)) {
243 fprintf(stderr, "Error initializing backlit background image.\n");
246 if (!dockapp_xpm2pixmap(backlight_off_xpm, &backdrop_off, NULL, NULL, 0)) {
247 fprintf(stderr, "Error initializing background image.\n");
250 if (!dockapp_xpm2pixmap(parts_xpm, &parts, NULL, colors, ncolor)) {
251 fprintf(stderr, "Error initializing parts image.\n");
256 if (!dockapp_iswindowed) dockapp_setshape(mask, 0, 0);
257 if (mask) XFreePixmap(display, mask);
259 /* pixmap : draw area */
260 pixmap = dockapp_XCreatePixmap(SIZE, SIZE);
262 /* Initialize pixmap */
263 if (backlight == LIGHTON)
264 dockapp_copyarea(backdrop_on, pixmap, 0, 0, SIZE, SIZE, 0, 0);
266 dockapp_copyarea(backdrop_off, pixmap, 0, 0, SIZE, SIZE, 0, 0);
268 dockapp_set_background(pixmap);
271 long update_timeout = update_interval*1000;
272 long animation_timeout = animationspeed;
273 long toggle_timeout = togglespeed*1000;
277 if (cur_acpi_infos.battery_status[0]==CHARGING || cur_acpi_infos.battery_status[1]==CHARGING)
281 timeout = update_timeout;
282 if( charging && animation_timeout<update_timeout){
283 if(animation_timeout<toggle_timeout)
284 timeout = animation_timeout;
285 else if(togglemode) timeout = toggle_timeout;
286 } else if(update_timeout<toggle_timeout)
287 timeout = update_timeout;
288 else if(togglemode) timeout = toggle_timeout;
289 if (dockapp_nextevent_or_timeout(&event, timeout)) {
291 switch (event.type) {
293 switch (event.xbutton.button) {
294 case 1: switch_light(); break;
295 case 3: mode=!mode; draw_all();dockapp_copy2window(pixmap);break;
303 update_timeout -= timeout;
304 animation_timeout -= timeout;
305 toggle_timeout -= timeout;
306 if(toggle_timeout<=0){
307 toggle_timeout = togglespeed*1000;
313 if(animation_timeout<=0){
314 animation_timeout = animationspeed;
320 if(update_timeout<=0){
323 update_timeout = update_interval*1000;
332 dockapp_copy2window(pixmap);
342 int init_stats(AcpiInfos *k) {
343 int bat_status[2]={NONE,NONE};
352 buf=(char *)malloc(sizeof(char)*512);
355 /* get info about existing batteries */
356 number_of_batteries=0;
358 if((fd = fopen(state_files[i], "r"))){
361 if(ptr = strstr(buf,"present:")) {
364 bat_status[i]|=STATE_OK;
367 if(ptr = strstr(buf,"present rate:")) {
369 sscanf(ptr,"%d",&k->rate[bat]);
372 if((fd = fopen(info_files[i], "r"))){
375 if(ptr = strstr(buf,"present:")) {
378 bat_status[i]|=INFO_OK;
381 if(ptr = strstr(buf,"last full capacity:")) {
383 sscanf(ptr,"%d",&k->currcap[bat]);
389 if(bat_status[0]==BAT_OK && bat_status[1]==BAT_OK){
390 printf("BAT0 and BAT1 ok\n");
391 number_of_batteries=2;
392 } else if(bat_status[0]==BAT_OK) {
394 number_of_batteries=1;
395 } else if(bat_status[1]==BAT_OK) {
397 number_of_batteries=1;
398 strcpy(state_files[0],state_files[1]);
399 strcpy(info_files[0],info_files[1]);
400 k->currcap[0] = k->currcap[1];
401 k->rate[0] = k->rate[1];
404 printf("%i batter%s found in system\n",number_of_batteries,number_of_batteries==1 ? "y" : "ies");
407 if ((rateElements = (RateListElem *) malloc(history_size * sizeof(RateListElem))) == NULL)
410 firstRateElem = rateElements;
413 /* get info about full battery charge */
415 for(bat=0;bat<number_of_batteries;bat++){
416 if ((fd = fopen(info_files[bat], "r"))) {
419 if(ptr = strstr(buf,"last full capacity:")) {
421 sscanf(ptr,"%d",&k->currcap[bat]);
424 if ((fd = fopen(state_files[bat], "r"))) {
427 if(ptr = strstr(buf,"present rate:")) {
429 sscanf(ptr,"%d",&k->rate[bat]);
435 /* link rateElements */
436 for(hist=0;hist<(history_size-1);hist++){
437 (*(rateElements+hist)).next = rateElements+hist+1;
438 (*(rateElements+hist)).rate[i] = k->rate[i];
440 (*(rateElements+history_size-1)).next = rateElements;
441 (*(rateElements+history_size-1)).rate[i] = k->rate[i];
444 k->ac_line_status = 0;
445 k->battery_status[0] = 0;
446 k->battery_percentage[0] = 0;
448 k->battery_status[1] = 0;
449 k->battery_percentage[1] = 0;
452 k->thermal_state = 0;
453 DEBUGSTRING("end of init_stats()");
456 /* called by timer */
457 static void update() {
458 static light pre_backlight;
459 static Bool in_alarm_mode = False;
461 /* get current battery usage in percent */
462 acpi_getinfos(&cur_acpi_infos);
465 if (cur_acpi_infos.low || (cur_acpi_infos.thermal_temp > alarm_level_temp)) {
466 if (!in_alarm_mode) {
467 in_alarm_mode = True;
468 pre_backlight = backlight;
469 my_system(notif_cmd);
471 if ( (switch_authorized) ||
472 ( (! switch_authorized) && (backlight != pre_backlight) ) ) {
479 in_alarm_mode = False;
480 if (backlight != pre_backlight) {
489 static void parse_config_file(char *config){
493 char stringbuffer[256];
502 buf=(char *)malloc(sizeof(char)*512);
505 if(config != NULL) { //config file by command line
506 DEBUGSTRING("using command line given config file name");
508 if((fd = fopen(config, "r"))){
509 DEBUGSTRING("config file found\n");
511 DEBUGSTRING("config file NOT found\n");
512 DEBUGSTRING("falling back to default config file\n");
515 if(fd==NULL) { // no config file found yet
516 // stringbuffer=strcat(getenv("HOME"),"/.wmbatteriesrc");
517 strcpy(stringbuffer,getenv("HOME"));
518 strcat(stringbuffer,"/.wmbatteriesrc");
521 DEBUGSTRING("trying config file in your $HOME dir\n");
522 DEBUGSTRING(getenv("HOME"));
523 DEBUGSTRING(stringbuffer);
524 if((fd = fopen(stringbuffer, "r"))){
525 DEBUGSTRING("config file found\n");
527 DEBUGSTRING("config file in $HOME dir nonexistant\n");
528 DEBUGSTRING("trying global one in /etc\n");
529 if((fd = fopen("/etc/wmbatteries", "r"))){
530 DEBUGSTRING("config file found\n");
533 DEBUGSTRING("no config file found. ignoring\n");
538 if(fd!=NULL){ // some config file was found, try parsing
539 DEBUGSTRING("begin parsing\n");
540 while( fgets( line, 255, fd ) != NULL )
543 item = strtok( line, "\t =\n\r" ) ;
544 if( item != NULL && item[0] != '#' )
546 value = strtok( NULL, "\t =\n\r" ) ;
547 if(!strcmp(item,"backlight")){
548 if(strcasecmp(value,"yes") && strcasecmp(value,"true") && strcasecmp(value,"false") && strcasecmp(value,"no")) {
549 printf("backlight option wrong in line %i,use yes/no or true/false\n",linenr);
551 if(!strcasecmp(value,"true") || !strcasecmp(value,"yes")){
554 backlight = LIGHTOFF;
559 if(!strcmp(item,"lightcolor")){
560 strcpy(light_color,value);
563 if(!strcmp(item,"temperature")){
564 strcpy(thermal,value);
567 if(!strcmp(item,"bat0_state")){
568 strcpy(state_files[0],value);
571 if(!strcmp(item,"bat1_state")){
572 strcpy(state_files[1],value);
575 if(!strcmp(item,"bat0_info")){
576 strcpy(info_files[0],value);
579 if(!strcmp(item,"bat1_info")){
580 strcpy(info_files[1],value);
583 if(!strcmp(item,"ac_state")){
584 strcpy(ac_state,value);
588 if(!strcmp(item,"updateinterval")){
591 printf("update interval is out of range in line %i,must be > 0\n",linenr);
597 if(!strcmp(item,"alarm")){
599 if(tmp<1 || tmp>100) {
600 printf("alarm is out of range in line %i,must be > 0 and <= 100\n",linenr);
606 if(!strcmp(item,"togglespeed")){
609 printf("togglespeed variable is out of range in line %i,must be > 0\n",linenr);
615 if(!strcmp(item,"animationspeed")){
618 printf("animationspeed variable is out of range in line %i,must be >= 100\n",linenr);
624 if(!strcmp(item,"historysize")){
626 if(tmp<1 || tmp>1000) {
627 printf("historysize variable is out of range in line %i,must be >=1 and <=1000\n",linenr);
633 if(!strcmp(item,"mode")){
634 if(strcmp(value,"rate") && strcmp(value,"toggle") && strcmp(value,"toggle")) {
635 printf("mode must be one of rate,temp,toggle in line %i\n",linenr);
637 if(strcmp(value,"rate")) mode=RATE;
638 if(strcmp(value,"temp")) mode=TEMP;
639 if(strcmp(value,"toggle")) togglemode=1;
649 DEBUGSTRING("end parsing\n");
654 static void draw_all(){
659 if (backlight == LIGHTON)
660 dockapp_copyarea(backdrop_on, pixmap, 0, 0, 58, 58, 0, 0);
662 dockapp_copyarea(backdrop_off, pixmap, 0, 0, 58, 58, 0, 0);
664 draw_remaining_time(cur_acpi_infos);
665 if(mode==RATE) draw_rate(cur_acpi_infos);
666 else if(mode==TEMP) draw_temp(cur_acpi_infos);
667 draw_statusdigit(cur_acpi_infos);
668 draw_pcgraph(cur_acpi_infos);
670 if(cur_acpi_infos.low) draw_low();
672 draw_batt(cur_acpi_infos);
676 /* called when mouse button pressed */
678 static void switch_light() {
682 dockapp_copyarea(backdrop_on, pixmap, 0, 0, 58, 58, 0, 0);
685 backlight = LIGHTOFF;
686 dockapp_copyarea(backdrop_off, pixmap, 0, 0, 58, 58, 0, 0);
690 draw_remaining_time(cur_acpi_infos);
691 if(mode==RATE) draw_rate(cur_acpi_infos);
692 else if(mode==TEMP) draw_temp(cur_acpi_infos);
693 draw_statusdigit(cur_acpi_infos);
694 draw_pcgraph(cur_acpi_infos);
695 if(cur_acpi_infos.battery_status[0]==CHARGING || cur_acpi_infos.battery_status[1]==CHARGING){
697 } else draw_batt(cur_acpi_infos);
698 if(cur_acpi_infos.low){
702 dockapp_copy2window(pixmap);
705 static void draw_batt(AcpiInfos infos){
708 if (backlight == LIGHTON) y = 28;
709 for(i=0;i<number_of_batteries;i++){
710 if(infos.battery_status[i]==DISCHARGING){
711 dockapp_copyarea(parts, pixmap,33+y , 63, 9, 5, 16+i*11, 39);
716 static void draw_remaining_time(AcpiInfos infos) {
718 if (backlight == LIGHTON) y = 20;
719 if (infos.ac_line_status == 1 && !(cur_acpi_infos.battery_status[0]==CHARGING || cur_acpi_infos.battery_status[1]==CHARGING)){
720 dockapp_copyarea(parts, pixmap, 0, 68+68+y, 10, 20, 17, 5);
721 dockapp_copyarea(parts, pixmap, 10, 68+68+y, 10, 20, 32, 5);
724 dockapp_copyarea(parts, pixmap, (infos.hours_left / 10) * 10, 68+y, 10, 20, 5, 5);
725 dockapp_copyarea(parts, pixmap, (infos.hours_left % 10) * 10, 68+y, 10, 20, 17, 5);
726 dockapp_copyarea(parts, pixmap, (infos.minutes_left / 10) * 10, 68+y, 10, 20, 32, 5);
727 dockapp_copyarea(parts, pixmap, (infos.minutes_left % 10) * 10, 68+y, 10, 20, 44, 5);
732 static void draw_low() {
734 if (backlight == LIGHTON) y = 28;
735 dockapp_copyarea(parts, pixmap,42+y , 58, 17, 7, 38, 38);
739 static void draw_temp(AcpiInfos infos) {
740 int temp = infos.thermal_temp;
742 if (backlight == LIGHTON) {
746 if (temp < 0 || temp>99) temp = 0;
747 dockapp_copyarea(parts, pixmap, (temp/10)*5 + light_offset, 40, 5, 9, 23, 46);
748 dockapp_copyarea(parts, pixmap, (temp%10)*5 + light_offset, 40, 5, 9, 29, 46);
750 dockapp_copyarea(parts, pixmap, 10 + light_offset, 49, 5, 9, 36, 46); //o
751 dockapp_copyarea(parts, pixmap, 15 + light_offset, 49, 5, 9, 42, 46); //C
755 static void blink_batt(){
758 if (backlight == LIGHTON) {
761 blink_pos=(blink_pos+1)%5;
762 for(bat=0;bat<number_of_batteries;bat++){
763 if(cur_acpi_infos.battery_status[bat]==CHARGING){
764 dockapp_copyarea(parts, pixmap, blink_pos*9+light_offset , 117, 9, 5, 16+bat*11, 39);
770 static void draw_statusdigit(AcpiInfos infos) {
772 if (backlight == LIGHTON) {
775 if (infos.ac_line_status == 1){
776 dockapp_copyarea(parts, pixmap,33+light_offset , 58, 9, 5, 5, 39);
780 static void draw_rate(AcpiInfos infos) {
782 long rate = infos.rate[0]+infos.rate[1];
783 if (backlight == LIGHTON) {
787 dockapp_copyarea(parts, pixmap, (rate/10000)*5 + light_offset, 40, 5, 9, 5, 46);
788 dockapp_copyarea(parts, pixmap, ((rate/1000)%10)*5 + light_offset, 40, 5, 9, 11, 46);
789 dockapp_copyarea(parts, pixmap, ((rate/100)%10)*5 + light_offset, 40, 5, 9, 17, 46);
790 dockapp_copyarea(parts, pixmap, ((rate/10)%10)*5 + light_offset, 40, 5, 9, 23, 46);
791 dockapp_copyarea(parts, pixmap, (rate%10)*5 + light_offset, 40, 5, 9, 29, 46);
793 dockapp_copyarea(parts, pixmap, 0 + light_offset, 49, 5, 9, 36, 46); //m
794 dockapp_copyarea(parts, pixmap, 5 + light_offset, 49, 5, 9, 42, 46); //W
798 static void draw_pcgraph(AcpiInfos infos) {
803 if (backlight == LIGHTON) {
806 for(bat=0;bat<number_of_batteries;bat++){
807 width = (infos.battery_percentage[bat]*32)/100;
808 dockapp_copyarea(parts, pixmap, 0, 58+light_offset, width, 5, 5, 26+6*bat);
809 if(infos.battery_percentage[bat] == 100){ // don't display leading 0
810 dockapp_copyarea(parts, pixmap, 4*(infos.battery_percentage[bat]/100), 126+light_offset, 3, 5, 38, 26+6*bat);
812 if(infos.battery_percentage[bat] > 9){ //don't display leading 0
813 dockapp_copyarea(parts, pixmap, 4*((infos.battery_percentage[bat]%100)/10), 126+light_offset, 3, 5, 42, 26+6*bat);
815 dockapp_copyarea(parts, pixmap, 4*(infos.battery_percentage[bat]%10), 126+light_offset, 3, 5, 46, 26+6*bat);
821 static void parse_arguments(int argc, char **argv) {
826 for (i = 1; i < argc; i++) { // first search for config file option
827 if (!strcmp(argv[i], "--config") || !strcmp(argv[i], "-c")) {
828 config_file = argv[i + 1];
832 // parse config file before other command line options, to allow overriding
833 parse_config_file(config_file);
834 for (i = 1; i < argc; i++) {
835 if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")) {
836 print_help(argv[0]), exit(0);
837 } else if (!strcmp(argv[i], "--version") || !strcmp(argv[i], "-v")) {
838 printf("%s version %s\n", PACKAGE, VERSION), exit(0);
839 } else if (!strcmp(argv[i], "--display") || !strcmp(argv[i], "-d")) {
840 display_name = argv[i + 1];
842 } else if (!strcmp(argv[i], "--backlight") || !strcmp(argv[i], "-bl")) {
844 } else if (!strcmp(argv[i], "--light-color") || !strcmp(argv[i], "-lc")) {
845 strcpy(light_color,argv[i + 1]);
847 } else if (!strcmp(argv[i], "--config") || !strcmp(argv[i], "-c")) {
848 config_file = argv[i + 1];
850 } else if (!strcmp(argv[i], "--interval") || !strcmp(argv[i], "-i")) {
852 fprintf(stderr, "%s: error parsing argument for option %s\n",
853 argv[0], argv[i]), exit(1);
854 if (sscanf(argv[i + 1], "%i", &integer) != 1)
855 fprintf(stderr, "%s: error parsing argument for option %s\n",
856 argv[0], argv[i]), exit(1);
858 fprintf(stderr, "%s: argument %s must be >=1\n",
859 argv[0], argv[i]), exit(1);
860 update_interval = integer;
862 } else if (!strcmp(argv[i], "--alarm") || !strcmp(argv[i], "-a")) {
864 fprintf(stderr, "%s: error parsing argument for option %s\n",
865 argv[0], argv[i]), exit(1);
866 if (sscanf(argv[i + 1], "%i", &integer) != 1)
867 fprintf(stderr, "%s: error parsing argument for option %s\n",
868 argv[0], argv[i]), exit(1);
869 if ( (integer < 0) || (integer > 100) )
870 fprintf(stderr, "%s: argument %s must be >=0 and <=100\n",
871 argv[0], argv[i]), exit(1);
872 alarm_level = integer;
874 } else if (!strcmp(argv[i], "--windowed") || !strcmp(argv[i], "-w")) {
875 dockapp_iswindowed = True;
876 } else if (!strcmp(argv[i], "--broken-wm") || !strcmp(argv[i], "-bw")) {
877 dockapp_isbrokenwm = True;
878 } else if (!strcmp(argv[i], "--notify") || !strcmp(argv[i], "-n")) {
879 notif_cmd = argv[i + 1];
881 } else if (!strcmp(argv[i], "--suspend") || !strcmp(argv[i], "-s")) {
882 suspend_cmd = argv[i + 1];
884 } else if (!strcmp(argv[i], "--togglespeed") || !strcmp(argv[i], "-ts")) {
886 fprintf(stderr, "%s: error parsing argument for option %s\n",
887 argv[0], argv[i]), exit(1);
888 if (sscanf(argv[i + 1], "%i", &integer) != 1)
889 fprintf(stderr, "%s: error parsing argument for option %s\n",
890 argv[0], argv[i]), exit(1);
892 fprintf(stderr, "%s: argument %s must be positive integer\n",
893 argv[0], argv[i],update_interval), exit(1);
896 } else if (!strcmp(argv[i], "--animationspeed") || !strcmp(argv[i], "-as")) {
898 fprintf(stderr, "%s: error parsing argument for option %s\n",
899 argv[0], argv[i]), exit(1);
900 if (sscanf(argv[i + 1], "%i", &integer) != 1)
901 fprintf(stderr, "%s: error parsing argument for option %s\n",
902 argv[0], argv[i]), exit(1);
904 fprintf(stderr, "%s: argument %s must be >=100\n",
905 argv[0], argv[i]), exit(1);
906 animationspeed=integer;
908 } else if (!strcmp(argv[i], "--historysize") || !strcmp(argv[i], "-hs")) {
910 fprintf(stderr, "%s: error parsing argument for option %s\n",
911 argv[0], argv[i]), exit(1);
912 if (sscanf(argv[i + 1], "%i", &integer) != 1)
913 fprintf(stderr, "%s: error parsing argument for option %s\n",
914 argv[0], argv[i]), exit(1);
915 if (integer < 1 || integer > 1000)
916 fprintf(stderr, "%s: argument %s must be >=1 && <=1000\n",
917 argv[0], argv[i]), exit(1);
918 history_size=integer;
920 } else if (!strcmp(argv[i], "--mode") || !strcmp(argv[i], "-m")) {
922 fprintf(stderr, "%s: error parsing argument for option %s\n",
923 argv[0], argv[i]), exit(1);
924 if (sscanf(argv[i + 1], "%c", &character) != 1)
925 fprintf(stderr, "%s: error parsing argument for option %s\n",
926 argv[0], argv[i]), exit(1);
927 if (!(character=='t' || character=='r' || character=='s'))
928 fprintf(stderr, "%s: argument %s must be t,r or s\n",
929 argv[0], argv[i]), exit(1);
930 if(character=='s') togglemode=1;
931 else if(character=='t') mode=TEMP;
932 else if(character=='r') mode=RATE;
934 } else if (!strcmp(argv[i], "--standby") || !strcmp(argv[i], "-S")) {
935 standby_cmd = argv[i + 1];
938 fprintf(stderr, "%s: unrecognized option '%s'\n", argv[0], argv[i]);
939 print_help(argv[0]), exit(1);
945 static void print_help(char *prog)
947 printf("Usage : %s [OPTIONS]\n"
948 "%s - Window Maker mails monitor dockapp\n"
949 " -d, --display <string> display to use\n"
950 " -bl, --backlight turn on back-light\n"
951 " -lc, --light-color <string> back-light color(rgb:6E/C6/3B is default)\n"
952 " -c, --config <string> set filename of config file\n"
953 " -i, --interval <number> number of secs between updates (1 is default)\n"
954 " -a, --alarm <number> low battery level when to raise alarm\n"
956 " -h, --help show this help text and exit\n"
957 " -v, --version show program version and exit\n"
958 " -w, --windowed run the application in windowed mode\n"
959 " -bw, --broken-wm activate broken window manager fix\n"
960 " -n, --notify <string> command to launch when alarm is on\n"
961 " -s, --suspend <string> set command for acpi suspend\n"
962 " -S, --standby <string> set command for acpi standby\n"
963 " -m, --mode [t|r|s] set mode for the lower row , \n"
964 " t=temperature,r=current rate,s=toggle\n"
965 " -ts --togglespeed <int> set toggle speed in seconds\n"
966 " -as --animationspeed <int> set speed for charging animation in msec\n"
967 " -hs --historysize <int> set size of history for calculating\n"
968 " average power consumption rate\n",
971 * ? -f, --file : configuration file
976 static void acpi_getinfos(AcpiInfos *infos) {
977 DEBUGSTRING("acpi_getinfos\n")
979 #if defined(linux) || defined(solaris)
983 (acpi_read(&temp_info))
987 fprintf(stderr, "Cannot read ACPI information: %i\n");
994 if (access(ACPIDEV, R_OK))
1001 static int my_system (char *cmd) {
1003 extern char **environ;
1005 if (cmd == 0) return 1;
1007 if (pid == -1) return -1;
1016 execve ("/bin/sh", argv, environ);
1027 int acpi_read(AcpiInfos *i) {
1030 int capacity[2],remain[2];
1035 buf=(char *)malloc(sizeof(char)*512);
1036 RateListElem currRateElement;
1046 DEBUGSTRING("acpi_read()\n")
1048 /* get acpi thermal cpu info */
1049 if ((fd = fopen(thermal, "r"))) {
1050 fscanf(fd, "temperature: %d", &i->thermal_temp);
1053 if ((fd = fopen(ac_state, "r"))) {
1055 fscanf(fd, "state: %s", buf);
1057 if(strstr(buf, "on-line") != NULL) i->ac_line_status=1;
1058 if(strstr(buf, "off-line") != NULL) i->ac_line_status=0;
1060 for(bat=0;bat<number_of_batteries;bat++){
1062 if ((fd = fopen(state_files[bat], "r"))) {
1064 fread(buf,512,1,fd);
1066 if(( ptr = strstr(buf,"charging state:"))) {
1071 i->battery_status[bat]=1;
1074 i->battery_status[bat]=3;
1077 i->battery_status[bat]=0;
1081 if ((ptr = strstr (buf, "remaining capacity:"))) {
1083 sscanf(ptr,"%d",&i->remain[bat]);
1085 if ((ptr = strstr (buf, "present rate:"))) {
1087 sscanf(ptr,"%d",&((*firstRateElem).rate[bat]));
1091 i->battery_percentage[bat] = (((float)(i->remain[bat])*100)/cur_acpi_infos.currcap[bat]);
1095 currRateElement = *firstRateElem;
1096 if(currRateElement.rate[bat]!=0){
1097 for(hist=0;hist<history_size;hist++){
1098 if(currRateElement.rate[bat]!=0){
1099 rate += currRateElement.rate[bat];
1100 } else rate+= (*firstRateElem).rate[bat];
1101 currRateElement = *currRateElement.next;
1111 rate = rate / history_size;
1112 i->rate[bat] = rate;
1115 if((i->battery_status[0]==1 || i->battery_status[1]==1) && (i->rate[0]+i->rate[1])>0){
1116 time = (float)(i->remain[0]+i->remain[1])/(float)(i->rate[0]+i->rate[1]);
1117 i->hours_left=(int)time;
1118 i->minutes_left=(int)((time-(int)time)*60);
1120 if(i->battery_status[0]==0 && i->battery_status[1]==0){
1124 if((i->battery_status[0]==3||i->battery_status[1]==3) && (i->rate[0]>0 || i->rate[1]>0)){
1125 time = (float)(cur_acpi_infos.currcap[0] - i->remain[0] + cur_acpi_infos.currcap[1] - i->remain[1])/(float)(i->rate[0]+i->rate[1]);
1126 i->hours_left=(int)time;
1127 i->minutes_left=(int)(60*(time-(int)time));
1129 for(bat=0;bat<number_of_batteries;bat++){
1130 allremain += i->remain[bat];
1131 allcapacity += cur_acpi_infos.currcap[bat];
1134 cur_acpi_infos.low=0;
1136 if(((double)allremain/(double)allcapacity)*100<alarm_level){
1137 cur_acpi_infos.low=1;
1141 DEBUGSTRING("MID acpi_read()\n")
1142 firstRateElem = ((*firstRateElem).next);
1144 DEBUGSTRING("END acpi_read()\n")