aboutsummaryrefslogtreecommitdiff
path: root/src/output
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2009-02-23 09:29:56 +0100
committerMax Kellermann <max@duempel.org>2009-02-23 09:29:56 +0100
commit5a898c15e79ab87d2466e61549fcc20ce115c67e (patch)
treecb65b88718b0b8f3cf05221816b193833c41fe8a /src/output
parentd50a3d513eb0452e762f1e4eeb717318958cd83c (diff)
output_api: play() returns a length
The old API required an output plugin to not return until all data passed to the play() method is consumed. Some output plugins have to loop to fulfill that requirement, and may block during that. Simplify these, by letting them consume only part of the buffer: make play() return the length of the consumed data.
Diffstat (limited to 'src/output')
-rw-r--r--src/output/alsa_plugin.c31
-rw-r--r--src/output/ao_plugin.c20
-rw-r--r--src/output/fifo_plugin.c17
-rw-r--r--src/output/jack_plugin.c33
-rw-r--r--src/output/mvp_plugin.c12
-rw-r--r--src/output/null_plugin.c6
-rw-r--r--src/output/oss_plugin.c17
-rw-r--r--src/output/osx_plugin.c45
-rw-r--r--src/output/pulse_plugin.c6
-rw-r--r--src/output/shout_plugin.c7
10 files changed, 82 insertions, 112 deletions
diff --git a/src/output/alsa_plugin.c b/src/output/alsa_plugin.c
index bbb03e80..05e09751 100644
--- a/src/output/alsa_plugin.c
+++ b/src/output/alsa_plugin.c
@@ -441,7 +441,7 @@ alsa_close(void *data)
mixer_close(ad->mixer);
}
-static bool
+static size_t
alsa_play(void *data, const char *chunk, size_t size)
{
struct alsa_data *ad = data;
@@ -449,28 +449,19 @@ alsa_play(void *data, const char *chunk, size_t size)
size /= ad->frame_size;
- while (size > 0) {
+ while (true) {
ret = ad->writei(ad->pcm, chunk, size);
-
- if (ret == -EAGAIN || ret == -EINTR)
- continue;
-
- if (ret < 0) {
- if (alsa_recover(ad, ret) < 0) {
- g_warning("closing ALSA device \"%s\" due to write "
- "error: %s\n",
- alsa_device(ad), snd_strerror(-errno));
- return false;
- }
-
- continue;
+ if (ret > 0)
+ return ret * ad->frame_size;
+
+ if (ret < 0 && ret != -EAGAIN && ret != -EINTR &&
+ alsa_recover(ad, ret) < 0) {
+ g_warning("closing ALSA device \"%s\" due to write "
+ "error: %s\n",
+ alsa_device(ad), snd_strerror(-errno));
+ return 0;
}
-
- chunk += ret * ad->frame_size;
- size -= ret;
}
-
- return true;
}
const struct audio_output_plugin alsaPlugin = {
diff --git a/src/output/ao_plugin.c b/src/output/ao_plugin.c
index b0662d7a..c9d10174 100644
--- a/src/output/ao_plugin.c
+++ b/src/output/ao_plugin.c
@@ -208,29 +208,23 @@ static int ao_play_deconst(ao_device *device, const void *output_samples,
return ao_play(device, u.out, num_bytes);
}
-static bool
+static size_t
audioOutputAo_play(void *data, const char *playChunk, size_t size)
{
AoData *ad = (AoData *)data;
- size_t chunk_size;
if (ad->device == NULL)
return false;
- while (size > 0) {
- chunk_size = ad->writeSize > size
- ? size : ad->writeSize;
-
- if (ao_play_deconst(ad->device, playChunk, chunk_size) == 0) {
- audioOutputAo_error("Closing libao device due to play error");
- return false;
- }
+ if (size > ad->writeSize)
+ size = ad->writeSize;
- playChunk += chunk_size;
- size -= chunk_size;
+ if (ao_play_deconst(ad->device, playChunk, size) == 0) {
+ audioOutputAo_error("Closing libao device due to play error");
+ return 0;
}
- return true;
+ return size;
}
const struct audio_output_plugin aoPlugin = {
diff --git a/src/output/fifo_plugin.c b/src/output/fifo_plugin.c
index b0c6d12f..1be0f2a7 100644
--- a/src/output/fifo_plugin.c
+++ b/src/output/fifo_plugin.c
@@ -237,11 +237,10 @@ static void fifo_dropBufferedAudio(void *data)
}
}
-static bool
+static size_t
fifo_playAudio(void *data, const char *playChunk, size_t size)
{
FifoData *fd = (FifoData *)data;
- size_t offset = 0;
ssize_t bytes;
if (!fd->timer->started)
@@ -251,8 +250,11 @@ fifo_playAudio(void *data, const char *playChunk, size_t size)
timer_add(fd->timer, size);
- while (size) {
- bytes = write(fd->output, playChunk + offset, size);
+ while (true) {
+ bytes = write(fd->output, playChunk, size);
+ if (bytes > 0)
+ return (size_t)bytes;
+
if (bytes < 0) {
switch (errno) {
case EAGAIN:
@@ -265,14 +267,9 @@ fifo_playAudio(void *data, const char *playChunk, size_t size)
g_warning("Closing FIFO output \"%s\" due to write error: %s",
fd->path, strerror(errno));
- return false;
+ return 0;
}
-
- size -= bytes;
- offset += bytes;
}
-
- return true;
}
const struct audio_output_plugin fifoPlugin = {
diff --git a/src/output/jack_plugin.c b/src/output/jack_plugin.c
index 2bcdf874..22841f8e 100644
--- a/src/output/jack_plugin.c
+++ b/src/output/jack_plugin.c
@@ -387,7 +387,7 @@ mpd_jack_write_samples(struct jack_data *jd, const void *src,
}
}
-static bool
+static size_t
mpd_jack_play(void *data, const char *buff, size_t size)
{
struct jack_data *jd = data;
@@ -396,36 +396,33 @@ mpd_jack_play(void *data, const char *buff, size_t size)
if (jd->shutdown) {
g_warning("Refusing to play, because there is no client thread.");
- return false;
+ return 0;
}
assert(size % frame_size == 0);
size /= frame_size;
- while (size > 0 && !jd->shutdown) {
+
+ while (!jd->shutdown) {
space = jack_ringbuffer_write_space(jd->ringbuffer[0]);
space1 = jack_ringbuffer_write_space(jd->ringbuffer[1]);
if (space > space1)
/* send data symmetrically */
space = space1;
- space /= sample_size;
- if (space > 0) {
- if (space > size)
- space = size;
-
- mpd_jack_write_samples(jd, buff, space);
-
- buff += space * frame_size;
- size -= space;
- } else {
- /* XXX do something more intelligent to
- synchronize */
- g_usleep(1000);
- }
+ if (space >= frame_size)
+ break;
+ /* XXX do something more intelligent to
+ synchronize */
+ g_usleep(1000);
}
- return true;
+ space /= sample_size;
+ if (space < size)
+ size = space;
+
+ mpd_jack_write_samples(jd, buff, size);
+ return size * frame_size;
}
const struct audio_output_plugin jackPlugin = {
diff --git a/src/output/mvp_plugin.c b/src/output/mvp_plugin.c
index cb570c8e..840661ea 100644
--- a/src/output/mvp_plugin.c
+++ b/src/output/mvp_plugin.c
@@ -248,7 +248,7 @@ static void mvp_dropBufferedAudio(void *data)
}
}
-static bool
+static size_t
mvp_playAudio(void *data, const char *playChunk, size_t size)
{
MvpData *md = data;
@@ -258,19 +258,19 @@ mvp_playAudio(void *data, const char *playChunk, size_t size)
if (md->fd < 0)
mvp_openDevice(md, &md->audio_format);
- while (size > 0) {
+ while (true) {
ret = write(md->fd, playChunk, size);
+ if (ret > 0)
+ return (size_t)ret;
+
if (ret < 0) {
if (errno == EINTR)
continue;
g_warning("closing mvp PCM device due to write error: "
"%s\n", strerror(errno));
- return false;
+ return 0;
}
- playChunk += ret;
- size -= ret;
}
- return true;
}
const struct audio_output_plugin mvpPlugin = {
diff --git a/src/output/null_plugin.c b/src/output/null_plugin.c
index 1ae55ca9..2506feb7 100644
--- a/src/output/null_plugin.c
+++ b/src/output/null_plugin.c
@@ -74,14 +74,14 @@ null_close(void *data)
}
}
-static bool
+static size_t
null_play(void *data, G_GNUC_UNUSED const char *chunk, size_t size)
{
struct null_data *nd = data;
Timer *timer = nd->timer;
if (!nd->sync)
- return true;
+ return size;
if (!timer->started)
timer_start(timer);
@@ -90,7 +90,7 @@ null_play(void *data, G_GNUC_UNUSED const char *chunk, size_t size)
timer_add(timer, size);
- return true;
+ return size;
}
static void
diff --git a/src/output/oss_plugin.c b/src/output/oss_plugin.c
index 007d5bc8..eca6f910 100644
--- a/src/output/oss_plugin.c
+++ b/src/output/oss_plugin.c
@@ -553,7 +553,7 @@ static void oss_dropBufferedAudio(void *data)
}
}
-static bool
+static size_t
oss_playAudio(void *data, const char *playChunk, size_t size)
{
OssData *od = data;
@@ -563,20 +563,17 @@ oss_playAudio(void *data, const char *playChunk, size_t size)
if (od->fd < 0 && !oss_open(od))
return false;
- while (size > 0) {
+ while (true) {
ret = write(od->fd, playChunk, size);
- if (ret < 0) {
- if (errno == EINTR)
- continue;
+ if (ret > 0)
+ return (size_t)ret;
+
+ if (ret < 0 && errno != EINTR) {
g_warning("closing oss device \"%s\" due to write error: "
"%s\n", od->device, strerror(errno));
- return false;
+ return 0;
}
- playChunk += ret;
- size -= ret;
}
-
- return true;
}
const struct audio_output_plugin ossPlugin = {
diff --git a/src/output/osx_plugin.c b/src/output/osx_plugin.c
index a97f5698..ffeb8cd5 100644
--- a/src/output/osx_plugin.c
+++ b/src/output/osx_plugin.c
@@ -256,13 +256,11 @@ osx_openDevice(void *data, struct audio_format *audioFormat)
return true;
}
-static bool
+static size_t
osx_play(void *data, const char *playChunk, size_t size)
{
OsxData *od = data;
- size_t bytesToCopy;
- size_t bytes;
- size_t curpos;
+ size_t start, nbytes;
if (!od->started) {
int err;
@@ -270,42 +268,35 @@ osx_play(void *data, const char *playChunk, size_t size)
err = AudioOutputUnitStart(od->au);
if (err) {
g_warning("unable to start audio output: %i\n", err);
- return false;
+ return 0;
}
}
g_mutex_lock(od->mutex);
- while (size) {
- curpos = od->pos + od->len;
- if (curpos >= od->bufferSize)
- curpos -= od->bufferSize;
+ while (od->len >= od->bufferSize)
+ /* wait for some free space in the buffer */
+ g_cond_wait(od->condition, od->mutex);
- bytesToCopy = MIN(od->bufferSize, size);
+ start = od->pos + od->len;
+ if (start >= od->bufferSize)
+ start -= od->bufferSize;
- while (od->len > od->bufferSize - bytesToCopy) {
- g_cond_wait(od->condition, od->mutex);
- }
+ nbytes = start < od->pos
+ ? od->pos - start
+ : od->bufferSize - start;
- size -= bytesToCopy;
- od->len += bytesToCopy;
+ assert(nbytes > 0);
- bytes = od->bufferSize - curpos;
- if (bytesToCopy > bytes) {
- memcpy(od->buffer + curpos, playChunk, bytes);
- curpos = 0;
- playChunk += bytes;
- bytesToCopy -= bytes;
- }
-
- memcpy(od->buffer + curpos, playChunk, bytesToCopy);
- playChunk += bytesToCopy;
+ if (nbytes > size)
+ nbytes = size;
- }
+ memcpy(od->buffer + start, playChunk, nbytes);
+ od->len += nbytes;
g_mutex_unlock(od->mutex);
- return true;
+ return nbytes;
}
const struct audio_output_plugin osxPlugin = {
diff --git a/src/output/pulse_plugin.c b/src/output/pulse_plugin.c
index 559d2ee5..0203310e 100644
--- a/src/output/pulse_plugin.c
+++ b/src/output/pulse_plugin.c
@@ -160,7 +160,7 @@ static void pulse_close(void *data)
}
}
-static bool
+static size_t
pulse_play(void *data, const char *playChunk, size_t size)
{
struct pulse_data *pd = data;
@@ -172,10 +172,10 @@ pulse_play(void *data, const char *playChunk, size_t size)
audio_output_get_name(pd->ao),
pa_strerror(error));
pulse_close(pd);
- return false;
+ return 0;
}
- return true;
+ return size;
}
const struct audio_output_plugin pulse_plugin = {
diff --git a/src/output/shout_plugin.c b/src/output/shout_plugin.c
index 7887e292..2563e809 100644
--- a/src/output/shout_plugin.c
+++ b/src/output/shout_plugin.c
@@ -413,7 +413,7 @@ my_shout_open_device(void *data, struct audio_format *audio_format)
return true;
}
-static bool
+static size_t
my_shout_play(void *data, const char *chunk, size_t size)
{
struct shout_data *sd = (struct shout_data *)data;
@@ -427,7 +427,10 @@ my_shout_play(void *data, const char *chunk, size_t size)
return false;
}
- return write_page(sd);
+ if (!write_page(sd))
+ return 0;
+
+ return size;
}
static bool