manual: Remove outdated sentence about para_afh.
[paraslash.git] / mood.c
diff --git a/mood.c b/mood.c
index f580400dd52bfe4d129f7526034745929b0cdf7e..d15e011f04c720cef376b73752d9fcba51c61f00 100644 (file)
--- a/mood.c
+++ b/mood.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2012 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007-2013 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -17,6 +17,7 @@
 #include "list.h"
 #include "ipc.h"
 #include "mm.h"
+#include "sideband.h"
 
 /**
  * Contains statistical data of the currently admissible audio files.
@@ -76,6 +77,10 @@ struct mood {
        struct list_head score_list;
 };
 
+/*
+ * If current_mood is NULL then no mood is currently open. If
+ * current_mood->name is NULL, the dummy mood is currently open
+ */
 static struct mood *current_mood;
 
 /**
@@ -107,12 +112,16 @@ __a_const static uint64_t int_sqrt(uint64_t x)
        return res;
 }
 
-/* returns 1 if row matches score item, 0 if not. */
-static int get_item_score(struct mood_item *item, const struct afs_info *afsi,
+/*
+ * 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, match = 1;
+       int ret;
+       bool match = true;
 
        *score_arg_sum += item->random_score? 100 : PARA_ABS(item->score_arg);
        ret = 100;
@@ -120,7 +129,7 @@ static int get_item_score(struct mood_item *item, const struct afs_info *afsi,
                ret = item->method->score_function(path, afsi, afhi,
                        item->parser_data);
                if ((ret < 0 && !item->logical_not) || (ret >= 0 && item->logical_not))
-                       match = 0; /* no match */
+                       match = false;
        }
        if (item->random_score)
                *score = PARA_ABS(ret) * para_random(100);
