From 2bf2f34b1211bfde95ef4ada77147a8b65830084 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sun, 2 Mar 2014 00:17:32 +0100 Subject: InputPlugin: allow init() to soft-fail Add enum InputResult which is a tri-state. Input plugins may now fail and just become unavailable. --- src/input/Init.cxx | 22 +++++++++++++++++-- src/input/InputPlugin.hxx | 31 ++++++++++++++++++++++++++- src/input/plugins/CdioParanoiaInputPlugin.cxx | 6 +++--- src/input/plugins/CurlInputPlugin.cxx | 10 +++++---- src/input/plugins/FfmpegInputPlugin.cxx | 6 +++--- src/input/plugins/SmbclientInputPlugin.cxx | 6 +++--- 6 files changed, 65 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/input/Init.cxx b/src/input/Init.cxx index 4b8eac320..5e64dcaed 100644 --- a/src/input/Init.cxx +++ b/src/input/Init.cxx @@ -25,6 +25,7 @@ #include "config/ConfigGlobal.hxx" #include "config/ConfigOption.hxx" #include "config/ConfigData.hxx" +#include "Log.hxx" #include #include @@ -49,12 +50,29 @@ input_stream_global_init(Error &error) /* the plugin is disabled in mpd.conf */ continue; - if (plugin->init == nullptr || plugin->init(*param, error)) + InputPlugin::InitResult result = plugin->init != nullptr + ? plugin->init(*param, error) + : InputPlugin::InitResult::SUCCESS; + + switch (result) { + case InputPlugin::InitResult::SUCCESS: input_plugins_enabled[i] = true; - else { + break; + + case InputPlugin::InitResult::ERROR: error.FormatPrefix("Failed to initialize input plugin '%s': ", plugin->name); return false; + + case InputPlugin::InitResult::UNAVAILABLE: + if (error.IsDefined()) { + FormatError(error, + "Input plugin '%s' is unavailable: ", + plugin->name); + error.Clear(); + } + + break; } } diff --git a/src/input/InputPlugin.hxx b/src/input/InputPlugin.hxx index 83e0ab26e..090c73df8 100644 --- a/src/input/InputPlugin.hxx +++ b/src/input/InputPlugin.hxx @@ -26,12 +26,41 @@ #include #include +#ifdef WIN32 +#include +/* damn you, windows.h! */ +#ifdef ERROR +#undef ERROR +#endif +#endif + struct config_param; struct InputStream; class Error; struct Tag; struct InputPlugin { + enum class InitResult { + /** + * A fatal error has occurred (e.g. misconfiguration). + * The #Error has been set. + */ + ERROR, + + /** + * The plugin was initialized successfully and is + * ready to be used. + */ + SUCCESS, + + /** + * The plugin is not available and shall be disabled. + * The #Error may be set describing the situation (to + * be logged). + */ + UNAVAILABLE, + }; + typedef int64_t offset_type; const char *name; @@ -42,7 +71,7 @@ struct InputPlugin { * @return true on success, false if the plugin should be * disabled */ - bool (*init)(const config_param ¶m, Error &error); + InitResult (*init)(const config_param ¶m, Error &error); /** * Global deinitialization. Called once before MPD shuts diff --git a/src/input/plugins/CdioParanoiaInputPlugin.cxx b/src/input/plugins/CdioParanoiaInputPlugin.cxx index 9267b50e1..767b2600f 100644 --- a/src/input/plugins/CdioParanoiaInputPlugin.cxx +++ b/src/input/plugins/CdioParanoiaInputPlugin.cxx @@ -87,7 +87,7 @@ static constexpr Domain cdio_domain("cdio"); static bool default_reverse_endian; -static bool +static InputPlugin::InitResult input_cdio_init(const config_param ¶m, Error &error) { const char *value = param.GetBlockValue("default_byte_order"); @@ -100,11 +100,11 @@ input_cdio_init(const config_param ¶m, Error &error) error.Format(config_domain, 0, "Unrecognized 'default_byte_order' setting: %s", value); - return false; + return InputPlugin::InitResult::ERROR; } } - return true; + return InputPlugin::InitResult::SUCCESS; } static void diff --git a/src/input/plugins/CurlInputPlugin.cxx b/src/input/plugins/CurlInputPlugin.cxx index 3704aa35a..3f496cb96 100644 --- a/src/input/plugins/CurlInputPlugin.cxx +++ b/src/input/plugins/CurlInputPlugin.cxx @@ -595,7 +595,7 @@ CurlMulti::OnTimeout() * */ -static bool +static InputPlugin::InitResult input_curl_init(const config_param ¶m, Error &error) { CURLcode code = curl_global_init(CURL_GLOBAL_ALL); @@ -603,7 +603,7 @@ input_curl_init(const config_param ¶m, Error &error) error.Format(curl_domain, code, "curl_global_init() failed: %s", curl_easy_strerror(code)); - return false; + return InputPlugin::InitResult::UNAVAILABLE; } const auto version_info = curl_version_info(CURLVERSION_FIRST); @@ -634,12 +634,14 @@ input_curl_init(const config_param ¶m, Error &error) CURLM *multi = curl_multi_init(); if (multi == nullptr) { + curl_slist_free_all(http_200_aliases); + curl_global_cleanup(); error.Set(curl_domain, 0, "curl_multi_init() failed"); - return false; + return InputPlugin::InitResult::UNAVAILABLE; } curl_multi = new CurlMulti(io_thread_get(), multi); - return true; + return InputPlugin::InitResult::SUCCESS; } static void diff --git a/src/input/plugins/FfmpegInputPlugin.cxx b/src/input/plugins/FfmpegInputPlugin.cxx index 0d0a4375e..dab4b59fb 100644 --- a/src/input/plugins/FfmpegInputPlugin.cxx +++ b/src/input/plugins/FfmpegInputPlugin.cxx @@ -69,7 +69,7 @@ input_ffmpeg_supported(void) return avio_enum_protocols(&opaque, 0) != nullptr; } -static bool +static InputPlugin::InitResult input_ffmpeg_init(gcc_unused const config_param ¶m, Error &error) { @@ -78,10 +78,10 @@ input_ffmpeg_init(gcc_unused const config_param ¶m, /* disable this plugin if there's no registered protocol */ if (!input_ffmpeg_supported()) { error.Set(ffmpeg_domain, "No protocol"); - return false; + return InputPlugin::InitResult::UNAVAILABLE; } - return true; + return InputPlugin::InitResult::SUCCESS; } static InputStream * diff --git a/src/input/plugins/SmbclientInputPlugin.cxx b/src/input/plugins/SmbclientInputPlugin.cxx index 6f2c191b0..9709d089a 100644 --- a/src/input/plugins/SmbclientInputPlugin.cxx +++ b/src/input/plugins/SmbclientInputPlugin.cxx @@ -91,17 +91,17 @@ public: * */ -static bool +static InputPlugin::InitResult input_smbclient_init(gcc_unused const config_param ¶m, Error &error) { if (!SmbclientInit(error)) - return false; + return InputPlugin::InitResult::UNAVAILABLE; // TODO: create one global SMBCCTX here? // TODO: evaluate config_param, call smbc_setOption*() - return true; + return InputPlugin::InitResult::SUCCESS; } static InputStream * -- cgit v1.2.3