mixer: migrate to C++ exceptions

This commit is contained in:
Max Kellermann
2016-09-09 12:52:51 +02:00
parent ae1eb9ccde
commit e7d327226a
21 changed files with 273 additions and 342 deletions

View File

@@ -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 <algorithm>
@@ -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 = {