X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=mood.c;h=9f1d7745a3589565045b919af94ad02b3f73602d;hp=9ddfc58853574a09d4d0073b052df14bced7054a;hb=4d5a9b90c3e9cbdff019776d05792beb57fbfa31;hpb=d36700894126811870ae0a0bcb5dbdb59588289c diff --git a/mood.c b/mood.c index 9ddfc588..9f1d7745 100644 --- a/mood.c +++ b/mood.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 Andre Noll + * Copyright (C) 2007-2009 Andre Noll * * Licensed under the GPL v2. For licencing details see COPYING. */ @@ -13,6 +13,7 @@ #include "afh.h" #include "afs.h" #include "list.h" +#include "ipc.h" /** * Contains statistical data of the currently admissible audio files. @@ -83,7 +84,7 @@ 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. */ + /** The name of the method. */ const char *name; /** Pointer to the mood parser. */ mood_parser *parser; @@ -247,14 +248,14 @@ static int mm_is_set_score_function(__a_unused const char *path, return -100; } -/* returns 1 if row matches score item, negative otherwise */ -static int add_item_score(const struct osl_row *row, struct mood_item *item, long *score, - long *score_arg_sum) +/* returns 1 if row matches score item, 0 if not, negative on errors */ +static int get_item_score(const struct osl_row *row, struct mood_item *item, + long *score, long *score_arg_sum) { struct afs_info afsi; struct afh_info afhi; char *path; - int ret; + int ret, match = 1; *score_arg_sum += item->random_score? 100 : PARA_ABS(item->score_arg); ret = 100; @@ -265,42 +266,62 @@ static int add_item_score(const struct osl_row *row, struct mood_item *item, lon ret = get_afhi_of_row(row, &afhi); if (ret< 0) return ret; + free(afhi.info_string); /* don't need the tag info */ ret = get_audio_file_path_of_row(row, &path); if (ret< 0) return ret; ret = item->method->score_function(path, &afsi, &afhi, item->parser_data); if ((ret < 0 && !item->logical_not) || (ret >= 0 && item->logical_not)) - return -1; /* no match */ + match = 0; /* no match */ } if (item->random_score) - *score += PARA_ABS(ret) * para_random(100); + *score = PARA_ABS(ret) * para_random(100); else - *score += PARA_ABS(ret) * item->score_arg; - return 1; + *score = PARA_ABS(ret) * item->score_arg; + return match; } +/* returns 1 if row admissible, 0 if not, negative on errors */ static int compute_mood_score(const struct osl_row *aft_row, struct mood *m, long *result) { struct mood_item *item; - int match = 0; - long score_arg_sum = 0, score = 0; + int ret, match = 0; + long score_arg_sum = 0, score = 0, item_score; if (!m) return -E_NO_MOOD; /* reject audio file if it matches any entry in the deny list */ - list_for_each_entry(item, &m->deny_list, mood_item_node) - if (add_item_score(aft_row, item, &score, &score_arg_sum) > 0) - return -E_NOT_ADMISSIBLE; - list_for_each_entry(item, &m->accept_list, mood_item_node) - if (add_item_score(aft_row, item, &score, &score_arg_sum) > 0) - match = 1; + list_for_each_entry(item, &m->deny_list, mood_item_node) { + ret = get_item_score(aft_row, item, &item_score, + &score_arg_sum); + if (ret < 0) + return ret; + if (ret > 0) /* not admissible */ + return 0; + score += item_score; + } + list_for_each_entry(item, &m->accept_list, mood_item_node) { + ret = get_item_score(aft_row, item, &item_score, + &score_arg_sum); + if (ret < 0) + return ret; + if (ret == 0) + continue; + match = 1; + score += item_score; + } /* reject if there is no matching entry in the accept list */ if (!match && !list_empty(&m->accept_list)) - return -E_NOT_ADMISSIBLE; - list_for_each_entry(item, &m->score_list, mood_item_node) - add_item_score(aft_row, item, &score, &score_arg_sum); + return 0; + list_for_each_entry(item, &m->score_list, mood_item_node) { + ret = get_item_score(aft_row, item, &item_score, + &score_arg_sum); + if (ret < 0) + return ret; + score += item_score; + } if (score_arg_sum) score /= score_arg_sum; *result = score; @@ -520,7 +541,7 @@ static int load_mood(const struct osl_row *mood_row, struct mood **m) osl_close_disk_object(&mood_def); if (ret < 0) { PARA_ERROR_LOG("unable to load mood %s: %s\n", mlpd.m->name, - PARA_STRERROR(-ret)); + para_strerror(-ret)); destroy_mood(mlpd.m); return ret; } @@ -538,39 +559,47 @@ static int check_mood(struct osl_row *mood_row, void *data) int ret = mood_get_name_and_def_by_row(mood_row, &mood_name, &mood_def); if (ret < 0) { - para_printf(pb, "failed to get mood definition\n"); + para_printf(pb, "failed to get mood definition: %s\n", + para_strerror(-ret)); return ret; } if (!*mood_name) /* ignore dummy row */ goto out; - para_printf(pb, "checking mood %s...\n", mood_name); + 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, parse_mood_line, &mlpd); if (ret < 0) para_printf(pb, "%s line %u: %s\n", mood_name, mlpd.line_num, - PARA_STRERROR(-ret)); + para_strerror(-ret)); out: osl_close_disk_object(&mood_def); - return 1; + return ret; } /** * Check all moods for syntax errors. * + * \param fd The afs socket. * \param query Unused. - * \param result: Contains check messages. */ -int mood_check_callback(__a_unused const struct osl_object *query, - struct osl_object *result) +void mood_check_callback(int fd, __a_unused const struct osl_object *query) { - struct para_buffer pb = {.buf = NULL}; + struct para_buffer pb = { + .max_size = SHMMAX, + .private_data = &fd, + .max_size_handler = pass_buffer_as_shm + }; - para_printf(&pb, "checking moods...\n"); + int ret = para_printf(&pb, "checking moods...\n"); + if (ret < 0) + return; osl_rbtree_loop(moods_table, BLOBCOL_ID, &pb, check_mood); - result->data = pb.buf; - result->size = pb.size; - return 1; + if (pb.offset) + pass_buffer_as_shm(pb.buf, pb.offset, &fd); + free(pb.buf); } #if 0 @@ -720,7 +749,7 @@ struct admissible_array { * \param aft_row The audio file to be added. * \param private_data Pointer to a struct admissible_file_info. * - * \return Negative on errors, positive on success. + * \return 1 if row admissible, 0 if not, negative on errors. */ static int add_if_admissible(struct osl_row *aft_row, void *data) { @@ -729,8 +758,8 @@ static int add_if_admissible(struct osl_row *aft_row, void *data) long score = 0; ret = compute_mood_score(aft_row, aa->m, &score); - if (ret < 0) - return (ret == -E_NOT_ADMISSIBLE)? 1 : ret; + if (ret <= 0) + return ret; if (statistics.num >= aa->size) { aa->size *= 2; aa->size += 100; @@ -868,6 +897,8 @@ static int mood_update_audio_file(const struct osl_row *aft_row, return ret; was_admissible = ret; ret = compute_mood_score(aft_row, current_mood, &score); + if (ret < 0) + return ret; is_admissible = (ret > 0); if (!was_admissible && !is_admissible) return 1; @@ -1013,9 +1044,10 @@ int reload_current_mood(void) int ret; char *mood_name = NULL; - PARA_NOTICE_LOG("reloading current mood\n"); if (!current_mood) return 1; + PARA_NOTICE_LOG("reloading %s\n", current_mood->name? + current_mood->name : "(dummy)"); if (current_mood->name) mood_name = para_strdup(current_mood->name); close_current_mood(); @@ -1027,7 +1059,9 @@ int reload_current_mood(void) int moods_event_handler(enum afs_events event, __a_unused struct para_buffer *pb, void *data) { - switch(event) { + if (!current_mood) + return 0; + switch (event) { /* * The three blob events might change the set of admissible files, * so we must reload the score list. @@ -1057,6 +1091,5 @@ int moods_event_handler(enum afs_events event, __a_unused struct para_buffer *pb default: return 1; } - return 1; }