1 #include "wmmixer-alsa.h"
3 int main(int argc
, char **argv
)
7 int exact
,left
,right
,device_index
,i
;
9 XpmColorSymbol xpmcsym
[4];
14 exact
=left
=right
=device_index
=-1;
21 if(!strcasecmp(e
->info
.eid
.name
,"Master Volume"))
23 else if(!strcasecmp(e
->info
.eid
.name
,"PCM Volume"))
25 else if(!strcasecmp(e
->info
.eid
.name
,"MIC Volume"))
27 else if(!strcasecmp(e
->info
.eid
.name
,"Line Volume"))
29 else if(!strcasecmp(e
->info
.eid
.name
,"CD Volume"))
31 else if(!strcasecmp(e
->info
.eid
.name
,"Synth Volume"))
33 else if(!strcasecmp(e
->info
.eid
.name
,"PC Speaker Volume"))
44 gcm
=GCGraphicsExposures
;
45 gcv
.graphics_exposures
=0;
46 gc_gc
=XCreateGC(d_display
, w_root
, gcm
, &gcv
);
48 color
[0]=mixColor(ledcolor
, 0, backcolor
, 100);
49 color
[1]=mixColor(ledcolor
, 100, backcolor
, 0);
50 color
[2]=mixColor(ledcolor
, 60, backcolor
, 40);
51 color
[3]=mixColor(ledcolor
, 25, backcolor
, 75);
53 xpmcsym
[0].name
="back_color";
54 xpmcsym
[0].value
=NULL
;;
55 xpmcsym
[0].pixel
=color
[0];
56 xpmcsym
[1].name
="led_color_high";
57 xpmcsym
[1].value
=NULL
;;
58 xpmcsym
[1].pixel
=color
[1];
59 xpmcsym
[2].name
="led_color_med";
60 xpmcsym
[2].value
=NULL
;;
61 xpmcsym
[2].pixel
=color
[2];
62 xpmcsym
[3].name
="led_color_low";
63 xpmcsym
[3].value
=NULL
;;
64 xpmcsym
[3].pixel
=color
[3];
66 xpmattr
.colorsymbols
=xpmcsym
;
67 xpmattr
.exactColors
=0;
68 xpmattr
.closeness
=40000;
69 xpmattr
.valuemask
=XpmColorSymbols
| XpmExactColors
| XpmCloseness
;
70 XpmCreatePixmapFromData(d_display
, w_root
, wmmixer_xpm
, &pm_main
, &pm_mask
, &xpmattr
);
71 XpmCreatePixmapFromData(d_display
, w_root
, tile_xpm
, &pm_tile
, NULL
, &xpmattr
);
72 XpmCreatePixmapFromData(d_display
, w_root
, icons_xpm
, &pm_icon
, NULL
, &xpmattr
);
73 pm_disp
=XCreatePixmap(d_display
, w_root
, 64, 64, DefaultDepth(d_display
, DefaultScreen(d_display
)));
75 if(wmaker
|| ushape
|| astep
)
76 XShapeCombineMask(d_display
, w_activewin
, ShapeBounding
, winsize
/2-32, winsize
/2-32, pm_mask
, ShapeSet
);
78 XCopyArea(d_display
, pm_tile
, pm_disp
, gc_gc
, 0, 0, 64, 64, 0, 0);
80 XSetClipMask(d_display
, gc_gc
, pm_mask
);
81 XCopyArea(d_display
, pm_main
, pm_disp
, gc_gc
, 0, 0, 64, 64, 0, 0);
82 XSetClipMask(d_display
, gc_gc
, None
);
85 fprintf(stderr
,"%s : Sorry, no supported channels found.\n", NAME
);
92 XSelectInput(d_display
, w_activewin
, ExposureMask
| ButtonPressMask
| ButtonReleaseMask
| ButtonMotionMask
);
93 XMapWindow(d_display
, w_main
);
97 while(XPending(d_display
))
99 XNextEvent(d_display
, &xev
);
106 pressEvent(&xev
.xbutton
);
109 releaseEvent(&xev
.xbutton
);
112 motionEvent(&xev
.xmotion
);
115 if(xev
.xclient
.data
.l
[0]==deleteWin
)
121 if(btnstate
& (BTNPREV
| BTNNEXT
))
124 if(rpttimer
>=RPTINTERVAL
)
126 if(btnstate
& BTNNEXT
)
154 XFreeGC(d_display
, gc_gc
);
155 XFreePixmap(d_display
, pm_main
);
156 XFreePixmap(d_display
, pm_tile
);
157 XFreePixmap(d_display
, pm_disp
);
158 XFreePixmap(d_display
, pm_mask
);
159 XFreePixmap(d_display
, pm_icon
);
164 void initXWin(int argc
, char **argv
)
170 winsize
=astep
? ASTEPSIZE
: NORMSIZE
;
172 if((d_display
=XOpenDisplay(display
))==NULL
)
174 fprintf(stderr
,"%s : Unable to open X display '%s'.\n", NAME
, XDisplayName(display
));
177 _XA_GNUSTEP_WM_FUNC
=XInternAtom(d_display
, "_GNUSTEP_WM_FUNCTION", 0);
178 deleteWin
=XInternAtom(d_display
, "WM_DELETE_WINDOW", 0);
180 w_root
=DefaultRootWindow(d_display
);
185 pos
=(XWMGeometry(d_display
, DefaultScreen(d_display
), position
, NULL
, 0, &shints
, &shints
.x
, &shints
.y
, &shints
.width
, &shints
.height
, &shints
.win_gravity
) & (XValue
| YValue
));
186 shints
.min_width
=winsize
;
187 shints
.min_height
=winsize
;
188 shints
.max_width
=winsize
;
189 shints
.max_height
=winsize
;
190 shints
.base_width
=winsize
;
191 shints
.base_height
=winsize
;
192 shints
.flags
=PMinSize
| PMaxSize
| PBaseSize
;
194 createWin(&w_main
, shints
.x
, shints
.y
);
196 if(wmaker
|| astep
|| pos
)
197 shints
.flags
|= USPosition
;
200 wmhints
.initial_state
=WithdrawnState
;
201 wmhints
.flags
=WindowGroupHint
| StateHint
| IconWindowHint
;
202 createWin(&w_icon
, shints
.x
, shints
.y
);
204 wmhints
.icon_window
=w_icon
;
208 wmhints
.initial_state
=NormalState
;
209 wmhints
.flags
=WindowGroupHint
| StateHint
;
212 wmhints
.window_group
=w_main
;
213 XSetWMHints(d_display
, w_main
, &wmhints
);
214 XSetWMNormalHints(d_display
, w_main
, &shints
);
215 XSetCommand(d_display
, w_main
, argv
, argc
);
216 XStoreName(d_display
, w_main
, NAME
);
217 XSetIconName(d_display
, w_main
, NAME
);
218 XSetWMProtocols(d_display
, w_activewin
, &deleteWin
, 1);
223 XDestroyWindow(d_display
, w_main
);
225 XDestroyWindow(d_display
, w_icon
);
226 XCloseDisplay(d_display
);
229 void createWin(Window
*win
, int x
, int y
)
231 XClassHint classHint
;
232 *win
=XCreateSimpleWindow(d_display
, w_root
, x
, y
, winsize
, winsize
, 0, 0, 0);
233 classHint
.res_name
=NAME
;
234 classHint
.res_class
=CLASS
;
235 XSetClassHint(d_display
, *win
, &classHint
);
238 unsigned long mixColor(char *colorname1
, int prop1
, char *colorname2
, int prop2
){
239 XColor color
, color1
, color2
;
240 XWindowAttributes winattr
;
241 XGetWindowAttributes(d_display
, w_root
, &winattr
);
242 XParseColor(d_display
, winattr
.colormap
, colorname1
, &color1
);
243 XParseColor(d_display
, winattr
.colormap
, colorname2
, &color2
);
245 color
.red
=(color1
.red
*prop1
+color2
.red
*prop2
)/(prop1
+prop2
);
246 color
.green
=(color1
.green
*prop1
+color2
.green
*prop2
)/(prop1
+prop2
);
247 color
.blue
=(color1
.blue
*prop1
+color2
.blue
*prop2
)/(prop1
+prop2
);
248 color
.flags
=DoRed
| DoGreen
| DoBlue
;
249 XAllocColor(d_display
, winattr
.colormap
, &color
);
253 void show_params(void)
255 fprintf(stdout
,"wmmixer-alsa %s\t\tby Sam Hawker\n"
256 "\t\t\tAdded support for ALSA by\n"
257 "\t\t\tMartin Dahl <dahlm@vf.telia.no>\n\n"
258 "Usage: wmmixer-alsa [options]\n\n"
259 "\t-h\t\tDisplay this help screen\n"
260 "\t-w\t\tUse WithdrawnState\n"
261 "\t-s\t\tShaped window\n"
262 "\t-a\t\tUse smaller window\n"
263 "\t-l <color>\t\tColor for led display\n"
264 "\t-b <color>\t\tColor for background\n"
265 "\t-p <position>\t\tWindow position\n"
266 "\t-d <display>\t\tTarget display\n",VERSION
);
270 void scanArgs(int argc
, char **argv
)
274 memset(backcolor
,0,32);
275 memset(ledcolor
,0,32);
276 memset(display
,0,32);
277 memset(position
,0,32);
278 strncpy(ledcolor
,LEDCOLOR
,32);
279 strncpy(backcolor
,BACKCOLOR
,32);
282 wmaker
=ushape
=astep
=0;
288 if(argv
[x
][0]!='-') show_params();
289 else switch(argv
[x
][1])
301 strncpy(ledcolor
,argv
[x
+1],32);
305 strncpy(backcolor
,argv
[x
+1],32);
309 strncpy(position
,argv
[x
+1],32);
313 strncpy(display
,argv
[x
+1],32);
327 nl
=convert_range(cure
->element
.data
.volume1
.pvoices
[0],cure
->info
.data
.volume1
.prange
[0].min
,cure
->info
.data
.volume1
.prange
[0].max
,0,100);
328 nr
=convert_range(cure
->element
.data
.volume1
.pvoices
[1],cure
->info
.data
.volume1
.prange
[1].min
,cure
->info
.data
.volume1
.prange
[1].max
,0,100);
337 if(nl
!=curleft
||nr
!=curright
)
355 void setVol(int left
, int right
)
359 cure
->element
.data
.volume1
.pvoices
[0]=convert_range(left
,0,100,cure
->info
.data
.volume1
.prange
[0].min
,cure
->info
.data
.volume1
.prange
[0].max
);
360 if(cure
->element
.data
.volume1
.pvoices
[0]>cure
->info
.data
.volume1
.prange
[0].max
)
361 cure
->element
.data
.volume1
.pvoices
[0]=cure
->info
.data
.volume1
.prange
[0].max
;
362 if(cure
->element
.data
.volume1
.pvoices
[0]<cure
->info
.data
.volume1
.prange
[0].min
)
363 cure
->element
.data
.volume1
.pvoices
[0]=cure
->info
.data
.volume1
.prange
[0].min
;
364 cure
->element
.data
.volume1
.pvoices
[1]=convert_range(right
,0,100,cure
->info
.data
.volume1
.prange
[1].min
,cure
->info
.data
.volume1
.prange
[1].max
);
365 if(cure
->element
.data
.volume1
.pvoices
[1]>cure
->info
.data
.volume1
.prange
[1].max
)
366 cure
->element
.data
.volume1
.pvoices
[1]=cure
->info
.data
.volume1
.prange
[1].max
;
367 if((err
=snd_mixer_element_write(mixer_handle
,&cure
->element
))<0)
368 fprintf(stderr
,"Mixer element write error: %s\n",snd_strerror(err
));
375 snd_mixer_callbacks_t callbacks
;
376 memset(&callbacks
,0,sizeof(callbacks
));
377 callbacks
.rebuild
=NULL
;
378 callbacks
.element
=NULL
;
379 callbacks
.group
=NULL
;
380 if((err
=snd_mixer_read(mixer_handle
,&callbacks
))<0)
382 fprintf(stderr
,"Callbacks error: %s\n",snd_strerror(err
));
388 int convert_range(int val
, int omin
, int omax
, int nmin
, int nmax
)
390 int orange
=omax
-omin
, nrange
=nmax
-nmin
;
393 return rint((((double)nrange
*((double)val
-(double)omin
))+((double)orange
/2.0))/(double)orange
+(double)nmin
);
396 void pressEvent(XButtonEvent
*xev
)
398 int x
=xev
->x
-(winsize
/2-32);
399 int y
=xev
->y
-(winsize
/2-32);
400 if(x
>=5 && y
>=33 && x
<=16 && y
<=43)
417 if(x
>=17 && y
>=33 && x
<=28 && y
<=43)
428 if(x
>=37 && x
<=56 && y
>=8 && y
<=56)
430 int v
=((60-y
)*100)/(2*25);
439 /* if(x>=5 && y>=47 && x<=28 && y<=57)
442 mixer.DeviceSet(channel[curchannel]);
443 mixer.Read(&nl,&nr,&flags);
444 if(flags & SND_MIXER_DFLG_MUTE)
447 flags &= ~SND_MIXER_DFLG_MUTE;
452 flags |= SND_MIXER_DFLG_MUTE;
454 mixer.Write(nl,nr,flags);
460 void releaseEvent(XButtonEvent
*xev
)
463 btnstate
&= ~(BTNPREV
| BTNNEXT
);
464 drawBtns(BTNPREV
| BTNNEXT
);
468 void motionEvent(XMotionEvent
*xev
)
470 int x
=xev
->x
-(winsize
/2-32);
471 int y
=xev
->y
-(winsize
/2-32);
472 if(x
>=37 && x
<=56 && y
>=8 && dragging
)
474 int v
=((60-y
)*100)/(2*25);
488 XCopyArea(d_display
, pm_disp
, w_activewin
, gc_gc
, 0, 0, 64, 64, winsize
/2-32, winsize
/2-32);
489 while(XCheckTypedEvent(d_display
, Expose
, &xev
));
494 XCopyArea(d_display
, pm_icon
, pm_disp
, gc_gc
, cure
->icon
*22, 0, 22, 22, 6, 5);
503 XSetForeground(d_display
, gc_gc
, color
[1]);
506 if(i
==(curleft
*25)/100)
507 XSetForeground(d_display
, gc_gc
, color
[3]);
508 XFillRectangle(d_display
, pm_disp
, gc_gc
, 37, 55-2*i
, 9, 1);
515 XSetForeground(d_display
, gc_gc
, color
[1]);
518 if(i
==(curright
*25)/100)
519 XSetForeground(d_display
, gc_gc
, color
[3]);
520 XFillRectangle(d_display
, pm_disp
, gc_gc
, 48, 55-2*i
, 9, 1);
524 void drawBtns(int btns
)
527 drawBtn(5, 33, 12, 11, (btnstate
& BTNPREV
));
529 drawBtn(17, 33, 12, 11, (btnstate
& BTNNEXT
));
531 drawBtn(5, 47, 24, 11, (btnstate
& BTNREC
));
534 void drawBtn(int x
, int y
, int w
, int h
, int down
)
537 XCopyArea(d_display
, pm_main
, pm_disp
, gc_gc
, x
, y
, w
, h
, x
, y
);
540 XCopyArea(d_display
, pm_main
, pm_disp
, gc_gc
, x
, y
, 1, h
-1, x
+w
-1, y
+1);
541 XCopyArea(d_display
, pm_main
, pm_disp
, gc_gc
, x
+w
-1, y
+1, 1, h
-1, x
, y
);
542 XCopyArea(d_display
, pm_main
, pm_disp
, gc_gc
, x
, y
, w
-1, 1, x
+1, y
+h
-1);
543 XCopyArea(d_display
, pm_main
, pm_disp
, gc_gc
, x
+1, y
+h
-1, w
-1, 1, x
, y
);