source: trunk/minix/commands/ibm/mixer.c@ 21

Last change on this file since 21 was 9, checked in by Mattia Monga, 13 years ago

Minix 3.1.2a

File size: 15.5 KB
Line 
1/*
2 * mixer
3 *
4 * Michel R. Prevenier.
5 */
6
7#include <sys/types.h>
8#include <errno.h>
9#include <curses.h>
10#include <signal.h>
11#include <stdlib.h>
12#include <unistd.h>
13#include <fcntl.h>
14#include <stdio.h>
15#include <string.h>
16#include <sys/ioctl.h>
17#include <minix/sound.h>
18
19#define CURS_CTRL '\033'
20#define ESCAPE 27
21#define UP 'A'
22#define DOWN 'B'
23#define LEFT 'D'
24#define RIGHT 'C'
25#define SPACE ' '
26
27
28_PROTOTYPE ( int main, (int arg, char **argv));
29_PROTOTYPE ( void usage, (void));
30_PROTOTYPE ( void non_interactive, (void));
31_PROTOTYPE ( void setup_screen, (void));
32_PROTOTYPE ( int read_settings, (void));
33_PROTOTYPE ( int write_settings, (void));
34_PROTOTYPE ( void rdwr_levels, (int flag));
35_PROTOTYPE ( void rdwr_inputs, (int flag));
36_PROTOTYPE ( void rdwr_outputs, (int flag));
37_PROTOTYPE ( void create_slider, (int x, int y, enum Device device));
38_PROTOTYPE ( void show_inputs, (int x, int y));
39_PROTOTYPE ( void show_outputs, (int x, int y));
40_PROTOTYPE ( char *d_name, (enum Device device, char *name));
41_PROTOTYPE ( void user_interface, (void));
42_PROTOTYPE ( void terminate, (int s));
43
44WINDOW *main_win;
45int old_stdin;
46int fd;
47char name[9];
48char *file_name;
49struct volume_level levels[9];
50struct inout_ctrl inputs_left[9];
51struct inout_ctrl inputs_right[9];
52struct inout_ctrl outputs[9];
53
54
55void usage()
56{
57 fprintf(stderr, "Usage: mixer [-r]\n");
58 exit(-1);
59}
60
61
62void terminate(s)
63int s;
64{
65 /* Restore terminal parameters and exit */
66
67 (void) fcntl(0,F_SETFL,old_stdin);
68 move(23, 0);
69 refresh();
70 resetty();
71 endwin();
72 exit(1);
73}
74
75
76int write_settings()
77{
78 /* Write the current mixer settings to $HOME/.mixer */
79
80 int fd;
81
82 if ((fd = creat(file_name, 0x124)) > 0)
83 {
84 write(fd, levels, sizeof(levels));
85 write(fd, inputs_left, sizeof(inputs_left));
86 write(fd, inputs_right, sizeof(inputs_right));
87 write(fd, outputs, sizeof(outputs));
88 close(fd);
89 return 1;
90 }
91
92 return 0;
93}
94
95
96int read_settings()
97{
98 /* Restore mixer settings saved in $HOME/.mixer */
99
100 int fd;
101
102 if ((fd = open(file_name, O_RDONLY)) > 0)
103 {
104 read(fd, levels, sizeof(levels));
105 read(fd, inputs_left, sizeof(inputs_left));
106 read(fd, inputs_right, sizeof(inputs_right));
107 read(fd, outputs, sizeof(outputs));
108 close(fd);
109 rdwr_levels(1);
110 rdwr_outputs(1);
111 rdwr_inputs(1);
112 return 1;
113 }
114 return 0;
115}
116
117
118void rdwr_levels(flag)
119int flag; /* 0 = read, 1 = write */
120{
121 /* Get or set mixer settings */
122
123 int i;
124 int cmd;
125
126 cmd = (flag == 0 ? MIXIOGETVOLUME : MIXIOSETVOLUME);
127
128 for(i = Master; i <= Bass; i++)
129 (void) (ioctl(fd, cmd, &levels[i]));
130}
131
132
133void rdwr_inputs(flag)
134int flag; /* 0 = read, 1 = write */
135{
136 /* Get or set input settings */
137
138 int i;
139 int cmd_left, cmd_right;
140
141 cmd_left = (flag == 0 ? MIXIOGETINPUTLEFT : MIXIOSETINPUTLEFT);
142 cmd_right = (flag == 0 ? MIXIOGETINPUTRIGHT : MIXIOSETINPUTRIGHT);
143
144 for(i = Fm; i <= Mic; i++)
145 {
146 (void) (ioctl(fd, cmd_left, &inputs_left[i]));
147 (void) (ioctl(fd, cmd_right, &inputs_right[i]));
148 }
149}
150
151
152void rdwr_outputs(flag)
153int flag; /* 0 = read, 1 = write */
154{
155 /* Get or set output settings */
156
157 int i;
158 int cmd;
159
160 cmd = (flag == 0 ? MIXIOGETOUTPUT : MIXIOSETOUTPUT);
161
162 for(i = Cd; i <= Mic; i++)
163 (void) (ioctl(fd, cmd, &outputs[i]));
164}
165
166
167int main(argc, argv)
168int argc;
169char **argv;
170
171{
172 int i;
173 char *home_ptr;
174 int fd2;
175
176 /* Open mixer */
177 if ((fd = open("/dev/mixer",O_RDONLY)) < 0)
178 {
179 fprintf(stderr, "Cannot open /dev/mixer\n");
180 exit(-1);
181 }
182
183 /* Get user's home directory and construct the $HOME/.mixer
184 * file name
185 */
186 home_ptr = getenv("HOME");
187 file_name = malloc(strlen(home_ptr)+strlen("mixer.ini\0"));
188 if (file_name == (char *)0)
189 {
190 fprintf(stderr, "Not enough memory\n");
191 exit(-1);
192 }
193 strncpy(file_name, home_ptr, strlen(home_ptr));
194 strncpy(file_name+strlen(home_ptr), "/.mixer\0", 9);
195
196 /* Fill in the device numbers */
197 for(i = Master; i <= Bass; i++)
198 {
199 levels[i].device = i;
200 inputs_left[i].device = i;
201 inputs_right[i].device = i;
202 outputs[i].device = i;
203 }
204
205 /* Get arguments */
206 if (argc > 1)
207 {
208 if (strncmp(argv[1], "-r", 2) == 0)
209 {
210 if (read_settings())
211 {
212 printf("Mixer settings restored\n");
213 exit(0);
214 }
215 else
216 {
217 fprintf(stderr, "Could not restore mixer settings\n");
218 exit(-1);
219 }
220 }
221 else usage();
222 }
223
224 /* Initialize windows. */
225 (void) initscr();
226 signal(SIGINT, terminate);
227 old_stdin = fcntl(0,F_GETFL);
228 cbreak();
229 noecho();
230 main_win = newwin(23,80,0,0);
231 scrollok(main_win, FALSE);
232
233 /* Read all current mixer settings */
234 rdwr_levels(0);
235 rdwr_inputs(0);
236 rdwr_outputs(0);
237
238 /* Set up the user screen and handle user input */
239 setup_screen();
240 user_interface();
241}
242
243
244void user_interface()
245{
246 /* This is the user interface. */
247
248 char c;
249 int x,y;
250 int right;
251 int input_scr, input_pos;
252 int output_scr, output_pos;
253 int max_level;
254 enum Device device;
255 int fd2;
256
257 device = Master;
258 right = 0;
259 input_scr = 0;
260 output_scr = 0;
261 input_pos = 0;
262 output_pos = 0;
263
264 while(1)
265 {
266 if (input_scr)
267 {
268 y = device + 9;
269 x = 51 + input_pos + (device == Mic ? 2 : 0);
270 }
271 else if (output_scr)
272 {
273 y = device + 15;
274 x = 53 + output_pos + (device == Mic ? 4 : 0);
275 }
276 else
277 {
278 y = (device != Speaker ? 2 : 1) +
279 (device - (device < Treble ? 0 : Treble)) * 3 +
280 (right == 0 ? 0 : 1);
281 if (!right)
282 x = 9 + levels[device].left / (device < Speaker ? 2 : 1 ) +
283 (device > Speaker ? 39 : 0);
284 else
285 x = 9 + levels[device].right / (device < Speaker ? 2 : 1) +
286 (device > Speaker ? 39 : 0);
287 }
288
289 wmove(main_win,y,x);
290 wrefresh(main_win);
291 c = wgetch(main_win);
292
293 switch(c)
294 {
295 case CURS_CTRL:
296 {
297 (void) wgetch(main_win);
298 c = wgetch(main_win);
299
300 switch(c)
301 {
302 case DOWN:
303 {
304 if (output_scr)
305 {
306 if (device < Mic)
307 {
308 device++;
309 if (device == Mic) output_pos = 0;
310 }
311 }
312 else if (right || input_scr)
313 {
314 if (!input_scr)
315 {
316 if (device < Bass)
317 {
318 device++;
319 right = 0;
320 }
321 else
322 {
323 input_scr = 1;
324 input_pos = 0;
325 device = Fm;
326 }
327 }
328 else
329 {
330 if (device < Mic)
331 {
332 device++;
333 if (device == Mic && input_pos > 8) input_pos = 8;
334 }
335 else
336 {
337 device = Cd;
338 output_scr = 1;
339 input_scr = 0;
340 output_pos = 0;
341 }
342 }
343 }
344 else
345 {
346 if (device != Mic && device != Speaker) right = 1;
347 else { device++; right = 0; }
348 }
349 };break;
350 case UP:
351 {
352 if (output_scr)
353 {
354 if (device > Cd) device--;
355 else
356 {
357 device = Mic;
358 output_scr = 0;
359 input_scr = 1;
360 }
361 }
362 else if (!right || input_scr)
363 {
364 if (input_scr)
365 {
366 if (device > Fm) device--;
367 else
368 {
369 input_scr = 0;
370 device = Bass;
371 right = 1;
372 }
373 }
374 else
375 {
376 if (device > Master)
377 {
378 device--;
379 if (device != Mic && device != Speaker) right = 1;
380 }
381 }
382 }
383 else
384 right = 0;
385 };break;
386 case RIGHT:
387 {
388 if (output_scr)
389 {
390 if (output_pos < 8 && device != Mic) output_pos = 8;
391 }
392 else if (!input_scr)
393 {
394 if (device < Speaker) max_level = 31;
395 else if (device > Speaker) max_level = 15;
396 else max_level = 4;
397
398 if (!right)
399 {
400 if (levels[device].left < max_level) levels[device].left+=
401 (device < Speaker ? 2 : 1);
402 }
403 else
404 {
405 if (levels[device].right < max_level) levels[device].right+=
406 (device < Speaker ? 2 : 1);
407 }
408 ioctl(fd, MIXIOSETVOLUME, &levels[device]);
409 ioctl(fd, MIXIOGETVOLUME, &levels[device]);
410 create_slider(1 + (device < Treble ? 0 : 39),
411 (device - (device < Treble ? 0 : Treble))*3 +
412 (device != Speaker ? 2 : 1), device);
413 }
414 else
415 {
416 if ((device != Mic && input_pos < 12) ||
417 (device == Mic && input_pos < 8))
418 input_pos += (4 + (device == Mic ? 4 : 0));
419 }
420 };break;
421 case LEFT:
422 {
423 if (output_scr)
424 {
425 if (output_pos > 0) output_pos = 0;
426 }
427 else if (!input_scr)
428 {
429 if (!right)
430 {
431 if (levels[device].left > 0) levels[device].left-=
432 (device < Speaker ? 2 : 1);
433 }
434 else
435 {
436 if (levels[device].right > 0) levels[device].right-=
437 (device < Speaker ? 2 : 1);
438 }
439 ioctl(fd, MIXIOSETVOLUME, &levels[device]);
440 ioctl(fd, MIXIOGETVOLUME, &levels[device]);
441 create_slider(1 + (device < Treble ? 0 : 39),
442 (device - (device < Treble ? 0 : Treble))*3 +
443 (device != Speaker ? 2 : 1), device);
444 }
445 else
446 {
447 if (input_pos > 0)
448 input_pos -= (4 + (device == Mic ? 4 : 0));
449 }
450 };break;
451 }
452 };break;
453 case SPACE:
454 {
455 if (output_scr)
456 {
457 switch(output_pos)
458 {
459 case 0:
460 case 4:
461 {
462 outputs[device].left =
463 (outputs[device].left == ON ? OFF : ON);
464 ioctl(fd, MIXIOSETOUTPUT, &outputs[device]);
465 };break;
466 case 8:
467 {
468 outputs[device].right =
469 (outputs[device].right == ON ? OFF : ON);
470 ioctl(fd, MIXIOSETOUTPUT, &outputs[device]);
471 };break;
472 }
473 ioctl(fd, MIXIOGETOUTPUT, &outputs[device]);
474 show_outputs(41,16);
475 }
476 else if (input_scr)
477 {
478 switch(input_pos)
479 {
480 case 0:
481 {
482 inputs_left[device].left =
483 (inputs_left[device].left == ON ? OFF : ON);
484 ioctl(fd, MIXIOSETINPUTLEFT, &inputs_left[device]);
485 };break;
486 case 4:
487 {
488 inputs_left[device].right =
489 (inputs_left[device].right == ON ? OFF : ON);
490 ioctl(fd, MIXIOSETINPUTLEFT, &inputs_left[device]);
491 };break;
492 case 8:
493 {
494 inputs_right[device].left =
495 (inputs_right[device].left == ON ? OFF : ON);
496 ioctl(fd, MIXIOSETINPUTRIGHT, &inputs_right[device]);
497 };break;
498 case 12:
499 {
500 inputs_right[device].right =
501 (inputs_right[device].right == ON ? OFF : ON);
502 ioctl(fd, MIXIOSETINPUTRIGHT, &inputs_right[device]);
503 };break;
504 }
505 ioctl(fd, MIXIOGETINPUTLEFT, &inputs_left[device]);
506 ioctl(fd, MIXIOGETINPUTRIGHT, &inputs_right[device]);
507 show_inputs(41,8);
508 }
509 };break;
510 case 's':
511 {
512 if (write_settings())
513 mvwprintw(main_win,22,28, "mixer settings saved");
514 else
515 mvwprintw(main_win,22,28, "error: file not saved");
516 wrefresh(main_win);
517 sleep(1);
518 mvwprintw(main_win,22,28, " ");
519 };break;
520 case 'r':
521 {
522 if (read_settings())
523 mvwprintw(main_win,22,28, "mixer settings restored");
524 else
525 mvwprintw(main_win,22,28, "error: could not open");
526 wrefresh(main_win);
527 sleep(1);
528 setup_screen();
529 };break;
530 case 'e': terminate(1);
531 }
532 }
533}
534
535
536char *d_name(device, name)
537enum Device device;
538char *name;
539{
540 /* Convert the device number to a name */
541
542 switch (device)
543 {
544 case Master: strncpy(name, "Master \0", 9);break;
545 case Dac: strncpy(name, "Dac \0", 9);break;
546 case Fm: strncpy(name, "Fm \0", 9);break;
547 case Cd: strncpy(name, "CD \0", 9);break;
548 case Line: strncpy(name, "Line \0", 9);break;
549 case Mic: strncpy(name, "Mic \0", 9);break;
550 case Speaker: strncpy(name, "Speaker \0", 9);break;
551 case Treble: strncpy(name, "Treble \0", 9);break;
552 case Bass: strncpy(name, "Bass \0", 9);break;
553 }
554 return name;
555}
556
557
558void create_slider(x, y, device)
559int x;
560int y;
561enum Device device;
562{
563 /* Create a slider on the screen */
564
565 int left;
566 int right;
567 int i;
568
569 mvwprintw(main_win,y,x, "%s", d_name(device, name));
570
571 left = levels[device].left / (device < Speaker ? 2 : 1);
572 right = levels[device].right / (device < Speaker ? 2 : 1);
573
574 for (i = 0; i < 16; i++)
575 {
576 if (device != Speaker || i < 4)
577 mvwprintw(main_win,y,x+i+8, (i == left ? "*" : "-"));
578 if (device < Mic || device > Speaker)
579 mvwprintw(main_win,y+1,x+i+8, (i == right ? "*" : "-"));
580 }
581
582 if (device < Mic || device > Speaker)
583 {
584 mvwprintw(main_win,y,x+i+10, "left");
585 mvwprintw(main_win,y+1,x+i+10, "right");
586 }
587 wrefresh(main_win);
588}
589
590void show_inputs(x,y)
591int x;
592int y;
593{
594 /* Show the input settings */
595
596 int i;
597
598 mvwprintw(main_win,y,x, " Rec-In ");
599 mvwprintw(main_win,y+1,x," left right");
600 mvwprintw(main_win,y+2,x," l r l r");
601 for (i = Fm; i <= Line; i++)
602 {
603 mvwprintw(main_win,y+i+1,x, "%s %d %d %d %d",
604 d_name(i, (char *)name),
605 (inputs_left[i].left == ON ? 1 : 0),
606 (inputs_left[i].right == ON ? 1 : 0),
607 (inputs_right[i].left == ON ? 1 : 0),
608 (inputs_right[i].right == ON ? 1 : 0));
609 }
610 mvwprintw(main_win,y+i+1,x, "%s %d %d",
611 d_name(Mic, (char *)name),
612 (inputs_left[Mic].left == ON ? 1 : 0),
613 (inputs_right[Mic].left == ON ? 1 : 0));
614 wrefresh(main_win);
615}
616
617void show_outputs(x,y)
618int x;
619int y;
620{
621 /* Show the output settings */
622
623 int i;
624
625 mvwprintw(main_win,y,x, " Mix-Out ");
626 mvwprintw(main_win,y+1,x, " left right");
627 for (i = Cd; i <= Line; i++)
628 {
629 mvwprintw(main_win,y+i-1,x,"%s %d %d",
630 d_name(i, (char *)name),
631 (outputs[i].left == ON ? 1 : 0),
632 (outputs[i].right == ON ? 1 : 0));
633 }
634 mvwprintw(main_win,y+i-1,x,"%s %d",
635 d_name(Mic, (char *)name),
636 (outputs[Mic].left == ON ? 1 : 0));
637
638 wrefresh(main_win);
639}
640
641
642void setup_screen()
643{
644 int i;
645
646 wclear(main_win);
647 mvwprintw(main_win,0,23,"------- Mixer Controls -------");
648 wrefresh(main_win);
649
650 for(i = 0; i <= Speaker; i++)
651 create_slider(1, i*3+(i <= Mic ? 2 : 1), i);
652
653 create_slider(40, 2, Treble);
654 create_slider(40, 5, Bass);
655
656 show_inputs(41,8);
657 show_outputs(41,16);
658}
Note: See TracBrowser for help on using the repository browser.