Initial dockapps git repo
[dockapps.git] / wmmixer-1.5 / wmmixer.cc
blob3cbe4a0789716259a56f583ad8a372d4c01c1c11
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 // 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.
12 #include "wmmixer.h"
14 //--------------------------------------------------------------------
15 WMMixer::WMMixer()
17 // Initialize member variables
18 current_channel_ = 0;
19 num_channels_ = 0;
20 current_channel_left_ = 0;
21 current_channel_right_ = 0;
22 repeat_timer_ = 0;
23 wheel_scroll_ = 2;
24 current_recording_ = false;
25 current_show_recording_ = false;
26 dragging_ = false;
28 strcpy(mixer_device_, MIXERDEV);
30 xhandler_ = new XHandler();
34 //--------------------------------------------------------------------
35 WMMixer::~WMMixer()
37 delete[] channel_list_;
38 delete mixctl_;
39 delete xhandler_;
43 //--------------------------------------------------------------------
44 void WMMixer::loop()
46 XEvent xev;
48 bool done=false;
49 while(!done)
51 while(XPending(xhandler_->getDisplay()))
53 XNextEvent(xhandler_->getDisplay(), &xev);
54 switch(xev.type)
56 case Expose:
57 xhandler_->repaint();
58 break;
59 case ButtonPress:
60 pressEvent(&xev.xbutton);
61 break;
62 case ButtonRelease:
63 releaseEvent(&xev.xbutton);
64 break;
65 case MotionNotify:
66 motionEvent(&xev.xmotion);
67 break;
68 case ClientMessage:
69 if(xev.xclient.data.l[0] == (int)xhandler_->getDeleteWin())
70 done=true;
71 break;
75 // keep a button pressed causes scrolling throught the channels
76 if(xhandler_->getButtonState() & (BTNPREV | BTNNEXT))
78 repeat_timer_++;
79 if(repeat_timer_ >= RPTINTERVAL)
81 if(xhandler_->getButtonState() & BTNNEXT)
83 current_channel_++;
84 if(current_channel_ >= num_channels_)
85 current_channel_ = 0;
87 else
89 if(current_channel_ < 1)
90 current_channel_ = num_channels_-1;
91 else
92 current_channel_--;
95 checkVol(true);
96 repeat_timer_ = 0;
99 else
101 checkVol(false);
104 XFlush(xhandler_->getDisplay());
105 usleep(100000);
110 //--------------------------------------------------------------------
111 void WMMixer::init(int argc, char **argv)
113 parseArgs(argc, argv);
115 initMixer();
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;
125 else
127 checkVol(true);
131 //--------------------------------------------------------------------
132 void WMMixer::initMixer()
134 // Initialize Mixer
137 mixctl_ = new MixCtl(mixer_device_);
139 catch(MixerDeviceException &exc)
141 std::cerr << NAME << " : " << exc.getErrorMessage() << "'." << std::endl;
142 exit(1);
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;
151 num_channels_++;
157 //--------------------------------------------------------------------
158 void WMMixer::checkVol(bool forced = true)
160 if(!forced && !mixctl_->hasChanged())
161 return;
163 if(mixctl_->isMuted(channel_list_[current_channel_]))
164 xhandler_->setButtonState(xhandler_->getButtonState() | BTNMUTE);
165 else
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);
174 if(forced)
176 current_channel_left_ = nl;
177 current_channel_right_ = nr;
178 current_recording_ = nrec;
179 if(nrec)
180 xhandler_->setButtonState(xhandler_->getButtonState() | BTNREC);
181 else
182 xhandler_->setButtonState(xhandler_->getButtonState() & ~BTNREC);
183 current_show_recording_=mixctl_->getRecords(channel_list_[current_channel_]);
184 updateDisplay();
186 else
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_);
195 else
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_);
203 else
204 xhandler_->drawMono(current_channel_left_);
206 if(nrec!=current_recording_)
208 current_recording_=nrec;
209 if(nrec)
210 xhandler_->setButtonState(xhandler_->getButtonState() | BTNREC);
211 else
212 xhandler_->setButtonState(xhandler_->getButtonState() & ~BTNREC);
213 xhandler_->drawBtns(BTNREC, current_show_recording_);
215 updateDisplay();
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)
261 switch (i)
263 case 'h':
264 case ':':
265 case '?':
266 displayUsage(argv[0]);
267 break;
268 case 'v':
269 displayVersion();
270 break;
271 case 'd':
272 xhandler_->setDisplay(optarg);
273 break;
274 case 'g':
275 xhandler_->setPosition(optarg);
276 break;
277 case 'w':
278 xhandler_->setWindowMaker();
279 break;
280 case 'a':
281 xhandler_->setAfterStep();
282 break;
283 case 's':
284 xhandler_->setUnshaped();
285 break;
286 case 'l':
287 xhandler_->setLedColor(optarg);
288 break;
289 case 'L':
290 xhandler_->setLedHighColor(optarg);
291 break;
292 case 'b':
293 xhandler_->setBackColor(optarg);
294 break;
295 case 'm':
296 sprintf(mixer_device_, "%s", optarg);
297 break;
298 case 'r':
299 if(atoi(optarg)>0)
300 wheel_scroll_ = atoi(optarg);
301 break;
306 //--------------------------------------------------------------------
307 void WMMixer::readConfigurationFile()
309 FILE *rcfile;
310 char rcfilen[256];
311 char buf[256];
312 int done;
313 // int current=-1;
314 unsigned current = mixctl_->getNrDevices() + 1;
316 sprintf(rcfilen, "%s/.wmmixer", getenv("HOME"));
317 if((rcfile=fopen(rcfilen, "r"))!=NULL)
319 num_channels_=0;
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", &current);
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;
334 else
336 channel_list_[num_channels_] = current;
337 num_channels_++;
340 if(strncmp(buf, "setchannel ", strlen("setchannel "))==0)
342 sscanf(buf, "setchannel %i", &current);
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);
353 else{
354 int value;
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);
365 else{
366 int value;
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);
376 else
378 int value;
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);
388 else
389 mixctl_->setRec(current, (strncmp(buf+strlen("setrecsrc "), "true", strlen("true"))==0));
393 while(done==0);
394 fclose(rcfile);
395 mixctl_->writeRec();
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;
420 exit(0);
424 //--------------------------------------------------------------------
425 void WMMixer::displayVersion()
427 std::cout << "wmmixer version 1.5" << std::endl;
428 exit(0);
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;
443 else
444 current_channel_--;
446 xhandler_->setButtonState(xhandler_->getButtonState() | BTNPREV);
447 repeat_timer_ = 0;
448 xhandler_->drawBtns(BTNPREV, current_show_recording_);
451 if(xhandler_->isRightButton(x, y))
453 current_channel_++;
454 if(current_channel_ >= num_channels_)
455 current_channel_=0;
457 xhandler_->setButtonState(xhandler_->getButtonState() | BTNNEXT);
458 repeat_timer_ = 0;
459 xhandler_->drawBtns(BTNNEXT, current_show_recording_);
462 // Volume settings
463 if(xhandler_->isVolumeBar(x, y))
465 int vl = 0, vr = 0;
467 if(xev->button < 4)
469 vl = ((60-y)*100)/(2*25);
470 vr = vl;
471 dragging_ = true;
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_;
485 if(vl <= 0)
486 vl = 0;
487 if(vr <= 0)
488 vr = 0;
490 if(x <= 50)
491 mixctl_->setLeft(channel_list_[current_channel_], vl);
492 if(x >= 45)
493 mixctl_->setRight(channel_list_[current_channel_], vr);
494 mixctl_->writeVol(channel_list_[current_channel_]);
496 forced_update = false;
499 // Toggle record
500 if(xhandler_->isRecButton(x, y))
502 mixctl_->setRec(channel_list_[current_channel_], !mixctl_->readRec(channel_list_[current_channel_], false));
503 mixctl_->writeRec();
504 forced_update = false;
507 // Toggle mute
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_]);
515 else
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)
531 dragging_ = false;
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);
545 if(v<0)
546 v=0;
547 if(x<=50)
548 mixctl_->setLeft(channel_list_[current_channel_], v);
549 if(x>=45)
550 mixctl_->setRight(channel_list_[current_channel_], v);
551 mixctl_->writeVol(channel_list_[current_channel_]);
552 checkVol(false);
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_);
565 else
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);
580 mixer.loop();