diff --git a/Makefile.am b/Makefile.am index 0041320b9..51991920e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1198,6 +1198,7 @@ ENCODER_LIBS = \ $(VORBISENC_LIBS) libencoder_plugins_a_SOURCES = \ + src/encoder/Configured.cxx src/encoder/Configured.hxx \ src/encoder/EncoderAPI.hxx \ src/encoder/EncoderInterface.hxx \ src/encoder/EncoderPlugin.hxx \ diff --git a/src/encoder/Configured.cxx b/src/encoder/Configured.cxx new file mode 100644 index 000000000..4e6c900f8 --- /dev/null +++ b/src/encoder/Configured.cxx @@ -0,0 +1,57 @@ +/* + * Copyright 2003-2017 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. + */ + +#include "config.h" +#include "Configured.hxx" +#include "EncoderList.hxx" +#include "EncoderPlugin.hxx" +#include "config/Block.hxx" +#include "util/StringAPI.hxx" +#include "util/RuntimeError.hxx" + +static const EncoderPlugin & +GetConfiguredEncoderPlugin(const ConfigBlock &block, bool shout_legacy) +{ + const char *name = block.GetBlockValue("encoder", nullptr); + if (name == nullptr && shout_legacy) + name = block.GetBlockValue("encoding", nullptr); + + if (name == nullptr) + name = "vorbis"; + + if (shout_legacy) { + if (StringIsEqual(name, "ogg")) + name = "vorbis"; + else if (StringIsEqual(name, "mp3")) + name = "lame"; + } + + const auto plugin = encoder_plugin_get(name); + if (plugin == nullptr) + throw FormatRuntimeError("No such encoder: %s", name); + + return *plugin; +} + +PreparedEncoder * +CreateConfiguredEncoder(const ConfigBlock &block, bool shout_legacy) +{ + return encoder_init(GetConfiguredEncoderPlugin(block, shout_legacy), + block); +} diff --git a/src/encoder/Configured.hxx b/src/encoder/Configured.hxx new file mode 100644 index 000000000..b2ebd2d7d --- /dev/null +++ b/src/encoder/Configured.hxx @@ -0,0 +1,39 @@ +/* + * Copyright 2003-2017 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_ENCODER_CONFIGURED_HXX +#define MPD_ENCODER_CONFIGURED_HXX + +struct ConfigBlock; +class PreparedEncoder; + +/** + * Create a #PreparedEncoder instance from the settings in the + * #ConfigBlock. Its "encoder" setting is used to choose the encoder + * plugin. + * + * Throws an exception on error. + * + * @param shout_legacy enable the "shout" plugin legacy configuration? + * i.e. fall back to setting "encoding" instead of "encoder" + */ +PreparedEncoder * +CreateConfiguredEncoder(const ConfigBlock &block, bool shout_legacy=false); + +#endif diff --git a/src/output/plugins/RecorderOutputPlugin.cxx b/src/output/plugins/RecorderOutputPlugin.cxx index 1e561fb39..4d39df9e2 100644 --- a/src/output/plugins/RecorderOutputPlugin.cxx +++ b/src/output/plugins/RecorderOutputPlugin.cxx @@ -23,14 +23,12 @@ #include "tag/Format.hxx" #include "encoder/ToOutputStream.hxx" #include "encoder/EncoderInterface.hxx" -#include "encoder/EncoderPlugin.hxx" -#include "encoder/EncoderList.hxx" +#include "encoder/Configured.hxx" #include "config/ConfigError.hxx" #include "config/ConfigPath.hxx" #include "Log.hxx" #include "fs/AllocatedPath.hxx" #include "fs/io/FileOutputStream.hxx" -#include "util/RuntimeError.hxx" #include "util/Domain.hxx" #include "util/ScopeExit.hxx" @@ -109,16 +107,11 @@ private: }; RecorderOutput::RecorderOutput(const ConfigBlock &block) - :AudioOutput(0) + :AudioOutput(0), + prepared_encoder(CreateConfiguredEncoder(block)) { /* read configuration */ - const char *encoder_name = - block.GetBlockValue("encoder", "vorbis"); - const auto encoder_plugin = encoder_plugin_get(encoder_name); - if (encoder_plugin == nullptr) - throw FormatRuntimeError("No such encoder: %s", encoder_name); - path = block.GetPath("path"); const char *fmt = block.GetBlockValue("format_path", nullptr); @@ -130,10 +123,6 @@ RecorderOutput::RecorderOutput(const ConfigBlock &block) if (!path.IsNull() && fmt != nullptr) throw std::runtime_error("Cannot have both 'path' and 'format_path'"); - - /* initialize encoder */ - - prepared_encoder.reset(encoder_init(*encoder_plugin, block)); } inline void diff --git a/src/output/plugins/ShoutOutputPlugin.cxx b/src/output/plugins/ShoutOutputPlugin.cxx index b30dae91d..6485e4140 100644 --- a/src/output/plugins/ShoutOutputPlugin.cxx +++ b/src/output/plugins/ShoutOutputPlugin.cxx @@ -21,8 +21,7 @@ #include "ShoutOutputPlugin.hxx" #include "../OutputAPI.hxx" #include "encoder/EncoderInterface.hxx" -#include "encoder/EncoderPlugin.hxx" -#include "encoder/EncoderList.hxx" +#include "encoder/Configured.hxx" #include "util/RuntimeError.hxx" #include "util/Domain.hxx" #include "util/StringAPI.hxx" @@ -88,17 +87,6 @@ require_block_string(const ConfigBlock &block, const char *name) return value; } -static const EncoderPlugin * -shout_encoder_plugin_get(const char *name) -{ - if (strcmp(name, "ogg") == 0) - name = "vorbis"; - else if (strcmp(name, "mp3") == 0) - name = "lame"; - - return encoder_plugin_get(name); -} - static void ShoutSetAudioInfo(shout_t *shout_conn, const AudioFormat &audio_format) { @@ -114,7 +102,8 @@ ShoutSetAudioInfo(shout_t *shout_conn, const AudioFormat &audio_format) ShoutOutput::ShoutOutput(const ConfigBlock &block) :AudioOutput(FLAG_PAUSE), shout_conn(shout_new()), - shout_meta(shout_metadata_new()) + shout_meta(shout_metadata_new()), + prepared_encoder(CreateConfiguredEncoder(block, true)) { NeedFullyDefinedAudioFormat(); @@ -156,16 +145,6 @@ ShoutOutput::ShoutOutput(const ConfigBlock &block) throw std::runtime_error("bitrate must be a positive integer"); } - const char *encoding = block.GetBlockValue("encoder", nullptr); - if (encoding == nullptr) - encoding = block.GetBlockValue("encoding", "vorbis"); - const auto encoder_plugin = shout_encoder_plugin_get(encoding); - if (encoder_plugin == nullptr) - throw FormatRuntimeError("couldn't find shout encoder plugin \"%s\"", - encoding); - - prepared_encoder.reset(encoder_init(*encoder_plugin, block)); - const char *const mime_type = prepared_encoder->GetMimeType(); unsigned shout_format; diff --git a/src/output/plugins/httpd/HttpdOutputPlugin.cxx b/src/output/plugins/httpd/HttpdOutputPlugin.cxx index 49a7c8f5b..731a5053a 100644 --- a/src/output/plugins/httpd/HttpdOutputPlugin.cxx +++ b/src/output/plugins/httpd/HttpdOutputPlugin.cxx @@ -23,15 +23,13 @@ #include "HttpdClient.hxx" #include "output/OutputAPI.hxx" #include "encoder/EncoderInterface.hxx" -#include "encoder/EncoderPlugin.hxx" -#include "encoder/EncoderList.hxx" +#include "encoder/Configured.hxx" #include "net/UniqueSocketDescriptor.hxx" #include "net/SocketAddress.hxx" #include "net/ToString.hxx" #include "Page.hxx" #include "IcyMetaDataServer.hxx" #include "event/Call.hxx" -#include "util/RuntimeError.hxx" #include "util/Domain.hxx" #include "util/DeleteDisposer.hxx" #include "Log.hxx" @@ -52,6 +50,7 @@ inline HttpdOutput::HttpdOutput(EventLoop &_loop, const ConfigBlock &block) :AudioOutput(FLAG_ENABLE_DISABLE|FLAG_PAUSE), ServerSocket(_loop), + prepared_encoder(CreateConfiguredEncoder(block)), defer_broadcast(_loop, BIND_THIS_METHOD(OnDeferredBroadcast)) { /* read configuration */ @@ -61,12 +60,6 @@ HttpdOutput::HttpdOutput(EventLoop &_loop, const ConfigBlock &block) unsigned port = block.GetBlockValue("port", 8000u); - const char *encoder_name = - block.GetBlockValue("encoder", "vorbis"); - const auto encoder_plugin = encoder_plugin_get(encoder_name); - if (encoder_plugin == nullptr) - throw FormatRuntimeError("No such encoder: %s", encoder_name); - clients_max = block.GetBlockValue("max_clients", 0u); /* set up bind_to_address */ @@ -77,10 +70,6 @@ HttpdOutput::HttpdOutput(EventLoop &_loop, const ConfigBlock &block) else AddPort(port); - /* initialize encoder */ - - prepared_encoder.reset(encoder_init(*encoder_plugin, block)); - /* determine content type */ content_type = prepared_encoder->GetMimeType(); if (content_type == nullptr)