diff options
author | Max Kellermann <max@duempel.org> | 2008-09-29 16:43:55 +0200 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2008-09-29 16:43:55 +0200 |
commit | 6e21e24caed1a9497e876e4b89b12687aa73d6ad (patch) | |
tree | dd1fe746cdd61eafc82117421cf3633e014a9bef | |
parent | c13e8b5146993999a87373a98b5a3da4b6cf599a (diff) | |
download | mpd-6e21e24caed1a9497e876e4b89b12687aa73d6ad.tar.gz mpd-6e21e24caed1a9497e876e4b89b12687aa73d6ad.tar.xz mpd-6e21e24caed1a9497e876e4b89b12687aa73d6ad.zip |
audio_output: added method pause()
pause() puts the audio output into pause mode: if supported, it may
perform a special action, which keeps the device open, but does not
play anything. Output plugins like "shout" might want to play silence
during pause, so their clients won't be disconnected. Plugins which
do not support pausing will simply be closed, and have to be reopened
when unpaused.
This pach includes an implementation for the shout plugin, which
sends silence chunks.
-rw-r--r-- | src/audio.c | 13 | ||||
-rw-r--r-- | src/audio.h | 2 | ||||
-rw-r--r-- | src/audioOutputs/audioOutput_shout.c | 19 | ||||
-rw-r--r-- | src/audioOutputs/audioOutput_shout.h | 2 | ||||
-rw-r--r-- | src/output_api.h | 11 | ||||
-rw-r--r-- | src/output_control.c | 5 | ||||
-rw-r--r-- | src/output_control.h | 3 | ||||
-rw-r--r-- | src/output_thread.c | 18 | ||||
-rw-r--r-- | src/player_thread.c | 2 |
9 files changed, 73 insertions, 2 deletions
diff --git a/src/audio.c b/src/audio.c index bbc7fd0eb..b38c47d72 100644 --- a/src/audio.c +++ b/src/audio.c @@ -397,6 +397,19 @@ int playAudio(const char *playChunk, size_t size) return 0; } +void audio_output_pause_all(void) +{ + unsigned int i; + + syncAudioDeviceStates(); + + for (i = 0; i < audioOutputArraySize; ++i) + if (audio_output_is_open(&audioOutputArray[i])) + audio_output_pause(&audioOutputArray[i]); + + audio_output_wait_all(); +} + void dropBufferedAudio(void) { unsigned int i; diff --git a/src/audio.h b/src/audio.h index 4e34b0f61..3ffa2dc55 100644 --- a/src/audio.h +++ b/src/audio.h @@ -45,6 +45,8 @@ int openAudioDevice(const struct audio_format *audioFormat); int playAudio(const char *playChunk, size_t size); +void audio_output_pause_all(void); + void dropBufferedAudio(void); void closeAudioDevice(void); diff --git a/src/audioOutputs/audioOutput_shout.c b/src/audioOutputs/audioOutput_shout.c index b55c06cc9..6b59044d8 100644 --- a/src/audioOutputs/audioOutput_shout.c +++ b/src/audioOutputs/audioOutput_shout.c @@ -87,7 +87,7 @@ static void free_shout_data(struct shout_data *sd) } \ } -static void *my_shout_init_driver(mpd_unused struct audio_output *audio_output, +static void *my_shout_init_driver(struct audio_output *audio_output, const struct audio_format *audio_format, ConfigParam *param) { @@ -104,6 +104,7 @@ static void *my_shout_init_driver(mpd_unused struct audio_output *audio_output, int public; sd = new_shout_data(); + sd->audio_output = audio_output; if (shout_init_count == 0) shout_init(); @@ -516,6 +517,21 @@ static int my_shout_play(void *data, return 0; } +static void my_shout_pause(void *data) +{ + struct shout_data *sd = (struct shout_data *)data; + static const char silence[1020]; + int ret; + + /* play silence until the player thread sends us a command */ + + while (sd->opened && !audio_output_is_pending(sd->audio_output)) { + ret = my_shout_play(data, silence, sizeof(silence)); + if (ret != 0) + break; + } +} + static void my_shout_set_tag(void *data, const struct tag *tag) { @@ -539,6 +555,7 @@ const struct audio_output_plugin shoutPlugin = { .finish = my_shout_finish_driver, .open = my_shout_open_device, .play = my_shout_play, + .pause = my_shout_pause, .cancel = my_shout_drop_buffered_audio, .close = my_shout_close_device, .send_tag = my_shout_set_tag, diff --git a/src/audioOutputs/audioOutput_shout.h b/src/audioOutputs/audioOutput_shout.h index ddab852df..bd525fd6d 100644 --- a/src/audioOutputs/audioOutput_shout.h +++ b/src/audioOutputs/audioOutput_shout.h @@ -59,6 +59,8 @@ struct shout_buffer { }; struct shout_data { + struct audio_output *audio_output; + shout_t *shout_conn; shout_metadata_t *shout_meta; int shout_error; diff --git a/src/output_api.h b/src/output_api.h index 96acff775..1cad66e60 100644 --- a/src/output_api.h +++ b/src/output_api.h @@ -82,6 +82,16 @@ struct audio_output_plugin { int (*play)(void *data, const char *playChunk, size_t size); /** + * Pause the device. If supported, it may perform a special + * action, which keeps the device open, but does not play + * anything. Output plugins like "shout" might want to play + * silence during pause, so their clients won't be + * disconnected. Plugins which do not support pausing will + * simply be closed, and have to be reopened when unpaused. + */ + void (*pause)(void *data); + + /** * Try to cancel data which may still be in the device's * buffers. */ @@ -104,6 +114,7 @@ enum audio_output_command { AO_COMMAND_OPEN, AO_COMMAND_CLOSE, AO_COMMAND_PLAY, + AO_COMMAND_PAUSE, AO_COMMAND_CANCEL, AO_COMMAND_SEND_TAG, AO_COMMAND_KILL diff --git a/src/output_control.c b/src/output_control.c index ac9394bd7..4724aeeea 100644 --- a/src/output_control.c +++ b/src/output_control.c @@ -103,6 +103,11 @@ void audio_output_play(struct audio_output *audioOutput, ao_command_async(audioOutput, AO_COMMAND_PLAY); } +void audio_output_pause(struct audio_output *audioOutput) +{ + ao_command_async(audioOutput, AO_COMMAND_PAUSE); +} + void audio_output_cancel(struct audio_output *audioOutput) { ao_command_async(audioOutput, AO_COMMAND_CANCEL); diff --git a/src/output_control.h b/src/output_control.h index b83a67b2f..7a31bb68f 100644 --- a/src/output_control.h +++ b/src/output_control.h @@ -41,6 +41,9 @@ audio_output_signal(struct audio_output *ao); void audio_output_play(struct audio_output *audioOutput, const char *playChunk, size_t size); + +void audio_output_pause(struct audio_output *audioOutput); + void audio_output_cancel(struct audio_output *audioOutput); void audio_output_close(struct audio_output *audioOutput); void audio_output_finish(struct audio_output *audioOutput); diff --git a/src/output_thread.c b/src/output_thread.c index 4bc5d8fcb..c2f4f6d3c 100644 --- a/src/output_thread.c +++ b/src/output_thread.c @@ -63,6 +63,20 @@ static void ao_play(struct audio_output *ao) ao_command_finished(ao); } +static void ao_pause(struct audio_output *ao) +{ + if (ao->plugin->pause != NULL) { + /* pause is supported */ + ao_command_finished(ao); + ao->plugin->pause(ao->data); + } else { + /* pause is not supported - simply close the device */ + ao->plugin->close(ao->data); + ao->open = 0; + ao_command_finished(ao); + } +} + static void *audio_output_task(void *arg) { struct audio_output *ao = arg; @@ -95,6 +109,10 @@ static void *audio_output_task(void *arg) ao_play(ao); break; + case AO_COMMAND_PAUSE: + ao_pause(ao); + break; + case AO_COMMAND_CANCEL: ao->plugin->cancel(ao->data); ao_command_finished(ao); diff --git a/src/player_thread.c b/src/player_thread.c index 171bd71c4..48715dd20 100644 --- a/src/player_thread.c +++ b/src/player_thread.c @@ -143,7 +143,7 @@ static void processDecodeInput(int *pause_r, unsigned int *bbp_r, *pause_r = 1; } else if (*pause_r) { dropBufferedAudio(); - closeAudioDevice(); + audio_output_pause_all(); } break; |