Takes no arguments and matches an audio file if and only if no
attributes are set.
- played_rarely
-
-Takes no arguments and matches all audio files where the number of
-times this audio file was selected is below the average.
-
- is_set attribute_name
+ is_set <attribute_name>
Takes the name of an attribute and matches iff that attribute is set.
- path_matches pattern
+ path_matches <pattern>
Takes a filename pattern and matches iff the path of the audio file
matches the pattern.
+ artist_matches <pattern>
+ album_matches <pattern>
+ title_matches <pattern>
+ comment_matches <pattern>
+
+Takes an extended regular expression and matches iff the text of the
+corresponding tag of the audio file matches the pattern. If the tag
+is not set, the empty string is matched against the pattern.
+
+ year
+
+Takes a comparator ~ of the set {<, =, <=, >, >=, !=} and a number
+N. Matches iff the year tag Y of the audio file is a number that
+satisfies the condition Y ~ N. If the audio file has no year tag,
+or if the tag is not a number, the file does not match.
----------
Mood usage
return res? 100 : -100;
}
+static int mm_regex_parser(int argc, char **argv, void **private)
+{
+ regex_t *preg;
+ int ret;
+
+ if (argc != 1)
+ return -E_MOOD_SYNTAX;
+ preg = para_malloc(sizeof(*preg));
+ ret = para_regcomp(preg, argv[1], REG_EXTENDED | REG_NOSUB);
+ if (ret < 0) {
+ free(preg);
+ return ret;
+ }
+ *private = preg;
+ return 1;
+}
+
+static int mm_regex_score_function(const regex_t *preg, const char *pattern)
+{
+ return regexec(preg, pattern, 0, NULL, 0) == 0? 100 : -100;
+}
+
+static void mm_regex_cleanup(void *private)
+{
+ regex_t *preg = private;
+ regfree(preg);
+ free(preg);
+}
+
+static int mm_artist_matches_score_function(__a_unused const char *path,
+ __a_unused const struct afs_info *afsi,
+ const struct afh_info *afhi,
+ const void *private)
+{
+ return mm_regex_score_function(private, afhi->tags.artist);
+}
+
+static int mm_title_matches_score_function(__a_unused const char *path,
+ __a_unused const struct afs_info *afsi,
+ const struct afh_info *afhi,
+ const void *private)
+{
+ return mm_regex_score_function(private, afhi->tags.title);
+}
+
+static int mm_album_matches_score_function(__a_unused const char *path,
+ __a_unused const struct afs_info *afsi,
+ const struct afh_info *afhi,
+ const void *private)
+{
+ return mm_regex_score_function(private, afhi->tags.album);
+}
+
+static int mm_comment_matches_score_function(__a_unused const char *path,
+ __a_unused const struct afs_info *afsi,
+ const struct afh_info *afhi,
+ const void *private)
+{
+ return mm_regex_score_function(private, afhi->tags.comment);
+}
+
struct mm_year_data {
/** The year given at the mood line. */
int32_t year;
DEFINE_MOOD_METHOD(_name), \
.cleanup = mm_ ## _name ## _cleanup
+#define DEFINE_REGEX_MOOD_METHOD(_name) \
+ .name = #_name, \
+ .parser = mm_regex_parser, \
+ .score_function = mm_ ## _name ## _score_function, \
+ .cleanup = mm_regex_cleanup
+
const struct mood_method mood_methods[] = {
{DEFINE_MOOD_METHOD(no_attributes_set)},
{DEFINE_MOOD_METHOD(is_set)},
{DEFINE_MOOD_METHOD_WITH_CLEANUP(path_matches)},
{DEFINE_MOOD_METHOD_WITH_CLEANUP(year)},
+ {DEFINE_REGEX_MOOD_METHOD(artist_matches)},
+ {DEFINE_REGEX_MOOD_METHOD(title_matches)},
+ {DEFINE_REGEX_MOOD_METHOD(album_matches)},
+ {DEFINE_REGEX_MOOD_METHOD(comment_matches)},
{.parser = NULL}
};
-