1 // wmmixer.cc - A mixer designed for WindowMaker
4 // Copyright (C) 1998 Sam Hawker <shawkie@geocities.com>
5 // Copyright (C) 2002 Gordon Fraser <gordon@debian.org>
6 // This software comes with ABSOLUTELY NO WARRANTY
7 // This software is free software, and you are welcome to redistribute it
8 // under certain conditions
9 // See the COPYING file for details.
14 //--------------------------------------------------------------------
17 // Initialize member variables
20 current_channel_left_
= 0;
21 current_channel_right_
= 0;
24 current_recording_
= false;
25 current_show_recording_
= false;
28 strcpy(mixer_device_
, MIXERDEV
);
30 xhandler_
= new XHandler();
34 //--------------------------------------------------------------------
37 delete[] channel_list_
;
43 //--------------------------------------------------------------------
51 while(XPending(xhandler_
->getDisplay()))
53 XNextEvent(xhandler_
->getDisplay(), &xev
);
60 pressEvent(&xev
.xbutton
);
63 releaseEvent(&xev
.xbutton
);
66 motionEvent(&xev
.xmotion
);
69 if(xev
.xclient
.data
.l
[0] == (int)xhandler_
->getDeleteWin())
75 // keep a button pressed causes scrolling throught the channels
76 if(xhandler_
->getButtonState() & (BTNPREV
| BTNNEXT
))
79 if(repeat_timer_
>= RPTINTERVAL
)
81 if(xhandler_
->getButtonState() & BTNNEXT
)
84 if(current_channel_
>= num_channels_
)
89 if(current_channel_
< 1)
90 current_channel_
= num_channels_
-1;
104 XFlush(xhandler_
->getDisplay());
110 //--------------------------------------------------------------------
111 void WMMixer::init(int argc
, char **argv
)
113 parseArgs(argc
, argv
);
117 readConfigurationFile();
119 xhandler_
->init(argc
, argv
, mixctl_
->getNrDevices());
121 if(num_channels_
== 0)
123 std::cerr
<< NAME
<< " : Sorry, no supported channels found." << std::endl
;
131 //--------------------------------------------------------------------
132 void WMMixer::initMixer()
137 mixctl_
= new MixCtl(mixer_device_
);
139 catch(MixerDeviceException
&exc
)
141 std::cerr
<< NAME
<< " : " << exc
.getErrorMessage() << "'." << std::endl
;
145 channel_list_
= new unsigned[mixctl_
->getNrDevices()];
147 for(unsigned count
=0; count
<mixctl_
->getNrDevices(); count
++)
149 if(mixctl_
->getSupport(count
)){
150 channel_list_
[num_channels_
]=count
;
157 //--------------------------------------------------------------------
158 void WMMixer::checkVol(bool forced
= true)
160 if(!forced
&& !mixctl_
->hasChanged())
163 if(mixctl_
->isMuted(channel_list_
[current_channel_
]))
164 xhandler_
->setButtonState(xhandler_
->getButtonState() | BTNMUTE
);
166 xhandler_
->setButtonState(xhandler_
->getButtonState() & ~BTNMUTE
);
169 mixctl_
->readVol(channel_list_
[current_channel_
], true);
170 unsigned nl
= mixctl_
->readLeft(channel_list_
[current_channel_
]);
171 unsigned nr
= mixctl_
->readRight(channel_list_
[current_channel_
]);
172 bool nrec
= mixctl_
->readRec(channel_list_
[current_channel_
], true);
176 current_channel_left_
= nl
;
177 current_channel_right_
= nr
;
178 current_recording_
= nrec
;
180 xhandler_
->setButtonState(xhandler_
->getButtonState() | BTNREC
);
182 xhandler_
->setButtonState(xhandler_
->getButtonState() & ~BTNREC
);
183 current_show_recording_
=mixctl_
->getRecords(channel_list_
[current_channel_
]);
188 if(nl
!= current_channel_left_
|| nr
!= current_channel_right_
|| nrec
!= current_recording_
)
190 if(nl
!=current_channel_left_
)
192 current_channel_left_
=nl
;
193 if(mixctl_
->getStereo(channel_list_
[current_channel_
]))
194 xhandler_
->drawLeft(current_channel_left_
);
196 xhandler_
->drawMono(current_channel_left_
);
198 if(nr
!=current_channel_right_
)
200 current_channel_right_
=nr
;
201 if(mixctl_
->getStereo(channel_list_
[current_channel_
]))
202 xhandler_
->drawRight(current_channel_right_
);
204 xhandler_
->drawMono(current_channel_left_
);
206 if(nrec
!=current_recording_
)
208 current_recording_
=nrec
;
210 xhandler_
->setButtonState(xhandler_
->getButtonState() | BTNREC
);
212 xhandler_
->setButtonState(xhandler_
->getButtonState() & ~BTNREC
);
213 xhandler_
->drawBtns(BTNREC
, current_show_recording_
);
222 //--------------------------------------------------------------------
223 void WMMixer::parseArgs(int argc
, char **argv
)
225 static struct option long_opts
[] = {
226 {"help", 0, NULL
, 'h'},
227 {"version", 0, NULL
, 'v'},
228 {"display", 1, NULL
, 'd'},
229 {"geometry", 1, NULL
, 'g'},
230 {"withdrawn", 0, NULL
, 'w'},
231 {"afterstep", 0, NULL
, 'a'},
232 {"shaped", 0, NULL
, 's'},
233 {"led-color", 1, NULL
, 'l'},
234 {"led-highcolor", 1, NULL
, 'L'},
235 {"back-color", 1, NULL
, 'b'},
236 {"mix-device", 1, NULL
, 'm'},
237 {"scrollwheel",1, NULL
, 'r'},
238 {NULL
, 0, NULL
, 0 }};
239 int i
, opt_index
= 0;
242 // For backward compatibility
243 for(i
=1; i
<argc
; i
++)
245 if(strcmp("-position", argv
[i
]) == 0)
247 sprintf(argv
[i
], "%s", "-g");
249 else if(strcmp("-help", argv
[i
]) == 0)
251 sprintf(argv
[i
], "%s", "-h");
253 else if(strcmp("-display", argv
[i
]) == 0)
255 sprintf(argv
[i
], "%s", "-d");
259 while ((i
= getopt_long(argc
, argv
, "hvd:g:wasl:L:b:m:r:", long_opts
, &opt_index
)) != -1)
266 displayUsage(argv
[0]);
272 xhandler_
->setDisplay(optarg
);
275 xhandler_
->setPosition(optarg
);
278 xhandler_
->setWindowMaker();
281 xhandler_
->setAfterStep();
284 xhandler_
->setUnshaped();
287 xhandler_
->setLedColor(optarg
);
290 xhandler_
->setLedHighColor(optarg
);
293 xhandler_
->setBackColor(optarg
);
296 sprintf(mixer_device_
, "%s", optarg
);
300 wheel_scroll_
= atoi(optarg
);
306 //--------------------------------------------------------------------
307 void WMMixer::readConfigurationFile()
314 unsigned current
= mixctl_
->getNrDevices() + 1;
316 sprintf(rcfilen
, "%s/.wmmixer", getenv("HOME"));
317 if((rcfile
=fopen(rcfilen
, "r"))!=NULL
)
322 fgets(buf
, 250, rcfile
);
323 if((done
=feof(rcfile
))==0)
325 buf
[strlen(buf
)-1]=0;
326 if(strncmp(buf
, "addchannel ", strlen("addchannel "))==0)
328 sscanf(buf
, "addchannel %i", ¤t
);
329 if(current
>= mixctl_
->getNrDevices() || mixctl_
->getSupport(current
) == false)
331 fprintf(stderr
,"%s : Sorry, this channel (%i) is not supported.\n", NAME
, current
);
332 current
= mixctl_
->getNrDevices() + 1;
336 channel_list_
[num_channels_
] = current
;
340 if(strncmp(buf
, "setchannel ", strlen("setchannel "))==0)
342 sscanf(buf
, "setchannel %i", ¤t
);
343 if(current
>= mixctl_
->getNrDevices() || mixctl_
->getSupport(current
)==false)
345 fprintf(stderr
,"%s : Sorry, this channel (%i) is not supported.\n", NAME
, current
);
346 current
= mixctl_
->getNrDevices() + 1;
349 if(strncmp(buf
, "setmono ", strlen("setmono "))==0)
351 if(current
== mixctl_
->getNrDevices() + 1)
352 fprintf(stderr
,"%s : Sorry, no current channel.\n", NAME
);
355 sscanf(buf
, "setmono %i", &value
);
356 mixctl_
->setLeft(current
, value
);
357 mixctl_
->setRight(current
, value
);
358 mixctl_
->writeVol(current
);
361 if(strncmp(buf
, "setleft ", strlen("setleft "))==0)
363 if(current
== mixctl_
->getNrDevices() + 1)
364 fprintf(stderr
, "%s : Sorry, no current channel.\n", NAME
);
367 sscanf(buf
, "setleft %i", &value
);
368 mixctl_
->setLeft(current
, value
);
369 mixctl_
->writeVol(current
);
372 if(strncmp(buf
, "setright ", strlen("setright "))==0)
374 if(current
== mixctl_
->getNrDevices() + 1)
375 fprintf(stderr
, "%s : Sorry, no current channel.\n", NAME
);
379 sscanf(buf
, "setleft %i", &value
);
380 mixctl_
->setRight(current
, value
);
381 mixctl_
->writeVol(current
);
384 if(strncmp(buf
, "setrecsrc ", strlen("setrecsrc "))==0)
386 if(current
== mixctl_
->getNrDevices() + 1)
387 fprintf(stderr
, "%s : Sorry, no current channel.\n", NAME
);
389 mixctl_
->setRec(current
, (strncmp(buf
+strlen("setrecsrc "), "true", strlen("true"))==0));
399 //--------------------------------------------------------------------
400 void WMMixer::displayUsage(const char* name
)
402 std::cout
<< "Usage: " << name
<< "[options]" << std::endl
;
403 std::cout
<< " -h, --help display this help screen" << std::endl
;
404 std::cout
<< " -v, --version display program version" << std::endl
;
405 std::cout
<< " -d, --display <string> display to use (see X manual pages)" << std::endl
;
406 std::cout
<< " -g, --geometry +XPOS+YPOS geometry to use (see X manual pages)" << std::endl
;
407 std::cout
<< " -w, --withdrawn run the application in withdrawn mode" << std::endl
;
408 std::cout
<< " (for WindowMaker, etc)" << std::endl
;
409 std::cout
<< " -a, --afterstep use smaller window (for AfterStep Wharf)" << std::endl
;
410 std::cout
<< " -s, --shaped shaped window" << std::endl
;
411 std::cout
<< " -l, --led-color <string> use the specified color for led display" << std::endl
;
412 std::cout
<< " -L, --led-highcolor <string> use the specified color for led shading" << std::endl
;
413 std::cout
<< " -b, --back-color <string> use the specified color for backgrounds" << std::endl
;
414 std::cout
<< " -m, --mix-device use specified device (rather than /dev/mixer)" << std::endl
;
415 std::cout
<< " -r, --scrollwheel <number> volume increase/decrease with mouse wheel (default: 2)" << std::endl
;
416 std::cout
<< "\nFor backward compatibility the following obsolete options are still supported:" << std::endl
;
417 std::cout
<< " -help display this help screen" << std::endl
;
418 std::cout
<< " -position geometry to use (see X manual pages)" << std::endl
;
419 std::cout
<< " -display display to use (see X manual pages)" << std::endl
;
424 //--------------------------------------------------------------------
425 void WMMixer::displayVersion()
427 std::cout
<< "wmmixer version 1.5" << std::endl
;
432 //--------------------------------------------------------------------
433 void WMMixer::pressEvent(XButtonEvent
*xev
)
435 bool forced_update
= true;
436 int x
= xev
->x
-(xhandler_
->getWindowSize()/2-32);
437 int y
= xev
->y
-(xhandler_
->getWindowSize()/2-32);
439 if(xhandler_
->isLeftButton(x
, y
))
441 if(current_channel_
< 1)
442 current_channel_
=num_channels_
-1;
446 xhandler_
->setButtonState(xhandler_
->getButtonState() | BTNPREV
);
448 xhandler_
->drawBtns(BTNPREV
, current_show_recording_
);
451 if(xhandler_
->isRightButton(x
, y
))
454 if(current_channel_
>= num_channels_
)
457 xhandler_
->setButtonState(xhandler_
->getButtonState() | BTNNEXT
);
459 xhandler_
->drawBtns(BTNNEXT
, current_show_recording_
);
463 if(xhandler_
->isVolumeBar(x
, y
))
469 vl
= ((60-y
)*100)/(2*25);
473 else if(xev
->button
== 4)
475 vr
= mixctl_
->readRight(channel_list_
[current_channel_
]) + wheel_scroll_
;
476 vl
= mixctl_
->readLeft(channel_list_
[current_channel_
]) + wheel_scroll_
;
479 else if(xev
->button
== 5)
481 vr
= mixctl_
->readRight(channel_list_
[current_channel_
]) - wheel_scroll_
;
482 vl
= mixctl_
->readLeft(channel_list_
[current_channel_
]) - wheel_scroll_
;
491 mixctl_
->setLeft(channel_list_
[current_channel_
], vl
);
493 mixctl_
->setRight(channel_list_
[current_channel_
], vr
);
494 mixctl_
->writeVol(channel_list_
[current_channel_
]);
496 forced_update
= false;
500 if(xhandler_
->isRecButton(x
, y
))
502 mixctl_
->setRec(channel_list_
[current_channel_
], !mixctl_
->readRec(channel_list_
[current_channel_
], false));
504 forced_update
= false;
508 if(xhandler_
->isMuteButton(x
, y
))
510 if(mixctl_
->isMuted(channel_list_
[current_channel_
]))
512 xhandler_
->setButtonState(xhandler_
->getButtonState() & ~BTNMUTE
);
513 mixctl_
->unmute(channel_list_
[current_channel_
]);
517 mixctl_
->mute(channel_list_
[current_channel_
]);
518 xhandler_
->setButtonState(xhandler_
->getButtonState() | BTNMUTE
);
521 xhandler_
->drawBtns(BTNMUTE
, current_show_recording_
);
524 // Update volume display
525 checkVol(forced_update
);
528 //--------------------------------------------------------------------
529 void WMMixer::releaseEvent(XButtonEvent
*xev
)
532 xhandler_
->setButtonState(xhandler_
->getButtonState() & ~(BTNPREV
| BTNNEXT
));
533 xhandler_
->drawBtns(BTNPREV
| BTNNEXT
, current_show_recording_
);
534 xhandler_
->repaint();
537 //--------------------------------------------------------------------
538 void WMMixer::motionEvent(XMotionEvent
*xev
)
540 int x
=xev
->x
-(xhandler_
->getWindowSize()/2-32);
541 int y
=xev
->y
-(xhandler_
->getWindowSize()/2-32);
542 // if(x>=37 && x<=56 && y>=8 && dragging_){
543 if(xhandler_
->isVolumeBar(x
, y
) && dragging_
){
544 int v
=((60-y
)*100)/(2*25);
548 mixctl_
->setLeft(channel_list_
[current_channel_
], v
);
550 mixctl_
->setRight(channel_list_
[current_channel_
], v
);
551 mixctl_
->writeVol(channel_list_
[current_channel_
]);
556 //--------------------------------------------------------------------
557 void WMMixer::updateDisplay()
559 xhandler_
->update(channel_list_
[current_channel_
]);
560 if(mixctl_
->getStereo(channel_list_
[current_channel_
]))
562 xhandler_
->drawLeft(current_channel_left_
);
563 xhandler_
->drawRight(current_channel_right_
);
567 xhandler_
->drawMono(current_channel_right_
);
569 xhandler_
->drawBtns(BTNREC
| BTNNEXT
| BTNPREV
| BTNMUTE
, current_show_recording_
);
570 xhandler_
->repaint();
575 //====================================================================
576 int main(int argc
, char** argv
)
578 WMMixer mixer
= WMMixer();
579 mixer
.init(argc
, argv
);