00001
00002
00003
00004
00005
00006
00007 #include <sys/types.h>
00008 #include <errno.h>
00009 #include <curses.h>
00010 #include <signal.h>
00011 #include <stdlib.h>
00012 #include <unistd.h>
00013 #include <fcntl.h>
00014 #include <stdio.h>
00015 #include <string.h>
00016 #include <sys/ioctl.h>
00017 #include <minix/sound.h>
00018
00019 #define CURS_CTRL '\033'
00020 #define ESCAPE 27
00021 #define UP 'A'
00022 #define DOWN 'B'
00023 #define LEFT 'D'
00024 #define RIGHT 'C'
00025 #define SPACE ' '
00026
00027
00028 _PROTOTYPE ( int main, (int arg, char **argv));
00029 _PROTOTYPE ( void usage, (void));
00030 _PROTOTYPE ( void non_interactive, (void));
00031 _PROTOTYPE ( void setup_screen, (void));
00032 _PROTOTYPE ( int read_settings, (void));
00033 _PROTOTYPE ( int write_settings, (void));
00034 _PROTOTYPE ( void rdwr_levels, (int flag));
00035 _PROTOTYPE ( void rdwr_inputs, (int flag));
00036 _PROTOTYPE ( void rdwr_outputs, (int flag));
00037 _PROTOTYPE ( void create_slider, (int x, int y, enum Device device));
00038 _PROTOTYPE ( void show_inputs, (int x, int y));
00039 _PROTOTYPE ( void show_outputs, (int x, int y));
00040 _PROTOTYPE ( char *d_name, (enum Device device, char *name));
00041 _PROTOTYPE ( void user_interface, (void));
00042 _PROTOTYPE ( void terminate, (int s));
00043
00044 WINDOW *main_win;
00045 int old_stdin;
00046 int fd;
00047 char name[9];
00048 char *file_name;
00049 struct volume_level levels[9];
00050 struct inout_ctrl inputs_left[9];
00051 struct inout_ctrl inputs_right[9];
00052 struct inout_ctrl outputs[9];
00053
00054
00055 void usage()
00056 {
00057 fprintf(stderr, "Usage: mixer [-r]\n");
00058 exit(-1);
00059 }
00060
00061
00062 void terminate(s)
00063 int s;
00064 {
00065
00066
00067 (void) fcntl(0,F_SETFL,old_stdin);
00068 move(23, 0);
00069 refresh();
00070 resetty();
00071 endwin();
00072 exit(1);
00073 }
00074
00075
00076 int write_settings()
00077 {
00078
00079
00080 int fd;
00081
00082 if ((fd = creat(file_name, 0x124)) > 0)
00083 {
00084 write(fd, levels, sizeof(levels));
00085 write(fd, inputs_left, sizeof(inputs_left));
00086 write(fd, inputs_right, sizeof(inputs_right));
00087 write(fd, outputs, sizeof(outputs));
00088 close(fd);
00089 return 1;
00090 }
00091
00092 return 0;
00093 }
00094
00095
00096 int read_settings()
00097 {
00098
00099
00100 int fd;
00101
00102 if ((fd = open(file_name, O_RDONLY)) > 0)
00103 {
00104 read(fd, levels, sizeof(levels));
00105 read(fd, inputs_left, sizeof(inputs_left));
00106 read(fd, inputs_right, sizeof(inputs_right));
00107 read(fd, outputs, sizeof(outputs));
00108 close(fd);
00109 rdwr_levels(1);
00110 rdwr_outputs(1);
00111 rdwr_inputs(1);
00112 return 1;
00113 }
00114 return 0;
00115 }
00116
00117
00118 void rdwr_levels(flag)
00119 int flag;
00120 {
00121
00122
00123 int i;
00124 int cmd;
00125
00126 cmd = (flag == 0 ? MIXIOGETVOLUME : MIXIOSETVOLUME);
00127
00128 for(i = Master; i <= Bass; i++)
00129 (void) (ioctl(fd, cmd, &levels[i]));
00130 }
00131
00132
00133 void rdwr_inputs(flag)
00134 int flag;
00135 {
00136
00137
00138 int i;
00139 int cmd_left, cmd_right;
00140
00141 cmd_left = (flag == 0 ? MIXIOGETINPUTLEFT : MIXIOSETINPUTLEFT);
00142 cmd_right = (flag == 0 ? MIXIOGETINPUTRIGHT : MIXIOSETINPUTRIGHT);
00143
00144 for(i = Fm; i <= Mic; i++)
00145 {
00146 (void) (ioctl(fd, cmd_left, &inputs_left[i]));
00147 (void) (ioctl(fd, cmd_right, &inputs_right[i]));
00148 }
00149 }
00150
00151
00152 void rdwr_outputs(flag)
00153 int flag;
00154 {
00155
00156
00157 int i;
00158 int cmd;
00159
00160 cmd = (flag == 0 ? MIXIOGETOUTPUT : MIXIOSETOUTPUT);
00161
00162 for(i = Cd; i <= Mic; i++)
00163 (void) (ioctl(fd, cmd, &outputs[i]));
00164 }
00165
00166
00167 int main(argc, argv)
00168 int argc;
00169 char **argv;
00170
00171 {
00172 int i;
00173 char *home_ptr;
00174 int fd2;
00175
00176
00177 if ((fd = open("/dev/mixer",O_RDONLY)) < 0)
00178 {
00179 fprintf(stderr, "Cannot open /dev/mixer\n");
00180 exit(-1);
00181 }
00182
00183
00184
00185
00186 home_ptr = getenv("HOME");
00187 file_name = malloc(strlen(home_ptr)+strlen("mixer.ini\0"));
00188 if (file_name == (char *)0)
00189 {
00190 fprintf(stderr, "Not enough memory\n");
00191 exit(-1);
00192 }
00193 strncpy(file_name, home_ptr, strlen(home_ptr));
00194 strncpy(file_name+strlen(home_ptr), "/.mixer\0", 9);
00195
00196
00197 for(i = Master; i <= Bass; i++)
00198 {
00199 levels[i].device = i;
00200 inputs_left[i].device = i;
00201 inputs_right[i].device = i;
00202 outputs[i].device = i;
00203 }
00204
00205
00206 if (argc > 1)
00207 {
00208 if (strncmp(argv[1], "-r", 2) == 0)
00209 {
00210 if (read_settings())
00211 {
00212 printf("Mixer settings restored\n");
00213 exit(0);
00214 }
00215 else
00216 {
00217 fprintf(stderr, "Could not restore mixer settings\n");
00218 exit(-1);
00219 }
00220 }
00221 else usage();
00222 }
00223
00224
00225 (void) initscr();
00226 signal(SIGINT, terminate);
00227 old_stdin = fcntl(0,F_GETFL);
00228 cbreak();
00229 noecho();
00230 main_win = newwin(23,80,0,0);
00231 scrollok(main_win, FALSE);
00232
00233
00234 rdwr_levels(0);
00235 rdwr_inputs(0);
00236 rdwr_outputs(0);
00237
00238
00239 setup_screen();
00240 user_interface();
00241 }
00242
00243
00244 void user_interface()
00245 {
00246
00247
00248 char c;
00249 int x,y;
00250 int right;
00251 int input_scr, input_pos;
00252 int output_scr, output_pos;
00253 int max_level;
00254 enum Device device;
00255 int fd2;
00256
00257 device = Master;
00258 right = 0;
00259 input_scr = 0;
00260 output_scr = 0;
00261 input_pos = 0;
00262 output_pos = 0;
00263
00264 while(1)
00265 {
00266 if (input_scr)
00267 {
00268 y = device + 9;
00269 x = 51 + input_pos + (device == Mic ? 2 : 0);
00270 }
00271 else if (output_scr)
00272 {
00273 y = device + 15;
00274 x = 53 + output_pos + (device == Mic ? 4 : 0);
00275 }
00276 else
00277 {
00278 y = (device != Speaker ? 2 : 1) +
00279 (device - (device < Treble ? 0 : Treble)) * 3 +
00280 (right == 0 ? 0 : 1);
00281 if (!right)
00282 x = 9 + levels[device].left / (device < Speaker ? 2 : 1 ) +
00283 (device > Speaker ? 39 : 0);
00284 else
00285 x = 9 + levels[device].right / (device < Speaker ? 2 : 1) +
00286 (device > Speaker ? 39 : 0);
00287 }
00288
00289 wmove(main_win,y,x);
00290 wrefresh(main_win);
00291 c = wgetch(main_win);
00292
00293 switch(c)
00294 {
00295 case CURS_CTRL:
00296 {
00297 (void) wgetch(main_win);
00298 c = wgetch(main_win);
00299
00300 switch(c)
00301 {
00302 case DOWN:
00303 {
00304 if (output_scr)
00305 {
00306 if (device < Mic)
00307 {
00308 device++;
00309 if (device == Mic) output_pos = 0;
00310 }
00311 }
00312 else if (right || input_scr)
00313 {
00314 if (!input_scr)
00315 {
00316 if (device < Bass)
00317 {
00318 device++;
00319 right = 0;
00320 }
00321 else
00322 {
00323 input_scr = 1;
00324 input_pos = 0;
00325 device = Fm;
00326 }
00327 }
00328 else
00329 {
00330 if (device < Mic)
00331 {
00332 device++;
00333 if (device == Mic && input_pos > 8) input_pos = 8;
00334 }
00335 else
00336 {
00337 device = Cd;
00338 output_scr = 1;
00339 input_scr = 0;
00340 output_pos = 0;
00341 }
00342 }
00343 }
00344 else
00345 {
00346 if (device != Mic && device != Speaker) right = 1;
00347 else { device++; right = 0; }
00348 }
00349 };break;
00350 case UP:
00351 {
00352 if (output_scr)
00353 {
00354 if (device > Cd) device--;
00355 else
00356 {
00357 device = Mic;
00358 output_scr = 0;
00359 input_scr = 1;
00360 }
00361 }
00362 else if (!right || input_scr)
00363 {
00364 if (input_scr)
00365 {
00366 if (device > Fm) device--;
00367 else
00368 {
00369 input_scr = 0;
00370 device = Bass;
00371 right = 1;
00372 }
00373 }
00374 else
00375 {
00376 if (device > Master)
00377 {
00378 device--;
00379 if (device != Mic && device != Speaker) right = 1;
00380 }
00381 }
00382 }
00383 else
00384 right = 0;
00385 };break;
00386 case RIGHT:
00387 {
00388 if (output_scr)
00389 {
00390 if (output_pos < 8 && device != Mic) output_pos = 8;
00391 }
00392 else if (!input_scr)
00393 {
00394 if (device < Speaker) max_level = 31;
00395 else if (device > Speaker) max_level = 15;
00396 else max_level = 4;
00397
00398 if (!right)
00399 {
00400 if (levels[device].left < max_level) levels[device].left+=
00401 (device < Speaker ? 2 : 1);
00402 }
00403 else
00404 {
00405 if (levels[device].right < max_level) levels[device].right+=
00406 (device < Speaker ? 2 : 1);
00407 }
00408 ioctl(fd, MIXIOSETVOLUME, &levels[device]);
00409 ioctl(fd, MIXIOGETVOLUME, &levels[device]);
00410 create_slider(1 + (device < Treble ? 0 : 39),
00411 (device - (device < Treble ? 0 : Treble))*3 +
00412 (device != Speaker ? 2 : 1), device);
00413 }
00414 else
00415 {
00416 if ((device != Mic && input_pos < 12) ||
00417 (device == Mic && input_pos < 8))
00418 input_pos += (4 + (device == Mic ? 4 : 0));
00419 }
00420 };break;
00421 case LEFT:
00422 {
00423 if (output_scr)
00424 {
00425 if (output_pos > 0) output_pos = 0;
00426 }
00427 else if (!input_scr)
00428 {
00429 if (!right)
00430 {
00431 if (levels[device].left > 0) levels[device].left-=
00432 (device < Speaker ? 2 : 1);
00433 }
00434 else
00435 {
00436 if (levels[device].right > 0) levels[device].right-=
00437 (device < Speaker ? 2 : 1);
00438 }
00439 ioctl(fd, MIXIOSETVOLUME, &levels[device]);
00440 ioctl(fd, MIXIOGETVOLUME, &levels[device]);
00441 create_slider(1 + (device < Treble ? 0 : 39),
00442 (device - (device < Treble ? 0 : Treble))*3 +
00443 (device != Speaker ? 2 : 1), device);
00444 }
00445 else
00446 {
00447 if (input_pos > 0)
00448 input_pos -= (4 + (device == Mic ? 4 : 0));
00449 }
00450 };break;
00451 }
00452 };break;
00453 case SPACE:
00454 {
00455 if (output_scr)
00456 {
00457 switch(output_pos)
00458 {
00459 case 0:
00460 case 4:
00461 {
00462 outputs[device].left =
00463 (outputs[device].left == ON ? OFF : ON);
00464 ioctl(fd, MIXIOSETOUTPUT, &outputs[device]);
00465 };break;
00466 case 8:
00467 {
00468 outputs[device].right =
00469 (outputs[device].right == ON ? OFF : ON);
00470 ioctl(fd, MIXIOSETOUTPUT, &outputs[device]);
00471 };break;
00472 }
00473 ioctl(fd, MIXIOGETOUTPUT, &outputs[device]);
00474 show_outputs(41,16);
00475 }
00476 else if (input_scr)
00477 {
00478 switch(input_pos)
00479 {
00480 case 0:
00481 {
00482 inputs_left[device].left =
00483 (inputs_left[device].left == ON ? OFF : ON);
00484 ioctl(fd, MIXIOSETINPUTLEFT, &inputs_left[device]);
00485 };break;
00486 case 4:
00487 {
00488 inputs_left[device].right =
00489 (inputs_left[device].right == ON ? OFF : ON);
00490 ioctl(fd, MIXIOSETINPUTLEFT, &inputs_left[device]);
00491 };break;
00492 case 8:
00493 {
00494 inputs_right[device].left =
00495 (inputs_right[device].left == ON ? OFF : ON);
00496 ioctl(fd, MIXIOSETINPUTRIGHT, &inputs_right[device]);
00497 };break;
00498 case 12:
00499 {
00500 inputs_right[device].right =
00501 (inputs_right[device].right == ON ? OFF : ON);
00502 ioctl(fd, MIXIOSETINPUTRIGHT, &inputs_right[device]);
00503 };break;
00504 }
00505 ioctl(fd, MIXIOGETINPUTLEFT, &inputs_left[device]);
00506 ioctl(fd, MIXIOGETINPUTRIGHT, &inputs_right[device]);
00507 show_inputs(41,8);
00508 }
00509 };break;
00510 case 's':
00511 {
00512 if (write_settings())
00513 mvwprintw(main_win,22,28, "mixer settings saved");
00514 else
00515 mvwprintw(main_win,22,28, "error: file not saved");
00516 wrefresh(main_win);
00517 sleep(1);
00518 mvwprintw(main_win,22,28, " ");
00519 };break;
00520 case 'r':
00521 {
00522 if (read_settings())
00523 mvwprintw(main_win,22,28, "mixer settings restored");
00524 else
00525 mvwprintw(main_win,22,28, "error: could not open");
00526 wrefresh(main_win);
00527 sleep(1);
00528 setup_screen();
00529 };break;
00530 case 'e': terminate(1);
00531 }
00532 }
00533 }
00534
00535
00536 char *d_name(device, name)
00537 enum Device device;
00538 char *name;
00539 {
00540
00541
00542 switch (device)
00543 {
00544 case Master: strncpy(name, "Master \0", 9);break;
00545 case Dac: strncpy(name, "Dac \0", 9);break;
00546 case Fm: strncpy(name, "Fm \0", 9);break;
00547 case Cd: strncpy(name, "CD \0", 9);break;
00548 case Line: strncpy(name, "Line \0", 9);break;
00549 case Mic: strncpy(name, "Mic \0", 9);break;
00550 case Speaker: strncpy(name, "Speaker \0", 9);break;
00551 case Treble: strncpy(name, "Treble \0", 9);break;
00552 case Bass: strncpy(name, "Bass \0", 9);break;
00553 }
00554 return name;
00555 }
00556
00557
00558 void create_slider(x, y, device)
00559 int x;
00560 int y;
00561 enum Device device;
00562 {
00563
00564
00565 int left;
00566 int right;
00567 int i;
00568
00569 mvwprintw(main_win,y,x, "%s", d_name(device, name));
00570
00571 left = levels[device].left / (device < Speaker ? 2 : 1);
00572 right = levels[device].right / (device < Speaker ? 2 : 1);
00573
00574 for (i = 0; i < 16; i++)
00575 {
00576 if (device != Speaker || i < 4)
00577 mvwprintw(main_win,y,x+i+8, (i == left ? "*" : "-"));
00578 if (device < Mic || device > Speaker)
00579 mvwprintw(main_win,y+1,x+i+8, (i == right ? "*" : "-"));
00580 }
00581
00582 if (device < Mic || device > Speaker)
00583 {
00584 mvwprintw(main_win,y,x+i+10, "left");
00585 mvwprintw(main_win,y+1,x+i+10, "right");
00586 }
00587 wrefresh(main_win);
00588 }
00589
00590 void show_inputs(x,y)
00591 int x;
00592 int y;
00593 {
00594
00595
00596 int i;
00597
00598 mvwprintw(main_win,y,x, " Rec-In ");
00599 mvwprintw(main_win,y+1,x," left right");
00600 mvwprintw(main_win,y+2,x," l r l r");
00601 for (i = Fm; i <= Line; i++)
00602 {
00603 mvwprintw(main_win,y+i+1,x, "%s %d %d %d %d",
00604 d_name(i, (char *)name),
00605 (inputs_left[i].left == ON ? 1 : 0),
00606 (inputs_left[i].right == ON ? 1 : 0),
00607 (inputs_right[i].left == ON ? 1 : 0),
00608 (inputs_right[i].right == ON ? 1 : 0));
00609 }
00610 mvwprintw(main_win,y+i+1,x, "%s %d %d",
00611 d_name(Mic, (char *)name),
00612 (inputs_left[Mic].left == ON ? 1 : 0),
00613 (inputs_right[Mic].left == ON ? 1 : 0));
00614 wrefresh(main_win);
00615 }
00616
00617 void show_outputs(x,y)
00618 int x;
00619 int y;
00620 {
00621
00622
00623 int i;
00624
00625 mvwprintw(main_win,y,x, " Mix-Out ");
00626 mvwprintw(main_win,y+1,x, " left right");
00627 for (i = Cd; i <= Line; i++)
00628 {
00629 mvwprintw(main_win,y+i-1,x,"%s %d %d",
00630 d_name(i, (char *)name),
00631 (outputs[i].left == ON ? 1 : 0),
00632 (outputs[i].right == ON ? 1 : 0));
00633 }
00634 mvwprintw(main_win,y+i-1,x,"%s %d",
00635 d_name(Mic, (char *)name),
00636 (outputs[Mic].left == ON ? 1 : 0));
00637
00638 wrefresh(main_win);
00639 }
00640
00641
00642 void setup_screen()
00643 {
00644 int i;
00645
00646 wclear(main_win);
00647 mvwprintw(main_win,0,23,"------- Mixer Controls -------");
00648 wrefresh(main_win);
00649
00650 for(i = 0; i <= Speaker; i++)
00651 create_slider(1, i*3+(i <= Mic ? 2 : 1), i);
00652
00653 create_slider(40, 2, Treble);
00654 create_slider(40, 5, Bass);
00655
00656 show_inputs(41,8);
00657 show_outputs(41,16);
00658 }