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