Commit a249a630 authored by Max Kellermann's avatar Max Kellermann

OutputThread: support plugins throwing exceptions

parent f39823ea
...@@ -66,6 +66,8 @@ struct AudioOutputPlugin { ...@@ -66,6 +66,8 @@ struct AudioOutputPlugin {
* Enable the device. This may allocate resources, preparing * Enable the device. This may allocate resources, preparing
* for the device to be opened. * for the device to be opened.
* *
* Throws #std::runtime_error on error.
*
* @return true on success, false on error * @return true on success, false on error
*/ */
bool (*enable)(AudioOutput *data, Error &error); bool (*enable)(AudioOutput *data, Error &error);
...@@ -79,6 +81,8 @@ struct AudioOutputPlugin { ...@@ -79,6 +81,8 @@ struct AudioOutputPlugin {
/** /**
* Really open the device. * Really open the device.
* *
* Throws #std::runtime_error on error.
*
* @param audio_format the audio format in which data is going * @param audio_format the audio format in which data is going
* to be delivered; may be modified by the plugin * to be delivered; may be modified by the plugin
*/ */
...@@ -110,6 +114,8 @@ struct AudioOutputPlugin { ...@@ -110,6 +114,8 @@ struct AudioOutputPlugin {
/** /**
* Play a chunk of audio data. * Play a chunk of audio data.
* *
* Throws #std::runtime_error on error.
*
* @return the number of bytes played, or 0 on error * @return the number of bytes played, or 0 on error
*/ */
size_t (*play)(AudioOutput *data, size_t (*play)(AudioOutput *data,
......
...@@ -61,7 +61,7 @@ AudioOutput::Enable() ...@@ -61,7 +61,7 @@ AudioOutput::Enable()
if (really_enabled) if (really_enabled)
return true; return true;
{ try {
const ScopeUnlock unlock(mutex); const ScopeUnlock unlock(mutex);
Error error; Error error;
if (!ao_plugin_enable(this, error)) { if (!ao_plugin_enable(this, error)) {
...@@ -70,6 +70,11 @@ AudioOutput::Enable() ...@@ -70,6 +70,11 @@ AudioOutput::Enable()
name, plugin.name); name, plugin.name);
return false; return false;
} }
} catch (const std::runtime_error &e) {
FormatError(e,
"Failed to enable \"%s\" [%s]",
name, plugin.name);
return false;
} }
really_enabled = true; really_enabled = true;
...@@ -174,7 +179,18 @@ AudioOutput::Open() ...@@ -174,7 +179,18 @@ AudioOutput::Open()
const AudioFormat retry_audio_format = out_audio_format; const AudioFormat retry_audio_format = out_audio_format;
retry_without_dsd: retry_without_dsd:
success = ao_plugin_open(this, out_audio_format, error); try {
success = ao_plugin_open(this, out_audio_format, error);
} catch (const std::runtime_error &e) {
FormatError(error, "Failed to open \"%s\" [%s]",
name, plugin.name);
CloseFilter();
mutex.lock();
fail_timer.Update();
return;
}
mutex.lock(); mutex.lock();
assert(!open); assert(!open);
...@@ -478,17 +494,23 @@ AudioOutput::PlayChunk(const MusicChunk *chunk) ...@@ -478,17 +494,23 @@ AudioOutput::PlayChunk(const MusicChunk *chunk)
size_t nbytes; size_t nbytes;
{ try {
const ScopeUnlock unlock(mutex); const ScopeUnlock unlock(mutex);
nbytes = ao_plugin_play(this, data.data, data.size, nbytes = ao_plugin_play(this, data.data, data.size,
error); error);
}
if (nbytes == 0) { if (nbytes == 0)
/* play()==0 means failure */ /* play()==0 means failure */
FormatError(error, "\"%s\" [%s] failed to play", FormatError(error, "\"%s\" [%s] failed to play",
name, plugin.name);
} catch (const std::runtime_error &e) {
FormatError(e, "\"%s\" [%s] failed to play",
name, plugin.name); name, plugin.name);
nbytes = 0;
}
if (nbytes == 0) {
Close(false); Close(false);
/* don't automatically reopen this device for /* don't automatically reopen this device for
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment