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