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
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);
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;
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)
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);
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,
.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)},
{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}
};