diff --git a/src/filter/plugins/ReplayGainFilterPlugin.cxx b/src/filter/plugins/ReplayGainFilterPlugin.cxx index 4e62d93c2..2ec07c2bd 100644 --- a/src/filter/plugins/ReplayGainFilterPlugin.cxx +++ b/src/filter/plugins/ReplayGainFilterPlugin.cxx @@ -158,9 +158,11 @@ ReplayGainFilter::Update() if (_volume > 100) _volume = 100; - Error error; - if (!mixer_set_volume(mixer, _volume, error)) - LogError(error, "Failed to update hardware mixer"); + try { + mixer_set_volume(mixer, _volume); + } catch (const std::runtime_error &e) { + LogError(e, "Failed to update hardware mixer"); + } } else pv.SetVolume(volume); } diff --git a/src/mixer/MixerAll.cxx b/src/mixer/MixerAll.cxx index e5878887b..f82d940f6 100644 --- a/src/mixer/MixerAll.cxx +++ b/src/mixer/MixerAll.cxx @@ -24,9 +24,10 @@ #include "MixerList.hxx" #include "output/Internal.hxx" #include "pcm/Volume.hxx" -#include "util/Error.hxx" #include "Log.hxx" +#include + #include static int @@ -39,14 +40,14 @@ output_mixer_get_volume(const AudioOutput &ao) if (mixer == nullptr) return -1; - Error error; - int volume = mixer_get_volume(mixer, error); - if (volume < 0 && error.IsDefined()) - FormatError(error, + try { + return mixer_get_volume(mixer); + } catch (const std::runtime_error &e) { + FormatError(e, "Failed to read mixer for '%s'", ao.name); - - return volume; + return -1; + } } int @@ -81,14 +82,15 @@ output_mixer_set_volume(AudioOutput &ao, unsigned volume) if (mixer == nullptr) return false; - Error error; - bool success = mixer_set_volume(mixer, volume, error); - if (!success && error.IsDefined()) - FormatError(error, + try { + mixer_set_volume(mixer, volume); + return true; + } catch (const std::runtime_error &e) { + FormatError(e, "Failed to set mixer for '%s'", ao.name); - - return success; + return false; + } } bool @@ -114,7 +116,7 @@ output_mixer_get_software_volume(const AudioOutput &ao) if (mixer == nullptr || !mixer->IsPlugin(software_mixer_plugin)) return -1; - return mixer_get_volume(mixer, IgnoreError()); + return mixer_get_volume(mixer); } int @@ -148,6 +150,6 @@ MultipleOutputs::SetSoftwareVolume(unsigned volume) if (mixer != nullptr && (&mixer->plugin == &software_mixer_plugin || &mixer->plugin == &null_mixer_plugin)) - mixer_set_volume(mixer, volume, IgnoreError()); + mixer_set_volume(mixer, volume); } } diff --git a/src/mixer/MixerControl.cxx b/src/mixer/MixerControl.cxx index f9821bb1a..33f26ccc9 100644 --- a/src/mixer/MixerControl.cxx +++ b/src/mixer/MixerControl.cxx @@ -20,7 +20,6 @@ #include "config.h" #include "MixerControl.hxx" #include "MixerInternal.hxx" -#include "util/Error.hxx" #include @@ -28,10 +27,9 @@ Mixer * mixer_new(EventLoop &event_loop, const MixerPlugin &plugin, AudioOutput &ao, MixerListener &listener, - const ConfigBlock &block, - Error &error) + const ConfigBlock &block) { - Mixer *mixer = plugin.init(event_loop, ao, listener, block, error); + Mixer *mixer = plugin.init(event_loop, ao, listener, block); assert(mixer == nullptr || mixer->IsPlugin(plugin)); @@ -50,20 +48,24 @@ mixer_free(Mixer *mixer) delete mixer; } -bool -mixer_open(Mixer *mixer, Error &error) +void +mixer_open(Mixer *mixer) { - bool success; - assert(mixer != nullptr); const ScopeLock protect(mixer->mutex); - success = mixer->open || (mixer->open = mixer->Open(error)); + if (mixer->open) + return; - mixer->failed = !success; - - return success; + try { + mixer->Open(); + mixer->open = true; + mixer->failed = false; + } catch (...) { + mixer->failed = true; + throw; + } } static void @@ -109,39 +111,41 @@ mixer_failed(Mixer *mixer) } int -mixer_get_volume(Mixer *mixer, Error &error) +mixer_get_volume(Mixer *mixer) { int volume; assert(mixer != nullptr); - if (mixer->plugin.global && !mixer->failed && - !mixer_open(mixer, error)) - return -1; + if (mixer->plugin.global && !mixer->failed) + mixer_open(mixer); const ScopeLock protect(mixer->mutex); if (mixer->open) { - volume = mixer->GetVolume(error); - if (volume < 0 && error.IsDefined()) + try { + volume = mixer->GetVolume(); + } catch (...) { mixer_failed(mixer); + throw; + } } else volume = -1; return volume; } -bool -mixer_set_volume(Mixer *mixer, unsigned volume, Error &error) +void +mixer_set_volume(Mixer *mixer, unsigned volume) { assert(mixer != nullptr); assert(volume <= 100); - if (mixer->plugin.global && !mixer->failed && - !mixer_open(mixer, error)) - return false; + if (mixer->plugin.global && !mixer->failed) + mixer_open(mixer); const ScopeLock protect(mixer->mutex); - return mixer->open && mixer->SetVolume(volume, error); + if (mixer->open) + mixer->SetVolume(volume); } diff --git a/src/mixer/MixerControl.hxx b/src/mixer/MixerControl.hxx index 23d5adf28..e153f9bc0 100644 --- a/src/mixer/MixerControl.hxx +++ b/src/mixer/MixerControl.hxx @@ -25,7 +25,6 @@ #ifndef MPD_MIXER_CONTROL_HXX #define MPD_MIXER_CONTROL_HXX -class Error; class Mixer; class EventLoop; struct AudioOutput; @@ -33,17 +32,22 @@ struct MixerPlugin; class MixerListener; struct ConfigBlock; +/** + * Throws std::runtime_error on error. + */ Mixer * mixer_new(EventLoop &event_loop, const MixerPlugin &plugin, AudioOutput &ao, MixerListener &listener, - const ConfigBlock &block, - Error &error); + const ConfigBlock &block); void mixer_free(Mixer *mixer); -bool -mixer_open(Mixer *mixer, Error &error); +/** + * Throws std::runtime_error on error. + */ +void +mixer_open(Mixer *mixer); void mixer_close(Mixer *mixer); @@ -55,10 +59,16 @@ mixer_close(Mixer *mixer); void mixer_auto_close(Mixer *mixer); +/** + * Throws std::runtime_error on error. + */ int -mixer_get_volume(Mixer *mixer, Error &error); +mixer_get_volume(Mixer *mixer); -bool -mixer_set_volume(Mixer *mixer, unsigned volume, Error &error); +/** + * Throws std::runtime_error on error. + */ +void +mixer_set_volume(Mixer *mixer, unsigned volume); #endif diff --git a/src/mixer/MixerInternal.hxx b/src/mixer/MixerInternal.hxx index a9476c10c..68cb4605f 100644 --- a/src/mixer/MixerInternal.hxx +++ b/src/mixer/MixerInternal.hxx @@ -67,9 +67,9 @@ public: /** * Open mixer device * - * @return true on success, false on error + * Throws std::runtime_error on error. */ - virtual bool Open(Error &error) = 0; + virtual void Open() = 0; /** * Close mixer device @@ -79,19 +79,22 @@ public: /** * Reads the current volume. * + * Throws std::runtime_error on error. + * * @return the current volume (0..100 including) or -1 if - * unavailable or on error (error set, mixer will be closed) + * unavailable */ gcc_pure - virtual int GetVolume(Error &error) = 0; + virtual int GetVolume() = 0; /** * Sets the volume. * - * @param volume the new volume (0..100 including) @return - * true on success, false on error + * Throws std::runtime_error on error. + * + * @param volume the new volume (0..100 including) */ - virtual bool SetVolume(unsigned volume, Error &error) = 0; + virtual void SetVolume(unsigned volume) = 0; }; #endif diff --git a/src/mixer/MixerPlugin.hxx b/src/mixer/MixerPlugin.hxx index f12631d0a..cc86b2e50 100644 --- a/src/mixer/MixerPlugin.hxx +++ b/src/mixer/MixerPlugin.hxx @@ -32,22 +32,20 @@ struct AudioOutput; class Mixer; class MixerListener; class EventLoop; -class Error; struct MixerPlugin { /** * Alocates and configures a mixer device. * + * Throws std::runtime_error on error. + * * @param ao the associated AudioOutput * @param param the configuration section - * @param error_r location to store the error occurring, or - * nullptr to ignore errors - * @return a mixer object, or nullptr on error + * @return a mixer object */ Mixer *(*init)(EventLoop &event_loop, AudioOutput &ao, MixerListener &listener, - const ConfigBlock &block, - Error &error); + const ConfigBlock &block); /** * If true, then the mixer is automatically opened, even if diff --git a/src/mixer/plugins/AlsaMixerPlugin.cxx b/src/mixer/plugins/AlsaMixerPlugin.cxx index d6984fa13..be43b3d33 100644 --- a/src/mixer/plugins/AlsaMixerPlugin.cxx +++ b/src/mixer/plugins/AlsaMixerPlugin.cxx @@ -26,8 +26,8 @@ #include "util/ASCII.hxx" #include "util/ReusableArray.hxx" #include "util/Clamp.hxx" -#include "util/Error.hxx" #include "util/Domain.hxx" +#include "util/RuntimeError.hxx" #include "Log.hxx" #include @@ -82,13 +82,13 @@ public: virtual ~AlsaMixer(); void Configure(const ConfigBlock &block); - bool Setup(Error &error); + void Setup(); /* virtual methods from class Mixer */ - virtual bool Open(Error &error) override; - virtual void Close() override; - virtual int GetVolume(Error &error) override; - virtual bool SetVolume(unsigned volume, Error &error) override; + void Open() override; + void Close() override; + int GetVolume() override; + void SetVolume(unsigned volume) override; }; static constexpr Domain alsa_mixer_domain("alsa_mixer"); @@ -148,8 +148,11 @@ alsa_mixer_elem_callback(snd_mixer_elem_t *elem, unsigned mask) snd_mixer_elem_get_callback_private(elem); if (mask & SND_CTL_EVENT_MASK_VALUE) { - int volume = mixer.GetVolume(IgnoreError()); - mixer.listener.OnMixerVolumeChanged(mixer, volume); + try { + int volume = mixer.GetVolume(); + mixer.listener.OnMixerVolumeChanged(mixer, volume); + } catch (const std::runtime_error &) { + } } return 0; @@ -174,8 +177,7 @@ AlsaMixer::Configure(const ConfigBlock &block) static Mixer * alsa_mixer_init(EventLoop &event_loop, gcc_unused AudioOutput &ao, MixerListener &listener, - const ConfigBlock &block, - gcc_unused Error &error) + const ConfigBlock &block) { AlsaMixer *am = new AlsaMixer(event_loop, listener); am->Configure(block); @@ -205,39 +207,26 @@ alsa_mixer_lookup_elem(snd_mixer_t *handle, const char *name, unsigned idx) return nullptr; } -inline bool -AlsaMixer::Setup(Error &error) +inline void +AlsaMixer::Setup() { int err; - if ((err = snd_mixer_attach(handle, device)) < 0) { - error.Format(alsa_mixer_domain, err, - "failed to attach to %s: %s", - device, snd_strerror(err)); - return false; - } + if ((err = snd_mixer_attach(handle, device)) < 0) + throw FormatRuntimeError("failed to attach to %s: %s", + device, snd_strerror(err)); - if ((err = snd_mixer_selem_register(handle, nullptr, - nullptr)) < 0) { - error.Format(alsa_mixer_domain, err, - "snd_mixer_selem_register() failed: %s", - snd_strerror(err)); - return false; - } + if ((err = snd_mixer_selem_register(handle, nullptr, nullptr)) < 0) + throw FormatRuntimeError("snd_mixer_selem_register() failed: %s", + snd_strerror(err)); - if ((err = snd_mixer_load(handle)) < 0) { - error.Format(alsa_mixer_domain, err, - "snd_mixer_load() failed: %s\n", - snd_strerror(err)); - return false; - } + if ((err = snd_mixer_load(handle)) < 0) + throw FormatRuntimeError("snd_mixer_load() failed: %s\n", + snd_strerror(err)); elem = alsa_mixer_lookup_elem(handle, control, index); - if (elem == nullptr) { - error.Format(alsa_mixer_domain, 0, - "no such mixer control: %s", control); - return false; - } + if (elem == nullptr) + throw FormatRuntimeError("no such mixer control: %s", control); snd_mixer_selem_get_playback_volume_range(elem, &volume_min, &volume_max); @@ -246,33 +235,29 @@ AlsaMixer::Setup(Error &error) snd_mixer_elem_set_callback(elem, alsa_mixer_elem_callback); monitor = new AlsaMixerMonitor(event_loop, handle); - - return true; } -inline bool -AlsaMixer::Open(Error &error) +void +AlsaMixer::Open() { int err; volume_set = -1; err = snd_mixer_open(&handle, 0); - if (err < 0) { - error.Format(alsa_mixer_domain, err, - "snd_mixer_open() failed: %s", snd_strerror(err)); - return false; - } + if (err < 0) + throw FormatRuntimeError("snd_mixer_open() failed: %s", + snd_strerror(err)); - if (!Setup(error)) { + try { + Setup(); + } catch (...) { snd_mixer_close(handle); - return false; + throw; } - - return true; } -inline void +void AlsaMixer::Close() { assert(handle != nullptr); @@ -283,8 +268,8 @@ AlsaMixer::Close() snd_mixer_close(handle); } -inline int -AlsaMixer::GetVolume(Error &error) +int +AlsaMixer::GetVolume() { int err; int ret; @@ -293,22 +278,16 @@ AlsaMixer::GetVolume(Error &error) assert(handle != nullptr); err = snd_mixer_handle_events(handle); - if (err < 0) { - error.Format(alsa_mixer_domain, err, - "snd_mixer_handle_events() failed: %s", - snd_strerror(err)); - return false; - } + if (err < 0) + throw FormatRuntimeError("snd_mixer_handle_events() failed: %s", + snd_strerror(err)); err = snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, &level); - if (err < 0) { - error.Format(alsa_mixer_domain, err, - "failed to read ALSA volume: %s", - snd_strerror(err)); - return false; - } + if (err < 0) + throw FormatRuntimeError("failed to read ALSA volume: %s", + snd_strerror(err)); ret = ((volume_set / 100.0) * (volume_max - volume_min) + volume_min) + 0.5; @@ -322,8 +301,8 @@ AlsaMixer::GetVolume(Error &error) return ret; } -inline bool -AlsaMixer::SetVolume(unsigned volume, Error &error) +void +AlsaMixer::SetVolume(unsigned volume) { float vol; long level; @@ -340,14 +319,9 @@ AlsaMixer::SetVolume(unsigned volume, Error &error) level = Clamp(level, volume_min, volume_max); err = snd_mixer_selem_set_playback_volume_all(elem, level); - if (err < 0) { - error.Format(alsa_mixer_domain, err, - "failed to set ALSA volume: %s", - snd_strerror(err)); - return false; - } - - return true; + if (err < 0) + throw FormatRuntimeError("failed to set ALSA volume: %s", + snd_strerror(err)); } const MixerPlugin alsa_mixer_plugin = { diff --git a/src/mixer/plugins/NullMixerPlugin.cxx b/src/mixer/plugins/NullMixerPlugin.cxx index 14c1b57d6..4dee37560 100644 --- a/src/mixer/plugins/NullMixerPlugin.cxx +++ b/src/mixer/plugins/NullMixerPlugin.cxx @@ -34,20 +34,18 @@ public: } /* virtual methods from class Mixer */ - bool Open(gcc_unused Error &error) override { - return true; + void Open() override { } void Close() override { } - int GetVolume(gcc_unused Error &error) override { + int GetVolume() override { return volume; } - bool SetVolume(unsigned _volume, gcc_unused Error &error) override { + void SetVolume(unsigned _volume) override { volume = _volume; - return true; } }; @@ -55,8 +53,7 @@ static Mixer * null_mixer_init(gcc_unused EventLoop &event_loop, gcc_unused AudioOutput &ao, MixerListener &listener, - gcc_unused const ConfigBlock &block, - gcc_unused Error &error) + gcc_unused const ConfigBlock &block) { return new NullMixer(listener); } diff --git a/src/mixer/plugins/OssMixerPlugin.cxx b/src/mixer/plugins/OssMixerPlugin.cxx index 4425e6fe8..b463c4563 100644 --- a/src/mixer/plugins/OssMixerPlugin.cxx +++ b/src/mixer/plugins/OssMixerPlugin.cxx @@ -21,9 +21,10 @@ #include "mixer/MixerInternal.hxx" #include "config/Block.hxx" #include "system/fd_util.h" +#include "system/Error.hxx" #include "util/ASCII.hxx" -#include "util/Error.hxx" #include "util/Domain.hxx" +#include "util/RuntimeError.hxx" #include "Log.hxx" #include @@ -49,16 +50,18 @@ class OssMixer final : public Mixer { int volume_control; public: - OssMixer(MixerListener &_listener) - :Mixer(oss_mixer_plugin, _listener) {} + OssMixer(MixerListener &_listener, const ConfigBlock &block) + :Mixer(oss_mixer_plugin, _listener) { + Configure(block); + } - bool Configure(const ConfigBlock &block, Error &error); + void Configure(const ConfigBlock &block); /* virtual methods from class Mixer */ - virtual bool Open(Error &error) override; - virtual void Close() override; - virtual int GetVolume(Error &error) override; - virtual bool SetVolume(unsigned volume, Error &error) override; + void Open() override; + void Close() override; + int GetVolume() override; + void SetVolume(unsigned volume) override; }; static constexpr Domain oss_mixer_domain("oss_mixer"); @@ -78,39 +81,27 @@ oss_find_mixer(const char *name) return -1; } -inline bool -OssMixer::Configure(const ConfigBlock &block, Error &error) +inline void +OssMixer::Configure(const ConfigBlock &block) { device = block.GetBlockValue("mixer_device", VOLUME_MIXER_OSS_DEFAULT); control = block.GetBlockValue("mixer_control"); if (control != NULL) { volume_control = oss_find_mixer(control); - if (volume_control < 0) { - error.Format(oss_mixer_domain, 0, - "no such mixer control: %s", control); - return false; - } + if (volume_control < 0) + throw FormatRuntimeError("no such mixer control: %s", + control); } else volume_control = SOUND_MIXER_PCM; - - return true; } static Mixer * oss_mixer_init(gcc_unused EventLoop &event_loop, gcc_unused AudioOutput &ao, MixerListener &listener, - const ConfigBlock &block, - Error &error) + const ConfigBlock &block) { - OssMixer *om = new OssMixer(listener); - - if (!om->Configure(block, error)) { - delete om; - return nullptr; - } - - return om; + return new OssMixer(listener, block); } void @@ -121,38 +112,32 @@ OssMixer::Close() close(device_fd); } -bool -OssMixer::Open(Error &error) +void +OssMixer::Open() { device_fd = open_cloexec(device, O_RDONLY, 0); - if (device_fd < 0) { - error.FormatErrno("failed to open %s", device); - return false; - } + if (device_fd < 0) + throw FormatErrno("failed to open %s", device); - if (control) { - int devmask = 0; + try { + if (control) { + int devmask = 0; - if (ioctl(device_fd, SOUND_MIXER_READ_DEVMASK, &devmask) < 0) { - error.SetErrno("READ_DEVMASK failed"); - Close(); - return false; - } - - if (((1 << volume_control) & devmask) == 0) { - error.Format(oss_mixer_domain, 0, - "mixer control \"%s\" not usable", - control); - Close(); - return false; + if (ioctl(device_fd, SOUND_MIXER_READ_DEVMASK, &devmask) < 0) + throw MakeErrno("READ_DEVMASK failed"); + + if (((1 << volume_control) & devmask) == 0) + throw FormatErrno("mixer control \"%s\" not usable", + control); } + } catch (...) { + Close(); + throw; } - - return true; } int -OssMixer::GetVolume(Error &error) +OssMixer::GetVolume() { int left, right, level; int ret; @@ -160,10 +145,8 @@ OssMixer::GetVolume(Error &error) assert(device_fd >= 0); ret = ioctl(device_fd, MIXER_READ(volume_control), &level); - if (ret < 0) { - error.SetErrno("failed to read OSS volume"); - return false; - } + if (ret < 0) + throw MakeErrno("failed to read OSS volume"); left = level & 0xff; right = (level & 0xff00) >> 8; @@ -177,24 +160,18 @@ OssMixer::GetVolume(Error &error) return left; } -bool -OssMixer::SetVolume(unsigned volume, Error &error) +void +OssMixer::SetVolume(unsigned volume) { int level; - int ret; assert(device_fd >= 0); assert(volume <= 100); level = (volume << 8) + volume; - ret = ioctl(device_fd, MIXER_WRITE(volume_control), &level); - if (ret < 0) { - error.SetErrno("failed to set OSS volume"); - return false; - } - - return true; + if (ioctl(device_fd, MIXER_WRITE(volume_control), &level) < 0) + throw MakeErrno("failed to set OSS volume"); } const MixerPlugin oss_mixer_plugin = { diff --git a/src/mixer/plugins/PulseMixerPlugin.cxx b/src/mixer/plugins/PulseMixerPlugin.cxx index efdcf43fd..ed9c93b9d 100644 --- a/src/mixer/plugins/PulseMixerPlugin.cxx +++ b/src/mixer/plugins/PulseMixerPlugin.cxx @@ -25,13 +25,14 @@ #include "mixer/MixerInternal.hxx" #include "mixer/Listener.hxx" #include "output/plugins/PulseOutputPlugin.hxx" -#include "util/Error.hxx" #include #include #include #include +#include + #include class PulseMixer final : public Mixer { @@ -52,18 +53,17 @@ public: void Offline(); void VolumeCallback(const pa_sink_input_info *i, int eol); void Update(pa_context *context, pa_stream *stream); - int GetVolumeInternal(Error &error); + int GetVolumeInternal(); /* virtual methods from class Mixer */ - bool Open(gcc_unused Error &error) override { - return true; + void Open() override { } void Close() override { } - int GetVolume(Error &error) override; - bool SetVolume(unsigned volume, Error &error) override; + int GetVolume() override; + void SetVolume(unsigned volume) override; }; void @@ -91,7 +91,7 @@ PulseMixer::VolumeCallback(const pa_sink_input_info *i, int eol) online = true; volume = i->volume; - listener.OnMixerVolumeChanged(*this, GetVolumeInternal(IgnoreError())); + listener.OnMixerVolumeChanged(*this, GetVolumeInternal()); } /** @@ -163,8 +163,7 @@ pulse_mixer_on_change(PulseMixer &pm, static Mixer * pulse_mixer_init(gcc_unused EventLoop &event_loop, AudioOutput &ao, MixerListener &listener, - gcc_unused const ConfigBlock &block, - gcc_unused Error &error) + gcc_unused const ConfigBlock &block) { PulseOutput &po = (PulseOutput &)ao; PulseMixer *pm = new PulseMixer(po, listener); @@ -180,42 +179,37 @@ PulseMixer::~PulseMixer() } int -PulseMixer::GetVolume(gcc_unused Error &error) +PulseMixer::GetVolume() { Pulse::LockGuard lock(pulse_output_get_mainloop(output)); - return GetVolumeInternal(error); + return GetVolumeInternal(); } /** * Pulse mainloop lock must be held by caller */ int -PulseMixer::GetVolumeInternal(gcc_unused Error &error) +PulseMixer::GetVolumeInternal() { return online ? (int)((100 * (pa_cvolume_avg(&volume) + 1)) / PA_VOLUME_NORM) : -1; } -bool -PulseMixer::SetVolume(unsigned new_volume, Error &error) +void +PulseMixer::SetVolume(unsigned new_volume) { Pulse::LockGuard lock(pulse_output_get_mainloop(output)); - if (!online) { - error.Set(pulse_domain, "disconnected"); - return false; - } + if (!online) + throw std::runtime_error("disconnected"); struct pa_cvolume cvolume; pa_cvolume_set(&cvolume, volume.channels, (new_volume * PA_VOLUME_NORM + 50) / 100); - bool success = pulse_output_set_volume(output, &cvolume, error); - if (success) - volume = cvolume; - - return success; + pulse_output_set_volume(output, &cvolume); + volume = cvolume; } const MixerPlugin pulse_mixer_plugin = { diff --git a/src/mixer/plugins/RoarMixerPlugin.cxx b/src/mixer/plugins/RoarMixerPlugin.cxx index e7bff4baa..198cce1b4 100644 --- a/src/mixer/plugins/RoarMixerPlugin.cxx +++ b/src/mixer/plugins/RoarMixerPlugin.cxx @@ -34,36 +34,34 @@ public: self(_output) {} /* virtual methods from class Mixer */ - virtual bool Open(gcc_unused Error &error) override { - return true; + void Open() override { } virtual void Close() override { } - virtual int GetVolume(Error &error) override; - virtual bool SetVolume(unsigned volume, Error &error) override; + int GetVolume() override; + void SetVolume(unsigned volume) override; }; static Mixer * roar_mixer_init(gcc_unused EventLoop &event_loop, AudioOutput &ao, MixerListener &listener, - gcc_unused const ConfigBlock &block, - gcc_unused Error &error) + gcc_unused const ConfigBlock &block) { return new RoarMixer((RoarOutput &)ao, listener); } int -RoarMixer::GetVolume(gcc_unused Error &error) +RoarMixer::GetVolume() { return roar_output_get_volume(self); } -bool -RoarMixer::SetVolume(unsigned volume, gcc_unused Error &error) +void +RoarMixer::SetVolume(unsigned volume) { - return roar_output_set_volume(self, volume); + roar_output_set_volume(self, volume); } const MixerPlugin roar_mixer_plugin = { diff --git a/src/mixer/plugins/SoftwareMixerPlugin.cxx b/src/mixer/plugins/SoftwareMixerPlugin.cxx index ddda07b70..fbb2b3cd0 100644 --- a/src/mixer/plugins/SoftwareMixerPlugin.cxx +++ b/src/mixer/plugins/SoftwareMixerPlugin.cxx @@ -26,7 +26,6 @@ #include "filter/plugins/VolumeFilterPlugin.hxx" #include "pcm/Volume.hxx" #include "config/Block.hxx" -#include "util/Error.hxx" #include #include @@ -48,26 +47,24 @@ public: void SetFilter(Filter *_filter); /* virtual methods from class Mixer */ - virtual bool Open(gcc_unused Error &error) override { - return true; + void Open() override { } virtual void Close() override { } - virtual int GetVolume(gcc_unused Error &error) override { + int GetVolume() override { return volume; } - virtual bool SetVolume(unsigned volume, Error &error) override; + void SetVolume(unsigned volume) override; }; static Mixer * software_mixer_init(gcc_unused EventLoop &event_loop, gcc_unused AudioOutput &ao, MixerListener &listener, - gcc_unused const ConfigBlock &block, - gcc_unused Error &error) + gcc_unused const ConfigBlock &block) { return new SoftwareMixer(listener); } @@ -87,8 +84,8 @@ PercentVolumeToSoftwareVolume(unsigned volume) return 0; } -bool -SoftwareMixer::SetVolume(unsigned new_volume, gcc_unused Error &error) +void +SoftwareMixer::SetVolume(unsigned new_volume) { assert(new_volume <= 100); @@ -96,7 +93,6 @@ SoftwareMixer::SetVolume(unsigned new_volume, gcc_unused Error &error) if (filter != nullptr) volume_filter_set(filter, PercentVolumeToSoftwareVolume(new_volume)); - return true; } const MixerPlugin software_mixer_plugin = { diff --git a/src/mixer/plugins/WinmmMixerPlugin.cxx b/src/mixer/plugins/WinmmMixerPlugin.cxx index 794003bca..221627ab2 100644 --- a/src/mixer/plugins/WinmmMixerPlugin.cxx +++ b/src/mixer/plugins/WinmmMixerPlugin.cxx @@ -21,11 +21,11 @@ #include "mixer/MixerInternal.hxx" #include "output/OutputAPI.hxx" #include "output/plugins/WinmmOutputPlugin.hxx" -#include "util/Error.hxx" -#include "util/Domain.hxx" #include +#include + #include #include #include @@ -40,19 +40,16 @@ public: } /* virtual methods from class Mixer */ - virtual bool Open(gcc_unused Error &error) override { - return true; + void Open() override { } - virtual void Close() override { + void Close() override { } - virtual int GetVolume(Error &error) override; - virtual bool SetVolume(unsigned volume, Error &error) override; + int GetVolume() override; + void SetVolume(unsigned volume) override; }; -static constexpr Domain winmm_mixer_domain("winmm_mixer"); - static inline int winmm_volume_decode(DWORD volume) { @@ -69,40 +66,33 @@ winmm_volume_encode(int volume) static Mixer * winmm_mixer_init(gcc_unused EventLoop &event_loop, AudioOutput &ao, MixerListener &listener, - gcc_unused const ConfigBlock &block, - gcc_unused Error &error) + gcc_unused const ConfigBlock &block) { return new WinmmMixer((WinmmOutput &)ao, listener); } int -WinmmMixer::GetVolume(Error &error) +WinmmMixer::GetVolume() { DWORD volume; HWAVEOUT handle = winmm_output_get_handle(output); MMRESULT result = waveOutGetVolume(handle, &volume); - if (result != MMSYSERR_NOERROR) { - error.Set(winmm_mixer_domain, "Failed to get winmm volume"); - return -1; - } + if (result != MMSYSERR_NOERROR) + throw std::runtime_error("Failed to get winmm volume"); return winmm_volume_decode(volume); } -bool -WinmmMixer::SetVolume(unsigned volume, Error &error) +void +WinmmMixer::SetVolume(unsigned volume) { DWORD value = winmm_volume_encode(volume); HWAVEOUT handle = winmm_output_get_handle(output); MMRESULT result = waveOutSetVolume(handle, value); - if (result != MMSYSERR_NOERROR) { - error.Set(winmm_mixer_domain, "Failed to set winmm volume"); - return false; - } - - return true; + if (result != MMSYSERR_NOERROR) + throw std::runtime_error("Failed to set winmm volume"); } const MixerPlugin winmm_mixer_plugin = { diff --git a/src/output/Init.cxx b/src/output/Init.cxx index b592c8c01..225cb7a14 100644 --- a/src/output/Init.cxx +++ b/src/output/Init.cxx @@ -115,8 +115,7 @@ audio_output_load_mixer(EventLoop &event_loop, AudioOutput &ao, const ConfigBlock &block, const MixerPlugin *plugin, PreparedFilter &filter_chain, - MixerListener &listener, - Error &error) + MixerListener &listener) { Mixer *mixer; @@ -127,20 +126,19 @@ audio_output_load_mixer(EventLoop &event_loop, AudioOutput &ao, case MixerType::NULL_: return mixer_new(event_loop, null_mixer_plugin, ao, listener, - block, error); + block); case MixerType::HARDWARE: if (plugin == nullptr) return nullptr; return mixer_new(event_loop, *plugin, ao, listener, - block, error); + block); case MixerType::SOFTWARE: mixer = mixer_new(event_loop, software_mixer_plugin, ao, listener, - ConfigBlock(), - IgnoreError()); + ConfigBlock()); assert(mixer != nullptr); filter_chain_append(filter_chain, "software_mixer", @@ -246,16 +244,16 @@ audio_output_setup(EventLoop &event_loop, AudioOutput &ao, /* set up the mixer */ - Error mixer_error; - ao.mixer = audio_output_load_mixer(event_loop, ao, block, - ao.plugin.mixer_plugin, - *ao.prepared_filter, - mixer_listener, - mixer_error); - if (ao.mixer == nullptr && mixer_error.IsDefined()) - FormatError(mixer_error, + try { + ao.mixer = audio_output_load_mixer(event_loop, ao, block, + ao.plugin.mixer_plugin, + *ao.prepared_filter, + mixer_listener); + } catch (const std::runtime_error &e) { + FormatError(e, "Failed to initialize hardware mixer for '%s'", ao.name); + } /* use the hardware mixer for replay gain? */ diff --git a/src/output/OutputControl.cxx b/src/output/OutputControl.cxx index 090db35d9..4b90333f8 100644 --- a/src/output/OutputControl.cxx +++ b/src/output/OutputControl.cxx @@ -27,6 +27,8 @@ #include "util/Error.hxx" #include "Log.hxx" +#include + #include /** after a failure, wait this number of seconds before @@ -145,10 +147,11 @@ AudioOutput::Open(const AudioFormat audio_format, const MusicPipe &mp) const bool open2 = open; if (open2 && mixer != nullptr) { - Error error; - if (!mixer_open(mixer, error)) - FormatWarning(output_domain, - "Failed to open mixer for '%s'", name); + try { + mixer_open(mixer); + } catch (const std::runtime_error &e) { + FormatError(e, "Failed to open mixer for '%s'", name); + } } return open2; diff --git a/src/output/plugins/PulseOutputPlugin.cxx b/src/output/plugins/PulseOutputPlugin.cxx index 748eff636..d8b0003e8 100644 --- a/src/output/plugins/PulseOutputPlugin.cxx +++ b/src/output/plugins/PulseOutputPlugin.cxx @@ -37,6 +37,8 @@ #include #include +#include + #include #include #include @@ -74,7 +76,7 @@ public: mixer = nullptr; } - bool SetVolume(const pa_cvolume &volume, Error &error); + void SetVolume(const pa_cvolume &volume); struct pa_threaded_mainloop *GetMainloop() { return mainloop; @@ -217,34 +219,27 @@ pulse_output_clear_mixer(PulseOutput &po, PulseMixer &pm) po.ClearMixer(pm); } -inline bool -PulseOutput::SetVolume(const pa_cvolume &volume, Error &error) +inline void +PulseOutput::SetVolume(const pa_cvolume &volume) { if (context == nullptr || stream == nullptr || - pa_stream_get_state(stream) != PA_STREAM_READY) { - error.Set(pulse_domain, "disconnected"); - return false; - } + pa_stream_get_state(stream) != PA_STREAM_READY) + throw std::runtime_error("disconnected"); pa_operation *o = pa_context_set_sink_input_volume(context, pa_stream_get_index(stream), &volume, nullptr, nullptr); - if (o == nullptr) { - SetPulseError(error, context, - "failed to set PulseAudio volume"); - return false; - } + if (o == nullptr) + throw std::runtime_error("failed to set PulseAudio volume"); pa_operation_unref(o); - return true; } -bool -pulse_output_set_volume(PulseOutput &po, const pa_cvolume *volume, - Error &error) +void +pulse_output_set_volume(PulseOutput &po, const pa_cvolume *volume) { - return po.SetVolume(*volume, error); + return po.SetVolume(*volume); } /** diff --git a/src/output/plugins/PulseOutputPlugin.hxx b/src/output/plugins/PulseOutputPlugin.hxx index c25371b0e..c80ff85e3 100644 --- a/src/output/plugins/PulseOutputPlugin.hxx +++ b/src/output/plugins/PulseOutputPlugin.hxx @@ -36,8 +36,7 @@ pulse_output_set_mixer(PulseOutput &po, PulseMixer &pm); void pulse_output_clear_mixer(PulseOutput &po, PulseMixer &pm); -bool -pulse_output_set_volume(PulseOutput &po, - const pa_cvolume *volume, Error &error); +void +pulse_output_set_volume(PulseOutput &po, const pa_cvolume *volume); #endif diff --git a/src/output/plugins/RoarOutputPlugin.cxx b/src/output/plugins/RoarOutputPlugin.cxx index 7ed0e95ac..072c29a6b 100644 --- a/src/output/plugins/RoarOutputPlugin.cxx +++ b/src/output/plugins/RoarOutputPlugin.cxx @@ -29,6 +29,7 @@ #include "Log.hxx" #include +#include /* libroar/services.h declares roar_service_stream::new - work around this C++ problem */ @@ -74,7 +75,7 @@ public: void Cancel(); int GetVolume() const; - bool SetVolume(unsigned volume); + void SetVolume(unsigned volume); }; static constexpr Domain roar_output_domain("roar_output"); @@ -90,7 +91,7 @@ RoarOutput::GetVolume() const float l, r; int error; if (roar_vs_volume_get(vss, &l, &r, &error) < 0) - return -1; + throw std::runtime_error(roar_vs_strerr(error)); return (l + r) * 50; } @@ -101,26 +102,26 @@ roar_output_get_volume(RoarOutput &roar) return roar.GetVolume(); } -bool +inline void RoarOutput::SetVolume(unsigned volume) { assert(volume <= 100); const ScopeLock protect(mutex); if (vss == nullptr || !alive) - return false; + throw std::runtime_error("closed"); int error; float level = volume / 100.0; - roar_vs_volume_mono(vss, level, &error); - return true; + if (roar_vs_volume_mono(vss, level, &error) < 0) + throw std::runtime_error(roar_vs_strerr(error)); } -bool +void roar_output_set_volume(RoarOutput &roar, unsigned volume) { - return roar.SetVolume(volume); + roar.SetVolume(volume); } inline void diff --git a/src/output/plugins/RoarOutputPlugin.hxx b/src/output/plugins/RoarOutputPlugin.hxx index 6478f65f7..caf9ec373 100644 --- a/src/output/plugins/RoarOutputPlugin.hxx +++ b/src/output/plugins/RoarOutputPlugin.hxx @@ -27,7 +27,7 @@ extern const struct AudioOutputPlugin roar_output_plugin; int roar_output_get_volume(RoarOutput &roar); -bool +void roar_output_set_volume(RoarOutput &roar, unsigned volume); #endif diff --git a/test/read_mixer.cxx b/test/read_mixer.cxx index 44e3f6b0d..ce45e863f 100644 --- a/test/read_mixer.cxx +++ b/test/read_mixer.cxx @@ -41,7 +41,7 @@ filter_plugin_by_name(gcc_unused const char *name) } int main(int argc, gcc_unused char **argv) -{ +try { int volume; if (argc != 2) { @@ -51,36 +51,27 @@ int main(int argc, gcc_unused char **argv) EventLoop event_loop; - Error error; Mixer *mixer = mixer_new(event_loop, alsa_mixer_plugin, *(AudioOutput *)nullptr, *(MixerListener *)nullptr, - ConfigBlock(), error); - if (mixer == NULL) { - LogError(error, "mixer_new() failed"); - return EXIT_FAILURE; - } + ConfigBlock()); - if (!mixer_open(mixer, error)) { - mixer_free(mixer); - LogError(error, "failed to open the mixer"); - return EXIT_FAILURE; - } + mixer_open(mixer); - volume = mixer_get_volume(mixer, error); + volume = mixer_get_volume(mixer); mixer_close(mixer); mixer_free(mixer); assert(volume >= -1 && volume <= 100); if (volume < 0) { - if (error.IsDefined()) { - LogError(error, "failed to read volume"); - } else - fprintf(stderr, "failed to read volume\n"); + fprintf(stderr, "failed to read volume\n"); return EXIT_FAILURE; } printf("%d\n", volume); return 0; +} catch (const std::exception &e) { + LogError(e); + return EXIT_FAILURE; } diff --git a/test/run_filter.cxx b/test/run_filter.cxx index f920008aa..91f29ac8e 100644 --- a/test/run_filter.cxx +++ b/test/run_filter.cxx @@ -41,11 +41,10 @@ #include #include -bool +void mixer_set_volume(gcc_unused Mixer *mixer, - gcc_unused unsigned volume, gcc_unused Error &error) + gcc_unused unsigned volume) { - return true; } static PreparedFilter *