diff --git a/Makefile.am b/Makefile.am index 31f088629..a9c0c8d83 100644 --- a/Makefile.am +++ b/Makefile.am @@ -166,6 +166,7 @@ libmpd_a_SOURCES = \ src/queue/PlaylistTag.cxx \ src/queue/PlaylistState.cxx src/queue/PlaylistState.hxx \ src/queue/Listener.hxx \ + src/PluginUnavailable.hxx \ src/ReplayGainConfig.cxx src/ReplayGainConfig.hxx \ src/ReplayGainInfo.cxx src/ReplayGainInfo.hxx \ src/DetachedSong.cxx src/DetachedSong.hxx \ diff --git a/src/PluginUnavailable.hxx b/src/PluginUnavailable.hxx new file mode 100644 index 000000000..1e5f85c52 --- /dev/null +++ b/src/PluginUnavailable.hxx @@ -0,0 +1,36 @@ +/* + * Copyright 2003-2016 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_PLUGIN_UNAVAILABLE_HXX +#define MPD_PLUGIN_UNAVAILABLE_HXX + +#include + +/** + * An exception class which is used by plugin initializers to indicate + * that this plugin is unavailable. It will be disabled, and MPD can + * continue initialization. + */ +class PluginUnavailable final : public std::runtime_error { +public: + explicit PluginUnavailable(const char *msg) + :std::runtime_error(msg) {} +}; + +#endif diff --git a/src/input/Init.cxx b/src/input/Init.cxx index d47f8cea3..dd5b12501 100644 --- a/src/input/Init.cxx +++ b/src/input/Init.cxx @@ -26,6 +26,7 @@ #include "config/ConfigOption.hxx" #include "config/Block.hxx" #include "Log.hxx" +#include "PluginUnavailable.hxx" #include "util/RuntimeError.hxx" #include @@ -59,6 +60,11 @@ input_stream_global_init(Error &error) result = plugin->init != nullptr ? plugin->init(*block, error) : InputPlugin::InitResult::SUCCESS; + } catch (const PluginUnavailable &e) { + FormatError(e, + "Input plugin '%s' is unavailable", + plugin->name); + continue; } catch (const std::runtime_error &e) { std::throw_with_nested(FormatRuntimeError("Failed to initialize input plugin '%s'", plugin->name)); @@ -73,16 +79,6 @@ input_stream_global_init(Error &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 8e3fd35ae..b8fa37833 100644 --- a/src/input/InputPlugin.hxx +++ b/src/input/InputPlugin.hxx @@ -52,13 +52,6 @@ struct InputPlugin { * 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, }; const char *name; @@ -66,8 +59,8 @@ struct InputPlugin { /** * Global initialization. This method is called when MPD starts. * - * @return true on success, false if the plugin should be - * disabled + * Throws #PluginUnavailable if the plugin is not available + * and shall be disabled. */ InitResult (*init)(const ConfigBlock &block, Error &error); diff --git a/src/input/plugins/CurlInputPlugin.cxx b/src/input/plugins/CurlInputPlugin.cxx index 98df83a25..4987a1b8d 100644 --- a/src/input/plugins/CurlInputPlugin.cxx +++ b/src/input/plugins/CurlInputPlugin.cxx @@ -35,6 +35,7 @@ #include "util/Error.hxx" #include "util/Domain.hxx" #include "Log.hxx" +#include "PluginUnavailable.hxx" #include #include @@ -533,15 +534,11 @@ CurlMulti::OnTimeout() */ static InputPlugin::InitResult -input_curl_init(const ConfigBlock &block, Error &error) +input_curl_init(const ConfigBlock &block, gcc_unused Error &error) { CURLcode code = curl_global_init(CURL_GLOBAL_ALL); - if (code != CURLE_OK) { - error.Format(curl_domain, code, - "curl_global_init() failed: %s", - curl_easy_strerror(code)); - return InputPlugin::InitResult::UNAVAILABLE; - } + if (code != CURLE_OK) + throw PluginUnavailable(curl_easy_strerror(code)); const auto version_info = curl_version_info(CURLVERSION_FIRST); if (version_info != nullptr) { @@ -576,8 +573,7 @@ input_curl_init(const ConfigBlock &block, Error &error) if (multi == nullptr) { curl_slist_free_all(http_200_aliases); curl_global_cleanup(); - error.Set(curl_domain, 0, "curl_multi_init() failed"); - return InputPlugin::InitResult::UNAVAILABLE; + throw PluginUnavailable("curl_multi_init() failed"); } curl_multi = new CurlMulti(io_thread_get(), multi); diff --git a/src/input/plugins/FfmpegInputPlugin.cxx b/src/input/plugins/FfmpegInputPlugin.cxx index 8e9723fd7..46980c26e 100644 --- a/src/input/plugins/FfmpegInputPlugin.cxx +++ b/src/input/plugins/FfmpegInputPlugin.cxx @@ -27,6 +27,7 @@ #include "lib/ffmpeg/Error.hxx" #include "../InputStream.hxx" #include "../InputPlugin.hxx" +#include "PluginUnavailable.hxx" #include "util/StringCompare.hxx" #include "util/Error.hxx" @@ -73,15 +74,13 @@ input_ffmpeg_supported(void) static InputPlugin::InitResult input_ffmpeg_init(gcc_unused const ConfigBlock &block, - Error &error) + gcc_unused Error &error) { FfmpegInit(); /* disable this plugin if there's no registered protocol */ - if (!input_ffmpeg_supported()) { - error.Set(ffmpeg_domain, "No protocol"); - return InputPlugin::InitResult::UNAVAILABLE; - } + if (!input_ffmpeg_supported()) + throw PluginUnavailable("No protocol"); return InputPlugin::InitResult::SUCCESS; } diff --git a/src/input/plugins/SmbclientInputPlugin.cxx b/src/input/plugins/SmbclientInputPlugin.cxx index 97be5c47a..948ed8160 100644 --- a/src/input/plugins/SmbclientInputPlugin.cxx +++ b/src/input/plugins/SmbclientInputPlugin.cxx @@ -23,6 +23,7 @@ #include "lib/smbclient/Mutex.hxx" #include "../InputStream.hxx" #include "../InputPlugin.hxx" +#include "PluginUnavailable.hxx" #include "util/StringCompare.hxx" #include "util/Error.hxx" @@ -73,7 +74,8 @@ input_smbclient_init(gcc_unused const ConfigBlock &block, gcc_unused Error &erro try { SmbclientInit(); } catch (const std::runtime_error &e) { - return InputPlugin::InitResult::UNAVAILABLE; + // TODO: use std::throw_with_nested()? + throw PluginUnavailable(e.what()); } // TODO: create one global SMBCCTX here?