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 <sndio.h> 9 #include "tools.h" 10 11 #define BUFSZ 0x100 12 unsigned char buf[BUFSZ]; 13 struct sio_par par; 14 char *xstr[] = SIO_XSTRINGS; 15 16 long long realpos = 0, playpos = 0; 17 18 void 19 cb(void *addr, int delta) 20 { 21 int bytes = delta * (int)(par.bps * par.pchan); 22 23 realpos += bytes; 24 25 fprintf(stderr, 26 "cb: bytes = %+7d, latency = %+7lld, " 27 "realpos = %+7lld, bufused = %+7lld\n", 28 bytes, playpos - realpos, 29 realpos, (realpos < 0) ? playpos : playpos - realpos); 30 } 31 32 void 33 usage(void) { 34 fprintf(stderr, "usage: play [-r rate] [-c nchan] [-e enc]\n"); 35 } 36 37 int 38 main(int argc, char **argv) { 39 int ch; 40 struct sio_hdl *hdl; 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 while ((ch = getopt(argc, argv, "r:c:e:b:x:")) != -1) { 53 switch(ch) { 54 case 'r': 55 if (sscanf(optarg, "%u", &par.rate) != 1) { 56 fprintf(stderr, "%s: bad rate\n", optarg); 57 exit(1); 58 } 59 break; 60 case 'c': 61 if (sscanf(optarg, "%u", &par.pchan) != 1) { 62 fprintf(stderr, "%s: bad channels\n", optarg); 63 exit(1); 64 } 65 break; 66 case 'e': 67 if (!sio_strtoenc(&par, optarg)) { 68 fprintf(stderr, "%s: bad encoding\n", optarg); 69 exit(1); 70 } 71 break; 72 case 'b': 73 if (sscanf(optarg, "%u", &par.appbufsz) != 1) { 74 fprintf(stderr, "%s: bad buf size\n", optarg); 75 exit(1); 76 } 77 break; 78 case 'x': 79 for (par.xrun = 0;; par.xrun++) { 80 if (par.xrun == sizeof(xstr) / sizeof(char *)) { 81 fprintf(stderr, 82 "%s: bad xrun mode\n", optarg); 83 exit(1); 84 } 85 if (strcmp(xstr[par.xrun], optarg) == 0) 86 break; 87 } 88 break; 89 default: 90 usage(); 91 exit(1); 92 break; 93 } 94 } 95 96 hdl = sio_open(NULL, SIO_PLAY, 0); 97 if (hdl == NULL) { 98 fprintf(stderr, "sio_open() failed\n"); 99 exit(1); 100 } 101 sio_onmove(hdl, cb, NULL); 102 if (!sio_setpar(hdl, &par)) { 103 fprintf(stderr, "sio_setpar() failed\n"); 104 exit(1); 105 } 106 if (!sio_getpar(hdl, &par)) { 107 fprintf(stderr, "sio_getpar() failed\n"); 108 exit(1); 109 } 110 if (!sio_start(hdl)) { 111 fprintf(stderr, "sio_start() failed\n"); 112 exit(1); 113 } 114 fprintf(stderr, "using %u bytes per buffer, rounding to %u\n", 115 par.bufsz * par.bps * par.pchan, 116 par.round * par.bps * par.pchan); 117 for (;;) { 118 len = read(STDIN_FILENO, buf, BUFSZ); 119 if (len < 0) { 120 perror("stdin"); 121 exit(1); 122 } 123 if (len == 0) 124 break; 125 n = sio_write(hdl, buf, len); 126 if (n == 0) { 127 fprintf(stderr, "sio_write: failed\n"); 128 exit(1); 129 } 130 playpos += n; 131 } 132 sio_close(hdl); 133 return 0; 134 } 135