diff --git a/src/filter/FilterConfig.cxx b/src/filter/FilterConfig.cxx index 236297eba..69e22497b 100644 --- a/src/filter/FilterConfig.cxx +++ b/src/filter/FilterConfig.cxx @@ -26,39 +26,31 @@ #include "config/ConfigGlobal.hxx" #include "config/ConfigError.hxx" #include "config/Block.hxx" -#include "util/Error.hxx" +#include "util/RuntimeError.hxx" #include #include -static bool -filter_chain_append_new(PreparedFilter &chain, const char *template_name, Error &error) +static void +filter_chain_append_new(PreparedFilter &chain, const char *template_name) { const auto *cfg = config_find_block(ConfigBlockOption::AUDIO_FILTER, "name", template_name); - if (cfg == nullptr) { - error.Format(config_domain, - "filter template not found: %s", - template_name); - return false; - } + if (cfg == nullptr) + throw FormatRuntimeError("Filter template not found: %s", + template_name); // Instantiate one of those filter plugins with the template name as a hint - PreparedFilter *f = filter_configured_new(*cfg, error); - if (f == nullptr) - // The error has already been set, just stop. - return false; + PreparedFilter *f = filter_configured_new(*cfg); const char *plugin_name = cfg->GetBlockValue("plugin", "unknown"); filter_chain_append(chain, plugin_name, f); - - return true; } -bool -filter_chain_parse(PreparedFilter &chain, const char *spec, Error &error) +void +filter_chain_parse(PreparedFilter &chain, const char *spec) { const char *const end = spec + strlen(spec); @@ -66,9 +58,7 @@ filter_chain_parse(PreparedFilter &chain, const char *spec, Error &error) const char *comma = std::find(spec, end, ','); if (comma > spec) { const std::string name(spec, comma); - if (!filter_chain_append_new(chain, name.c_str(), - error)) - return false; + filter_chain_append_new(chain, name.c_str()); } if (comma == end) @@ -76,6 +66,4 @@ filter_chain_parse(PreparedFilter &chain, const char *spec, Error &error) spec = comma + 1; } - - return true; } diff --git a/src/filter/FilterConfig.hxx b/src/filter/FilterConfig.hxx index 6d6fb4744..05de21877 100644 --- a/src/filter/FilterConfig.hxx +++ b/src/filter/FilterConfig.hxx @@ -26,18 +26,18 @@ #define MPD_FILTER_CONFIG_HXX class PreparedFilter; -class Error; /** * Builds a filter chain from a configuration string on the form * "name1, name2, name3, ..." by looking up each name among the * configured filter sections. + * + * Throws std::runtime_error on error. + * * @param chain the chain to append filters on * @param spec the filter chain specification - * @param error space to return an error description - * @return true on success */ -bool -filter_chain_parse(PreparedFilter &chain, const char *spec, Error &error); +void +filter_chain_parse(PreparedFilter &chain, const char *spec); #endif diff --git a/src/filter/FilterPlugin.cxx b/src/filter/FilterPlugin.cxx index f43fee06c..06db15379 100644 --- a/src/filter/FilterPlugin.cxx +++ b/src/filter/FilterPlugin.cxx @@ -22,37 +22,29 @@ #include "FilterRegistry.hxx" #include "config/Block.hxx" #include "config/ConfigError.hxx" -#include "util/Error.hxx" +#include "util/RuntimeError.hxx" #include PreparedFilter * -filter_new(const struct filter_plugin *plugin, - const ConfigBlock &block, Error &error) +filter_new(const struct filter_plugin *plugin, const ConfigBlock &block) { assert(plugin != nullptr); - assert(!error.IsDefined()); - return plugin->init(block, error); + return plugin->init(block); } PreparedFilter * -filter_configured_new(const ConfigBlock &block, Error &error) +filter_configured_new(const ConfigBlock &block) { - assert(!error.IsDefined()); - const char *plugin_name = block.GetBlockValue("plugin"); - if (plugin_name == nullptr) { - error.Set(config_domain, "No filter plugin specified"); - return nullptr; - } + if (plugin_name == nullptr) + throw std::runtime_error("No filter plugin specified"); const filter_plugin *plugin = filter_plugin_by_name(plugin_name); - if (plugin == nullptr) { - error.Format(config_domain, - "No such filter plugin: %s", plugin_name); - return nullptr; - } + if (plugin == nullptr) + throw FormatRuntimeError("No such filter plugin: %s", + plugin_name); - return filter_new(plugin, block, error); + return filter_new(plugin, block); } diff --git a/src/filter/FilterPlugin.hxx b/src/filter/FilterPlugin.hxx index 2ebca232b..1e09c29c4 100644 --- a/src/filter/FilterPlugin.hxx +++ b/src/filter/FilterPlugin.hxx @@ -28,7 +28,6 @@ struct ConfigBlock; class PreparedFilter; -class Error; struct filter_plugin { const char *name; @@ -36,32 +35,30 @@ struct filter_plugin { /** * Allocates and configures a filter. */ - PreparedFilter *(*init)(const ConfigBlock &block, Error &error); + PreparedFilter *(*init)(const ConfigBlock &block); }; /** * Creates a new instance of the specified filter plugin. * + * Throws std::runtime_error on error. + * * @param plugin the filter plugin * @param block configuration section - * @param error location to store the error occurring, or nullptr to - * ignore errors. - * @return a new filter object, or nullptr on error */ PreparedFilter * filter_new(const struct filter_plugin *plugin, - const ConfigBlock &block, Error &error); + const ConfigBlock &block); /** * Creates a new filter, loads configuration and the plugin name from * the specified configuration section. * + * Throws std::runtime_error on error. + * * @param block the configuration section - * @param error location to store the error occurring, or nullptr to - * ignore errors. - * @return a new filter object, or nullptr on error */ PreparedFilter * -filter_configured_new(const ConfigBlock &block, Error &error); +filter_configured_new(const ConfigBlock &block); #endif diff --git a/src/filter/plugins/ChainFilterPlugin.cxx b/src/filter/plugins/ChainFilterPlugin.cxx index fafba0250..f853320a5 100644 --- a/src/filter/plugins/ChainFilterPlugin.cxx +++ b/src/filter/plugins/ChainFilterPlugin.cxx @@ -93,8 +93,7 @@ public: }; static PreparedFilter * -chain_filter_init(gcc_unused const ConfigBlock &block, - gcc_unused Error &error) +chain_filter_init(gcc_unused const ConfigBlock &block) { return new PreparedChainFilter(); } diff --git a/src/filter/plugins/ConvertFilterPlugin.cxx b/src/filter/plugins/ConvertFilterPlugin.cxx index fb8e684b6..f4dc37d73 100644 --- a/src/filter/plugins/ConvertFilterPlugin.cxx +++ b/src/filter/plugins/ConvertFilterPlugin.cxx @@ -64,8 +64,7 @@ public: }; static PreparedFilter * -convert_filter_init(gcc_unused const ConfigBlock &block, - gcc_unused Error &error) +convert_filter_init(gcc_unused const ConfigBlock &block) { return new PreparedConvertFilter(); } diff --git a/src/filter/plugins/NormalizeFilterPlugin.cxx b/src/filter/plugins/NormalizeFilterPlugin.cxx index 4211b8ced..459be88cd 100644 --- a/src/filter/plugins/NormalizeFilterPlugin.cxx +++ b/src/filter/plugins/NormalizeFilterPlugin.cxx @@ -53,8 +53,7 @@ public: }; static PreparedFilter * -normalize_filter_init(gcc_unused const ConfigBlock &block, - gcc_unused Error &error) +normalize_filter_init(gcc_unused const ConfigBlock &block) { return new PreparedNormalizeFilter(); } diff --git a/src/filter/plugins/NullFilterPlugin.cxx b/src/filter/plugins/NullFilterPlugin.cxx index 47a7bb555..b44180e9f 100644 --- a/src/filter/plugins/NullFilterPlugin.cxx +++ b/src/filter/plugins/NullFilterPlugin.cxx @@ -49,8 +49,7 @@ public: }; static PreparedFilter * -null_filter_init(gcc_unused const ConfigBlock &block, - gcc_unused Error &error) +null_filter_init(gcc_unused const ConfigBlock &block) { return new PreparedNullFilter(); } diff --git a/src/filter/plugins/ReplayGainFilterPlugin.cxx b/src/filter/plugins/ReplayGainFilterPlugin.cxx index 1c36a17c7..b6c212c46 100644 --- a/src/filter/plugins/ReplayGainFilterPlugin.cxx +++ b/src/filter/plugins/ReplayGainFilterPlugin.cxx @@ -168,8 +168,7 @@ ReplayGainFilter::Update() } static PreparedFilter * -replay_gain_filter_init(gcc_unused const ConfigBlock &block, - gcc_unused Error &error) +replay_gain_filter_init(gcc_unused const ConfigBlock &block) { return new PreparedReplayGainFilter(); } diff --git a/src/filter/plugins/RouteFilterPlugin.cxx b/src/filter/plugins/RouteFilterPlugin.cxx index f08bf84bc..374ffc4e1 100644 --- a/src/filter/plugins/RouteFilterPlugin.cxx +++ b/src/filter/plugins/RouteFilterPlugin.cxx @@ -49,7 +49,7 @@ #include "pcm/PcmBuffer.hxx" #include "pcm/Silence.hxx" #include "util/StringUtil.hxx" -#include "util/Error.hxx" +#include "util/RuntimeError.hxx" #include "util/ConstBuffer.hxx" #include "util/WritableBuffer.hxx" @@ -130,16 +130,14 @@ public: * and input channel a gets copied to output channel b, etc. * @param block the configuration block to read * @param filter a route_filter whose min_channels and sources[] to set - * @return true on success, false on error */ - bool Configure(const ConfigBlock &block, Error &error); + PreparedRouteFilter(const ConfigBlock &block); /* virtual methods from class PreparedFilter */ Filter *Open(AudioFormat &af) override; }; -bool -PreparedRouteFilter::Configure(const ConfigBlock &block, Error &error) +PreparedRouteFilter::PreparedRouteFilter(const ConfigBlock &block) { /* TODO: * With a more clever way of marking "don't copy to output N", @@ -160,18 +158,12 @@ PreparedRouteFilter::Configure(const ConfigBlock &block, Error &error) char *endptr; const unsigned source = strtoul(routes, &endptr, 10); endptr = StripLeft(endptr); - if (endptr == routes || *endptr != '>') { - error.Set(config_domain, - "Malformed 'routes' specification"); - return false; - } + if (endptr == routes || *endptr != '>') + throw std::runtime_error("Malformed 'routes' specification"); - if (source >= MAX_CHANNELS) { - error.Format(config_domain, - "Invalid source channel number: %u", - source); - return false; - } + if (source >= MAX_CHANNELS) + throw FormatRuntimeError("Invalid source channel number: %u", + source); if (source >= min_input_channels) min_input_channels = source + 1; @@ -180,18 +172,12 @@ PreparedRouteFilter::Configure(const ConfigBlock &block, Error &error) unsigned dest = strtoul(routes, &endptr, 10); endptr = StripLeft(endptr); - if (endptr == routes) { - error.Set(config_domain, - "Malformed 'routes' specification"); - return false; - } + if (endptr == routes) + throw std::runtime_error("Malformed 'routes' specification"); - if (dest >= MAX_CHANNELS) { - error.Format(config_domain, - "Invalid destination channel number: %u", - dest); - return false; - } + if (dest >= MAX_CHANNELS) + throw FormatRuntimeError("Invalid destination channel number: %u", + dest); if (dest >= min_output_channels) min_output_channels = dest + 1; @@ -203,28 +189,17 @@ PreparedRouteFilter::Configure(const ConfigBlock &block, Error &error) if (*routes == 0) break; - if (*routes != ',') { - error.Set(config_domain, - "Malformed 'routes' specification"); - return false; - } + if (*routes != ',') + throw std::runtime_error("Malformed 'routes' specification"); ++routes; } - - return true; } static PreparedFilter * -route_filter_init(const ConfigBlock &block, Error &error) +route_filter_init(const ConfigBlock &block) { - auto *filter = new PreparedRouteFilter(); - if (!filter->Configure(block, error)) { - delete filter; - return nullptr; - } - - return filter; + return new PreparedRouteFilter(block); } RouteFilter::RouteFilter(const AudioFormat &audio_format, diff --git a/src/filter/plugins/VolumeFilterPlugin.cxx b/src/filter/plugins/VolumeFilterPlugin.cxx index 530839030..5ed86d222 100644 --- a/src/filter/plugins/VolumeFilterPlugin.cxx +++ b/src/filter/plugins/VolumeFilterPlugin.cxx @@ -61,8 +61,7 @@ public: }; static PreparedFilter * -volume_filter_init(gcc_unused const ConfigBlock &block, - gcc_unused Error &error) +volume_filter_init(gcc_unused const ConfigBlock &block) { return new PreparedVolumeFilter(); } diff --git a/src/output/Init.cxx b/src/output/Init.cxx index 00dc9d569..b592c8c01 100644 --- a/src/output/Init.cxx +++ b/src/output/Init.cxx @@ -39,6 +39,8 @@ #include "util/Error.hxx" #include "Log.hxx" +#include + #include #include @@ -105,8 +107,7 @@ audio_output_mixer_type(const ConfigBlock &block) static PreparedFilter * CreateVolumeFilter() { - return filter_new(&volume_filter_plugin, ConfigBlock(), - IgnoreError()); + return filter_new(&volume_filter_plugin, ConfigBlock()); } static Mixer * @@ -190,25 +191,24 @@ AudioOutput::Configure(const ConfigBlock &block, Error &error) if (config_get_bool(ConfigOption::VOLUME_NORMALIZATION, false)) { auto *normalize_filter = - filter_new(&normalize_filter_plugin, ConfigBlock(), - IgnoreError()); + filter_new(&normalize_filter_plugin, ConfigBlock()); assert(normalize_filter != nullptr); filter_chain_append(*prepared_filter, "normalize", autoconvert_filter_new(normalize_filter)); } - Error filter_error; - filter_chain_parse(*prepared_filter, - block.GetBlockValue(AUDIO_FILTERS, ""), - filter_error); - - // It's not really fatal - Part of the filter chain has been set up already - // and even an empty one will work (if only with unexpected behaviour) - if (filter_error.IsDefined()) - FormatError(filter_error, + try { + filter_chain_parse(*prepared_filter, + block.GetBlockValue(AUDIO_FILTERS, "")); + } catch (const std::runtime_error &e) { + /* It's not really fatal - Part of the filter chain + has been set up already and even an empty one will + work (if only with unexpected behaviour) */ + FormatError(e, "Failed to initialize filter chain for '%s'", name); + } /* done */ @@ -229,14 +229,13 @@ audio_output_setup(EventLoop &event_loop, AudioOutput &ao, if (strcmp(replay_gain_handler, "none") != 0) { ao.prepared_replay_gain_filter = filter_new(&replay_gain_filter_plugin, - block, IgnoreError()); + block); assert(ao.prepared_replay_gain_filter != nullptr); ao.replay_gain_serial = 0; ao.prepared_other_replay_gain_filter = filter_new(&replay_gain_filter_plugin, - block, - IgnoreError()); + block); assert(ao.prepared_other_replay_gain_filter != nullptr); ao.other_replay_gain_serial = 0; @@ -276,8 +275,7 @@ audio_output_setup(EventLoop &event_loop, AudioOutput &ao, /* the "convert" filter must be the last one in the chain */ - auto *f = filter_new(&convert_filter_plugin, ConfigBlock(), - IgnoreError()); + auto *f = filter_new(&convert_filter_plugin, ConfigBlock()); assert(f != nullptr); filter_chain_append(*ao.prepared_filter, "convert", diff --git a/test/run_filter.cxx b/test/run_filter.cxx index 58f235956..f920008aa 100644 --- a/test/run_filter.cxx +++ b/test/run_filter.cxx @@ -58,14 +58,7 @@ load_filter(const char *name) return nullptr; } - Error error; - auto *filter = filter_configured_new(*param, error); - if (filter == NULL) { - LogError(error, "Failed to load filter"); - return NULL; - } - - return filter; + return filter_configured_new(*param); } int main(int argc, char **argv)