]> git.tue.mpg.de Git - paraslash.git/commitdiff
com_select(): Support '-' to reactivate the previous mood/playlist.
authorAndre Noll <maan@tuebingen.mpg.de>
Mon, 25 Nov 2024 20:55:43 +0000 (21:55 +0100)
committerAndre Noll <maan@tuebingen.mpg.de>
Sun, 5 Jan 2025 17:57:29 +0000 (18:57 +0100)
This adds two global variables to keep track of the previously active
mood or playlist. The select subcommand makes use of this information
if the argument is the special string '-'. The subcommand then follows
common Unix conventions and reactivates the previous mood or playlist.

afs.c
m4/lls/server_cmd.suite.m4

diff --git a/afs.c b/afs.c
index 445d5871097b79cdcd14170c2a1f59998354dc98..ad1ececf2a75a1513b2f47ba06a961d3725c2d43 100644 (file)
--- a/afs.c
+++ b/afs.c
@@ -69,8 +69,8 @@ static int server_socket;
 static struct command_task command_task_struct;
 static struct signal_task *signal_task;
 
-static enum play_mode current_play_mode;
-static char *current_mop; /* mode or playlist specifier. NULL means dummy mood */
+static enum play_mode current_play_mode, previous_play_mode;
+static char *current_mop, *previous_mop; /* NULL means dummy mood */
 
 extern uint32_t afs_socket_cookie;
 
@@ -435,41 +435,56 @@ static int activate_mood_or_playlist(const char *arg, struct para_buffer *pb)
 {
        enum play_mode mode;
        int ret;
-       char *msg;
+       char *errmsg;
 
        if (!arg) { /* load dummy mood */
-               ret = mood_load(NULL, NULL, &msg);
+               ret = mood_load(NULL, NULL, &errmsg);
                mode = PLAY_MODE_MOOD;
+       } else if (!strcmp(arg, "-")) { /* load previous mop */
+               char *mop = previous_mop? previous_mop + 2 : NULL;
+               if (previous_play_mode == PLAY_MODE_MOOD)
+                       ret = mood_load(mop, NULL, &errmsg);
+               else
+                       ret = playlist_load(mop, NULL, &errmsg);
+               mode = previous_play_mode;
        } else if (!strncmp(arg, "p/", 2)) {
-               ret = playlist_load(arg + 2, NULL, &msg);
+               ret = playlist_load(arg + 2, NULL, &errmsg);
                mode = PLAY_MODE_PLAYLIST;
        } else if (!strncmp(arg, "m/", 2)) {
-               ret = mood_load(arg + 2, NULL, &msg);
+               ret = mood_load(arg + 2, NULL, &errmsg);
                mode = PLAY_MODE_MOOD;
        } else {
                ret = -ERRNO_TO_PARA_ERROR(EINVAL);
-               msg = make_message("%s: parse error\n", arg);
+               errmsg = make_message("%s: parse error\n", arg);
        }
        if (pb)
-               para_printf(pb, "%s", msg);
-       free(msg);
+               para_printf(pb, "%s", errmsg);
+       free(errmsg);
        if (ret < 0)
                return ret;
-       current_play_mode = mode;
        /*
         * We get called with arg == current_mop from the signal dispatcher
         * after SIGHUP and from the error path of the select command to
-        * re-select the current mood or playlist. In this case the assignment
-        * to current_mop below would result in a use-after-free condition.
+        * re-select the current mood or playlist. Don't update the four global
+        * mop variables in these cases.
         */
        if (arg != current_mop) {
-               free(current_mop);
-               current_mop = arg? para_strdup(arg) : NULL;
+               previous_play_mode = current_play_mode;
+               current_play_mode = mode;
+               if (arg && !strcmp(arg, "-")) {
+                       char *tmp = current_mop;
+                       current_mop = previous_mop;
+                       previous_mop = tmp;
+               } else {
+                       free(previous_mop);
+                       previous_mop = current_mop;
+                       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));
+       snprintf(mmd->afs_mode_string, sizeof(mmd->afs_mode_string) - 1,
+               "%s", current_mop? current_mop : "dummy");
        mmd->afs_mode_string[sizeof(mmd->afs_mode_string) - 1] = '\0';
        mmd->events++;
        mutex_unlock(mmd_mutex);
@@ -959,6 +974,7 @@ out:
        signal_shutdown(signal_task);
        free_status_items();
        free(current_mop);
+       free(previous_mop);
        free_lpr();
        if (ret < 0)
                PARA_EMERG_LOG("%s\n", para_strerror(-ret));
index d694082beac70f0990f0356d1cc2443ca9c38657..f700339e6b649bba55d5fbd846e9a6fcbb0fc09a 100644 (file)
@@ -418,11 +418,13 @@ m4_include(`com_ll.m4')
 
 [subcommand select]
        purpose = activate a mood or a playlist
-       non-opts-name = specifier/name
+       non-opts-name = mop
        aux_info = AFS_READ | AFS_WRITE
        [description]
-               The specifier is either 'm' or 'p' to indicate whether a playlist or
-               a mood should be activated. Example:
+               The argument is either the special string '-' to load the previous
+               mood or playlist, or of the form specifier/name. In the latter case
+               the specifier part of the argument is either 'm' or 'p' to indicate
+               whether a playlist or a mood should be activated. Example:
 
                        select m/foo