Commit ecee6f41 authored by Max Kellermann's avatar Max Kellermann

mixer/MixerInternal: remember error details

If a mixer is not open, rethrow the original exception each time setting the volume is requested. This further improves error messages sent to MPD clients.
parent 47680f93
...@@ -60,9 +60,9 @@ mixer_open(Mixer *mixer) ...@@ -60,9 +60,9 @@ mixer_open(Mixer *mixer)
try { try {
mixer->Open(); mixer->Open();
mixer->open = true; mixer->open = true;
mixer->failed = false; mixer->failure = {};
} catch (...) { } catch (...) {
mixer->failed = true; mixer->failure = std::current_exception();
throw; throw;
} }
} }
...@@ -75,6 +75,7 @@ mixer_close_internal(Mixer *mixer) ...@@ -75,6 +75,7 @@ mixer_close_internal(Mixer *mixer)
mixer->Close(); mixer->Close();
mixer->open = false; mixer->open = false;
mixer->failure = {};
} }
void void
...@@ -95,20 +96,6 @@ mixer_auto_close(Mixer *mixer) ...@@ -95,20 +96,6 @@ mixer_auto_close(Mixer *mixer)
mixer_close(mixer); mixer_close(mixer);
} }
/*
* Close the mixer due to failure. The mutex must be locked before
* calling this function.
*/
static void
mixer_failed(Mixer *mixer)
{
assert(mixer->open);
mixer_close_internal(mixer);
mixer->failed = true;
}
int int
mixer_get_volume(Mixer *mixer) mixer_get_volume(Mixer *mixer)
{ {
...@@ -116,7 +103,7 @@ mixer_get_volume(Mixer *mixer) ...@@ -116,7 +103,7 @@ mixer_get_volume(Mixer *mixer)
assert(mixer != nullptr); assert(mixer != nullptr);
if (mixer->plugin.global && !mixer->failed) if (mixer->plugin.global && !mixer->failure)
mixer_open(mixer); mixer_open(mixer);
const std::scoped_lock<Mutex> protect(mixer->mutex); const std::scoped_lock<Mutex> protect(mixer->mutex);
...@@ -125,7 +112,8 @@ mixer_get_volume(Mixer *mixer) ...@@ -125,7 +112,8 @@ mixer_get_volume(Mixer *mixer)
try { try {
volume = mixer->GetVolume(); volume = mixer->GetVolume();
} catch (...) { } catch (...) {
mixer_failed(mixer); mixer_close_internal(mixer);
mixer->failure = std::current_exception();
throw; throw;
} }
} else } else
...@@ -140,11 +128,13 @@ mixer_set_volume(Mixer *mixer, unsigned volume) ...@@ -140,11 +128,13 @@ mixer_set_volume(Mixer *mixer, unsigned volume)
assert(mixer != nullptr); assert(mixer != nullptr);
assert(volume <= 100); assert(volume <= 100);
if (mixer->plugin.global && !mixer->failed) if (mixer->plugin.global && !mixer->failure)
mixer_open(mixer); mixer_open(mixer);
const std::scoped_lock<Mutex> protect(mixer->mutex); const std::scoped_lock<Mutex> protect(mixer->mutex);
if (mixer->open) if (mixer->open)
mixer->SetVolume(volume); mixer->SetVolume(volume);
else if (mixer->failure)
std::rethrow_exception(mixer->failure);
} }
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#include "thread/Mutex.hxx" #include "thread/Mutex.hxx"
#include "util/Compiler.h" #include "util/Compiler.h"
#include <exception>
class MixerListener; class MixerListener;
class Mixer { class Mixer {
...@@ -40,15 +42,15 @@ public: ...@@ -40,15 +42,15 @@ public:
Mutex mutex; Mutex mutex;
/** /**
* Is the mixer device currently open? * Contains error details if this mixer has failed. If set,
* it should not be reopened automatically.
*/ */
bool open = false; std::exception_ptr failure;
/** /**
* Has this mixer failed, and should not be reopened * Is the mixer device currently open?
* automatically?
*/ */
bool failed = false; bool open = false;
public: public:
explicit Mixer(const MixerPlugin &_plugin, explicit Mixer(const MixerPlugin &_plugin,
......
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