Commit e686d191 authored by Max Kellermann's avatar Max Kellermann

output: added option "always_on" for radio stations

Did you ever accidently click "stop" while feeding a radio station? This option sets the output device to "pause" to disable the "close" method. It falls back to "pause" then, which is specific to the plugin. Some plugins implement it by feeding silence.
parent 762565e9
...@@ -339,6 +339,18 @@ cd mpd-version</programlisting> ...@@ -339,6 +339,18 @@ cd mpd-version</programlisting>
</row> </row>
<row> <row>
<entry> <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> <varname>mixer_type</varname>
<parameter>hardware|software|none</parameter> <parameter>hardware|software|none</parameter>
</entry> </entry>
......
...@@ -559,6 +559,29 @@ audio_output_all_close(void) ...@@ -559,6 +559,29 @@ audio_output_all_close(void)
} }
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) audio_output_all_song_border(void)
{ {
/* clear the elapsed_time pointer at the beginning of a new /* clear the elapsed_time pointer at the beginning of a new
......
...@@ -92,6 +92,13 @@ void ...@@ -92,6 +92,13 @@ void
audio_output_all_close(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 * Enqueue a #music_chunk object for playing, i.e. pushes it to a
* #music_pipe. * #music_pipe.
* *
......
...@@ -118,9 +118,13 @@ audio_output_open(struct audio_output *ao, ...@@ -118,9 +118,13 @@ audio_output_open(struct audio_output *ao,
if (ao->open && if (ao->open &&
audio_format_equals(audio_format, &ao->in_audio_format)) { 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) { if (ao->pause) {
ao->chunk = NULL;
ao->pipe = mp;
/* unpause with the CANCEL command; this is a /* unpause with the CANCEL command; this is a
hack, but suits well for forcing the thread hack, but suits well for forcing the thread
to leave the ao_pause() thread, and we need to leave the ao_pause() thread, and we need
...@@ -266,6 +270,15 @@ void audio_output_close(struct audio_output *ao) ...@@ -266,6 +270,15 @@ void audio_output_close(struct audio_output *ao)
g_mutex_unlock(ao->mutex); 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) void audio_output_finish(struct audio_output *ao)
{ {
audio_output_close(ao); audio_output_close(ao);
......
...@@ -71,7 +71,16 @@ void ...@@ -71,7 +71,16 @@ void
audio_output_drain_async(struct audio_output *ao); audio_output_drain_async(struct audio_output *ao);
void audio_output_cancel(struct audio_output *ao); void audio_output_cancel(struct audio_output *ao);
void audio_output_close(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); void audio_output_finish(struct audio_output *ao);
#endif #endif
...@@ -184,6 +184,7 @@ audio_output_init(struct audio_output *ao, const struct config_param *param, ...@@ -184,6 +184,7 @@ audio_output_init(struct audio_output *ao, const struct config_param *param,
} }
ao->plugin = plugin; ao->plugin = plugin;
ao->always_on = config_get_block_bool(param, "always_on", false);
ao->enabled = config_get_block_bool(param, "enabled", true); ao->enabled = config_get_block_bool(param, "enabled", true);
ao->really_enabled = false; ao->really_enabled = false;
ao->open = false; ao->open = false;
......
...@@ -76,6 +76,12 @@ struct audio_output { ...@@ -76,6 +76,12 @@ struct audio_output {
struct mixer *mixer; 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? * Has the user enabled this device?
*/ */
bool enabled; bool enabled;
......
...@@ -978,7 +978,7 @@ static gpointer player_task(G_GNUC_UNUSED gpointer arg) ...@@ -978,7 +978,7 @@ static gpointer player_task(G_GNUC_UNUSED gpointer arg)
case PLAYER_COMMAND_CLOSE_AUDIO: case PLAYER_COMMAND_CLOSE_AUDIO:
player_unlock(); player_unlock();
audio_output_all_close(); audio_output_all_release();
player_lock(); player_lock();
player_command_finished_locked(); player_command_finished_locked();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment