Esempio n. 1
0
/* Core streaming function for this module
 * This is what actually produces the data which gets streamed.
 *
 * returns:  >0  Number of bytes read
 *            0  Non-fatal error.
 *           <0  Fatal error.
 */
static int sndio_read(void *self, ref_buffer *rb)
{
    int result;
    im_sndio_state *s = self;

    rb->buf = malloc(BUFSIZE * s->par.bps * s->par.rchan);
    if(!rb->buf)
        return -1;
    result = sio_read(s->hdl, rb->buf, BUFSIZE * s->par.bps * s->par.rchan);

    rb->len = result;
    rb->aux_data = s->par.rate * s->par.rchan * s->par.bps;

    if(s->newtrack)
    {
        rb->critical = 1;
        s->newtrack = 0;
    }

    if(result == 0)
    {
        if(sio_eof(s->hdl))
        {
            LOG_ERROR0("Error reading from audio device");
            free(rb->buf);
            return -1;
        }
    }

    return rb->len;
}
Esempio n. 2
0
/* 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;
}
Esempio n. 3
0
/* 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);
	}
}
Esempio n. 4
0
static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt)
{
    SndioData *s = s1->priv_data;
    int64_t bdelay, cur_time;
    int ret;

    if ((ret = av_new_packet(pkt, s->buffer_size)) < 0)
        return ret;

    ret = sio_read(s->hdl, pkt->data, pkt->size);
    if (ret == 0 || sio_eof(s->hdl)) {
        av_free_packet(pkt);
        return AVERROR_EOF;
    }

    pkt->size   = ret;
    s->softpos += ret;

    /* compute pts of the start of the packet */
    cur_time = av_gettime();

    bdelay = ret + s->hwpos - s->softpos;

    /* convert to pts */
    pkt->pts = cur_time - ((bdelay * 1000000) /
        (s->bps * s->channels * s->sample_rate));

    return 0;
}
Esempio n. 5
0
unsigned int
siofile_read(struct file *file, unsigned char *data, unsigned int count)
{
	struct siofile *f = (struct siofile *)file;
	unsigned int n;

#ifdef DEBUG
	if (f->rtickets == 0) {
		file_dbg(&f->file);
		dbg_puts(": called with no read tickets\n");
	}
#endif
	if (count > f->rtickets)
		count = f->rtickets;
	n = f->started ? sio_read(f->hdl, data, count) : 0;
	if (n == 0) {
		f->file.state &= ~FILE_ROK;
		if (sio_eof(f->hdl)) {
#ifdef DEBUG
			dbg_puts(f->file.name);
			dbg_puts(": failed to read from device\n");
#endif
			file_eof(&f->file);
		} else {
#ifdef DEBUG
			if (debug_level >= 4) {
				file_dbg(&f->file);
				dbg_puts(": reading blocked\n");
			}
#endif
		}
		return 0;
	} else {
		f->rtickets -= n;
		if (f->rtickets == 0) {
			f->file.state &= ~FILE_ROK;
#ifdef DEBUG
			if (debug_level >= 4) {
				file_dbg(&f->file);
				dbg_puts(": read tickets exhausted\n");
			}
#endif
		}
	}
	return n;

}
Esempio n. 6
0
void
siofile_stop(struct file *file)
{
	struct siofile *f = (struct siofile *)file;

	f->started = 0;
	f->onmove = NULL;
	if (!sio_eof(f->hdl) && !sio_stop(f->hdl)) {
#ifdef DEBUG
		dbg_puts(f->file.name);
		dbg_puts(": failed to stop device\n");
#endif
		file_close(file);
		return;
	}
#ifdef DEBUG
	if (debug_level >= 3) {
		file_dbg(&f->file);
		dbg_puts(": stopped\n");
	}
#endif
}
Esempio n. 7
0
File: siofile.c Progetto: t6/sndio
void
dev_sio_stop(struct dev *d)
{
	if (!sio_eof(d->sio.hdl) && !sio_stop(d->sio.hdl)) {
		if (log_level >= 1) {
			dev_log(d);
			log_puts(": failed to stop device\n");
		}
		return;
	}
#ifdef DEBUG
	if (log_level >= 3) {
		dev_log(d);
		log_puts(": stopped, load avg = ");
		log_puti(d->sio.sum_utime / 1000);
		log_puts(" / ");
		log_puti(d->sio.sum_wtime / 1000);
		log_puts("\n");
	}
#endif
	timo_del(&d->sio.watchdog);
}
Esempio n. 8
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;
}