diff options
| author | Mia Herkt <mia@0x0.st> | 2022-12-20 15:45:55 +0100 |
|---|---|---|
| committer | Mia Herkt <mia@0x0.st> | 2022-12-20 16:19:49 +0100 |
| commit | eebd5d8c6d8a756384b6cf1b2cc76b8a83cdf929 (patch) | |
| tree | 764a7c28cbdc165d0cf843f8cc0f6bc53ab224b6 /modui/mpvwidget.py | |
| parent | dcea8bffe19b8ba308f9361d6c8ef08281ddff1b (diff) | |
Add moderation TUI
This ended up way fancier than I imagined.
Diffstat (limited to 'modui/mpvwidget.py')
| -rw-r--r-- | modui/mpvwidget.py | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/modui/mpvwidget.py b/modui/mpvwidget.py new file mode 100644 index 0000000..50e5859 --- /dev/null +++ b/modui/mpvwidget.py @@ -0,0 +1,88 @@ +import time +import fcntl, struct, termios +from sys import stdout + +from textual import events, log +from textual.widgets import Static + +from fhost import app as fhost_app + +class MpvWidget(Static): + def __init__(self, **kwargs): + super().__init__(**kwargs) + + self.mpv = None + self.vo = fhost_app.config.get("MOD_PREVIEW_PROTO") + + if not self.vo in ["sixel", "kitty"]: + self.update("⚠ Previews not enabled. \n\nSet MOD_PREVIEW_PROTO to 'sixel' or 'kitty' in config.py,\nwhichever is supported by your terminal.") + else: + try: + import mpv + self.mpv = mpv.MPV() + self.mpv.profile = "sw-fast" + self.mpv["vo"] = self.vo + self.mpv[f"vo-{self.vo}-config-clear"] = False + self.mpv[f"vo-{self.vo}-alt-screen"] = False + self.mpv[f"vo-sixel-buffered"] = True + self.mpv["audio"] = False + self.mpv["loop-file"] = "inf" + self.mpv["image-display-duration"] = 0.5 if self.vo == "sixel" else "inf" + except Exception as e: + self.mpv = None + self.update(f"⚠ Previews require python-mpv with libmpv 0.36.0 or later \n\nError was:\n{type(e).__name__}: {e}") + + def start_mpv(self, f: str|None = None, pos: float|str|None = None) -> None: + self.display = True + self.screen._refresh_layout() + + if self.mpv: + if self.content_region.x: + r, c, w, h = struct.unpack('hhhh', fcntl.ioctl(0, termios.TIOCGWINSZ, '12345678')) + width = int((w / c) * self.content_region.width) + height = int((h / r) * (self.content_region.height + (1 if self.vo == "sixel" else 0))) + self.mpv[f"vo-{self.vo}-left"] = self.content_region.x + 1 + self.mpv[f"vo-{self.vo}-top"] = self.content_region.y + 1 + self.mpv[f"vo-{self.vo}-rows"] = self.content_region.height + (1 if self.vo == "sixel" else 0) + self.mpv[f"vo-{self.vo}-cols"] = self.content_region.width + self.mpv[f"vo-{self.vo}-width"] = width + self.mpv[f"vo-{self.vo}-height"] = height + + if pos != None: + self.mpv["start"] = pos + + if f: + self.mpv.loadfile(f) + else: + self.mpv.playlist_play_index(0) + + def stop_mpv(self, wait: bool = False) -> None: + if self.mpv: + if not self.mpv.idle_active: + self.mpv.stop(True) + if wait: + time.sleep(0.1) + self.clear_mpv() + self.display = False + + def on_resize(self, size) -> None: + if self.mpv: + if not self.mpv.idle_active: + t = self.mpv.time_pos + self.stop_mpv() + if t: + self.mpv["start"] = t + self.start_mpv() + + def clear_mpv(self) -> None: + if self.vo == "kitty": + stdout.write("\033_Ga=d;\033\\") + stdout.flush() + + def shutdown(self) -> None: + if self.mpv: + self.mpv.stop() + del self.mpv + if self.vo == "kitty": + stdout.write("\033_Ga=d;\033\\\033[?25l") + stdout.flush() |
