From 184ea897a9b446611a9d02315160b6d77c0926fe Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Mon, 16 Mar 2020 19:30:55 +0100 Subject: [PATCH] Remove support for version 1 moods. Version 2 moods were introduced in v0.6.1 which was released more than three years ago. Since then the older version 1 moods have been deprecated. This commit gets rid of them removing quite some questionable and unmaintained code. --- configure.ac | 1 - mm.c | 375 ----------------------------------------------- mm.h | 62 -------- mood.c | 399 ++++++--------------------------------------------- 4 files changed, 41 insertions(+), 796 deletions(-) delete mode 100644 mm.c delete mode 100644 mm.h diff --git a/configure.ac b/configure.ac index f518f89a..24009858 100644 --- a/configure.ac +++ b/configure.ac @@ -391,7 +391,6 @@ if test -n "$CRYPTOLIB" && test $HAVE_OSL = yes && test -n "$BISON" && \ daemon http_send close_on_fork - mm crypt_common base64 ipc diff --git a/mm.c b/mm.c deleted file mode 100644 index 358783a1..00000000 --- a/mm.c +++ /dev/null @@ -1,375 +0,0 @@ -/* Copyright (C) 2007 Andre Noll , see file COPYING. */ - -/** \file mm.c Paraslash's mood methods. */ - -#include -#include -#include -#include - -#include "para.h" -#include "error.h" -#include "string.h" -#include "afh.h" -#include "afs.h" -#include "mm.h" - -/** The comparators for numeric mood methods (year, bitrate, ...). */ -#define MOOD_COMPARATORS \ - MC(LESS, <) \ - MC(LESS_OR_EQUAL, <=) \ - MC(EQUAL, =) \ - MC(EQUAL2, ==) \ - MC(NOT_EQUAL, !=) \ - MC(NOT_EQUAL2, <>) \ - MC(GREATER, >) \ - MC(GREATER_OR_EQUAL, >=) \ - -/** Prefix mood comparator name with "_MC", example: MC_LESS. */ -#define MC(a, b) MC_ ## a, -/** Each mood comparator is identified by an integer of this type. */ -enum mood_comparator_id {MOOD_COMPARATORS NUM_MOOD_COMPARATORS}; -#undef MC -/** Stringfied mood comparator, example: "<". */ -#define MC(a, b) # b, -/** Array of mood comparators represented as C strings ("<", "<=", ...). */ -static const char *mood_comparators[] = {MOOD_COMPARATORS}; -#undef MC - -static int parse_mood_comparator(const char *word) -{ - int i; - - for (i = 0; i < NUM_MOOD_COMPARATORS; i++) - if (!strcmp(word, mood_comparators[i])) - return i; - return -E_MOOD_SYNTAX; -} - -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 (cnd->id) { - case MC_LESS: - res = val < arg; break; - case MC_LESS_OR_EQUAL: - res = val <= arg; break; - case MC_EQUAL: - case MC_EQUAL2: - res = val == arg; break; - case MC_NOT_EQUAL: - case MC_NOT_EQUAL2: - res = val != arg; break; - case MC_GREATER: - res = val > arg; break; - case MC_GREATER_OR_EQUAL: - 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; - 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); -} - -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); -} - -static int mm_image_id_score_function(__a_unused const char *path, - const struct afs_info *afsi, - __a_unused const struct afh_info *afhi, - const void *private) -{ - return mm_compare_num_score_function(afsi->image_id, private); -} - -static int mm_lyrics_id_score_function(__a_unused const char *path, - const struct afs_info *afsi, - __a_unused const struct afh_info *afhi, - const void *private) -{ - return mm_compare_num_score_function(afsi->lyrics_id, private); -} - -static int mm_num_played_score_function(__a_unused const char *path, - const struct afs_info *afsi, - __a_unused const struct afh_info *afhi, - const void *private) -{ - return mm_compare_num_score_function(afsi->num_played, private); -} - -struct mm_year_data { - /** Comparator and year given at the mood line. */ - struct mm_compare_num_data *cnd; - /** Used to detect Y2K issues. */ - int32_t current_year; -}; - -static int mm_year_parser(int argc, char **argv, void **private) -{ - int ret; - struct mm_year_data *mmyd = para_malloc(sizeof(*mmyd)); - time_t current_time; - struct tm *gmt; - - ret = mm_compare_num_parser(argc, argv, (void **)&mmyd->cnd); - if (ret < 0) - goto err; - current_time = time(NULL); - gmt = gmtime(¤t_time); - /* tm_year is the number of years since 1900 */ - mmyd->current_year = gmt->tm_year + 1900; - *private = mmyd; - return 1; -err: - free(mmyd); - return ret; -} - -static int mm_year_score_function(__a_unused const char *path, - __a_unused const struct afs_info *afsi, - const struct afh_info *afhi, - const void *private) -{ - const struct mm_year_data *mmyd = private; - int32_t tag_year; - int ret = para_atoi32(afhi->tags.year, &tag_year); - - if (ret < 0) /* year tag not present or not a number */ - return -100; - if (tag_year < 0) - return -100; - /* try to work around Y2K issues */ - if (tag_year < 100) { - tag_year += 1900; - if (tag_year + 100 <= mmyd->current_year) - tag_year += 100; /* assume tag_year >= 2000 */ - } - return mm_compare_num_score_function(tag_year, mmyd->cnd); -} - -static void mm_year_cleanup(void *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, - __a_unused void **ignored) -{ - return argc? -E_MOOD_SYNTAX : 1; -} - -static int mm_no_attributes_set_score_function(__a_unused const char *path, - const struct afs_info *afsi, - __a_unused const struct afh_info *afhi, - __a_unused const void *data) -{ - if (!afsi->attributes) - return 100; - return -100; -} - -static int mm_path_matches_score_function(const char *path, - __a_unused const struct afs_info *afsi, - __a_unused const struct afh_info *afhi, - const void *data) -{ - if (fnmatch(data, path, 0)) - return -100; - return 100; -} - -static int mm_path_matches_parser(int argc, char **argv, void **data) -{ - if (argc != 1) - return -E_MOOD_SYNTAX; - *data = para_strdup(argv[1]); - return 1; -} - -static void mm_path_matches_cleanup(void *data) -{ - free(data); -} - -static int mm_is_set_parser(int argc, char **argv, void **bitnum) -{ - int ret; - unsigned char c, *res; - - if (argc != 1) - return -E_MOOD_SYNTAX; - ret = get_attribute_bitnum_by_name(argv[1], &c); - if (ret < 0) - return ret; - res = para_malloc(1); - *res = c; - *bitnum = res; - return 1; -} - -static int mm_is_set_score_function(__a_unused const char *path, - __a_unused const struct afs_info *afsi, - __a_unused const struct afh_info *afhi, - const void *data) -{ - const unsigned char *bn = data; - if (afsi->attributes & (1ULL << *bn)) - return 100; - return -100; -} - -#define DEFINE_MOOD_METHOD(_name) \ -.parser = mm_ ## _name ## _parser, \ -.score_function = mm_ ## _name ## _score_function, \ -.name = #_name - -#define DEFINE_MOOD_METHOD_WITH_CLEANUP(_name) \ - 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 - -#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_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)}, - {DEFINE_COMPARE_NUM_MOOD_METHOD(bitrate)}, - {DEFINE_COMPARE_NUM_MOOD_METHOD(frequency)}, - {DEFINE_COMPARE_NUM_MOOD_METHOD(channels)}, - {DEFINE_COMPARE_NUM_MOOD_METHOD(num_played)}, - {DEFINE_COMPARE_NUM_MOOD_METHOD(image_id)}, - {DEFINE_COMPARE_NUM_MOOD_METHOD(lyrics_id)}, - {.parser = NULL} -}; diff --git a/mm.h b/mm.h deleted file mode 100644 index 28038e72..00000000 --- a/mm.h +++ /dev/null @@ -1,62 +0,0 @@ -/* Copyright (C) 2007 Andre Noll , see file COPYING. */ - -/** \file mm.h Symbols and declarations for mood methods. */ - -/** - * Assign scores according to a mood_method. - * - * Each mood_method has its own mood_score_function. The first three parameters - * passed to that function are informations about the audio file whose score is - * to be computed. The data argument depends on the mood method this function - * is used for. It usually is the argument given at the end of a mood line. - * - * Mood score functions must return values between -100 and +100 inclusively. - * Boolean score functions should always return either -100 or +100. - * - * \sa struct \ref mood_method, \ref mood_parser. - */ -typedef int mood_score_function(const char *path, const struct afs_info *afsi, - const struct afh_info *afhi, const void *data); - -/** - * Pre-process a mood line. - * - * The mood_parser of a mood_method is called once at mood open time for each - * line of the current mood definition that contains the mood_method's name as - * a keyword. The line is passed to the mood_parser as the first argument. The - * mood_parser must determine whether the line is syntactically correct and - * return a positive value if so and a negative value otherwise. - * - * Some mood parsers pre-process the data given in the mood line to compute a - * structure which depends of the particular mood_method and which is used - * later in the mood_score_function of the mood_method. The mood_parser may - * store a pointer to its structure via the void** pointer. - * - * \sa \ref mood_cleanup_function, \ref mood_score_function. - */ -typedef int mood_parser(int, char **, void **); - -/** - * Deallocate resources which were allocated by the mood_parser. - * - * Function to free the resources allocated in \ref mood_method::parser. The - * argument is a pointer to mood method specific data returned by ->parser(). - */ -typedef void mood_cleanup_function(void *); - -/** - * Used for scoring and to determine whether a file is admissible. - */ -struct mood_method { - /** The name of the method. */ - const char *name; - /** Pointer to the mood parser. */ - mood_parser *parser; - /** Pointer to the score function */ - mood_score_function *score_function; - /** Optional cleanup function. */ - mood_cleanup_function *cleanup; -}; - -/** The array of available mood methods. */ -extern const struct mood_method mood_methods[]; diff --git a/mood.c b/mood.c index a63d4d2a..ccc57a03 100644 --- a/mood.c +++ b/mood.c @@ -12,7 +12,6 @@ #include "afh.h" #include "afs.h" #include "list.h" -#include "mm.h" #include "mood.h" /* @@ -44,42 +43,10 @@ struct afs_statistics { }; static struct afs_statistics statistics; -/** - * Each line of the current mood corresponds to a mood_item. - */ -struct mood_item { - /** The method this line is referring to. */ - const struct mood_method *method; - /** The data structure computed by the mood parser. */ - void *parser_data; - /** The given score value, or zero if none was given. */ - int32_t score_arg; - /** Non-zero if random scoring was requested. */ - int random_score; - /** Whether the "not" keyword was given in the mood line. */ - int logical_not; - /** The position in the list of items. */ - struct list_head mood_item_node; -}; - -/* - * Created from the mood definition by \ref change_current_mood(). - * - * When a mood is opened, each line of its definition is investigated, and a - * corresponding mood item is produced. Each mood line starts with accept, - * deny, or score which determines the type of the mood line. For each such - * type a linked list is maintained whose entries are the mood items. - */ struct mood { /** The name of this mood. */ char *name; - /** The list of mood items of type \p accept. */ - struct list_head accept_list; - /** The list of mood items of type \p deny. */ - struct list_head deny_list; - /** The list of mood items of type \p score. */ - struct list_head score_list; - /* Only used for version 2 moods. */ + /** Info for the bison parser. */ struct mp_context *parser_context; }; @@ -146,115 +113,20 @@ __a_const static uint64_t int_sqrt(uint64_t x) return res; } -/* - * Returns true if row matches, false if it does not match. In any case score - * and score_arg_sum are set/increased accordingly. - */ -static bool get_item_score(struct mood_item *item, const struct afs_info *afsi, - const struct afh_info *afhi, const char *path, long *score, - long *score_arg_sum) -{ - int ret; - bool match = true; - - *score_arg_sum += item->random_score? 100 : PARA_ABS(item->score_arg); - ret = 100; - if (item->method) { - ret = item->method->score_function(path, afsi, afhi, - item->parser_data); - if ((ret < 0 && !item->logical_not) || (ret >= 0 && item->logical_not)) - match = false; - } - if (item->random_score) - *score = PARA_ABS(ret) * para_random(100); - else - *score = PARA_ABS(ret) * item->score_arg; - return match; -} - /* returns 1 if row admissible, 0 if not, negative on errors */ -static int row_is_admissible(const struct osl_row *aft_row, struct mood *m, - long *scorep) +static int row_is_admissible(const struct osl_row *aft_row, struct mood *m) { - struct mood_item *item; - int ret; - bool match; - long score_arg_sum = 0, score = 0, item_score; - struct afs_info afsi; - struct afh_info afhi; - char *path; - if (!m) return -E_NO_MOOD; - if (m->parser_context) { - *scorep = 0; - return mp_eval_row(aft_row, m->parser_context); - } - ret = get_afsi_of_row(aft_row, &afsi); - if (ret < 0) - return ret; - ret = get_afhi_of_row(aft_row, &afhi); - if (ret < 0) - return ret; - ret = get_audio_file_path_of_row(aft_row, &path); - if (ret < 0) - return ret; - /* reject audio file if it matches any entry in the deny list */ - list_for_each_entry(item, &m->deny_list, mood_item_node) { - match = get_item_score(item, &afsi, &afhi, path, &item_score, - &score_arg_sum); - if (match) /* not admissible */ - return 0; - score += item_score; - } - match = false; - list_for_each_entry(item, &m->accept_list, mood_item_node) { - ret = get_item_score(item, &afsi, &afhi, path, &item_score, - &score_arg_sum); - if (ret == 0) - continue; - match = true; - score += item_score; - } - /* reject if there is no matching entry in the accept list */ - if (!match && !list_empty(&m->accept_list)) - return 0; - list_for_each_entry(item, &m->score_list, mood_item_node) { - match = get_item_score(item, &afsi, &afhi, path, &item_score, - &score_arg_sum); - if (match) - score += item_score; - } - if (score_arg_sum) - score /= score_arg_sum; - *scorep = score; - return 1; -} - -static void cleanup_list_entry(struct mood_item *item) -{ - if (item->method && item->method->cleanup) - item->method->cleanup(item->parser_data); - else - free(item->parser_data); - list_del(&item->mood_item_node); - free(item); + return mp_eval_row(aft_row, m->parser_context); } static void destroy_mood(struct mood *m) { - struct mood_item *tmp, *item; - if (!m) return; - list_for_each_entry_safe(item, tmp, &m->accept_list, mood_item_node) - cleanup_list_entry(item); - list_for_each_entry_safe(item, tmp, &m->deny_list, mood_item_node) - cleanup_list_entry(item); - list_for_each_entry_safe(item, tmp, &m->score_list, mood_item_node) - cleanup_list_entry(item); - free(m->name); mp_shutdown(m->parser_context); + free(m->name); free(m); } @@ -263,160 +135,16 @@ static struct mood *alloc_new_mood(const char *name) struct mood *m = para_calloc(sizeof(struct mood)); if (name) m->name = para_strdup(name); - INIT_LIST_HEAD(&m->accept_list); - INIT_LIST_HEAD(&m->deny_list); - INIT_LIST_HEAD(&m->score_list); return m; } -/** The different types of a mood line. */ -enum mood_line_type { - /** Invalid. */ - ML_INVALID, - /** Accept line. */ - ML_ACCEPT, - /** Deny line. */ - ML_DENY, - /** Score line. */ - ML_SCORE -}; - -/** Data passed to the parser of a mood line. */ -struct mood_line_parser_data { - /** The mood this mood line belongs to. */ - struct mood *m; - /** The line number in the mood definition. */ - unsigned line_num; -}; - -/* - * ] | deny [with score ] | score > - * [if] [not] [options] - * is either an integer or "random" which assigns a random score to - * all matching files - */ -static int parse_mood_line(char *mood_line, void *data) -{ - struct mood_line_parser_data *mlpd = data; - char **argv; - unsigned num_words; - char **w; - int i, ret; - enum mood_line_type mlt = ML_INVALID; - struct mood_item *mi = NULL; - - mlpd->line_num++; - ret = create_argv(mood_line, " \t", &argv); - if (ret < 0) - return ret; - num_words = ret; - if (!num_words) /* empty line */ - goto out; - w = argv; - if (**w == '#') /* comment */ - goto out; - if (!strcmp(*w, "accept")) - mlt = ML_ACCEPT; - else if (!strcmp(*w, "deny")) - mlt = ML_DENY; - else if (!strcmp(*w, "score")) - mlt = ML_SCORE; - ret = -E_MOOD_SYNTAX; - if (mlt == ML_INVALID) - goto out; - mi = para_calloc(sizeof(struct mood_item)); - if (mlt != ML_SCORE) { - ret = -E_MOOD_SYNTAX; - w++; - if (!*w) - goto out; - if (strcmp(*w, "with")) - goto check_for_if; - w++; - if (!*w) - goto out; - if (strcmp(*w, "score")) - goto out; - } - if (mlt == ML_SCORE || !strcmp(*w, "score")) { - ret = -E_MOOD_SYNTAX; - w++; - if (!*w) - goto out; - if (strcmp(*w, "random")) { - mi->random_score = 0; - ret = para_atoi32(*w, &mi->score_arg); - if (ret < 0) - goto out; - } else { - mi->random_score = 1; - if (!*(w + 1)) - goto success; /* the line "score random" is valid */ - } - } else - mi->score_arg = 0; - ret = -E_MOOD_SYNTAX; - w++; - if (!*w) - goto out; -check_for_if: - if (!strcmp(*w, "if")) { - ret = -E_MOOD_SYNTAX; - w++; - if (!*w) - goto out; - } - if (!strcmp(*w, "not")) { - ret = -E_MOOD_SYNTAX; - w++; - if (!*w) - goto out; - mi->logical_not = 1; - } else - mi->logical_not = 0; - for (i = 0; mood_methods[i].parser; i++) { - if (strcmp(*w, mood_methods[i].name)) - continue; - break; - } - ret = -E_MOOD_SYNTAX; - if (!mood_methods[i].parser) - goto out; - ret = mood_methods[i].parser(num_words - 1 - (w - argv), w, - &mi->parser_data); - if (ret < 0) - goto out; - mi->method = &mood_methods[i]; -success: - if (mlpd->m) { - if (mlt == ML_ACCEPT) - para_list_add(&mi->mood_item_node, &mlpd->m->accept_list); - else if (mlt == ML_DENY) - para_list_add(&mi->mood_item_node, &mlpd->m->deny_list); - else - para_list_add(&mi->mood_item_node, &mlpd->m->score_list); - } - PARA_DEBUG_LOG("%s entry added, method: %p\n", mlt == ML_ACCEPT? "accept" : - (mlt == ML_DENY? "deny" : "score"), mi->method); - ret = 1; -out: - free_argv(argv); - if (mi && (ret < 0 || !mlpd->m)) { /* mi was not added to any list */ - free(mi->parser_data); - free(mi); - } - return ret; -} - static int load_mood(const struct osl_row *mood_row, struct mood **m, char **errmsg) { char *mood_name; struct osl_object mood_def; - struct mood_line_parser_data mlpd = {.line_num = 0}; int ret; - *m = NULL; ret = mood_get_name_and_def_by_row(mood_row, &mood_name, &mood_def); if (ret < 0) { if (errmsg) @@ -425,33 +153,19 @@ static int load_mood(const struct osl_row *mood_row, struct mood **m, return ret; } assert(*mood_name); - mlpd.m = alloc_new_mood(mood_name); - ret = for_each_line(FELF_READ_ONLY, mood_def.data, mood_def.size, - parse_mood_line, &mlpd); - if (ret < 0) { - PARA_INFO_LOG("opening version 2 mood %s\n", mlpd.m->name); - ret = mp_init(mood_def.data, mood_def.size, &mlpd.m->parser_context, - errmsg); - if (ret < 0) - destroy_mood(mlpd.m); - } else { - PARA_WARNING_LOG("loaded version 1 mood %s\n", mlpd.m->name); - PARA_WARNING_LOG("please convert to version 2\n"); - ret = 1; - } + *m = alloc_new_mood(mood_name); + PARA_INFO_LOG("opening mood %s\n", mood_name); + ret = mp_init(mood_def.data, mood_def.size, &(*m)->parser_context, errmsg); osl_close_disk_object(&mood_def); - if (ret >= 0) - *m = mlpd.m; return ret; } static int check_mood(struct osl_row *mood_row, void *data) { struct para_buffer *pb = data; - char *mood_name; + char *mood_name, *errmsg; struct osl_object mood_def; - struct mood_line_parser_data mlpd = {.line_num = 0}; - + struct mood *m; int ret = mood_get_name_and_def_by_row(mood_row, &mood_name, &mood_def); if (ret < 0) { @@ -460,24 +174,15 @@ static int check_mood(struct osl_row *mood_row, void *data) } if (!*mood_name) /* ignore dummy row */ goto out; - ret = for_each_line(FELF_READ_ONLY, mood_def.data, mood_def.size, - parse_mood_line, &mlpd); + m = alloc_new_mood("check"); + ret = mp_init(mood_def.data, mood_def.size, &m->parser_context, + &errmsg); if (ret < 0) { - char *errmsg; - struct mood *m = alloc_new_mood("check"); - ret = mp_init(mood_def.data, mood_def.size, &m->parser_context, - &errmsg); - if (ret < 0) { - para_printf(pb, "%s: %s\n", mood_name, errmsg); - free(errmsg); - para_printf(pb, "%s\n", para_strerror(-ret)); - } else - destroy_mood(m); - } else { - para_printf(pb, "%s: v1 mood, please convert to v2\n", - mood_name); - - } + para_printf(pb, "%s: %s\n", mood_name, errmsg); + free(errmsg); + para_printf(pb, "%s\n", para_strerror(-ret)); + } else + destroy_mood(m); ret = 1; /* don't fail the loop on invalid mood definitions */ out: osl_close_disk_object(&mood_def); @@ -506,13 +211,13 @@ static int64_t normalized_value(int64_t x, int64_t n, int64_t sum, int64_t qd) return 100 * (n * x - sum) / (int64_t)int_sqrt(n) / (int64_t)int_sqrt(qd); } -static long compute_score(struct afs_info *afsi, long mood_score) +static long compute_score(struct afs_info *afsi) { - mood_score -= normalized_value(afsi->num_played, statistics.num, + long score = -normalized_value(afsi->num_played, statistics.num, statistics.num_played_sum, statistics.num_played_qd); - mood_score -= normalized_value(afsi->last_played, statistics.num, + score -= normalized_value(afsi->last_played, statistics.num, statistics.last_played_sum, statistics.last_played_qd); - return mood_score / 3; + return score / 2; } static int add_afs_statistics(const struct osl_row *row) @@ -581,63 +286,42 @@ static int del_afs_statistics(const struct osl_row *row) /* * At mood open time we determine the set of admissible files for the given - * mood. The mood score of each admissible file is computed by adding up all - * mood item scores. Next, we update the afs statistics and append a struct - * admissible_file_info to a temporary array. - * - * When all files have been processed in this way, the final score of each - * admissible file is computed by adding the dynamic score (which depends on - * the afs_statistics and the current time) to the mood score. Finally, all - * audio files in the temporary array are added to the score table and the - * array is freed. + * mood where each file is identified by a pointer to a row of the audio file + * table. In the first pass the pointers are added to a temporary array and + * statistics are computed. When all admissible files have been processed in + * this way, the score of each admissible file is computed and the (row, score) + * pair is added to the score table. This has to be done in a second pass + * since the score depends on the statistics. Finally, the array is freed. */ -struct admissible_file_info -{ - /** The admissible audio file. */ - struct osl_row *aft_row; - /** Its score. */ - long score; -}; - -/** The temporary array of admissible files. */ struct admissible_array { /** Files are admissible wrt. this mood. */ struct mood *m; /** The size of the array */ unsigned size; /** Pointer to the array of admissible files. */ - struct admissible_file_info *array; + struct osl_row **array; }; -/** - * Add an entry to the array of admissible files. - * - * \param aft_row The audio file to be added. - * \param private_data Pointer to a struct admissible_file_info. - * - * \return 1 if row admissible, 0 if not, negative on errors. +/* + * Check whether the given audio file is admissible. If it is, add it to array + * of admissible files. */ static int add_if_admissible(struct osl_row *aft_row, void *data) { struct admissible_array *aa = data; int ret; - long score = 0; - ret = row_is_admissible(aft_row, aa->m, &score); + ret = row_is_admissible(aft_row, aa->m); if (ret <= 0) return ret; if (statistics.num >= aa->size) { aa->size *= 2; aa->size += 100; aa->array = para_realloc(aa->array, - aa->size * sizeof(struct admissible_file_info)); + aa->size * sizeof(struct osl_row *)); } - aa->array[statistics.num].aft_row = aft_row; - aa->array[statistics.num].score = score; - ret = add_afs_statistics(aft_row); - if (ret < 0) - return ret; - return 1; + aa->array[statistics.num] = aft_row; + return add_afs_statistics(aft_row); } /** @@ -704,7 +388,7 @@ static int update_afs_statistics(struct afs_info *old_afsi, return 1; } -static int add_to_score_table(const struct osl_row *aft_row, long mood_score) +static int add_to_score_table(const struct osl_row *aft_row) { long score; struct afs_info afsi; @@ -712,7 +396,7 @@ static int add_to_score_table(const struct osl_row *aft_row, long mood_score) if (ret < 0) return ret; - score = compute_score(&afsi, mood_score); + score = compute_score(&afsi); return score_add(aft_row, score); } @@ -770,7 +454,7 @@ static int mood_update_audio_file(const struct osl_row *aft_row, if (ret < 0) return ret; was_admissible = ret; - ret = row_is_admissible(aft_row, current_mood, &score); + ret = row_is_admissible(aft_row, current_mood); if (ret < 0) return ret; is_admissible = (ret > 0); @@ -782,7 +466,7 @@ static int mood_update_audio_file(const struct osl_row *aft_row, ret = add_afs_statistics(aft_row); if (ret < 0) return ret; - return add_to_score_table(aft_row, score); + return add_to_score_table(aft_row); } /* update score */ ret = get_afsi_of_row(aft_row, &afsi); @@ -793,7 +477,7 @@ static int mood_update_audio_file(const struct osl_row *aft_row, if (ret < 0) return ret; } - score = compute_score(&afsi, score); + score = compute_score(&afsi); PARA_DEBUG_LOG("score: %li\n", score); percent = (score + 100) / 3; if (percent > 100) @@ -902,8 +586,7 @@ int change_current_mood(const char *mood_name, char **errmsg) return ret; } for (i = 0; i < statistics.num; i++) { - struct admissible_file_info *a = aa.array + i; - ret = add_to_score_table(a->aft_row, a->score); + ret = add_to_score_table(aa.array[i]); if (ret < 0) { if (errmsg) *errmsg = make_message( -- 2.39.2