aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/SongFilter.hxx16
-rw-r--r--src/db/ProxyDatabasePlugin.cxx39
2 files changed, 54 insertions, 1 deletions
diff --git a/src/SongFilter.hxx b/src/SongFilter.hxx
index a71fe2cb1..a34fca8c2 100644
--- a/src/SongFilter.hxx
+++ b/src/SongFilter.hxx
@@ -61,6 +61,10 @@ public:
return tag;
}
+ bool GetFoldCase() const {
+ return fold_case;
+ }
+
const std::string &GetValue() const {
return value;
}
@@ -106,6 +110,18 @@ public:
}
/**
+ * Is there at least one item with "fold case" enabled?
+ */
+ gcc_pure
+ bool HasFoldCase() const {
+ for (const auto &i : items)
+ if (i.GetFoldCase())
+ return true;
+
+ return false;
+ }
+
+ /**
* Returns the "base" specification (if there is one) or an
* empty string.
*/
diff --git a/src/db/ProxyDatabasePlugin.cxx b/src/db/ProxyDatabasePlugin.cxx
index 5bab287ad..05d023668 100644
--- a/src/db/ProxyDatabasePlugin.cxx
+++ b/src/db/ProxyDatabasePlugin.cxx
@@ -472,6 +472,38 @@ Visit(struct mpd_connection *connection, const char *uri,
return CheckError(connection, error);
}
+static bool
+SearchSongs(struct mpd_connection *connection,
+ const DatabaseSelection &selection,
+ VisitSong visit_song,
+ Error &error)
+{
+ assert(selection.recursive);
+ assert(visit_song);
+
+ const bool exact = selection.filter == nullptr ||
+ !selection.filter->HasFoldCase();
+
+ if (!mpd_search_db_songs(connection, exact) ||
+ !SendConstraints(connection, selection) ||
+ !mpd_search_commit(connection))
+ return CheckError(connection, error);
+
+ bool result = true;
+ struct mpd_song *song;
+ while (result && (song = mpd_recv_song(connection)) != nullptr) {
+ Song *song2 = Convert(song);
+ mpd_song_free(song);
+
+ result = !Match(selection.filter, *song2) ||
+ visit_song(*song2, error);
+ song2->Free();
+ }
+
+ mpd_response_finish(connection);
+ return result && CheckError(connection, error);
+}
+
bool
ProxyDatabase::Visit(const DatabaseSelection &selection,
VisitDirectory visit_directory,
@@ -479,9 +511,14 @@ ProxyDatabase::Visit(const DatabaseSelection &selection,
VisitPlaylist visit_playlist,
Error &error) const
{
- // TODO: match
// TODO: auto-reconnect
+ if (!visit_directory && !visit_playlist && selection.recursive)
+ /* this optimized code path can only be used under
+ certain conditions */
+ return ::SearchSongs(connection, selection, visit_song, error);
+
+ /* fall back to recursive walk (slow!) */
return ::Visit(connection, selection.uri.c_str(),
selection.recursive, selection.filter,
visit_directory, visit_song, visit_playlist,