input/Plugin: add attribute prefixes
This commit is contained in:
parent
9ec86acb9c
commit
3e78c9ab48
35
src/input/InputPlugin.cxx
Normal file
35
src/input/InputPlugin.cxx
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2003-2018 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 "InputPlugin.hxx"
|
||||||
|
#include "util/StringCompare.hxx"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
bool
|
||||||
|
InputPlugin::SupportsUri(const char *uri) const noexcept
|
||||||
|
{
|
||||||
|
assert(prefixes != nullptr);
|
||||||
|
|
||||||
|
for (auto i = prefixes; *i != nullptr; ++i)
|
||||||
|
if (StringStartsWithIgnoreCase(uri, *i))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@ -21,6 +21,7 @@
|
|||||||
#define MPD_INPUT_PLUGIN_HXX
|
#define MPD_INPUT_PLUGIN_HXX
|
||||||
|
|
||||||
#include "Ptr.hxx"
|
#include "Ptr.hxx"
|
||||||
|
#include "util/Compiler.h"
|
||||||
|
|
||||||
struct ConfigBlock;
|
struct ConfigBlock;
|
||||||
class Mutex;
|
class Mutex;
|
||||||
@ -31,6 +32,12 @@ class RemoteTagHandler;
|
|||||||
struct InputPlugin {
|
struct InputPlugin {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A nullptr-terminated list of URI prefixes handled by this
|
||||||
|
* plugin. This is usually a string in the form "scheme://".
|
||||||
|
*/
|
||||||
|
const char *const*prefixes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global initialization. This method is called when MPD starts.
|
* Global initialization. This method is called when MPD starts.
|
||||||
*
|
*
|
||||||
@ -66,6 +73,9 @@ struct InputPlugin {
|
|||||||
*/
|
*/
|
||||||
std::unique_ptr<RemoteTagScanner> (*scan_tags)(const char *uri,
|
std::unique_ptr<RemoteTagScanner> (*scan_tags)(const char *uri,
|
||||||
RemoteTagHandler &handler) = nullptr;
|
RemoteTagHandler &handler) = nullptr;
|
||||||
|
|
||||||
|
gcc_pure
|
||||||
|
bool SupportsUri(const char *uri) const noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -38,6 +38,9 @@ InputStream::Open(const char *url, Mutex &mutex)
|
|||||||
}
|
}
|
||||||
|
|
||||||
input_plugins_for_each_enabled(plugin) {
|
input_plugins_for_each_enabled(plugin) {
|
||||||
|
if (!plugin->SupportsUri(url))
|
||||||
|
continue;
|
||||||
|
|
||||||
auto is = plugin->open(url, mutex);
|
auto is = plugin->open(url, mutex);
|
||||||
if (is != nullptr)
|
if (is != nullptr)
|
||||||
return input_rewind_open(std::move(is));
|
return input_rewind_open(std::move(is));
|
||||||
|
@ -27,7 +27,7 @@ std::unique_ptr<RemoteTagScanner>
|
|||||||
InputScanTags(const char *uri, RemoteTagHandler &handler)
|
InputScanTags(const char *uri, RemoteTagHandler &handler)
|
||||||
{
|
{
|
||||||
input_plugins_for_each_enabled(plugin) {
|
input_plugins_for_each_enabled(plugin) {
|
||||||
if (plugin->scan_tags == nullptr)
|
if (plugin->scan_tags == nullptr || !plugin->SupportsUri(uri))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto scanner = plugin->scan_tags(uri, handler);
|
auto scanner = plugin->scan_tags(uri, handler);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
input_api = static_library(
|
input_api = static_library(
|
||||||
'input_api',
|
'input_api',
|
||||||
'Error.cxx',
|
'Error.cxx',
|
||||||
|
'InputPlugin.cxx',
|
||||||
'InputStream.cxx',
|
'InputStream.cxx',
|
||||||
'ThreadInputStream.cxx',
|
'ThreadInputStream.cxx',
|
||||||
'AsyncInputStream.cxx',
|
'AsyncInputStream.cxx',
|
||||||
|
@ -409,8 +409,14 @@ alsa_input_open(const char *uri, Mutex &mutex)
|
|||||||
mutex);
|
mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr const char *alsa_prefixes[] = {
|
||||||
|
"alsa://",
|
||||||
|
nullptr
|
||||||
|
};
|
||||||
|
|
||||||
const struct InputPlugin input_plugin_alsa = {
|
const struct InputPlugin input_plugin_alsa = {
|
||||||
"alsa",
|
"alsa",
|
||||||
|
alsa_prefixes,
|
||||||
alsa_input_init,
|
alsa_input_init,
|
||||||
nullptr,
|
nullptr,
|
||||||
alsa_input_open,
|
alsa_input_open,
|
||||||
|
@ -357,8 +357,14 @@ CdioParanoiaInputStream::IsEOF() noexcept
|
|||||||
return lsn_from + lsn_relofs > lsn_to;
|
return lsn_from + lsn_relofs > lsn_to;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr const char *cdio_paranoia_prefixes[] = {
|
||||||
|
"cdda://",
|
||||||
|
nullptr
|
||||||
|
};
|
||||||
|
|
||||||
const InputPlugin input_plugin_cdio_paranoia = {
|
const InputPlugin input_plugin_cdio_paranoia = {
|
||||||
"cdio_paranoia",
|
"cdio_paranoia",
|
||||||
|
cdio_paranoia_prefixes,
|
||||||
input_cdio_init,
|
input_cdio_init,
|
||||||
nullptr,
|
nullptr,
|
||||||
input_cdio_open,
|
input_cdio_open,
|
||||||
|
@ -473,8 +473,15 @@ input_curl_open(const char *url, Mutex &mutex)
|
|||||||
return CurlInputStream::Open(url, {}, mutex);
|
return CurlInputStream::Open(url, {}, mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr const char *curl_prefixes[] = {
|
||||||
|
"http://",
|
||||||
|
"https://",
|
||||||
|
nullptr
|
||||||
|
};
|
||||||
|
|
||||||
const struct InputPlugin input_plugin_curl = {
|
const struct InputPlugin input_plugin_curl = {
|
||||||
"curl",
|
"curl",
|
||||||
|
curl_prefixes,
|
||||||
input_curl_init,
|
input_curl_init,
|
||||||
input_curl_finish,
|
input_curl_finish,
|
||||||
input_curl_open,
|
input_curl_open,
|
||||||
|
@ -85,14 +85,6 @@ static InputStreamPtr
|
|||||||
input_ffmpeg_open(const char *uri,
|
input_ffmpeg_open(const char *uri,
|
||||||
Mutex &mutex)
|
Mutex &mutex)
|
||||||
{
|
{
|
||||||
if (!StringStartsWithCaseASCII(uri, "gopher://") &&
|
|
||||||
!StringStartsWithCaseASCII(uri, "rtp://") &&
|
|
||||||
!StringStartsWithCaseASCII(uri, "rtsp://") &&
|
|
||||||
!StringStartsWithCaseASCII(uri, "rtmp://") &&
|
|
||||||
!StringStartsWithCaseASCII(uri, "rtmpt://") &&
|
|
||||||
!StringStartsWithCaseASCII(uri, "rtmps://"))
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
AVIOContext *h;
|
AVIOContext *h;
|
||||||
auto result = avio_open(&h, uri, AVIO_FLAG_READ);
|
auto result = avio_open(&h, uri, AVIO_FLAG_READ);
|
||||||
if (result != 0)
|
if (result != 0)
|
||||||
@ -146,8 +138,19 @@ FfmpegInputStream::Seek(offset_type new_offset)
|
|||||||
eof = false;
|
eof = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
input_ffmpeg_init,
|
input_ffmpeg_init,
|
||||||
nullptr,
|
nullptr,
|
||||||
input_ffmpeg_open,
|
input_ffmpeg_open,
|
||||||
|
@ -72,12 +72,6 @@ static InputStreamPtr
|
|||||||
input_mms_open(const char *url,
|
input_mms_open(const char *url,
|
||||||
Mutex &mutex)
|
Mutex &mutex)
|
||||||
{
|
{
|
||||||
if (!StringStartsWithCaseASCII(url, "mms://") &&
|
|
||||||
!StringStartsWithCaseASCII(url, "mmsh://") &&
|
|
||||||
!StringStartsWithCaseASCII(url, "mmst://") &&
|
|
||||||
!StringStartsWithCaseASCII(url, "mmsu://"))
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
auto m = std::make_unique<MmsInputStream>(url, mutex);
|
auto m = std::make_unique<MmsInputStream>(url, mutex);
|
||||||
m->Start();
|
m->Start();
|
||||||
return m;
|
return m;
|
||||||
@ -103,8 +97,17 @@ MmsInputStream::ThreadRead(void *ptr, size_t read_size)
|
|||||||
return (size_t)nbytes;
|
return (size_t)nbytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr const char *mms_prefixes[] = {
|
||||||
|
"mms://",
|
||||||
|
"mmsh://",
|
||||||
|
"mmst://",
|
||||||
|
"mmsu://",
|
||||||
|
nullptr
|
||||||
|
};
|
||||||
|
|
||||||
const InputPlugin input_plugin_mms = {
|
const InputPlugin input_plugin_mms = {
|
||||||
"mms",
|
"mms",
|
||||||
|
mms_prefixes,
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr,
|
nullptr,
|
||||||
input_mms_open,
|
input_mms_open,
|
||||||
|
@ -217,16 +217,19 @@ static InputStreamPtr
|
|||||||
input_nfs_open(const char *uri,
|
input_nfs_open(const char *uri,
|
||||||
Mutex &mutex)
|
Mutex &mutex)
|
||||||
{
|
{
|
||||||
if (!StringStartsWithCaseASCII(uri, "nfs://"))
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
auto is = std::make_unique<NfsInputStream>(uri, mutex);
|
auto is = std::make_unique<NfsInputStream>(uri, mutex);
|
||||||
is->Open();
|
is->Open();
|
||||||
return is;
|
return is;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr const char *nfs_prefixes[] = {
|
||||||
|
"nfs://",
|
||||||
|
nullptr
|
||||||
|
};
|
||||||
|
|
||||||
const InputPlugin input_plugin_nfs = {
|
const InputPlugin input_plugin_nfs = {
|
||||||
"nfs",
|
"nfs",
|
||||||
|
nfs_prefixes,
|
||||||
input_nfs_init,
|
input_nfs_init,
|
||||||
input_nfs_finish,
|
input_nfs_finish,
|
||||||
input_nfs_open,
|
input_nfs_open,
|
||||||
|
@ -209,8 +209,14 @@ ScanQobuzTags(const char *uri, RemoteTagHandler &handler)
|
|||||||
handler);
|
handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr const char *qobuz_prefixes[] = {
|
||||||
|
"qobuz://",
|
||||||
|
nullptr
|
||||||
|
};
|
||||||
|
|
||||||
const InputPlugin qobuz_input_plugin = {
|
const InputPlugin qobuz_input_plugin = {
|
||||||
"qobuz",
|
"qobuz",
|
||||||
|
qobuz_prefixes,
|
||||||
InitQobuzInput,
|
InitQobuzInput,
|
||||||
FinishQobuzInput,
|
FinishQobuzInput,
|
||||||
OpenQobuzInput,
|
OpenQobuzInput,
|
||||||
|
@ -87,9 +87,6 @@ static InputStreamPtr
|
|||||||
input_smbclient_open(const char *uri,
|
input_smbclient_open(const char *uri,
|
||||||
Mutex &mutex)
|
Mutex &mutex)
|
||||||
{
|
{
|
||||||
if (!StringStartsWithCaseASCII(uri, "smb://"))
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
const std::lock_guard<Mutex> protect(smbclient_mutex);
|
const std::lock_guard<Mutex> protect(smbclient_mutex);
|
||||||
|
|
||||||
SMBCCTX *ctx = smbc_new_context();
|
SMBCCTX *ctx = smbc_new_context();
|
||||||
@ -158,8 +155,14 @@ SmbclientInputStream::Seek(offset_type new_offset)
|
|||||||
offset = result;
|
offset = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr const char *smbclient_prefixes[] = {
|
||||||
|
"smb://",
|
||||||
|
nullptr
|
||||||
|
};
|
||||||
|
|
||||||
const InputPlugin input_plugin_smbclient = {
|
const InputPlugin input_plugin_smbclient = {
|
||||||
"smbclient",
|
"smbclient",
|
||||||
|
smbclient_prefixes,
|
||||||
input_smbclient_init,
|
input_smbclient_init,
|
||||||
nullptr,
|
nullptr,
|
||||||
input_smbclient_open,
|
input_smbclient_open,
|
||||||
|
@ -239,8 +239,14 @@ ScanTidalTags(const char *uri, RemoteTagHandler &handler)
|
|||||||
track_id, handler);
|
track_id, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr const char *tidal_prefixes[] = {
|
||||||
|
"tidal://",
|
||||||
|
nullptr
|
||||||
|
};
|
||||||
|
|
||||||
const InputPlugin tidal_input_plugin = {
|
const InputPlugin tidal_input_plugin = {
|
||||||
"tidal",
|
"tidal",
|
||||||
|
tidal_prefixes,
|
||||||
InitTidalInput,
|
InitTidalInput,
|
||||||
FinishTidalInput,
|
FinishTidalInput,
|
||||||
OpenTidalInput,
|
OpenTidalInput,
|
||||||
|
78
src/ls.cxx
78
src/ls.cxx
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@ -19,94 +19,42 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "ls.hxx"
|
#include "ls.hxx"
|
||||||
|
#include "input/Registry.hxx"
|
||||||
|
#include "input/InputPlugin.hxx"
|
||||||
#include "client/Response.hxx"
|
#include "client/Response.hxx"
|
||||||
#include "util/ASCII.hxx"
|
#include "util/ASCII.hxx"
|
||||||
#include "util/UriUtil.hxx"
|
#include "util/UriUtil.hxx"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
/**
|
|
||||||
* file:// is not included in remoteUrlPrefixes, the connection method
|
|
||||||
* is detected at runtime and displayed as a urlhandler if the client is
|
|
||||||
* connected by IPC socket.
|
|
||||||
*/
|
|
||||||
static const char *const remoteUrlPrefixes[] = {
|
|
||||||
#if defined(ENABLE_CURL)
|
|
||||||
"http://",
|
|
||||||
"https://",
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_MMS
|
|
||||||
"mms://",
|
|
||||||
"mmsh://",
|
|
||||||
"mmst://",
|
|
||||||
"mmsu://",
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_FFMPEG
|
|
||||||
"gopher://",
|
|
||||||
"rtp://",
|
|
||||||
"rtsp://",
|
|
||||||
"rtmp://",
|
|
||||||
"rtmpt://",
|
|
||||||
"rtmps://",
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_SMBCLIENT
|
|
||||||
"smb://",
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_NFS
|
|
||||||
"nfs://",
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_CDIO_PARANOIA
|
|
||||||
"cdda://",
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_ALSA
|
|
||||||
"alsa://",
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_QOBUZ
|
|
||||||
"qobuz://",
|
|
||||||
#endif
|
|
||||||
#ifdef ENABLE_TIDAL
|
|
||||||
"tidal://",
|
|
||||||
#endif
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
void print_supported_uri_schemes_to_fp(FILE *fp)
|
void print_supported_uri_schemes_to_fp(FILE *fp)
|
||||||
{
|
{
|
||||||
const char *const*prefixes = remoteUrlPrefixes;
|
|
||||||
|
|
||||||
#ifdef HAVE_UN
|
#ifdef HAVE_UN
|
||||||
fprintf(fp, " file://");
|
fprintf(fp, " file://");
|
||||||
#endif
|
#endif
|
||||||
while (*prefixes) {
|
input_plugins_for_each(plugin)
|
||||||
fprintf(fp, " %s", *prefixes);
|
for (auto i = plugin->prefixes; *i != nullptr; ++i)
|
||||||
prefixes++;
|
fprintf(fp, " %s", *i);
|
||||||
}
|
|
||||||
fprintf(fp,"\n");
|
fprintf(fp,"\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
print_supported_uri_schemes(Response &r)
|
print_supported_uri_schemes(Response &r)
|
||||||
{
|
{
|
||||||
const char *const *prefixes = remoteUrlPrefixes;
|
input_plugins_for_each_enabled(plugin)
|
||||||
|
for (auto i = plugin->prefixes; *i != nullptr; ++i)
|
||||||
while (*prefixes) {
|
r.Format("handler: %s\n", *i);
|
||||||
r.Format("handler: %s\n", *prefixes);
|
|
||||||
prefixes++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
uri_supported_scheme(const char *uri) noexcept
|
uri_supported_scheme(const char *uri) noexcept
|
||||||
{
|
{
|
||||||
const char *const*urlPrefixes = remoteUrlPrefixes;
|
|
||||||
|
|
||||||
assert(uri_has_scheme(uri));
|
assert(uri_has_scheme(uri));
|
||||||
|
|
||||||
while (*urlPrefixes) {
|
input_plugins_for_each_enabled(plugin)
|
||||||
if (StringStartsWithCaseASCII(uri, *urlPrefixes))
|
for (auto i = plugin->prefixes; *i != nullptr; ++i)
|
||||||
return true;
|
if (StringStartsWithCaseASCII(uri, *i))
|
||||||
urlPrefixes++;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
Loading…
Reference in New Issue
Block a user