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; }
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; }
static void * sunaudio_mainloop(void *arg) { struct cubeb_stream *s = arg; int state; DPR("sunaudio_mainloop()\n"); s->state_cb(s, s->arg, CUBEB_STATE_STARTED); pthread_mutex_lock(&s->mutex); DPR("sunaudio_mainloop(), started\n"); for (;;) { if (!s->active) { DPR("sunaudio_mainloop() stopped\n"); state = CUBEB_STATE_STOPPED; break; } if (!s->using_oss) { audio_info_t info; ioctl(s->fd, AUDIO_GETINFO, &info); if (s->frm_played > info.play.samples + 3 * s->n_frm) { pthread_mutex_unlock(&s->mutex); struct timespec ts = {0, 10000}; // 10 ms nanosleep(&ts, NULL); pthread_mutex_lock(&s->mutex); continue; } } pthread_mutex_unlock(&s->mutex); unsigned int got = s->data_cb(s, s->arg, s->buf, s->n_frm); DPR("sunaudio_mainloop() ask %d got %d\n", s->n_frm, got); pthread_mutex_lock(&s->mutex); if (got < 0) { DPR("sunaudio_mainloop() cb err\n"); state = CUBEB_STATE_ERROR; break; } if (s->conv) { float_to_s16(s->buf, got * s->n_channles); } unsigned int avail = got * 2 * s->n_channles; // coverted to s16 unsigned int pos = 0; while (avail > 0 && s->active) { int written = write(s->fd, s->buf + pos, avail); if (written == -1) { if (errno != EINTR && errno != EWOULDBLOCK) { DPR("sunaudio_mainloop() write err\n"); state = CUBEB_STATE_ERROR; break; } pthread_mutex_unlock(&s->mutex); struct timespec ts = {0, 10000}; // 10 ms nanosleep(&ts, NULL); pthread_mutex_lock(&s->mutex); } else { pos += written; DPR("sunaudio_mainloop() write %d pos %d\n", written, pos); s->frm_played += written / 2 / s->n_channles; avail -= written; } } if ((got < s->n_frm)) { DPR("sunaudio_mainloop() drained\n"); state = CUBEB_STATE_DRAINED; break; } } pthread_mutex_unlock(&s->mutex); s->state_cb(s, s->arg, state); return NULL; }