aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/user.xml12
-rw-r--r--src/output_all.c23
-rw-r--r--src/output_all.h7
-rw-r--r--src/output_control.c15
-rw-r--r--src/output_control.h9
-rw-r--r--src/output_init.c1
-rw-r--r--src/output_internal.h6
-rw-r--r--src/player_thread.c2
8 files changed, 73 insertions, 2 deletions
diff --git a/doc/user.xml b/doc/user.xml
index 30fcae69..e1e62eb9 100644
--- a/doc/user.xml
+++ b/doc/user.xml
@@ -339,6 +339,18 @@ cd mpd-version</programlisting>
</row>
<row>
<entry>
+ <varname>always_on</varname>
+ <parameter>yes|no</parameter>
+ </entry>
+ <entry>
+ If set to "yes", then MPD attempts to keep this audio
+ output always open. This may be useful for streaming
+ servers, when you don't want to disconnect all
+ listeners even when playback is accidently stopped.
+ </entry>
+ </row>
+ <row>
+ <entry>
<varname>mixer_type</varname>
<parameter>hardware|software|none</parameter>
</entry>
diff --git a/src/output_all.c b/src/output_all.c
index 4b770114..dbd5a6ce 100644
--- a/src/output_all.c
+++ b/src/output_all.c
@@ -559,6 +559,29 @@ audio_output_all_close(void)
}
void
+audio_output_all_release(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < num_audio_outputs; ++i)
+ audio_output_release(&audio_outputs[i]);
+
+ if (g_mp != NULL) {
+ assert(g_music_buffer != NULL);
+
+ music_pipe_clear(g_mp, g_music_buffer);
+ music_pipe_free(g_mp);
+ g_mp = NULL;
+ }
+
+ g_music_buffer = NULL;
+
+ audio_format_clear(&input_audio_format);
+
+ audio_output_all_elapsed_time = -1.0;
+}
+
+void
audio_output_all_song_border(void)
{
/* clear the elapsed_time pointer at the beginning of a new
diff --git a/src/output_all.h b/src/output_all.h
index 8c3f1e80..a579bf5f 100644
--- a/src/output_all.h
+++ b/src/output_all.h
@@ -92,6 +92,13 @@ void
audio_output_all_close(void);
/**
+ * Closes all audio outputs. Outputs with the "always_on" flag are
+ * put into pause mode.
+ */
+void
+audio_output_all_release(void);
+
+/**
* Enqueue a #music_chunk object for playing, i.e. pushes it to a
* #music_pipe.
*
diff --git a/src/output_control.c b/src/output_control.c
index b5d983ae..17edc3d7 100644
--- a/src/output_control.c
+++ b/src/output_control.c
@@ -118,9 +118,13 @@ audio_output_open(struct audio_output *ao,
if (ao->open &&
audio_format_equals(audio_format, &ao->in_audio_format)) {
- assert(ao->pipe == mp);
+ assert(ao->pipe == mp ||
+ (ao->always_on && ao->pause));
if (ao->pause) {
+ ao->chunk = NULL;
+ ao->pipe = mp;
+
/* unpause with the CANCEL command; this is a
hack, but suits well for forcing the thread
to leave the ao_pause() thread, and we need
@@ -266,6 +270,15 @@ void audio_output_close(struct audio_output *ao)
g_mutex_unlock(ao->mutex);
}
+void
+audio_output_release(struct audio_output *ao)
+{
+ if (ao->always_on)
+ audio_output_pause(ao);
+ else
+ audio_output_close(ao);
+}
+
void audio_output_finish(struct audio_output *ao)
{
audio_output_close(ao);
diff --git a/src/output_control.h b/src/output_control.h
index 9c2171a4..7f4f4a53 100644
--- a/src/output_control.h
+++ b/src/output_control.h
@@ -71,7 +71,16 @@ void
audio_output_drain_async(struct audio_output *ao);
void audio_output_cancel(struct audio_output *ao);
+
void audio_output_close(struct audio_output *ao);
+
+/**
+ * Closes the audio output, but if the "always_on" flag is set, put it
+ * into pause mode instead.
+ */
+void
+audio_output_release(struct audio_output *ao);
+
void audio_output_finish(struct audio_output *ao);
#endif
diff --git a/src/output_init.c b/src/output_init.c
index f3d22ace..6ee340ed 100644
--- a/src/output_init.c
+++ b/src/output_init.c
@@ -184,6 +184,7 @@ audio_output_init(struct audio_output *ao, const struct config_param *param,
}
ao->plugin = plugin;
+ ao->always_on = config_get_block_bool(param, "always_on", false);
ao->enabled = config_get_block_bool(param, "enabled", true);
ao->really_enabled = false;
ao->open = false;
diff --git a/src/output_internal.h b/src/output_internal.h
index 2a438c62..06df9531 100644
--- a/src/output_internal.h
+++ b/src/output_internal.h
@@ -76,6 +76,12 @@ struct audio_output {
struct mixer *mixer;
/**
+ * Shall this output always play something (i.e. silence),
+ * even when playback is stopped?
+ */
+ bool always_on;
+
+ /**
* Has the user enabled this device?
*/
bool enabled;
diff --git a/src/player_thread.c b/src/player_thread.c
index 3e234c4f..2496f0cd 100644
--- a/src/player_thread.c
+++ b/src/player_thread.c
@@ -978,7 +978,7 @@ static gpointer player_task(G_GNUC_UNUSED gpointer arg)
case PLAYER_COMMAND_CLOSE_AUDIO:
player_unlock();
- audio_output_all_close();
+ audio_output_all_release();
player_lock();
player_command_finished_locked();