output/Thread: split Open()
Simplify the code, eliminate duplicate rollback code and eliminate the "goto" kludge.
This commit is contained in:
parent
093cb475bb
commit
ceba6816de
@ -401,6 +401,26 @@ private:
|
|||||||
void Disable();
|
void Disable();
|
||||||
|
|
||||||
void Open();
|
void Open();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open the #ChainFilter and call OpenOutputAndConvert().
|
||||||
|
*
|
||||||
|
* Caller must not lock the mutex.
|
||||||
|
*
|
||||||
|
* @return true on success
|
||||||
|
*/
|
||||||
|
bool OpenFilterAndOutput();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoke OutputPlugin::open() and configure the
|
||||||
|
* #ConvertFilter.
|
||||||
|
*
|
||||||
|
* Caller must not lock the mutex.
|
||||||
|
*
|
||||||
|
* @return true on success
|
||||||
|
*/
|
||||||
|
bool OpenOutputAndConvert(AudioFormat audio_format);
|
||||||
|
|
||||||
void Close(bool drain);
|
void Close(bool drain);
|
||||||
void Reopen();
|
void Reopen();
|
||||||
|
|
||||||
|
@ -131,8 +131,6 @@ AudioOutput::CloseFilter()
|
|||||||
inline void
|
inline void
|
||||||
AudioOutput::Open()
|
AudioOutput::Open()
|
||||||
{
|
{
|
||||||
struct audio_format_string af_string;
|
|
||||||
|
|
||||||
assert(!open);
|
assert(!open);
|
||||||
assert(in_audio_format.IsValid());
|
assert(in_audio_format.IsValid());
|
||||||
|
|
||||||
@ -144,42 +142,55 @@ AudioOutput::Open()
|
|||||||
/* still no luck */
|
/* still no luck */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* open the filter */
|
bool success;
|
||||||
|
|
||||||
const ScopeUnlock unlock(mutex);
|
{
|
||||||
|
const ScopeUnlock unlock(mutex);
|
||||||
|
success = OpenFilterAndOutput();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
open = true;
|
||||||
|
else
|
||||||
|
fail_timer.Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
AudioOutput::OpenFilterAndOutput()
|
||||||
|
{
|
||||||
AudioFormat filter_audio_format;
|
AudioFormat filter_audio_format;
|
||||||
try {
|
try {
|
||||||
filter_audio_format = OpenFilter(in_audio_format);
|
filter_audio_format = OpenFilter(in_audio_format);
|
||||||
} catch (const std::runtime_error &e) {
|
} catch (const std::runtime_error &e) {
|
||||||
FormatError(e, "Failed to open filter for \"%s\" [%s]",
|
FormatError(e, "Failed to open filter for \"%s\" [%s]",
|
||||||
name, plugin.name);
|
name, plugin.name);
|
||||||
|
return false;
|
||||||
fail_timer.Update();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(filter_audio_format.IsValid());
|
assert(filter_audio_format.IsValid());
|
||||||
|
|
||||||
const auto retry_audio_format = out_audio_format =
|
const auto audio_format =
|
||||||
filter_audio_format.WithMask(config_audio_format);
|
filter_audio_format.WithMask(config_audio_format);
|
||||||
|
bool success = OpenOutputAndConvert(audio_format);
|
||||||
|
if (!success)
|
||||||
|
CloseFilter();
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
AudioOutput::OpenOutputAndConvert(AudioFormat desired_audio_format)
|
||||||
|
{
|
||||||
|
out_audio_format = desired_audio_format;
|
||||||
|
|
||||||
retry_without_dsd:
|
|
||||||
try {
|
try {
|
||||||
ao_plugin_open(this, out_audio_format);
|
ao_plugin_open(this, out_audio_format);
|
||||||
} catch (const std::runtime_error &e) {
|
} catch (const std::runtime_error &e) {
|
||||||
FormatError(e, "Failed to open \"%s\" [%s]",
|
FormatError(e, "Failed to open \"%s\" [%s]",
|
||||||
name, plugin.name);
|
name, plugin.name);
|
||||||
|
return false;
|
||||||
CloseFilter();
|
|
||||||
|
|
||||||
const ScopeLock lock(mutex);
|
|
||||||
fail_timer.Update();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(!open);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
convert_filter_set(convert_filter.Get(), out_audio_format);
|
convert_filter_set(convert_filter.Get(), out_audio_format);
|
||||||
} catch (const std::runtime_error &e) {
|
} catch (const std::runtime_error &e) {
|
||||||
@ -195,26 +206,16 @@ AudioOutput::Open()
|
|||||||
implemented; our last resort is to give up
|
implemented; our last resort is to give up
|
||||||
DSD and fall back to PCM */
|
DSD and fall back to PCM */
|
||||||
|
|
||||||
// TODO: clean up this workaround
|
|
||||||
|
|
||||||
FormatError(output_domain, "Retrying without DSD");
|
FormatError(output_domain, "Retrying without DSD");
|
||||||
|
|
||||||
out_audio_format = retry_audio_format;
|
desired_audio_format.format = SampleFormat::FLOAT;
|
||||||
out_audio_format.format = SampleFormat::FLOAT;
|
return OpenOutputAndConvert(desired_audio_format);
|
||||||
|
|
||||||
/* sorry for the "goto" - this is a workaround
|
|
||||||
for the stable branch that should be as
|
|
||||||
unintrusive as possible */
|
|
||||||
goto retry_without_dsd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseFilter();
|
return false;
|
||||||
|
|
||||||
const ScopeLock lock(mutex);
|
|
||||||
fail_timer.Update();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct audio_format_string af_string;
|
||||||
FormatDebug(output_domain,
|
FormatDebug(output_domain,
|
||||||
"opened plugin=%s name=\"%s\" audio_format=%s",
|
"opened plugin=%s name=\"%s\" audio_format=%s",
|
||||||
plugin.name, name,
|
plugin.name, name,
|
||||||
@ -225,8 +226,7 @@ AudioOutput::Open()
|
|||||||
audio_format_to_string(in_audio_format,
|
audio_format_to_string(in_audio_format,
|
||||||
&af_string));
|
&af_string));
|
||||||
|
|
||||||
const ScopeLock lock(mutex);
|
return true;
|
||||||
open = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
Loading…
Reference in New Issue
Block a user