From d894e0cc7ce94d09847a8a35f47127968d4268f1 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Tue, 23 Oct 2007 16:09:01 +0200 Subject: [PATCH] Implement com_select(). --- afs.c | 112 +++++++++++++++++++++++++++++++++++++++++++---------- afs.cmd | 11 ++++++ afs.h | 2 + mood.c | 37 ++++++++---------- playlist.c | 7 +++- server.ggo | 2 +- 6 files changed, 128 insertions(+), 43 deletions(-) diff --git a/afs.c b/afs.c index becff09d..0c7526c7 100644 --- a/afs.c +++ b/afs.c @@ -79,6 +79,7 @@ static int server_socket; static struct command_task command_task_struct; static struct signal_task signal_task_struct; +static enum play_mode current_play_mode; /** * A random number used to "authenticate" the connection. @@ -143,7 +144,7 @@ struct callback_result { * \param result Callback result will be stored here. * * This function creates a shared memory area, copies the buffer pointed to by - * \a buf to that area and notifies the afs process that \a f should be + * query to that area and notifies the afs process that \a f should be * called ASAP. * * \return Negative, on errors, the return value of the callback function @@ -507,32 +508,102 @@ destroy: return ret; } -static enum play_mode init_admissible_files(void) +static char *current_mop; /* mode or playlist specifier. NULL means dummy mooe */ + +/* Never fails if arg == NULL */ +static int activate_mood_or_playlist(char *arg, int *num_admissible) { - int ret = 0; - char *arg = conf.afs_initial_mode_arg; + enum play_mode mode; + int ret; - if (conf.afs_initial_mode_given) { + if (!arg) { + ret = change_current_mood(NULL); /* always successful */ + mode = PLAY_MODE_MOOD; + } else { if (!strncmp(arg, "p:", 2)) { ret = playlist_open(arg + 2); - if (ret >= 0) - return PLAY_MODE_PLAYLIST; - goto dummy; - } - if (!strncmp(arg, "m:", 2)) { + mode = PLAY_MODE_PLAYLIST; + } else if (!strncmp(arg, "m:", 2)) { ret = change_current_mood(arg + 2); - if (ret >= 0) - return PLAY_MODE_MOOD; - goto dummy; - } - PARA_ERROR_LOG("bad afs initial mode arg: %s\n", arg); + mode = PLAY_MODE_MOOD; + } else + ret = -E_AFS_SYNTAX; + if (ret < 0) + return ret; + } + if (num_admissible) + *num_admissible = ret; + current_play_mode = mode; + if (arg != current_mop) { + free(current_mop); + if (arg) + current_mop = para_strdup(arg); + else + current_mop = NULL; } -dummy: + return 1; +} + +static int com_select_callback(const struct osl_object *query, + struct osl_object *result) +{ + struct para_buffer pb = {.buf = NULL}; + char *arg = query->data; + int num_admissible, ret; + + ret = clear_score_table(); if (ret < 0) - PARA_ERROR_LOG("%s\n", PARA_STRERROR(-ret)); + return ret; + if (current_play_mode == PLAY_MODE_MOOD) + close_current_mood(); + else + playlist_close(); + ret = activate_mood_or_playlist(arg, &num_admissible); + if (ret < 0) { + para_printf(&pb, "%s\n", PARA_STRERROR(-ret)); + para_printf(&pb, "switching back to %s\n", current_mop? + current_mop : "dummy"); + ret = activate_mood_or_playlist(current_mop, &num_admissible); + if (ret < 0) { + para_printf(&pb, "failed, switching to dummy\n"); + change_current_mood(NULL); /* always successful */ + } + } + para_printf(&pb, "activated %s (%d admissible files)\n", current_mop? + current_mop : "dummy mood", num_admissible); + result->data = pb.buf; + result->size = pb.size; + return 1; +} + +int com_select(int fd, int argc, char * const * const argv) +{ + int ret; + struct osl_object query, result; + + if (argc != 2) + return -E_AFS_SYNTAX; + query.data = argv[1]; + query.size = strlen(argv[1]) + 1; + ret = send_callback_request(com_select_callback, &query, + &result); + if (ret > 0 && result.data && result.size) { + ret = send_va_buffer(fd, "%s", (char *)result.data); + free(result.data); + } + return ret; +} + +static void init_admissible_files(void) +{ + int ret = 0; + char *arg = conf.afs_initial_mode_arg; + ret = activate_mood_or_playlist(arg, NULL); + if (ret >= 0) + return; + PARA_ERROR_LOG("%s\n", PARA_STRERROR(-ret)); PARA_NOTICE_LOG("defaulting to dummy mood\n"); - change_current_mood(NULL); /* always successful */ - return PLAY_MODE_MOOD; + activate_mood_or_playlist(NULL, NULL); /* always successful */ } static int setup_command_socket_or_die(void) @@ -861,7 +932,6 @@ static void register_tasks(uint32_t cookie) */ __noreturn void afs_init(uint32_t cookie, int socket_fd) { - enum play_mode current_play_mode; struct sched s; int i, ret; @@ -880,7 +950,7 @@ __noreturn void afs_init(uint32_t cookie, int socket_fd) exit(EXIT_FAILURE); PARA_INFO_LOG("server_socket: %d, afs_socket_cookie: %u\n", server_socket, (unsigned) cookie); - current_play_mode = init_admissible_files(); + init_admissible_files(); register_tasks(cookie); s.default_timeout.tv_sec = 0; s.default_timeout.tv_usec = 99 * 1000; diff --git a/afs.cmd b/afs.cmd index efebdc8b..343bdd90 100644 --- a/afs.cmd +++ b/afs.cmd @@ -232,6 +232,17 @@ H: -n Copy the numplayed count. H: H: -v Verbose mode. --- +N: select +P: AFS_READ | AFS_WRITE +D: Activate a mood or a playlist. +U: select : +H: The specifier is either 'm' or 'p' to indicate whether a playlist or +H: a mood should be activated. Example: +H: +H: select m:foo +H: +H: loads the mood named 'foo'. +--- T: add N: add@member@ O: int com_add@member@(int fd, int argc, char * const * const argv); diff --git a/afs.h b/afs.h index 61630726..4d3feb48 100644 --- a/afs.h +++ b/afs.h @@ -168,6 +168,7 @@ int aft_check_callback(const struct osl_object *query, struct osl_object *result /* mood */ int change_current_mood(char *mood_name); +void close_current_mood(void); int reload_current_mood(void); int mood_check_callback(__a_unused const struct osl_object *query, struct osl_object *result); @@ -175,6 +176,7 @@ int mood_check_callback(__a_unused const struct osl_object *query, /* playlist */ int playlist_open(char *name); +void playlist_close(void); int playlist_update_audio_file(struct osl_row *aft_row); int playlist_check_callback(__a_unused const struct osl_object *query, struct osl_object *result); diff --git a/mood.c b/mood.c index fd82ba4a..a89ae85f 100644 --- a/mood.c +++ b/mood.c @@ -912,6 +912,20 @@ static void log_statistics(void) (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(). + */ +void close_current_mood(void) +{ + destroy_mood(current_mood); + current_mood = NULL; + memset(&statistics, 0, sizeof(statistics)); +} + + /** * Change the current mood. * @@ -951,10 +965,10 @@ int change_current_mood(char *mood_name) ret = load_mood(row, &m); if (ret < 0) return ret; - destroy_mood(current_mood); + close_current_mood(); current_mood = m; } else { - destroy_mood(current_mood); + close_current_mood(); current_mood = alloc_new_mood("dummy"); } aa.m = current_mood; @@ -972,25 +986,11 @@ int change_current_mood(char *mood_name) goto out; } PARA_NOTICE_LOG("score add complete\n"); - ret = 1; + ret = statistics.num; out: free(aa.array); return ret; } - -/** - * Close the current mood. - * - * Free all resources of the current mood which were allocated during - * mood_open(). - */ -static void close_current_mood(void) -{ - destroy_mood(current_mood); - current_mood = NULL; - memset(&statistics, 0, sizeof(statistics)); -} - /** * Close and re-open the current mood. * @@ -1015,9 +1015,6 @@ int reload_current_mood(void) if (current_mood->name) mood_name = para_strdup(current_mood->name); close_current_mood(); - ret = clear_score_table(); - if (ret < 0) - return ret; ret = change_current_mood(mood_name); free(mood_name); return ret; diff --git a/playlist.c b/playlist.c index 1c496cae..9afa8128 100644 --- a/playlist.c +++ b/playlist.c @@ -144,6 +144,10 @@ int playlist_check_callback(__a_unused const struct osl_object *query, */ void playlist_close(void) { + int ret; + + if (!current_playlist.name) + return; free(current_playlist.name); current_playlist.name = NULL; } @@ -171,8 +175,9 @@ int playlist_open(char *name) PARA_NOTICE_LOG("failed to load playlist %s\n", name); return ret; } + playlist_close(); ret = load_playlist(row, ¤t_playlist); - return (ret == -E_PLAYLIST_LOADED)? 1 : ret; + return (ret == -E_PLAYLIST_LOADED)? current_playlist.length : ret; } static int search_path(char *path, void *data) diff --git a/server.ggo b/server.ggo index f6ebc172..650dcf0e 100644 --- a/server.ggo +++ b/server.ggo @@ -166,7 +166,7 @@ loaded. Example: --afs_initial_mode p:foo loads the playlist named 'foo'." - string typestr="name" + string typestr="aspecifier>:" optional -- 2.39.2