summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Kellermann <max@musicpd.org>2018-09-02 11:02:50 +0200
committerMax Kellermann <max@musicpd.org>2018-09-02 17:51:30 +0200
commita8e70f09016ed844578e79e63649553ee8f247ae (patch)
treeeefa28db60b76d33a2aee61ee274fc8e597427fb
parentc7c32a3ce92f4fa483a4a1b41aa39cdaa0afcf45 (diff)
db/proxy: forward `sort` and `window` to server
-rw-r--r--NEWS1
-rw-r--r--src/db/plugins/ProxyDatabasePlugin.cxx137
2 files changed, 135 insertions, 3 deletions
diff --git a/NEWS b/NEWS
index dc967f6b0..4fbbe18a2 100644
--- a/NEWS
+++ b/NEWS
@@ -12,6 +12,7 @@ ver 0.21 (not yet released)
* database
- simple: scan audio formats
- proxy: require libmpdclient 2.9
+ - proxy: forward `sort` and `window` to server
* player
- "one-shot" single mode
* input
diff --git a/src/db/plugins/ProxyDatabasePlugin.cxx b/src/db/plugins/ProxyDatabasePlugin.cxx
index daeaa8477..6d0600c0c 100644
--- a/src/db/plugins/ProxyDatabasePlugin.cxx
+++ b/src/db/plugins/ProxyDatabasePlugin.cxx
@@ -367,6 +367,38 @@ SendConstraints(mpd_connection *connection, const DatabaseSelection &selection)
!SendConstraints(connection, *selection.filter))
return false;
+#if LIBMPDCLIENT_CHECK_VERSION(2, 11, 0)
+ 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 (selection.sort == SORT_TAG_LAST_MODIFIED) {
+ if (!mpd_search_add_sort_name(connection, "Last-Modified",
+ selection.descending))
+ return false;
+ } else {
+#endif
+ const auto sort = Convert(selection.sort);
+ /* if this is an unsupported tag, the sort
+ will be done later by class
+ DatabaseVisitorHelper */
+ if (sort != MPD_TAG_COUNT &&
+ !mpd_search_add_sort_tag(connection, sort,
+ selection.descending))
+ return false;
+#if LIBMPDCLIENT_CHECK_VERSION(2, 15, 0)
+ }
+#endif
+ }
+#endif
+
+#if LIBMPDCLIENT_CHECK_VERSION(2, 10, 0)
+ if (selection.window != RangeArg::All() &&
+ mpd_connection_cmp_server_version(connection, 0, 20, 0) >= 0 &&
+ !mpd_search_add_window(connection, selection.window.start,
+ selection.window.end))
+ return false;
+#endif
+
return true;
}
@@ -805,12 +837,110 @@ try {
throw;
}
-gcc_const
+#if LIBMPDCLIENT_CHECK_VERSION(2, 10, 0)
+
+gcc_pure
+static bool
+IsFilterSupported(const ISongFilter &f) noexcept
+{
+ if (auto t = dynamic_cast<const TagSongFilter *>(&f)) {
+ if (t->IsNegated())
+ // TODO implement
+ return false;
+
+ if (t->GetTagType() == TAG_NUM_OF_ITEM_TYPES)
+ return true;
+
+ const auto tag = Convert(t->GetTagType());
+ if (tag == MPD_TAG_COUNT)
+ return false;
+
+ return true;
+ } else if (auto u = dynamic_cast<const UriSongFilter *>(&f)) {
+ if (u->IsNegated())
+ // TODO implement
+ return false;
+
+ return false;
+ } else if (dynamic_cast<const BaseSongFilter *>(&f)) {
+ return true;
+ } else
+ return false;
+}
+
+gcc_pure
+static bool
+IsFilterFullySupported(const SongFilter &filter) noexcept
+{
+ for (const auto &i : filter.GetItems())
+ if (!IsFilterSupported(*i))
+ return false;
+
+ return true;
+}
+
+gcc_pure
+static bool
+IsFilterFullySupported(const SongFilter *filter) noexcept
+{
+ return filter == nullptr ||
+ IsFilterFullySupported(*filter);
+}
+
+#endif
+
+#if LIBMPDCLIENT_CHECK_VERSION(2, 11, 0)
+
+gcc_pure
+static bool
+IsSortSupported(TagType tag_type,
+ 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)) {
+ /* sort "Last-Modified" requires libmpdclient 2.15 for
+ mpd_search_add_sort_name() */
+#if LIBMPDCLIENT_CHECK_VERSION(2, 15, 0)
+ return true;
+#else
+ return false;
+#endif
+ }
+
+ return Convert(tag_type) != MPD_TAG_COUNT;
+}
+
+#endif
+
+gcc_pure
static DatabaseSelection
-CheckSelection(DatabaseSelection selection) noexcept
+CheckSelection(DatabaseSelection selection,
+ struct mpd_connection *connection) noexcept
{
selection.uri.clear();
selection.filter = nullptr;
+
+#if LIBMPDCLIENT_CHECK_VERSION(2, 11, 0)
+ if (selection.sort != TAG_NUM_OF_ITEM_TYPES &&
+ IsSortSupported(selection.sort, connection))
+ /* we can forward the "sort" parameter to the other
+ MPD */
+ selection.sort = TAG_NUM_OF_ITEM_TYPES;
+#endif
+
+#if LIBMPDCLIENT_CHECK_VERSION(2, 10, 0)
+ if (selection.window != RangeArg::All() &&
+ IsFilterFullySupported(selection.filter))
+ /* we can forward the "window" parameter to the other
+ MPD */
+ selection.window = RangeArg::All();
+#else
+ (void)connection;
+#endif
+
return selection;
}
@@ -823,7 +953,8 @@ ProxyDatabase::Visit(const DatabaseSelection &selection,
// TODO: eliminate the const_cast
const_cast<ProxyDatabase *>(this)->EnsureConnected();
- DatabaseVisitorHelper helper(CheckSelection(selection), visit_song);
+ DatabaseVisitorHelper helper(CheckSelection(selection, connection),
+ visit_song);
if (!visit_directory && !visit_playlist && selection.recursive &&
!selection.IsEmpty()) {