output/Thread: unify exception handling

This commit is contained in:
Max Kellermann 2016-12-27 14:55:56 +01:00
parent 6fc47fbb69
commit a9f2d25957
2 changed files with 46 additions and 37 deletions

View File

@ -410,20 +410,27 @@ public:
private: private:
void CommandFinished(); void CommandFinished();
bool Enable(); /**
* Throws #std::runtime_error on error.
*/
void Enable();
void Disable(); void Disable();
/**
* Throws #std::runtime_error on error.
*/
void Open(); void Open();
/** /**
* Invoke OutputPlugin::open() and configure the * Invoke OutputPlugin::open() and configure the
* #ConvertFilter. * #ConvertFilter.
* *
* Caller must not lock the mutex. * Throws #std::runtime_error on error.
* *
* @return true on success * Caller must not lock the mutex.
*/ */
bool OpenOutputAndConvert(AudioFormat audio_format); void OpenOutputAndConvert(AudioFormat audio_format);
void Close(bool drain); void Close(bool drain);

View File

@ -55,24 +55,21 @@ AudioOutput::CommandFinished()
audio_output_client_notify.Signal(); audio_output_client_notify.Signal();
} }
inline bool inline void
AudioOutput::Enable() AudioOutput::Enable()
{ {
if (really_enabled) if (really_enabled)
return true; return;
try { try {
const ScopeUnlock unlock(mutex); const ScopeUnlock unlock(mutex);
ao_plugin_enable(this); ao_plugin_enable(this);
} catch (const std::runtime_error &e) { } catch (const std::runtime_error &e) {
FormatError(e, std::throw_with_nested(FormatRuntimeError("Failed to enable output \"%s\" [%s]",
"Failed to enable \"%s\" [%s]", name, plugin.name));
name, plugin.name);
return false;
} }
really_enabled = true; really_enabled = true;
return true;
} }
inline void inline void
@ -106,11 +103,7 @@ AudioOutput::Open()
fail_timer.Reset(); fail_timer.Reset();
/* enable the device (just in case the last enable has failed) */ /* enable the device (just in case the last enable has failed) */
if (!Enable()) { Enable();
/* still no luck */
fail_timer.Update();
return;
}
AudioFormat f; AudioFormat f;
@ -124,10 +117,8 @@ AudioOutput::Open()
if (mixer != nullptr && mixer->IsPlugin(software_mixer_plugin)) if (mixer != nullptr && mixer->IsPlugin(software_mixer_plugin))
software_mixer_set_filter(*mixer, volume_filter.Get()); software_mixer_set_filter(*mixer, volume_filter.Get());
} catch (const std::runtime_error &e) { } catch (const std::runtime_error &e) {
FormatError(e, "Failed to open filter for \"%s\" [%s]", std::throw_with_nested(FormatRuntimeError("Failed to open filter for \"%s\" [%s]",
name, plugin.name); name, plugin.name));
fail_timer.Update();
return;
} }
if (open && f != filter_audio_format) { if (open && f != filter_audio_format) {
@ -140,16 +131,18 @@ AudioOutput::Open()
filter_audio_format = f; filter_audio_format = f;
if (!open) { if (!open) {
if (OpenOutputAndConvert(filter_audio_format)) { try {
open = true; OpenOutputAndConvert(filter_audio_format);
} else { } catch (...) {
CloseFilter(); CloseFilter();
fail_timer.Update(); throw;
} }
open = true;
} }
} }
bool void
AudioOutput::OpenOutputAndConvert(AudioFormat desired_audio_format) AudioOutput::OpenOutputAndConvert(AudioFormat desired_audio_format)
{ {
out_audio_format = desired_audio_format; out_audio_format = desired_audio_format;
@ -157,17 +150,13 @@ AudioOutput::OpenOutputAndConvert(AudioFormat desired_audio_format)
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]", std::throw_with_nested(FormatRuntimeError("Failed to open \"%s\" [%s]",
name, plugin.name); name, plugin.name));
return false;
} }
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) {
FormatError(e, "Failed to convert for \"%s\" [%s]",
name, plugin.name);
ao_plugin_close(this); ao_plugin_close(this);
if (out_audio_format.format == SampleFormat::DSD) { if (out_audio_format.format == SampleFormat::DSD) {
@ -177,13 +166,16 @@ AudioOutput::OpenOutputAndConvert(AudioFormat desired_audio_format)
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 */
LogError(e);
FormatError(output_domain, "Retrying without DSD"); FormatError(output_domain, "Retrying without DSD");
desired_audio_format.format = SampleFormat::FLOAT; desired_audio_format.format = SampleFormat::FLOAT;
return OpenOutputAndConvert(desired_audio_format); OpenOutputAndConvert(desired_audio_format);
return;
} }
return false; std::throw_with_nested(FormatRuntimeError("Failed to convert for \"%s\" [%s]",
name, plugin.name));
} }
struct audio_format_string af_string; struct audio_format_string af_string;
@ -196,8 +188,6 @@ AudioOutput::OpenOutputAndConvert(AudioFormat desired_audio_format)
FormatDebug(output_domain, "converting from %s", FormatDebug(output_domain, "converting from %s",
audio_format_to_string(source.GetInputAudioFormat(), audio_format_to_string(source.GetInputAudioFormat(),
&af_string)); &af_string));
return true;
} }
void void
@ -415,7 +405,13 @@ AudioOutput::Task()
break; break;
case Command::ENABLE: case Command::ENABLE:
Enable(); try {
Enable();
} catch (const std::runtime_error &e) {
LogError(e);
fail_timer.Update();
}
CommandFinished(); CommandFinished();
break; break;
@ -425,7 +421,13 @@ AudioOutput::Task()
break; break;
case Command::OPEN: case Command::OPEN:
Open(); try {
Open();
} catch (const std::runtime_error &e) {
LogError(e);
fail_timer.Update();
}
CommandFinished(); CommandFinished();
break; break;