encoder/Plugin: migrate from class Error to C++ exceptions
This commit is contained in:
parent
aead221184
commit
0c343cb1c3
@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
struct AudioFormat;
|
struct AudioFormat;
|
||||||
struct Tag;
|
struct Tag;
|
||||||
|
class Error;
|
||||||
|
|
||||||
class Encoder {
|
class Encoder {
|
||||||
const bool implements_tag;
|
const bool implements_tag;
|
||||||
|
@ -22,27 +22,27 @@
|
|||||||
|
|
||||||
class PreparedEncoder;
|
class PreparedEncoder;
|
||||||
struct ConfigBlock;
|
struct ConfigBlock;
|
||||||
class Error;
|
|
||||||
|
|
||||||
struct EncoderPlugin {
|
struct EncoderPlugin {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
PreparedEncoder *(*init)(const ConfigBlock &block,
|
/**
|
||||||
Error &error);
|
* Throws #std::runtime_error on error.
|
||||||
|
*/
|
||||||
|
PreparedEncoder *(*init)(const ConfigBlock &block);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new encoder object.
|
* Creates a new encoder object.
|
||||||
*
|
*
|
||||||
|
* Throws #std::runtime_error on error.
|
||||||
|
*
|
||||||
* @param plugin the encoder plugin
|
* @param plugin the encoder plugin
|
||||||
* @param error location to store the error occurring, or nullptr to ignore errors.
|
|
||||||
* @return an encoder object on success, nullptr on failure
|
|
||||||
*/
|
*/
|
||||||
static inline PreparedEncoder *
|
static inline PreparedEncoder *
|
||||||
encoder_init(const EncoderPlugin &plugin, const ConfigBlock &block,
|
encoder_init(const EncoderPlugin &plugin, const ConfigBlock &block)
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
return plugin.init(block, error);
|
return plugin.init(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -89,10 +89,10 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
class PreparedFlacEncoder final : public PreparedEncoder {
|
class PreparedFlacEncoder final : public PreparedEncoder {
|
||||||
unsigned compression;
|
const unsigned compression;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool Configure(const ConfigBlock &block, Error &error);
|
PreparedFlacEncoder(const ConfigBlock &block);
|
||||||
|
|
||||||
/* virtual methods from class PreparedEncoder */
|
/* virtual methods from class PreparedEncoder */
|
||||||
Encoder *Open(AudioFormat &audio_format, Error &) override;
|
Encoder *Open(AudioFormat &audio_format, Error &) override;
|
||||||
@ -104,26 +104,15 @@ public:
|
|||||||
|
|
||||||
static constexpr Domain flac_encoder_domain("vorbis_encoder");
|
static constexpr Domain flac_encoder_domain("vorbis_encoder");
|
||||||
|
|
||||||
bool
|
PreparedFlacEncoder::PreparedFlacEncoder(const ConfigBlock &block)
|
||||||
PreparedFlacEncoder::Configure(const ConfigBlock &block, Error &)
|
:compression(block.GetBlockValue("compression", 5u))
|
||||||
{
|
{
|
||||||
compression = block.GetBlockValue("compression", 5u);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PreparedEncoder *
|
static PreparedEncoder *
|
||||||
flac_encoder_init(const ConfigBlock &block, Error &error)
|
flac_encoder_init(const ConfigBlock &block)
|
||||||
{
|
{
|
||||||
auto *encoder = new PreparedFlacEncoder();
|
return new PreparedFlacEncoder(block);
|
||||||
|
|
||||||
/* load configuration from "block" */
|
|
||||||
if (!encoder->Configure(block, error)) {
|
|
||||||
/* configuration has failed, roll back and return error */
|
|
||||||
delete encoder;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return encoder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "config/ConfigError.hxx"
|
#include "config/ConfigError.hxx"
|
||||||
#include "util/NumberParser.hxx"
|
#include "util/NumberParser.hxx"
|
||||||
#include "util/ReusableArray.hxx"
|
#include "util/ReusableArray.hxx"
|
||||||
|
#include "util/RuntimeError.hxx"
|
||||||
#include "util/Error.hxx"
|
#include "util/Error.hxx"
|
||||||
#include "util/Domain.hxx"
|
#include "util/Domain.hxx"
|
||||||
|
|
||||||
@ -58,7 +59,7 @@ class PreparedLameEncoder final : public PreparedEncoder {
|
|||||||
int bitrate;
|
int bitrate;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool Configure(const ConfigBlock &block, Error &error);
|
PreparedLameEncoder(const ConfigBlock &block);
|
||||||
|
|
||||||
/* virtual methods from class PreparedEncoder */
|
/* virtual methods from class PreparedEncoder */
|
||||||
Encoder *Open(AudioFormat &audio_format, Error &) override;
|
Encoder *Open(AudioFormat &audio_format, Error &) override;
|
||||||
@ -70,8 +71,7 @@ public:
|
|||||||
|
|
||||||
static constexpr Domain lame_encoder_domain("lame_encoder");
|
static constexpr Domain lame_encoder_domain("lame_encoder");
|
||||||
|
|
||||||
bool
|
PreparedLameEncoder::PreparedLameEncoder(const ConfigBlock &block)
|
||||||
PreparedLameEncoder::Configure(const ConfigBlock &block, Error &error)
|
|
||||||
{
|
{
|
||||||
const char *value;
|
const char *value;
|
||||||
char *endptr;
|
char *endptr;
|
||||||
@ -82,55 +82,32 @@ PreparedLameEncoder::Configure(const ConfigBlock &block, Error &error)
|
|||||||
|
|
||||||
quality = ParseDouble(value, &endptr);
|
quality = ParseDouble(value, &endptr);
|
||||||
|
|
||||||
if (*endptr != '\0' || quality < -1.0 || quality > 10.0) {
|
if (*endptr != '\0' || quality < -1.0 || quality > 10.0)
|
||||||
error.Format(config_domain,
|
throw FormatRuntimeError("quality \"%s\" is not a number in the "
|
||||||
"quality \"%s\" is not a number in the "
|
"range -1 to 10",
|
||||||
"range -1 to 10",
|
value);
|
||||||
value);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (block.GetBlockValue("bitrate") != nullptr) {
|
if (block.GetBlockValue("bitrate") != nullptr)
|
||||||
error.Set(config_domain,
|
throw std::runtime_error("quality and bitrate are both defined");
|
||||||
"quality and bitrate are both defined");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/* a bit rate was configured */
|
/* a bit rate was configured */
|
||||||
|
|
||||||
value = block.GetBlockValue("bitrate");
|
value = block.GetBlockValue("bitrate");
|
||||||
if (value == nullptr) {
|
if (value == nullptr)
|
||||||
error.Set(config_domain,
|
throw std::runtime_error("neither bitrate nor quality defined");
|
||||||
"neither bitrate nor quality defined");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
quality = -2.0;
|
quality = -2.0;
|
||||||
bitrate = ParseInt(value, &endptr);
|
bitrate = ParseInt(value, &endptr);
|
||||||
|
|
||||||
if (*endptr != '\0' || bitrate <= 0) {
|
if (*endptr != '\0' || bitrate <= 0)
|
||||||
error.Set(config_domain,
|
throw std::runtime_error("bitrate should be a positive integer");
|
||||||
"bitrate should be a positive integer");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PreparedEncoder *
|
static PreparedEncoder *
|
||||||
lame_encoder_init(const ConfigBlock &block, Error &error)
|
lame_encoder_init(const ConfigBlock &block)
|
||||||
{
|
{
|
||||||
auto *encoder = new PreparedLameEncoder();
|
return new PreparedLameEncoder(block);
|
||||||
|
|
||||||
/* load configuration from "block" */
|
|
||||||
if (!encoder->Configure(block, error)) {
|
|
||||||
/* configuration has failed, roll back and return error */
|
|
||||||
delete encoder;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return encoder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -51,8 +51,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
static PreparedEncoder *
|
static PreparedEncoder *
|
||||||
null_encoder_init(gcc_unused const ConfigBlock &block,
|
null_encoder_init(gcc_unused const ConfigBlock &block)
|
||||||
gcc_unused Error &error)
|
|
||||||
{
|
{
|
||||||
return new PreparedNullEncoder();
|
return new PreparedNullEncoder();
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,8 @@
|
|||||||
#include <opus.h>
|
#include <opus.h>
|
||||||
#include <ogg/ogg.h>
|
#include <ogg/ogg.h>
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
@ -78,7 +80,7 @@ class PreparedOpusEncoder final : public PreparedEncoder {
|
|||||||
int signal;
|
int signal;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool Configure(const ConfigBlock &block, Error &error);
|
PreparedOpusEncoder(const ConfigBlock &block);
|
||||||
|
|
||||||
/* virtual methods from class PreparedEncoder */
|
/* virtual methods from class PreparedEncoder */
|
||||||
Encoder *Open(AudioFormat &audio_format, Error &) override;
|
Encoder *Open(AudioFormat &audio_format, Error &) override;
|
||||||
@ -90,8 +92,7 @@ public:
|
|||||||
|
|
||||||
static constexpr Domain opus_encoder_domain("opus_encoder");
|
static constexpr Domain opus_encoder_domain("opus_encoder");
|
||||||
|
|
||||||
bool
|
PreparedOpusEncoder::PreparedOpusEncoder(const ConfigBlock &block)
|
||||||
PreparedOpusEncoder::Configure(const ConfigBlock &block, Error &error)
|
|
||||||
{
|
{
|
||||||
const char *value = block.GetBlockValue("bitrate", "auto");
|
const char *value = block.GetBlockValue("bitrate", "auto");
|
||||||
if (strcmp(value, "auto") == 0)
|
if (strcmp(value, "auto") == 0)
|
||||||
@ -102,17 +103,13 @@ PreparedOpusEncoder::Configure(const ConfigBlock &block, Error &error)
|
|||||||
char *endptr;
|
char *endptr;
|
||||||
bitrate = strtoul(value, &endptr, 10);
|
bitrate = strtoul(value, &endptr, 10);
|
||||||
if (endptr == value || *endptr != 0 ||
|
if (endptr == value || *endptr != 0 ||
|
||||||
bitrate < 500 || bitrate > 512000) {
|
bitrate < 500 || bitrate > 512000)
|
||||||
error.Set(config_domain, "Invalid bit rate");
|
throw std::runtime_error("Invalid bit rate");
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
complexity = block.GetBlockValue("complexity", 10u);
|
complexity = block.GetBlockValue("complexity", 10u);
|
||||||
if (complexity > 10) {
|
if (complexity > 10)
|
||||||
error.Format(config_domain, "Invalid complexity");
|
throw std::runtime_error("Invalid complexity");
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
value = block.GetBlockValue("signal", "auto");
|
value = block.GetBlockValue("signal", "auto");
|
||||||
if (strcmp(value, "auto") == 0)
|
if (strcmp(value, "auto") == 0)
|
||||||
@ -121,27 +118,14 @@ PreparedOpusEncoder::Configure(const ConfigBlock &block, Error &error)
|
|||||||
signal = OPUS_SIGNAL_VOICE;
|
signal = OPUS_SIGNAL_VOICE;
|
||||||
else if (strcmp(value, "music") == 0)
|
else if (strcmp(value, "music") == 0)
|
||||||
signal = OPUS_SIGNAL_MUSIC;
|
signal = OPUS_SIGNAL_MUSIC;
|
||||||
else {
|
else
|
||||||
error.Format(config_domain, "Invalid signal");
|
throw std::runtime_error("Invalid signal");
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PreparedEncoder *
|
static PreparedEncoder *
|
||||||
opus_encoder_init(const ConfigBlock &block, Error &error)
|
opus_encoder_init(const ConfigBlock &block)
|
||||||
{
|
{
|
||||||
auto *encoder = new PreparedOpusEncoder();
|
return new PreparedOpusEncoder(block);
|
||||||
|
|
||||||
/* load configuration from "block" */
|
|
||||||
if (!encoder->Configure(block, error)) {
|
|
||||||
/* configuration has failed, roll back and return error */
|
|
||||||
delete encoder;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return encoder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OpusEncoder::OpusEncoder(AudioFormat &_audio_format, ::OpusEncoder *_enc)
|
OpusEncoder::OpusEncoder(AudioFormat &_audio_format, ::OpusEncoder *_enc)
|
||||||
|
@ -88,7 +88,7 @@ class PreparedShineEncoder final : public PreparedEncoder {
|
|||||||
shine_config_t config;
|
shine_config_t config;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool Configure(const ConfigBlock &block, Error &error);
|
PreparedShineEncoder(const ConfigBlock &block);
|
||||||
|
|
||||||
/* virtual methods from class PreparedEncoder */
|
/* virtual methods from class PreparedEncoder */
|
||||||
Encoder *Open(AudioFormat &audio_format, Error &) override;
|
Encoder *Open(AudioFormat &audio_format, Error &) override;
|
||||||
@ -98,28 +98,16 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool
|
PreparedShineEncoder::PreparedShineEncoder(const ConfigBlock &block)
|
||||||
PreparedShineEncoder::Configure(const ConfigBlock &block, Error &)
|
|
||||||
{
|
{
|
||||||
shine_set_config_mpeg_defaults(&config.mpeg);
|
shine_set_config_mpeg_defaults(&config.mpeg);
|
||||||
config.mpeg.bitr = block.GetBlockValue("bitrate", 128);
|
config.mpeg.bitr = block.GetBlockValue("bitrate", 128);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PreparedEncoder *
|
static PreparedEncoder *
|
||||||
shine_encoder_init(const ConfigBlock &block, Error &error)
|
shine_encoder_init(const ConfigBlock &block)
|
||||||
{
|
{
|
||||||
auto *encoder = new PreparedShineEncoder();
|
return new PreparedShineEncoder(block);
|
||||||
|
|
||||||
/* load configuration from "block" */
|
|
||||||
if (!encoder->Configure(block, error)) {
|
|
||||||
/* configuration has failed, roll back and return error */
|
|
||||||
delete encoder;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return encoder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static shine_t
|
static shine_t
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "AudioFormat.hxx"
|
#include "AudioFormat.hxx"
|
||||||
#include "config/ConfigError.hxx"
|
#include "config/ConfigError.hxx"
|
||||||
#include "util/NumberParser.hxx"
|
#include "util/NumberParser.hxx"
|
||||||
|
#include "util/RuntimeError.hxx"
|
||||||
#include "util/Error.hxx"
|
#include "util/Error.hxx"
|
||||||
#include "util/Domain.hxx"
|
#include "util/Domain.hxx"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
@ -77,7 +78,7 @@ class PreparedTwolameEncoder final : public PreparedEncoder {
|
|||||||
int bitrate;
|
int bitrate;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool Configure(const ConfigBlock &block, Error &error);
|
PreparedTwolameEncoder(const ConfigBlock &block);
|
||||||
|
|
||||||
/* virtual methods from class PreparedEncoder */
|
/* virtual methods from class PreparedEncoder */
|
||||||
Encoder *Open(AudioFormat &audio_format, Error &) override;
|
Encoder *Open(AudioFormat &audio_format, Error &) override;
|
||||||
@ -89,8 +90,7 @@ public:
|
|||||||
|
|
||||||
static constexpr Domain twolame_encoder_domain("twolame_encoder");
|
static constexpr Domain twolame_encoder_domain("twolame_encoder");
|
||||||
|
|
||||||
bool
|
PreparedTwolameEncoder::PreparedTwolameEncoder(const ConfigBlock &block)
|
||||||
PreparedTwolameEncoder::Configure(const ConfigBlock &block, Error &error)
|
|
||||||
{
|
{
|
||||||
const char *value;
|
const char *value;
|
||||||
char *endptr;
|
char *endptr;
|
||||||
@ -101,58 +101,35 @@ PreparedTwolameEncoder::Configure(const ConfigBlock &block, Error &error)
|
|||||||
|
|
||||||
quality = ParseDouble(value, &endptr);
|
quality = ParseDouble(value, &endptr);
|
||||||
|
|
||||||
if (*endptr != '\0' || quality < -1.0 || quality > 10.0) {
|
if (*endptr != '\0' || quality < -1.0 || quality > 10.0)
|
||||||
error.Format(config_domain,
|
throw FormatRuntimeError("quality \"%s\" is not a number in the "
|
||||||
"quality \"%s\" is not a number in the "
|
"range -1 to 10",
|
||||||
"range -1 to 10",
|
value);
|
||||||
value);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (block.GetBlockValue("bitrate") != nullptr) {
|
if (block.GetBlockValue("bitrate") != nullptr)
|
||||||
error.Set(config_domain,
|
throw std::runtime_error("quality and bitrate are both defined");
|
||||||
"quality and bitrate are both defined");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/* a bit rate was configured */
|
/* a bit rate was configured */
|
||||||
|
|
||||||
value = block.GetBlockValue("bitrate");
|
value = block.GetBlockValue("bitrate");
|
||||||
if (value == nullptr) {
|
if (value == nullptr)
|
||||||
error.Set(config_domain,
|
throw std::runtime_error("neither bitrate nor quality defined");
|
||||||
"neither bitrate nor quality defined");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
quality = -2.0;
|
quality = -2.0;
|
||||||
bitrate = ParseInt(value, &endptr);
|
bitrate = ParseInt(value, &endptr);
|
||||||
|
|
||||||
if (*endptr != '\0' || bitrate <= 0) {
|
if (*endptr != '\0' || bitrate <= 0)
|
||||||
error.Set(config_domain,
|
throw std::runtime_error("bitrate should be a positive integer");
|
||||||
"bitrate should be a positive integer");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PreparedEncoder *
|
static PreparedEncoder *
|
||||||
twolame_encoder_init(const ConfigBlock &block, Error &error_r)
|
twolame_encoder_init(const ConfigBlock &block)
|
||||||
{
|
{
|
||||||
FormatDebug(twolame_encoder_domain,
|
FormatDebug(twolame_encoder_domain,
|
||||||
"libtwolame version %s", get_twolame_version());
|
"libtwolame version %s", get_twolame_version());
|
||||||
|
|
||||||
auto *encoder = new PreparedTwolameEncoder();
|
return new PreparedTwolameEncoder(block);
|
||||||
|
|
||||||
/* load configuration from "block" */
|
|
||||||
if (!encoder->Configure(block, error_r)) {
|
|
||||||
/* configuration has failed, roll back and return error */
|
|
||||||
delete encoder;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return encoder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include "config/ConfigError.hxx"
|
#include "config/ConfigError.hxx"
|
||||||
#include "util/StringUtil.hxx"
|
#include "util/StringUtil.hxx"
|
||||||
#include "util/NumberParser.hxx"
|
#include "util/NumberParser.hxx"
|
||||||
|
#include "util/RuntimeError.hxx"
|
||||||
#include "util/Error.hxx"
|
#include "util/Error.hxx"
|
||||||
#include "util/Domain.hxx"
|
#include "util/Domain.hxx"
|
||||||
|
|
||||||
@ -73,7 +74,7 @@ class PreparedVorbisEncoder final : public PreparedEncoder {
|
|||||||
int bitrate;
|
int bitrate;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool Configure(const ConfigBlock &block, Error &error);
|
PreparedVorbisEncoder(const ConfigBlock &block);
|
||||||
|
|
||||||
/* virtual methods from class PreparedEncoder */
|
/* virtual methods from class PreparedEncoder */
|
||||||
Encoder *Open(AudioFormat &audio_format, Error &) override;
|
Encoder *Open(AudioFormat &audio_format, Error &) override;
|
||||||
@ -85,8 +86,7 @@ public:
|
|||||||
|
|
||||||
static constexpr Domain vorbis_encoder_domain("vorbis_encoder");
|
static constexpr Domain vorbis_encoder_domain("vorbis_encoder");
|
||||||
|
|
||||||
bool
|
PreparedVorbisEncoder::PreparedVorbisEncoder(const ConfigBlock &block)
|
||||||
PreparedVorbisEncoder::Configure(const ConfigBlock &block, Error &error)
|
|
||||||
{
|
{
|
||||||
const char *value = block.GetBlockValue("quality");
|
const char *value = block.GetBlockValue("quality");
|
||||||
if (value != nullptr) {
|
if (value != nullptr) {
|
||||||
@ -95,56 +95,33 @@ PreparedVorbisEncoder::Configure(const ConfigBlock &block, Error &error)
|
|||||||
char *endptr;
|
char *endptr;
|
||||||
quality = ParseDouble(value, &endptr);
|
quality = ParseDouble(value, &endptr);
|
||||||
|
|
||||||
if (*endptr != '\0' || quality < -1.0 || quality > 10.0) {
|
if (*endptr != '\0' || quality < -1.0 || quality > 10.0)
|
||||||
error.Format(config_domain,
|
throw FormatRuntimeError("quality \"%s\" is not a number in the "
|
||||||
"quality \"%s\" is not a number in the "
|
"range -1 to 10",
|
||||||
"range -1 to 10",
|
value);
|
||||||
value);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (block.GetBlockValue("bitrate") != nullptr) {
|
if (block.GetBlockValue("bitrate") != nullptr)
|
||||||
error.Set(config_domain,
|
throw std::runtime_error("quality and bitrate are both defined");
|
||||||
"quality and bitrate are both defined");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/* a bit rate was configured */
|
/* a bit rate was configured */
|
||||||
|
|
||||||
value = block.GetBlockValue("bitrate");
|
value = block.GetBlockValue("bitrate");
|
||||||
if (value == nullptr) {
|
if (value == nullptr)
|
||||||
error.Set(config_domain,
|
throw std::runtime_error("neither bitrate nor quality defined");
|
||||||
"neither bitrate nor quality defined");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
quality = -2.0;
|
quality = -2.0;
|
||||||
|
|
||||||
char *endptr;
|
char *endptr;
|
||||||
bitrate = ParseInt(value, &endptr);
|
bitrate = ParseInt(value, &endptr);
|
||||||
if (*endptr != '\0' || bitrate <= 0) {
|
if (*endptr != '\0' || bitrate <= 0)
|
||||||
error.Set(config_domain,
|
throw std::runtime_error("bitrate should be a positive integer");
|
||||||
"bitrate should be a positive integer");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PreparedEncoder *
|
static PreparedEncoder *
|
||||||
vorbis_encoder_init(const ConfigBlock &block, Error &error)
|
vorbis_encoder_init(const ConfigBlock &block)
|
||||||
{
|
{
|
||||||
auto *encoder = new PreparedVorbisEncoder();
|
return new PreparedVorbisEncoder(block);
|
||||||
|
|
||||||
/* load configuration from "block" */
|
|
||||||
if (!encoder->Configure(block, error)) {
|
|
||||||
/* configuration has failed, roll back and return error */
|
|
||||||
delete encoder;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return encoder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -98,8 +98,7 @@ fill_wave_header(WaveHeader *header, int channels, int bits,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static PreparedEncoder *
|
static PreparedEncoder *
|
||||||
wave_encoder_init(gcc_unused const ConfigBlock &block,
|
wave_encoder_init(gcc_unused const ConfigBlock &block)
|
||||||
gcc_unused Error &error)
|
|
||||||
{
|
{
|
||||||
return new PreparedWaveEncoder();
|
return new PreparedWaveEncoder();
|
||||||
}
|
}
|
||||||
|
@ -148,9 +148,7 @@ RecorderOutput::Configure(const ConfigBlock &block, Error &error)
|
|||||||
|
|
||||||
/* initialize encoder */
|
/* initialize encoder */
|
||||||
|
|
||||||
prepared_encoder = encoder_init(*encoder_plugin, block, error);
|
prepared_encoder = encoder_init(*encoder_plugin, block);
|
||||||
if (prepared_encoder == nullptr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -160,14 +158,19 @@ RecorderOutput::Create(const ConfigBlock &block, Error &error)
|
|||||||
{
|
{
|
||||||
RecorderOutput *recorder = new RecorderOutput();
|
RecorderOutput *recorder = new RecorderOutput();
|
||||||
|
|
||||||
if (!recorder->Initialize(block, error)) {
|
try {
|
||||||
delete recorder;
|
if (!recorder->Initialize(block, error)) {
|
||||||
return nullptr;
|
delete recorder;
|
||||||
}
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (!recorder->Configure(block, error)) {
|
if (!recorder->Configure(block, error)) {
|
||||||
|
delete recorder;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
delete recorder;
|
delete recorder;
|
||||||
return nullptr;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
return recorder;
|
return recorder;
|
||||||
|
@ -194,9 +194,7 @@ ShoutOutput::Configure(const ConfigBlock &block, Error &error)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
prepared_encoder = encoder_init(*encoder_plugin, block, error);
|
prepared_encoder = encoder_init(*encoder_plugin, block);
|
||||||
if (prepared_encoder == nullptr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
unsigned shout_format;
|
unsigned shout_format;
|
||||||
if (strcmp(encoding, "mp3") == 0 || strcmp(encoding, "lame") == 0)
|
if (strcmp(encoding, "mp3") == 0 || strcmp(encoding, "lame") == 0)
|
||||||
@ -304,9 +302,14 @@ ShoutOutput::Create(const ConfigBlock &block, Error &error)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sd->Configure(block, error)) {
|
try {
|
||||||
|
if (!sd->Configure(block, error)) {
|
||||||
|
delete sd;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
delete sd;
|
delete sd;
|
||||||
return nullptr;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sd;
|
return sd;
|
||||||
|
@ -117,9 +117,7 @@ HttpdOutput::Configure(const ConfigBlock &block, Error &error)
|
|||||||
|
|
||||||
/* initialize encoder */
|
/* initialize encoder */
|
||||||
|
|
||||||
prepared_encoder = encoder_init(*encoder_plugin, block, error);
|
prepared_encoder = encoder_init(*encoder_plugin, block);
|
||||||
if (prepared_encoder == nullptr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/* determine content type */
|
/* determine content type */
|
||||||
content_type = prepared_encoder->GetMimeType();
|
content_type = prepared_encoder->GetMimeType();
|
||||||
|
@ -67,11 +67,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
Error error;
|
Error error;
|
||||||
std::unique_ptr<PreparedEncoder> p_encoder(encoder_init(*plugin, block, error));
|
std::unique_ptr<PreparedEncoder> p_encoder(encoder_init(*plugin, block));
|
||||||
if (p_encoder == nullptr) {
|
|
||||||
LogError(error, "Failed to initialize encoder");
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* open the encoder */
|
/* open the encoder */
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ static uint8_t zero[256];
|
|||||||
|
|
||||||
int
|
int
|
||||||
main(gcc_unused int argc, gcc_unused char **argv)
|
main(gcc_unused int argc, gcc_unused char **argv)
|
||||||
{
|
try {
|
||||||
gcc_unused bool success;
|
gcc_unused bool success;
|
||||||
|
|
||||||
/* create the encoder */
|
/* create the encoder */
|
||||||
@ -50,65 +50,62 @@ main(gcc_unused int argc, gcc_unused char **argv)
|
|||||||
ConfigBlock block;
|
ConfigBlock block;
|
||||||
block.AddBlockParam("quality", "5.0", -1);
|
block.AddBlockParam("quality", "5.0", -1);
|
||||||
|
|
||||||
std::unique_ptr<PreparedEncoder> p_encoder(encoder_init(*plugin, block,
|
std::unique_ptr<PreparedEncoder> p_encoder(encoder_init(*plugin, block));
|
||||||
IgnoreError()));
|
|
||||||
assert(p_encoder != nullptr);
|
assert(p_encoder != nullptr);
|
||||||
|
|
||||||
try {
|
/* open the encoder */
|
||||||
/* open the encoder */
|
|
||||||
|
|
||||||
AudioFormat audio_format(44100, SampleFormat::S16, 2);
|
AudioFormat audio_format(44100, SampleFormat::S16, 2);
|
||||||
std::unique_ptr<Encoder> encoder(p_encoder->Open(audio_format,
|
std::unique_ptr<Encoder> encoder(p_encoder->Open(audio_format,
|
||||||
IgnoreError()));
|
IgnoreError()));
|
||||||
assert(encoder != nullptr);
|
assert(encoder != nullptr);
|
||||||
|
|
||||||
StdioOutputStream os(stdout);
|
StdioOutputStream os(stdout);
|
||||||
|
|
||||||
EncoderToOutputStream(os, *encoder);
|
EncoderToOutputStream(os, *encoder);
|
||||||
|
|
||||||
/* write a block of data */
|
/* write a block of data */
|
||||||
|
|
||||||
success = encoder->Write(zero, sizeof(zero), IgnoreError());
|
success = encoder->Write(zero, sizeof(zero), IgnoreError());
|
||||||
assert(success);
|
assert(success);
|
||||||
|
|
||||||
EncoderToOutputStream(os, *encoder);
|
EncoderToOutputStream(os, *encoder);
|
||||||
|
|
||||||
/* write a tag */
|
/* write a tag */
|
||||||
|
|
||||||
success = encoder->PreTag(IgnoreError());
|
success = encoder->PreTag(IgnoreError());
|
||||||
assert(success);
|
assert(success);
|
||||||
|
|
||||||
EncoderToOutputStream(os, *encoder);
|
EncoderToOutputStream(os, *encoder);
|
||||||
|
|
||||||
Tag tag;
|
Tag tag;
|
||||||
|
|
||||||
{
|
{
|
||||||
TagBuilder tag_builder;
|
TagBuilder tag_builder;
|
||||||
tag_builder.AddItem(TAG_ARTIST, "Foo");
|
tag_builder.AddItem(TAG_ARTIST, "Foo");
|
||||||
tag_builder.AddItem(TAG_TITLE, "Bar");
|
tag_builder.AddItem(TAG_TITLE, "Bar");
|
||||||
tag_builder.Commit(tag);
|
tag_builder.Commit(tag);
|
||||||
}
|
|
||||||
|
|
||||||
success = encoder->SendTag(tag, IgnoreError());
|
|
||||||
assert(success);
|
|
||||||
|
|
||||||
EncoderToOutputStream(os, *encoder);
|
|
||||||
|
|
||||||
/* write another block of data */
|
|
||||||
|
|
||||||
success = encoder->Write(zero, sizeof(zero), IgnoreError());
|
|
||||||
assert(success);
|
|
||||||
|
|
||||||
/* finish */
|
|
||||||
|
|
||||||
success = encoder->End(IgnoreError());
|
|
||||||
assert(success);
|
|
||||||
|
|
||||||
EncoderToOutputStream(os, *encoder);
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
} catch (const std::exception &e) {
|
|
||||||
LogError(e);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
success = encoder->SendTag(tag, IgnoreError());
|
||||||
|
assert(success);
|
||||||
|
|
||||||
|
EncoderToOutputStream(os, *encoder);
|
||||||
|
|
||||||
|
/* write another block of data */
|
||||||
|
|
||||||
|
success = encoder->Write(zero, sizeof(zero), IgnoreError());
|
||||||
|
assert(success);
|
||||||
|
|
||||||
|
/* finish */
|
||||||
|
|
||||||
|
success = encoder->End(IgnoreError());
|
||||||
|
assert(success);
|
||||||
|
|
||||||
|
EncoderToOutputStream(os, *encoder);
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
LogError(e);
|
||||||
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user