]> git.tuebingen.mpg.de Git - paraslash.git/blobdiff - mood.c
Fix off-by-one bug in chunktable saving.
[paraslash.git] / mood.c
diff --git a/mood.c b/mood.c
index b7ee99eb73799b03fdd0fff63b7ff77e940a1a82..9074581c6c8d40741a99c3c1772716381e03f2a4 100644 (file)
--- a/mood.c
+++ b/mood.c
@@ -9,10 +9,10 @@
 #include <fnmatch.h>
 #include "para.h"
 #include "error.h"
+#include "string.h"
 #include "afh.h"
 #include "afs.h"
 #include "list.h"
-#include "string.h"
 
 /**
  * Contains statistical data of the currently admissible audio files.
@@ -36,11 +36,10 @@ struct afs_statistics statistics;
 /**
  * Assign scores according to a mood_method.
  *
- * Each mood_method has its own mood_score_function. The first parameter passed
- * to that function is a pointer to a row of the audio file table.  It
- * determines the audio file for which a score is to be assigned.  The second
- * argument depends on the mood method this function is used for. It usually is
- * the argument given at the end of a mood line.
+ * 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.
@@ -176,8 +175,6 @@ static int mm_no_attributes_set_score_function(__a_unused const char *path,
                __a_unused const struct audio_format_info *afhi,
                __a_unused const void *data)
 {
-       if (!strcmp(path, "/home/mp3/checked/dvd_08/cd_52/Sade__Paradise.mp3"))
-               PARA_NOTICE_LOG("%s: %llu\n", path, afsi->attributes);
        if (!afsi->attributes)
                return 100;
        return -100;
@@ -310,31 +307,21 @@ static int compute_mood_score(const struct osl_row *aft_row, struct mood *m,
        return 1;
 }
 
+#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
+
 static const struct mood_method mood_methods[] = {
-{
-       .parser = mm_no_attributes_set_parser,
-       .score_function = mm_no_attributes_set_score_function,
-       .name = "no_attributes_set"
-},
-{
-       .parser = mm_played_rarely_parser,
-       .score_function = mm_played_rarely_score_function,
-       .name = "played_rarely"
-},
-{
-       .parser = mm_is_set_parser,
-       .score_function = mm_is_set_score_function,
-       .name = "is_set"
-},
-{
-       .parser = mm_name_like_parser,
-       .score_function = mm_name_like_score_function,
-       .cleanup = mm_name_like_cleanup,
-       .name = "name_like"
-},
-{
-       .parser = NULL
-}
+       {DEFINE_MOOD_METHOD(no_attributes_set)},
+       {DEFINE_MOOD_METHOD(played_rarely)},
+       {DEFINE_MOOD_METHOD(is_set)},
+       {DEFINE_MOOD_METHOD_WITH_CLEANUP(name_like)},
+       {.parser = NULL}
 };
 
 static void cleanup_list_entry(struct mood_item *item)
@@ -865,13 +852,13 @@ static int delete_from_statistics_and_score_table(const struct osl_row *aft_row)
  *
  * \return Positive on success, negative on errors.
  *
- * \sa score_delete(), mood_update_audio_file().
+ * \sa score_delete().
  */
-int mood_delete_audio_file(const struct osl_row *aft_row)
+static int mood_delete_audio_file(const struct osl_row *aft_row)
 {
        int ret;
 
-       ret = row_belongs_to_score_table(aft_row);
+       ret = row_belongs_to_score_table(aft_row, NULL);
        if (ret < 0)
                return ret;
        if (!ret) /* not admissible, nothing to do */
@@ -890,15 +877,17 @@ int mood_delete_audio_file(const struct osl_row *aft_row)
  *
  * \return Positive on success, negative on errors.
  */
-int mood_update_audio_file(const struct osl_row *aft_row, struct afs_info *old_afsi)
+static int mood_update_audio_file(const struct osl_row *aft_row,
+               struct afs_info *old_afsi)
 {
        long score, percent;
        int ret, is_admissible, was_admissible = 0;
        struct afs_info afsi;
+       unsigned rank;
 
        if (!current_mood)
                return 1; /* nothing to do */
-       ret = row_belongs_to_score_table(aft_row);
+       ret = row_belongs_to_score_table(aft_row, &rank);
        if (ret < 0)
                return ret;
        was_admissible = ret;
@@ -932,7 +921,7 @@ int mood_update_audio_file(const struct osl_row *aft_row, struct afs_info *old_a
                percent = 100;
        else if (percent < 0)
                percent = 0;
-       PARA_DEBUG_LOG("re-inserting at %lu%%\n", percent);
+       PARA_DEBUG_LOG("moving from rank %u to %lu%%\n", rank, percent);
        return score_update(aft_row, percent);
 }
 
@@ -1033,7 +1022,7 @@ out:
  * Free all resources of the current mood which were allocated during
  * mood_open().
  */
-void close_current_mood(void)
+static void close_current_mood(void)
 {
        destroy_mood(current_mood);
        current_mood = NULL;
@@ -1058,12 +1047,52 @@ int reload_current_mood(void)
        int ret;
        char *mood_name;
 
+       PARA_NOTICE_LOG("reloading current mood\n");
        if (!current_mood)
                return 1;
-       score_shutdown(0);
        mood_name = para_strdup(current_mood->name);
        close_current_mood();
+       ret = clear_score_table();
+       if (ret < 0)
+               return ret;
        ret = change_current_mood(mood_name);
        free(mood_name);
        return ret;
 }
+
+int moods_event_handler(enum afs_events event, struct para_buffer *pb,
+               void *data)
+{
+       switch(event) {
+       /*
+        * The three blob events might change the set of admissible files,
+        * so we must reload the score list.
+        */
+       case BLOB_RENAME:
+       case BLOB_REMOVE:
+       case BLOB_ADD:
+               if (data == moods_table || data == playlists_table)
+                       return 1; /* no reload necessary for these */
+               return reload_current_mood();
+       /* these also require reload of the score table */
+       case ATTRIBUTE_ADD:
+       case ATTRIBUTE_REMOVE:
+       case ATTRIBUTE_RENAME:
+               return reload_current_mood();
+       /* changes to the aft only require to re-examine the audio file */
+       case AFSI_CHANGE: {
+               struct afsi_change_event_data *aced = data;
+               return mood_update_audio_file(aced->aft_row, aced->old_afsi);
+               }
+       case AFHI_CHANGE:
+       case AUDIO_FILE_RENAME:
+       case AUDIO_FILE_ADD:
+               return mood_update_audio_file(data, NULL);
+       case AUDIO_FILE_REMOVE:
+               return mood_delete_audio_file(data);
+       default:
+               return 1;
+       }
+       return 1;
+}
+