Merge branch 'runtime_enumeration' of git://github.com/eugene2k/MPD
This commit is contained in:
commit
44aaf51345
@ -21,15 +21,54 @@
|
|||||||
#include "util/StringCompare.hxx"
|
#include "util/StringCompare.hxx"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
bool
|
bool
|
||||||
InputPlugin::SupportsUri(const char *uri) const noexcept
|
InputPlugin::SupportsUri(const char *uri) const noexcept
|
||||||
{
|
{
|
||||||
assert(prefixes != nullptr);
|
assert(prefixes || protocols);
|
||||||
|
if (prefixes != nullptr) {
|
||||||
for (auto i = prefixes; *i != nullptr; ++i)
|
for (auto i = prefixes; *i != nullptr; ++i)
|
||||||
if (StringStartsWithIgnoreCase(uri, *i))
|
if (StringStartsWithIgnoreCase(uri, *i))
|
||||||
return true;
|
return true;
|
||||||
|
} else {
|
||||||
|
for (auto schema : protocols()) {
|
||||||
|
if (StringStartsWithIgnoreCase(uri, schema.c_str())){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note: The whitelist has to be ordered alphabetically
|
||||||
|
constexpr static const char *whitelist[] = {
|
||||||
|
"ftp",
|
||||||
|
"ftps",
|
||||||
|
"gopher",
|
||||||
|
"http",
|
||||||
|
"https",
|
||||||
|
"mmsh",
|
||||||
|
"mmst",
|
||||||
|
"rtmp",
|
||||||
|
"rtmpe",
|
||||||
|
"rtmps",
|
||||||
|
"rtmpt",
|
||||||
|
"rtmpte",
|
||||||
|
"rtmpts",
|
||||||
|
"rtp",
|
||||||
|
"scp",
|
||||||
|
"sftp",
|
||||||
|
"smb",
|
||||||
|
"srtp",
|
||||||
|
};
|
||||||
|
|
||||||
|
bool
|
||||||
|
protocol_is_whitelisted(const char *proto) {
|
||||||
|
auto begin = std::begin(whitelist);
|
||||||
|
auto end = std::end(whitelist);
|
||||||
|
return std::binary_search(begin, end, proto, [](const char* a, const char* b) {
|
||||||
|
return strcasecmp(a,b) < 0;
|
||||||
|
});
|
||||||
|
}
|
@ -23,6 +23,9 @@
|
|||||||
#include "Ptr.hxx"
|
#include "Ptr.hxx"
|
||||||
#include "thread/Mutex.hxx"
|
#include "thread/Mutex.hxx"
|
||||||
#include "util/Compiler.h"
|
#include "util/Compiler.h"
|
||||||
|
#include <assert.h>
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
struct ConfigBlock;
|
struct ConfigBlock;
|
||||||
class EventLoop;
|
class EventLoop;
|
||||||
@ -62,6 +65,11 @@ struct InputPlugin {
|
|||||||
*/
|
*/
|
||||||
InputStreamPtr (*open)(const char *uri, Mutex &mutex);
|
InputStreamPtr (*open)(const char *uri, Mutex &mutex);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return a set of supported protocols
|
||||||
|
*/
|
||||||
|
std::set<std::string> (*protocols)();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare a #RemoteTagScanner. The operation must be started
|
* Prepare a #RemoteTagScanner. The operation must be started
|
||||||
* using RemoteTagScanner::Start(). Returns nullptr if the
|
* using RemoteTagScanner::Start(). Returns nullptr if the
|
||||||
@ -76,6 +84,25 @@ struct InputPlugin {
|
|||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool SupportsUri(const char *uri) const noexcept;
|
bool SupportsUri(const char *uri) const noexcept;
|
||||||
|
|
||||||
|
template<typename F>
|
||||||
|
void ForeachSupportedUri(F lambda) const noexcept {
|
||||||
|
assert(prefixes || protocols);
|
||||||
|
|
||||||
|
if (prefixes != nullptr) {
|
||||||
|
for (auto schema = prefixes; *schema != nullptr; ++schema) {
|
||||||
|
lambda(*schema);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (protocols != nullptr) {
|
||||||
|
for (auto schema : protocols()) {
|
||||||
|
lambda(schema.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool
|
||||||
|
protocol_is_whitelisted(const char *proto);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -486,4 +486,5 @@ const struct InputPlugin input_plugin_alsa = {
|
|||||||
alsa_input_init,
|
alsa_input_init,
|
||||||
nullptr,
|
nullptr,
|
||||||
alsa_input_open,
|
alsa_input_open,
|
||||||
|
nullptr
|
||||||
};
|
};
|
||||||
|
@ -360,4 +360,5 @@ const InputPlugin input_plugin_cdio_paranoia = {
|
|||||||
input_cdio_init,
|
input_cdio_init,
|
||||||
nullptr,
|
nullptr,
|
||||||
input_cdio_open,
|
input_cdio_open,
|
||||||
|
nullptr
|
||||||
};
|
};
|
||||||
|
@ -470,16 +470,25 @@ input_curl_open(const char *url, Mutex &mutex)
|
|||||||
return CurlInputStream::Open(url, {}, mutex);
|
return CurlInputStream::Open(url, {}, mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr const char *curl_prefixes[] = {
|
static std::set<std::string>
|
||||||
"http://",
|
input_curl_protocols() {
|
||||||
"https://",
|
std::set<std::string> protocols;
|
||||||
nullptr
|
auto version_info = curl_version_info(CURLVERSION_FIRST);
|
||||||
};
|
for (auto proto_ptr = version_info->protocols; *proto_ptr != nullptr; proto_ptr++) {
|
||||||
|
if (protocol_is_whitelisted(*proto_ptr)) {
|
||||||
|
std::string schema(*proto_ptr);
|
||||||
|
schema.append("://");
|
||||||
|
protocols.emplace(schema);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return protocols;
|
||||||
|
}
|
||||||
|
|
||||||
const struct InputPlugin input_plugin_curl = {
|
const struct InputPlugin input_plugin_curl = {
|
||||||
"curl",
|
"curl",
|
||||||
curl_prefixes,
|
nullptr,
|
||||||
input_curl_init,
|
input_curl_init,
|
||||||
input_curl_finish,
|
input_curl_finish,
|
||||||
input_curl_open,
|
input_curl_open,
|
||||||
|
input_curl_protocols
|
||||||
};
|
};
|
||||||
|
@ -25,8 +25,13 @@
|
|||||||
#include "lib/ffmpeg/Init.hxx"
|
#include "lib/ffmpeg/Init.hxx"
|
||||||
#include "lib/ffmpeg/Error.hxx"
|
#include "lib/ffmpeg/Error.hxx"
|
||||||
#include "../InputStream.hxx"
|
#include "../InputStream.hxx"
|
||||||
#include "../InputPlugin.hxx"
|
|
||||||
#include "PluginUnavailable.hxx"
|
#include "PluginUnavailable.hxx"
|
||||||
|
#include "util/StringAPI.hxx"
|
||||||
|
#include "../InputPlugin.hxx"
|
||||||
|
#include <iostream>
|
||||||
|
#include <exception>
|
||||||
|
#include <typeinfo>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
class FfmpegInputStream final : public InputStream {
|
class FfmpegInputStream final : public InputStream {
|
||||||
Ffmpeg::IOContext io;
|
Ffmpeg::IOContext io;
|
||||||
@ -73,6 +78,22 @@ input_ffmpeg_init(EventLoop &, const ConfigBlock &)
|
|||||||
throw PluginUnavailable("No protocol");
|
throw PluginUnavailable("No protocol");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::set<std::string>
|
||||||
|
input_ffmpeg_protocols() {
|
||||||
|
void *opaque = nullptr;
|
||||||
|
const char* protocol;
|
||||||
|
std::set<std::string> protocols;
|
||||||
|
while ((protocol = avio_enum_protocols(&opaque, 0))) {
|
||||||
|
if (protocol_is_whitelisted(protocol)) {
|
||||||
|
std::string schema(protocol);
|
||||||
|
schema.append("://");
|
||||||
|
protocols.emplace(schema);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return protocols;
|
||||||
|
}
|
||||||
|
|
||||||
static InputStreamPtr
|
static InputStreamPtr
|
||||||
input_ffmpeg_open(const char *uri,
|
input_ffmpeg_open(const char *uri,
|
||||||
Mutex &mutex)
|
Mutex &mutex)
|
||||||
@ -114,20 +135,11 @@ FfmpegInputStream::Seek(std::unique_lock<Mutex> &, offset_type new_offset)
|
|||||||
offset = result;
|
offset = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr const char *ffmpeg_prefixes[] = {
|
|
||||||
"gopher://",
|
|
||||||
"rtp://",
|
|
||||||
"rtsp://",
|
|
||||||
"rtmp://",
|
|
||||||
"rtmpt://",
|
|
||||||
"rtmps://",
|
|
||||||
nullptr
|
|
||||||
};
|
|
||||||
|
|
||||||
const InputPlugin input_plugin_ffmpeg = {
|
const InputPlugin input_plugin_ffmpeg = {
|
||||||
"ffmpeg",
|
"ffmpeg",
|
||||||
ffmpeg_prefixes,
|
nullptr,
|
||||||
input_ffmpeg_init,
|
input_ffmpeg_init,
|
||||||
nullptr,
|
nullptr,
|
||||||
input_ffmpeg_open,
|
input_ffmpeg_open,
|
||||||
|
input_ffmpeg_protocols
|
||||||
};
|
};
|
||||||
|
@ -110,4 +110,5 @@ const InputPlugin input_plugin_mms = {
|
|||||||
nullptr,
|
nullptr,
|
||||||
nullptr,
|
nullptr,
|
||||||
input_mms_open,
|
input_mms_open,
|
||||||
|
nullptr
|
||||||
};
|
};
|
||||||
|
@ -232,4 +232,5 @@ const InputPlugin input_plugin_nfs = {
|
|||||||
input_nfs_init,
|
input_nfs_init,
|
||||||
input_nfs_finish,
|
input_nfs_finish,
|
||||||
input_nfs_open,
|
input_nfs_open,
|
||||||
|
nullptr
|
||||||
};
|
};
|
||||||
|
@ -219,5 +219,6 @@ const InputPlugin qobuz_input_plugin = {
|
|||||||
InitQobuzInput,
|
InitQobuzInput,
|
||||||
FinishQobuzInput,
|
FinishQobuzInput,
|
||||||
OpenQobuzInput,
|
OpenQobuzInput,
|
||||||
|
nullptr,
|
||||||
ScanQobuzTags,
|
ScanQobuzTags,
|
||||||
};
|
};
|
||||||
|
@ -166,4 +166,5 @@ const InputPlugin input_plugin_smbclient = {
|
|||||||
input_smbclient_init,
|
input_smbclient_init,
|
||||||
nullptr,
|
nullptr,
|
||||||
input_smbclient_open,
|
input_smbclient_open,
|
||||||
|
nullptr
|
||||||
};
|
};
|
||||||
|
@ -251,5 +251,6 @@ const InputPlugin tidal_input_plugin = {
|
|||||||
InitTidalInput,
|
InitTidalInput,
|
||||||
FinishTidalInput,
|
FinishTidalInput,
|
||||||
OpenTidalInput,
|
OpenTidalInput,
|
||||||
|
nullptr,
|
||||||
ScanTidalTags,
|
ScanTidalTags,
|
||||||
};
|
};
|
||||||
|
27
src/ls.cxx
27
src/ls.cxx
@ -22,28 +22,41 @@
|
|||||||
#include "input/Registry.hxx"
|
#include "input/Registry.hxx"
|
||||||
#include "input/InputPlugin.hxx"
|
#include "input/InputPlugin.hxx"
|
||||||
#include "client/Response.hxx"
|
#include "client/Response.hxx"
|
||||||
#include "util/ASCII.hxx"
|
|
||||||
#include "util/UriUtil.hxx"
|
#include "util/UriUtil.hxx"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
void print_supported_uri_schemes_to_fp(FILE *fp)
|
void print_supported_uri_schemes_to_fp(FILE *fp)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_UN
|
#ifdef HAVE_UN
|
||||||
fprintf(fp, " file://");
|
fprintf(fp, " file://");
|
||||||
#endif
|
#endif
|
||||||
|
std::set<std::string> protocols;
|
||||||
input_plugins_for_each(plugin)
|
input_plugins_for_each(plugin)
|
||||||
for (auto i = plugin->prefixes; *i != nullptr; ++i)
|
plugin->ForeachSupportedUri([&](const char* uri) {
|
||||||
fprintf(fp, " %s", *i);
|
protocols.emplace(uri);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (auto protocol : protocols) {
|
||||||
|
fprintf(fp, " %s", protocol.c_str());
|
||||||
|
}
|
||||||
fprintf(fp,"\n");
|
fprintf(fp,"\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
print_supported_uri_schemes(Response &r)
|
print_supported_uri_schemes(Response &r)
|
||||||
{
|
{
|
||||||
|
std::set<std::string> protocols;
|
||||||
input_plugins_for_each_enabled(plugin)
|
input_plugins_for_each_enabled(plugin)
|
||||||
for (auto i = plugin->prefixes; *i != nullptr; ++i)
|
plugin->ForeachSupportedUri([&](const char* uri) {
|
||||||
r.Format("handler: %s\n", *i);
|
protocols.emplace(uri);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (auto protocol : protocols) {
|
||||||
|
r.Format("handler: %s\n", protocol.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -52,9 +65,7 @@ uri_supported_scheme(const char *uri) noexcept
|
|||||||
assert(uri_has_scheme(uri));
|
assert(uri_has_scheme(uri));
|
||||||
|
|
||||||
input_plugins_for_each_enabled(plugin)
|
input_plugins_for_each_enabled(plugin)
|
||||||
for (auto i = plugin->prefixes; *i != nullptr; ++i)
|
return plugin->SupportsUri(uri);
|
||||||
if (StringStartsWithCaseASCII(uri, *i))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user