output/Internal: move the "open" flag to struct AudioOutputControl
This commit is contained in:
parent
5ed5d7fe60
commit
6e2b348758
@ -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();
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user