xref: /openbsd/regress/lib/libsndio/vol/vol.c (revision 09467b48)
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
22 usage(void) {
23 	fprintf(stderr, "usage: vol [-r rate] [-c nchan] [-e enc]\n");
24 }
25 
26 void
27 onvol(void *addr, unsigned val)
28 {
29 	vol = val;
30 	fprintf(stderr, "volume set to %u\n", vol);
31 }
32 
33 int
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