From 7e971bf713ae4559645888ac7f91a5b0cdbc67eb Mon Sep 17 00:00:00 2001 From: 0xmoonlight <0xmoonlight@protonmail.com> Date: Sun, 15 Feb 2026 22:15:31 +0200 Subject: [PATCH 1/2] Add /qan and /qans commands for queue-add-next Adds two new playlist commands: - /qan [file/url] - insert after the currently playing item - /qans [file/url] - insert after the currently playing item and select it Closes #702 Co-Authored-By: Claude Opus 4.6 --- syncplay/client.py | 8 ++++++++ syncplay/constants.py | 2 ++ syncplay/messages_en.py | 2 ++ syncplay/ui/consoleUI.py | 11 +++++++++++ 4 files changed, 23 insertions(+) diff --git a/syncplay/client.py b/syncplay/client.py index 92ae5508..07c95f1d 100755 --- a/syncplay/client.py +++ b/syncplay/client.py @@ -2074,6 +2074,14 @@ def changePlaylist(self, files, username=None, resetIndex=False): def addToPlaylist(self, file): self.changePlaylist([*self._playlist, file]) + def addToPlaylistNext(self, file): + if self._playlistIndex is not None: + insert_pos = self._playlistIndex + 1 + new_playlist = self._playlist[:insert_pos] + [file] + self._playlist[insert_pos:] + else: + new_playlist = [file] + self._playlist + self.changePlaylist(new_playlist) + def deleteAtIndex(self, index): new_playlist = self._playlist.copy() if index >= 0 and index < len(new_playlist): diff --git a/syncplay/constants.py b/syncplay/constants.py index 32937f72..9f258859 100755 --- a/syncplay/constants.py +++ b/syncplay/constants.py @@ -128,6 +128,8 @@ def getValueForOS(constantDict): COMMANDS_TOGGLE = ['t', 'toggle'] COMMANDS_QUEUE = ['queue', 'qa', 'add'] COMMANDS_QUEUEANDSELECT = ['queueandselect','qas'] +COMMANDS_QUEUENEXT = ['queuenext', 'qan'] +COMMANDS_QUEUENEXTANDSELECT = ['queuenextandselect', 'qans'] COMMANDS_PLAYLIST = ['playlist', 'ql', 'pl'] COMMANDS_SELECT = ['select', 'qs'] COMMANDS_DELETE = ['delete', 'd', 'qd'] diff --git a/syncplay/messages_en.py b/syncplay/messages_en.py index 263c879b..99cafc46 100644 --- a/syncplay/messages_en.py +++ b/syncplay/messages_en.py @@ -112,6 +112,8 @@ "commandlist-notification/chat": "\tch [message] - send a chat message in a room", "commandList-notification/queue": "\tqa [file/url] - add file or url to bottom of playlist", "commandList-notification/queueandselect": "\tqas [file/url] - add file or url to bottom of playlist and select it", + "commandList-notification/queuenext": "\tqan [file/url] - add file or url after the currently playing item", + "commandList-notification/queuenextandselect": "\tqans [file/url] - add file or url after the currently playing item and select it", "commandList-notification/playlist": "\tql - show the current playlist", "commandList-notification/select": "\tqs [index] - select given entry in the playlist", "commandList-notification/next": "\tqn - select next entry in the playlist", diff --git a/syncplay/ui/consoleUI.py b/syncplay/ui/consoleUI.py index bff0c363..30a84dc6 100755 --- a/syncplay/ui/consoleUI.py +++ b/syncplay/ui/consoleUI.py @@ -198,6 +198,15 @@ def executeCommand(self, data): elif command.group('command') in constants.COMMANDS_QUEUEANDSELECT: self._syncplayClient.playlist.switchToNewPlaylistItem = True self.executeCommand("{} {}".format(constants.COMMANDS_QUEUE[0], command.group('parameter'))) + elif command.group('command') in constants.COMMANDS_QUEUENEXT: + filename = command.group('parameter') + if filename is None: + self.showErrorMessage("No file/url given") + return + self._syncplayClient.playlist.addToPlaylistNext(filename) + elif command.group('command') in constants.COMMANDS_QUEUENEXTANDSELECT: + self._syncplayClient.playlist.switchToNewPlaylistItem = True + self.executeCommand("{} {}".format(constants.COMMANDS_QUEUENEXT[0], command.group('parameter'))) elif command.group('command') in constants.COMMANDS_PLAYLIST: playlist = self._syncplayClient.playlist playlist_elements = ["\t{}: {}".format(i+1, el) for i, el in enumerate(playlist._playlist)] @@ -264,6 +273,8 @@ def executeCommand(self, data): self.showMessage(getMessage("commandlist-notification/chat"), True) self.showMessage(getMessage("commandList-notification/queue"), True) self.showMessage(getMessage("commandList-notification/queueandselect"), True) + self.showMessage(getMessage("commandList-notification/queuenext"), True) + self.showMessage(getMessage("commandList-notification/queuenextandselect"), True) self.showMessage(getMessage("commandList-notification/playlist"), True) self.showMessage(getMessage("commandList-notification/select"), True) self.showMessage(getMessage("commandList-notification/next"), True) From abc3168b8c87bf29632e33163efe7da04527c9d4 Mon Sep 17 00:00:00 2001 From: 0xmoonlight <0xmoonlight@protonmail.com> Date: Wed, 18 Feb 2026 04:28:03 +0200 Subject: [PATCH 2/2] Extract hardcoded "No file/url given" string to messages_en.py Replace hardcoded error strings in queue and queue-next command handlers with getMessage() calls for i18n consistency. Co-Authored-By: Claude Opus 4.6 --- syncplay/messages_en.py | 1 + syncplay/ui/consoleUI.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/syncplay/messages_en.py b/syncplay/messages_en.py index 99cafc46..9c5d4b6a 100644 --- a/syncplay/messages_en.py +++ b/syncplay/messages_en.py @@ -177,6 +177,7 @@ "invalid-seek-value": "Invalid seek value", "invalid-offset-value": "Invalid offset value", + "no-file-or-url-given-error": "No file/url given", "switch-file-not-found-error": "Could not switch to file '{0}'. Syncplay looks in specified media directories.", # File not found "folder-search-timeout-error": "The search for media in media directories was aborted as it took too long to search through '{}' after having processed the first {:,} files. This will occur if you select a folder with too many sub-folders in your list of media folders to search through or if there are too many files to process. For automatic file switching to work again please select File->Set Media Directories in the menu bar and remove this directory or replace it with an appropriate sub-folder. If the folder is actually fine then you can re-enable it by selecting File->Set Media Directories and pressing 'OK'.", # Folder, Files processed. Note: {:,} is {} but with added commas seprators. diff --git a/syncplay/ui/consoleUI.py b/syncplay/ui/consoleUI.py index 30a84dc6..e637acaa 100755 --- a/syncplay/ui/consoleUI.py +++ b/syncplay/ui/consoleUI.py @@ -192,7 +192,7 @@ def executeCommand(self, data): elif command.group('command') in constants.COMMANDS_QUEUE: filename = command.group('parameter') if filename is None: - self.showErrorMessage("No file/url given") + self.showErrorMessage(getMessage("no-file-or-url-given-error")) return self._syncplayClient.ui.addFileToPlaylist(filename) elif command.group('command') in constants.COMMANDS_QUEUEANDSELECT: @@ -201,7 +201,7 @@ def executeCommand(self, data): elif command.group('command') in constants.COMMANDS_QUEUENEXT: filename = command.group('parameter') if filename is None: - self.showErrorMessage("No file/url given") + self.showErrorMessage(getMessage("no-file-or-url-given-error")) return self._syncplayClient.playlist.addToPlaylistNext(filename) elif command.group('command') in constants.COMMANDS_QUEUENEXTANDSELECT: