output/ao: migrate from class Error to C++ exceptions

This commit is contained in:
Max Kellermann 2016-11-02 12:36:13 +01:00
parent 6ead9750f4
commit 65e6755b8b

View File

@ -20,9 +20,10 @@
#include "config.h" #include "config.h"
#include "AoOutputPlugin.hxx" #include "AoOutputPlugin.hxx"
#include "../OutputAPI.hxx" #include "../OutputAPI.hxx"
#include "system/Error.hxx"
#include "util/DivideString.hxx" #include "util/DivideString.hxx"
#include "util/SplitString.hxx" #include "util/SplitString.hxx"
#include "util/Error.hxx" #include "util/RuntimeError.hxx"
#include "util/Domain.hxx" #include "util/Domain.hxx"
#include "Log.hxx" #include "Log.hxx"
@ -38,27 +39,21 @@ static unsigned ao_output_ref;
struct AoOutput { struct AoOutput {
AudioOutput base; AudioOutput base;
size_t write_size; const size_t write_size;
int driver; int driver;
ao_option *options; ao_option *options = nullptr;
ao_device *device; ao_device *device;
AoOutput() AoOutput(const ConfigBlock &block);
:base(ao_output_plugin) {}
bool Initialize(const ConfigBlock &block, Error &error) {
return base.Configure(block, error);
}
bool Configure(const ConfigBlock &block, Error &error);
}; };
static constexpr Domain ao_output_domain("ao_output"); static constexpr Domain ao_output_domain("ao_output");
static void
ao_output_error(Error &error_r) static std::system_error
MakeAoError()
{ {
const char *error; const char *error = "Unknown libao failure";
switch (errno) { switch (errno) {
case AO_ENODRIVER: case AO_ENODRIVER:
@ -80,47 +75,33 @@ ao_output_error(Error &error_r)
case AO_EFAIL: case AO_EFAIL:
error = "Generic libao failure"; error = "Generic libao failure";
break; break;
default:
error_r.SetErrno();
return;
} }
error_r.Set(ao_output_domain, errno, error); return MakeErrno(errno, error);
} }
inline bool AoOutput::AoOutput(const ConfigBlock &block)
AoOutput::Configure(const ConfigBlock &block, Error &error) :base(ao_output_plugin, block),
write_size(block.GetBlockValue("write_size", 1024u))
{ {
const char *value;
options = nullptr;
write_size = block.GetBlockValue("write_size", 1024u);
if (ao_output_ref == 0) { if (ao_output_ref == 0) {
ao_initialize(); ao_initialize();
} }
ao_output_ref++; ao_output_ref++;
value = block.GetBlockValue("driver", "default"); const char *value = block.GetBlockValue("driver", "default");
if (0 == strcmp(value, "default")) if (0 == strcmp(value, "default"))
driver = ao_default_driver_id(); driver = ao_default_driver_id();
else else
driver = ao_driver_id(value); driver = ao_driver_id(value);
if (driver < 0) { if (driver < 0)
error.Format(ao_output_domain, throw FormatRuntimeError("\"%s\" is not a valid ao driver",
"\"%s\" is not a valid ao driver",
value); value);
return false;
}
ao_info *ai = ao_driver_info(driver); ao_info *ai = ao_driver_info(driver);
if (ai == nullptr) { if (ai == nullptr)
error.Set(ao_output_domain, "problems getting driver info"); throw std::runtime_error("problems getting driver info");
return false;
}
FormatDebug(ao_output_domain, "using ao driver \"%s\" for \"%s\"\n", FormatDebug(ao_output_domain, "using ao driver \"%s\" for \"%s\"\n",
ai->short_name, block.GetBlockValue("name", nullptr)); ai->short_name, block.GetBlockValue("name", nullptr));
@ -130,36 +111,19 @@ AoOutput::Configure(const ConfigBlock &block, Error &error)
for (const auto &i : SplitString(value, ';')) { for (const auto &i : SplitString(value, ';')) {
const DivideString ss(i.c_str(), '=', true); const DivideString ss(i.c_str(), '=', true);
if (!ss.IsDefined()) { if (!ss.IsDefined())
error.Format(ao_output_domain, throw FormatRuntimeError("problems parsing options \"%s\"",
"problems parsing options \"%s\"",
i.c_str()); i.c_str());
return false;
}
ao_append_option(&options, ss.GetFirst(), ss.GetSecond()); ao_append_option(&options, ss.GetFirst(), ss.GetSecond());
} }
} }
return true;
} }
static AudioOutput * static AudioOutput *
ao_output_init(const ConfigBlock &block, Error &error) ao_output_init(const ConfigBlock &block, gcc_unused Error &error)
{ {
AoOutput *ad = new AoOutput(); return &(new AoOutput(block))->base;
if (!ad->Initialize(block, error)) {
delete ad;
return nullptr;
}
if (!ad->Configure(block, error)) {
delete ad;
return nullptr;
}
return &ad->base;
} }
static void static void
@ -186,7 +150,7 @@ ao_output_close(AudioOutput *ao)
static bool static bool
ao_output_open(AudioOutput *ao, AudioFormat &audio_format, ao_output_open(AudioOutput *ao, AudioFormat &audio_format,
Error &error) gcc_unused Error &error)
{ {
ao_sample_format format = OUR_AO_FORMAT_INITIALIZER; ao_sample_format format = OUR_AO_FORMAT_INITIALIZER;
AoOutput *ad = (AoOutput *)ao; AoOutput *ad = (AoOutput *)ao;
@ -215,10 +179,8 @@ ao_output_open(AudioOutput *ao, AudioFormat &audio_format,
ad->device = ao_open_live(ad->driver, &format, ad->options); ad->device = ao_open_live(ad->driver, &format, ad->options);
if (ad->device == nullptr) { if (ad->device == nullptr)
ao_output_error(error); throw MakeAoError();
return false;
}
return true; return true;
} }
@ -242,17 +204,15 @@ static int ao_play_deconst(ao_device *device, const void *output_samples,
static size_t static size_t
ao_output_play(AudioOutput *ao, const void *chunk, size_t size, ao_output_play(AudioOutput *ao, const void *chunk, size_t size,
Error &error) gcc_unused Error &error)
{ {
AoOutput *ad = (AoOutput *)ao; AoOutput *ad = (AoOutput *)ao;
if (size > ad->write_size) if (size > ad->write_size)
size = ad->write_size; size = ad->write_size;
if (ao_play_deconst(ad->device, chunk, size) == 0) { if (ao_play_deconst(ad->device, chunk, size) == 0)
ao_output_error(error); throw MakeAoError();
return 0;
}
return size; return size;
} }