X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=mood.c;h=9074581c6c8d40741a99c3c1772716381e03f2a4;hp=e685fd91c982fd82cd9afa69c3a06932328907a5;hb=97f53e18953fc2013c0b14f0261ac385e45b0284;hpb=07010f70da6ea0ba9940116eef83abeb02fa8d5d diff --git a/mood.c b/mood.c index e685fd91..9074581c 100644 --- a/mood.c +++ b/mood.c @@ -9,10 +9,10 @@ #include #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. @@ -164,6 +163,23 @@ static uint64_t int_sqrt(uint64_t x) return res; } +static int mm_no_attributes_set_parser(const char *arg, __a_unused void **ignored) +{ + if (arg && *arg) + PARA_WARNING_LOG("ignored junk at eol: %s\n", arg); + return 1; +} + +static int mm_no_attributes_set_score_function(__a_unused const char *path, + const struct afs_info *afsi, + __a_unused const struct audio_format_info *afhi, + __a_unused const void *data) +{ + if (!afsi->attributes) + return 100; + return -100; +} + static int mm_played_rarely_score_function(__a_unused const char *path, const struct afs_info *afsi, __a_unused const struct audio_format_info *afhi, @@ -182,7 +198,7 @@ static int mm_played_rarely_score_function(__a_unused const char *path, static int mm_played_rarely_parser(const char *arg, __a_unused void **ignored) { - if (*arg) + if (arg && *arg) PARA_WARNING_LOG("ignored junk at eol: %s\n", arg); return 1; } @@ -291,26 +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_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) @@ -841,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 */ @@ -866,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; @@ -908,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); } @@ -1009,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; @@ -1034,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; +} +