Reporting version 1.5.0 to mumble-server caused it to expect the newer audio frame format (terminator bit on opus length varint). pymumble 1.6.1 does not implement this, so the server silently dropped every UDPTunnel audio packet. Revert to native 1.2.4 -- audio works, only side effect is a cosmetic ChannelListener warning. Also remove --cprofile from docker-compose command.
74 lines
2.5 KiB
Python
74 lines
2.5 KiB
Python
"""Patch pymumble deps for Python 3.13+ / musl (Alpine).
|
|
|
|
1. pymumble: ssl.wrap_socket was removed in 3.13
|
|
2. opuslib: ctypes.util.find_library fails on musl-based distros
|
|
3. pymumble: close stale socket on reconnect
|
|
"""
|
|
|
|
import pathlib
|
|
import sysconfig
|
|
|
|
site = sysconfig.get_path("purelib")
|
|
|
|
# -- pymumble: replace ssl.wrap_socket with SSLContext --
|
|
p = pathlib.Path(f"{site}/pymumble_py3/mumble.py")
|
|
src = p.read_text()
|
|
|
|
old = """\
|
|
try:
|
|
self.control_socket = ssl.wrap_socket(std_sock, certfile=self.certfile, keyfile=self.keyfile, ssl_version=ssl.PROTOCOL_TLS)
|
|
except AttributeError:
|
|
self.control_socket = ssl.wrap_socket(std_sock, certfile=self.certfile, keyfile=self.keyfile, ssl_version=ssl.PROTOCOL_TLSv1)
|
|
try:"""
|
|
|
|
new = """\
|
|
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
|
|
ctx.check_hostname = False
|
|
ctx.verify_mode = ssl.CERT_NONE
|
|
if self.certfile:
|
|
ctx.load_cert_chain(certfile=self.certfile, keyfile=self.keyfile)
|
|
self.control_socket = ctx.wrap_socket(std_sock, server_hostname=self.host)
|
|
try:"""
|
|
|
|
assert old in src, "pymumble ssl patch target not found"
|
|
p.write_text(src.replace(old, new))
|
|
print("pymumble ssl patch applied")
|
|
|
|
# -- opuslib: find_library fails on musl, use direct CDLL fallback --
|
|
p = pathlib.Path(f"{site}/opuslib/api/__init__.py")
|
|
src = p.read_text()
|
|
|
|
old_opus = "lib_location = find_library('opus')"
|
|
new_opus = "lib_location = find_library('opus') or 'libopus.so.0'"
|
|
|
|
assert old_opus in src, "opuslib find_library patch target not found"
|
|
p.write_text(src.replace(old_opus, new_opus))
|
|
print("opuslib musl patch applied")
|
|
|
|
# -- pymumble: close old socket before reconnecting --
|
|
# init_connection() drops control_socket reference without closing it.
|
|
# The lingering TCP connection causes Murmur to kick the new session
|
|
# with "You connected to the server from another device".
|
|
p = pathlib.Path(f"{site}/pymumble_py3/mumble.py")
|
|
src = p.read_text()
|
|
|
|
old_init = """\
|
|
self.connected = PYMUMBLE_CONN_STATE_NOT_CONNECTED
|
|
self.control_socket = None"""
|
|
|
|
new_init = """\
|
|
self.connected = PYMUMBLE_CONN_STATE_NOT_CONNECTED
|
|
if getattr(self, 'control_socket', None) is not None:
|
|
try:
|
|
self.control_socket.close()
|
|
except Exception:
|
|
pass
|
|
self.control_socket = None"""
|
|
|
|
assert old_init in src, "pymumble init_connection socket patch target not found"
|
|
src = src.replace(old_init, new_init)
|
|
print("pymumble reconnect socket patch applied")
|
|
|
|
p.write_text(src)
|
|
|