File: | src/lib/libsndio/sio.c |
Warning: | line 398, column 3 The right operand of '*' is a garbage value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: sio.c,v 1.26 2021/11/01 14:43:24 ratchov Exp $ */ | |||
2 | /* | |||
3 | * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org> | |||
4 | * | |||
5 | * Permission to use, copy, modify, and distribute this software for any | |||
6 | * purpose with or without fee is hereby granted, provided that the above | |||
7 | * copyright notice and this permission notice appear in all copies. | |||
8 | * | |||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||
16 | */ | |||
17 | ||||
18 | #include <sys/types.h> | |||
19 | ||||
20 | #include <errno(*__errno()).h> | |||
21 | #include <fcntl.h> | |||
22 | #include <poll.h> | |||
23 | #include <stdio.h> | |||
24 | #include <stdlib.h> | |||
25 | #include <string.h> | |||
26 | #include <time.h> | |||
27 | #include <unistd.h> | |||
28 | ||||
29 | #include "debug.h" | |||
30 | #include "sio_priv.h" | |||
31 | ||||
32 | #define SIO_PAR_MAGIC0x83b905a4 0x83b905a4 | |||
33 | ||||
34 | void | |||
35 | sio_initpar(struct sio_par *par) | |||
36 | { | |||
37 | memset(par, 0xff, sizeof(struct sio_par)); | |||
38 | par->__magic = SIO_PAR_MAGIC0x83b905a4; | |||
39 | } | |||
40 | ||||
41 | struct sio_hdl * | |||
42 | sio_open(const char *str, unsigned int mode, int nbio) | |||
43 | { | |||
44 | static char devany[] = SIO_DEVANY"default"; | |||
45 | struct sio_hdl *hdl; | |||
46 | ||||
47 | #ifdef DEBUG1 | |||
48 | _sndio_debug_init(); | |||
49 | #endif | |||
50 | if ((mode & (SIO_PLAY1 | SIO_REC2)) == 0) | |||
51 | return NULL((void *)0); | |||
52 | if (str == NULL((void *)0)) /* backward compat */ | |||
53 | str = devany; | |||
54 | if (strcmp(str, devany) == 0 && !issetugid()) { | |||
55 | if ((mode & SIO_PLAY1) == 0) | |||
56 | str = getenv("AUDIORECDEVICE"); | |||
57 | if ((mode & SIO_REC2) == 0) | |||
58 | str = getenv("AUDIOPLAYDEVICE"); | |||
59 | if (mode == (SIO_PLAY1 | SIO_REC2) || str == NULL((void *)0)) | |||
60 | str = getenv("AUDIODEVICE"); | |||
61 | if (str == NULL((void *)0)) | |||
62 | str = devany; | |||
63 | } | |||
64 | if (strcmp(str, devany) == 0) { | |||
65 | hdl = _sio_aucat_open("snd/default", mode, nbio); | |||
66 | if (hdl != NULL((void *)0)) | |||
67 | return hdl; | |||
68 | return _sio_sun_open("rsnd/0", mode, nbio); | |||
69 | } | |||
70 | if (_sndio_parsetype(str, "snd")) | |||
71 | return _sio_aucat_open(str, mode, nbio); | |||
72 | if (_sndio_parsetype(str, "rsnd")) | |||
73 | return _sio_sun_open(str, mode, nbio); | |||
74 | DPRINTF("sio_open: %s: unknown device type\n", str)do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_open: %s: unknown device type\n" , str); } while(0); | |||
75 | return NULL((void *)0); | |||
76 | } | |||
77 | ||||
78 | void | |||
79 | _sio_create(struct sio_hdl *hdl, struct sio_ops *ops, | |||
80 | unsigned int mode, int nbio) | |||
81 | { | |||
82 | hdl->ops = ops; | |||
83 | hdl->mode = mode; | |||
84 | hdl->nbio = nbio; | |||
85 | hdl->started = 0; | |||
86 | hdl->eof = 0; | |||
87 | hdl->move_cb = NULL((void *)0); | |||
88 | hdl->vol_cb = NULL((void *)0); | |||
89 | } | |||
90 | ||||
91 | void | |||
92 | sio_close(struct sio_hdl *hdl) | |||
93 | { | |||
94 | hdl->ops->close(hdl); | |||
95 | } | |||
96 | ||||
97 | int | |||
98 | sio_start(struct sio_hdl *hdl) | |||
99 | { | |||
100 | #ifdef DEBUG1 | |||
101 | struct timespec ts; | |||
102 | #endif | |||
103 | ||||
104 | if (hdl->eof) { | |||
105 | DPRINTF("sio_start: eof\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_start: eof\n" ); } while(0); | |||
106 | return 0; | |||
107 | } | |||
108 | if (hdl->started) { | |||
109 | DPRINTF("sio_start: already started\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_start: already started\n" ); } while(0); | |||
110 | hdl->eof = 1; | |||
111 | return 0; | |||
112 | } | |||
113 | hdl->cpos = 0; | |||
114 | hdl->rused = hdl->wused = 0; | |||
115 | if (!sio_getpar(hdl, &hdl->par)) | |||
116 | return 0; | |||
117 | #ifdef DEBUG1 | |||
118 | hdl->pollcnt = 0; | |||
119 | clock_gettime(CLOCK_MONOTONIC3, &ts); | |||
120 | hdl->start_nsec = 1000000000LL * ts.tv_sec + ts.tv_nsec; | |||
121 | #endif | |||
122 | hdl->rdrop = hdl->wsil = 0; | |||
123 | if (!hdl->ops->start(hdl)) | |||
124 | return 0; | |||
125 | hdl->started = 1; | |||
126 | return 1; | |||
127 | } | |||
128 | ||||
129 | int | |||
130 | sio_stop(struct sio_hdl *hdl) | |||
131 | { | |||
132 | if (hdl->eof) { | |||
133 | DPRINTF("sio_stop: eof\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_stop: eof\n" ); } while(0); | |||
134 | return 0; | |||
135 | } | |||
136 | if (!hdl->started) { | |||
137 | DPRINTF("sio_stop: not started\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_stop: not started\n" ); } while(0); | |||
138 | hdl->eof = 1; | |||
139 | return 0; | |||
140 | } | |||
141 | if (!hdl->ops->stop(hdl)) | |||
142 | return 0; | |||
143 | #ifdef DEBUG1 | |||
144 | DPRINTFN(2, "libsndio: polls: %llu, samples = %llu\n",do { if (_sndio_debug >= (2)) fprintf((&__sF[2]), "libsndio: polls: %llu, samples = %llu\n" , hdl->pollcnt, hdl->cpos); } while(0) | |||
145 | hdl->pollcnt, hdl->cpos)do { if (_sndio_debug >= (2)) fprintf((&__sF[2]), "libsndio: polls: %llu, samples = %llu\n" , hdl->pollcnt, hdl->cpos); } while(0); | |||
146 | #endif | |||
147 | hdl->started = 0; | |||
148 | return 1; | |||
149 | } | |||
150 | ||||
151 | int | |||
152 | sio_setpar(struct sio_hdl *hdl, struct sio_par *par) | |||
153 | { | |||
154 | if (hdl->eof) { | |||
155 | DPRINTF("sio_setpar: eof\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_setpar: eof\n" ); } while(0); | |||
156 | return 0; | |||
157 | } | |||
158 | if (par->__magic != SIO_PAR_MAGIC0x83b905a4) { | |||
159 | DPRINTF("sio_setpar: uninitialized sio_par structure\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_setpar: uninitialized sio_par structure\n" ); } while(0); | |||
160 | hdl->eof = 1; | |||
161 | return 0; | |||
162 | } | |||
163 | if (hdl->started) { | |||
164 | DPRINTF("sio_setpar: already started\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_setpar: already started\n" ); } while(0); | |||
165 | hdl->eof = 1; | |||
166 | return 0; | |||
167 | } | |||
168 | if (par->bufsz != ~0U) { | |||
169 | DPRINTF("sio_setpar: setting bufsz is deprecated\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_setpar: setting bufsz is deprecated\n" ); } while(0); | |||
170 | par->appbufsz = par->bufsz; | |||
171 | par->bufsz = ~0U; | |||
172 | } | |||
173 | if (par->rate != ~0U && par->appbufsz == ~0U) | |||
174 | par->appbufsz = par->rate * 200 / 1000; | |||
175 | return hdl->ops->setpar(hdl, par); | |||
176 | } | |||
177 | ||||
178 | int | |||
179 | sio_getpar(struct sio_hdl *hdl, struct sio_par *par) | |||
180 | { | |||
181 | if (hdl->eof) { | |||
182 | DPRINTF("sio_getpar: eof\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_getpar: eof\n" ); } while(0); | |||
183 | return 0; | |||
184 | } | |||
185 | if (hdl->started) { | |||
186 | DPRINTF("sio_getpar: already started\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_getpar: already started\n" ); } while(0); | |||
187 | hdl->eof = 1; | |||
188 | return 0; | |||
189 | } | |||
190 | if (!hdl->ops->getpar(hdl, par)) { | |||
191 | par->__magic = 0; | |||
192 | return 0; | |||
193 | } | |||
194 | par->__magic = 0; | |||
195 | return 1; | |||
196 | } | |||
197 | ||||
198 | int | |||
199 | sio_getcap(struct sio_hdl *hdl, struct sio_cap *cap) | |||
200 | { | |||
201 | if (hdl->eof) { | |||
202 | DPRINTF("sio_getcap: eof\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_getcap: eof\n" ); } while(0); | |||
203 | return 0; | |||
204 | } | |||
205 | if (hdl->started) { | |||
206 | DPRINTF("sio_getcap: already started\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_getcap: already started\n" ); } while(0); | |||
207 | hdl->eof = 1; | |||
208 | return 0; | |||
209 | } | |||
210 | return hdl->ops->getcap(hdl, cap); | |||
211 | } | |||
212 | ||||
213 | static int | |||
214 | sio_psleep(struct sio_hdl *hdl, int event) | |||
215 | { | |||
216 | struct pollfd pfd[SIO_MAXNFDS16]; | |||
217 | int revents; | |||
218 | int nfds; | |||
219 | ||||
220 | nfds = sio_nfds(hdl); | |||
221 | if (nfds > SIO_MAXNFDS16) { | |||
222 | DPRINTF("sio_psleep: %d: too many descriptors\n", nfds)do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_psleep: %d: too many descriptors\n" , nfds); } while(0); | |||
223 | hdl->eof = 1; | |||
224 | return 0; | |||
225 | } | |||
226 | for (;;) { | |||
227 | nfds = sio_pollfd(hdl, pfd, event); | |||
228 | while (poll(pfd, nfds, -1) == -1) { | |||
229 | if (errno(*__errno()) == EINTR4) | |||
230 | continue; | |||
231 | DPERROR("sio_psleep: poll")do { if (_sndio_debug > 0) perror("sio_psleep: poll"); } while (0); | |||
232 | hdl->eof = 1; | |||
233 | return 0; | |||
234 | } | |||
235 | revents = sio_revents(hdl, pfd); | |||
236 | if (revents & POLLHUP0x0010) { | |||
237 | DPRINTF("sio_psleep: hang-up\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_psleep: hang-up\n" ); } while(0); | |||
238 | return 0; | |||
239 | } | |||
240 | if (revents & event) | |||
241 | break; | |||
242 | } | |||
243 | return 1; | |||
244 | } | |||
245 | ||||
246 | static int | |||
247 | sio_rdrop(struct sio_hdl *hdl) | |||
248 | { | |||
249 | #define DROP_NMAX0x1000 0x1000 | |||
250 | static char dummy[DROP_NMAX0x1000]; | |||
251 | ssize_t n, todo; | |||
252 | ||||
253 | while (hdl->rdrop > 0) { | |||
254 | todo = hdl->rdrop; | |||
255 | if (todo > DROP_NMAX0x1000) | |||
256 | todo = DROP_NMAX0x1000; | |||
257 | n = hdl->ops->read(hdl, dummy, todo); | |||
258 | if (n == 0) | |||
259 | return 0; | |||
260 | hdl->rdrop -= n; | |||
261 | DPRINTF("sio_rdrop: dropped %zu bytes\n", n)do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_rdrop: dropped %zu bytes\n" , n); } while(0); | |||
262 | } | |||
263 | return 1; | |||
264 | } | |||
265 | ||||
266 | static int | |||
267 | sio_wsil(struct sio_hdl *hdl) | |||
268 | { | |||
269 | #define ZERO_NMAX0x1000 0x1000 | |||
270 | static char zero[ZERO_NMAX0x1000]; | |||
271 | ssize_t n, todo; | |||
272 | ||||
273 | while (hdl->wsil > 0) { | |||
274 | todo = hdl->wsil; | |||
275 | if (todo > ZERO_NMAX0x1000) | |||
276 | todo = ZERO_NMAX0x1000; | |||
277 | n = hdl->ops->write(hdl, zero, todo); | |||
278 | if (n == 0) | |||
279 | return 0; | |||
280 | hdl->wsil -= n; | |||
281 | DPRINTF("sio_wsil: inserted %zu bytes\n", n)do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_wsil: inserted %zu bytes\n" , n); } while(0); | |||
282 | } | |||
283 | return 1; | |||
284 | } | |||
285 | ||||
286 | size_t | |||
287 | sio_read(struct sio_hdl *hdl, void *buf, size_t len) | |||
288 | { | |||
289 | unsigned int n; | |||
290 | char *data = buf; | |||
291 | size_t todo = len, maxread; | |||
292 | ||||
293 | if (hdl->eof) { | |||
294 | DPRINTF("sio_read: eof\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_read: eof\n" ); } while(0); | |||
295 | return 0; | |||
296 | } | |||
297 | if (!hdl->started || !(hdl->mode & SIO_REC2)) { | |||
298 | DPRINTF("sio_read: recording not started\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_read: recording not started\n" ); } while(0); | |||
299 | hdl->eof = 1; | |||
300 | return 0; | |||
301 | } | |||
302 | while (todo > 0) { | |||
303 | if (!sio_rdrop(hdl)) | |||
304 | return 0; | |||
305 | maxread = hdl->rused; | |||
306 | if (maxread > todo) | |||
307 | maxread = todo; | |||
308 | n = maxread > 0 ? hdl->ops->read(hdl, data, maxread) : 0; | |||
309 | if (n == 0) { | |||
310 | if (hdl->nbio || hdl->eof || todo < len) | |||
311 | break; | |||
312 | if (!sio_psleep(hdl, POLLIN0x0001)) | |||
313 | break; | |||
314 | continue; | |||
315 | } | |||
316 | data += n; | |||
317 | todo -= n; | |||
318 | hdl->rused -= n; | |||
319 | } | |||
320 | return len - todo; | |||
321 | } | |||
322 | ||||
323 | size_t | |||
324 | sio_write(struct sio_hdl *hdl, const void *buf, size_t len) | |||
325 | { | |||
326 | unsigned int n; | |||
327 | const unsigned char *data = buf; | |||
328 | size_t todo = len, maxwrite; | |||
329 | ||||
330 | if (hdl->eof) { | |||
| ||||
331 | DPRINTF("sio_write: eof\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_write: eof\n" ); } while(0); | |||
332 | return 0; | |||
333 | } | |||
334 | if (!hdl->started || !(hdl->mode & SIO_PLAY1)) { | |||
335 | DPRINTF("sio_write: playback not started\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_write: playback not started\n" ); } while(0); | |||
336 | hdl->eof = 1; | |||
337 | return 0; | |||
338 | } | |||
339 | while (todo > 0) { | |||
340 | if (!sio_wsil(hdl)) | |||
341 | return 0; | |||
342 | maxwrite = hdl->par.bufsz * hdl->par.pchan * hdl->par.bps - | |||
343 | hdl->wused; | |||
344 | if (maxwrite > todo) | |||
345 | maxwrite = todo; | |||
346 | n = maxwrite > 0 ? hdl->ops->write(hdl, data, maxwrite) : 0; | |||
347 | if (n
| |||
348 | if (hdl->nbio || hdl->eof
| |||
349 | break; | |||
350 | if (!sio_psleep(hdl, POLLOUT0x0004)) | |||
351 | break; | |||
352 | continue; | |||
353 | } | |||
354 | data += n; | |||
355 | todo -= n; | |||
356 | hdl->wused += n; | |||
357 | } | |||
358 | return len - todo; | |||
359 | } | |||
360 | ||||
361 | int | |||
362 | sio_nfds(struct sio_hdl *hdl) | |||
363 | { | |||
364 | return hdl->ops->nfds(hdl); | |||
365 | } | |||
366 | ||||
367 | int | |||
368 | sio_pollfd(struct sio_hdl *hdl, struct pollfd *pfd, int events) | |||
369 | { | |||
370 | if (hdl->eof) | |||
371 | return 0; | |||
372 | if (!hdl->started) | |||
373 | events = 0; | |||
374 | return hdl->ops->pollfd(hdl, pfd, events); | |||
375 | } | |||
376 | ||||
377 | int | |||
378 | sio_revents(struct sio_hdl *hdl, struct pollfd *pfd) | |||
379 | { | |||
380 | int revents; | |||
381 | #ifdef DEBUG1 | |||
382 | struct timespec ts0, ts1; | |||
383 | ||||
384 | if (_sndio_debug >= 4) | |||
385 | clock_gettime(CLOCK_MONOTONIC3, &ts0); | |||
386 | #endif | |||
387 | if (hdl->eof) | |||
388 | return POLLHUP0x0010; | |||
389 | #ifdef DEBUG1 | |||
390 | hdl->pollcnt++; | |||
391 | #endif | |||
392 | revents = hdl->ops->revents(hdl, pfd); | |||
393 | if (!hdl->started) | |||
394 | return revents & POLLHUP0x0010; | |||
395 | #ifdef DEBUG1 | |||
396 | if (_sndio_debug >= 4) { | |||
397 | clock_gettime(CLOCK_MONOTONIC3, &ts1); | |||
398 | DPRINTF("%09lld: sio_revents: revents = 0x%x, took %lldns\n",do { if (_sndio_debug > 0) fprintf((&__sF[2]), "%09lld: sio_revents: revents = 0x%x, took %lldns\n" , 1000000000LL * ts0.tv_sec + ts0.tv_nsec - hdl->start_nsec , revents, 1000000000LL * (ts1.tv_sec - ts0.tv_sec) + ts1.tv_nsec - ts0.tv_nsec); } while(0) | |||
| ||||
399 | 1000000000LL * ts0.tv_sec +do { if (_sndio_debug > 0) fprintf((&__sF[2]), "%09lld: sio_revents: revents = 0x%x, took %lldns\n" , 1000000000LL * ts0.tv_sec + ts0.tv_nsec - hdl->start_nsec , revents, 1000000000LL * (ts1.tv_sec - ts0.tv_sec) + ts1.tv_nsec - ts0.tv_nsec); } while(0) | |||
400 | ts0.tv_nsec - hdl->start_nsec,do { if (_sndio_debug > 0) fprintf((&__sF[2]), "%09lld: sio_revents: revents = 0x%x, took %lldns\n" , 1000000000LL * ts0.tv_sec + ts0.tv_nsec - hdl->start_nsec , revents, 1000000000LL * (ts1.tv_sec - ts0.tv_sec) + ts1.tv_nsec - ts0.tv_nsec); } while(0) | |||
401 | revents,do { if (_sndio_debug > 0) fprintf((&__sF[2]), "%09lld: sio_revents: revents = 0x%x, took %lldns\n" , 1000000000LL * ts0.tv_sec + ts0.tv_nsec - hdl->start_nsec , revents, 1000000000LL * (ts1.tv_sec - ts0.tv_sec) + ts1.tv_nsec - ts0.tv_nsec); } while(0) | |||
402 | 1000000000LL * (ts1.tv_sec - ts0.tv_sec) +do { if (_sndio_debug > 0) fprintf((&__sF[2]), "%09lld: sio_revents: revents = 0x%x, took %lldns\n" , 1000000000LL * ts0.tv_sec + ts0.tv_nsec - hdl->start_nsec , revents, 1000000000LL * (ts1.tv_sec - ts0.tv_sec) + ts1.tv_nsec - ts0.tv_nsec); } while(0) | |||
403 | ts1.tv_nsec - ts0.tv_nsec)do { if (_sndio_debug > 0) fprintf((&__sF[2]), "%09lld: sio_revents: revents = 0x%x, took %lldns\n" , 1000000000LL * ts0.tv_sec + ts0.tv_nsec - hdl->start_nsec , revents, 1000000000LL * (ts1.tv_sec - ts0.tv_sec) + ts1.tv_nsec - ts0.tv_nsec); } while(0); | |||
404 | } | |||
405 | #endif | |||
406 | if ((hdl->mode & SIO_PLAY1) && !sio_wsil(hdl)) | |||
407 | revents &= ~POLLOUT0x0004; | |||
408 | if ((hdl->mode & SIO_REC2) && !sio_rdrop(hdl)) | |||
409 | revents &= ~POLLIN0x0001; | |||
410 | return revents; | |||
411 | } | |||
412 | ||||
413 | int | |||
414 | sio_eof(struct sio_hdl *hdl) | |||
415 | { | |||
416 | return hdl->eof; | |||
417 | } | |||
418 | ||||
419 | void | |||
420 | sio_onmove(struct sio_hdl *hdl, void (*cb)(void *, int), void *addr) | |||
421 | { | |||
422 | if (hdl->started) { | |||
423 | DPRINTF("sio_onmove: already started\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_onmove: already started\n" ); } while(0); | |||
424 | hdl->eof = 1; | |||
425 | return; | |||
426 | } | |||
427 | hdl->move_cb = cb; | |||
428 | hdl->move_addr = addr; | |||
429 | } | |||
430 | ||||
431 | #ifdef DEBUG1 | |||
432 | void | |||
433 | _sio_printpos(struct sio_hdl *hdl) | |||
434 | { | |||
435 | struct timespec ts; | |||
436 | long long rpos, rdiff; | |||
437 | long long cpos, cdiff; | |||
438 | long long wpos, wdiff; | |||
439 | unsigned rbpf, wbpf, rround, wround; | |||
440 | ||||
441 | clock_gettime(CLOCK_MONOTONIC3, &ts); | |||
442 | rbpf = (hdl->mode & SIO_REC2) ? hdl->par.bps * hdl->par.rchan : 1; | |||
443 | wbpf = (hdl->mode & SIO_PLAY1) ? hdl->par.bps * hdl->par.pchan : 1; | |||
444 | rround = hdl->par.round * rbpf; | |||
445 | wround = hdl->par.round * wbpf; | |||
446 | ||||
447 | rpos = (hdl->mode & SIO_REC2) ? | |||
448 | hdl->cpos * rbpf - hdl->rused : 0; | |||
449 | wpos = (hdl->mode & SIO_PLAY1) ? | |||
450 | hdl->cpos * wbpf + hdl->wused : 0; | |||
451 | ||||
452 | cdiff = hdl->cpos % hdl->par.round; | |||
453 | cpos = hdl->cpos / hdl->par.round; | |||
454 | if (cdiff > hdl->par.round / 2) { | |||
455 | cpos++; | |||
456 | cdiff = cdiff - hdl->par.round; | |||
457 | } | |||
458 | rdiff = rpos % rround; | |||
459 | rpos = rpos / rround; | |||
460 | if (rdiff > rround / 2) { | |||
461 | rpos++; | |||
462 | rdiff = rdiff - rround; | |||
463 | } | |||
464 | wdiff = wpos % wround; | |||
465 | wpos = wpos / wround; | |||
466 | if (wdiff > wround / 2) { | |||
467 | wpos++; | |||
468 | wdiff = wdiff - wround; | |||
469 | } | |||
470 | DPRINTF("%011lld: "do { if (_sndio_debug > 0) fprintf((&__sF[2]), "%011lld: " "clk %+5lld%+5lld, wr %+5lld%+5lld rd: %+5lld%+5lld\n", 1000000000LL * ts.tv_sec + ts.tv_nsec - hdl->start_nsec, cpos, cdiff, wpos , wdiff, rpos, rdiff); } while(0) | |||
471 | "clk %+5lld%+5lld, wr %+5lld%+5lld rd: %+5lld%+5lld\n",do { if (_sndio_debug > 0) fprintf((&__sF[2]), "%011lld: " "clk %+5lld%+5lld, wr %+5lld%+5lld rd: %+5lld%+5lld\n", 1000000000LL * ts.tv_sec + ts.tv_nsec - hdl->start_nsec, cpos, cdiff, wpos , wdiff, rpos, rdiff); } while(0) | |||
472 | 1000000000LL * ts.tv_sec + ts.tv_nsec - hdl->start_nsec,do { if (_sndio_debug > 0) fprintf((&__sF[2]), "%011lld: " "clk %+5lld%+5lld, wr %+5lld%+5lld rd: %+5lld%+5lld\n", 1000000000LL * ts.tv_sec + ts.tv_nsec - hdl->start_nsec, cpos, cdiff, wpos , wdiff, rpos, rdiff); } while(0) | |||
473 | cpos, cdiff, wpos, wdiff, rpos, rdiff)do { if (_sndio_debug > 0) fprintf((&__sF[2]), "%011lld: " "clk %+5lld%+5lld, wr %+5lld%+5lld rd: %+5lld%+5lld\n", 1000000000LL * ts.tv_sec + ts.tv_nsec - hdl->start_nsec, cpos, cdiff, wpos , wdiff, rpos, rdiff); } while(0); | |||
474 | } | |||
475 | #endif | |||
476 | ||||
477 | void | |||
478 | _sio_onmove_cb(struct sio_hdl *hdl, int delta) | |||
479 | { | |||
480 | hdl->cpos += delta; | |||
481 | if (hdl->mode & SIO_REC2) | |||
482 | hdl->rused += delta * (hdl->par.bps * hdl->par.rchan); | |||
483 | if (hdl->mode & SIO_PLAY1) | |||
484 | hdl->wused -= delta * (hdl->par.bps * hdl->par.pchan); | |||
485 | #ifdef DEBUG1 | |||
486 | if (_sndio_debug >= 3) | |||
487 | _sio_printpos(hdl); | |||
488 | if ((hdl->mode & SIO_PLAY1) && hdl->wused < 0) { | |||
489 | DPRINTFN(1, "sndio: h/w failure: negative buffer usage\n")do { if (_sndio_debug >= (1)) fprintf((&__sF[2]), "sndio: h/w failure: negative buffer usage\n" ); } while(0); | |||
490 | hdl->eof = 1; | |||
491 | return; | |||
492 | } | |||
493 | #endif | |||
494 | if (hdl->move_cb) | |||
495 | hdl->move_cb(hdl->move_addr, delta); | |||
496 | } | |||
497 | ||||
498 | int | |||
499 | sio_setvol(struct sio_hdl *hdl, unsigned int ctl) | |||
500 | { | |||
501 | if (hdl->eof) | |||
502 | return 0; | |||
503 | if (!hdl->ops->setvol) | |||
504 | return 1; | |||
505 | if (!hdl->ops->setvol(hdl, ctl)) | |||
506 | return 0; | |||
507 | hdl->ops->getvol(hdl); | |||
508 | return 1; | |||
509 | } | |||
510 | ||||
511 | int | |||
512 | sio_onvol(struct sio_hdl *hdl, void (*cb)(void *, unsigned int), void *addr) | |||
513 | { | |||
514 | if (hdl->started) { | |||
515 | DPRINTF("sio_onvol: already started\n")do { if (_sndio_debug > 0) fprintf((&__sF[2]), "sio_onvol: already started\n" ); } while(0); | |||
516 | hdl->eof = 1; | |||
517 | return 0; | |||
518 | } | |||
519 | if (!hdl->ops->setvol) | |||
520 | return 0; | |||
521 | hdl->vol_cb = cb; | |||
522 | hdl->vol_addr = addr; | |||
523 | hdl->ops->getvol(hdl); | |||
524 | return 1; | |||
525 | } | |||
526 | ||||
527 | void | |||
528 | _sio_onvol_cb(struct sio_hdl *hdl, unsigned int ctl) | |||
529 | { | |||
530 | if (hdl->vol_cb) | |||
531 | hdl->vol_cb(hdl->vol_addr, ctl); | |||
532 | } |