@@ -134,7 +143,8 @@ static int compute_mood_score(const struct osl_row *aft_row, struct mood *m,
                long *result)
 {
        struct mood_item *item;
-       int ret, match = 0;
+       int ret;
+       bool match;
        long score_arg_sum = 0, score = 0, item_score;
        struct afs_info afsi;
        struct afh_info afhi;
@@ -153,27 +163,29 @@ static int compute_mood_score(const struct osl_row *aft_row, struct mood *m,
                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) {
-               ret = get_item_score(item, &afsi, &afhi, path, &item_score,
+               match = get_item_score(item, &afsi, &afhi, path, &item_score,
                        &score_arg_sum);
-               if (ret > 0) /* not admissible */
+               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 = 1;
+               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) {
-               ret = get_item_score(item, &afsi, &afhi, path, &item_score,
+               match = get_item_score(item, &afsi, &afhi, path, &item_score,
                        &score_arg_sum);
-               score += item_score;
+               if (match)
+                       score += item_score;
        }
        if (score_arg_sum)
                score /= score_arg_sum;
@@ -210,7 +222,8 @@ static void destroy_mood(struct mood *m)
 static struct mood *alloc_new_mood(const char *name)
 {
        struct mood *m = para_calloc(sizeof(struct mood));
-       m->name = para_strdup(name);
+       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);
@@ -373,7 +386,7 @@ static int load_mood(const struct osl_row *mood_row, struct mood **m)
        if (!*mood_name)
                return -E_DUMMY_ROW;
        mlpd.m = alloc_new_mood(mood_name);
-       ret = for_each_line_ro(mood_def.data, mood_def.size,
+       ret = for_each_line(FELF_READ_ONLY, mood_def.data, mood_def.size,
                parse_mood_line, &mlpd);
        osl_close_disk_object(&mood_def);
        if (ret < 0) {
@@ -405,7 +418,7 @@ static int check_mood(struct osl_row *mood_row, void *data)
        ret = para_printf(pb, "checking mood %s...\n", mood_name);
        if (ret < 0)
                goto out;
-       ret = for_each_line_ro(mood_def.data, mood_def.size,
+       ret = for_each_line(FELF_READ_ONLY, mood_def.data, mood_def.size,
                parse_mood_line, &mlpd);
        if (ret < 0)
                para_printf(pb, "%s line %u: %s\n", mood_name, mlpd.line_num,
@@ -425,8 +438,11 @@ void mood_check_callback(int fd, __a_unused const struct osl_object *query)
 {
        struct para_buffer pb = {
                .max_size = shm_get_shmmax(),
-               .private_data = &fd,
-               .max_size_handler = pass_buffer_as_shm
+               .private_data = &(struct afs_max_size_handler_data) {
+                       .fd = fd,
+                       .band = SBD_OUTPUT
+               },
+               .max_size_handler = afs_max_size_handler
        };
 
        int ret = para_printf(&pb, "checking moods...\n");
@@ -435,23 +451,10 @@ void mood_check_callback(int fd, __a_unused const struct osl_object *query)
        osl_rbtree_loop(moods_table, BLOBCOL_ID, &pb,
                check_mood);
        if (pb.offset)
-               pass_buffer_as_shm(pb.buf, pb.offset, &fd);
+               pass_buffer_as_shm(fd, SBD_OUTPUT, pb.buf, pb.offset);
        free(pb.buf);
 }
 
-#if 0
-static unsigned int_log2(uint64_t x)
-{
-       unsigned res = 0;
-
-       while (x) {
-               x /= 2;
-               res++;
-       }
-       return res;
-}
-#endif
-
 static int64_t normalized_value(int64_t x, int64_t n, int64_t sum, int64_t qd)
 {
        if (!n || !qd)
@@ -459,31 +462,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 * qd);
 }
 
-static long compute_num_played_score(struct afs_info *afsi)
+static long compute_score(struct afs_info *afsi, long mood_score)
 {
-       return -normalized_value(afsi->num_played, statistics.num,
+       mood_score -= normalized_value(afsi->num_played, statistics.num,
                statistics.num_played_sum, statistics.num_played_qd);
-}
-
-static long compute_last_played_score(struct afs_info *afsi)
-{
-       return -normalized_value(afsi->last_played, statistics.num,
+       mood_score -= normalized_value(afsi->last_played, statistics.num,
                statistics.last_played_sum, statistics.last_played_qd);
-}
-
-static long compute_dynamic_score(const struct osl_row *aft_row)
-{
-       struct afs_info afsi;
-       int64_t score, nscore = 0, lscore = 0;
-       int ret;
-
-       ret = get_afsi_of_row(aft_row, &afsi);
-       if (ret < 0)
-               return -100;
-       nscore = compute_num_played_score(&afsi);
-       lscore = compute_last_played_score(&afsi);
-       score = nscore + lscore;
-       return score;
+       return mood_score / 3;
 }
 
 static int add_afs_statistics(const struct osl_row *row)
@@ -675,7 +660,13 @@ static int update_afs_statistics(struct afs_info *old_afsi, struct afs_info *new
 
 static int add_to_score_table(const struct osl_row *aft_row, long mood_score)
 {
-       long score = (compute_dynamic_score(aft_row) + mood_score) / 3;
+       long score;
+       struct afs_info afsi;
+       int ret = get_afsi_of_row(aft_row, &afsi);
+
+       if (ret < 0)
+               return ret;
+       score = compute_score(&afsi, mood_score);
        return score_add(aft_row, score);
 }
 
@@ -756,9 +747,7 @@ static int mood_update_audio_file(const struct osl_row *aft_row,
                if (ret < 0)
                        return ret;
        }
-       score += compute_num_played_score(&afsi);
-       score += compute_last_played_score(&afsi);
-       score /= 3;
+       score = compute_score(&afsi, score);
        PARA_DEBUG_LOG("score: %li\n", score);
        percent = (score + 100) / 3;
        if (percent > 100)
@@ -839,9 +828,9 @@ int change_current_mood(char *mood_name)
                        return ret;
                close_current_mood();
                current_mood = m;
-       } else {
+       } else { /* load dummy mood */
                close_current_mood();
-               current_mood = alloc_new_mood("dummy");
+               current_mood = alloc_new_mood(NULL);
        }
        aa.m = current_mood;
        PARA_NOTICE_LOG("computing statistics of admissible files\n");
@@ -856,7 +845,7 @@ int change_current_mood(char *mood_name)
                if (ret < 0)
                        goto out;
        }
-       PARA_NOTICE_LOG("loaded mood %s\n", current_mood->name);
+       PARA_NOTICE_LOG("loaded mood %s\n", mood_name? mood_name : "(dummy)");
        ret = statistics.num;
 out:
        free(aa.array);
@@ -902,6 +891,8 @@ static int reload_current_mood(void)
  * This function performs actions required due to the occurrence of the given
  * event. Possible actions include reload of the current mood and update of the
  * score of an audio file.
+ *
+ * \return Standard.
  */
 int moods_event_handler(enum afs_events event, __a_unused struct para_buffer *pb,
                void *data)