-/*
- * Copyright (C) 2005 Andre Noll <maan@tuebingen.mpg.de>
- *
- * Licensed under the GPL v2. For licencing details see COPYING.
- */
+/* Copyright (C) 2005 Andre Noll <maan@tuebingen.mpg.de>, see file COPYING. */
/** \file alsa_write.c paraslash's alsa output plugin */
/* time until buffer underrun occurs, in milliseconds */
unsigned buffer_time;
struct timeval drain_barrier;
- /* File descriptor for select(). */
+ /* File descriptor to monitor for reading. */
int poll_fd;
};
case SF_S16_BE: return SND_PCM_FORMAT_S16_BE;
case SF_U16_LE: return SND_PCM_FORMAT_U16_LE;
case SF_U16_BE: return SND_PCM_FORMAT_U16_BE;
+ case SF_FLOAT_LE: return SND_PCM_FORMAT_FLOAT_LE;
+ case SF_FLOAT_BE: return SND_PCM_FORMAT_FLOAT_BE;
default: return SND_PCM_FORMAT_S16_LE;
}
}
return ret;
}
-static void alsa_write_pre_select(struct sched *s, void *context)
+static void alsa_write_pre_monitor(struct sched *s, void *context)
{
struct pollfd pfd;
struct writer_node *wn = context;
return;
}
pad->poll_fd = pfd.fd;
- para_fd_set(pfd.fd, &s->rfds, &s->max_fileno);
+ sched_monitor_readfd(pfd.fd, s);
}
static void alsa_close(struct writer_node *wn)
if (!pad)
return;
+ if (!pad->handle)
+ goto free_pad;
/*
* It's OK to have a blocking operation here because we already made
* sure that the PCM output buffer is (nearly) empty.
snd_pcm_drain(pad->handle);
snd_pcm_close(pad->handle);
snd_config_update_free_global();
+free_pad:
free(pad);
}
-static int alsa_write_post_select(__a_unused struct sched *s, void *context)
+static int alsa_write_post_monitor(__a_unused struct sched *s, void *context)
{
struct writer_node *wn = context;
struct private_alsa_write_data *pad = wn->private_data;
goto err;
again:
ret = btr_node_status(btrn, wn->min_iqs, BTR_NT_LEAF);
+ if (ret < 0)
+ goto err;
if (ret == 0)
return 0;
btr_merge(btrn, wn->min_iqs);
bytes = btr_next_buffer(btrn, &data);
if (ret < 0 || bytes < wn->min_iqs) { /* eof */
assert(btr_no_parent(btrn));
- ret = -E_WRITE_COMMON_EOF;
+ ret = -E_EOF;
if (!pad)
goto err;
/* wait until pending frames are played */
if (bytes == 0) /* no data available */
return 0;
- pad = wn->private_data = para_calloc(sizeof(*pad));
- get_btr_sample_rate(btrn, &val);
+ pad = wn->private_data = zalloc(sizeof(*pad));
+ ret = get_btr_sample_rate(btrn, &val);
+ if (ret < 0)
+ goto err;
pad->sample_rate = val;
- get_btr_channels(btrn, &val);
+ ret = get_btr_channels(btrn, &val);
+ if (ret < 0)
+ goto err;
pad->channels = val;
- get_btr_sample_format(btrn, &val);
+ ret = get_btr_sample_format(btrn, &val);
+ if (ret < 0)
+ goto err;
pad->sample_format = get_alsa_pcm_format(val);
-
PARA_INFO_LOG("%u channel(s), %uHz\n", pad->channels,
pad->sample_rate);
ret = alsa_init(wn);
- if (ret < 0) {
- free(wn->private_data);
- wn->private_data = NULL;
+ if (ret < 0)
goto err;
- }
wn->min_iqs = pad->bytes_per_frame;
goto again;
}
frames = snd_pcm_writei(pad->handle, data, frames);
if (frames == 0 || frames == -EAGAIN) {
char buf[100];
- if (pad->poll_fd >= 0 && FD_ISSET(pad->poll_fd, &s->rfds))
+ if (pad->poll_fd >= 0 && sched_read_ok(pad->poll_fd, s))
if (read(pad->poll_fd, buf, 100))
do_nothing;
return 0;
goto again;
}
if (frames == -EPIPE) {
- PARA_WARNING_LOG("underrun (tried to write %zu bytes)\n", bytes);
+ snd_pcm_status_t *status;
+ snd_pcm_status_malloc(&status);
+ if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN)
+ PARA_WARNING_LOG("underrun\n");
+ snd_pcm_status_free(status);
snd_pcm_prepare(pad->handle);
return 0;
}
struct writer lsg_write_cmd_com_alsa_user_data = {
- .pre_select = alsa_write_pre_select,
- .post_select = alsa_write_post_select,
+ .pre_monitor = alsa_write_pre_monitor,
+ .post_monitor = alsa_write_post_monitor,
.close = alsa_close,
};