aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS1
-rw-r--r--doc/protocol.xml8
-rw-r--r--src/DatabaseSelection.cxx10
-rw-r--r--src/DatabaseSelection.hxx4
-rw-r--r--src/SongFilter.cxx27
-rw-r--r--src/SongFilter.hxx12
6 files changed, 57 insertions, 5 deletions
diff --git a/NEWS b/NEWS
index 8922ff562..15b88ff64 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,7 @@ ver 0.18 (2012/??/??)
- new command "readcomments" lists arbitrary file tags
- new command "toggleoutput"
- "find"/"search" with "any" does not match file name
+ - "search" and "find" with base URI (keyword "base")
- search for album artist falls back to the artist tag
- re-add the "volume" command
* input:
diff --git a/doc/protocol.xml b/doc/protocol.xml
index 234db46db..2068b6925 100644
--- a/doc/protocol.xml
+++ b/doc/protocol.xml
@@ -1483,9 +1483,13 @@ OK
<para>
Finds songs in the db that are exactly
<varname>WHAT</varname>. <varname>TYPE</varname> can
- be any tag supported by MPD, or one of the two special
+ be any tag supported by MPD, or one of the three special
parameters — <parameter>file</parameter> to search by
- full path (relative to database root), and
+
+ full path (relative to the music directory),
+ <parameter>in</parameter> to restrict the search to
+ songs in the given directory (also relative to the music
+ directory) and
<parameter>any</parameter> to match against all
available tags. <varname>WHAT</varname> is what to find.
</para>
diff --git a/src/DatabaseSelection.cxx b/src/DatabaseSelection.cxx
index a372d5862..2164ba2cd 100644
--- a/src/DatabaseSelection.cxx
+++ b/src/DatabaseSelection.cxx
@@ -20,6 +20,16 @@
#include "DatabaseSelection.hxx"
#include "SongFilter.hxx"
+DatabaseSelection::DatabaseSelection(const char *_uri, bool _recursive,
+ const SongFilter *_filter)
+ :uri(_uri), recursive(_recursive), filter(_filter)
+{
+ /* optimization: if the caller didn't specify a base URI, pick
+ the one from SongFilter */
+ if (uri.empty() && filter != nullptr)
+ uri = filter->GetBase();
+}
+
bool
DatabaseSelection::Match(const Song &song) const
{
diff --git a/src/DatabaseSelection.hxx b/src/DatabaseSelection.hxx
index 67a88b945..cdc0a8fef 100644
--- a/src/DatabaseSelection.hxx
+++ b/src/DatabaseSelection.hxx
@@ -42,9 +42,7 @@ struct DatabaseSelection {
const SongFilter *filter;
DatabaseSelection(const char *_uri, bool _recursive,
- const SongFilter *_filter=nullptr)
- :uri(_uri), recursive(_recursive), filter(_filter) {
- }
+ const SongFilter *_filter=nullptr);
gcc_pure
bool Match(const Song &song) const;
diff --git a/src/SongFilter.cxx b/src/SongFilter.cxx
index 7592f2665..396bd7191 100644
--- a/src/SongFilter.cxx
+++ b/src/SongFilter.cxx
@@ -22,6 +22,7 @@
#include "Song.hxx"
#include "tag/Tag.hxx"
#include "util/ASCII.hxx"
+#include "util/UriUtil.hxx"
#include <glib.h>
@@ -43,6 +44,9 @@ locate_parse_type(const char *str)
if (StringEqualsCaseASCII(str, LOCATE_TAG_ANY_KEY))
return LOCATE_TAG_ANY_TYPE;
+ if (strcmp(str, "base") == 0)
+ return LOCATE_TAG_BASE_TYPE;
+
return tag_name_parse_i(str);
}
@@ -134,6 +138,11 @@ SongFilter::Item::Match(const Tag &_tag) const
bool
SongFilter::Item::Match(const Song &song) const
{
+ if (tag == LOCATE_TAG_BASE_TYPE) {
+ const auto uri = song.GetURI();
+ return uri_is_child_or_same(value.c_str(), uri.c_str());
+ }
+
if (tag == LOCATE_TAG_FILE_TYPE) {
const auto uri = song.GetURI();
return StringMatch(uri.c_str());
@@ -159,6 +168,14 @@ SongFilter::Parse(const char *tag_string, const char *value, bool fold_case)
if (tag == TAG_NUM_OF_ITEM_TYPES)
return false;
+ if (tag == LOCATE_TAG_BASE_TYPE) {
+ if (!uri_safe_local(value))
+ return false;
+
+ /* case folding doesn't work with "base" */
+ fold_case = false;
+ }
+
items.push_back(Item(tag, value, fold_case));
return true;
}
@@ -185,3 +202,13 @@ SongFilter::Match(const Song &song) const
return true;
}
+
+std::string
+SongFilter::GetBase() const
+{
+ for (const auto &i : items)
+ if (i.GetTag() == LOCATE_TAG_BASE_TYPE)
+ return i.GetValue();
+
+ return std::string();
+}
diff --git a/src/SongFilter.hxx b/src/SongFilter.hxx
index 6f77ecc7e..a71fe2cb1 100644
--- a/src/SongFilter.hxx
+++ b/src/SongFilter.hxx
@@ -27,6 +27,11 @@
#include <stdint.h>
+/**
+ * Limit the search to files within the given directory.
+ */
+#define LOCATE_TAG_BASE_TYPE (TAG_NUM_OF_ITEM_TYPES + 1)
+
#define LOCATE_TAG_FILE_TYPE TAG_NUM_OF_ITEM_TYPES+10
#define LOCATE_TAG_ANY_TYPE TAG_NUM_OF_ITEM_TYPES+20
@@ -99,6 +104,13 @@ public:
const std::list<Item> &GetItems() const {
return items;
}
+
+ /**
+ * Returns the "base" specification (if there is one) or an
+ * empty string.
+ */
+ gcc_pure
+ std::string GetBase() const;
};
/**