db/proxy: require MPD 0.21 or later

This commit is contained in:
Max Kellermann 2023-03-10 13:40:08 +01:00
parent 3be8375e4f
commit e927655774
2 changed files with 31 additions and 37 deletions

2
NEWS
View File

@ -9,6 +9,8 @@ ver 0.24 (not yet released)
- operator "starts_with" - operator "starts_with"
- show PCRE support in "config" response - show PCRE support in "config" response
- apply Unicode normalization to case-insensitive filter expressions - apply Unicode normalization to case-insensitive filter expressions
* database
- proxy: require MPD 0.21 or later
* archive * archive
- add option to disable archive plugins in mpd.conf - add option to disable archive plugins in mpd.conf
* input * input

View File

@ -306,6 +306,8 @@ CheckError(struct mpd_connection *connection)
ThrowError(connection); ThrowError(connection);
} }
#if !LIBMPDCLIENT_CHECK_VERSION(2, 15, 0)
static bool static bool
SendConstraints(mpd_connection *connection, const ISongFilter &f) SendConstraints(mpd_connection *connection, const ISongFilter &f)
{ {
@ -343,20 +345,19 @@ SendConstraints(mpd_connection *connection, const ISongFilter &f)
return true; return true;
} }
#endif
static bool static bool
SendConstraints(mpd_connection *connection, const SongFilter &filter) SendConstraints(mpd_connection *connection, const SongFilter &filter)
{ {
#if LIBMPDCLIENT_CHECK_VERSION(2, 15, 0) #if LIBMPDCLIENT_CHECK_VERSION(2, 15, 0)
if (mpd_connection_cmp_server_version(connection, 0, 21, 0) >= 0) return mpd_search_add_expression(connection,
/* with MPD 0.21 (and libmpdclient 2.15), we can pass filter.ToExpression().c_str());
arbitrary filters as expression */ #else
return mpd_search_add_expression(connection,
filter.ToExpression().c_str());
#endif
return std::all_of( return std::all_of(
filter.GetItems().begin(), filter.GetItems().end(), filter.GetItems().begin(), filter.GetItems().end(),
[=](const auto &item) { return SendConstraints(connection, *item); }); [=](const auto &item) { return SendConstraints(connection, *item); });
#endif
} }
static bool static bool
@ -373,8 +374,7 @@ SendConstraints(mpd_connection *connection, const DatabaseSelection &selection,
!SendConstraints(connection, *selection.filter)) !SendConstraints(connection, *selection.filter))
return false; return false;
if (selection.sort != TAG_NUM_OF_ITEM_TYPES && if (selection.sort != TAG_NUM_OF_ITEM_TYPES) {
mpd_connection_cmp_server_version(connection, 0, 21, 0) >= 0) {
#if LIBMPDCLIENT_CHECK_VERSION(2, 15, 0) #if LIBMPDCLIENT_CHECK_VERSION(2, 15, 0)
if (selection.sort == SORT_TAG_LAST_MODIFIED) { if (selection.sort == SORT_TAG_LAST_MODIFIED) {
if (!mpd_search_add_sort_name(connection, "Last-Modified", if (!mpd_search_add_sort_name(connection, "Last-Modified",
@ -487,11 +487,11 @@ ProxyDatabase::Connect()
try { try {
CheckError(connection); CheckError(connection);
if (mpd_connection_cmp_server_version(connection, 0, 20, 0) < 0) { if (mpd_connection_cmp_server_version(connection, 0, 21, 0) < 0) {
const unsigned *version = const unsigned *version =
mpd_connection_get_server_version(connection); mpd_connection_get_server_version(connection);
throw FmtRuntimeError("Connect to MPD {}.{}.{}, but this " throw FmtRuntimeError("Connect to MPD {}.{}.{}, but this "
"plugin requires at least version 0.20", "plugin requires at least version 0.21",
version[0], version[1], version[2]); version[0], version[1], version[2]);
} }
@ -863,6 +863,8 @@ try {
throw; throw;
} }
#if !LIBMPDCLIENT_CHECK_VERSION(2, 15, 0)
[[gnu::pure]] [[gnu::pure]]
static bool static bool
IsFilterSupported(const ISongFilter &f) noexcept IsFilterSupported(const ISongFilter &f) noexcept
@ -889,42 +891,33 @@ IsFilterSupported(const ISongFilter &f) noexcept
return false; return false;
} }
[[gnu::pure]]
static bool
IsFilterFullySupported(const SongFilter &filter,
const struct mpd_connection *connection) noexcept
{
#if LIBMPDCLIENT_CHECK_VERSION(2, 15, 0)
if (mpd_connection_cmp_server_version(connection, 0, 21, 0) >= 0)
/* with MPD 0.21 (and libmpdclient 2.15), we can pass
arbitrary filters as expression */
return true;
#else
(void)connection;
#endif #endif
[[gnu::pure]]
static bool
IsFilterFullySupported(const SongFilter &filter) noexcept
{
#if LIBMPDCLIENT_CHECK_VERSION(2, 15, 0)
(void)filter;
return true;
#else
return std::all_of(filter.GetItems().begin(), filter.GetItems().end(), return std::all_of(filter.GetItems().begin(), filter.GetItems().end(),
[](const auto &item) { return IsFilterSupported(*item); }); [](const auto &item) { return IsFilterSupported(*item); });
#endif
} }
[[gnu::pure]] [[gnu::pure]]
static bool static bool
IsFilterFullySupported(const SongFilter *filter, IsFilterFullySupported(const SongFilter *filter) noexcept
const struct mpd_connection *connection) noexcept
{ {
return filter == nullptr || return filter == nullptr ||
IsFilterFullySupported(*filter, connection); IsFilterFullySupported(*filter);
} }
[[gnu::pure]] [[gnu::pure]]
static bool static bool
IsSortSupported(TagType tag_type, IsSortSupported(TagType tag_type) noexcept
const struct mpd_connection *connection) noexcept
{ {
if (mpd_connection_cmp_server_version(connection, 0, 21, 0) < 0)
/* sorting requires MPD 0.21 */
return false;
if (tag_type == TagType(SORT_TAG_LAST_MODIFIED)) { if (tag_type == TagType(SORT_TAG_LAST_MODIFIED)) {
/* sort "Last-Modified" requires libmpdclient 2.15 for /* sort "Last-Modified" requires libmpdclient 2.15 for
mpd_search_add_sort_name() */ mpd_search_add_sort_name() */
@ -940,20 +933,19 @@ IsSortSupported(TagType tag_type,
[[gnu::pure]] [[gnu::pure]]
static DatabaseSelection static DatabaseSelection
CheckSelection(DatabaseSelection selection, CheckSelection(DatabaseSelection selection) noexcept
struct mpd_connection *connection) noexcept
{ {
selection.uri.clear(); selection.uri.clear();
selection.filter = nullptr; selection.filter = nullptr;
if (selection.sort != TAG_NUM_OF_ITEM_TYPES && if (selection.sort != TAG_NUM_OF_ITEM_TYPES &&
IsSortSupported(selection.sort, connection)) IsSortSupported(selection.sort))
/* we can forward the "sort" parameter to the other /* we can forward the "sort" parameter to the other
MPD */ MPD */
selection.sort = TAG_NUM_OF_ITEM_TYPES; selection.sort = TAG_NUM_OF_ITEM_TYPES;
if (selection.window != RangeArg::All() && if (selection.window != RangeArg::All() &&
IsFilterFullySupported(selection.filter, connection)) IsFilterFullySupported(selection.filter))
/* we can forward the "window" parameter to the other /* we can forward the "window" parameter to the other
MPD */ MPD */
selection.window = RangeArg::All(); selection.window = RangeArg::All();
@ -970,7 +962,7 @@ ProxyDatabase::Visit(const DatabaseSelection &selection,
// TODO: eliminate the const_cast // TODO: eliminate the const_cast
const_cast<ProxyDatabase *>(this)->EnsureConnected(); const_cast<ProxyDatabase *>(this)->EnsureConnected();
DatabaseVisitorHelper helper(CheckSelection(selection, connection), DatabaseVisitorHelper helper(CheckSelection(selection),
visit_song); visit_song);
if (!visit_directory && !visit_playlist && selection.recursive && if (!visit_directory && !visit_playlist && selection.recursive &&