diff options
-rw-r--r-- | src/output/alsa_plugin.c | 31 | ||||
-rw-r--r-- | src/output/ao_plugin.c | 20 | ||||
-rw-r--r-- | src/output/fifo_plugin.c | 17 | ||||
-rw-r--r-- | src/output/jack_plugin.c | 33 | ||||
-rw-r--r-- | src/output/mvp_plugin.c | 12 | ||||
-rw-r--r-- | src/output/null_plugin.c | 6 | ||||
-rw-r--r-- | src/output/oss_plugin.c | 17 | ||||
-rw-r--r-- | src/output/osx_plugin.c | 45 | ||||
-rw-r--r-- | src/output/pulse_plugin.c | 6 | ||||
-rw-r--r-- | src/output/shout_plugin.c | 7 | ||||
-rw-r--r-- | src/output_plugin.h | 6 | ||||
-rw-r--r-- | src/output_thread.c | 22 |
12 files changed, 103 insertions, 119 deletions
diff --git a/src/output/alsa_plugin.c b/src/output/alsa_plugin.c index bbb03e80b..05e097513 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 b0662d7a1..c9d10174e 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 b0c6d12f4..1be0f2a7d 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 2bcdf874f..22841f8ef 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 cb570c8ee..840661ea7 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 1ae55ca9b..2506feb74 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 007d5bc84..eca6f9101 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 a97f56982..ffeb8cd5e 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 559d2ee56..0203310e7 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 7887e2922..2563e8092 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 diff --git a/src/output_plugin.h b/src/output_plugin.h index b652dc44e..8a2bcadac 100644 --- a/src/output_plugin.h +++ b/src/output_plugin.h @@ -92,8 +92,10 @@ struct audio_output_plugin { /** * Play a chunk of audio data. + * + * @return the number of bytes played, or 0 on error */ - bool (*play)(void *data, const char *playChunk, size_t size); + size_t (*play)(void *data, const char *chunk, size_t size); /** * Try to cancel data which may still be in the device's @@ -167,7 +169,7 @@ ao_plugin_send_tag(const struct audio_output_plugin *plugin, plugin->send_tag(data, tag); } -static inline bool +static inline size_t ao_plugin_play(const struct audio_output_plugin *plugin, void *data, const void *chunk, size_t size) { diff --git a/src/output_thread.c b/src/output_thread.c index 098e1b427..709d8d1a2 100644 --- a/src/output_thread.c +++ b/src/output_thread.c @@ -52,9 +52,9 @@ static void ao_play(struct audio_output *ao) { const char *data = ao->args.play.data; size_t size = ao->args.play.size; - bool ret; assert(size > 0); + assert(size % audio_format_frame_size(&ao->out_audio_format) == 0); if (!audio_format_equals(&ao->in_audio_format, &ao->out_audio_format)) { data = pcm_convert(&ao->convert_state, @@ -69,10 +69,22 @@ static void ao_play(struct audio_output *ao) return; } - ret = ao_plugin_play(ao->plugin, ao->data, data, size); - if (!ret) { - ao_plugin_cancel(ao->plugin, ao->data); - ao_close(ao); + while (size > 0) { + size_t nbytes; + + nbytes = ao_plugin_play(ao->plugin, ao->data, data, size); + if (nbytes == 0) { + /* play()==0 means failure */ + ao_plugin_cancel(ao->plugin, ao->data); + ao_close(ao); + break; + } + + assert(nbytes <= size); + assert(nbytes % audio_format_frame_size(&ao->out_audio_format) == 0); + + data += nbytes; + size -= nbytes; } ao_command_finished(ao); |