Commit 2bf2f34b authored by Max Kellermann's avatar Max Kellermann

InputPlugin: allow init() to soft-fail

Add enum InputResult which is a tri-state. Input plugins may now fail and just become unavailable.
parent 7453c26e
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include "config/ConfigGlobal.hxx" #include "config/ConfigGlobal.hxx"
#include "config/ConfigOption.hxx" #include "config/ConfigOption.hxx"
#include "config/ConfigData.hxx" #include "config/ConfigData.hxx"
#include "Log.hxx"
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
...@@ -49,12 +50,29 @@ input_stream_global_init(Error &error) ...@@ -49,12 +50,29 @@ input_stream_global_init(Error &error)
/* the plugin is disabled in mpd.conf */ /* the plugin is disabled in mpd.conf */
continue; 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; input_plugins_enabled[i] = true;
else { break;
case InputPlugin::InitResult::ERROR:
error.FormatPrefix("Failed to initialize input plugin '%s': ", error.FormatPrefix("Failed to initialize input plugin '%s': ",
plugin->name); plugin->name);
return false; return false;
case InputPlugin::InitResult::UNAVAILABLE:
if (error.IsDefined()) {
FormatError(error,
"Input plugin '%s' is unavailable: ",
plugin->name);
error.Clear();
}
break;
} }
} }
......
...@@ -26,12 +26,41 @@ ...@@ -26,12 +26,41 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#ifdef WIN32
#include <windows.h>
/* damn you, windows.h! */
#ifdef ERROR
#undef ERROR
#endif
#endif
struct config_param; struct config_param;
struct InputStream; struct InputStream;
class Error; class Error;
struct Tag; struct Tag;
struct InputPlugin { 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; typedef int64_t offset_type;
const char *name; const char *name;
...@@ -42,7 +71,7 @@ struct InputPlugin { ...@@ -42,7 +71,7 @@ struct InputPlugin {
* @return true on success, false if the plugin should be * @return true on success, false if the plugin should be
* disabled * disabled
*/ */
bool (*init)(const config_param &param, Error &error); InitResult (*init)(const config_param &param, Error &error);
/** /**
* Global deinitialization. Called once before MPD shuts * Global deinitialization. Called once before MPD shuts
......
...@@ -87,7 +87,7 @@ static constexpr Domain cdio_domain("cdio"); ...@@ -87,7 +87,7 @@ static constexpr Domain cdio_domain("cdio");
static bool default_reverse_endian; static bool default_reverse_endian;
static bool static InputPlugin::InitResult
input_cdio_init(const config_param &param, Error &error) input_cdio_init(const config_param &param, Error &error)
{ {
const char *value = param.GetBlockValue("default_byte_order"); const char *value = param.GetBlockValue("default_byte_order");
...@@ -100,11 +100,11 @@ input_cdio_init(const config_param &param, Error &error) ...@@ -100,11 +100,11 @@ input_cdio_init(const config_param &param, Error &error)
error.Format(config_domain, 0, error.Format(config_domain, 0,
"Unrecognized 'default_byte_order' setting: %s", "Unrecognized 'default_byte_order' setting: %s",
value); value);
return false; return InputPlugin::InitResult::ERROR;
} }
} }
return true; return InputPlugin::InitResult::SUCCESS;
} }
static void static void
......
...@@ -595,7 +595,7 @@ CurlMulti::OnTimeout() ...@@ -595,7 +595,7 @@ CurlMulti::OnTimeout()
* *
*/ */
static bool static InputPlugin::InitResult
input_curl_init(const config_param &param, Error &error) input_curl_init(const config_param &param, Error &error)
{ {
CURLcode code = curl_global_init(CURL_GLOBAL_ALL); CURLcode code = curl_global_init(CURL_GLOBAL_ALL);
...@@ -603,7 +603,7 @@ input_curl_init(const config_param &param, Error &error) ...@@ -603,7 +603,7 @@ input_curl_init(const config_param &param, Error &error)
error.Format(curl_domain, code, error.Format(curl_domain, code,
"curl_global_init() failed: %s", "curl_global_init() failed: %s",
curl_easy_strerror(code)); curl_easy_strerror(code));
return false; return InputPlugin::InitResult::UNAVAILABLE;
} }
const auto version_info = curl_version_info(CURLVERSION_FIRST); const auto version_info = curl_version_info(CURLVERSION_FIRST);
...@@ -634,12 +634,14 @@ input_curl_init(const config_param &param, Error &error) ...@@ -634,12 +634,14 @@ input_curl_init(const config_param &param, Error &error)
CURLM *multi = curl_multi_init(); CURLM *multi = curl_multi_init();
if (multi == nullptr) { if (multi == nullptr) {
curl_slist_free_all(http_200_aliases);
curl_global_cleanup();
error.Set(curl_domain, 0, "curl_multi_init() failed"); error.Set(curl_domain, 0, "curl_multi_init() failed");
return false; return InputPlugin::InitResult::UNAVAILABLE;
} }
curl_multi = new CurlMulti(io_thread_get(), multi); curl_multi = new CurlMulti(io_thread_get(), multi);
return true; return InputPlugin::InitResult::SUCCESS;
} }
static void static void
......
...@@ -69,7 +69,7 @@ input_ffmpeg_supported(void) ...@@ -69,7 +69,7 @@ input_ffmpeg_supported(void)
return avio_enum_protocols(&opaque, 0) != nullptr; return avio_enum_protocols(&opaque, 0) != nullptr;
} }
static bool static InputPlugin::InitResult
input_ffmpeg_init(gcc_unused const config_param &param, input_ffmpeg_init(gcc_unused const config_param &param,
Error &error) Error &error)
{ {
...@@ -78,10 +78,10 @@ input_ffmpeg_init(gcc_unused const config_param &param, ...@@ -78,10 +78,10 @@ input_ffmpeg_init(gcc_unused const config_param &param,
/* disable this plugin if there's no registered protocol */ /* disable this plugin if there's no registered protocol */
if (!input_ffmpeg_supported()) { if (!input_ffmpeg_supported()) {
error.Set(ffmpeg_domain, "No protocol"); error.Set(ffmpeg_domain, "No protocol");
return false; return InputPlugin::InitResult::UNAVAILABLE;
} }
return true; return InputPlugin::InitResult::SUCCESS;
} }
static InputStream * static InputStream *
......
...@@ -91,17 +91,17 @@ public: ...@@ -91,17 +91,17 @@ public:
* *
*/ */
static bool static InputPlugin::InitResult
input_smbclient_init(gcc_unused const config_param &param, Error &error) input_smbclient_init(gcc_unused const config_param &param, Error &error)
{ {
if (!SmbclientInit(error)) if (!SmbclientInit(error))
return false; return InputPlugin::InitResult::UNAVAILABLE;
// TODO: create one global SMBCCTX here? // TODO: create one global SMBCCTX here?
// TODO: evaluate config_param, call smbc_setOption*() // TODO: evaluate config_param, call smbc_setOption*()
return true; return InputPlugin::InitResult::SUCCESS;
} }
static InputStream * static InputStream *
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment