output/ao: migrate from class Error to C++ exceptions
This commit is contained in:
parent
6ead9750f4
commit
65e6755b8b
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user