]> git.tuebingen.mpg.de Git - paraslash.git/commitdiff
Remove support for version 1 moods.
authorAndre Noll <maan@tuebingen.mpg.de>
Mon, 16 Mar 2020 18:30:55 +0000 (19:30 +0100)
committerAndre Noll <maan@tuebingen.mpg.de>
Sat, 27 Feb 2021 16:58:12 +0000 (17:58 +0100)
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
mm.c [deleted file]
mm.h [deleted file]
mood.c

index f518f89af154933ffaa64401ba1086b7e3f369c9..240098589d4374233cfed7b04146ec299d008a61 100644 (file)
@@ -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 (file)
index 358783a..0000000
--- a/mm.c
+++ /dev/null
@@ -1,375 +0,0 @@
-/* Copyright (C) 2007 Andre Noll <maan@tuebingen.mpg.de>, see file COPYING. */
-
-/** \file mm.c Paraslash's mood methods. */
-
-#include <regex.h>
-#include <fnmatch.h>
-#include <osl.h>
-#include <lopsub.h>
-
-#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(&current_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 (file)
index 28038e7..0000000
--- a/mm.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* Copyright (C) 2007 Andre Noll <maan@tuebingen.mpg.de>, 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 a63d4d2af5d10d7b64c319d915e00b9b7ea62e89..ccc57a0305d5e23152d789bb974b53729171ec25 100644 (file)
--- 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;
-};
-
-/*
- * <accept [with score <score>] | deny [with score <score>]  | score <score>>
- *     [if] [not] <mood_method> [options]
- * <score> 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(