Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package syncplay for openSUSE:Factory checked in at 2024-02-05 22:01:54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/syncplay (Old) and /work/SRC/openSUSE:Factory/.syncplay.new.1815 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "syncplay" Mon Feb 5 22:01:54 2024 rev:5 rq:1144195 version:1.7.1 Changes: -------- --- /work/SRC/openSUSE:Factory/syncplay/syncplay.changes 2023-04-17 17:41:35.242322557 +0200 +++ /work/SRC/openSUSE:Factory/.syncplay.new.1815/syncplay.changes 2024-02-05 22:02:06.240973735 +0100 @@ -1,0 +2,22 @@ +Sat Feb 3 16:44:06 UTC 2024 - Alexei Sorokin <sor.ale...@meowr.ru> + +- Update to version 1.7.1: + * Headline changes: + - Adding --interface-ipv4 and --interface-ipv6 command line + switches to server to allow better control over binding to + interfaces. + * Tweaks: + - Re-work readiness notifications for non-operators. + - Show current offset in set offset dialogue. + * Bug fixes and maintenance: + - Fix GUI TypeError. + - Playlist restoration should not undo clearing actions. + - Support player arguments like âno-border in mpv. + - Ensure MPC-HC resets position on playlist change. + - Define desktop filename for Wayland compliance to fix icon. + - Fix offset sub-second precision bug. + - Remove broken setAlignment calls. + - Donât pass empty model to QCompleter. +- Set `BuildArch` to `noarch`. + +------------------------------------------------------------------- Old: ---- syncplay-1.7.0.tar.gz New: ---- syncplay-1.7.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ syncplay.spec ++++++ --- /var/tmp/diff_new_pack.BmNNhv/_old 2024-02-05 22:02:06.900997613 +0100 +++ /var/tmp/diff_new_pack.BmNNhv/_new 2024-02-05 22:02:06.904997757 +0100 @@ -1,7 +1,7 @@ # # spec file for package syncplay # -# Copyright (c) 2023 SUSE LLC +# Copyright (c) 2024 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,7 +17,7 @@ Name: syncplay -Version: 1.7.0 +Version: 1.7.1 Release: 0 Summary: Client/server to synchronize media playback on mpv/VLC on multiple computers License: Apache-2.0 @@ -29,6 +29,7 @@ BuildRequires: make BuildRequires: python-rpm-generators BuildRequires: update-desktop-files +BuildArch: noarch %{?python_enable_dependency_generator} %description ++++++ syncplay-1.7.0.tar.gz -> syncplay-1.7.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.0/.github/workflows/build.yml new/syncplay-1.7.1/.github/workflows/build.yml --- old/syncplay-1.7.0/.github/workflows/build.yml 2023-03-26 23:33:30.000000000 +0200 +++ new/syncplay-1.7.1/.github/workflows/build.yml 2023-11-24 01:30:23.000000000 +0100 @@ -137,40 +137,6 @@ path: | dist_actions/Syncplay_${{ env.VER }}.dmg - appimage: - name: Build AppImage - runs-on: ubuntu-18.04 - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Install dependencies - run: | - sudo apt-get install --no-install-recommends \ - libglib2.0-0 \ - libxkbcommon-x11-0 \ - libxcb1 \ - ; - - - name: Build - run: ci/appimage-script.sh - - - name: Prepare for deployment - run: | - ls -al - export VER="$(cat syncplay/__init__.py | awk '/version/ {gsub("\047", "", $3); print $NF}')" - echo "VER=$VER" >> $GITHUB_ENV - mkdir dist_actions - ci/appimage-deploy.sh - ls -al dist_actions - - - name: Deploy - uses: actions/upload-artifact@v2 - with: - name: Syncplay-${{ env.VER }}-x86_64.AppImage - path: | - dist_actions/Syncplay-${{ env.VER }}-x86_64.AppImage - deb: name: Build Debian package runs-on: ubuntu-20.04 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.0/buildPy2exe.py new/syncplay-1.7.1/buildPy2exe.py --- old/syncplay-1.7.0/buildPy2exe.py 2023-03-26 23:33:30.000000000 +0200 +++ new/syncplay-1.7.1/buildPy2exe.py 2023-11-24 01:30:23.000000000 +0100 @@ -673,9 +673,7 @@ "icon_resources": [(1, "syncplay\\resources\\icon.ico")], 'dest_base': "Syncplay"}, ], - console=['syncplayServer.py'], - # *** If you wish to make the Syncplay client use console mode (for --no-gui to work) then comment out the above two lines and uncomment the following line: - # console=['syncplayServer.py', {"script":"syncplayClient.py", "icon_resources":[(1, "resources\\icon.ico")], 'dest_base': "Syncplay"}], + console=['syncplayServer.py', {"script":"syncplayClient.py", "icon_resources":[(1, "syncplay\\resources\\icon.ico")], 'dest_base': "SyncplayConsole"}], options={ 'py2exe': { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.0/requirements_gui.txt new/syncplay-1.7.1/requirements_gui.txt --- old/syncplay-1.7.0/requirements_gui.txt 2023-03-26 23:33:30.000000000 +0200 +++ new/syncplay-1.7.1/requirements_gui.txt 2023-11-24 01:30:23.000000000 +0100 @@ -1,3 +1,3 @@ -pyside2>=5.11.0; sys_platform != 'darwin' -pyside6; sys_platform == 'darwin' +pyside2>=5.11.0; sys_platform != 'darwin' and (sys_platform == 'win32' or python_version < '3.12') +pyside6; sys_platform == 'darwin' or (sys_platform != 'win32' and python_version >= '3.12') requests>=2.20.0; sys_platform == 'darwin' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.0/syncplay/__init__.py new/syncplay-1.7.1/syncplay/__init__.py --- old/syncplay-1.7.0/syncplay/__init__.py 2023-03-26 23:33:30.000000000 +0200 +++ new/syncplay-1.7.1/syncplay/__init__.py 2023-11-24 01:30:23.000000000 +0100 @@ -1,5 +1,5 @@ -version = '1.7.0' +version = '1.7.1' revision = '' milestone = 'Yoitsu' -release_number = '105' +release_number = '109' projectURL = 'https://syncplay.pl/' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.0/syncplay/client.py new/syncplay-1.7.1/syncplay/client.py --- old/syncplay-1.7.0/syncplay/client.py 2023-03-26 23:33:30.000000000 +0200 +++ new/syncplay-1.7.1/syncplay/client.py 2023-11-24 01:30:23.000000000 +0100 @@ -136,6 +136,7 @@ self._warnings = self._WarningManager(self._player, self.userlist, self.ui, self) self.fileSwitch = FileSwitchManager(self) self.playlist = SyncplayPlaylist(self) + self.playlistMayNeedRestoring = False self._serverSupportsTLS = True @@ -858,6 +859,7 @@ def retry(retries): self._lastGlobalUpdate = None self.ui.setSSLMode(False) + self.playlistMayNeedRestoring = True if retries == 0: self.onDisconnect() if retries > constants.RECONNECT_RETRIES: @@ -1184,12 +1186,12 @@ def checkReadyStates(self): if not self._client: return - if self._client.getPlayerPaused() or not self._userlist.currentUser.isReady(): + if self._client.getPlayerPaused() or not self._userlist.currentUser.isReady() or not self._userlist.areAllRelevantUsersInRoomReady(): self._warnings["not-all-ready"]["displayedFor"] = 0 - if self._userlist.areYouAloneInRoom() or not self._userlist.currentUser.canControl(): + if self._userlist.areYouAloneInRoom(): if self._warnings["not-all-ready"]['timer'].running: self._warnings["not-all-ready"]['timer'].stop() - elif not self._userlist.areAllUsersInRoomReady(): + elif not self._userlist.areAllRelevantUsersInRoomReady(): self._displayReadySameWarning() if constants.SHOW_OSD_WARNINGS and not self._warnings["not-all-ready"]['timer'].running: self._warnings["not-all-ready"]['timer'].start(constants.WARNING_OSD_MESSAGES_LOOP_INTERVAL, True) @@ -1450,9 +1452,28 @@ user = self._users[username] user.setControllerStatus(True) + def areAllRelevantUsersInRoomReady(self, requireSameFilenames=False): + if not self.currentUser.isReady(): + return False + if self.currentUser.canControl(): + return self.areAllUsersInRoomReady(requireSameFilenames) + else: + for user in self._users.values(): + if user.room == self.currentUser.room and user.canControl(): + if user.isReadyWithFile() == False: + return False + elif ( + requireSameFilenames and + ( + self.currentUser.file is None + or user.file is None + or not utils.sameFilename(self.currentUser.file['name'], user.file['name']) + ) + ): + return False + return True + def areAllUsersInRoomReady(self, requireSameFilenames=False): - if not self.currentUser.canControl(): - return True if not self.currentUser.isReady(): return False for user in self._users.values(): @@ -1460,12 +1481,12 @@ if user.isReadyWithFile() == False: return False elif ( - requireSameFilenames and - ( - self.currentUser.file is None - or user.file is None - or not utils.sameFilename(self.currentUser.file['name'], user.file['name']) - ) + requireSameFilenames and + ( + self.currentUser.file is None + or user.file is None + or not utils.sameFilename(self.currentUser.file['name'], user.file['name']) + ) ): return False return True @@ -1935,12 +1956,10 @@ playlistFile.write(playlistToSave) self._ui.showMessage("Playlist saved as {}".format(path)) # TODO: Move to messages_en - - def playlistNeedsRestoring(self, files, username): - return self._client.sharedPlaylistIsEnabled() and self._playlist != None and files == [] and username == None and not self._playlistBufferIsFromOldRoom(self._client.userlist.currentUser.room) - def playlistNeedsRestoring(self, files, username): - return self._client.sharedPlaylistIsEnabled() and len(self._playlist) > 0 and not files and username == None and (self._previousPlaylistRoom == None or self._previousPlaylistRoom == self._client.userlist.currentUser.room) + if self._client.playlistMayNeedRestoring: + self._client.playlistMayNeedRestoring = False + return self._client.sharedPlaylistIsEnabled() and self._playlist != None and files == [] and username == None and not self._playlistBufferIsFromOldRoom(self._client.userlist.currentUser.room) def changePlaylist(self, files, username=None, resetIndex=False): if self.playlistNeedsRestoring(files, username): @@ -1950,6 +1969,7 @@ self._client._protocol.setPlaylistIndex(self._playlistIndex) return self.queuedIndexFilename = None + self._client.playlistMayNeedRestoring = False if self._playlist == files: if self._playlistIndex != 0 and resetIndex: self.changeToPlaylistIndex(0) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.0/syncplay/constants.py new/syncplay-1.7.1/syncplay/constants.py --- old/syncplay-1.7.0/syncplay/constants.py 2023-03-26 23:33:30.000000000 +0200 +++ new/syncplay-1.7.1/syncplay/constants.py 2023-11-24 01:30:23.000000000 +0100 @@ -29,7 +29,7 @@ UI_TIME_FORMAT = "[%X] " CONFIG_NAMES = [".syncplay", "syncplay.ini"] # Syncplay searches first to last DEFAULT_CONFIG_NAME = "syncplay.ini" -RECENT_CLIENT_THRESHOLD = "1.7.0" # This and higher considered 'recent' clients (no warnings) +RECENT_CLIENT_THRESHOLD = "1.7.1" # This and higher considered 'recent' clients (no warnings) MUSIC_FORMATS = [".mp3", ".m4a", ".m4p", ".wav", ".aiff", ".r", ".ogg", ".flac"] # ALL LOWER CASE! WARN_OLD_CLIENTS = True # Use MOTD to inform old clients to upgrade LIST_RELATIVE_CONFIGS = True # Print list of relative configs loaded diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.0/syncplay/ep_server.py new/syncplay-1.7.1/syncplay/ep_server.py --- old/syncplay-1.7.0/syncplay/ep_server.py 2023-03-26 23:33:30.000000000 +0200 +++ new/syncplay-1.7.1/syncplay/ep_server.py 2023-11-24 01:30:23.000000000 +0100 @@ -6,19 +6,26 @@ from syncplay.server import SyncFactory, ConfigurationGetter -class ServerStatus: pass + +class ServerStatus: + listening6 = False + listening4 = False + def isListening6(f): ServerStatus.listening6 = True + def isListening4(f): ServerStatus.listening4 = True + def failed6(f): ServerStatus.listening6 = False print(f.value) print("IPv6 listening failed.") + def failed4(f): ServerStatus.listening4 = False if f.type is CannotListenError and ServerStatus.listening6: @@ -27,9 +34,11 @@ print(f.value) print("IPv4 listening failed.") + def main(): argsGetter = ConfigurationGetter() args = argsGetter.getConfiguration() + factory = SyncFactory( args.port, args.password, @@ -45,15 +54,25 @@ args.stats_db_file, args.tls ) - endpoint6 = TCP6ServerEndpoint(reactor, int(args.port)) - endpoint6.listen(factory).addCallbacks(isListening6, failed6) - endpoint4 = TCP4ServerEndpoint(reactor, int(args.port)) - endpoint4.listen(factory).addCallbacks(isListening4, failed4) + + if args.ipv6_only is True: + endpoint6 = TCP6ServerEndpoint(reactor, int(args.port), interface=args.interface_ipv6) + endpoint6.listen(factory).addCallbacks(isListening6, failed6) + elif args.ipv4_only is True: + endpoint4 = TCP4ServerEndpoint(reactor, int(args.port), interface=args.interface_ipv4) + endpoint4.listen(factory).addCallbacks(isListening4, failed4) + else: + endpoint6 = TCP6ServerEndpoint(reactor, int(args.port), interface=args.interface_ipv6) + endpoint6.listen(factory).addCallbacks(isListening6, failed6) + endpoint4 = TCP4ServerEndpoint(reactor, int(args.port), interface=args.interface_ipv4) + endpoint4.listen(factory).addCallbacks(isListening4, failed4) + if ServerStatus.listening6 or ServerStatus.listening4: reactor.run() else: print("Unable to listen using either IPv4 and IPv6 protocols. Quitting the server now.") sys.exit() + if __name__ == "__main__": - main() \ No newline at end of file + main() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.0/syncplay/messages_de.py new/syncplay-1.7.1/syncplay/messages_de.py --- old/syncplay-1.7.0/syncplay/messages_de.py 2023-03-26 23:33:30.000000000 +0200 +++ new/syncplay-1.7.1/syncplay/messages_de.py 2023-11-24 01:30:23.000000000 +0100 @@ -499,6 +499,10 @@ "server-startTLS-argument": "Erlaube TLS-Verbindungen mit den Zertifikatdateien im Angegebenen Pfad", "server-messed-up-motd-unescaped-placeholders": "Die Nachricht des Tages hat unmaskierte Platzhalter. Alle $-Zeichen sollten verdoppelt werden ($$).", "server-messed-up-motd-too-long": "Die Nachricht des Tages ist zu lang - Maximal {} Zeichen, aktuell {}.", + "server-listen-only-on-ipv4": "Listen only on IPv4 when starting the server.", + "server-listen-only-on-ipv6": "Listen only on IPv6 when starting the server.", + "server-interface-ipv4": "The IP address to bind to for IPv4. Leaving it empty defaults to using all.", + "server-interface-ipv6": "The IP address to bind to for IPv6. Leaving it empty defaults to using all.", # Server errors "unknown-command-server-error": "Unbekannter Befehl {}", # message diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.0/syncplay/messages_en.py new/syncplay-1.7.1/syncplay/messages_en.py --- old/syncplay-1.7.0/syncplay/messages_en.py 2023-03-26 23:33:30.000000000 +0200 +++ new/syncplay-1.7.1/syncplay/messages_en.py 2023-11-24 01:30:23.000000000 +0100 @@ -500,6 +500,10 @@ "server-startTLS-argument": "Enable TLS connections using the certificate files in the path provided", "server-messed-up-motd-unescaped-placeholders": "Message of the Day has unescaped placeholders. All $ signs should be doubled ($$).", "server-messed-up-motd-too-long": "Message of the Day is too long - maximum of {} chars, {} given.", + "server-listen-only-on-ipv4": "Listen only on IPv4 when starting the server.", + "server-listen-only-on-ipv6": "Listen only on IPv6 when starting the server.", + "server-interface-ipv4": "The IP address to bind to for IPv4. Leaving it empty defaults to using all.", + "server-interface-ipv6": "The IP address to bind to for IPv6. Leaving it empty defaults to using all.", # Server errors "unknown-command-server-error": "Unknown command {}", # message diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.0/syncplay/messages_eo.py new/syncplay-1.7.1/syncplay/messages_eo.py --- old/syncplay-1.7.0/syncplay/messages_eo.py 2023-03-26 23:33:30.000000000 +0200 +++ new/syncplay-1.7.1/syncplay/messages_eo.py 2023-11-24 01:30:23.000000000 +0100 @@ -503,6 +503,10 @@ "server-startTLS-argument": "Åalti TLS-konektojn per la atestilaj dosieroj en la donita vojo", "server-messed-up-motd-unescaped-placeholders": "MesaÄo de tago havas neÅirmitajn anstataÅiÄojn. Äiuj dolarsignoj devus aperi duoble ($$).", "server-messed-up-motd-too-long": "MesaÄo de tago estas tro longa â maksimuma kvanto estas {} signoj, sed {} estas donitaj.", + "server-listen-only-on-ipv4": "Listen only on IPv4 when starting the server.", + "server-listen-only-on-ipv6": "Listen only on IPv6 when starting the server.", + "server-interface-ipv4": "The IP address to bind to for IPv4. Leaving it empty defaults to using all.", + "server-interface-ipv6": "The IP address to bind to for IPv6. Leaving it empty defaults to using all.", # Server errors "unknown-command-server-error": "Nekonata ordono {}", # message diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.0/syncplay/messages_es.py new/syncplay-1.7.1/syncplay/messages_es.py --- old/syncplay-1.7.0/syncplay/messages_es.py 2023-03-26 23:33:30.000000000 +0200 +++ new/syncplay-1.7.1/syncplay/messages_es.py 2023-11-24 01:30:23.000000000 +0100 @@ -499,6 +499,10 @@ "server-startTLS-argument": "Habilitar conexiones TLS usando los archivos de certificado en la ruta provista", "server-messed-up-motd-unescaped-placeholders": "El mensaje del dia contiene marcadores de posición sin escapar. Todos los signos $ deberÃan ser dobles ($$).", "server-messed-up-motd-too-long": "El mensaje del dÃa es muy largo - máximo de {} caracteres, se recibieron {}.", + "server-listen-only-on-ipv4": "Listen only on IPv4 when starting the server.", + "server-listen-only-on-ipv6": "Listen only on IPv6 when starting the server.", + "server-interface-ipv4": "The IP address to bind to for IPv4. Leaving it empty defaults to using all.", + "server-interface-ipv6": "The IP address to bind to for IPv6. Leaving it empty defaults to using all.", # Server errors "unknown-command-server-error": "Comando desconocido {}", # message diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.0/syncplay/messages_fr.py new/syncplay-1.7.1/syncplay/messages_fr.py --- old/syncplay-1.7.0/syncplay/messages_fr.py 2023-03-26 23:33:30.000000000 +0200 +++ new/syncplay-1.7.1/syncplay/messages_fr.py 2023-11-24 01:30:23.000000000 +0100 @@ -500,6 +500,10 @@ "server-startTLS-argument": "Activer les connexions TLS à l'aide des fichiers de certificat dans le chemin fourni", "server-messed-up-motd-unescaped-placeholders": "Le message du jour a des espaces réservés non échappés. Tous les signes $ doivent être doublés ($$).", "server-messed-up-motd-too-long": "Le message du jour est trop long: {}caractères maximum, {} donnés.", + "server-listen-only-on-ipv4": "Listen only on IPv4 when starting the server.", + "server-listen-only-on-ipv6": "Listen only on IPv6 when starting the server.", + "server-interface-ipv4": "The IP address to bind to for IPv4. Leaving it empty defaults to using all.", + "server-interface-ipv6": "The IP address to bind to for IPv6. Leaving it empty defaults to using all.", # Server errors "unknown-command-server-error": "Commande inconnue {}", # message diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.0/syncplay/messages_it.py new/syncplay-1.7.1/syncplay/messages_it.py --- old/syncplay-1.7.0/syncplay/messages_it.py 2023-03-26 23:33:30.000000000 +0200 +++ new/syncplay-1.7.1/syncplay/messages_it.py 2023-11-24 01:30:23.000000000 +0100 @@ -499,6 +499,10 @@ "server-startTLS-argument": "Abilita il protocollo TLS usando i certificati contenuti nel percorso indicato", "server-messed-up-motd-unescaped-placeholders": "Il messaggio del giorno ha dei caratteri non 'escaped'. Tutti i simboli $ devono essere doppi ($$).", "server-messed-up-motd-too-long": "Il messaggio del giorno è troppo lungo - numero massimo di caratteri è {}, {} trovati.", + "server-listen-only-on-ipv4": "Listen only on IPv4 when starting the server.", + "server-listen-only-on-ipv6": "Listen only on IPv6 when starting the server.", + "server-interface-ipv4": "The IP address to bind to for IPv4. Leaving it empty defaults to using all.", + "server-interface-ipv6": "The IP address to bind to for IPv6. Leaving it empty defaults to using all.", # Server errors "unknown-command-server-error": "Comando non riconosciuto {}", # message diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.0/syncplay/messages_pt_BR.py new/syncplay-1.7.1/syncplay/messages_pt_BR.py --- old/syncplay-1.7.0/syncplay/messages_pt_BR.py 2023-03-26 23:33:30.000000000 +0200 +++ new/syncplay-1.7.1/syncplay/messages_pt_BR.py 2023-11-24 01:30:23.000000000 +0100 @@ -500,6 +500,10 @@ "server-startTLS-argument": "Habilita conexões TLS usando os arquivos de certificado no caminho fornecido", "server-messed-up-motd-unescaped-placeholders": "A Mensagem do Dia possui placeholders não escapados. Todos os sinais de $ devem ser dobrados (como em $$).", "server-messed-up-motd-too-long": "A Mensagem do Dia é muito longa - máximo de {} caracteres, {} foram dados.", + "server-listen-only-on-ipv4": "Listen only on IPv4 when starting the server.", + "server-listen-only-on-ipv6": "Listen only on IPv6 when starting the server.", + "server-interface-ipv4": "The IP address to bind to for IPv4. Leaving it empty defaults to using all.", + "server-interface-ipv6": "The IP address to bind to for IPv6. Leaving it empty defaults to using all.", # Server errors "unknown-command-server-error": "Comando desconhecido: {}", # message diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.0/syncplay/messages_pt_PT.py new/syncplay-1.7.1/syncplay/messages_pt_PT.py --- old/syncplay-1.7.0/syncplay/messages_pt_PT.py 2023-03-26 23:33:30.000000000 +0200 +++ new/syncplay-1.7.1/syncplay/messages_pt_PT.py 2023-11-24 01:30:23.000000000 +0100 @@ -499,6 +499,10 @@ "server-startTLS-argument": "Habilita conexões TLS usando os arquivos de certificado no caminho fornecido", "server-messed-up-motd-unescaped-placeholders": "A Mensagem do Dia possui placeholders não escapados. Todos os sinais de $ devem ser dobrados (como em $$).", "server-messed-up-motd-too-long": "A Mensagem do Dia é muito longa - máximo de {} caracteres, {} foram dados.", + "server-listen-only-on-ipv4": "Listen only on IPv4 when starting the server.", + "server-listen-only-on-ipv6": "Listen only on IPv6 when starting the server.", + "server-interface-ipv4": "The IP address to bind to for IPv4. Leaving it empty defaults to using all.", + "server-interface-ipv6": "The IP address to bind to for IPv6. Leaving it empty defaults to using all.", # Server errors "unknown-command-server-error": "Comando desconhecido: {}", # message diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.0/syncplay/messages_ru.py new/syncplay-1.7.1/syncplay/messages_ru.py --- old/syncplay-1.7.0/syncplay/messages_ru.py 2023-03-26 23:33:30.000000000 +0200 +++ new/syncplay-1.7.1/syncplay/messages_ru.py 2023-11-24 01:30:23.000000000 +0100 @@ -496,6 +496,10 @@ "server-startTLS-argument": "ÐклÑÑиÑÑ TLS-ÑÐ¾ÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ð¸ÑполÑзÑÑ ÑÐ°Ð¹Ð»Ñ ÑеÑÑиÑикаÑов в Ñказанном пÑÑи", "server-messed-up-motd-unescaped-placeholders": "MOTD-ÑообÑение ÑодеÑÐ¶Ð¸Ñ Ð½ÐµÑкÑаниÑованнÑе ÑпеÑÑимволÑ. ÐÑе знаки $ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð±ÑÑÑ Ð¿ÑодÑблиÑÐ¾Ð²Ð°Ð½Ñ ($$).", "server-messed-up-motd-too-long": "MOTD-ÑообÑение ÑлиÑком длинное: макÑималÑÐ½Ð°Ñ Ð´Ð»Ð¸Ð½Ð° - {} Ñимвол(ов), ÑекÑÑÐ°Ñ Ð´Ð»Ð¸Ð½Ð° - {} Ñимвол(ов).", + "server-listen-only-on-ipv4": "Listen only on IPv4 when starting the server.", + "server-listen-only-on-ipv6": "Listen only on IPv6 when starting the server.", + "server-interface-ipv4": "The IP address to bind to for IPv4. Leaving it empty defaults to using all.", + "server-interface-ipv6": "The IP address to bind to for IPv6. Leaving it empty defaults to using all.", # Server errors "unknown-command-server-error": "ÐеизвеÑÑÐ½Ð°Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð°: {}", # message diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.0/syncplay/messages_tr.py new/syncplay-1.7.1/syncplay/messages_tr.py --- old/syncplay-1.7.0/syncplay/messages_tr.py 2023-03-26 23:33:30.000000000 +0200 +++ new/syncplay-1.7.1/syncplay/messages_tr.py 2023-11-24 01:30:23.000000000 +0100 @@ -500,6 +500,10 @@ "server-startTLS-argument": "Dosya yolundaki sertifika dosyalarını kullanarak TLS baÄlantılarını etkinleÅtirin", "server-messed-up-motd-unescaped-placeholders": "Günün Mesajında çıkıŠkaraktersiz yer tutucular var. Tüm $ iÅaretleri iki katına çıkarılmalıdır ($$).", "server-messed-up-motd-too-long": "Günün Mesajı çok uzun - maksimum {} karakter olmalı, {} verildi.", + "server-listen-only-on-ipv4": "Listen only on IPv4 when starting the server.", + "server-listen-only-on-ipv6": "Listen only on IPv6 when starting the server.", + "server-interface-ipv4": "The IP address to bind to for IPv4. Leaving it empty defaults to using all.", + "server-interface-ipv6": "The IP address to bind to for IPv6. Leaving it empty defaults to using all.", # Server errors "unknown-command-server-error": "Bilinmeyen komut {}", # message diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.0/syncplay/messages_zh_CN.py new/syncplay-1.7.1/syncplay/messages_zh_CN.py --- old/syncplay-1.7.0/syncplay/messages_zh_CN.py 2023-03-26 23:33:30.000000000 +0200 +++ new/syncplay-1.7.1/syncplay/messages_zh_CN.py 2023-11-24 01:30:23.000000000 +0100 @@ -500,6 +500,10 @@ "server-startTLS-argument": "ä½¿ç¨æä¾çè·¯å¾ä¸çè¯ä¹¦æä»¶å¯ç¨TLSè¿æ¥", "server-messed-up-motd-unescaped-placeholders": "æ¯æ¥ä¿¡æ¯ä¸ææªè½¬ä¹çå ä½ç¬¦ãææ $ å符åºå½éå¤ä¸¤é ($$).", "server-messed-up-motd-too-long": "æ¯æ¥ä¿¡æ¯è¿é¿ - æå¤§{}个chars, ç»åºçé¿åº¦{}", + "server-listen-only-on-ipv4": "Listen only on IPv4 when starting the server.", + "server-listen-only-on-ipv6": "Listen only on IPv6 when starting the server.", + "server-interface-ipv4": "The IP address to bind to for IPv4. Leaving it empty defaults to using all.", + "server-interface-ipv6": "The IP address to bind to for IPv6. Leaving it empty defaults to using all.", # Server errors "unknown-command-server-error": "æªç¥å½ä»¤ {}", # message diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.0/syncplay/players/mpc.py new/syncplay-1.7.1/syncplay/players/mpc.py --- old/syncplay-1.7.0/syncplay/players/mpc.py 2023-03-26 23:33:30.000000000 +0200 +++ new/syncplay-1.7.1/syncplay/players/mpc.py 2023-11-24 01:30:23.000000000 +0100 @@ -407,7 +407,7 @@ def openFile(self, filePath, resetPosition=False): self._mpcApi.openFile(filePath) if resetPosition: - self.setPosition(0) + self.setPosition(0, resetPosition=True) def displayMessage( self, message, @@ -429,9 +429,11 @@ pass @retry(MpcHcApi.PlayerNotReadyException, constants.MPC_MAX_RETRIES, constants.MPC_RETRY_WAIT_TIME, 1) - def setPosition(self, value): + def setPosition(self, value, resetPosition=False): if self._mpcApi.filePlaying: self._mpcApi.seek(value) + elif resetPosition: + raise MpcHcApi.PlayerNotReadyException() def __getPosition(self): self.__positionUpdate.clear() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.0/syncplay/players/mpv.py new/syncplay-1.7.1/syncplay/players/mpv.py --- old/syncplay-1.7.0/syncplay/players/mpv.py 2023-03-26 23:33:30.000000000 +0200 +++ new/syncplay-1.7.1/syncplay/players/mpv.py 2023-11-24 01:30:23.000000000 +0100 @@ -69,7 +69,7 @@ argValue = argValue[1:-1] else: argName = argToAdd - argValue = "yes" + argValue = "" args[argName] = argValue return args diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.0/syncplay/server.py new/syncplay-1.7.1/syncplay/server.py --- old/syncplay-1.7.0/syncplay/server.py 2023-03-26 23:33:30.000000000 +0200 +++ new/syncplay-1.7.1/syncplay/server.py 2023-11-24 01:30:23.000000000 +0100 @@ -2,9 +2,7 @@ import codecs import hashlib import os -import random import time -import json from string import Template from twisted.enterprise import adbapi @@ -292,18 +290,18 @@ def __init__(self, dbHandle, roomManager): self._dbHandle = dbHandle self._roomManagerHandle = roomManager - + def startRecorder(self, delay): try: self._dbHandle.connect() reactor.callLater(delay, self._scheduleClientSnapshot) except: print("--- Error in initializing the stats database. Server Stats not enabled. ---") - + def _scheduleClientSnapshot(self): self._clientSnapshotTimer = task.LoopingCall(self._runClientSnapshot) - self._clientSnapshotTimer.start(constants.SERVER_STATS_SNAPSHOT_INTERVAL) - + self._clientSnapshotTimer.start(constants.SERVER_STATS_SNAPSHOT_INTERVAL) + def _runClientSnapshot(self): try: snapshotTime = int(time.time()) @@ -499,7 +497,7 @@ while username.lower() in allnames: username += '_' return username - + def exportRooms(self): return self._rooms @@ -891,3 +889,7 @@ self._argparser.add_argument('--max-username-length', metavar='maxUsernameLength', type=int, nargs='?', help=getMessage("server-maxusernamelength-argument").format(constants.MAX_USERNAME_LENGTH)) self._argparser.add_argument('--stats-db-file', metavar='file', type=str, nargs='?', help=getMessage("server-stats-db-file-argument")) self._argparser.add_argument('--tls', metavar='path', type=str, nargs='?', help=getMessage("server-startTLS-argument")) + self._argparser.add_argument('--ipv4-only', action='store_true', help=getMessage("server-listen-only-on-ipv4")) + self._argparser.add_argument('--ipv6-only', action='store_true', help=getMessage("server-listen-only-on-ipv6")) + self._argparser.add_argument('--interface-ipv4', metavar='interfaceIPv4', type=str, nargs='?', help=getMessage("server-interface-ipv4"), default='') + self._argparser.add_argument('--interface-ipv6', metavar='interfaceIPv6', type=str, nargs='?', help=getMessage("server-interface-ipv6"), default='') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.0/syncplay/ui/ConfigurationGetter.py new/syncplay-1.7.1/syncplay/ui/ConfigurationGetter.py --- old/syncplay-1.7.0/syncplay/ui/ConfigurationGetter.py 2023-03-26 23:33:30.000000000 +0200 +++ new/syncplay-1.7.1/syncplay/ui/ConfigurationGetter.py 2023-11-24 01:30:23.000000000 +0100 @@ -5,7 +5,7 @@ import re import os import sys -from configparser import SafeConfigParser, DEFAULTSECT +from configparser import ConfigParser, DEFAULTSECT from syncplay import constants, utils, version, milestone from syncplay.messages import getMessage, setLanguage, isValidLanguage @@ -389,7 +389,7 @@ open(iniPath, 'w').close() else: return - parser.readfp(codecs.open(iniPath, "r", "utf_8_sig")) + parser.read_file(codecs.open(iniPath, "r", "utf_8_sig")) for section, options in list(self._iniStructure.items()): if parser.has_section(section): for option in options: @@ -408,10 +408,12 @@ sys.exit() def _promptForMissingArguments(self, error=None): - if self._config['noGui']: + if self._config['noGui'] or utils.isWindowsConsole(): if error: print("{}!".format(error)) print(getMessage("missing-arguments-error")) + if utils.isWindowsConsole(): + input(getMessage("enter-to-exit-prompt")) sys.exit() else: from syncplay.ui.GuiConfiguration import GuiConfiguration @@ -432,7 +434,7 @@ if self._config['noStore']: return parser = SafeConfigParserUnicode(strict=False) - parser.readfp(codecs.open(iniPath, "r", "utf_8_sig")) + parser.read_file(codecs.open(iniPath, "r", "utf_8_sig")) for section, options in list(self._iniStructure.items()): if not parser.has_section(section): parser.add_section(section) @@ -521,6 +523,7 @@ raise ImportError if QCoreApplication.instance() is None: self.app = QtWidgets.QApplication(sys.argv) + self.app.setDesktopFileName("syncplay") if isWindows(): try: from syncplay.vendor import darkdetect @@ -549,7 +552,7 @@ # Arguments not validated yet - booleans are still text values if self._config['language']: setLanguage(self._config['language']) - if (self._config['forceGuiPrompt'] == "True" or not self._config['file']) and not self._config['noGui']: + if (self._config['forceGuiPrompt'] == "True" or not self._config['file']) and not self._config['noGui'] and not utils.isWindowsConsole(): self._forceGuiPrompt() self._checkConfig() self._saveConfig(iniPath) @@ -592,7 +595,7 @@ self._config = backup -class SafeConfigParserUnicode(SafeConfigParser): +class SafeConfigParserUnicode(ConfigParser): def write(self, fp): """Write an .ini-format representation of the configuration state.""" if self._defaults: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.0/syncplay/ui/GuiConfiguration.py new/syncplay-1.7.1/syncplay/ui/GuiConfiguration.py --- old/syncplay-1.7.0/syncplay/ui/GuiConfiguration.py 2023-03-26 23:33:30.000000000 +0200 +++ new/syncplay-1.7.1/syncplay/ui/GuiConfiguration.py 2023-11-24 01:30:23.000000000 +0100 @@ -660,7 +660,7 @@ self.serverpassLabel = QLabel(getMessage("password-label"), self) self.roomsCombobox = QtWidgets.QComboBox(self) self.roomsCombobox.setEditable(True) - caseSensitiveCompleter = QtWidgets.QCompleter("", self) + caseSensitiveCompleter = QtWidgets.QCompleter(self) caseSensitiveCompleter.setCaseSensitivity(Qt.CaseSensitive) self.roomsCombobox.setCompleter(caseSensitiveCompleter) self.fillRoomsCombobox() @@ -1194,7 +1194,6 @@ self.displaySettingsGroup = QtWidgets.QGroupBox(getMessage("messages-other-title")) self.displaySettingsLayout = QtWidgets.QVBoxLayout() - self.displaySettingsLayout.setAlignment(Qt.AlignTop & Qt.AlignLeft) self.displaySettingsFrame = QtWidgets.QFrame() self.showDurationNotificationCheckbox = QCheckBox(getMessage("showdurationnotification-label")) @@ -1206,7 +1205,6 @@ self.languageLayout.setContentsMargins(0, 0, 0, 0) self.languageFrame.setLayout(self.languageLayout) self.languageFrame.setSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum) - self.languageLayout.setAlignment(Qt.AlignTop & Qt.AlignLeft) self.languageLabel = QLabel(getMessage("language-label"), self) self.languageCombobox = QtWidgets.QComboBox(self) self.languageCombobox.addItem(getMessage("automatic-language").format(getMessage("LANGUAGE", getInitialLanguage()))) @@ -1227,7 +1225,6 @@ self.displaySettingsGroup.setLayout(self.displaySettingsLayout) self.displaySettingsGroup.setMaximumHeight(self.displaySettingsGroup.minimumSizeHint().height()) - self.displaySettingsLayout.setAlignment(Qt.AlignTop & Qt.AlignLeft) self.messageLayout.addWidget(self.displaySettingsGroup) # messageFrame diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.0/syncplay/ui/__init__.py new/syncplay-1.7.1/syncplay/ui/__init__.py --- old/syncplay-1.7.0/syncplay/ui/__init__.py 2023-03-26 23:33:30.000000000 +0200 +++ new/syncplay-1.7.1/syncplay/ui/__init__.py 2023-11-24 01:30:23.000000000 +0100 @@ -1,19 +1,21 @@ import os +from syncplay.utils import isWindowsConsole if "QT_PREFERRED_BINDING" not in os.environ: os.environ["QT_PREFERRED_BINDING"] = os.pathsep.join( ["PySide6", "PySide2", "PySide", "PyQt5", "PyQt4"] ) -try: - from syncplay.ui.gui import MainWindow as GraphicalUI -except ImportError: - pass +if not isWindowsConsole(): + try: + from syncplay.ui.gui import MainWindow as GraphicalUI + except ImportError: + pass from syncplay.ui.consoleUI import ConsoleUI def getUi(graphical=True, passedBar=None): - if graphical: + if graphical and not isWindowsConsole(): ui = GraphicalUI(passedBar=passedBar) else: ui = ConsoleUI() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.0/syncplay/ui/gui.py new/syncplay-1.7.1/syncplay/ui/gui.py --- old/syncplay-1.7.0/syncplay/ui/gui.py 2023-03-26 23:33:30.000000000 +0200 +++ new/syncplay-1.7.1/syncplay/ui/gui.py 2023-11-24 01:30:23.000000000 +0100 @@ -1355,9 +1355,10 @@ @needsClient def setOffset(self): + oldoffset = str(self._syncplayClient.getUserOffset()) newoffset, ok = QtWidgets.QInputDialog.getText( self, getMessage("setoffset-msgbox-label"), - getMessage("offsetinfo-msgbox-label"), QtWidgets.QLineEdit.Normal, "") + getMessage("offsetinfo-msgbox-label"), QtWidgets.QLineEdit.Normal, oldoffset) if ok and newoffset != '': o = re.match(constants.UI_OFFSET_REGEX, "o " + newoffset) if o: @@ -1513,7 +1514,7 @@ window.listLayout.addWidget(window.listSplit) window.roomsCombobox = QtWidgets.QComboBox(self) window.roomsCombobox.setEditable(True) - caseSensitiveCompleter = QtWidgets.QCompleter("", self) + caseSensitiveCompleter = QtWidgets.QCompleter(self) caseSensitiveCompleter.setCaseSensitivity(Qt.CaseSensitive) window.roomsCombobox.setCompleter(caseSensitiveCompleter) #window.roomsCombobox.setMaxLength(constants.MAX_ROOM_NAME_LENGTH) @@ -2106,7 +2107,10 @@ if isMacOS(): self.setWindowFlags(self.windowFlags()) else: - self.setWindowFlags(self.windowFlags() & Qt.AA_DontUseNativeMenuBar) + try: + self.setWindowFlags(self.windowFlags() & Qt.AA_DontUseNativeMenuBar) + except TypeError: + self.setWindowFlags(self.windowFlags()) self.setWindowTitle("Syncplay v" + version + revision) self.mainLayout = QtWidgets.QVBoxLayout() self.addTopLayout(self) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.0/syncplay/utils.py new/syncplay-1.7.1/syncplay/utils.py --- old/syncplay-1.7.0/syncplay/utils.py 2023-03-26 23:33:30.000000000 +0200 +++ new/syncplay-1.7.1/syncplay/utils.py 2023-11-24 01:30:23.000000000 +0100 @@ -12,7 +12,6 @@ import sys import time import traceback -import unicodedata import urllib.error import urllib.parse import urllib.request @@ -38,6 +37,8 @@ def isBSD(): return constants.OS_BSD in sys.platform or sys.platform.startswith(constants.OS_DRAGONFLY) +def isWindowsConsole(): + return os.path.basename(sys.executable) == "SyncplayConsole.exe" def retry(ExceptionToCheck, tries=4, delay=3, backoff=2, logger=None): """Retry calling the decorated function using an exponential backoff. @@ -82,6 +83,8 @@ def parseTime(timeStr): + if ":" not in timeStr: + return float(timeStr) regex = re.compile(constants.PARSE_TIME_REGEX) parts = regex.match(timeStr) if not parts: @@ -226,6 +229,28 @@ sys.stdout = Blackhole() del Blackhole + elif isWindowsConsole(): + class Blackhole(object): + softspace = 0 + + def write(self, text): + pass + + def flush(self): + pass + + class Stderr(object): + softspace = 0 + _file = None + _error = None + + def flush(self): + if self._file is not None: + self._file.flush() + + sys.stderr = Blackhole() + del Blackhole + def truncateText(unicodeText, maxLength): try: