#include <regex.h>
#include <osl.h>
+#include <lopsub.h>
#include "para.h"
#include "error.h"
#include "mm.h"
#include "sideband.h"
#include "mood.h"
+#include "sched.h"
/**
* Contains statistical data of the currently admissible audio files.
struct list_head mood_item_node;
};
-/**
- * Created from the mood definition by mood_open().
+/*
+ * Created from the mood definition by \ref change_current_mood().
*
* When a mood is opened, each line of its definition is investigated, and a
- * corresponding mood item is produced. Each mood line starts with \p accept,
- * \p deny, or \p score which determines the type of the mood line. For each
- * such type a linked list is maintained whose entries are the mood items.
- *
- * \sa mood_item, mood_open().
+ * corresponding mood item is produced. Each mood line starts with accept,
+ * deny, or score which determines the type of the mood line. For each such
+ * type a linked list is maintained whose entries are the mood items.
*/
struct mood {
/** The name of this mood. */
/*
* If current_mood is NULL then no mood is currently open. If
- * current_mood->name is NULL, the dummy mood is currently open
+ * current_mood->name is NULL, the dummy mood is currently open.
*/
static struct mood *current_mood;
}
/* 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)
+static int row_is_admissible(const struct osl_row *aft_row, struct mood *m,
+ long *scorep)
{
struct mood_item *item;
int ret;
if (!m)
return -E_NO_MOOD;
ret = get_afsi_of_row(aft_row, &afsi);
- if (ret< 0)
+ if (ret < 0)
return ret;
ret = get_afhi_of_row(aft_row, &afhi);
- if (ret< 0)
+ if (ret < 0)
return ret;
ret = get_audio_file_path_of_row(aft_row, &path);
- if (ret< 0)
+ if (ret < 0)
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) {
}
if (score_arg_sum)
score /= score_arg_sum;
- *result = score;
+ *scorep = score;
return 1;
}
* <score> is either an integer or "random" which assigns a random score to
* all matching files
*/
-
static int parse_mood_line(char *mood_line, void *data)
{
struct mood_line_parser_data *mlpd = data;
return 1;
}
-/**
- * Structure used during mood_open().
- *
+/*
* 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
* 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.
*/
struct admissible_file_info
{
int ret;
long score = 0;
- ret = compute_mood_score(aft_row, aa->m, &score);
+ ret = row_is_admissible(aft_row, aa->m, &score);
if (ret <= 0)
return ret;
if (statistics.num >= aa->size) {
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)
+static int update_afs_statistics(struct afs_info *old_afsi,
+ struct afs_info *new_afsi)
{
unsigned n;
int ret = get_num_admissible_files(&n);
*
* \return Positive on success, negative on errors.
*
- * \sa score_delete().
+ * \sa \ref score_delete().
*/
static int mood_delete_audio_file(const struct osl_row *aft_row)
{
if (ret < 0)
return ret;
was_admissible = ret;
- ret = compute_mood_score(aft_row, current_mood, &score);
+ ret = row_is_admissible(aft_row, current_mood, &score);
if (ret < 0)
return ret;
is_admissible = (ret > 0);
percent = 100;
else if (percent < 0)
percent = 0;
- PARA_DEBUG_LOG("moving from rank %u to %lu%%\n", rank, percent);
+ PARA_DEBUG_LOG("moving from rank %u to %li%%\n", rank, percent);
return score_update(aft_row, percent);
}
static void log_statistics(void)
{
unsigned n = statistics.num;
+ int mean_days, sigma_days;
+ /*
+ * We can not use the "now" pointer from sched.c here because we are
+ * called before schedule(), which initializes "now".
+ */
+ struct timeval rnow;
+ assert(current_mood);
+ PARA_NOTICE_LOG("loaded mood %s\n", current_mood->name?
+ current_mood->name : "(dummy)");
if (!n) {
- PARA_NOTICE_LOG("no admissible files\n");
+ PARA_WARNING_LOG("no admissible files\n");
return;
}
- PARA_INFO_LOG("last_played mean: %lli, last_played sigma: %llu\n",
- (long long int)(statistics.last_played_sum / n),
- (long long unsigned)int_sqrt(statistics.last_played_qd / n));
- PARA_INFO_LOG("num_played mean: %lli, num_played sigma: %llu\n",
- (long long int)statistics.num_played_sum / n,
+ PARA_NOTICE_LOG("%u admissible files\n", statistics.num);
+ clock_get_realtime(&rnow);
+ mean_days = (rnow.tv_sec - statistics.last_played_sum / n) / 3600 / 24;
+ sigma_days = int_sqrt(statistics.last_played_qd / n) / 3600 / 24;
+ PARA_NOTICE_LOG("last_played mean/sigma: %d/%d days\n", mean_days, sigma_days);
+ PARA_NOTICE_LOG("num_played mean/sigma: %llu/%llu\n",
+ (long long unsigned)statistics.num_played_sum / n,
(long long unsigned)int_sqrt(statistics.num_played_qd / n));
}
/**
* Close the current mood.
*
- * Free all resources of the current mood which were allocated during
- * mood_open().
+ * Frees all resources of the current mood.
*/
void close_current_mood(void)
{
* \return Positive on success, negative on errors. Loading the dummy mood
* always succeeds.
*
- * \sa struct admissible_file_info, struct admissible_array, struct
- * afs_info::last_played, mood_close().
+ * \sa struct \ref afs_info::last_played.
*/
int change_current_mood(const char *mood_name)
{
ret = audio_file_loop(&aa, add_if_admissible);
if (ret < 0)
return ret;
- log_statistics();
- 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", mood_name? mood_name : "(dummy)");
+ log_statistics();
ret = statistics.num;
out:
free(aa.array);
return ret;
}
-/**
+
+/*
* Close and re-open the current mood.
*
- * This function is used if changes to the audio file table or the
- * attribute table were made that render the current list of admissible
- * files useless. For example, if an attribute is removed from the
- * attribute table, this function is called.
- *
- * \return Positive on success, negative on errors. If no mood is currently
- * open, the function returns success.
+ * This function is called on events which render the current list of
+ * admissible files useless, for example if an attribute is removed from the
+ * attribute table.
*
- * \sa mood_open(), mood_close().
+ * If no mood is currently open, the function returns success.
*/
static int reload_current_mood(void)
{