Example #1
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;
}
Example #2
0
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;
}