diff options
-rw-r--r-- | src/SongFilter.hxx | 16 | ||||
-rw-r--r-- | src/db/ProxyDatabasePlugin.cxx | 39 |
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, |