output/control: add command `RELEASE`

With the new command, the decision to pause or close the output moves
into the output thread.
This commit is contained in:
Max Kellermann 2018-11-12 11:30:05 +01:00
parent 9a813cd3b1
commit e097fef79e
3 changed files with 45 additions and 3 deletions

View File

@ -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

View File

@ -131,6 +131,12 @@ class AudioOutputControl {
CLOSE,
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.

View File

@ -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();