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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
35 #include "backlight_on.xpm"
36 #include "backlight_off.xpm"
46 #define WMBATTERIES_VERSION "0.1.3"
48 #define FREE(data) {if (data) free (data); data = NULL;}
50 #define RATE_HISTORY 10
51 #define BLINK_ONLOADING_TIMEOUT 500
54 #define WINDOWED_BG ". c #AEAAAE"
55 #define MAX_HISTORY 16
56 #define CPUNUM_NONE -1
65 #define DEFAULT_UPDATE_INTERVAL 5
76 #define DEBUGSTRING(STRING) printf("DEBUG: %s\n",STRING);
80 #define DEBUGSTRING(STRING)
84 # define ACPIDEV "/proc/acpi/info"
87 typedef struct AcpiInfos
{
88 const char driver_version
[10];
90 int battery_status
[2];
91 int battery_percentage
[2];
102 typedef struct RateListElem
{
104 struct RateListElem
*next
;
107 typedef enum { LIGHTOFF
, LIGHTON
} light
;
115 static char *display_name
= "";
116 static char light_color
[256] = ""; /* back-light color */
117 char tmp_string
[256];
118 static char *config_file
= NULL
; /* name of configfile */
119 static unsigned update_interval
= DEFAULT_UPDATE_INTERVAL
;
120 static light backlight
= LIGHTOFF
;
121 static unsigned switch_authorized
= True
;
122 static unsigned alarm_level
= 20;
123 static unsigned alarm_level_temp
= 70;
124 static char *notif_cmd
= NULL
;
125 static char *suspend_cmd
= NULL
;
126 static char *standby_cmd
= NULL
;
127 static int mode
= TEMP
;
128 static int togglemode
= TOGGLEMODE
;
129 static int togglespeed
= TOGGLESPEED
;
130 static int animationspeed
= 500;
131 static AcpiInfos cur_acpi_infos
;
132 static number_of_batteries
= 2;
133 static char state_files
[2][256]={BAT0_STATE_FILE
,BAT1_STATE_FILE
};
134 static char info_files
[2][256]={BAT0_INFO_FILE
,BAT1_INFO_FILE
};
135 static char thermal
[256]=THERMAL_FILE
;
136 static char ac_state
[256]=AC_STATE_FILE
;
137 static int history_size
= RATE_HISTORY
;
139 static RateListElem
*rateElements
;
140 static RateListElem
*firstRateElem
;
143 # ifndef ACPI_32_BIT_SUPPORT
144 # define ACPI_32_BIT_SUPPORT 0x0002
150 static void parse_config_file(char *config
);
151 static void update();
152 static void switch_light();
153 static void draw_remaining_time(AcpiInfos infos
);
154 static void draw_batt(AcpiInfos infos
);
155 static void draw_low();
156 static void draw_rate(AcpiInfos infos
);
157 static void draw_temp(AcpiInfos infos
);
158 static void draw_statusdigit(AcpiInfos infos
);
159 static void draw_pcgraph(AcpiInfos infos
);
160 static void parse_arguments(int argc
, char **argv
);
161 static void print_help(char *prog
);
162 static void acpi_getinfos(AcpiInfos
*infos
);
163 static int acpi_exists();
164 static int my_system (char *cmd
);
165 static void blink_batt();
166 static void draw_all();
168 static void debug(char *debug_string
);
170 int acpi_read(AcpiInfos
*i
);
171 int init_stats(AcpiInfos
*k
);
177 static void debug(char *debug_string
){
178 printf("DEBUG: %s\n",debug_string
);
181 int main(int argc
, char **argv
) {
184 XpmColorSymbol colors
[2] = { {"Back0", NULL
, 0}, {"Back1", NULL
, 0} };
190 long togglecounter
=0;
191 long animationcounter
=0;
193 sa
.sa_handler
= SIG_IGN
;
195 sa
.sa_flags
= SA_NOCLDWAIT
;
201 printf("wmbatteries %s (c) Florian Krohs\n"
202 "<florian.krohs@informatik.uni-oldenburg.de>\n\n"
203 "This Software comes with absolut no warranty.\n"
204 "Use at your own risk!\n\n",WMBATTERIES_VERSION
);
206 sigemptyset(&sa
.sa_mask
);
207 sigaction(SIGCHLD
, &sa
, NULL
);
209 /* Parse CommandLine */
210 parse_arguments(argc
, argv
);
212 /* Check for ACPI support */
213 if (!acpi_exists()) {
215 fprintf(stderr
, "No ACPI support in kernel\n");
217 fprintf(stderr
, "Unable to access ACPI info\n");
222 /* Initialize Application */
224 init_stats(&cur_acpi_infos
);
225 //acpi_getinfos(&cur_acpi_infos);
227 dockapp_open_window(display_name
, PACKAGE
, SIZE
, SIZE
, argc
, argv
);
228 dockapp_set_eventmask(ButtonPressMask
);
230 if (strcmp(light_color
,"")) {
231 colors
[0].pixel
= dockapp_getcolor(light_color
);
232 colors
[1].pixel
= dockapp_blendedcolor(light_color
, -24, -24, -24, 1.0);
236 /* change raw xpm data to pixmap */
237 if (dockapp_iswindowed
)
238 backlight_on_xpm
[1] = backlight_off_xpm
[1] = WINDOWED_BG
;
240 if (!dockapp_xpm2pixmap(backlight_on_xpm
, &backdrop_on
, &mask
, colors
, ncolor
)) {
241 fprintf(stderr
, "Error initializing backlit background image.\n");
244 if (!dockapp_xpm2pixmap(backlight_off_xpm
, &backdrop_off
, NULL
, NULL
, 0)) {
245 fprintf(stderr
, "Error initializing background image.\n");
248 if (!dockapp_xpm2pixmap(parts_xpm
, &parts
, NULL
, colors
, ncolor
)) {
249 fprintf(stderr
, "Error initializing parts image.\n");
254 if (!dockapp_iswindowed
) dockapp_setshape(mask
, 0, 0);
255 if (mask
) XFreePixmap(display
, mask
);
257 /* pixmap : draw area */
258 pixmap
= dockapp_XCreatePixmap(SIZE
, SIZE
);
260 /* Initialize pixmap */
261 if (backlight
== LIGHTON
)
262 dockapp_copyarea(backdrop_on
, pixmap
, 0, 0, SIZE
, SIZE
, 0, 0);
264 dockapp_copyarea(backdrop_off
, pixmap
, 0, 0, SIZE
, SIZE
, 0, 0);
266 dockapp_set_background(pixmap
);
269 long update_timeout
= update_interval
*1000;
270 long animation_timeout
= animationspeed
;
271 long toggle_timeout
= togglespeed
*1000;
275 if (cur_acpi_infos
.battery_status
[0]==CHARGING
|| cur_acpi_infos
.battery_status
[1]==CHARGING
)
279 timeout
= update_timeout
;
280 if( charging
&& animation_timeout
<update_timeout
){
281 if(animation_timeout
<toggle_timeout
)
282 timeout
= animation_timeout
;
283 else if(togglemode
) timeout
= toggle_timeout
;
284 } else if(update_timeout
<toggle_timeout
)
285 timeout
= update_timeout
;
286 else if(togglemode
) timeout
= toggle_timeout
;
287 if (dockapp_nextevent_or_timeout(&event
, timeout
)) {
289 switch (event
.type
) {
291 switch (event
.xbutton
.button
) {
292 case 1: switch_light(); break;
293 case 3: mode
=!mode
; draw_all();dockapp_copy2window(pixmap
);break;
301 update_timeout
-= timeout
;
302 animation_timeout
-= timeout
;
303 toggle_timeout
-= timeout
;
304 if(toggle_timeout
<=0){
305 toggle_timeout
= togglespeed
*1000;
311 if(animation_timeout
<=0){
312 animation_timeout
= animationspeed
;
318 if(update_timeout
<=0){
321 update_timeout
= update_interval
*1000;
330 dockapp_copy2window(pixmap
);
340 int init_stats(AcpiInfos
*k
) {
341 int bat_status
[2]={NONE
,NONE
};
350 buf
=(char *)malloc(sizeof(char)*512);
353 /* get info about existing batteries */
354 number_of_batteries
=0;
356 if((fd
= fopen(state_files
[i
], "r"))){
359 if(ptr
= strstr(buf
,"present:")) {
362 bat_status
[i
]|=STATE_OK
;
365 if(ptr
= strstr(buf
,"present rate:")) {
367 sscanf(ptr
,"%d",&k
->rate
[bat
]);
370 if((fd
= fopen(info_files
[i
], "r"))){
373 if(ptr
= strstr(buf
,"present:")) {
376 bat_status
[i
]|=INFO_OK
;
379 if(ptr
= strstr(buf
,"last full capacity:")) {
381 sscanf(ptr
,"%d",&k
->currcap
[bat
]);
387 if(bat_status
[0]==BAT_OK
&& bat_status
[1]==BAT_OK
){
388 printf("BAT0 and BAT1 ok\n");
389 number_of_batteries
=2;
390 } else if(bat_status
[0]==BAT_OK
) {
392 number_of_batteries
=1;
393 } else if(bat_status
[1]==BAT_OK
) {
395 number_of_batteries
=1;
396 strcpy(state_files
[0],state_files
[1]);
397 strcpy(info_files
[0],info_files
[1]);
398 k
->currcap
[0] = k
->currcap
[1];
399 k
->rate
[0] = k
->rate
[1];
402 printf("%i batter%s found in system\n",number_of_batteries
,number_of_batteries
==1 ? "y" : "ies");
405 if ((rateElements
= (RateListElem
*) malloc(history_size
* sizeof(RateListElem
))) == NULL
)
408 firstRateElem
= rateElements
;
411 /* get info about full battery charge */
413 for(bat
=0;bat
<number_of_batteries
;bat
++){
414 if ((fd
= fopen(info_files
[bat
], "r"))) {
417 if(ptr
= strstr(buf
,"last full capacity:")) {
419 sscanf(ptr
,"%d",&k
->currcap
[bat
]);
422 if ((fd
= fopen(state_files
[bat
], "r"))) {
425 if(ptr
= strstr(buf
,"present rate:")) {
427 sscanf(ptr
,"%d",&k
->rate
[bat
]);
433 /* link rateElements */
434 for(hist
=0;hist
<(history_size
-1);hist
++){
435 (*(rateElements
+hist
)).next
= rateElements
+hist
+1;
436 (*(rateElements
+hist
)).rate
[i
] = k
->rate
[i
];
438 (*(rateElements
+history_size
-1)).next
= rateElements
;
439 (*(rateElements
+history_size
-1)).rate
[i
] = k
->rate
[i
];
442 k
->ac_line_status
= 0;
443 k
->battery_status
[0] = 0;
444 k
->battery_percentage
[0] = 0;
446 k
->battery_status
[1] = 0;
447 k
->battery_percentage
[1] = 0;
450 k
->thermal_state
= 0;
451 DEBUGSTRING("end of init_stats()");
454 /* called by timer */
455 static void update() {
456 static light pre_backlight
;
457 static Bool in_alarm_mode
= False
;
459 /* get current battery usage in percent */
460 acpi_getinfos(&cur_acpi_infos
);
463 if (cur_acpi_infos
.low
|| (cur_acpi_infos
.thermal_temp
> alarm_level_temp
)) {
464 if (!in_alarm_mode
) {
465 in_alarm_mode
= True
;
466 pre_backlight
= backlight
;
467 my_system(notif_cmd
);
469 if ( (switch_authorized
) ||
470 ( (! switch_authorized
) && (backlight
!= pre_backlight
) ) ) {
477 in_alarm_mode
= False
;
478 if (backlight
!= pre_backlight
) {
487 static void parse_config_file(char *config
){
491 char stringbuffer
[256];
500 buf
=(char *)malloc(sizeof(char)*512);
503 if(config
!= NULL
) { //config file by command line
504 DEBUGSTRING("using command line given config file name");
506 if((fd
= fopen(config
, "r"))){
507 DEBUGSTRING("config file found\n");
509 DEBUGSTRING("config file NOT found\n");
510 DEBUGSTRING("falling back to default config file\n");
513 if(fd
==NULL
) { // no config file found yet
514 strcpy(stringbuffer
,getenv("HOME"));
515 strcat(stringbuffer
,"/.wmbatteriesrc");
516 DEBUGSTRING("trying config file in your $HOME dir\n");
517 DEBUGSTRING(stringbuffer
);
518 if((fd
= fopen(stringbuffer
, "r"))){
519 DEBUGSTRING("config file found\n");
521 DEBUGSTRING("config file in $HOME dir nonexistant\n");
522 DEBUGSTRING("trying global one in /etc\n");
523 if((fd
= fopen("/etc/wmbatteries", "r"))){
524 DEBUGSTRING("config file found\n");
527 DEBUGSTRING("no config file found. ignoring\n");
532 if(fd
!=NULL
){ // some config file was found, try parsing
533 DEBUGSTRING("begin parsing\n");
534 while( fgets( line
, 255, fd
) != NULL
)
537 item
= strtok( line
, "\t =\n\r" ) ;
538 if( item
!= NULL
&& item
[0] != '#' )
540 value
= strtok( NULL
, "\t =\n\r" ) ;
541 if(!strcmp(item
,"backlight")){
542 if(strcasecmp(value
,"yes") && strcasecmp(value
,"true") && strcasecmp(value
,"false") && strcasecmp(value
,"no")) {
543 printf("backlight option wrong in line %i,use yes/no or true/false\n",linenr
);
545 if(!strcasecmp(value
,"true") || !strcasecmp(value
,"yes")){
548 backlight
= LIGHTOFF
;
553 if(!strcmp(item
,"lightcolor")){
554 strcpy(light_color
,value
);
557 if(!strcmp(item
,"temperature")){
558 strcpy(thermal
,value
);
561 if(!strcmp(item
,"bat0_state")){
562 strcpy(state_files
[0],value
);
565 if(!strcmp(item
,"bat1_state")){
566 strcpy(state_files
[1],value
);
569 if(!strcmp(item
,"bat0_info")){
570 strcpy(info_files
[0],value
);
573 if(!strcmp(item
,"bat1_info")){
574 strcpy(info_files
[1],value
);
577 if(!strcmp(item
,"ac_state")){
578 strcpy(ac_state
,value
);
582 if(!strcmp(item
,"updateinterval")){
585 printf("update interval is out of range in line %i,must be > 0\n",linenr
);
591 if(!strcmp(item
,"alarm")){
593 if(tmp
<1 || tmp
>100) {
594 printf("alarm is out of range in line %i,must be > 0 and <= 100\n",linenr
);
600 if(!strcmp(item
,"togglespeed")){
603 printf("togglespeed variable is out of range in line %i,must be > 0\n",linenr
);
609 if(!strcmp(item
,"animationspeed")){
612 printf("animationspeed variable is out of range in line %i,must be >= 100\n",linenr
);
618 if(!strcmp(item
,"historysize")){
620 if(tmp
<1 || tmp
>1000) {
621 printf("historysize variable is out of range in line %i,must be >=1 and <=1000\n",linenr
);
627 if(!strcmp(item
,"mode")){
628 if(strcmp(value
,"rate") && strcmp(value
,"toggle") && strcmp(value
,"toggle")) {
629 printf("mode must be one of rate,temp,toggle in line %i\n",linenr
);
631 if(strcmp(value
,"rate")) mode
=RATE
;
632 if(strcmp(value
,"temp")) mode
=TEMP
;
633 if(strcmp(value
,"toggle")) togglemode
=1;
643 DEBUGSTRING("end parsing\n");
648 static void draw_all(){
653 if (backlight
== LIGHTON
)
654 dockapp_copyarea(backdrop_on
, pixmap
, 0, 0, 58, 58, 0, 0);
656 dockapp_copyarea(backdrop_off
, pixmap
, 0, 0, 58, 58, 0, 0);
658 draw_remaining_time(cur_acpi_infos
);
659 if(mode
==RATE
) draw_rate(cur_acpi_infos
);
660 else if(mode
==TEMP
) draw_temp(cur_acpi_infos
);
661 draw_statusdigit(cur_acpi_infos
);
662 draw_pcgraph(cur_acpi_infos
);
664 if(cur_acpi_infos
.low
) draw_low();
666 draw_batt(cur_acpi_infos
);
670 /* called when mouse button pressed */
672 static void switch_light() {
676 dockapp_copyarea(backdrop_on
, pixmap
, 0, 0, 58, 58, 0, 0);
679 backlight
= LIGHTOFF
;
680 dockapp_copyarea(backdrop_off
, pixmap
, 0, 0, 58, 58, 0, 0);
684 draw_remaining_time(cur_acpi_infos
);
685 if(mode
==RATE
) draw_rate(cur_acpi_infos
);
686 else if(mode
==TEMP
) draw_temp(cur_acpi_infos
);
687 draw_statusdigit(cur_acpi_infos
);
688 draw_pcgraph(cur_acpi_infos
);
689 if(cur_acpi_infos
.battery_status
[0]==CHARGING
|| cur_acpi_infos
.battery_status
[1]==CHARGING
){
691 } else draw_batt(cur_acpi_infos
);
692 if(cur_acpi_infos
.low
){
696 dockapp_copy2window(pixmap
);
699 static void draw_batt(AcpiInfos infos
){
702 if (backlight
== LIGHTON
) y
= 28;
703 for(i
=0;i
<number_of_batteries
;i
++){
704 if(infos
.battery_status
[i
]==DISCHARGING
){
705 dockapp_copyarea(parts
, pixmap
,33+y
, 63, 9, 5, 16+i
*11, 39);
710 static void draw_remaining_time(AcpiInfos infos
) {
712 if (backlight
== LIGHTON
) y
= 20;
713 if (infos
.ac_line_status
== 1 && !(cur_acpi_infos
.battery_status
[0]==CHARGING
|| cur_acpi_infos
.battery_status
[1]==CHARGING
)){
714 dockapp_copyarea(parts
, pixmap
, 0, 68+68+y
, 10, 20, 17, 5);
715 dockapp_copyarea(parts
, pixmap
, 10, 68+68+y
, 10, 20, 32, 5);
718 dockapp_copyarea(parts
, pixmap
, (infos
.hours_left
/ 10) * 10, 68+y
, 10, 20, 5, 5);
719 dockapp_copyarea(parts
, pixmap
, (infos
.hours_left
% 10) * 10, 68+y
, 10, 20, 17, 5);
720 dockapp_copyarea(parts
, pixmap
, (infos
.minutes_left
/ 10) * 10, 68+y
, 10, 20, 32, 5);
721 dockapp_copyarea(parts
, pixmap
, (infos
.minutes_left
% 10) * 10, 68+y
, 10, 20, 44, 5);
726 static void draw_low() {
728 if (backlight
== LIGHTON
) y
= 28;
729 dockapp_copyarea(parts
, pixmap
,42+y
, 58, 17, 7, 38, 38);
733 static void draw_temp(AcpiInfos infos
) {
734 int temp
= infos
.thermal_temp
;
736 if (backlight
== LIGHTON
) {
740 if (temp
< 0 || temp
>99) temp
= 0;
741 dockapp_copyarea(parts
, pixmap
, (temp
/10)*5 + light_offset
, 40, 5, 9, 23, 46);
742 dockapp_copyarea(parts
, pixmap
, (temp
%10)*5 + light_offset
, 40, 5, 9, 29, 46);
744 dockapp_copyarea(parts
, pixmap
, 10 + light_offset
, 49, 5, 9, 36, 46); //o
745 dockapp_copyarea(parts
, pixmap
, 15 + light_offset
, 49, 5, 9, 42, 46); //C
749 static void blink_batt(){
752 if (backlight
== LIGHTON
) {
755 blink_pos
=(blink_pos
+1)%5;
756 for(bat
=0;bat
<number_of_batteries
;bat
++){
757 if(cur_acpi_infos
.battery_status
[bat
]==CHARGING
){
758 dockapp_copyarea(parts
, pixmap
, blink_pos
*9+light_offset
, 117, 9, 5, 16+bat
*11, 39);
764 static void draw_statusdigit(AcpiInfos infos
) {
766 if (backlight
== LIGHTON
) {
769 if (infos
.ac_line_status
== 1){
770 dockapp_copyarea(parts
, pixmap
,33+light_offset
, 58, 9, 5, 5, 39);
774 static void draw_rate(AcpiInfos infos
) {
776 long rate
= infos
.rate
[0]+infos
.rate
[1];
777 if (backlight
== LIGHTON
) {
781 dockapp_copyarea(parts
, pixmap
, (rate
/10000)*5 + light_offset
, 40, 5, 9, 5, 46);
782 dockapp_copyarea(parts
, pixmap
, ((rate
/1000)%10)*5 + light_offset
, 40, 5, 9, 11, 46);
783 dockapp_copyarea(parts
, pixmap
, ((rate
/100)%10)*5 + light_offset
, 40, 5, 9, 17, 46);
784 dockapp_copyarea(parts
, pixmap
, ((rate
/10)%10)*5 + light_offset
, 40, 5, 9, 23, 46);
785 dockapp_copyarea(parts
, pixmap
, (rate
%10)*5 + light_offset
, 40, 5, 9, 29, 46);
787 dockapp_copyarea(parts
, pixmap
, 0 + light_offset
, 49, 5, 9, 36, 46); //m
788 dockapp_copyarea(parts
, pixmap
, 5 + light_offset
, 49, 5, 9, 42, 46); //W
792 static void draw_pcgraph(AcpiInfos infos
) {
797 if (backlight
== LIGHTON
) {
800 for(bat
=0;bat
<number_of_batteries
;bat
++){
801 width
= (infos
.battery_percentage
[bat
]*32)/100;
802 dockapp_copyarea(parts
, pixmap
, 0, 58+light_offset
, width
, 5, 5, 26+6*bat
);
803 if(infos
.battery_percentage
[bat
] == 100){ // don't display leading 0
804 dockapp_copyarea(parts
, pixmap
, 4*(infos
.battery_percentage
[bat
]/100), 126+light_offset
, 3, 5, 38, 26+6*bat
);
806 if(infos
.battery_percentage
[bat
] > 9){ //don't display leading 0
807 dockapp_copyarea(parts
, pixmap
, 4*((infos
.battery_percentage
[bat
]%100)/10), 126+light_offset
, 3, 5, 42, 26+6*bat
);
809 dockapp_copyarea(parts
, pixmap
, 4*(infos
.battery_percentage
[bat
]%10), 126+light_offset
, 3, 5, 46, 26+6*bat
);
815 static void parse_arguments(int argc
, char **argv
) {
820 for (i
= 1; i
< argc
; i
++) { // first search for config file option
821 if (!strcmp(argv
[i
], "--config") || !strcmp(argv
[i
], "-c")) {
822 config_file
= argv
[i
+ 1];
826 // parse config file before other command line options, to allow overriding
827 parse_config_file(config_file
);
828 for (i
= 1; i
< argc
; i
++) {
829 if (!strcmp(argv
[i
], "--help") || !strcmp(argv
[i
], "-h")) {
830 print_help(argv
[0]), exit(0);
831 } else if (!strcmp(argv
[i
], "--version") || !strcmp(argv
[i
], "-v")) {
832 printf("%s version %s\n", PACKAGE
, VERSION
), exit(0);
833 } else if (!strcmp(argv
[i
], "--display") || !strcmp(argv
[i
], "-d")) {
834 display_name
= argv
[i
+ 1];
836 } else if (!strcmp(argv
[i
], "--backlight") || !strcmp(argv
[i
], "-bl")) {
838 } else if (!strcmp(argv
[i
], "--light-color") || !strcmp(argv
[i
], "-lc")) {
839 strcpy(light_color
,argv
[i
+ 1]);
841 } else if (!strcmp(argv
[i
], "--config") || !strcmp(argv
[i
], "-c")) {
842 config_file
= argv
[i
+ 1];
844 } else if (!strcmp(argv
[i
], "--interval") || !strcmp(argv
[i
], "-i")) {
846 fprintf(stderr
, "%s: error parsing argument for option %s\n",
847 argv
[0], argv
[i
]), exit(1);
848 if (sscanf(argv
[i
+ 1], "%i", &integer
) != 1)
849 fprintf(stderr
, "%s: error parsing argument for option %s\n",
850 argv
[0], argv
[i
]), exit(1);
852 fprintf(stderr
, "%s: argument %s must be >=1\n",
853 argv
[0], argv
[i
]), exit(1);
854 update_interval
= integer
;
856 } else if (!strcmp(argv
[i
], "--alarm") || !strcmp(argv
[i
], "-a")) {
858 fprintf(stderr
, "%s: error parsing argument for option %s\n",
859 argv
[0], argv
[i
]), exit(1);
860 if (sscanf(argv
[i
+ 1], "%i", &integer
) != 1)
861 fprintf(stderr
, "%s: error parsing argument for option %s\n",
862 argv
[0], argv
[i
]), exit(1);
863 if ( (integer
< 0) || (integer
> 100) )
864 fprintf(stderr
, "%s: argument %s must be >=0 and <=100\n",
865 argv
[0], argv
[i
]), exit(1);
866 alarm_level
= integer
;
868 } else if (!strcmp(argv
[i
], "--windowed") || !strcmp(argv
[i
], "-w")) {
869 dockapp_iswindowed
= True
;
870 } else if (!strcmp(argv
[i
], "--broken-wm") || !strcmp(argv
[i
], "-bw")) {
871 dockapp_isbrokenwm
= True
;
872 } else if (!strcmp(argv
[i
], "--notify") || !strcmp(argv
[i
], "-n")) {
873 notif_cmd
= argv
[i
+ 1];
875 } else if (!strcmp(argv
[i
], "--suspend") || !strcmp(argv
[i
], "-s")) {
876 suspend_cmd
= argv
[i
+ 1];
878 } else if (!strcmp(argv
[i
], "--togglespeed") || !strcmp(argv
[i
], "-ts")) {
880 fprintf(stderr
, "%s: error parsing argument for option %s\n",
881 argv
[0], argv
[i
]), exit(1);
882 if (sscanf(argv
[i
+ 1], "%i", &integer
) != 1)
883 fprintf(stderr
, "%s: error parsing argument for option %s\n",
884 argv
[0], argv
[i
]), exit(1);
886 fprintf(stderr
, "%s: argument %s must be positive integer\n",
887 argv
[0], argv
[i
],update_interval
), exit(1);
890 } else if (!strcmp(argv
[i
], "--animationspeed") || !strcmp(argv
[i
], "-as")) {
892 fprintf(stderr
, "%s: error parsing argument for option %s\n",
893 argv
[0], argv
[i
]), exit(1);
894 if (sscanf(argv
[i
+ 1], "%i", &integer
) != 1)
895 fprintf(stderr
, "%s: error parsing argument for option %s\n",
896 argv
[0], argv
[i
]), exit(1);
898 fprintf(stderr
, "%s: argument %s must be >=100\n",
899 argv
[0], argv
[i
]), exit(1);
900 animationspeed
=integer
;
902 } else if (!strcmp(argv
[i
], "--historysize") || !strcmp(argv
[i
], "-hs")) {
904 fprintf(stderr
, "%s: error parsing argument for option %s\n",
905 argv
[0], argv
[i
]), exit(1);
906 if (sscanf(argv
[i
+ 1], "%i", &integer
) != 1)
907 fprintf(stderr
, "%s: error parsing argument for option %s\n",
908 argv
[0], argv
[i
]), exit(1);
909 if (integer
< 1 || integer
> 1000)
910 fprintf(stderr
, "%s: argument %s must be >=1 && <=1000\n",
911 argv
[0], argv
[i
]), exit(1);
912 history_size
=integer
;
914 } else if (!strcmp(argv
[i
], "--mode") || !strcmp(argv
[i
], "-m")) {
916 fprintf(stderr
, "%s: error parsing argument for option %s\n",
917 argv
[0], argv
[i
]), exit(1);
918 if (sscanf(argv
[i
+ 1], "%c", &character
) != 1)
919 fprintf(stderr
, "%s: error parsing argument for option %s\n",
920 argv
[0], argv
[i
]), exit(1);
921 if (!(character
=='t' || character
=='r' || character
=='s'))
922 fprintf(stderr
, "%s: argument %s must be t,r or s\n",
923 argv
[0], argv
[i
]), exit(1);
924 if(character
=='s') togglemode
=1;
925 else if(character
=='t') mode
=TEMP
;
926 else if(character
=='r') mode
=RATE
;
928 } else if (!strcmp(argv
[i
], "--standby") || !strcmp(argv
[i
], "-S")) {
929 standby_cmd
= argv
[i
+ 1];
932 fprintf(stderr
, "%s: unrecognized option '%s'\n", argv
[0], argv
[i
]);
933 print_help(argv
[0]), exit(1);
939 static void print_help(char *prog
)
941 printf("Usage : %s [OPTIONS]\n"
942 "%s - Window Maker mails monitor dockapp\n"
943 " -d, --display <string> display to use\n"
944 " -bl, --backlight turn on back-light\n"
945 " -lc, --light-color <string> back-light color(rgb:6E/C6/3B is default)\n"
946 " -c, --config <string> set filename of config file\n"
947 " -i, --interval <number> number of secs between updates (1 is default)\n"
948 " -a, --alarm <number> low battery level when to raise alarm\n"
950 " -h, --help show this help text and exit\n"
951 " -v, --version show program version and exit\n"
952 " -w, --windowed run the application in windowed mode\n"
953 " -bw, --broken-wm activate broken window manager fix\n"
954 " -n, --notify <string> command to launch when alarm is on\n"
955 " -s, --suspend <string> set command for acpi suspend\n"
956 " -S, --standby <string> set command for acpi standby\n"
957 " -m, --mode [t|r|s] set mode for the lower row , \n"
958 " t=temperature,r=current rate,s=toggle\n"
959 " -ts --togglespeed <int> set toggle speed in seconds\n"
960 " -as --animationspeed <int> set speed for charging animation in msec\n"
961 " -hs --historysize <int> set size of history for calculating\n"
962 " average power consumption rate\n",
965 * ? -f, --file : configuration file
970 static void acpi_getinfos(AcpiInfos
*infos
) {
971 DEBUGSTRING("acpi_getinfos\n")
973 #if defined(linux) || defined(solaris)
977 (acpi_read(&temp_info
))
981 fprintf(stderr
, "Cannot read ACPI information: %i\n");
988 if (access(ACPIDEV
, R_OK
))
995 static int my_system (char *cmd
) {
997 extern char **environ
;
999 if (cmd
== 0) return 1;
1001 if (pid
== -1) return -1;
1010 execve ("/bin/sh", argv
, environ
);
1021 int acpi_read(AcpiInfos
*i
) {
1024 int capacity
[2],remain
[2];
1029 buf
=(char *)malloc(sizeof(char)*512);
1030 RateListElem currRateElement
;
1040 DEBUGSTRING("acpi_read()\n")
1042 /* get acpi thermal cpu info */
1043 if ((fd
= fopen(thermal
, "r"))) {
1044 fscanf(fd
, "temperature: %d", &i
->thermal_temp
);
1047 if ((fd
= fopen(ac_state
, "r"))) {
1049 fscanf(fd
, "state: %s", buf
);
1051 if(strstr(buf
, "on-line") != NULL
) i
->ac_line_status
=1;
1052 if(strstr(buf
, "off-line") != NULL
) i
->ac_line_status
=0;
1054 for(bat
=0;bat
<number_of_batteries
;bat
++){
1056 if ((fd
= fopen(state_files
[bat
], "r"))) {
1058 fread(buf
,512,1,fd
);
1060 if(( ptr
= strstr(buf
,"charging state:"))) {
1065 i
->battery_status
[bat
]=1;
1068 i
->battery_status
[bat
]=3;
1071 i
->battery_status
[bat
]=0;
1075 if ((ptr
= strstr (buf
, "remaining capacity:"))) {
1077 sscanf(ptr
,"%d",&i
->remain
[bat
]);
1079 if ((ptr
= strstr (buf
, "present rate:"))) {
1081 sscanf(ptr
,"%d",&((*firstRateElem
).rate
[bat
]));
1085 i
->battery_percentage
[bat
] = (((float)(i
->remain
[bat
])*100)/cur_acpi_infos
.currcap
[bat
]);
1089 currRateElement
= *firstRateElem
;
1090 if(currRateElement
.rate
[bat
]!=0){
1091 for(hist
=0;hist
<history_size
;hist
++){
1092 if(currRateElement
.rate
[bat
]!=0){
1093 rate
+= currRateElement
.rate
[bat
];
1094 } else rate
+= (*firstRateElem
).rate
[bat
];
1095 currRateElement
= *currRateElement
.next
;
1105 rate
= rate
/ history_size
;
1106 i
->rate
[bat
] = rate
;
1109 if((i
->battery_status
[0]==1 || i
->battery_status
[1]==1) && (i
->rate
[0]+i
->rate
[1])>0){
1110 time
= (float)(i
->remain
[0]+i
->remain
[1])/(float)(i
->rate
[0]+i
->rate
[1]);
1111 i
->hours_left
=(int)time
;
1112 i
->minutes_left
=(int)((time
-(int)time
)*60);
1114 if(i
->battery_status
[0]==0 && i
->battery_status
[1]==0){
1118 if((i
->battery_status
[0]==3||i
->battery_status
[1]==3) && (i
->rate
[0]>0 || i
->rate
[1]>0)){
1119 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]);
1120 i
->hours_left
=(int)time
;
1121 i
->minutes_left
=(int)(60*(time
-(int)time
));
1123 for(bat
=0;bat
<number_of_batteries
;bat
++){
1124 allremain
+= i
->remain
[bat
];
1125 allcapacity
+= cur_acpi_infos
.currcap
[bat
];
1128 cur_acpi_infos
.low
=0;
1130 if(((double)allremain
/(double)allcapacity
)*100<alarm_level
){
1131 cur_acpi_infos
.low
=1;
1135 DEBUGSTRING("MID acpi_read()\n")
1136 firstRateElem
= ((*firstRateElem
).next
);
1138 DEBUGSTRING("END acpi_read()\n")