/*
- * Copyright (C) 2007-2011 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2007 Andre Noll <maan@tuebingen.mpg.de>
*
* Licensed under the GPL v2. For licencing details see COPYING.
*/
#include "list.h"
#include "ipc.h"
#include "mm.h"
+#include "sideband.h"
+#include "mood.h"
/**
* Contains statistical data of the currently admissible audio files.
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;
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;
/**
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;
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);
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;
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;
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);
char *mood_name;
struct osl_object mood_def;
struct mood_line_parser_data mlpd = {.line_num = 0};
- int ret = mood_get_name_and_def_by_row(mood_row, &mood_name, &mood_def);
+ int ret;
+ *m = NULL;
+ ret = mood_get_name_and_def_by_row(mood_row, &mood_name, &mood_def);
if (ret < 0)
return ret;
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) {
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,
{
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");
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)
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)
/**
* 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.
*/
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);
}
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)
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");
if (ret < 0)
return ret;
log_statistics();
- PARA_INFO_LOG("%d admissible files \n", statistics.num);
+ PARA_INFO_LOG("%d admissible files\n", statistics.num);
for (i = 0; i < statistics.num; i++) {
struct admissible_file_info *a = aa.array + i;
ret = add_to_score_table(a->aft_row, a->score);
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);
* 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)