/* Retrieves the just recorded buffer, if there is one. */ static int sndio_rec_read(void *buf) { struct pollfd pfd; nfds_t nfds; int ret, nbytes, offset = 0; /* make sure counters have been updated */ nfds = sio_pollfd(hdl, &pfd, POLLIN); poll(&pfd, nfds, 0); sio_revents(hdl, &pfd); if (!(sio_revents(hdl, &pfd) & POLLIN)) return 0; nbytes = sndio_rec_bufsize; while (nbytes) { ret = sio_read(hdl, buf + offset, nbytes); if (sio_eof(hdl)) return 0; offset += ret; nbytes -= ret; } return 1; }
static int sio_psleep(struct sio_hdl *hdl, int event) { struct pollfd pfd[SIO_MAXNFDS]; int revents; int nfds; nfds = sio_nfds(hdl); if (nfds > SIO_MAXNFDS) { DPRINTF("sio_psleep: %d: too many descriptors\n", nfds); hdl->eof = 1; return 0; } for (;;) { nfds = sio_pollfd(hdl, pfd, event); while (poll(pfd, nfds, -1) < 0) { if (errno == EINTR) continue; DPERROR("sio_psleep: poll"); hdl->eof = 1; return 0; } revents = sio_revents(hdl, pfd); if (revents & POLLHUP) { DPRINTF("sio_psleep: hang-up\n"); return 0; } if (revents & event) break; } return 1; }
/* * make libsndio call movecb() */ static void update(struct ao *ao) { struct priv *p = ao->priv; int n = sio_pollfd(p->hdl, p->pfd, POLLOUT); while (poll(p->pfd, n, 0) < 0 && errno == EINTR) {} sio_revents(p->hdl, p->pfd); }
void SNDDMA_Submit(void) { struct pollfd pfd; size_t count, todo, avail; int n; n = sio_pollfd(hdl, &pfd, POLLOUT); while (poll(&pfd, n, 0) < 0 && errno == EINTR) ; if (!(sio_revents(hdl, &pfd) & POLLOUT)) return; avail = dma_buffer_size; while (avail > 0) { todo = dma_buffer_size - dma_ptr; if (todo > avail) todo = avail; count = sio_write(hdl, dma_buffer + dma_ptr, todo); if (count == 0) break; dma_ptr += count; if (dma_ptr >= dma_buffer_size) dma_ptr -= dma_buffer_size; avail -= count; } }
/* write as many blocks as is currently possible */ static void sndio_update(int threaded) { struct pollfd pfd; nfds_t nfds; int i, nblocks, nbytes; /* make sure counters have been updated */ nfds = sio_pollfd(hdl, &pfd, POLLOUT); poll(&pfd, nfds, 0); if (!(sio_revents(hdl, &pfd) & POLLOUT)) return; nblocks = (sndio_play_appbufsz - (sndio_playpos - sndio_realpos)) / sndio_play_round; /* we got POLLOUT, so we can write something. if we don't * write anything, we could underrun. */ if (nblocks < 1) nblocks = 1; for (i = 0; i < nblocks; i++) { sio_write(hdl, sndio_play_bufdata, sndio_play_bufsize); sndio_playpos += sndio_play_round; if (sio_eof(hdl)) { /* print error message? */ return; } _mix_some_samples((uintptr_t) sndio_play_bufdata, 0, sndio_signed); } }
static void * read_thread(void *dp) { sndio_in_driver *d = dp; struct pollfd pfd; int size, ret, off, nfds; if (!sio_start(d->hdl)) { error_error("could not start sndio"); goto done; } while (d->read_trun) { nfds = sio_pollfd(d->hdl, &pfd, POLLIN); poll(&pfd, nfds, -1); if (sio_revents(d->hdl, &pfd) & POLLIN) { size = d->par.rchan * d->par.bps * d->bufsize; off = 0; while (size > 0) { ret = sio_read(d->hdl, d->sndbuf + off, size); off += ret; size -= ret; } sample_editor_sampled(d->sndbuf, d->bufsize, d->par.rate, d->mf); } } done: pthread_exit(NULL); return NULL; }
int dev_sio_revents(void *arg, struct pollfd *pfd) { struct dev *d = arg; int events; events = sio_revents(d->sio.hdl, pfd); #ifdef DEBUG d->sio.events = events; #endif return events; }
int sa_stream_get_position(sa_stream_t *s, sa_position_t position, int64_t *pos) { if (s == NULL) return SA_ERROR_NO_INIT; sio_pollfd(s->handle, &s->pfd, 0); poll(&s->pfd, 1, 0); sio_revents(s->handle, &s->pfd); *pos = s->position; return SA_SUCCESS; }
/* * how many bytes can be played without blocking */ static int get_space(struct ao *ao) { struct priv *p = ao->priv; int n; /* * call poll() and sio_revents(), so the * delay counter is updated */ n = sio_pollfd(p->hdl, p->pfd, POLLOUT); while (poll(p->pfd, n, 0) < 0 && errno == EINTR) ; /* nothing */ sio_revents(p->hdl, p->pfd); return (p->par.bufsz * p->par.pchan * p->par.bps - p->delay) / ao->sstride; }
static int swfdec_playback_stream_avail_update (Stream *stream) { struct pollfd pfd; int n, revents, used, avail; n = sio_pollfd (stream->hdl, &pfd, POLLOUT); while (poll (&pfd, n, 0) < 0 && errno == EINTR) ; revents = sio_revents (stream->hdl, &pfd); used = (stream->f_played < 0) ? stream->f_written : stream->f_written - stream->f_played; avail = stream->par.bufsz - used; return avail; }
static signed long BlockingGetStreamWriteAvailable(PaStream *stream) { PaSndioStream *s = (PaSndioStream *)stream; int n, events; n = sio_pollfd(s->hdl, s->pfds, POLLOUT); while (poll(s->pfds, n, 0) < 0) { if (errno == EINTR) continue; perror("poll"); abort(); } events = sio_revents(s->hdl, s->pfds); if (!(events & POLLOUT)) return 0; return s->par.bufsz - (s->bytesWritten - s->framesProcessed); }
static signed long BlockingGetStreamWriteAvailable(PaStream *stream) { PaSndioStream *s = (PaSndioStream *)stream; struct pollfd pfd; int n, events; n = sio_pollfd(s->hdl, &pfd, POLLOUT); while (poll(&pfd, n, 0) < 0) { if (errno == EINTR) continue; perror("poll"); abort(); } events = sio_revents(s->hdl, &pfd); if (!(events & POLLOUT)) return 0; return s->par.bufsz - (s->wpos - s->realpos); }
int siofile_revents(struct file *file, struct pollfd *pfd) { return sio_revents(((struct siofile *)file)->hdl, pfd); }
static void * sndio_mainloop(void *arg) { #define MAXFDS 8 struct pollfd pfds[MAXFDS]; cubeb_stream *s = arg; int n, eof = 0, prime, nfds, events, revents, state = CUBEB_STATE_STARTED; size_t pstart = 0, pend = 0, rstart = 0, rend = 0; long nfr; DPR("sndio_mainloop()\n"); s->state_cb(s, s->arg, CUBEB_STATE_STARTED); pthread_mutex_lock(&s->mtx); if (!sio_start(s->hdl)) { pthread_mutex_unlock(&s->mtx); return NULL; } DPR("sndio_mainloop(), started\n"); if (s->mode & SIO_PLAY) { pstart = pend = s->nfr * s->pbpf; prime = s->nblks; if (s->mode & SIO_REC) { memset(s->rbuf, 0, s->nfr * s->rbpf); rstart = rend = s->nfr * s->rbpf; } } else { prime = 0; rstart = 0; rend = s->nfr * s->rbpf; } for (;;) { if (!s->active) { DPR("sndio_mainloop() stopped\n"); state = CUBEB_STATE_STOPPED; break; } /* do we have a complete block? */ if ((!(s->mode & SIO_PLAY) || pstart == pend) && (!(s->mode & SIO_REC) || rstart == rend)) { if (eof) { DPR("sndio_mainloop() drained\n"); state = CUBEB_STATE_DRAINED; break; } if ((s->mode & SIO_REC) && s->conv) s16_to_float(s->rbuf, s->nfr * s->rchan); /* invoke call-back, it returns less that s->nfr if done */ pthread_mutex_unlock(&s->mtx); nfr = s->data_cb(s, s->arg, s->rbuf, s->pbuf, s->nfr); pthread_mutex_lock(&s->mtx); if (nfr < 0) { DPR("sndio_mainloop() cb err\n"); state = CUBEB_STATE_ERROR; break; } s->swpos += nfr; /* was this last call-back invocation (aka end-of-stream) ? */ if (nfr < s->nfr) { if (!(s->mode & SIO_PLAY) || nfr == 0) { state = CUBEB_STATE_DRAINED; break; } /* need to write (aka drain) the partial play block we got */ pend = nfr * s->pbpf; eof = 1; } if (prime > 0) prime--; if ((s->mode & SIO_PLAY) && s->conv) float_to_s16(s->pbuf, nfr * s->pchan); if (s->mode & SIO_REC) rstart = 0; if (s->mode & SIO_PLAY) pstart = 0; } events = 0; if ((s->mode & SIO_REC) && rstart < rend && prime == 0) events |= POLLIN; if ((s->mode & SIO_PLAY) && pstart < pend) events |= POLLOUT; nfds = sio_pollfd(s->hdl, pfds, events); if (nfds > 0) { pthread_mutex_unlock(&s->mtx); n = poll(pfds, nfds, -1); pthread_mutex_lock(&s->mtx); if (n < 0) continue; } revents = sio_revents(s->hdl, pfds); if (revents & POLLHUP) { state = CUBEB_STATE_ERROR; break; } if (revents & POLLOUT) { n = sio_write(s->hdl, s->pbuf + pstart, pend - pstart); if (n == 0 && sio_eof(s->hdl)) { DPR("sndio_mainloop() werr\n"); state = CUBEB_STATE_ERROR; break; } pstart += n; } if (revents & POLLIN) { n = sio_read(s->hdl, s->rbuf + rstart, rend - rstart); if (n == 0 && sio_eof(s->hdl)) { DPR("sndio_mainloop() rerr\n"); state = CUBEB_STATE_ERROR; break; } rstart += n; } /* skip rec block, if not recording (yet) */ if (prime > 0 && (s->mode & SIO_REC)) rstart = rend; } sio_stop(s->hdl); s->hwpos = s->swpos; pthread_mutex_unlock(&s->mtx); s->state_cb(s, s->arg, state); return NULL; }
int main(int argc, char **argv) { int ch; int tty; struct sio_hdl *hdl; struct termios tio; struct pollfd pfd[2]; char cmd; ssize_t n, len; /* * defaults parameters */ sio_initpar(&par); par.sig = 1; par.bits = 16; par.pchan = 2; par.rate = 44100; if (isatty(STDIN_FILENO)) { fprintf(stderr, "stdin can't be a tty\n"); exit(1); } tty = open("/dev/tty", O_RDWR); if (tty < 0) { perror("/dev/tty"); exit(1); } if (tcgetattr(tty, &tio) < 0) { perror("tcsetattr"); exit(1); } tio.c_lflag &= ~ICANON; tio.c_lflag &= ~ECHO; tio.c_cc[VMIN] = 1; tio.c_cc[VTIME] = 0; if (tcsetattr(tty, TCSAFLUSH, &tio) < 0) { perror("tcsetattr"); exit(1); } while ((ch = getopt(argc, argv, "r:c:e:b:x:")) != -1) { switch(ch) { case 'r': if (sscanf(optarg, "%u", &par.rate) != 1) { fprintf(stderr, "%s: bad rate\n", optarg); exit(1); } break; case 'c': if (sscanf(optarg, "%u", &par.pchan) != 1) { fprintf(stderr, "%s: bad channels\n", optarg); exit(1); } break; case 'e': if (!sio_strtoenc(&par, optarg)) { fprintf(stderr, "%s: bad encoding\n", optarg); exit(1); } break; default: usage(); exit(1); break; } } hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0); if (hdl == NULL) { fprintf(stderr, "sio_open() failed\n"); exit(1); } if (!sio_setpar(hdl, &par)) { fprintf(stderr, "sio_setpar() failed\n"); exit(1); } if (!sio_onvol(hdl, onvol, NULL)) fprintf(stderr, "warning: no volume knob on this device\n"); fprintf(stderr, "use ``+'' and ``-'' to adjust the volume\n"); if (!sio_start(hdl)) { fprintf(stderr, "sio_start() failed\n"); exit(1); } for (;;) { pfd[0].fd = tty; pfd[0].events = POLLIN; sio_pollfd(hdl, &pfd[1], POLLOUT); if (poll(pfd, 2, -1) < 0) { perror("poll"); exit(1); } if (pfd[0].revents & POLLIN) { if (read(tty, &cmd, 1) < 0) { perror("read(tty)"); exit(1); } switch (cmd) { case '+': if (vol < SIO_MAXVOL) { vol++; sio_setvol(hdl, vol); } break; case '-': if (vol > 0) { vol--; sio_setvol(hdl, vol); } break; } } if (sio_revents(hdl, &pfd[1]) & POLLOUT) { len = read(STDIN_FILENO, buf, BUFSZ); if (len < 0) { perror("stdin"); exit(1); } if (len == 0) break; n = sio_write(hdl, buf, len); if (n == 0) { fprintf(stderr, "sio_write: failed\n"); exit(1); } } } sio_close(hdl); return 0; }
static void * sndio_mainloop(void *arg) { #define MAXFDS 8 struct pollfd pfds[MAXFDS]; cubeb_stream *s = arg; int n, nfds, revents, state = CUBEB_STATE_STARTED; size_t start = 0, end = 0; long nfr; DPR("sndio_mainloop()\n"); s->state_cb(s, s->arg, CUBEB_STATE_STARTED); pthread_mutex_lock(&s->mtx); if (!sio_start(s->hdl)) { pthread_mutex_unlock(&s->mtx); return NULL; } DPR("sndio_mainloop(), started\n"); start = end = s->nfr; for (;;) { if (!s->active) { DPR("sndio_mainloop() stopped\n"); state = CUBEB_STATE_STOPPED; break; } if (start == end) { if (end < s->nfr) { DPR("sndio_mainloop() drained\n"); state = CUBEB_STATE_DRAINED; break; } pthread_mutex_unlock(&s->mtx); nfr = s->data_cb(s, s->arg, NULL, s->buf, s->nfr); pthread_mutex_lock(&s->mtx); if (nfr < 0) { DPR("sndio_mainloop() cb err\n"); state = CUBEB_STATE_ERROR; break; } if (s->conv) float_to_s16(s->buf, nfr * s->pchan); start = 0; end = nfr * s->bpf; } if (end == 0) continue; nfds = sio_pollfd(s->hdl, pfds, POLLOUT); if (nfds > 0) { pthread_mutex_unlock(&s->mtx); n = poll(pfds, nfds, -1); pthread_mutex_lock(&s->mtx); if (n < 0) continue; } revents = sio_revents(s->hdl, pfds); if (revents & POLLHUP) break; if (revents & POLLOUT) { n = sio_write(s->hdl, s->buf + start, end - start); if (n == 0) { DPR("sndio_mainloop() werr\n"); state = CUBEB_STATE_ERROR; break; } s->wrpos += n; start += n; } } sio_stop(s->hdl); s->rdpos = s->wrpos; pthread_mutex_unlock(&s->mtx); s->state_cb(s, s->arg, state); return NULL; }