encoder/Plugin: migrate from class Error to C++ exceptions
This commit is contained in:
		| @@ -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,6 +158,7 @@ RecorderOutput::Create(const ConfigBlock &block, Error &error) | |||||||
| { | { | ||||||
| 	RecorderOutput *recorder = new RecorderOutput(); | 	RecorderOutput *recorder = new RecorderOutput(); | ||||||
|  |  | ||||||
|  | 	try { | ||||||
| 		if (!recorder->Initialize(block, error)) { | 		if (!recorder->Initialize(block, error)) { | ||||||
| 			delete recorder; | 			delete recorder; | ||||||
| 			return nullptr; | 			return nullptr; | ||||||
| @@ -169,6 +168,10 @@ RecorderOutput::Create(const ConfigBlock &block, Error &error) | |||||||
| 			delete recorder; | 			delete recorder; | ||||||
| 			return nullptr; | 			return nullptr; | ||||||
| 		} | 		} | ||||||
|  | 	} catch (...) { | ||||||
|  | 		delete recorder; | ||||||
|  | 		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,10 +302,15 @@ ShoutOutput::Create(const ConfigBlock &block, Error &error) | |||||||
| 		return nullptr; | 		return nullptr; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	try { | ||||||
| 		if (!sd->Configure(block, error)) { | 		if (!sd->Configure(block, error)) { | ||||||
| 			delete sd; | 			delete sd; | ||||||
| 			return nullptr; | 			return nullptr; | ||||||
| 		} | 		} | ||||||
|  | 	} catch (...) { | ||||||
|  | 		delete sd; | ||||||
|  | 		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,11 +50,9 @@ 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); | ||||||
| @@ -111,4 +109,3 @@ main(gcc_unused int argc, gcc_unused char **argv) | |||||||
| 	LogError(e); | 	LogError(e); | ||||||
| 	return EXIT_FAILURE; | 	return EXIT_FAILURE; | ||||||
| } | } | ||||||
| } |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Max Kellermann
					Max Kellermann