1 #include <errno.h>
2 #include <fcntl.h>
3 #include <poll.h>
4 #include <stdio.h>
5 #include <string.h>
6 #include <stdlib.h>
7 #include <unistd.h>
8 #include <termios.h>
9 #include <sndio.h>
10 #include "tools.h"
11
12 #define BUFSZ 0x100
13
14 void usage(void);
15 void onvol(void *, unsigned);
16
17 unsigned char buf[BUFSZ];
18 struct sio_par par;
19 unsigned vol = 0xdeadbeef;
20
21 void
usage(void)22 usage(void) {
23 fprintf(stderr, "usage: vol [-r rate] [-c nchan] [-e enc]\n");
24 }
25
26 void
onvol(void * addr,unsigned val)27 onvol(void *addr, unsigned val)
28 {
29 vol = val;
30 fprintf(stderr, "volume set to %u\n", vol);
31 }
32
33 int
main(int argc,char ** argv)34 main(int argc, char **argv) {
35 int ch;
36 int tty;
37 struct sio_hdl *hdl;
38 struct termios tio;
39 struct pollfd pfd[2];
40 char cmd;
41 ssize_t n, len;
42
43 /*
44 * defaults parameters
45 */
46 sio_initpar(&par);
47 par.sig = 1;
48 par.bits = 16;
49 par.pchan = 2;
50 par.rate = 44100;
51
52 if (isatty(STDIN_FILENO)) {
53 fprintf(stderr, "stdin can't be a tty\n");
54 exit(1);
55 }
56 tty = open("/dev/tty", O_RDWR);
57 if (tty < 0) {
58 perror("/dev/tty");
59 exit(1);
60 }
61 if (tcgetattr(tty, &tio) < 0) {
62 perror("tcsetattr");
63 exit(1);
64 }
65 tio.c_lflag &= ~ICANON;
66 tio.c_lflag &= ~ECHO;
67 tio.c_cc[VMIN] = 1;
68 tio.c_cc[VTIME] = 0;
69 if (tcsetattr(tty, TCSAFLUSH, &tio) < 0) {
70 perror("tcsetattr");
71 exit(1);
72 }
73
74 while ((ch = getopt(argc, argv, "r:c:e:b:x:")) != -1) {
75 switch(ch) {
76 case 'r':
77 if (sscanf(optarg, "%u", &par.rate) != 1) {
78 fprintf(stderr, "%s: bad rate\n", optarg);
79 exit(1);
80 }
81 break;
82 case 'c':
83 if (sscanf(optarg, "%u", &par.pchan) != 1) {
84 fprintf(stderr, "%s: bad channels\n", optarg);
85 exit(1);
86 }
87 break;
88 case 'e':
89 if (!sio_strtoenc(&par, optarg)) {
90 fprintf(stderr, "%s: bad encoding\n", optarg);
91 exit(1);
92 }
93 break;
94 default:
95 usage();
96 exit(1);
97 break;
98 }
99 }
100
101 hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0);
102 if (hdl == NULL) {
103 fprintf(stderr, "sio_open() failed\n");
104 exit(1);
105 }
106 if (!sio_setpar(hdl, &par)) {
107 fprintf(stderr, "sio_setpar() failed\n");
108 exit(1);
109 }
110 if (!sio_onvol(hdl, onvol, NULL))
111 fprintf(stderr, "warning: no volume knob on this device\n");
112 fprintf(stderr, "use ``+'' and ``-'' to adjust the volume\n");
113 if (!sio_start(hdl)) {
114 fprintf(stderr, "sio_start() failed\n");
115 exit(1);
116 }
117 for (;;) {
118 pfd[0].fd = tty;
119 pfd[0].events = POLLIN;
120 sio_pollfd(hdl, &pfd[1], POLLOUT);
121 if (poll(pfd, 2, -1) < 0) {
122 perror("poll");
123 exit(1);
124 }
125 if (pfd[0].revents & POLLIN) {
126 if (read(tty, &cmd, 1) < 0) {
127 perror("read(tty)");
128 exit(1);
129 }
130 switch (cmd) {
131 case '+':
132 if (vol < SIO_MAXVOL) {
133 vol++;
134 sio_setvol(hdl, vol);
135 }
136 break;
137 case '-':
138 if (vol > 0) {
139 vol--;
140 sio_setvol(hdl, vol);
141 }
142 break;
143 }
144 }
145 if (sio_revents(hdl, &pfd[1]) & POLLOUT) {
146 len = read(STDIN_FILENO, buf, BUFSZ);
147 if (len < 0) {
148 perror("stdin");
149 exit(1);
150 }
151 if (len == 0)
152 break;
153 n = sio_write(hdl, buf, len);
154 if (n == 0) {
155 fprintf(stderr, "sio_write: failed\n");
156 exit(1);
157 }
158 }
159 }
160 sio_close(hdl);
161 return 0;
162 }
163