diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/output_plugin.h | 18 | ||||
-rw-r--r-- | src/output_thread.c | 30 | ||||
-rw-r--r-- | src/timer.c | 6 |
3 files changed, 51 insertions, 3 deletions
diff --git a/src/output_plugin.h b/src/output_plugin.h index fabfe0dfa..36e17ed1b 100644 --- a/src/output_plugin.h +++ b/src/output_plugin.h @@ -101,6 +101,16 @@ struct audio_output_plugin { void (*close)(void *data); /** + * Returns a positive number if the output thread shall delay + * the next call to play() or pause(). This should be + * implemented instead of doing a sleep inside the plugin, + * because this allows MPD to listen to commands meanwhile. + * + * @return the number of milliseconds to wait + */ + unsigned (*delay)(void *data); + + /** * Display metadata for the next chunk. Optional method, * because not all devices can display metadata. */ @@ -202,6 +212,14 @@ ao_plugin_close(const struct audio_output_plugin *plugin, void *data) plugin->close(data); } +static inline unsigned +ao_plugin_delay(const struct audio_output_plugin *plugin, void *data) +{ + return plugin->delay != NULL + ? plugin->delay(data) + : 0; +} + static inline void ao_plugin_send_tag(const struct audio_output_plugin *plugin, void *data, const struct tag *tag) diff --git a/src/output_thread.c b/src/output_thread.c index c10a1552f..8b120325c 100644 --- a/src/output_thread.c +++ b/src/output_thread.c @@ -278,6 +278,30 @@ ao_reopen(struct audio_output *ao) ao_open(ao); } +/** + * Wait until the output's delay reaches zero. + * + * @return true if playback should be continued, false if a command + * was issued + */ +static bool +ao_wait(struct audio_output *ao) +{ + while (true) { + unsigned delay = ao_plugin_delay(ao->plugin, ao->data); + if (delay == 0) + return true; + + GTimeVal tv; + g_get_current_time(&tv); + g_time_val_add(&tv, delay * 1000); + g_cond_timed_wait(ao->cond, ao->mutex, &tv); + + if (ao->command != AO_COMMAND_NONE) + return false; + } +} + static const char * ao_chunk_data(struct audio_output *ao, const struct music_chunk *chunk, struct filter *replay_gain_filter, @@ -414,6 +438,9 @@ ao_play_chunk(struct audio_output *ao, const struct music_chunk *chunk) while (size > 0 && ao->command == AO_COMMAND_NONE) { size_t nbytes; + if (!ao_wait(ao)) + break; + g_mutex_unlock(ao->mutex); nbytes = ao_plugin_play(ao->plugin, ao->data, data, size, &error); @@ -511,6 +538,9 @@ static void ao_pause(struct audio_output *ao) ao_command_finished(ao); do { + if (!ao_wait(ao)) + break; + g_mutex_unlock(ao->mutex); ret = ao_plugin_pause(ao->plugin, ao->data); g_mutex_lock(ao->mutex); diff --git a/src/timer.c b/src/timer.c index 49c2ee3ac..e125b1009 100644 --- a/src/timer.c +++ b/src/timer.c @@ -74,12 +74,12 @@ void timer_add(Timer *timer, int size) unsigned timer_delay(const Timer *timer) { - int64_t delay = timer->time - now(); + int64_t delay = (timer->time - now()) / 1000; if (delay < 0) return 0; - if (delay > 1000 * 1000 * 1000) - return 1000 * 1000; + if (delay > G_MAXINT) + delay = G_MAXINT; return delay / 1000; } |