X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=mood.c;h=a1ef816d7cb8d503fa1f69181da4011bd44460fa;hp=77b4a7361554fa05ca36f7685114c2bd1b7ba68c;hb=8b0ab0837ecdd5d28c7b6f31a605552f6942ca64;hpb=a6e79f02b6eab623425686f8f3cab5bc942e77d4 diff --git a/mood.c b/mood.c index 77b4a736..a1ef816d 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. */ @@ -7,12 +7,14 @@ /** \file mood.c Paraslash's mood handling functions. */ #include +#include #include "para.h" #include "error.h" #include "string.h" #include "afh.h" #include "afs.h" #include "list.h" +#include "ipc.h" /** * Contains statistical data of the currently admissible audio files. @@ -61,11 +63,11 @@ typedef int mood_score_function(const char *path, const struct afs_info *afsi, * Some mood parsers pre-process the data given in the mood line to compute a * structure which depends of the particular mood_method and which is used * later in the mood_score_function of the mood_method. The mood_parser may - * store a pointer to its structure via the second argument. + * store a pointer to its structure via the void** pointer. * * \sa mood_open(), mood_cleanup_function, mood_score_function. */ -typedef int mood_parser(const char *, void **); +typedef int mood_parser(int, char **, void **); /** * Deallocate resources which were allocated by the mood_parser. @@ -83,7 +85,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; @@ -163,11 +165,10 @@ static uint64_t int_sqrt(uint64_t x) return res; } -static int mm_no_attributes_set_parser(const char *arg, __a_unused void **ignored) +static int mm_no_attributes_set_parser(int argc, __a_unused char **argv, + __a_unused void **ignored) { - if (arg && *arg) - PARA_WARNING_LOG("ignored junk at eol: %s\n", arg); - return 1; + return argc? -E_MOOD_SYNTAX : 1; } static int mm_no_attributes_set_score_function(__a_unused const char *path, @@ -196,14 +197,13 @@ static int mm_played_rarely_score_function(__a_unused const char *path, return -100; } -static int mm_played_rarely_parser(const char *arg, __a_unused void **ignored) +static int mm_played_rarely_parser(int argc, __a_unused char **argv, + __a_unused void **ignored) { - if (arg && *arg) - PARA_WARNING_LOG("ignored junk at eol: %s\n", arg); - return 1; + return argc? -E_MOOD_SYNTAX : 1; } -static int mm_name_like_score_function(const char *path, +static int mm_path_matches_score_function(const char *path, __a_unused const struct afs_info *afsi, __a_unused const struct afh_info *afhi, const void *data) @@ -213,27 +213,33 @@ static int mm_name_like_score_function(const char *path, return 100; } -static int mm_name_like_parser(const char *arg, void **data) +static int mm_path_matches_parser(int argc, char **argv, void **data) { - *data = para_strdup(arg); + if (argc != 1) + return -E_MOOD_SYNTAX; + *data = para_strdup(argv[1]); return 1; } -static void mm_name_like_cleanup(void *data) +static void mm_path_matches_cleanup(void *data) { free(data); } -static int mm_is_set_parser(const char *arg, void **bitnum) +static int mm_is_set_parser(int argc, char **argv, void **bitnum) { - unsigned char *c = para_malloc(1); - int ret = get_attribute_bitnum_by_name(arg, c); + int ret; + unsigned char c, *res; - if (ret >= 0) - *bitnum = c; - else - free(c); - return ret; + if (argc != 1) + return -E_MOOD_SYNTAX; + ret = get_attribute_bitnum_by_name(argv[1], &c); + if (ret < 0) + return ret; + res = para_malloc(1); + *res = c; + *bitnum = res; + return 1; } static int mm_is_set_score_function(__a_unused const char *path, @@ -320,7 +326,7 @@ static const struct mood_method mood_methods[] = { {DEFINE_MOOD_METHOD(no_attributes_set)}, {DEFINE_MOOD_METHOD(played_rarely)}, {DEFINE_MOOD_METHOD(is_set)}, - {DEFINE_MOOD_METHOD_WITH_CLEANUP(name_like)}, + {DEFINE_MOOD_METHOD_WITH_CLEANUP(path_matches)}, {.parser = NULL} }; @@ -372,8 +378,11 @@ enum mood_line_type { ML_SCORE }; +/** Data passed to the parser of a mood line. */ struct mood_line_parser_data { + /** The mood this mood line belongs to. */ struct mood *m; + /** The line number in the mood definition. */ unsigned line_num; }; @@ -388,17 +397,17 @@ static int parse_mood_line(char *mood_line, void *data) { struct mood_line_parser_data *mlpd = data; char **argv; - char *delim = " \t"; unsigned num_words; char **w; int i, ret; enum mood_line_type mlt = ML_INVALID; struct mood_item *mi = NULL; - char *buf = para_strdup(mood_line); mlpd->line_num++; - num_words = split_args(buf, &argv, delim); - ret = 1; + ret = create_argv(mood_line, " \t", &argv); + if (ret < 0) + return ret; + num_words = ret; if (!num_words) /* empty line */ goto out; w = argv; @@ -419,11 +428,13 @@ static int parse_mood_line(char *mood_line, void *data) w++; if (!*w) goto out; - if (!strcmp(*w, "with")) { - w++; - if (!*w) - goto out; - } + if (strcmp(*w, "with")) + goto check_for_if; + w++; + if (!*w) + goto out; + if (strcmp(*w, "score")) + goto out; } if (mlt == ML_SCORE || !strcmp(*w, "score")) { ret = -E_MOOD_SYNTAX; @@ -446,6 +457,7 @@ static int parse_mood_line(char *mood_line, void *data) w++; if (!*w) goto out; +check_for_if: if (!strcmp(*w, "if")) { ret = -E_MOOD_SYNTAX; w++; @@ -468,8 +480,8 @@ static int parse_mood_line(char *mood_line, void *data) ret = -E_MOOD_SYNTAX; if (!mood_methods[i].parser) goto out; - w++; - ret = mood_methods[i].parser(*w, &mi->parser_data); + ret = mood_methods[i].parser(num_words - 1 - (w - argv), w, + &mi->parser_data); if (ret < 0) goto out; mi->method = &mood_methods[i]; @@ -486,8 +498,7 @@ success: (mlt == ML_DENY? "deny" : "score"), mi->method); ret = 1; out: - free(argv); - free(buf); + free_argv(argv); if (ret >= 0) return ret; if (mi) { @@ -514,7 +525,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; } @@ -532,39 +543,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 @@ -956,7 +975,7 @@ int change_current_mood(char *mood_name) .data = mood_name, .size = strlen(mood_name) + 1 }; - ret = osl_get_row(moods_table, BLOBCOL_NAME, &obj, &row); + ret = osl(osl_get_row(moods_table, BLOBCOL_NAME, &obj, &row)); if (ret < 0) { PARA_NOTICE_LOG("no such mood: %s\n", mood_name); return ret; @@ -1007,9 +1026,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(); @@ -1051,6 +1071,5 @@ int moods_event_handler(enum afs_events event, __a_unused struct para_buffer *pb default: return 1; } - return 1; }