libdockapp: bump library version to 3.0.1.
[dockapps.git] / wmsmixer / wmsmixer.cc
blob5f97512cd04119ce561022740290d42dbac108d3
1 // wmsmixer - A mixer designed for WindowMaker with scrollwheel support
2 // Copyright (C) 2003 Damian Kramer <psiren@hibernaculum.net>
3 // Copyright (C) 1998 Sam Hawker <shawkie@geocities.com>
4 // This software comes with ABSOLUTELY NO WARRANTY
5 // This software is free software, and you are welcome to redistribute it
6 // under certain conditions
7 // See the README file for a more complete notice.
10 // Defines, includes and global variables
11 // --------------------------------------
13 // User defines - standard
14 #define WINDOWMAKER false
15 #define USESHAPE false
16 #define AFTERSTEP false
17 #define NORMSIZE 64
18 #define ASTEPSIZE 56
19 #define NAME "wmsmixer"
20 #define CLASS "Wmsmixer"
22 #define VERSION "0.5.1"
24 // User defines - custom
25 #define MIXERDEV "/dev/mixer"
26 #define BACKCOLOR "#202020"
27 #define LEDCOLOR "#00c9c1"
29 #undef CLAMP
30 #define CLAMP(x, l, h) (((x) > (h)) ? (h) : (((x) < (l)) ? (l) : (x)))
32 // Includes - standard
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <ctype.h>
39 // Includes - custom
40 #include "mixctl.h"
42 // X-Windows includes - standard
43 #include <X11/X.h>
44 #include <X11/Xlib.h>
45 #include <X11/Xutil.h>
46 #include <X11/Xproto.h>
47 #include <X11/xpm.h>
48 #include <X11/extensions/shape.h>
50 // Pixmaps - standard
51 Pixmap pm_main;
52 Pixmap pm_tile;
53 Pixmap pm_disp;
54 Pixmap pm_mask;
56 // Pixmaps - custom
57 Pixmap pm_icon;
58 Pixmap pm_digits;
59 Pixmap pm_chars;
61 // Xpm images - standard
62 #include "XPM/wmsmixer.xpm"
63 #include "XPM/tile.xpm"
65 // Xpm images - custom
66 #include "XPM/icons.xpm"
67 #include "XPM/digits.xpm"
68 #include "XPM/chars.xpm"
70 // Variables for command-line arguments - standard
71 bool wmaker=WINDOWMAKER;
72 bool ushape=USESHAPE;
73 bool astep=AFTERSTEP;
74 char display[256]="";
75 char position[256]="";
76 int winsize;
77 bool no_volume_display = 0;
79 // Variables for command-line arguments - custom
80 char mixdev[256]=MIXERDEV;
81 char backcolor[256]=BACKCOLOR;
82 char ledcolor[256]=LEDCOLOR;
84 // X-Windows basics - standard
85 Atom _XA_GNUSTEP_WM_FUNC;
86 Atom deleteWin;
87 Display *d_display;
88 Window w_icon;
89 Window w_main;
90 Window w_root;
91 Window w_activewin;
93 // X-Windows basics - custom
94 GC gc_gc;
95 unsigned long color[4];
97 int text_counter = 0;
99 // Misc custom global variables
100 // ----------------------------
102 // Current state information
103 int curchannel=0;
104 int curleft;
105 int curright;
107 // For buttons
108 int btnstate=0;
109 #define BTNNEXT 1
110 #define BTNPREV 2
112 // For repeating next and prev buttons
113 #define RPTINTERVAL 5
114 int rpttimer=0;
116 // For draggable volume control
117 bool dragging=false;
119 int channels=0;
120 int channel[25];
121 int icon[25]={0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24};
122 char *small_labels[25] = {"vol ", "bass", "trbl", "synt", "pcm ", "spkr", "line",
123 "mic ", "cd ", "mix ", "pcm2", "rec ", "igai", "ogai",
124 "lin1", "lin2", "lin3", "dig1", "dig2", "dig3", "phin",
125 "phou", "vid ", "rad ", "mon "};
127 MixCtl *mixctl;
130 // Procedures and functions
131 // ------------------------
133 // Procedures and functions - standard
134 void initXWin(int argc, char **argv);
135 void freeXWin();
136 void createWin(Window *win, int x, int y);
137 unsigned long getColor(char *colorname);
138 unsigned long mixColor(char *colorname1, int prop1, char *colorname2, int prop2);
140 // Procedures and functions - custom
141 void scanArgs(int argc, char **argv);
142 void readFile();
143 void checkVol(bool forced);
144 void pressEvent(XButtonEvent *xev);
145 void releaseEvent(XButtonEvent *xev);
146 void motionEvent(XMotionEvent *xev);
147 void repaint();
148 void update();
149 void drawLeft();
150 void drawRight();
151 void drawMono();
152 void drawVolLevel();
153 void drawText(char *text);
154 void drawBtns(int btns);
155 void drawBtn(int x, int y, int w, int h, bool down);
158 // Implementation
159 // --------------
161 int main(int argc, char **argv)
163 scanArgs(argc, argv);
164 initXWin(argc, argv);
166 XGCValues gcv;
167 unsigned long gcm;
168 gcm=GCGraphicsExposures;
169 gcv.graphics_exposures=false;
170 gc_gc=XCreateGC(d_display, w_root, gcm, &gcv);
172 color[0]=mixColor(ledcolor, 0, backcolor, 100);
173 color[1]=mixColor(ledcolor, 100, backcolor, 0);
174 color[2]=mixColor(ledcolor, 60, backcolor, 40);
175 color[3]=mixColor(ledcolor, 25, backcolor, 75);
177 XpmAttributes xpmattr;
178 XpmColorSymbol xpmcsym[4]={{"back_color", NULL, color[0]},
179 {"led_color_high", NULL, color[1]},
180 {"led_color_med", NULL, color[2]},
181 {"led_color_low", NULL, color[3]}};
182 xpmattr.numsymbols=4;
183 xpmattr.colorsymbols=xpmcsym;
184 xpmattr.exactColors=false;
185 xpmattr.closeness=40000;
186 xpmattr.valuemask=XpmColorSymbols | XpmExactColors | XpmCloseness;
187 XpmCreatePixmapFromData(d_display, w_root, wmsmixer_xpm, &pm_main, &pm_mask, &xpmattr);
188 XpmCreatePixmapFromData(d_display, w_root, tile_xpm, &pm_tile, NULL, &xpmattr);
189 XpmCreatePixmapFromData(d_display, w_root, icons_xpm, &pm_icon, NULL, &xpmattr);
190 XpmCreatePixmapFromData(d_display, w_root, digits_xpm, &pm_digits, NULL, &xpmattr);
191 XpmCreatePixmapFromData(d_display, w_root, chars_xpm, &pm_chars, NULL, &xpmattr);
192 pm_disp=XCreatePixmap(d_display, w_root, 64, 64, DefaultDepth(d_display, DefaultScreen(d_display)));
195 if(wmaker || ushape || astep)
196 XShapeCombineMask(d_display, w_activewin, ShapeBounding, winsize/2-32, winsize/2-32, pm_mask, ShapeSet);
197 else
198 XCopyArea(d_display, pm_tile, pm_disp, gc_gc, 0, 0, 64, 64, 0, 0);
200 XSetClipMask(d_display, gc_gc, pm_mask);
201 XCopyArea(d_display, pm_main, pm_disp, gc_gc, 0, 0, 64, 64, 0, 0);
202 XSetClipMask(d_display, gc_gc, None);
204 mixctl=new MixCtl(mixdev);
206 if(!mixctl->openOK())
207 fprintf(stderr,"%s : Unable to open mixer device '%s'.\n", NAME, mixdev);
208 else{
209 for(int i=0;i<mixctl->getNrDevices();i++){
210 if(i==25){
211 fprintf(stderr,"%s : Sorry, can only use channels 0-24\n", NAME);
212 break;
214 if(mixctl->getSupport(i)){
215 channel[channels]=i;
216 channels++;
221 readFile();
223 if(channels==0)
224 fprintf(stderr,"%s : Sorry, no supported channels found.\n", NAME);
225 else{
226 checkVol(true);
228 XEvent xev;
229 XSelectInput(d_display, w_activewin, ExposureMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask);
230 XMapWindow(d_display, w_main);
232 bool done=false;
233 while(!done){
234 while(XPending(d_display)){
235 XNextEvent(d_display, &xev);
236 switch(xev.type){
237 case Expose:
238 repaint();
239 break;
240 case ButtonPress:
241 pressEvent(&xev.xbutton);
242 break;
243 case ButtonRelease:
244 releaseEvent(&xev.xbutton);
245 break;
246 case MotionNotify:
247 motionEvent(&xev.xmotion);
248 break;
249 case ClientMessage:
250 if(xev.xclient.data.l[0]==deleteWin)
251 done=true;
252 break;
256 if(btnstate & (BTNPREV | BTNNEXT)){
257 rpttimer++;
258 if(rpttimer>=RPTINTERVAL){
259 if(btnstate & BTNNEXT)
260 curchannel++;
261 else
262 curchannel--;
263 if(curchannel<0)
264 curchannel=channels-1;
265 if(curchannel>=channels)
266 curchannel=0;
267 checkVol(true);
268 rpttimer=0;
271 else
272 checkVol(false);
274 if(text_counter) {
275 text_counter--;
276 if(!text_counter) {
277 drawVolLevel();
278 repaint();
280 // printf("%c", text_counter);
283 XFlush(d_display);
285 usleep(50000);
288 XFreeGC(d_display, gc_gc);
289 XFreePixmap(d_display, pm_main);
290 XFreePixmap(d_display, pm_tile);
291 XFreePixmap(d_display, pm_disp);
292 XFreePixmap(d_display, pm_mask);
293 XFreePixmap(d_display, pm_icon);
294 XFreePixmap(d_display, pm_digits);
295 XFreePixmap(d_display, pm_chars);
296 freeXWin();
297 delete mixctl;
298 return 0;
301 void initXWin(int argc, char **argv)
303 winsize=astep ? ASTEPSIZE : NORMSIZE;
305 if((d_display=XOpenDisplay(display))==NULL){
306 fprintf(stderr,"%s : Unable to open X display '%s'.\n", NAME, XDisplayName(display));
307 exit(1);
309 _XA_GNUSTEP_WM_FUNC=XInternAtom(d_display, "_GNUSTEP_WM_FUNCTION", false);
310 deleteWin=XInternAtom(d_display, "WM_DELETE_WINDOW", false);
312 w_root=DefaultRootWindow(d_display);
314 XWMHints wmhints;
315 XSizeHints shints;
316 shints.x=0;
317 shints.y=0;
318 shints.flags=0;
319 bool pos=(XWMGeometry(d_display, DefaultScreen(d_display), position, NULL, 0, &shints, &shints.x, &shints.y,
320 &shints.width, &shints.height, &shints.win_gravity) & (XValue | YValue));
321 shints.min_width=winsize;
322 shints.min_height=winsize;
323 shints.max_width=winsize;
324 shints.max_height=winsize;
325 shints.base_width=winsize;
326 shints.base_height=winsize;
327 shints.flags=PMinSize | PMaxSize | PBaseSize;
329 createWin(&w_main, shints.x, shints.y);
331 if(wmaker || astep || pos)
332 shints.flags |= USPosition;
333 if(wmaker){
334 wmhints.initial_state=WithdrawnState;
335 wmhints.flags=WindowGroupHint | StateHint | IconWindowHint;
336 createWin(&w_icon, shints.x, shints.y);
337 w_activewin=w_icon;
338 wmhints.icon_window=w_icon;
340 else{
341 wmhints.initial_state=NormalState;
342 wmhints.flags=WindowGroupHint | StateHint;
343 w_activewin=w_main;
345 wmhints.window_group=w_main;
346 XSetWMHints(d_display, w_main, &wmhints);
347 XSetWMNormalHints(d_display, w_main, &shints);
348 XSetCommand(d_display, w_main, argv, argc);
349 XStoreName(d_display, w_main, NAME);
350 XSetIconName(d_display, w_main, NAME);
351 XSetWMProtocols(d_display, w_activewin, &deleteWin, 1);
354 void freeXWin()
356 XDestroyWindow(d_display, w_main);
357 if(wmaker)
358 XDestroyWindow(d_display, w_icon);
359 XCloseDisplay(d_display);
362 void createWin(Window *win, int x, int y)
364 XClassHint classHint;
365 *win=XCreateSimpleWindow(d_display, w_root, x, y, winsize, winsize, 0, 0, 0);
366 classHint.res_name=NAME;
367 classHint.res_class=CLASS;
368 XSetClassHint(d_display, *win, &classHint);
371 unsigned long getColor(char *colorname)
373 XColor color;
374 XWindowAttributes winattr;
375 XGetWindowAttributes(d_display, w_root, &winattr);
376 color.pixel=0;
377 XParseColor(d_display, winattr.colormap, colorname, &color);
378 color.flags=DoRed | DoGreen | DoBlue;
379 XAllocColor(d_display, winattr.colormap, &color);
380 return color.pixel;
383 unsigned long mixColor(char *colorname1, int prop1, char *colorname2, int prop2)
385 XColor color, color1, color2;
386 XWindowAttributes winattr;
387 XGetWindowAttributes(d_display, w_root, &winattr);
388 XParseColor(d_display, winattr.colormap, colorname1, &color1);
389 XParseColor(d_display, winattr.colormap, colorname2, &color2);
390 color.pixel=0;
391 color.red=(color1.red*prop1+color2.red*prop2)/(prop1+prop2);
392 color.green=(color1.green*prop1+color2.green*prop2)/(prop1+prop2);
393 color.blue=(color1.blue*prop1+color2.blue*prop2)/(prop1+prop2);
394 color.flags=DoRed | DoGreen | DoBlue;
395 XAllocColor(d_display, winattr.colormap, &color);
396 return color.pixel;
399 void scanArgs(int argc, char **argv)
401 for(int i=1;i<argc;i++){
402 if(strcmp(argv[i], "-h")==0 || strcmp(argv[i], "--help")==0) {
403 fprintf(stderr, "wmsmixer - A mixer designed for WindowMaker with scrollwheel support\n");
404 fprintf(stderr, "Copyright (C) 2003 Damian Kramer <psiren@hibernaculum.net>\n");
405 fprintf(stderr, "Copyright (C) 1998 Sam Hawker <shawkie@geocities.com>\n");
406 fprintf(stderr, "This software comes with ABSOLUTELY NO WARRANTY\n");
407 fprintf(stderr, "This software is free software, and you are welcome to redistribute it\n");
408 fprintf(stderr, "under certain conditions\n");
409 fprintf(stderr, "See the README file for a more complete notice.\n\n");
410 fprintf(stderr, "usage:\n\n %s [options]\n\noptions:\n\n",argv[0]);
411 fprintf(stderr, " -h | --help display this help screen\n");
412 fprintf(stderr, " -v | --version display the version\n");
413 fprintf(stderr, " -w use WithdrawnState (for WindowMaker)\n");
414 fprintf(stderr, " -s shaped window\n");
415 fprintf(stderr, " -a use smaller window (for AfterStep Wharf)\n");
416 fprintf(stderr, " -l led_color use the specified color for led display\n");
417 fprintf(stderr, " -b back_color use the specified color for backgrounds\n");
418 fprintf(stderr, " -d mix_device use specified device (rather than /dev/mixer)\n");
419 fprintf(stderr, " -position position set window position (see X manual pages)\n");
420 fprintf(stderr, " -display display select target display (see X manual pages)\n\n");
421 exit(0);
423 if(strcmp(argv[i], "-v")==0 || strcmp(argv[i], "--version")==0) {
424 fprintf(stderr, "wmsmixer version %s\n", VERSION);
425 exit(0);
427 if(strcmp(argv[i], "-w")==0)
428 wmaker=!wmaker;
429 if(strcmp(argv[i], "-s")==0)
430 ushape=!ushape;
431 if(strcmp(argv[i], "-a")==0)
432 astep=!astep;
433 if(strcmp(argv[i], "-novol")==0)
434 no_volume_display = 1;
435 if(strcmp(argv[i], "-d")==0){
436 if(i<argc-1){
437 i++;
438 sprintf(mixdev, "%s", argv[i]);
440 continue;
442 if(strcmp(argv[i], "-l")==0){
443 if(i<argc-1){
444 i++;
445 sprintf(ledcolor, "%s", argv[i]);
447 continue;
449 if(strcmp(argv[i], "-b")==0){
450 if(i<argc-1){
451 i++;
452 sprintf(backcolor, "%s", argv[i]);
454 continue;
456 if(strcmp(argv[i], "-position")==0){
457 if(i<argc-1){
458 i++;
459 sprintf(position, "%s", argv[i]);
461 continue;
463 if(strcmp(argv[i], "-display")==0){
464 if(i<argc-1){
465 i++;
466 sprintf(display, "%s", argv[i]);
468 continue;
473 void readFile()
475 FILE *rcfile;
476 char rcfilen[256];
477 char buf[256];
478 int done;
479 int current=-1;
480 sprintf(rcfilen, "%s/.wmsmixer", getenv("HOME"));
481 if((rcfile=fopen(rcfilen, "r"))!=NULL){
482 channels=0;
484 fgets(buf, 250, rcfile);
485 if((done=feof(rcfile))==0){
486 buf[strlen(buf)-1]=0;
487 if(strncmp(buf, "addchannel ", strlen("addchannel "))==0){
488 sscanf(buf, "addchannel %i", &current);
489 if(current>=mixctl->getNrDevices() || mixctl->getSupport(current)==false){
490 fprintf(stderr,"%s : Sorry, this channel (%i) is not supported.\n", NAME, current);
491 current=-1;
493 else{
494 channel[channels]=current;
495 channels++;
498 if(strncmp(buf, "setchannel ", strlen("setchannel "))==0){
499 sscanf(buf, "setchannel %i", &current);
500 if(current>=mixctl->getNrDevices() || mixctl->getSupport(current)==false){
501 fprintf(stderr,"%s : Sorry, this channel (%i) is not supported.\n", NAME, current);
502 current=-1;
505 if(strncmp(buf, "setname ", strlen("setname "))==0){
506 if(current==-1)
507 fprintf(stderr,"%s : Sorry, no current channel.\n", NAME);
508 else {
509 small_labels[current] = (char *)malloc(sizeof(char)*5);
510 sscanf(buf, "setname %4s", small_labels[current]);
513 if(strncmp(buf, "setmono ", strlen("setmono "))==0){
514 if(current==-1)
515 fprintf(stderr,"%s : Sorry, no current channel.\n", NAME);
516 else{
517 int value;
518 sscanf(buf, "setmono %i", &value);
519 mixctl->setLeft(current, value);
520 mixctl->setRight(current, value);
521 mixctl->writeVol(current);
524 if(strncmp(buf, "setleft ", strlen("setleft "))==0){
525 if(current==-1)
526 fprintf(stderr, "%s : Sorry, no current channel.\n", NAME);
527 else{
528 int value;
529 sscanf(buf, "setleft %i", &value);
530 mixctl->setLeft(current, value);
531 mixctl->writeVol(current);
534 if(strncmp(buf, "setright ", strlen("setright "))==0){
535 if(current==-1)
536 fprintf(stderr, "%s : Sorry, no current channel.\n", NAME);
537 else{
538 int value;
539 sscanf(buf, "setleft %i", &value);
540 mixctl->setRight(current, value);
541 mixctl->writeVol(current);
545 } while(done==0);
546 fclose(rcfile);
550 void checkVol(bool forced=true)
552 mixctl->readVol(channel[curchannel], true);
553 int nl=mixctl->readLeft(channel[curchannel]);
554 int nr=mixctl->readRight(channel[curchannel]);
555 if(forced){
556 curleft=nl;
557 curright=nr;
558 update();
559 repaint();
561 else{
562 if(nl!=curleft || nr!=curright){
563 if(nl!=curleft){
564 curleft=nl;
565 if(mixctl->getStereo(channel[curchannel]))
566 drawLeft();
567 else
568 drawMono();
570 if(nr!=curright){
571 curright=nr;
572 if(mixctl->getStereo(channel[curchannel]))
573 drawRight();
574 else
575 drawMono();
577 if(!no_volume_display)
578 drawVolLevel();
579 repaint();
584 void pressEvent(XButtonEvent *xev)
586 if(xev->button == Button4 || xev->button == Button5) {
587 int inc;
588 if(xev->button == Button4) inc = 4;
589 else inc = -4;
591 mixctl->readVol(channel[curchannel], false);
592 mixctl->setLeft(channel[curchannel],
593 CLAMP(mixctl->readLeft(channel[curchannel]) + inc, 0, 100));
594 mixctl->setRight(channel[curchannel],
595 CLAMP(mixctl->readRight(channel[curchannel]) + inc, 0, 100));
596 mixctl->writeVol(channel[curchannel]);
597 checkVol(false);
598 return;
601 int x=xev->x-(winsize/2-32);
602 int y=xev->y-(winsize/2-32);
603 if(x>=5 && y>=47 && x<=17 && y<=57){
604 curchannel--;
605 if(curchannel<0)
606 curchannel=channels-1;
607 btnstate |= BTNPREV;
608 rpttimer=0;
609 drawBtns(BTNPREV);
610 checkVol(true);
611 return;
613 if(x>=18 && y>=47 && x<=30 && y<=57){
614 curchannel++;
615 if(curchannel>=channels)
616 curchannel=0;
617 btnstate|=BTNNEXT;
618 rpttimer=0;
619 drawBtns(BTNNEXT);
620 checkVol(true);
621 return;
623 if(x>=37 && x<=56 && y>=8 && y<=56){
624 int v=((60-y)*100)/(2*25);
625 dragging=true;
626 if(x<=50)
627 mixctl->setLeft(channel[curchannel], v);
628 if(x>=45)
629 mixctl->setRight(channel[curchannel], v);
630 mixctl->writeVol(channel[curchannel]);
631 checkVol(false);
632 return;
634 if(x>=5 && y>=21 && x<=30 && y<=42) {
635 drawText(small_labels[channel[curchannel]]);
636 return;
641 void releaseEvent(XButtonEvent *xev)
643 dragging=false;
644 btnstate &= ~(BTNPREV | BTNNEXT);
645 drawBtns(BTNPREV | BTNNEXT);
646 repaint();
649 void motionEvent(XMotionEvent *xev)
651 int x=xev->x-(winsize/2-32);
652 int y=xev->y-(winsize/2-32);
653 if(x>=37 && x<=56 && y>=8 && dragging){
654 int v=((60-y)*100)/(2*25);
655 if(v<0)
656 v=0;
657 if(x<=50)
658 mixctl->setLeft(channel[curchannel], v);
659 if(x>=45)
660 mixctl->setRight(channel[curchannel], v);
661 mixctl->writeVol(channel[curchannel]);
662 checkVol(false);
666 void repaint()
668 XCopyArea(d_display, pm_disp, w_activewin, gc_gc, 0, 0, 64, 64, winsize/2-32, winsize/2-32);
669 XEvent xev;
670 while(XCheckTypedEvent(d_display, Expose, &xev));
673 void update()
675 drawText(small_labels[channel[curchannel]]);
677 XCopyArea(d_display, pm_icon, pm_disp, gc_gc, icon[channel[curchannel]]*26, 0, 26, 24, 5, 19);
678 if(mixctl->getStereo(channel[curchannel])) {
679 drawLeft();
680 drawRight();
682 else {
683 drawMono();
687 void drawText(char *text)
689 char *p = text;
690 char p2;
692 for(int i=0; i<4; i++, p++) {
693 p2 = toupper(*p);
694 if(p2 >= 'A' && p2 <= 'Z') {
695 XCopyArea(d_display, pm_chars, pm_disp, gc_gc, 6*((int)p2-65), 0, 6, 9, 5+(i*6), 5);
697 else if(p2 >= '0' && p2 <= '9') {
698 XCopyArea(d_display, pm_digits, pm_disp, gc_gc, 6*((int)p2-48), 0, 6, 9, 5+(i*6), 5);
700 else {
701 if(p2 == '\0')
702 p--;
703 XCopyArea(d_display, pm_digits, pm_disp, gc_gc, 60, 0, 6, 9, 5+(i*6), 5);
706 if(!no_volume_display)
707 text_counter = 10;
710 void drawVolLevel()
712 int digits[4];
714 int vol = (mixctl->readLeft(channel[curchannel]) +
715 mixctl->readRight(channel[curchannel])) / 2;
717 digits[0] = (vol/100) ? 1 : 10;
718 digits[1] = (vol/10) == 10 ? 0 : (vol/10);
719 digits[2] = vol%10;
720 digits[3] = 10;
722 for(int i=0; i<4; i++) {
723 XCopyArea(d_display, pm_digits, pm_disp, gc_gc, 6*digits[i], 0, 6, 9, 5+(i*6), 5);
727 void drawLeft()
729 XSetForeground(d_display, gc_gc, color[0]);
730 XFillRectangle(d_display, pm_disp, gc_gc, 46, 7, 2, 49);
732 XSetForeground(d_display, gc_gc, color[1]);
733 for(int i=0;i<25;i++) {
734 if(i==(curleft*25)/100)
735 XSetForeground(d_display, gc_gc, color[3]);
736 XFillRectangle(d_display, pm_disp, gc_gc, 37, 55-2*i, 9, 1);
740 void drawRight()
742 XSetForeground(d_display, gc_gc, color[0]);
743 XFillRectangle(d_display, pm_disp, gc_gc, 46, 7, 2, 49);
745 XSetForeground(d_display, gc_gc, color[1]);
746 for(int i=0;i<25;i++) {
747 if(i==(curright*25)/100)
748 XSetForeground(d_display, gc_gc, color[3]);
749 XFillRectangle(d_display, pm_disp, gc_gc, 48, 55-2*i, 9, 1);
753 void drawMono()
755 XSetForeground(d_display, gc_gc, color[1]);
756 for(int i=0;i<25;i++){
757 if(i==(curright*25)/100)
758 XSetForeground(d_display, gc_gc, color[3]);
759 XFillRectangle(d_display, pm_disp, gc_gc, 37, 55-2*i, 20, 1);
764 void drawBtns(int btns)
766 if(btns & BTNPREV)
767 drawBtn(5, 47, 13, 11, (btnstate & BTNPREV));
768 if(btns & BTNNEXT)
769 drawBtn(18, 47, 13, 11, (btnstate & BTNNEXT));
772 void drawBtn(int x, int y, int w, int h, bool down)
774 if(!down)
775 XCopyArea(d_display, pm_main, pm_disp, gc_gc, x, y, w, h, x, y);
776 else {
777 XCopyArea(d_display, pm_main, pm_disp, gc_gc, x, y, 1, h-1, x+w-1, y+1);
778 XCopyArea(d_display, pm_main, pm_disp, gc_gc, x+w-1, y+1, 1, h-1, x, y);
779 XCopyArea(d_display, pm_main, pm_disp, gc_gc, x, y, w-1, 1, x+1, y+h-1);
780 XCopyArea(d_display, pm_main, pm_disp, gc_gc, x+1, y+h-1, w-1, 1, x, y);