Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package syncplay for openSUSE:Factory checked in at 2026-09-11 18:04:42 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/syncplay (Old) and /work/SRC/openSUSE:Factory/.syncplay.new.1265 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "syncplay" Fri Sep 11 18:04:42 2026 rev:10 rq:1377346 version:1.7.6 Changes: -------- --- /work/SRC/openSUSE:Factory/syncplay/syncplay.changes 2026-05-25 21:59:14.770993543 +0200 +++ /work/SRC/openSUSE:Factory/.syncplay.new.1265/syncplay.changes 2026-09-11 18:08:00.581606298 +0200 @@ -1,0 +2,24 @@ +Tue Sep 8 11:21:34 UTC 2026 - Luna D Dragon <[email protected]> + +- Update to 1.7.6 + - Fix M3U8 playlist loading by skipping comment and metadata lines + beginning with # + - Restore TLS compatibility with pyOpenSSL 26.2.0 ( + - Improve the invalid TLS certificate error message + - Fix a race condition that could cause deleted persistent rooms + to reappear after the server restarted + - Fix setting other users as ready or not ready in isolated rooms + - Do not offer readiness status controls for room entries + - Initialize latencyCalculation before its conditional assignment + - Fix automatic reconnection after a server timeout, including + cases occurring after a PC wakes from sleep + - Fix the default IPv6 server listen interface + - Support mpv version strings containing a v prefix + - Fix setuptools deprecation warnings for Syncplay resource + packages + - Update the copyright notice to 2026 + - Fix incorrect file ownership in Debian packages by building + them with fakeroot +- drop support-tls-on-pyopenssl-26.2.0.patch (upstream) + +------------------------------------------------------------------- Old: ---- support-tls-on-pyopenssl-26.2.0.patch syncplay-1.7.5.tar.gz New: ---- syncplay-1.7.6.tar.gz ----------(Old B)---------- Old: them with fakeroot - drop support-tls-on-pyopenssl-26.2.0.patch (upstream) ----------(Old E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ syncplay.spec ++++++ --- /var/tmp/diff_new_pack.E5xkNS/_old 2026-09-11 18:08:01.962664073 +0200 +++ /var/tmp/diff_new_pack.E5xkNS/_new 2026-09-11 18:08:01.972664491 +0200 @@ -17,7 +17,7 @@ Name: syncplay -Version: 1.7.5 +Version: 1.7.6 Release: 0 Summary: Client/server to synchronize media playback on mpv/VLC on multiple computers License: Apache-2.0 @@ -25,7 +25,6 @@ Source: https://github.com/Syncplay/syncplay/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz #PATCH-FIX-SUSE switch-env-to-python.patch [email protected] -- Sets interpreter to python3 as opposed to env python3 Patch0: switch-env-to-python.patch -Patch1: support-tls-on-pyopenssl-26.2.0.patch BuildRequires: hicolor-icon-theme BuildRequires: make BuildRequires: python-rpm-generators ++++++ syncplay-1.7.5.tar.gz -> syncplay-1.7.6.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.5/.github/workflows/build.yml new/syncplay-1.7.6/.github/workflows/build.yml --- old/syncplay-1.7.5/.github/workflows/build.yml 2026-02-19 19:20:40.000000000 +0100 +++ new/syncplay-1.7.6/.github/workflows/build.yml 2026-08-03 22:20:45.000000000 +0200 @@ -7,10 +7,10 @@ runs-on: windows-2022 steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v5 - name: Setup Python - uses: actions/setup-python@v2 + uses: actions/setup-python@v6 with: python-version: '3.8' architecture: x86 @@ -48,14 +48,14 @@ run: dir - name: Deploy portable - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: Syncplay_${{ env.VER }}_Portable path: | syncplay_v${{ env.VER }} - name: Deploy installer - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: Syncplay-${{ env.VER }}-Setup.exe path: | @@ -66,7 +66,7 @@ runs-on: macos-15-intel steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v5 - name: Setup Python run: | @@ -131,7 +131,7 @@ ls -al dist_actions - name: Deploy - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: Syncplay_${{ env.VER }}.dmg path: | @@ -142,7 +142,7 @@ runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v5 - name: Build run: ci/deb-script.sh @@ -164,14 +164,14 @@ ls -al dist_actions - name: Deploy full deb - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: syncplay.deb path: | dist_actions/syncplay_*.deb - name: Deploy server deb - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: syncplay-server.deb path: | diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.5/ci/deb-script.sh new/syncplay-1.7.6/ci/deb-script.sh --- old/syncplay-1.7.5/ci/deb-script.sh 2026-02-19 19:20:40.000000000 +0100 +++ new/syncplay-1.7.6/ci/deb-script.sh 2026-08-03 22:20:45.000000000 +0200 @@ -29,6 +29,6 @@ > /tmp/syncplay/DEBIAN/prerm chmod 555 /tmp/syncplay/DEBIAN/prerm -make install DESTDIR=/tmp/syncplay -dpkg -b /tmp/syncplay/ +fakeroot make install DESTDIR=/tmp/syncplay +fakeroot dpkg -b /tmp/syncplay/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.5/ci/deb-server-script.sh new/syncplay-1.7.6/ci/deb-server-script.sh --- old/syncplay-1.7.5/ci/deb-server-script.sh 2026-02-19 19:20:40.000000000 +0100 +++ new/syncplay-1.7.6/ci/deb-server-script.sh 2026-08-03 22:20:45.000000000 +0200 @@ -31,5 +31,5 @@ > /tmp/syncplay-server/DEBIAN/prerm chmod 555 /tmp/syncplay-server/DEBIAN/prerm -make install-server DESTDIR=/tmp/syncplay-server -dpkg -b /tmp/syncplay-server/ +fakeroot make install-server DESTDIR=/tmp/syncplay-server +fakeroot dpkg -b /tmp/syncplay-server/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.5/syncplay/__init__.py new/syncplay-1.7.6/syncplay/__init__.py --- old/syncplay-1.7.5/syncplay/__init__.py 2026-02-19 19:20:40.000000000 +0100 +++ new/syncplay-1.7.6/syncplay/__init__.py 2026-08-03 22:20:45.000000000 +0200 @@ -1,5 +1,5 @@ -version = '1.7.5' +version = '1.7.6' revision = ' stable' milestone = 'Yoitsu' -release_number = '117' +release_number = '119' projectURL = 'https://syncplay.pl/' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.5/syncplay/client.py new/syncplay-1.7.6/syncplay/client.py --- old/syncplay-1.7.5/syncplay/client.py 2026-02-19 19:20:40.000000000 +0100 +++ new/syncplay-1.7.6/syncplay/client.py 2026-08-03 22:20:45.000000000 +0200 @@ -156,6 +156,7 @@ def initProtocol(self, protocol): self._protocol = protocol + self._lastGlobalUpdate = time.time() def destroyProtocol(self): if self._protocol: @@ -188,9 +189,10 @@ def checkIfConnected(self): if self._lastGlobalUpdate and self._protocol and time.time() - self._lastGlobalUpdate > constants.PROTOCOL_TIMEOUT: + protocol = self._protocol self._lastGlobalUpdate = None self.ui.showErrorMessage(getMessage("server-timeout-error")) - self._protocol.drop() + protocol.abort() return False return True @@ -2021,6 +2023,10 @@ with open(path) as f: newPlaylist = f.read().splitlines() + if path.lower().endswith(".m3u8"): + newPlaylist = [ + line for line in newPlaylist if line.strip() and not line.startswith("#") + ] if shuffle: random.shuffle(newPlaylist) if newPlaylist: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.5/syncplay/constants.py new/syncplay-1.7.6/syncplay/constants.py --- old/syncplay-1.7.5/syncplay/constants.py 2026-02-19 19:20:40.000000000 +0100 +++ new/syncplay-1.7.6/syncplay/constants.py 2026-08-03 22:20:45.000000000 +0200 @@ -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.5" # This and higher considered 'recent' clients (no warnings) +RECENT_CLIENT_THRESHOLD = "1.7.6" # 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.5/syncplay/messages_en.py new/syncplay-1.7.6/syncplay/messages_en.py --- old/syncplay-1.7.5/syncplay/messages_en.py 2026-02-19 19:20:40.000000000 +0100 +++ new/syncplay-1.7.6/syncplay/messages_en.py 2026-08-03 22:20:45.000000000 +0200 @@ -362,7 +362,7 @@ "startTLS-initiated": "Attempting secure connection", "startTLS-secure-connection-ok": "Secure connection established ({})", - "startTLS-server-certificate-invalid": 'Secure connection failed. The server uses an invalid security certificate. This communication could be intercepted by a third party. For further details and troubleshooting see <a href="https://syncplay.pl/trouble">here</a>.', + "startTLS-server-certificate-invalid": 'Secure connection failed because Syncplay could not verify the server security certificate. The certificate may be expired, incomplete, or signed by a certificate authority that this client does not trust. The server may need to be updated, or its administrator may need to configure a more widely compatible certificate chain. For further details and troubleshooting see <a href="https://syncplay.pl/trouble">here</a>.', "startTLS-server-certificate-invalid-DNS-ID": "Syncplay does not trust this server because it uses a certificate that is not valid for its hostname.", "startTLS-not-supported-client": "This client does not support TLS", "startTLS-not-supported-server": "This server does not support TLS", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.5/syncplay/players/mpv.py new/syncplay-1.7.6/syncplay/players/mpv.py --- old/syncplay-1.7.5/syncplay/players/mpv.py 2026-02-19 19:20:40.000000000 +0100 +++ new/syncplay-1.7.6/syncplay/players/mpv.py 2026-08-03 22:20:45.000000000 +0200 @@ -17,7 +17,7 @@ from syncplay.vendor.python_mpv_jsonipc.python_mpv_jsonipc import MPV class MpvPlayer(BasePlayer): - RE_VERSION = re.compile(r'.*mpv (\d+)\.(\d+)\.\d+.*') + RE_VERSION = re.compile(r'.*mpv v?(\d+)\.(\d+)\.\d+.*') osdMessageSeparator = "\\n" osdMessageSeparator = "; " # TODO: Make conditional POSITION_QUERY = 'time-pos' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.5/syncplay/protocols.py new/syncplay-1.7.6/syncplay/protocols.py --- old/syncplay-1.7.5/syncplay/protocols.py 2026-02-19 19:20:40.000000000 +0100 +++ new/syncplay-1.7.6/syncplay/protocols.py 2026-08-03 22:20:45.000000000 +0200 @@ -62,6 +62,12 @@ def drop(self): self.transport.loseConnection() + def abort(self): + if hasattr(self.transport, "abortConnection"): + self.transport.abortConnection() + else: + self.drop() + def dropWithError(self, error): raise NotImplementedError() @@ -260,6 +266,7 @@ return position, paused, doSeek, setBy def _handleStatePing(self, state): + latencyCalculation = None if "latencyCalculation" in state["ping"]: latencyCalculation = state["ping"]["latencyCalculation"] if "clientLatencyCalculation" in state["ping"]: @@ -401,9 +408,27 @@ self.sendHello() return - for x in range(0,self._serverCertificateTLS.get_extension_count()): - if (self._serverCertificateTLS.get_extension(x).get_short_name() == b'subjectAltName'): - self._subjectTLS = self._serverCertificateTLS.get_extension(x).__str__().replace("DNS:", "") + self._subjectTLS = "" + try: + from cryptography import x509 + cryptographyCertificate = self._serverCertificateTLS.to_cryptography() + subjectAltName = cryptographyCertificate.extensions.get_extension_for_class(x509.SubjectAlternativeName).value + names = subjectAltName.get_values_for_type(x509.DNSName) + names = names + ["IP Address:{}".format(ipAddress) for ipAddress in subjectAltName.get_values_for_type(x509.IPAddress)] + self._subjectTLS = ", ".join([str(name) for name in names]) + except Exception: + pass + + if not self._subjectTLS: + try: + if hasattr(self._serverCertificateTLS, "get_extension_count") and hasattr(self._serverCertificateTLS, "get_extension"): + for x in range(0,self._serverCertificateTLS.get_extension_count()): + extension = self._serverCertificateTLS.get_extension(x) + if extension.get_short_name() == b'subjectAltName': + self._subjectTLS = str(extension).replace("DNS:", "") + break + except Exception: + pass if not self._subjectTLS: self._subjectTLS = self._client._config.get("host", "") or "" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/syncplay-1.7.5/syncplay/server.py new/syncplay-1.7.6/syncplay/server.py --- old/syncplay-1.7.5/syncplay/server.py 2026-02-19 19:20:40.000000000 +0100 +++ new/syncplay-1.7.6/syncplay/server.py 2026-08-03 22:20:45.000000000 +0200 @@ -221,11 +221,11 @@ for watcherToSet in room.getWatchers(): if watcherToSet.getName() == username: watcherToSet.setReady(isReady) - self._roomManager.broadcastRoom(watcherToSet, lambda w: w.sendSetReady(watcherToSet.getName(), watcherToSet.isReady(), manuallyInitiated, watcher.getName())) + self._roomManager.broadcastRoom(watcher, lambda w: w.sendSetReady(watcherToSet.getName(), watcherToSet.isReady(), manuallyInitiated, watcher.getName())) if isReady: - messageDict = { "message": getMessage("ready-chat-message").format(username, watcherToSet.getName()), "username": watcher.getName()} + messageDict = { "message": getMessage("ready-chat-message").format(username), "username": watcher.getName()} else: - messageDict = {"message": getMessage("not-ready-chat-message").format(username, watcherToSet.getName()), "username": watcher.getName()} + messageDict = {"message": getMessage("not-ready-chat-message").format(username), "username": watcher.getName()} self._roomManager.broadcastRoom(watcher, lambda w: w.sendChatMessage(messageDict, "setOthersReadiness")) else: watcher.setReady(isReady) @@ -489,20 +489,16 @@ if RoomPasswordProvider.isControlledRoom(roomName): room = ControlledRoom(roomName, self._roomsDbHandle) else: - if roomName in self._rooms: - self._deleteRoomIfEmpty(self._rooms[roomName]) room = Room(roomName, self._roomsDbHandle) self._rooms[roomName] = room return room def _deleteRoomIfEmpty(self, room): + if room.isPermanent(): + return + if room.isPersistent() and not room.isPlaylistEmpty(): + return if room.isEmpty() and room.getName(): - if self._roomsDbHandle and room.isPermanent(): - return - if self._roomsDbHandle and room.isNotPermanent(): - if room.isPersistent() and not room.isPlaylistEmpty(): - return - self._roomsDbHandle.deleteRoom(room.getName()) del self._rooms[room.getName()] def findFreeUsername(self, username, maxUsernameLength=constants.MAX_USERNAME_LENGTH): @@ -581,8 +577,11 @@ def writeToDb(self): if not self.isPersistent(): return - processed_playlist = getListAsMultilineString(self._playlist) - self._roomsDbHandle.saveRoom(self._name, processed_playlist, self._playlistIndex, self._position, self._lastSavedUpdate) + if self.isPlaylistEmpty(): + self._roomsDbHandle.deleteRoom(self._name) + else: + processed_playlist = getListAsMultilineString(self._playlist) + self._roomsDbHandle.saveRoom(self._name, processed_playlist, self._playlistIndex, self._position, self._lastSavedUpdate) def loadRoom(self, room): name, playlist, playlistindex, position, lastupdate = room @@ -917,4 +916,4 @@ 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='') + 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.5/syncplay/ui/gui.py new/syncplay-1.7.6/syncplay/ui/gui.py --- old/syncplay-1.7.5/syncplay/ui/gui.py 2026-02-19 19:20:40.000000000 +0100 +++ new/syncplay-1.7.6/syncplay/ui/gui.py 2026-08-03 22:20:45.000000000 +0200 @@ -159,7 +159,7 @@ "<br />Python " + python_version() + " - " + __binding__ + " " + __binding_version__ + " - Qt " + __qt_version__ + "</center></p>") licenseLabel = QtWidgets.QLabel( - "<center><p>Copyright © 2012–2025 Syncplay</p><p>" + + "<center><p>Copyright © 2012–2026 Syncplay</p><p>" + getMessage("about-dialog-license-text") + "</p></center>") aboutIcon = QtGui.QIcon() aboutIcon.addFile(resourcespath + "syncplayAbout.png") @@ -795,6 +795,7 @@ addUsersStreamToPlaylistLabelText = getMessage("addotherusersstreamstoplaylist-menu-label").format(shortUsername) filename = item.sibling(item.row(), 3).data() + isUserRow = item.parent().row() != -1 while item.parent().row() != -1: item = item.parent() roomToJoin = item.sibling(item.row(), 0).data() @@ -824,7 +825,7 @@ if path: menu.addAction(QtGui.QPixmap(resourcespath + "folder_film.png"), getMessage('open-containing-folder'), lambda: utils.open_system_file_browser(path)) - if roomToJoin == self._syncplayClient.getRoom() and self._syncplayClient.userlist.currentUser.canControl() and self._syncplayClient.userlist.isReadinessSupported(requiresOtherUsers=False) and self._syncplayClient.serverFeatures["setOthersReadiness"]: + if isUserRow and roomToJoin == self._syncplayClient.getRoom() and self._syncplayClient.userlist.currentUser.canControl() and self._syncplayClient.userlist.isReadinessSupported(requiresOtherUsers=False) and self._syncplayClient.serverFeatures["setOthersReadiness"]: if self._syncplayClient.userlist.isReady(username): addSetUserAsReadyText = getMessage("setasnotready-menu-label").format(shortUsername) menu.addAction(QtGui.QPixmap(resourcespath + "cross.png"), addSetUserAsReadyText, lambda: self._syncplayClient.setOthersReadiness(username, False))
