X-Git-Url: http://git.tuebingen.mpg.de/?a=blobdiff_plain;f=afs.c;h=cea8f2707491f00bab0f457a3463fd4762147a21;hb=9055c71be97f1095dcdbd83da305b600f204f763;hp=f9dd7583df42a3b5d8bf48fe36ccdea88020c3d4;hpb=328a4081d2ca9a99cbd87bf58133254dea77a86a;p=paraslash.git diff --git a/afs.c b/afs.c index f9dd7583..cea8f270 100644 --- a/afs.c +++ b/afs.c @@ -30,20 +30,29 @@ #include "sched.h" #include "fd.h" #include "signal.h" -#include "mood.h" #include "sideband.h" #include "command.h" -static struct afs_table afs_tables[] = { - {.init = aft_init, .name = "audio_files"}, - {.init = attribute_init, .name = "attributes"}, - {.init = score_init, .name = "scores"}, - {.init = moods_init, .name = "moods"}, - {.init = lyrics_init, .name = "lyrics"}, - {.init = images_init, .name = "images"}, - {.init = playlists_init, .name = "playlists"}, +/** + * The array of tables of the audio file selector. + * + * We organize them in an array to be able to loop over all tables. + */ +static const struct afs_table { + /** The name is no table operation, so define it here. */ + const char * const name; + /** The only way to invoke the ops is via this pointer. */ + const struct afs_table_operations *ops; +} afs_tables[] = { + {.name = "audio_files", .ops = &aft_ops}, + {.name = "attributes", .ops = &attr_ops}, + {.name = "scores", .ops = &score_ops}, + {.name = "moods", .ops = &moods_ops}, + {.name = "lyrics", .ops = &lyrics_ops}, + {.name = "images", .ops = &images_ops}, + {.name = "playlists", .ops = &playlists_ops}, }; - +/** Used to loop over the afs tables. */ #define NUM_AFS_TABLES ARRAY_SIZE(afs_tables) struct command_task { @@ -91,7 +100,7 @@ extern uint32_t afs_socket_cookie; */ struct callback_query { /** The function to be called. */ - afs_callback *handler; + afs_callback *cb; /** The number of bytes of the query */ size_t query_size; }; @@ -182,7 +191,7 @@ int send_callback_request(afs_callback *f, struct osl_object *query, if (ret < 0) goto out; cq = query_shm; - cq->handler = f; + cq->cb = f; cq->query_size = query_shm_size - sizeof(*cq); if (query) @@ -422,40 +431,30 @@ no_admissible_files: return write_all(server_socket, buf, 8); } -static int activate_mood_or_playlist(const char *arg, int *num_admissible, - char **errmsg) +static int activate_mood_or_playlist(const char *arg, struct para_buffer *pb) { enum play_mode mode; int ret; + char *msg; if (!arg) { + ret = mood_load(NULL, &msg); + mode = PLAY_MODE_MOOD; + } else if (!strncmp(arg, "p/", 2)) { + ret = playlist_load(arg + 2, &msg); + mode = PLAY_MODE_PLAYLIST; + } else if (!strncmp(arg, "m/", 2)) { + ret = mood_load(arg + 2, &msg); mode = PLAY_MODE_MOOD; - ret = change_current_mood(NULL, errmsg); - if (ret < 0) { - if (num_admissible) - *num_admissible = 0; - return ret; - } } else { - if (!strncmp(arg, "p/", 2)) { - ret = playlist_open(arg + 2); - if (ret < 0 && errmsg) - *errmsg = make_message( "could not open %s", - arg); - mode = PLAY_MODE_PLAYLIST; - } else if (!strncmp(arg, "m/", 2)) { - ret = change_current_mood(arg + 2, errmsg); - mode = PLAY_MODE_MOOD; - } else { - if (errmsg) - *errmsg = make_message("%s: parse error", arg); - return -ERRNO_TO_PARA_ERROR(EINVAL); - } - if (ret < 0) - return ret; + ret = -ERRNO_TO_PARA_ERROR(EINVAL); + msg = make_message("%s: parse error", arg); } - if (num_admissible) - *num_admissible = ret; + if (pb) + para_printf(pb, "%s", msg); + free(msg); + if (ret < 0) + return ret; current_play_mode = mode; /* * We get called with arg == current_mop from the signal dispatcher @@ -465,22 +464,15 @@ static int activate_mood_or_playlist(const char *arg, int *num_admissible, */ if (arg != current_mop) { free(current_mop); - if (arg) { - current_mop = para_strdup(arg); - mutex_lock(mmd_mutex); - strncpy(mmd->afs_mode_string, arg, - sizeof(mmd->afs_mode_string)); - mmd->afs_mode_string[sizeof(mmd->afs_mode_string) - 1] = '\0'; - mmd->events++; - mutex_unlock(mmd_mutex); - } else { - mutex_lock(mmd_mutex); - strcpy(mmd->afs_mode_string, "dummy"); - mmd->events++; - mutex_unlock(mmd_mutex); - current_mop = NULL; - } + current_mop = arg? para_strdup(arg) : NULL; } + /* Notify the server about the mood/playlist change. */ + mutex_lock(mmd_mutex); + strncpy(mmd->afs_mode_string, arg? arg: "dummy", + sizeof(mmd->afs_mode_string)); + mmd->afs_mode_string[sizeof(mmd->afs_mode_string) - 1] = '\0'; + mmd->events++; + mutex_unlock(mmd_mutex); return 1; } @@ -537,46 +529,30 @@ static int com_select_callback(struct afs_callback_arg *aca) { const struct lls_command *cmd = SERVER_CMD_CMD_PTR(SELECT); const char *arg; - int num_admissible, ret; - char *errmsg; + int ret; ret = lls_deserialize_parse_result(aca->query.data, cmd, &aca->lpr); assert(ret >= 0); arg = lls_input(0, aca->lpr); - ret = clear_score_table(); - if (ret < 0) { - para_printf(&aca->pbout, "could not clear score table\n"); - goto free_lpr; - } + score_clear(); if (current_play_mode == PLAY_MODE_MOOD) - close_current_mood(); + mood_unload(); else - playlist_close(); - ret = activate_mood_or_playlist(arg, &num_admissible, &errmsg); + playlist_unload(); + ret = activate_mood_or_playlist(arg, &aca->pbout); if (ret >= 0) - goto out; + goto free_lpr; /* ignore subsequent errors (but log them) */ - para_printf(&aca->pbout, "%s\n", errmsg); - free(errmsg); - para_printf(&aca->pbout, "could not activate %s\n", arg); if (current_mop && strcmp(current_mop, arg) != 0) { int ret2; para_printf(&aca->pbout, "switching back to %s\n", current_mop); - ret2 = activate_mood_or_playlist(current_mop, &num_admissible, - &errmsg); + ret2 = activate_mood_or_playlist(current_mop, &aca->pbout); if (ret2 >= 0) - goto out; - para_printf(&aca->pbout, "%s\n", errmsg); - free(errmsg); + goto free_lpr; para_printf(&aca->pbout, "could not reactivate %s: %s\n", current_mop, para_strerror(-ret2)); } - para_printf(&aca->pbout, "activating dummy mood\n"); - activate_mood_or_playlist(NULL, &num_admissible, NULL); -out: - para_printf(&aca->pbout, "activated %s (%d admissible file%s)\n", - current_mop? current_mop : "dummy mood", num_admissible, - num_admissible == 1? "" : "s"); + activate_mood_or_playlist(NULL, &aca->pbout); free_lpr: lls_free_parse_result(aca->lpr, cmd); return ret; @@ -598,12 +574,12 @@ EXPORT_SERVER_CMD_HANDLER(select); static void init_admissible_files(const char *arg) { - int ret = activate_mood_or_playlist(arg, NULL, NULL); + int ret = activate_mood_or_playlist(arg, NULL); if (ret < 0) { PARA_WARNING_LOG("could not activate %s: %s\n", arg, para_strerror(-ret)); if (arg) - activate_mood_or_playlist(NULL, NULL, NULL); + activate_mood_or_playlist(NULL, NULL); } } @@ -631,7 +607,7 @@ static void close_afs_tables(void) int i; PARA_NOTICE_LOG("closing afs tables\n"); for (i = 0; i < NUM_AFS_TABLES; i++) - afs_tables[i].close(); + afs_tables[i].ops->close(); free(database_dir); database_dir = NULL; } @@ -670,7 +646,7 @@ static int open_afs_tables(void) PARA_NOTICE_LOG("opening %zu osl tables in %s\n", NUM_AFS_TABLES, database_dir); for (i = 0; i < NUM_AFS_TABLES; i++) { - ret = afs_tables[i].open(database_dir); + ret = afs_tables[i].ops->open(database_dir); if (ret >= 0) continue; PARA_ERROR_LOG("could not open %s\n", afs_tables[i].name); @@ -679,7 +655,7 @@ static int open_afs_tables(void) if (ret >= 0) return ret; while (i) - afs_tables[--i].close(); + afs_tables[--i].ops->close(); return ret; } @@ -818,7 +794,7 @@ static int call_callback(int fd, int query_shmid) .fd = fd, .band = SBD_OUTPUT }; - ret = cq->handler(&aca); + ret = cq->cb(&aca); ret2 = shm_detach(query_shm); if (ret2 < 0) { if (ret < 0) /* ignore (but log) detach error */ @@ -971,12 +947,10 @@ static int afs_poll(struct pollfd *fds, nfds_t nfds, int timeout) __noreturn void afs_init(int socket_fd) { static struct sched s; - int i, ret; + int ret; register_signal_task(&s); init_list_head(&afs_client_list); - for (i = 0; i < NUM_AFS_TABLES; i++) - afs_tables[i].init(&afs_tables[i]); ret = open_afs_tables(); if (ret < 0) goto out; @@ -998,7 +972,7 @@ __noreturn void afs_init(int socket_fd) } ret = schedule(&s); sched_shutdown(&s); - close_current_mood(); + mood_unload(); out_close: close_afs_tables(); out: @@ -1019,13 +993,13 @@ static int com_init_callback(struct afs_callback_arg *aca) close_afs_tables(); get_database_dir(); for (i = 0; i < NUM_AFS_TABLES; i++) { - struct afs_table *t = &afs_tables[i]; + const struct afs_table *t = afs_tables + i; if (!(table_mask & (1 << i))) continue; - if (!t->create) + if (!t->ops->create) continue; - ret = t->create(database_dir); + ret = t->ops->create(database_dir); if (ret < 0) { para_printf(&aca->pbout, "cannot create table %s\n", t->name); @@ -1057,7 +1031,7 @@ static int com_init(struct command_context *cc, struct lls_parse_result *lpr) table_mask = 0; for (i = 0; i < num_inputs; i++) { for (j = 0; j < NUM_AFS_TABLES; j++) { - struct afs_table *t = &afs_tables[j]; + const struct afs_table *t = afs_tables + j; if (strcmp(lls_input(i, lpr), t->name)) continue; @@ -1131,10 +1105,10 @@ __must_check int afs_event(enum afs_events event, struct para_buffer *pb, int i, ret; for (i = 0; i < NUM_AFS_TABLES; i++) { - struct afs_table *t = &afs_tables[i]; - if (!t->event_handler) + const struct afs_table *t = afs_tables + i; + if (!t->ops->event_handler) continue; - ret = t->event_handler(event, pb, data); + ret = t->ops->event_handler(event, pb, data); if (ret < 0) { PARA_CRIT_LOG("table %s, event %u: %s\n", t->name, event, para_strerror(-ret));