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 // Patch added by Rodolfo (kix) Garcia <kix@kix.es> to select the config file
7 // This software comes with ABSOLUTELY NO WARRANTY
8 // This software is free software, and you are welcome to redistribute it
9 // under certain conditions
10 // See the COPYING file for details.
15 //--------------------------------------------------------------------
18 // Initialize member variables
21 current_channel_left_
= 0;
22 current_channel_right_
= 0;
25 current_recording_
= false;
26 current_show_recording_
= false;
29 strcpy(mixer_device_
, MIXERDEV
);
31 xhandler_
= new XHandler();
35 //--------------------------------------------------------------------
38 delete[] channel_list_
;
44 //--------------------------------------------------------------------
52 while(XPending(xhandler_
->getDisplay()))
54 XNextEvent(xhandler_
->getDisplay(), &xev
);
61 pressEvent(&xev
.xbutton
);
64 releaseEvent(&xev
.xbutton
);
67 motionEvent(&xev
.xmotion
);
70 if(xev
.xclient
.data
.l
[0] == (int)xhandler_
->getDeleteWin())
76 // keep a button pressed causes scrolling throught the channels
77 if(xhandler_
->getButtonState() & (BTNPREV
| BTNNEXT
))
80 if(repeat_timer_
>= RPTINTERVAL
)
82 if(xhandler_
->getButtonState() & BTNNEXT
)
85 if(current_channel_
>= num_channels_
)
90 if(current_channel_
< 1)
91 current_channel_
= num_channels_
-1;
105 XFlush(xhandler_
->getDisplay());
111 //--------------------------------------------------------------------
112 void WMMixer::init(int argc
, char **argv
)
114 parseArgs(argc
, argv
);
118 readConfigurationFile();
120 xhandler_
->init(argc
, argv
, mixctl_
->getNrDevices());
122 if(num_channels_
== 0)
124 std::cerr
<< NAME
<< " : Sorry, no supported channels found." << std::endl
;
132 //--------------------------------------------------------------------
133 void WMMixer::initMixer()
138 mixctl_
= new MixCtl(mixer_device_
);
140 catch(MixerDeviceException
&exc
)
142 std::cerr
<< NAME
<< " : " << exc
.getErrorMessage() << "'." << std::endl
;
146 channel_list_
= new unsigned[mixctl_
->getNrDevices()];
148 for(unsigned count
=0; count
<mixctl_
->getNrDevices(); count
++)
150 if(mixctl_
->getSupport(count
)){
151 channel_list_
[num_channels_
]=count
;
158 //--------------------------------------------------------------------
159 void WMMixer::checkVol(bool forced
= true)
161 if(!forced
&& !mixctl_
->hasChanged())
164 if(mixctl_
->isMuted(channel_list_
[current_channel_
]))
165 xhandler_
->setButtonState(xhandler_
->getButtonState() | BTNMUTE
);
167 xhandler_
->setButtonState(xhandler_
->getButtonState() & ~BTNMUTE
);
170 mixctl_
->readVol(channel_list_
[current_channel_
], true);
171 unsigned nl
= mixctl_
->readLeft(channel_list_
[current_channel_
]);
172 unsigned nr
= mixctl_
->readRight(channel_list_
[current_channel_
]);
173 bool nrec
= mixctl_
->readRec(channel_list_
[current_channel_
], true);
177 current_channel_left_
= nl
;
178 current_channel_right_
= nr
;
179 current_recording_
= nrec
;
181 xhandler_
->setButtonState(xhandler_
->getButtonState() | BTNREC
);
183 xhandler_
->setButtonState(xhandler_
->getButtonState() & ~BTNREC
);
184 current_show_recording_
=mixctl_
->getRecords(channel_list_
[current_channel_
]);
189 if(nl
!= current_channel_left_
|| nr
!= current_channel_right_
|| nrec
!= current_recording_
)
191 if(nl
!=current_channel_left_
)
193 current_channel_left_
=nl
;
194 if(mixctl_
->getStereo(channel_list_
[current_channel_
]))
195 xhandler_
->drawLeft(current_channel_left_
);
197 xhandler_
->drawMono(current_channel_left_
);
199 if(nr
!=current_channel_right_
)
201 current_channel_right_
=nr
;
202 if(mixctl_
->getStereo(channel_list_
[current_channel_
]))
203 xhandler_
->drawRight(current_channel_right_
);
205 xhandler_
->drawMono(current_channel_left_
);
207 if(nrec
!=current_recording_
)
209 current_recording_
=nrec
;
211 xhandler_
->setButtonState(xhandler_
->getButtonState() | BTNREC
);
213 xhandler_
->setButtonState(xhandler_
->getButtonState() & ~BTNREC
);
214 xhandler_
->drawBtns(BTNREC
, current_show_recording_
);
223 //--------------------------------------------------------------------
224 void WMMixer::parseArgs(int argc
, char **argv
)
226 static struct option long_opts
[] = {
227 {"help", 0, NULL
, 'h'},
228 {"version", 0, NULL
, 'v'},
229 {"display", 1, NULL
, 'd'},
230 {"geometry", 1, NULL
, 'g'},
231 {"withdrawn", 0, NULL
, 'w'},
232 {"afterstep", 0, NULL
, 'a'},
233 {"shaped", 0, NULL
, 's'},
234 {"led-color", 1, NULL
, 'l'},
235 {"led-highcolor", 1, NULL
, 'L'},
236 {"back-color", 1, NULL
, 'b'},
237 {"mix-device", 1, NULL
, 'm'},
238 {"config-file", 1, NULL
, 'c'},
239 {"x-class", 1, NULL
, 'x'},
240 {"scrollwheel",1, NULL
, 'r'},
241 {NULL
, 0, NULL
, 0 }};
242 int i
, opt_index
= 0;
244 // init the config file name
245 snprintf(config_file_
, CONFIGFILELEN
-1, "%s/.wmmixer", getenv("HOME"));
247 // For backward compatibility
248 for(i
=1; i
<argc
; i
++)
250 if(strcmp("-position", argv
[i
]) == 0)
252 sprintf(argv
[i
], "%s", "-g");
254 else if(strcmp("-help", argv
[i
]) == 0)
256 sprintf(argv
[i
], "%s", "-h");
258 else if(strcmp("-display", argv
[i
]) == 0)
260 sprintf(argv
[i
], "%s", "-d");
264 while ((i
= getopt_long(argc
, argv
, "hvd:g:wasl:L:b:m:c:x:r:", long_opts
, &opt_index
)) != -1)
271 displayUsage(argv
[0]);
277 xhandler_
->setDisplay(optarg
);
280 xhandler_
->setPosition(optarg
);
283 xhandler_
->setWindowMaker();
286 xhandler_
->setAfterStep();
289 xhandler_
->setUnshaped();
292 xhandler_
->setLedColor(optarg
);
295 xhandler_
->setLedHighColor(optarg
);
298 xhandler_
->setBackColor(optarg
);
301 sprintf(mixer_device_
, "%s", optarg
);
304 snprintf(config_file_
, CONFIGFILELEN
-1, "%s", optarg
);
307 xhandler_
->setWindowClass(optarg
);
311 wheel_scroll_
= atoi(optarg
);
317 //--------------------------------------------------------------------
318 void WMMixer::readConfigurationFile()
324 unsigned current
= mixctl_
->getNrDevices() + 1;
326 if((rcfile
=fopen(config_file_
, "r"))!=NULL
)
331 fgets(buf
, 250, rcfile
);
332 if((done
=feof(rcfile
))==0)
334 buf
[strlen(buf
)-1]=0;
335 if(strncmp(buf
, "addchannel ", strlen("addchannel "))==0)
337 sscanf(buf
, "addchannel %i", ¤t
);
338 if(current
>= mixctl_
->getNrDevices() || mixctl_
->getSupport(current
) == false)
340 fprintf(stderr
,"%s : Sorry, this channel (%i) is not supported.\n", NAME
, current
);
341 current
= mixctl_
->getNrDevices() + 1;
345 channel_list_
[num_channels_
] = current
;
349 if(strncmp(buf
, "setchannel ", strlen("setchannel "))==0)
351 sscanf(buf
, "setchannel %i", ¤t
);
352 if(current
>= mixctl_
->getNrDevices() || mixctl_
->getSupport(current
)==false)
354 fprintf(stderr
,"%s : Sorry, this channel (%i) is not supported.\n", NAME
, current
);
355 current
= mixctl_
->getNrDevices() + 1;
358 if(strncmp(buf
, "setmono ", strlen("setmono "))==0)
360 if(current
== mixctl_
->getNrDevices() + 1)
361 fprintf(stderr
,"%s : Sorry, no current channel.\n", NAME
);
364 sscanf(buf
, "setmono %i", &value
);
365 mixctl_
->setLeft(current
, value
);
366 mixctl_
->setRight(current
, value
);
367 mixctl_
->writeVol(current
);
370 if(strncmp(buf
, "setleft ", strlen("setleft "))==0)
372 if(current
== mixctl_
->getNrDevices() + 1)
373 fprintf(stderr
, "%s : Sorry, no current channel.\n", NAME
);
376 sscanf(buf
, "setleft %i", &value
);
377 mixctl_
->setLeft(current
, value
);
378 mixctl_
->writeVol(current
);
381 if(strncmp(buf
, "setright ", strlen("setright "))==0)
383 if(current
== mixctl_
->getNrDevices() + 1)
384 fprintf(stderr
, "%s : Sorry, no current channel.\n", NAME
);
388 sscanf(buf
, "setleft %i", &value
);
389 mixctl_
->setRight(current
, value
);
390 mixctl_
->writeVol(current
);
393 if(strncmp(buf
, "setrecsrc ", strlen("setrecsrc "))==0)
395 if(current
== mixctl_
->getNrDevices() + 1)
396 fprintf(stderr
, "%s : Sorry, no current channel.\n", NAME
);
398 mixctl_
->setRec(current
, (strncmp(buf
+strlen("setrecsrc "), "true", strlen("true"))==0));
408 //--------------------------------------------------------------------
409 void WMMixer::displayUsage(const char* name
)
411 std::cout
<< "Usage: " << name
<< "[options]" << std::endl
;
412 std::cout
<< " -h, --help display this help screen" << std::endl
;
413 std::cout
<< " -v, --version display program version" << std::endl
;
414 std::cout
<< " -d, --display <string> display to use (see X manual pages)" << std::endl
;
415 std::cout
<< " -g, --geometry +XPOS+YPOS geometry to use (see X manual pages)" << std::endl
;
416 std::cout
<< " -w, --withdrawn run the application in withdrawn mode" << std::endl
;
417 std::cout
<< " (for WindowMaker, etc)" << std::endl
;
418 std::cout
<< " -a, --afterstep use smaller window (for AfterStep Wharf)" << std::endl
;
419 std::cout
<< " -s, --shaped shaped window" << std::endl
;
420 std::cout
<< " -l, --led-color <string> use the specified color for led display" << std::endl
;
421 std::cout
<< " -L, --led-highcolor <string> use the specified color for led shading" << std::endl
;
422 std::cout
<< " -b, --back-color <string> use the specified color for backgrounds" << std::endl
;
423 std::cout
<< " -m, --mix-device use specified device (rather than /dev/mixer)" << std::endl
;
424 std::cout
<< " -c, --config-file use specified config file (rather than $HOME/.wmmixer)" << std::endl
;
425 std::cout
<< " -x, --x-class <string> use specified class (rather than WMMmixer)" << std::endl
;
426 std::cout
<< " -r, --scrollwheel <number> volume increase/decrease with mouse wheel (default: 2)" << std::endl
;
427 std::cout
<< "\nFor backward compatibility the following obsolete options are still supported:" << std::endl
;
428 std::cout
<< " -help display this help screen" << std::endl
;
429 std::cout
<< " -position geometry to use (see X manual pages)" << std::endl
;
430 std::cout
<< " -display display to use (see X manual pages)" << std::endl
;
435 //--------------------------------------------------------------------
436 void WMMixer::displayVersion()
438 std::cout
<< "wmmixer version " PACKAGE_VERSION
<< std::endl
;
443 //--------------------------------------------------------------------
444 void WMMixer::pressEvent(XButtonEvent
*xev
)
446 bool forced_update
= true;
447 int x
= xev
->x
-(xhandler_
->getWindowSize()/2-32);
448 int y
= xev
->y
-(xhandler_
->getWindowSize()/2-32);
450 if(xhandler_
->isLeftButton(x
, y
))
452 if(current_channel_
< 1)
453 current_channel_
=num_channels_
-1;
457 xhandler_
->setButtonState(xhandler_
->getButtonState() | BTNPREV
);
459 xhandler_
->drawBtns(BTNPREV
, current_show_recording_
);
462 if(xhandler_
->isRightButton(x
, y
))
465 if(current_channel_
>= num_channels_
)
468 xhandler_
->setButtonState(xhandler_
->getButtonState() | BTNNEXT
);
470 xhandler_
->drawBtns(BTNNEXT
, current_show_recording_
);
474 if(xhandler_
->isVolumeBar(x
, y
))
480 vl
= ((60-y
)*100)/(2*25);
484 else if(xev
->button
== 4)
486 vr
= mixctl_
->readRight(channel_list_
[current_channel_
]) + wheel_scroll_
;
487 vl
= mixctl_
->readLeft(channel_list_
[current_channel_
]) + wheel_scroll_
;
490 else if(xev
->button
== 5)
492 vr
= mixctl_
->readRight(channel_list_
[current_channel_
]) - wheel_scroll_
;
493 vl
= mixctl_
->readLeft(channel_list_
[current_channel_
]) - wheel_scroll_
;
502 mixctl_
->setLeft(channel_list_
[current_channel_
], vl
);
504 mixctl_
->setRight(channel_list_
[current_channel_
], vr
);
505 mixctl_
->writeVol(channel_list_
[current_channel_
]);
507 forced_update
= false;
511 if(xhandler_
->isRecButton(x
, y
))
513 mixctl_
->setRec(channel_list_
[current_channel_
], !mixctl_
->readRec(channel_list_
[current_channel_
], false));
515 forced_update
= false;
519 if(xhandler_
->isMuteButton(x
, y
))
521 if(mixctl_
->isMuted(channel_list_
[current_channel_
]))
523 xhandler_
->setButtonState(xhandler_
->getButtonState() & ~BTNMUTE
);
524 mixctl_
->unmute(channel_list_
[current_channel_
]);
528 mixctl_
->mute(channel_list_
[current_channel_
]);
529 xhandler_
->setButtonState(xhandler_
->getButtonState() | BTNMUTE
);
532 xhandler_
->drawBtns(BTNMUTE
, current_show_recording_
);
535 // Update volume display
536 checkVol(forced_update
);
539 //--------------------------------------------------------------------
540 void WMMixer::releaseEvent(XButtonEvent
*xev
)
543 xhandler_
->setButtonState(xhandler_
->getButtonState() & ~(BTNPREV
| BTNNEXT
));
544 xhandler_
->drawBtns(BTNPREV
| BTNNEXT
, current_show_recording_
);
545 xhandler_
->repaint();
548 //--------------------------------------------------------------------
549 void WMMixer::motionEvent(XMotionEvent
*xev
)
551 int x
=xev
->x
-(xhandler_
->getWindowSize()/2-32);
552 int y
=xev
->y
-(xhandler_
->getWindowSize()/2-32);
553 // if(x>=37 && x<=56 && y>=8 && dragging_){
554 if(xhandler_
->isVolumeBar(x
, y
) && dragging_
){
555 int v
=((60-y
)*100)/(2*25);
559 mixctl_
->setLeft(channel_list_
[current_channel_
], v
);
561 mixctl_
->setRight(channel_list_
[current_channel_
], v
);
562 mixctl_
->writeVol(channel_list_
[current_channel_
]);
567 //--------------------------------------------------------------------
568 void WMMixer::updateDisplay()
570 xhandler_
->update(channel_list_
[current_channel_
]);
571 if(mixctl_
->getStereo(channel_list_
[current_channel_
]))
573 xhandler_
->drawLeft(current_channel_left_
);
574 xhandler_
->drawRight(current_channel_right_
);
578 xhandler_
->drawMono(current_channel_right_
);
580 xhandler_
->drawBtns(BTNREC
| BTNNEXT
| BTNPREV
| BTNMUTE
, current_show_recording_
);
581 xhandler_
->repaint();
586 //====================================================================
587 int main(int argc
, char** argv
)
589 WMMixer mixer
= WMMixer();
590 mixer
.init(argc
, argv
);