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