output/Internal: move the "open" flag to struct AudioOutputControl

This commit is contained in:
Max Kellermann 2017-06-08 22:25:45 +02:00
parent 5ed5d7fe60
commit 6e2b348758
5 changed files with 53 additions and 68 deletions

View File

@ -85,12 +85,6 @@ AudioOutputControl::LockToggleEnabled() noexcept
return enabled = !enabled;
}
bool
AudioOutputControl::IsOpen() const noexcept
{
return output->IsOpen();
}
void
AudioOutputControl::WaitForCommand() noexcept
{
@ -180,7 +174,7 @@ AudioOutputControl::Open(const AudioFormat audio_format,
fail_timer.Reset();
if (output->open && audio_format == request.audio_format) {
if (open && audio_format == request.audio_format) {
assert(request.pipe == &mp || (always_on && pause));
if (!pause)
@ -196,7 +190,7 @@ AudioOutputControl::Open(const AudioFormat audio_format,
StartThread();
CommandWait(Command::OPEN);
const bool open2 = output->open;
const bool open2 = open;
if (open2 && output->mixer != nullptr) {
try {
@ -218,9 +212,9 @@ AudioOutputControl::CloseWait() noexcept
if (output->mixer != nullptr)
mixer_auto_close(output->mixer);
assert(!output->open || !fail_timer.IsDefined());
assert(!open || !fail_timer.IsDefined());
if (output->open)
if (open)
CommandWait(Command::CLOSE);
else
fail_timer.Reset();
@ -247,7 +241,7 @@ AudioOutputControl::LockUpdate(const AudioFormat audio_format,
bool
AudioOutputControl::IsChunkConsumed(const MusicChunk &chunk) const noexcept
{
if (!output->open)
if (!open)
return true;
return source.IsChunkConsumed(chunk);
@ -332,7 +326,7 @@ AudioOutputControl::LockRelease() noexcept
void
AudioOutputControl::LockCloseWait() noexcept
{
assert(!output->open || !fail_timer.IsDefined());
assert(!open || !fail_timer.IsDefined());
const std::lock_guard<Mutex> protect(mutex);
CloseWait();

View File

@ -155,6 +155,16 @@ class AudioOutputControl {
*/
bool really_enabled = false;
/**
* Is the device (already) open and functional?
*
* This attribute may only be modified by the output thread.
* It is protected with #mutex: write accesses inside the
* output thread and read accesses outside of it may only be
* performed while the lock is held.
*/
bool open = false;
/**
* Is the device paused? i.e. the output thread is in the
* ao_pause() loop.
@ -202,6 +212,7 @@ public:
assert(!fail_timer.IsDefined());
assert(!thread.IsDefined());
assert(output == nullptr);
assert(!open);
}
#endif
@ -240,8 +251,12 @@ public:
*/
bool LockToggleEnabled() noexcept;
gcc_pure
bool IsOpen() const noexcept;
/**
* Caller must lock the mutex.
*/
bool IsOpen() const noexcept {
return open;
}
/**
* Caller must lock the mutex.
@ -337,6 +352,11 @@ public:
source.SetReplayGainMode(_mode);
}
/**
* Throws #std::runtime_error on error.
*/
void InternalOpen2(AudioFormat in_audio_format);
/**
* Caller must lock the mutex.
*/

View File

@ -27,8 +27,6 @@
AudioOutput::~AudioOutput()
{
assert(!open);
if (mixer != nullptr)
mixer_free(mixer);
@ -40,7 +38,5 @@ AudioOutput::~AudioOutput()
void
audio_output_free(AudioOutput *ao) noexcept
{
assert(!ao->IsOpen());
ao_plugin_finish(ao);
}

View File

@ -52,16 +52,6 @@ struct AudioOutput {
*/
Mixer *mixer = nullptr;
/**
* Is the device (already) open and functional?
*
* This attribute may only be modified by the output thread.
* It is protected with #mutex: write accesses inside the
* output thread and read accesses outside of it may only be
* performed while the lock is held.
*/
bool open = false;
/**
* The configured audio format.
*/
@ -145,13 +135,6 @@ public:
return name;
}
/**
* Caller must lock the mutex.
*/
bool IsOpen() const {
return open;
}
/**
* Throws #std::runtime_error on error.
*/
@ -159,14 +142,8 @@ public:
void Disable() noexcept;
/**
* Throws #std::runtime_error on error.
*/
void Open(AudioFormat in_audio_format);
void Close(bool drain) noexcept;
private:
/**
* Invoke OutputPlugin::open() and configure the
* #ConvertFilter.
@ -189,7 +166,6 @@ private:
*/
void CloseFilter() noexcept;
public:
void BeginPause() noexcept;
bool IteratePause() noexcept;

View File

@ -84,44 +84,47 @@ AudioOutput::CloseFilter() noexcept
}
inline void
AudioOutput::Open(const AudioFormat in_audio_format)
AudioOutputControl::InternalOpen2(const AudioFormat in_audio_format)
{
assert(in_audio_format.IsValid());
if (mixer != nullptr && mixer->IsPlugin(software_mixer_plugin))
software_mixer_set_filter(*mixer, volume_filter.Get());
if (output->mixer != nullptr &&
output->mixer->IsPlugin(software_mixer_plugin))
software_mixer_set_filter(*output->mixer,
output->volume_filter.Get());
const auto cf = in_audio_format.WithMask(config_audio_format);
const auto cf = in_audio_format.WithMask(output->config_audio_format);
if (open && cf != filter_audio_format) {
if (open && cf != output->filter_audio_format) {
/* if the filter's output format changes, the output
must be reopened as well */
CloseOutput(true);
output->CloseOutput(true);
open = false;
}
filter_audio_format = cf;
output->filter_audio_format = cf;
if (!open) {
try {
OpenOutputAndConvert(filter_audio_format);
output->OpenOutputAndConvert(output->filter_audio_format);
} catch (...) {
CloseFilter();
output->CloseFilter();
throw;
}
open = true;
} else if (in_audio_format != out_audio_format) {
} else if (in_audio_format != output->out_audio_format) {
/* reconfigure the final ConvertFilter for its new
input AudioFormat */
try {
convert_filter_set(convert_filter.Get(),
out_audio_format);
convert_filter_set(output->convert_filter.Get(),
output->out_audio_format);
} catch (const std::runtime_error &e) {
Close(false);
open = false;
output->Close(false);
std::throw_with_nested(FormatRuntimeError("Failed to convert for \"%s\" [%s]",
name, plugin.name));
GetName(), output->plugin.name));
}
}
}
@ -227,7 +230,7 @@ AudioOutputControl::InternalOpen(const AudioFormat in_audio_format,
}
try {
output->Open(f);
InternalOpen2(f);
} catch (...) {
source.Close();
throw;
@ -251,6 +254,7 @@ AudioOutputControl::InternalClose(bool drain) noexcept
if (!IsOpen())
return;
open = false;
output->Close(drain);
source.Close();
}
@ -258,10 +262,6 @@ AudioOutputControl::InternalClose(bool drain) noexcept
void
AudioOutput::Close(bool drain) noexcept
{
assert(open);
open = false;
const ScopeUnlock unlock(mutex);
CloseOutput(drain);
@ -438,9 +438,6 @@ AudioOutput::IteratePause() noexcept
success = false;
}
if (!success)
Close(false);
return success;
}
@ -457,6 +454,8 @@ AudioOutputControl::InternalPause() noexcept
break;
if (!output->IteratePause()) {
open = false;
output->Close(false);
source.Close();
break;
}
@ -510,7 +509,7 @@ AudioOutputControl::Task()
break;
case Command::PAUSE:
if (!output->open) {
if (!open) {
/* the output has failed after
audio_output_all_pause() has
submitted the PAUSE command; bail
@ -527,7 +526,7 @@ AudioOutputControl::Task()
continue;
case Command::DRAIN:
if (output->open) {
if (open) {
const ScopeUnlock unlock(mutex);
ao_plugin_drain(*output);
}
@ -538,7 +537,7 @@ AudioOutputControl::Task()
case Command::CANCEL:
source.Cancel();
if (output->open) {
if (open) {
const ScopeUnlock unlock(mutex);
ao_plugin_cancel(*output);
}
@ -553,7 +552,7 @@ AudioOutputControl::Task()
return;
}
if (output->open && allow_play && InternalPlay())
if (open && allow_play && InternalPlay())
/* don't wait for an event if there are more
chunks in the pipe */
continue;