xref: /openbsd/regress/lib/libsndio/play/play.c (revision 891d7ab6)
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