X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=mood.c;h=584c46b8fa375f24d2f87492d44f67ac902fa98b;hp=315ef0cbdc61b7de1a3bbbd8f8683d7ab81d9c81;hb=3d3a2f50;hpb=80541d0f045e1ed57332800eff9832e0a5b72ddf diff --git a/mood.c b/mood.c index 315ef0cb..584c46b8 100644 --- a/mood.c +++ b/mood.c @@ -16,11 +16,18 @@ #include "afh.h" #include "afs.h" #include "list.h" -#include "ipc.h" #include "mm.h" -#include "sideband.h" #include "mood.h" -#include "sched.h" + +/* + * Mood parser API. It's overkill to have an own header file for + * these declarations as they are only needed in this .c file. + */ +struct mp_context; +int mp_init(const char *definition, int nbytes, struct mp_context **result, + char **errmsg); +bool mp_eval_row(const struct osl_row *aft_row, struct mp_context *ctx); +void mp_shutdown(struct mp_context *ctx); /** * Contains statistical data of the currently admissible audio files. @@ -76,6 +83,8 @@ struct mood { struct list_head deny_list; /** The list of mood items of type \p score. */ struct list_head score_list; + /* Only used for version 2 moods. */ + struct mp_context *parser_context; }; /* @@ -153,6 +162,10 @@ static int row_is_admissible(const struct osl_row *aft_row, struct mood *m, if (!m) return -E_NO_MOOD; + if (m->parser_context) { + *scorep = 0; + return mp_eval_row(aft_row, m->parser_context); + } ret = get_afsi_of_row(aft_row, &afsi); if (ret < 0) return ret; @@ -217,6 +230,7 @@ static void destroy_mood(struct mood *m) list_for_each_entry_safe(item, tmp, &m->score_list, mood_item_node) cleanup_list_entry(item); free(m->name); + mp_shutdown(m->parser_context); free(m); } @@ -363,16 +377,15 @@ success: ret = 1; out: free_argv(argv); - if (ret >= 0) - return ret; - if (mi) { + if (mi && (ret < 0 || !mlpd->m)) { /* mi was not added to any list */ free(mi->parser_data); free(mi); } return ret; } -static int load_mood(const struct osl_row *mood_row, struct mood **m) +static int load_mood(const struct osl_row *mood_row, struct mood **m, + char **errmsg) { char *mood_name; struct osl_object mood_def; @@ -388,15 +401,21 @@ static int load_mood(const struct osl_row *mood_row, struct mood **m) mlpd.m = alloc_new_mood(mood_name); 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) { - PARA_ERROR_LOG("unable to load mood %s: %s\n", mlpd.m->name, - para_strerror(-ret)); - destroy_mood(mlpd.m); - return ret; + PARA_INFO_LOG("opening version 2 mood %s\n", mlpd.m->name); + ret = mp_init(mood_def.data, mood_def.size, &mlpd.m->parser_context, + errmsg); + if (ret < 0) + destroy_mood(mlpd.m); + } else { + PARA_WARNING_LOG("loaded version 1 mood %s\n", mlpd.m->name); + PARA_WARNING_LOG("please convert to version 2\n"); + ret = 1; } - *m = mlpd.m; - return 1; + osl_close_disk_object(&mood_def); + if (ret >= 0) + *m = mlpd.m; + return ret; } static int check_mood(struct osl_row *mood_row, void *data) @@ -414,12 +433,24 @@ static int check_mood(struct osl_row *mood_row, void *data) } if (!*mood_name) /* ignore dummy row */ 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, "mood %s: error in line %u: %s\n", mood_name, - mlpd.line_num, para_strerror(-ret)); + if (ret < 0) { + char *errmsg; + struct mood *m = alloc_new_mood("check"); + ret = mp_init(mood_def.data, mood_def.size, &m->parser_context, + &errmsg); + if (ret < 0) { + para_printf(pb, "%s: %s\n", mood_name, errmsg); + free(errmsg); + para_printf(pb, "%s\n", para_strerror(-ret)); + } else + destroy_mood(m); + } else { + para_printf(pb, "%s: v1 mood, please convert to v2\n", + mood_name); + + } ret = 1; /* don't fail the loop on invalid mood definitions */ out: osl_close_disk_object(&mood_def); @@ -789,18 +820,22 @@ void close_current_mood(void) * Change the current mood. * * \param mood_name The name of the mood to open. + * \param errmsg Error description is returned here. * * If \a mood_name is \a NULL, load the dummy mood that accepts every audio file * and uses a scoring method based only on the \a last_played information. * + * The errmsg pointer may be NULL, in which case no error message will be + * returned. If a non-NULL pointer is given, the caller must free *errmsg. + * * If there is already an open mood, it will be closed first. * * \return Positive on success, negative on errors. Loading the dummy mood * always succeeds. * - * \sa struct \ref afs_info::last_played. + * \sa struct \ref afs_info::last_played, \ref mp_eval_row(). */ -int change_current_mood(const char *mood_name) +int change_current_mood(const char *mood_name, char **errmsg) { int i, ret; struct admissible_array aa = { @@ -820,7 +855,7 @@ int change_current_mood(const char *mood_name) PARA_NOTICE_LOG("no such mood: %s\n", mood_name); return ret; } - ret = load_mood(row, &m); + ret = load_mood(row, &m, errmsg); if (ret < 0) return ret; close_current_mood(); @@ -871,7 +906,7 @@ static int reload_current_mood(void) if (current_mood->name) mood_name = para_strdup(current_mood->name); close_current_mood(); - ret = change_current_mood(mood_name); + ret = change_current_mood(mood_name, NULL); free(mood_name); return ret; }