wmcore: add Debian man-page.
[dockapps.git] / wmmixer / wmmixer.cc
blob74a6cfc71900e19258b29d507cf358fadd6a7dbd
1 // wmmixer.cc - A mixer designed for WindowMaker
2 //
3 // Release 1.5
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.
13 #include "wmmixer.h"
15 //--------------------------------------------------------------------
16 WMMixer::WMMixer()
18 // Initialize member variables
19 current_channel_ = 0;
20 num_channels_ = 0;
21 current_channel_left_ = 0;
22 current_channel_right_ = 0;
23 repeat_timer_ = 0;
24 wheel_scroll_ = 2;
25 current_recording_ = false;
26 current_show_recording_ = false;
27 dragging_ = false;
29 strcpy(mixer_device_, MIXERDEV);
31 xhandler_ = new XHandler();
35 //--------------------------------------------------------------------
36 WMMixer::~WMMixer()
38 delete[] channel_list_;
39 delete mixctl_;
40 delete xhandler_;
44 //--------------------------------------------------------------------
45 void WMMixer::loop()
47 XEvent xev;
49 bool done=false;
50 while(!done)
52 while(XPending(xhandler_->getDisplay()))
54 XNextEvent(xhandler_->getDisplay(), &xev);
55 switch(xev.type)
57 case Expose:
58 xhandler_->repaint();
59 break;
60 case ButtonPress:
61 pressEvent(&xev.xbutton);
62 break;
63 case ButtonRelease:
64 releaseEvent(&xev.xbutton);
65 break;
66 case MotionNotify:
67 motionEvent(&xev.xmotion);
68 break;
69 case ClientMessage:
70 if(xev.xclient.data.l[0] == (int)xhandler_->getDeleteWin())
71 done=true;
72 break;
76 // keep a button pressed causes scrolling throught the channels
77 if(xhandler_->getButtonState() & (BTNPREV | BTNNEXT))
79 repeat_timer_++;
80 if(repeat_timer_ >= RPTINTERVAL)
82 if(xhandler_->getButtonState() & BTNNEXT)
84 current_channel_++;
85 if(current_channel_ >= num_channels_)
86 current_channel_ = 0;
88 else
90 if(current_channel_ < 1)
91 current_channel_ = num_channels_-1;
92 else
93 current_channel_--;
96 checkVol(true);
97 repeat_timer_ = 0;
100 else
102 checkVol(false);
105 XFlush(xhandler_->getDisplay());
106 usleep(100000);
111 //--------------------------------------------------------------------
112 void WMMixer::init(int argc, char **argv)
114 parseArgs(argc, argv);
116 initMixer();
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;
126 else
128 checkVol(true);
132 //--------------------------------------------------------------------
133 void WMMixer::initMixer()
135 // Initialize Mixer
138 mixctl_ = new MixCtl(mixer_device_);
140 catch(MixerDeviceException &exc)
142 std::cerr << NAME << " : " << exc.getErrorMessage() << "'." << std::endl;
143 exit(1);
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;
152 num_channels_++;
158 //--------------------------------------------------------------------
159 void WMMixer::checkVol(bool forced = true)
161 if(!forced && !mixctl_->hasChanged())
162 return;
164 if(mixctl_->isMuted(channel_list_[current_channel_]))
165 xhandler_->setButtonState(xhandler_->getButtonState() | BTNMUTE);
166 else
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);
175 if(forced)
177 current_channel_left_ = nl;
178 current_channel_right_ = nr;
179 current_recording_ = nrec;
180 if(nrec)
181 xhandler_->setButtonState(xhandler_->getButtonState() | BTNREC);
182 else
183 xhandler_->setButtonState(xhandler_->getButtonState() & ~BTNREC);
184 current_show_recording_=mixctl_->getRecords(channel_list_[current_channel_]);
185 updateDisplay();
187 else
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_);
196 else
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_);
204 else
205 xhandler_->drawMono(current_channel_left_);
207 if(nrec!=current_recording_)
209 current_recording_=nrec;
210 if(nrec)
211 xhandler_->setButtonState(xhandler_->getButtonState() | BTNREC);
212 else
213 xhandler_->setButtonState(xhandler_->getButtonState() & ~BTNREC);
214 xhandler_->drawBtns(BTNREC, current_show_recording_);
216 updateDisplay();
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)
266 switch (i)
268 case 'h':
269 case ':':
270 case '?':
271 displayUsage(argv[0]);
272 break;
273 case 'v':
274 displayVersion();
275 break;
276 case 'd':
277 xhandler_->setDisplay(optarg);
278 break;
279 case 'g':
280 xhandler_->setPosition(optarg);
281 break;
282 case 'w':
283 xhandler_->setWindowMaker();
284 break;
285 case 'a':
286 xhandler_->setAfterStep();
287 break;
288 case 's':
289 xhandler_->setUnshaped();
290 break;
291 case 'l':
292 xhandler_->setLedColor(optarg);
293 break;
294 case 'L':
295 xhandler_->setLedHighColor(optarg);
296 break;
297 case 'b':
298 xhandler_->setBackColor(optarg);
299 break;
300 case 'm':
301 sprintf(mixer_device_, "%s", optarg);
302 break;
303 case 'c':
304 snprintf(config_file_, CONFIGFILELEN -1, "%s", optarg);
305 break;
306 case 'x':
307 xhandler_->setWindowClass(optarg);
308 break;
309 case 'r':
310 if(atoi(optarg)>0)
311 wheel_scroll_ = atoi(optarg);
312 break;
317 //--------------------------------------------------------------------
318 void WMMixer::readConfigurationFile()
320 FILE *rcfile;
321 char buf[256];
322 int done;
323 // int current=-1;
324 unsigned current = mixctl_->getNrDevices() + 1;
326 if((rcfile=fopen(config_file_, "r"))!=NULL)
328 num_channels_=0;
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", &current);
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;
343 else
345 channel_list_[num_channels_] = current;
346 num_channels_++;
349 if(strncmp(buf, "setchannel ", strlen("setchannel "))==0)
351 sscanf(buf, "setchannel %i", &current);
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);
362 else{
363 int value;
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);
374 else{
375 int value;
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);
385 else
387 int value;
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);
397 else
398 mixctl_->setRec(current, (strncmp(buf+strlen("setrecsrc "), "true", strlen("true"))==0));
402 while(done==0);
403 fclose(rcfile);
404 mixctl_->writeRec();
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;
431 exit(0);
435 //--------------------------------------------------------------------
436 void WMMixer::displayVersion()
438 std::cout << "wmmixer version " PACKAGE_VERSION << std::endl;
439 exit(0);
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;
454 else
455 current_channel_--;
457 xhandler_->setButtonState(xhandler_->getButtonState() | BTNPREV);
458 repeat_timer_ = 0;
459 xhandler_->drawBtns(BTNPREV, current_show_recording_);
462 if(xhandler_->isRightButton(x, y))
464 current_channel_++;
465 if(current_channel_ >= num_channels_)
466 current_channel_=0;
468 xhandler_->setButtonState(xhandler_->getButtonState() | BTNNEXT);
469 repeat_timer_ = 0;
470 xhandler_->drawBtns(BTNNEXT, current_show_recording_);
473 // Volume settings
474 if(xhandler_->isVolumeBar(x, y))
476 int vl = 0, vr = 0;
478 if(xev->button < 4)
480 vl = ((60-y)*100)/(2*25);
481 vr = vl;
482 dragging_ = true;
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_;
496 if(vl <= 0)
497 vl = 0;
498 if(vr <= 0)
499 vr = 0;
501 if(x <= 50)
502 mixctl_->setLeft(channel_list_[current_channel_], vl);
503 if(x >= 45)
504 mixctl_->setRight(channel_list_[current_channel_], vr);
505 mixctl_->writeVol(channel_list_[current_channel_]);
507 forced_update = false;
510 // Toggle record
511 if(xhandler_->isRecButton(x, y))
513 mixctl_->setRec(channel_list_[current_channel_], !mixctl_->readRec(channel_list_[current_channel_], false));
514 mixctl_->writeRec();
515 forced_update = false;
518 // Toggle mute
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_]);
526 else
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)
542 dragging_ = false;
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);
556 if(v<0)
557 v=0;
558 if(x<=50)
559 mixctl_->setLeft(channel_list_[current_channel_], v);
560 if(x>=45)
561 mixctl_->setRight(channel_list_[current_channel_], v);
562 mixctl_->writeVol(channel_list_[current_channel_]);
563 checkVol(false);
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_);
576 else
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);
591 mixer.loop();