wmclockmon: update change-log
[dockapps.git] / wmwifi / src / wmwifi.c
blobbf95dc814e98cf257ab5f8332c1cd8f841e06f5c
1 /*
2 * wmupmon - A dockapp to monitor system uptime
3 * Copyright (C) 2003 Justin Spadea <jzs@mail.rit.edu>
5 * Based on work by Seiichi SATO <ssato@sh.rim.or.jp>
6 * Copyright (C) 2001,2002 Seiichi SATO <ssato@sh.rim.or.jp>
7 * AND by Mark Staggs <me@markstaggs.net>
8 * Copyright (C) 2002 Mark Staggs <me@markstaggs.net>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include "dockapp.h"
27 #include <dockapp.h>
28 #include "display_link.xpm"
29 #include "display_stats.xpm"
30 #include "parts.xpm"
31 #include "font.xpm"
32 #include "wmwifi.h"
34 #define SIZE 58
35 #define WINDOWED_BG " \tc #AEAAAE"
36 #define MAX_HISTORY 16
37 #define CPUNUM_NONE -1
39 typedef enum { LIGHTON, LIGHTOFF } light;
40 typedef enum { STANDARD, EXTENDED } interface;
41 Pixmap pixmap;
42 Pixmap fonts;
43 Pixmap backdrop_on;
44 Pixmap display_link;
45 Pixmap display_stats;
46 Pixmap backdrop_on_stats;
47 Pixmap display_error;
48 Pixmap parts;
49 Pixmap mask;
50 static char *display_name = "";
51 static char *light_color = NULL; /* back-light color */
52 static unsigned update_interval = 1;
53 static light backlight = LIGHTOFF;
54 static interface gui = STANDARD;
55 static interface lgui = STANDARD;
56 Bool wmwifi_learn;
57 Bool scroll = True;
58 int count;
59 struct theme {
60 char *bg;
61 char *fg;
62 char *hi;
63 char *mt;
65 struct theme tcur;
66 struct theme blgt;
67 struct wifi lwfi;
68 time_t last_update = 0;
69 time_t last_swap = 0;
70 time_t now = 0;
72 /* prototypes */
73 static void update(struct wifi *wfi);
74 static void switch_interface(struct wifi *wfi);
75 static void do_theme(struct theme thm);
76 static void draw_junk(struct wifi *wfi);
77 static void draw_ext(struct wifi *wfi);
78 static void draw_text(char *text, int dx, int dy, Bool digit);
79 static void parse_arguments(int argc, char **argv);
80 static void print_help(char *prog);
81 static void copy_wifi(struct wifi *lwfi, struct wifi *wfi);
82 static void clear_wifi(struct wifi *wfi);
83 static void refresh(struct theme thm);
85 int main(int argc, char **argv)
87 XEvent event;
88 XButtonPressedEvent *bevent;
89 int i;
90 struct wifi wfi;
92 wfi.ifnum = 0;
94 /* Parse CommandLine */
95 parse_arguments(argc, argv);
97 /* Initialize Application */
98 dockapp_open_window(display_name, PACKAGE, SIZE, SIZE, argc, argv);
99 dockapp_set_eventmask(ButtonPressMask);
101 if (backlight == LIGHTON) {
102 do_theme(blgt);
103 } else {
104 do_theme(tcur);
107 /* shape window */
108 if (!dockapp_iswindowed)
109 dockapp_setshape(mask, 0, 0);
110 if (mask)
111 XFreePixmap(display, mask);
113 /* pixmap : draw area */
114 pixmap = dockapp_XCreatePixmap(SIZE, SIZE);
116 /* Initialize pixmap */
118 if (gui == STANDARD)
119 dockapp_copyarea(display_link, pixmap, 0, 0, SIZE, SIZE, 0, 0);
120 else
121 dockapp_copyarea(display_stats, pixmap, 0, 0, SIZE, SIZE, 0, 0);
123 dockapp_set_background(pixmap);
124 dockapp_show();
125 draw_text("link", 32, 47, False);
127 /* Main loop */
128 while (1) {
129 if (time(NULL) != last_update)
130 update(&wfi);
132 while (XPending(display)) {
133 XNextEvent(display, &event);
135 switch (event.type) {
136 case ButtonPress:
137 bevent = (XButtonPressedEvent *) & event;
138 switch (bevent->button & 0xff) {
139 case Button1:
140 scroll = (scroll) ? False : True;
141 count = 0;
142 break;
143 case Button2:
144 next_if(&wfi);
145 break;
146 case Button3:
147 switch_interface(&wfi);
148 break;
150 break;
151 default: /* make gcc happy */
152 break;
155 usleep(update_interval*1000000L);
157 return 0;
160 static void do_theme(struct theme thm)
162 XpmColorSymbol colors[4] =
163 { {"Back0", NULL, 0}, {"Fore0", NULL, 0}, {"High0", NULL, 0},
164 {"Mid0", NULL, 0}
166 int ncolor = 0;
167 int i;
169 colors[0].pixel = dockapp_getcolor(thm.bg);
170 colors[1].pixel = dockapp_getcolor(thm.fg);
171 colors[2].pixel = dockapp_getcolor(thm.hi);
172 colors[3].pixel = dockapp_getcolor(thm.mt);
173 ncolor = 4;
174 /* change raw xpm data to pixmap */
175 if (dockapp_iswindowed)
176 display_link_xpm[1] = WINDOWED_BG;
178 if (!dockapp_xpm2pixmap
179 (display_link_xpm, &display_link, &mask, colors, ncolor)) {
180 fprintf(stderr, "Error initializing background image.\n");
181 exit(1);
183 if (!dockapp_xpm2pixmap
184 (display_stats_xpm, &display_stats, &mask, colors, ncolor)) {
185 fprintf(stderr, "Error initializing background image.\n");
186 exit(1);
188 if (!dockapp_xpm2pixmap(parts_xpm, &parts, NULL, colors, ncolor)) {
189 fprintf(stderr, "Error initializing parts image.\n");
190 exit(1);
192 if (!dockapp_xpm2pixmap(font_xpm, &fonts, NULL, colors, ncolor)) {
193 fprintf(stderr, "Error initializing fonts image.\n");
194 exit(1);
198 /* called by timer */
199 static void update(struct wifi *wfi)
201 int sw, percent;
202 extern int count;
203 //char *str = calloc(1, sizeof(wfi->ifname) + sizeof(wfi->essid) + 3);
204 char str[512];
206 now = time(NULL);
208 /* get current link level from /proc/net/wireless */
209 copy_wifi(&lwfi, wfi);
210 get_wifi_info(wfi);
212 if (wfi->max_qual == -1) {
213 tcur.bg = "rgb:ff/0/0";
214 tcur.fg = "rgb:0/0/0";
215 tcur.mt = "rgb:00/00/00";
216 do_theme(tcur);
217 dockapp_copyarea(display_link, pixmap, 0, 0, 58, 58, 0, 0);
218 draw_text("ERROR", (56 / 2) - 5 * 2.5, 4, False);
219 } else {
220 /* all clear */
222 /* If percent == 0, show backlight */
223 percent = wfi->link / (wfi->max_qual / 100);
224 if (percent > 0) {
225 if (backlight == LIGHTON) {
226 refresh(tcur);
228 backlight = LIGHTOFF;
229 } else {
230 if (backlight == LIGHTOFF) {
231 refresh(blgt);
233 backlight = LIGHTON;
236 if (gui == STANDARD) {
237 if (gui != lgui) {
238 if (backlight == LIGHTOFF)
239 refresh(tcur);
240 else
241 refresh(blgt);
242 lgui = gui;
244 /* draw junk */
245 draw_junk(wfi);
246 } else {
247 if (gui != lgui) {
248 if (backlight == LIGHTOFF)
249 refresh(tcur);
250 else
251 refresh(blgt);
252 lgui = gui;
254 draw_ext(wfi);
256 count++;
257 if (scroll) {
258 dockapp_copyarea(display_link, pixmap, 0, 0, 58, 12, 0, 0);
259 snprintf(str, strlen(wfi->ifname) + strlen(wfi->essid) + 4,
260 "%s - %s", wfi->ifname, wfi->essid);
261 draw_text(str, 52 - (count * 3), 4, False);
262 dockapp_copyarea(display_link, pixmap, 0, 0, 4, 12, 0, 0);
263 dockapp_copyarea(display_link, pixmap, 55, 0, 3, 12, 55, 0);
264 if (count > (strlen(str) * 3))
265 count = 1;
266 } else {
267 int diff = now - last_swap;
268 /* swap between ifname and essid every 2 seconds */
269 if (diff <= 2)
270 sw = 1;
271 else if ((diff > 2) && (diff <= 4))
272 sw = 2;
273 else
274 last_swap = now;
276 switch (sw) {
277 case 1:
278 dockapp_copyarea(display_link, pixmap, 0, 0, 58, 12, 0, 0);
279 draw_text(wfi->ifname,
280 ((56 / 2) - (strlen(wfi->ifname) * 2)), 4,
281 False);
282 dockapp_copyarea(display_link, pixmap, 0, 0, 4, 12, 0, 0);
283 dockapp_copyarea(display_link, pixmap, 55, 0, 3, 12, 55,
285 break;
286 case 2:
287 dockapp_copyarea(display_link, pixmap, 0, 0, 58, 12, 0, 0);
288 draw_text(wfi->essid,
289 ((56 / 2) - (strlen(wfi->essid) * 2)), 4, False);
290 dockapp_copyarea(display_link, pixmap, 0, 0, 4, 12, 0, 0);
291 dockapp_copyarea(display_link, pixmap, 55, 0, 3, 12, 55,
293 break;
296 /* show */
298 dockapp_copy2window(pixmap);
299 time(&last_update);
301 static void refresh(struct theme thm)
303 do_theme(thm);
304 switch (gui) {
305 case STANDARD:
306 dockapp_copyarea(display_link, pixmap, 0, 0, 58, 58, 0, 0);
307 clear_wifi(&lwfi);
308 draw_text("link", 32, 47, False);
309 break;
310 case EXTENDED:
311 dockapp_copyarea(display_stats, pixmap, 0, 0, 58, 58, 0, 0);
312 clear_wifi(&lwfi);
313 draw_text("lnk", 37, 45, False);
314 draw_text("lvl", 37, 36, False);
315 draw_text("nse", 37, 27, False);
316 draw_text("rte", 37, 18, False);
317 break;
321 static void switch_interface(struct wifi *wfi)
323 switch (gui) {
324 case STANDARD:
325 lgui = gui;
326 gui = EXTENDED;
327 dockapp_copyarea(display_link, pixmap, 0, 0, 58, 58, 0, 0);
328 draw_text("lnk", 37, 45, False);
329 draw_text("lvl", 37, 36, False);
330 draw_text("nse", 37, 27, False);
331 draw_text("rte", 37, 18, False);
332 break;
333 case EXTENDED:
334 lgui = gui;
335 gui = STANDARD;
336 dockapp_copyarea(display_stats, pixmap, 0, 0, 58, 58, 0, 0);
337 draw_text("link", 32, 47, False);
338 break;
340 dockapp_copy2window(pixmap);
343 /* called when mouse button pressed */
344 static void draw_ext(struct wifi *wfi)
346 char buffer[25];
347 double rate = wfi->bitrate.value;
349 if (lwfi.link != wfi->link) {
350 sprintf(buffer, "%.f", wfi->link);
351 draw_text(buffer, 15, 45, True);
354 if (lwfi.level != wfi->level) {
355 sprintf(buffer, "%d", wfi->level - 0x100);
356 draw_text(buffer, 15, 36, True);
359 if ((lwfi.noise - 0x100) != (wfi->noise - 0x100)) {
360 sprintf(buffer, "%d", wfi->noise - 0x100);
361 draw_text(buffer, 15, 27, True);
364 if (lwfi.bitrate.value != wfi->bitrate.value) {
365 if (rate >= GIGA) {
366 sprintf(buffer, "%.fgb", rate / GIGA);
367 draw_text(buffer, 9, 18, False);
368 } else {
369 if (rate >= MEGA) {
370 sprintf(buffer, "%.fmb", (rate / MEGA));
371 draw_text(buffer, 9, 18, False);
372 } else {
373 sprintf(buffer, "%.fkb", rate / KILO);
374 draw_text(buffer, 3, 18, False);
380 static void draw_text(char *text, int dx, int dy, Bool digit)
382 int ax, ay = 1, bx, len, i;
383 char tmptext[255] = "";
385 len = strlen(text);
386 bx = 4;
389 for (i = 0; i < len; i++) {
390 digit = (!isalpha(text[i])) ? True : False;
394 if (digit) {
395 if (len == 4)
396 dx -= 6;
397 strcat(tmptext, text);
398 if (len == 3)
399 strcat(tmptext, text);
400 if (len == 2) {
401 tmptext[0] = 0x20;
402 tmptext[1] = text[0];
403 tmptext[2] = text[1];
404 len++;
406 if (len == 1) {
407 tmptext[0] = ' ';
408 tmptext[1] = ' ';
409 tmptext[2] = text[0];
410 len += 2;
412 } else {
413 strcpy(tmptext, text);
416 for (i = 0; i < len; i++) {
417 if (isalpha(tmptext[i])) {
418 ax = ((tolower(tmptext[i]) - 97) * 6) + 1;
419 ay = 1;
420 } else {
421 ax = ((tmptext[i] - 33) * 6) + 1;
422 ay = 10;
424 /* Space */
425 if (tmptext[i] == 0x20)
426 ax = 79;
427 /* Draw Text */
428 dockapp_copyarea(fonts, pixmap, ax, ay, 6, 8, dx, dy);
429 dx += 6;
434 static void draw_junk(struct wifi *wfi)
436 int num = wfi->link;
437 int percent;
438 int y1 = 5;
439 char tmp[255];
441 if (lwfi.link != wfi->link) {
443 if (wfi->max_qual > -1) {
444 if (num < 0)
445 num = 0;
447 /* Calculate Link percentage */
448 percent = num / (wfi->max_qual / 100);
449 num = percent;
451 /* draw digits */
453 sprintf(tmp, "%d", num);
454 draw_text(tmp, 6, 47, True);
456 dockapp_copyarea(display_link, pixmap, 10, 21, 15, 24, 10, 21);
457 dockapp_copyarea(display_link, pixmap, 37, 16, 18, 30, 37, 16);
459 if (num > 0) {
460 /* Level bar 1 ( > 1 - 20%) */
461 dockapp_copyarea(parts, pixmap, 70, 27, 2, 2, 37, 44);
463 if (num > 20) {
464 /* Level bar 2 (18.4 - 40%) */
465 dockapp_copyarea(parts, pixmap, 70, 27, 2, 2, 41, 44);
466 dockapp_copyarea(parts, pixmap, 74, 22, 2, 7, 41, 37);
467 /* Antenna */
468 dockapp_copyarea(parts, pixmap, 2, y1, 15, 24, 10, 21);
470 if (num > 40) {
471 /* Level bar 3 (36.8 - 60%) */
472 dockapp_copyarea(parts, pixmap, 70, 27, 2, 2, 45, 44);
473 dockapp_copyarea(parts, pixmap, 74, 22, 2, 7, 45, 37);
474 dockapp_copyarea(parts, pixmap, 74, 22, 2, 7, 45, 30);
475 /* Antenna */
476 dockapp_copyarea(parts, pixmap, 18, y1, 15, 24, 10, 21);
478 if (num > 60) {
479 dockapp_copyarea(parts, pixmap, 70, 27, 2, 2, 49, 44);
480 dockapp_copyarea(parts, pixmap, 74, 22, 2, 7, 49, 37);
481 dockapp_copyarea(parts, pixmap, 74, 22, 2, 7, 49, 30);
482 dockapp_copyarea(parts, pixmap, 74, 22, 2, 7, 49, 23);
483 /* Antenna */
484 dockapp_copyarea(parts, pixmap, 34, y1, 15, 24, 10, 21);
486 if (num > 80) {
487 /* Level bar 5 (73.6 - 100%) */
488 dockapp_copyarea(parts, pixmap, 70, 27, 2, 2, 53, 44);
489 dockapp_copyarea(parts, pixmap, 74, 22, 2, 7, 53, 37);
490 dockapp_copyarea(parts, pixmap, 74, 22, 2, 7, 53, 30);
491 dockapp_copyarea(parts, pixmap, 74, 22, 2, 7, 53, 23);
492 dockapp_copyarea(parts, pixmap, 74, 22, 2, 7, 53, 16);
493 /* Antenna */
494 dockapp_copyarea(parts, pixmap, 50, y1, 15, 24, 10, 21);
500 static void copy_wifi(struct wifi *lwfi, struct wifi *wfi)
502 memcpy(lwfi->ifname, wfi->ifname, 255);
503 memcpy(lwfi->essid, wfi->essid, IW_ESSID_MAX_SIZE + 1);
504 lwfi->ifnum = wfi->ifnum;
505 lwfi->link = wfi->link;
506 lwfi->level = wfi->level;
507 lwfi->noise = wfi->noise;
508 lwfi->bitrate.value = wfi->bitrate.value;
510 static void clear_wifi(struct wifi *wfi)
512 //memcpy(wfi->ifname, 0, 255);
513 //memcpy(wfi->essid, 0, IW_ESSID_MAX_SIZE + 1);
514 wfi->ifnum = 0;
515 wfi->link = (float) 0;
516 wfi->level = 0;
517 wfi->noise = 0 - 0x100;
518 wfi->bitrate.value = 0;
520 static void parse_arguments(int argc, char **argv)
522 int i;
523 int integer;
524 //dockapp_isbrokenwm = True;
526 /* Default to Classic Theme */
527 tcur.bg = "rgb:8e/96/8a";
528 tcur.hi = "rgb:76/7c/6f";
529 tcur.mt = "rgb:44/44/44";
530 tcur.fg = "rgb:00/00/00";
531 blgt.bg = "rgb:6E/C6/3B";
532 blgt.fg = "rgb:00/00/00";
533 blgt.mt = "rgb:00/00/00";
534 blgt.hi = "rgb:6c/b2/37";
537 for (i = 1; i < argc; i++) {
538 if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h"))
539 print_help(argv[0]), exit(0);
540 else if (!strcmp(argv[i], "--version") || !strcmp(argv[i], "-v"))
541 printf("%s version %s\n", PACKAGE, VERSION), exit(0);
542 else if (!strcmp(argv[i], "--display") || !strcmp(argv[i], "-d")) {
543 display_name = argv[i + 1];
544 i++;
545 } else if (!strcmp(argv[i], "--backlight")
546 || !strcmp(argv[i], "-bl")) {
547 backlight = LIGHTON;
548 } else if (!strcmp(argv[i], "--light-color")
549 || !strcmp(argv[i], "-lc")) {
550 light_color = argv[i + 1];
551 blgt.bg = argv[i + 1];
552 i++;
553 } else if (!strcmp(argv[i], "--interval")
554 || !strcmp(argv[i], "-i")) {
555 if (argc == i + 1)
556 fprintf(stderr,
557 "%s: error parsing argument for option %s\n",
558 argv[0], argv[i]), exit(1);
559 if (sscanf(argv[i + 1], "%i", &integer) != 1)
560 fprintf(stderr,
561 "%s: error parsing argument for option %s\n",
562 argv[0], argv[i]), exit(1);
563 if (integer < 1)
564 fprintf(stderr, "%s: argument %s must be >=1\n",
565 argv[0], argv[i]), exit(1);
566 update_interval = integer;
567 i++;
568 } else if (!strcmp(argv[i], "--learn")
569 || !strcmp(argv[i], "-l")) {
570 wmwifi_learn = True;
571 } else if (!strcmp(argv[i], "--scroll-on")
572 || !strcmp(argv[i], "+s")) {
573 scroll = True;
574 } else if (!strcmp(argv[i], "--scroll-off")
575 || !strcmp(argv[i], "-s")) {
576 scroll = False;
577 } else if (!strcmp(argv[i], "--windowed")
578 || !strcmp(argv[i], "-w")) {
579 dockapp_iswindowed = True;
580 } else if (!strcmp(argv[i], "--theme-classic")
581 || !strcmp(argv[i], "-tc")) {
582 tcur.bg = "rgb:8e/96/8a";
583 tcur.hi = "rgb:76/7c/6f";
584 tcur.mt = "rgb:44/44/44";
585 tcur.fg = "rgb:00/00/00";
586 } else if (!strcmp(argv[i], "--theme-snow")
587 || !strcmp(argv[i], "-ts")) {
588 tcur.hi = "rgb:cc/cc/cc";
589 tcur.mt = "rgb:aa/aa/aa";
590 tcur.bg = "rgb:ff/ff/ff";
591 tcur.fg = "rgb:00/00/00";
592 } else if (!strcmp(argv[i], "--theme-new")
593 || !strcmp(argv[i], "-tn")) {
594 tcur.hi = "rgb:00/49/41";
595 tcur.mt = "rgb:02/7e/72";
596 tcur.bg = "rgb:20/20/20";
597 tcur.fg = "rgb:20/b2/ae";
598 } else if (!strcmp(argv[i], "--hilight-color")
599 || !strcmp(argv[i], "-hi")) {
600 tcur.hi = argv[i + 1];
601 i++;
602 } else if (!strcmp(argv[i], "--midtone-color")
603 || !strcmp(argv[i], "-mt")) {
604 tcur.mt = argv[i + 1];
605 i++;
606 } else if (!strcmp(argv[i], "--background-color")
607 || !strcmp(argv[i], "-bg")) {
608 tcur.bg = argv[i + 1];
609 i++;
610 } else if (!strcmp(argv[i], "--foreground-color")
611 || !strcmp(argv[i], "-fg")) {
612 tcur.fg = argv[i + 1];
613 i++;
614 } else if (!strcmp(argv[i], "--broken-wm")
615 || !strcmp(argv[i], "-bw"))
616 dockapp_isbrokenwm = True;
617 else {
618 fprintf(stderr, "%s: unrecognized option '%s'\n", argv[0],
619 argv[i]);
620 print_help(argv[0]), exit(1);
625 static void print_help(char *prog)
627 printf("Usage : %s [OPTIONS]\n", prog);
628 printf("wmwifi - Wireless signal strength monitor dockapp\n");
629 printf(" -d, --display <string> display to use\n");
630 printf(" -bl, --backlight turn on back-light\n");
631 printf
632 (" -lc, --light-color <string> back-light color(rgb:6E/C6/3B is default)\n");
633 printf
634 (" -fg, --foreground-color <string> foreground color(rgb:00/00/00 is default)\n");
635 printf
636 (" -bg, --background-color <string> background color(rgb:8e/96/8a is default)\n");
637 printf
638 (" -hc, --hilight-color <string> background highlight color(rgb:76/7c/6f is default)\n");
639 printf
640 (" -mt, --midtone-color <string> midtone highlight color(rgb:44/44/44 is default)\n");
641 printf
642 (" -i, --interval <number> number of secs between updates (1 is default)\n");
643 printf
644 (" -h, --help show this help text and exit\n");
645 printf
646 (" -v, --version show program version and exit\n");
647 printf
648 (" -w, --windowed run the application in windowed mode\n");
649 printf
650 (" -bw, --broken-wm activate broken window manager fix\n");
651 printf
652 (" -l, --learn enter learning mode (may break quality)\n");
653 printf
654 (" +s, --scroll-on scroll interface name and essid\n");
655 printf
656 (" -s, --scroll-off use <= 0.5 style interface and essid\n");
657 printf
658 (" -tc, --theme-classic Theme: use <= 0.5 style interface theme\n");
659 printf(" -ts, --theme-snow Theme: Snow\n");
660 printf(" -tn, --theme-new Theme: New\n");