remove network sync, only single player

This commit is contained in:
j 2026-01-28 18:16:19 +01:00
commit 75ad983d47

View file

@ -3,7 +3,6 @@ import argparse
import collections import collections
import json import json
import os import os
import socket
import time import time
from threading import Thread from threading import Thread
from datetime import datetime from datetime import datetime
@ -58,10 +57,7 @@ class Sync(Thread):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.is_main = kwargs.get('mode', 'main') == 'main' self.is_main = kwargs.get('mode', 'main') == 'main'
self.start_at_hour = kwargs.get("hour", False) self.start_at_hour = kwargs.get("hour", False)
self.sock = self.init_socket()
self.main = Main() self.main = Main()
if self.is_main:
self.socket_enable_broadcast()
if kwargs.get("music"): if kwargs.get("music"):
music = mpv.MPV( music = mpv.MPV(
@ -104,12 +100,7 @@ class Sync(Thread):
logger.error("loaded paylist: %s", self.playlist) logger.error("loaded paylist: %s", self.playlist)
logger.debug("current playlist: %s", json.dumps(self.mpv.playlist, indent=2)) logger.debug("current playlist: %s", json.dumps(self.mpv.playlist, indent=2))
self.deviations = collections.deque(maxlen=10) self.deviations = collections.deque(maxlen=10)
if not self.is_main: if self.start_at_hour:
self.mpv.pause = False
time.sleep(0.1)
self.mpv.pause = True
self.sync_to_main()
elif self.start_at_hour:
self.mpv.pause = True self.mpv.pause = True
fmt = '%Y-%m-%d %H' fmt = '%Y-%m-%d %H'
now = datetime.now() now = datetime.now()
@ -140,15 +131,7 @@ class Sync(Thread):
def run(self): def run(self):
while self.active: while self.active:
if self.is_main: time.sleep(0.5)
time.sleep(0.5)
else:
if self.need_to_sync:
self.sync_to_main()
self.deviations = collections.deque(maxlen=10)
self.need_to_sync = False
else:
self.read_position_main()
self.reload_playlist() self.reload_playlist()
if not self.is_paused and self._tick and abs(time.time() - self._tick) > 60: if not self.is_paused and self._tick and abs(time.time() - self._tick) > 60:
logger.error("player is stuck") logger.error("player is stuck")
@ -161,7 +144,6 @@ class Sync(Thread):
return True return True
return False return False
def q_binding(self, *args): def q_binding(self, *args):
if self.is_keydown(args): if self.is_keydown(args):
self.stop() self.stop()
@ -193,25 +175,9 @@ class Sync(Thread):
def stop(self, *args): def stop(self, *args):
self.active = False self.active = False
if self.sock:
self.sock.close()
self.sock = None
def time_pos_cb(self, pos, *args, **kwargs): def time_pos_cb(self, pos, *args, **kwargs):
self._tick = time.time() self._tick = time.time()
if self.is_main:
self.send_position_local()
elif self.ready:
self.adjust_position()
if self._pos != self.mpv.playlist_current_pos:
self._pos = self.mpv.playlist_current_pos
self.deviations = collections.deque(maxlen=10)
self.need_to_sync = False
try:
track = self.mpv.playlist[self._pos]
logger.error("%s %s", datetime.now(), track["filename"])
except:
pass
def reload_playlist(self): def reload_playlist(self):
if not self.reload_check: if not self.reload_check:
@ -249,155 +215,6 @@ class Sync(Thread):
logger.error("reloaded paylist: %s", self.playlist) logger.error("reloaded paylist: %s", self.playlist)
logger.debug("current playlist: %s", json.dumps(self.mpv.playlist, indent=2)) logger.debug("current playlist: %s", json.dumps(self.mpv.playlist, indent=2))
def init_socket(self):
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(("0.0.0.0", PORT))
return sock
#
# main specific
#
def socket_enable_broadcast(self):
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
self.sock.connect((self.destination, PORT))
def send_position_local(self):
if not self.active:
return
try:
msg = (
"%0.4f %s"
% (self.mpv.time_pos, self.mpv.playlist_current_pos)
).encode()
if CONFIG.get("sync_group"):
msg = ("%s " % CONFIG["sync_group"]).encode() + msg
except:
return
try:
self.sock.send(msg)
except socket.error as e:
logger.error("send failed: %s", e)
def send_playback_state(self):
state = 'pause' if self.mpv.pause else 'play'
msg = ("%s -1" % state).encode()
try:
self.sock.send(msg)
except socket.error as e:
logger.error("send failed: %s", e)
#
# follower specific
#
_last_ping = None
def read_position_main(self):
self.sock.settimeout(5)
while True:
try:
data = self.sock.recvfrom(1024)[0].decode().split(" ", 1)
except socket.timeout:
if self._last_ping != "pause":
logger.error("failed to receive data from main")
return
except OSError:
logger.error("socket closed")
return
if CONFIG.get("sync_group"):
if data[0] == str(CONFIG["sync_group"]):
data = data[1].split(" ", 1)
break
else:
break
self._last_ping = data[0]
if data[0] == "pause":
self.is_paused = True
self.mpv.pause = True
elif data[0] == "play":
self.is_paused = False
self._tick = 0
self.mpv.pause = False
else:
self.main.time_pos = float(data[0])
self.main.playlist_current_pos = int(data[1])
def adjust_position(self):
if self.mpv.time_pos is not None:
try:
deviation = self.main.time_pos - self.mpv.time_pos
except:
return
self.deviations.append(deviation)
median_deviation = self.median(list(self.deviations))
frames = deviation / 0.04
median_frames = median_deviation / 0.04
if abs(deviation) <= 0.04 and self.mpv.speed != 1.0:
self.mpv.speed = 1.0
logger.error(
'%0.05f back to normal speed %0.05f (%d) median %0.05f (%d) -> %s' % (self.mpv.time_pos, deviation, frames, median_deviation, median_frames, self.mpv.speed)
)
if time.time() - self.last_sync > SYNC_GRACE_TIME and abs(median_deviation) > SYNC_TOLERANCE:
if abs(median_deviation) < 1:
step = 0.02
if median_deviation > 0:
self.mpv.speed += step
else:
self.mpv.speed -= step
logger.error(
'%0.05f need to adjust speed %0.05f (%d) median %0.05f (%d) -> %s' % (self.mpv.time_pos, deviation, frames, median_deviation, median_frames, self.mpv.speed)
)
self.need_to_sync = False
self.deviations = collections.deque(maxlen=10)
self.last_sync = time.time()
elif self.mpv.time_pos > 2 and not self.need_to_sync:
logger.error(
'%0.05f need to sync %0.05f (%d) median %0.05f (%d)' % (self.mpv.time_pos, deviation, frames, median_deviation, median_frames)
)
self.need_to_sync = True
def median(self, lst):
quotient, remainder = divmod(len(lst), 2)
if remainder:
return sorted(lst)[quotient]
return float(sum(sorted(lst)[quotient - 1:quotient + 1]) / 2.0)
def sync_to_main(self):
logger.error('sync to main')
self.read_position_main()
#print(self.main.playlist_current_pos)
if self.main.playlist_current_pos != self.mpv.playlist_current_pos:
self.mpv.playlist_play_index(self.main.playlist_current_pos)
self.mpv.pause = False
self.mpv.wait_until_playing()
try:
track = self.mpv.playlist[self.mpv.playlist_current_pos]
logger.error("%s %s", datetime.now(), track["filename"])
except:
pass
self.mpv.pause = True
self.mpv.speed = 1
pos = self.main.time_pos + SYNC_JUMP_AHEAD
#print(pos, self.mpv.playlist_current_pos, self.mpv.time_pos)
self.mpv.seek(pos, 'absolute', 'exact')
time.sleep(0.1)
self.read_position_main()
sync_timer = time.time() # - 10 * 0.04
deviation = self.main.time_pos - self.mpv.time_pos
while self.active:
#print(deviation, abs(deviation) - (time.time() - sync_timer))
if abs(deviation) - (time.time() - sync_timer) < 0:
self.mpv.pause = False
try:
track = self.mpv.playlist[self.mpv.playlist_current_pos]
logger.error("%s %s %s", datetime.now(), track["filename"], pos)
except:
pass
break
self.last_sync = time.time()
def main(): def main():
parser = argparse.ArgumentParser(description='p_for_power player') parser = argparse.ArgumentParser(description='p_for_power player')