diff --git a/copyparty/broker_mp.py b/copyparty/broker_mp.py index b1b2f9d9..9479c707 100644 --- a/copyparty/broker_mp.py +++ b/copyparty/broker_mp.py @@ -146,21 +146,17 @@ class BrokerMp(object): returns a Queue object which eventually contains the response if want_retval (not-impl here since nothing uses it yet) """ - if dest == "httpsrv.listen": - for p in self.procs: - p.q_pend.put((0, dest, [args[0], len(self.procs)])) - - elif dest == "httpsrv.set_netdevs": - for p in self.procs: - p.q_pend.put((0, dest, list(args))) + if dest.startswith("httpsrv."): + if dest == "httpsrv.listen": + for p in self.procs: + p.q_pend.put((0, dest, [args[0], len(self.procs)])) + else: + for p in self.procs: + p.q_pend.put((0, dest, list(args))) elif dest == "cb_httpsrv_up": self.hub.cb_httpsrv_up() - elif dest == "httpsrv.set_bad_ver": - for p in self.procs: - p.q_pend.put((0, dest, list(args))) - else: raise Exception("what is " + str(dest)) diff --git a/copyparty/broker_thr.py b/copyparty/broker_thr.py index ae290d06..242746f9 100644 --- a/copyparty/broker_thr.py +++ b/copyparty/broker_thr.py @@ -58,13 +58,8 @@ class BrokerThr(BrokerCli): self.httpsrv.listen(args[0], 1) return - if dest == "httpsrv.set_netdevs": - self.httpsrv.set_netdevs(args[0]) - return - - if dest == "httpsrv.set_bad_ver": - self.httpsrv.set_bad_ver() - return + getattr(self.httpsrv, dest[8:])(*args) + return # new ipc invoking managed service in hub obj = self.hub diff --git a/copyparty/httpcli.py b/copyparty/httpcli.py index 9ff05b47..a6b93d2e 100644 --- a/copyparty/httpcli.py +++ b/copyparty/httpcli.py @@ -229,7 +229,7 @@ class HttpCli(object): self.E: EnvParams = self.args.E self.asrv = conn.asrv # mypy404 self.ico = conn.ico # mypy404 - self.thumbcli = conn.thumbcli # mypy404 + self.thumbcli = conn.hsrv.thumbcli self.u2fh = conn.u2fh # mypy404 self.pipes = conn.pipes # mypy404 self.log_func = conn.log_func # mypy404 diff --git a/copyparty/httpconn.py b/copyparty/httpconn.py index b7522374..3d4636dc 100644 --- a/copyparty/httpconn.py +++ b/copyparty/httpconn.py @@ -69,8 +69,6 @@ class HttpConn(object): self.bans: dict[str, int] = hsrv.bans self.aclose: dict[str, int] = hsrv.aclose - enth = (HAVE_PIL or HAVE_VIPS or HAVE_FFMPEG) and not self.args.no_thumb - self.thumbcli: Optional[ThumbCli] = ThumbCli(hsrv) if enth else None # mypy404 self.ico: Ico = Ico(self.args) # mypy404 self.t0: float = time.time() # mypy404 diff --git a/copyparty/httpsrv.py b/copyparty/httpsrv.py index c82cd43d..7da35727 100644 --- a/copyparty/httpsrv.py +++ b/copyparty/httpsrv.py @@ -57,6 +57,9 @@ except SyntaxError: from .httpconn import HttpConn from .metrics import Metrics +from .mtag import HAVE_FFMPEG +from .th_cli import ThumbCli +from .th_srv import HAVE_PIL, HAVE_VIPS from .u2idx import U2idx from .util import ( E_SCK, @@ -133,6 +136,8 @@ class HttpSrv(object): self.bans: dict[str, int] = {} self.aclose: dict[str, int] = {} + self.thumbcli: Optional[ThumbCli] = None + dli: dict[str, tuple[float, int, "VFS", str, str]] = {} # info dls: dict[str, tuple[float, int]] = {} # state self.dli = self.tdli = dli @@ -230,16 +235,20 @@ class HttpSrv(object): if self.args.log_thrs: start_log_thrs(self.log, self.args.log_thrs, nid) - self.th_cfg: dict[str, set[str]] = {} - Daemon(self.post_init, "hsrv-init2") + if (HAVE_PIL or HAVE_VIPS or HAVE_FFMPEG) and not self.args.no_thumb: + Daemon(self.post_init, "hsrv-init2") def post_init(self) -> None: try: x = self.broker.ask("thumbsrv.getcfg") - self.th_cfg = x.get() + self.thumbcli = ThumbCli(self, x.get()) except: pass + def set_th_cfg(self, c: dict[str, set[str]], opts: tuple[bool]) -> None: + self.args.th_no_jxl = opts[0] + self.thumbcli = ThumbCli(self, c) + def set_bad_ver(self) -> None: self.bad_ver = True diff --git a/copyparty/th_cli.py b/copyparty/th_cli.py index f2a1379c..1a4155ac 100644 --- a/copyparty/th_cli.py +++ b/copyparty/th_cli.py @@ -24,7 +24,7 @@ IMG_EXTS = set(["webp", "jpg", "png", "jxl"]) class ThumbCli(object): - def __init__(self, hsrv: "HttpSrv") -> None: + def __init__(self, hsrv: "HttpSrv", c: dict[str, set[str]]) -> None: self.broker = hsrv.broker self.log_func = hsrv.log self.args = hsrv.args @@ -33,16 +33,6 @@ class ThumbCli(object): # cache on both sides for less broker spam self.cooldown = Cooldown(self.args.th_poke) - try: - c = hsrv.th_cfg - if not c: - raise Exception() - except: - c = { - k: set() - for k in ["thumbable", "pil", "vips", "raw", "ffi", "ffv", "ffa"] - } - self.thumbable = c["thumbable"] self.fmt_pil = c["pil"] self.fmt_vips = c["vips"] diff --git a/copyparty/th_srv.py b/copyparty/th_srv.py index 94314d44..d0cd43e3 100644 --- a/copyparty/th_srv.py +++ b/copyparty/th_srv.py @@ -327,6 +327,10 @@ class ThumbSrv(object): self.fmt_pil.discard(f) self.thumbable: set[str] = set() + self._build_thumbable() + + def _build_thumbable(self) -> None: + self.thumbable.clear() if "pil" in self.args.th_dec: self.thumbable |= self.fmt_pil @@ -417,6 +421,10 @@ class ThumbSrv(object): return None + def _rebuild_thumbable(self) -> None: + self._build_thumbable() + self.hub.broker.say("httpsrv.set_th_cfg", self.getcfg(), (self.args.th_no_jxl,)) + def getcfg(self) -> dict[str, set[str]]: return { "thumbable": self.thumbable, @@ -834,6 +842,21 @@ class ThumbSrv(object): ret = 321 c = 3 + elif cmd[-1].lower().endswith(b".jxl") and ( + "Error selecting an encoder" in serr + or "Automatic encoder selection failed" in serr + or "Default encoder for format webp" in serr + or "Unrecognized option 'effort:v" in serr + or "Please choose an encoder manually" in serr + ): + self.args.th_no_jxl = True + self.fmt_ffi.discard("jxl") + self.fmt_ffv.discard("jxl") + self._rebuild_thumbable() + t = "FFmpeg failed because it was compiled without jpegxl; enabling --th-no-jxl to force webp output:\n" + ret = 321 + c = 1 + elif ( (not self.args.th_ff_jpg or time.time() - int(self.args.th_ff_jpg) < 60) and cmd[-1].lower().endswith(b".webp") diff --git a/tests/util.py b/tests/util.py index f4563faa..2d75c71d 100644 --- a/tests/util.py +++ b/tests/util.py @@ -316,6 +316,7 @@ class VHttpSrv(object): self.g403 = Garda("") self.gurl = Garda("") + self.thumbcli = None self.u2idx = None def cachebuster(self):