aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/audio.c13
-rw-r--r--src/audio.h2
-rw-r--r--src/audioOutputs/audioOutput_shout.c19
-rw-r--r--src/audioOutputs/audioOutput_shout.h2
-rw-r--r--src/output_api.h11
-rw-r--r--src/output_control.c5
-rw-r--r--src/output_control.h3
-rw-r--r--src/output_thread.c18
-rw-r--r--src/player_thread.c2
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;