Add bitrate, frequency, and channels mood methods.
authorAndre Noll <maan@systemlinux.org>
Sun, 12 Jul 2009 15:30:09 +0000 (17:30 +0200)
committerAndre Noll <maan@systemlinux.org>
Sun, 12 Jul 2009 15:30:09 +0000 (17:30 +0200)
This isolates the number comparing code from the year mood method so that it can also
be used by the new methods.

README.afs
mm.c

index 7889bda..edd2d17 100644 (file)
@@ -174,12 +174,24 @@ 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
+       year ~ <num>
+       bitrate ~ <num>
+       frequency ~ <num>
+       channels ~ <num>
 
 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.
+<num>. Matches an audio file iff the condition <val> ~ <num> is
+satisfied where val is the corresponding value of the audio file
+(bitrate in kbit/s, frequency in Hz, channel count, value of the
+year tag).
+
+The year tag is special as its value is undefined if the audio file
+has no year tag or the content of the year tag is not a number. Such
+audio files never match. Another difference is the special treatment
+if the year tag is a two-digit number. In this case either 1900 or
+2000 are added to the tag value, depending on whether the number is
+greater than 2000 plus the current year.
+
 
 ----------
 Mood usage
diff --git a/mm.c b/mm.c
index 4ed72ad..4f76d40 100644 (file)
--- a/mm.c
+++ b/mm.c
@@ -45,25 +45,34 @@ static int parse_mood_comparator(const char *word)
        return -E_MOOD_SYNTAX;
 }
 
-static int compare_int32(int32_t a, int32_t b, enum mood_comparator_id id)
+struct mm_compare_num_data {
+       /** <, <=, =, !=, >=, or >. */
+       enum mood_comparator_id id;
+       /** The value given at the mood line. */
+       int32_t arg;
+};
+
+static int mm_compare_num_score_function(int32_t val,
+               const struct mm_compare_num_data *cnd)
 {
        int res;
+       int32_t arg = cnd->arg;
 
-       switch (id) {
+       switch (cnd->id) {
        case MC_LESS:
-               res = a < b; break;
+               res = val < arg; break;
        case MC_LESS_OR_EQUAL:
-               res = a <= b; break;
+               res = val <= arg; break;
        case MC_EQUAL:
        case MC_EQUAL2:
-               res = a == b; break;
+               res = val == arg; break;
        case MC_NOT_EQUAL:
        case MC_NOT_EQUAL2:
-               res = a != b; break;
+               res = val != arg; break;
        case MC_GREATER:
-               res = a > b; break;
+               res = val > arg; break;
        case MC_GREATER_OR_EQUAL:
-               res = a >= b; break;
+               res = val >= arg; break;
        default:
                PARA_EMERG_LOG("BUG: invalid mood comparator\n");
                exit(EXIT_FAILURE);
@@ -71,6 +80,28 @@ static int compare_int32(int32_t a, int32_t b, enum mood_comparator_id id)
        return res? 100 : -100;
 }
 
+static int mm_compare_num_parser(int argc, char **argv, void **private)
+{
+       int ret;
+       enum mood_comparator_id id;
+       int32_t arg;
+       struct mm_compare_num_data *cnd;
+       if (argc != 2)
+               return -E_MOOD_SYNTAX;
+       ret = parse_mood_comparator(argv[1]);
+       if (ret < 0)
+               return ret;
+       id = ret;
+       ret = para_atoi32(argv[2], &arg);
+       if (ret < 0)
+               return ret;
+       cnd = para_malloc(sizeof(struct mm_compare_num_data));
+       cnd->id = id;
+       cnd->arg = arg;
+       *private = cnd;
+       return 1;
+}
+
 static int mm_regex_parser(int argc, char **argv, void **private)
 {
        regex_t *preg;
@@ -132,13 +163,35 @@ static int mm_comment_matches_score_function(__a_unused const char *path,
        return mm_regex_score_function(private, afhi->tags.comment);
 }
 
+static int mm_bitrate_score_function(__a_unused const char *path,
+               __a_unused const struct afs_info *afsi,
+               const struct afh_info *afhi,
+               const void *private)
+{
+       return mm_compare_num_score_function(afhi->bitrate, private);
+}
+
+static int mm_frequency_score_function(__a_unused const char *path,
+               __a_unused const struct afs_info *afsi,
+               const struct afh_info *afhi,
+               const void *private)
+{
+       return mm_compare_num_score_function(afhi->frequency, private);
+}
+
+static int mm_channels_score_function(__a_unused const char *path,
+               __a_unused const struct afs_info *afsi,
+               const struct afh_info *afhi,
+               const void *private)
+{
+       return mm_compare_num_score_function(afhi->channels, private);
+}
+
 struct mm_year_data {
-       /** The year given at the mood line. */
-       int32_t year;
+       /** Comparator and year given at the mood line. */
+       struct mm_compare_num_data *cnd;
        /** Used to detect Y2K issues. */
        int32_t current_year;
-       /** <, <=, =, !=, >=, or >. */
-       enum mood_comparator_id id;
 };
 
 static int mm_year_parser(int argc, char **argv, void **private)
@@ -148,13 +201,7 @@ static int mm_year_parser(int argc, char **argv, void **private)
        time_t current_time;
        struct tm *gmt;
 
-       if (argc != 2)
-               goto err;
-       ret = parse_mood_comparator(argv[1]);
-       mmyd->id = ret;
-       if (ret < 0)
-               goto err;
-       ret = para_atoi32(argv[2], &mmyd->year);
+       ret = mm_compare_num_parser(argc, argv, (void **)&mmyd->cnd);
        if (ret < 0)
                goto err;
        current_time = time(NULL);
@@ -187,12 +234,15 @@ static int mm_year_score_function(__a_unused const char *path,
                if (tag_year + 100 <= mmyd->current_year)
                        tag_year += 100; /* assume tag_year >= 2000 */
        }
-       return compare_int32(tag_year, mmyd->year, mmyd->id);
+       return mm_compare_num_score_function(tag_year, mmyd->cnd);
 }
 
 static void mm_year_cleanup(void *private)
 {
-       free(private);
+       struct mm_year_data *mmyd = private;
+
+       free(mmyd->cnd);
+       free(mmyd);
 }
 
 static int mm_no_attributes_set_parser(int argc, __a_unused char **argv,
@@ -276,6 +326,11 @@ static int mm_is_set_score_function(__a_unused const char *path,
        .score_function = mm_ ## _name ## _score_function, \
        .cleanup = mm_regex_cleanup
 
+#define DEFINE_COMPARE_NUM_MOOD_METHOD(_name) \
+       .name = #_name, \
+       .parser = mm_compare_num_parser, \
+       .score_function = mm_ ## _name ## _score_function
+
 const struct mood_method mood_methods[] = {
        {DEFINE_MOOD_METHOD(no_attributes_set)},
        {DEFINE_MOOD_METHOD(is_set)},
@@ -285,5 +340,8 @@ const struct mood_method mood_methods[] = {
        {DEFINE_REGEX_MOOD_METHOD(title_matches)},
        {DEFINE_REGEX_MOOD_METHOD(album_matches)},
        {DEFINE_REGEX_MOOD_METHOD(comment_matches)},
+       {DEFINE_COMPARE_NUM_MOOD_METHOD(bitrate)},
+       {DEFINE_COMPARE_NUM_MOOD_METHOD(frequency)},
+       {DEFINE_COMPARE_NUM_MOOD_METHOD(channels)},
        {.parser = NULL}
 };