]> git.tuebingen.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>
Sat, 19 Apr 2025 14:16:48 +0000 (16:16 +0200)
This adds two static global variables to afs.c which track the
previously active mood or playlist. The select subcommand now 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..4951af7521b8eed9424f812348e76a31cd1067a2 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;
 
@@ -440,6 +440,13 @@ static int activate_mood_or_playlist(const char *arg, struct para_buffer *pb)
        if (!arg) { /* load dummy mood */
                ret = mood_load(NULL, NULL, &msg);
                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, &msg);
+               else
+                       ret = playlist_load(mop, NULL, &msg);
+               mode = previous_play_mode;
        } else if (!strncmp(arg, "p/", 2)) {
                ret = playlist_load(arg + 2, NULL, &msg);
                mode = PLAY_MODE_PLAYLIST;
@@ -455,21 +462,29 @@ static int activate_mood_or_playlist(const char *arg, struct para_buffer *pb)
        free(msg);
        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