X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=mood.c;h=83c3a574a53c5658afe43a296ae2de9f2c368873;hp=a2525a78d627b789697253fcfe5b565ba8ef9fbe;hb=06d0c50525fc14e8127916481a74c14a2f7098af;hpb=bc15c3ff65eb00e04ebc303cfa9ee3d1a4675b35 diff --git a/mood.c b/mood.c index a2525a78..83c3a574 100644 --- a/mood.c +++ b/mood.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007-2014 Andre Noll + * Copyright (C) 2007 Andre Noll * * Licensed under the GPL v2. For licencing details see COPYING. */ @@ -30,7 +30,7 @@ struct afs_statistics { int64_t num_played_sum; /** Sum of last played times over all admissible files. */ int64_t last_played_sum; - /** Quadratic deviation of num played time. */ + /** Quadratic deviation of num played count. */ int64_t num_played_qd; /** Quadratic deviation of last played time. */ int64_t last_played_qd; @@ -410,20 +410,18 @@ 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: %s\n", - para_strerror(-ret)); + para_printf(pb, "cannot read mood\n"); return ret; } if (!*mood_name) /* ignore dummy row */ goto out; - ret = para_printf(pb, "checking mood %s...\n", mood_name); - if (ret < 0) - goto out; + para_printf(pb, "checking mood %s...\n", mood_name); 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, - para_strerror(-ret)); + para_printf(pb, "mood %s: error in line %u: %s\n", mood_name, + mlpd.line_num, para_strerror(-ret)); + ret = 1; /* don't fail the loop on invalid mood definitions */ out: osl_close_disk_object(&mood_def); return ret; @@ -432,35 +430,23 @@ out: /** * Check all moods for syntax errors. * - * \param fd The afs socket. - * \param query Unused. + * \param aca Only ->pbout is used for diagnostics. + * + * \return Negative on fatal errors. Inconsistent mood definitions are not + * considered an error. */ -void mood_check_callback(int fd, __a_unused const struct osl_object *query) +int mood_check_callback(struct afs_callback_arg *aca) { - struct para_buffer pb = { - .max_size = shm_get_shmmax(), - .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"); - if (ret < 0) - return; - osl_rbtree_loop(moods_table, BLOBCOL_ID, &pb, - check_mood); - if (pb.offset) - pass_buffer_as_shm(fd, SBD_OUTPUT, pb.buf, pb.offset); - free(pb.buf); + para_printf(&aca->pbout, "checking moods...\n"); + return osl(osl_rbtree_loop(moods_table, BLOBCOL_ID, &aca->pbout, + check_mood)); } static int64_t normalized_value(int64_t x, int64_t n, int64_t sum, int64_t qd) { if (!n || !qd) return 0; - return 100 * (n * x - sum) / (int64_t)int_sqrt(n * 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) @@ -474,7 +460,7 @@ static long compute_score(struct afs_info *afsi, long mood_score) static int add_afs_statistics(const struct osl_row *row) { - uint64_t n, x, s; + uint64_t n, x, s, q; struct afs_info afsi; int ret; @@ -484,14 +470,18 @@ static int add_afs_statistics(const struct osl_row *row) n = statistics.num; x = afsi.last_played; s = statistics.last_played_sum; - if (n > 0) - statistics.last_played_qd += (x - s / n) * (x - s / n) * n / (n + 1); + if (n > 0) { + q = (x > s / n)? x - s / n : s / n - x; + statistics.last_played_qd += q * q * n / (n + 1); + } statistics.last_played_sum += x; x = afsi.num_played; s = statistics.num_played_sum; - if (n > 0) - statistics.num_played_qd += (x - s / n) * (x - s / n) * n / (n + 1); + if (n > 0) { + q = (x > s / n)? x - s / n : s / n - x; + statistics.num_played_qd += q * q * n / (n + 1); + } statistics.num_played_sum += x; statistics.num++; return 1; @@ -535,16 +525,16 @@ static int del_afs_statistics(const struct osl_row *row) /** * Structure used during mood_open(). * - * At mood open time, we look at each file in the audio file table in order to - * determine whether it is admissible. If a file happens to be admissible, its - * mood score is computed by calling each relevant mood_score_function. Next, - * we update the afs_statistics and add a struct admissible_file_info to a - * temporary array. + * 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. * - * If all files have been processed that way, the final score of each + * 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) to the mood score. Finally, all audio files in the - * array are added to the score table and the admissible array is freed. + * 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. * * \sa mood_method, admissible_array. */ @@ -618,7 +608,8 @@ static int add_if_admissible(struct osl_row *aft_row, void *data) * the last number a_n was replaced by b) may be computed in O(1) time in terms * of n, q, a_n, b, and S as * - * q' = q + d * s - (2 * S + d) * d / n, + * q' = q + d * s - (2 * S + d) * d / n + * = q + d * (s - 2 * S / n - d /n), * * where d = b - a_n, and s = b + a_n. * @@ -635,7 +626,7 @@ _static_inline_ int64_t update_quadratic_deviation(int64_t n, int64_t old_qd, { int64_t delta = new_val - old_val; int64_t sigma = new_val + old_val; - return old_qd + delta * sigma - (2 * old_sum + delta) * delta / n; + return old_qd + delta * (sigma - 2 * old_sum / n - delta / n); } static int update_afs_statistics(struct afs_info *old_afsi, struct afs_info *new_afsi) @@ -804,7 +795,7 @@ void close_current_mood(void) * \sa struct admissible_file_info, struct admissible_array, struct * afs_info::last_played, mood_close(). */ -int change_current_mood(char *mood_name) +int change_current_mood(const char *mood_name) { int i, ret; struct admissible_array aa = { @@ -816,7 +807,7 @@ int change_current_mood(char *mood_name) struct mood *m; struct osl_row *row; struct osl_object obj = { - .data = mood_name, + .data = (char *)mood_name, .size = strlen(mood_name) + 1 }; ret = osl(osl_get_row(moods_table, BLOBCOL_NAME, &obj, &row)); @@ -870,6 +861,9 @@ static int reload_current_mood(void) int ret; char *mood_name = NULL; + ret = clear_score_table(); + if (ret < 0) + return ret; if (!current_mood) return 1; PARA_NOTICE_LOG("reloading %s\n", current_mood->name? @@ -898,8 +892,6 @@ static int reload_current_mood(void) int moods_event_handler(enum afs_events event, __a_unused struct para_buffer *pb, void *data) { - int ret; - if (!current_mood) return 0; switch (event) { @@ -912,10 +904,6 @@ int moods_event_handler(enum afs_events event, __a_unused struct para_buffer *pb case BLOB_ADD: if (data == moods_table || data == playlists_table) return 1; /* no reload necessary for these */ - ret = clear_score_table(); - if (ret < 0) - PARA_CRIT_LOG("clear score table returned %s\n", - para_strerror(-ret)); return reload_current_mood(); /* these also require reload of the score table */ case ATTRIBUTE_ADD: