int alsa_src_alloc(struct ausrc_st **stp, const struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg) { struct ausrc_st *st; snd_pcm_format_t pcmfmt; int num_frames; int err; (void)ctx; (void)errh; if (!stp || !as || !prm || !rh) return EINVAL; if (!str_isset(device)) device = alsa_dev; st = mem_zalloc(sizeof(*st), ausrc_destructor); if (!st) return ENOMEM; err = str_dup(&st->device, device); if (err) goto out; st->prm = *prm; st->as = as; st->rh = rh; st->arg = arg; st->aufmt = alsa_sample_format; st->sampc = prm->srate * prm->ch * prm->ptime / 1000; num_frames = st->prm.srate * st->prm.ptime / 1000; st->sampv = mem_alloc(2 * st->sampc, NULL); if (!st->sampv) { err = ENOMEM; goto out; } if (st->aufmt != AUFMT_S16LE) { size_t sz = aufmt_sample_size(st->aufmt) * st->sampc; st->xsampv = mem_alloc(sz, NULL); if (!st->xsampv) { err = ENOMEM; goto out; } } err = snd_pcm_open(&st->read, st->device, SND_PCM_STREAM_CAPTURE, 0); if (err < 0) { warning("alsa: could not open ausrc device '%s' (%s)\n", st->device, snd_strerror(err)); goto out; } pcmfmt = aufmt_to_alsaformat(st->aufmt); if (pcmfmt == SND_PCM_FORMAT_UNKNOWN) { warning("alsa: unknown sample format '%s'\n", aufmt_name(st->aufmt)); err = EINVAL; goto out; } err = alsa_reset(st->read, st->prm.srate, st->prm.ch, num_frames, pcmfmt); if (err) { warning("alsa: could not reset source '%s' (%s)\n", st->device, snd_strerror(err)); goto out; } st->run = true; err = pthread_create(&st->thread, NULL, read_thread, st); if (err) { st->run = false; goto out; } debug("alsa: recording started (%s)\n", st->device); out: if (err) mem_deref(st); else *stp = st; return err; }
int alsa_src_alloc(struct ausrc_st **stp, struct ausrc *as, struct media_ctx **ctx, struct ausrc_prm *prm, const char *device, ausrc_read_h *rh, ausrc_error_h *errh, void *arg) { struct ausrc_st *st; int err; (void)ctx; (void)errh; if (!str_isset(device)) device = alsa_dev; st = mem_zalloc(sizeof(*st), ausrc_destructor); if (!st) return ENOMEM; st->as = mem_ref(as); st->rh = rh; st->arg = arg; st->sample_size = prm->ch * (prm->fmt == AUFMT_S16LE ? 2 : 1); st->frame_size = prm->frame_size; err = snd_pcm_open(&st->read, device, SND_PCM_STREAM_CAPTURE, 0); if (err < 0) { DEBUG_WARNING("read open: %s %s\n", device, snd_strerror(err)); goto out; } st->mbr = mbuf_alloc(st->sample_size * st->frame_size); if (!st->mbr) { err = ENOMEM; goto out; } err = alsa_reset(st->read, prm->srate, prm->ch, prm->fmt, prm->frame_size); if (err) goto out; /* Start */ err = snd_pcm_start(st->read); if (err) { DEBUG_WARNING("snd_pcm_start on read: %s\n", snd_strerror(err)); goto out; } st->run = true; err = pthread_create(&st->thread, NULL, read_thread, st); if (err) { st->run = false; goto out; } out: if (err) mem_deref(st); else *stp = st; return err; }
int alsa_play_alloc(struct auplay_st **stp, const struct auplay *ap, struct auplay_prm *prm, const char *device, auplay_write_h *wh, void *arg) { struct auplay_st *st; snd_pcm_format_t pcmfmt; int num_frames; int err; if (!stp || !ap || !prm || !wh) return EINVAL; if (!str_isset(device)) device = alsa_dev; st = mem_zalloc(sizeof(*st), auplay_destructor); if (!st) return ENOMEM; err = str_dup(&st->device, device); if (err) goto out; st->prm = *prm; st->ap = ap; st->wh = wh; st->arg = arg; st->aufmt = alsa_sample_format; st->sampc = prm->srate * prm->ch * prm->ptime / 1000; num_frames = st->prm.srate * st->prm.ptime / 1000; st->sampv = mem_alloc(2 * st->sampc, NULL); if (!st->sampv) { err = ENOMEM; goto out; } if (st->aufmt != AUFMT_S16LE) { size_t sz = aufmt_sample_size(st->aufmt) * st->sampc; st->xsampv = mem_alloc(sz, NULL); if (!st->xsampv) { err = ENOMEM; goto out; } } err = snd_pcm_open(&st->write, st->device, SND_PCM_STREAM_PLAYBACK, 0); if (err < 0) { warning("alsa: could not open auplay device '%s' (%s)\n", st->device, snd_strerror(err)); goto out; } pcmfmt = aufmt_to_alsaformat(st->aufmt); if (pcmfmt == SND_PCM_FORMAT_UNKNOWN) { warning("alsa: unknown sample format '%s'\n", aufmt_name(st->aufmt)); err = EINVAL; goto out; } err = alsa_reset(st->write, st->prm.srate, st->prm.ch, num_frames, pcmfmt); if (err) { warning("alsa: could not reset player '%s' (%s)\n", st->device, snd_strerror(err)); goto out; } st->run = true; err = pthread_create(&st->thread, NULL, write_thread, st); if (err) { st->run = false; goto out; } debug("alsa: playback started (%s)\n", st->device); out: if (err) mem_deref(st); else *stp = st; return err; }