summaryrefslogtreecommitdiff
path: root/src/output
diff options
context:
space:
mode:
authorMax Kellermann <max@musicpd.org>2018-11-12 11:30:05 +0100
committerMax Kellermann <max@musicpd.org>2018-11-12 12:09:37 +0100
commite097fef79e66b6ff6cf04a911067d3750b20bd48 (patch)
treee40e3df98debf38d8399fd00d4b3fac745765e82 /src/output
parent9a813cd3b11057d767e5bc30b83350e6052d1c28 (diff)
output/control: add command `RELEASE`
With the new command, the decision to pause or close the output moves into the output thread.
Diffstat (limited to 'src/output')
-rw-r--r--src/output/Control.cxx18
-rw-r--r--src/output/Control.hxx6
-rw-r--r--src/output/Thread.cxx24
3 files changed, 45 insertions, 3 deletions
diff --git a/src/output/Control.cxx b/src/output/Control.cxx
index 81847a1de..39812b165 100644
--- a/src/output/Control.cxx
+++ b/src/output/Control.cxx
@@ -347,10 +347,22 @@ AudioOutputControl::LockAllowPlay() noexcept
void
AudioOutputControl::LockRelease() noexcept
{
- if (always_on)
- LockPauseAsync();
+ if (output->mixer != nullptr &&
+ (!always_on || !output->SupportsPause()))
+ /* the device has no pause mode: close the mixer,
+ unless its "global" flag is set (checked by
+ mixer_auto_close()) */
+ mixer_auto_close(output->mixer);
+
+ const std::lock_guard<Mutex> protect(mutex);
+
+ assert(!open || !fail_timer.IsDefined());
+ assert(allow_play);
+
+ if (IsOpen())
+ CommandWait(Command::RELEASE);
else
- LockCloseWait();
+ fail_timer.Reset();
}
void
diff --git a/src/output/Control.hxx b/src/output/Control.hxx
index 58924edd5..3a961c57c 100644
--- a/src/output/Control.hxx
+++ b/src/output/Control.hxx
@@ -132,6 +132,12 @@ class AudioOutputControl {
PAUSE,
/**
+ * Close or pause the device, depending on the
+ * #always_on setting.
+ */
+ RELEASE,
+
+ /**
* Drains the internal (hardware) buffers of the device. This
* operation may take a while to complete.
*/
diff --git a/src/output/Thread.cxx b/src/output/Thread.cxx
index 4211cd078..b88eecbad 100644
--- a/src/output/Thread.cxx
+++ b/src/output/Thread.cxx
@@ -456,6 +456,30 @@ AudioOutputControl::Task() noexcept
the new command first */
continue;
+ case Command::RELEASE:
+ if (!open) {
+ /* the output has failed after
+ the PAUSE command was submitted; bail
+ out */
+ CommandFinished();
+ break;
+ }
+
+ if (always_on) {
+ /* in "always_on" mode, the output is
+ paused instead of being closed */
+ InternalPause();
+ } else {
+ InternalClose(false);
+ CommandFinished();
+ }
+
+ /* don't "break" here: this might cause
+ Play() to be called when command==CLOSE
+ ends the paused state - "continue" checks
+ the new command first */
+ continue;
+
case Command::DRAIN:
if (open)
InternalDrain();