refactor(autostart): abstract backend implementation for autostart
This commit is contained in:
15
rewind/autostart/autostart_backend.py
Normal file
15
rewind/autostart/autostart_backend.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
class AutostartBackend:
|
||||||
|
def __init__(self, program_path: str):
|
||||||
|
self.program_path = program_path
|
||||||
|
|
||||||
|
def enable_autostart(self):
|
||||||
|
raise NotImplementedError("enable_autostart not implemented for this platform")
|
||||||
|
|
||||||
|
def disable_autostart(self):
|
||||||
|
raise NotImplementedError("disable_autostart not implemented for this platform")
|
||||||
|
|
||||||
|
def start_daemon(self):
|
||||||
|
raise NotImplementedError("start_daemon not implemented for this platform")
|
||||||
|
|
||||||
|
def stop_daemon(self):
|
||||||
|
raise NotImplementedError("stop_daemon not implemented for this platform")
|
||||||
@@ -1,14 +1,19 @@
|
|||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from rewind.autostart.autostart_backend import AutostartBackend
|
||||||
|
|
||||||
def _run(cmd: list[str]):
|
class LinuxBackend(AutostartBackend):
|
||||||
|
def __init__(self, program_path: str):
|
||||||
|
super().__init__(program_path)
|
||||||
|
|
||||||
|
def _run(self, cmd: list[str]):
|
||||||
result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||||
if result.returncode != 0:
|
if result.returncode != 0:
|
||||||
raise RuntimeError(f"Command failed: {' '.join(cmd)}\n{result.stderr}")
|
raise RuntimeError(f"Command failed: {' '.join(cmd)}\n{result.stderr}")
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def _create_systemd_service(program_path: str):
|
def _create_systemd_service(self):
|
||||||
systemd_dir = Path.home() / ".config/systemd/user"
|
systemd_dir = Path.home() / ".config/systemd/user"
|
||||||
systemd_dir.mkdir(parents=True, exist_ok=True)
|
systemd_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
@@ -16,60 +21,60 @@ def _create_systemd_service(program_path: str):
|
|||||||
daemon_service = systemd_dir / "rewind-daemon.service"
|
daemon_service = systemd_dir / "rewind-daemon.service"
|
||||||
|
|
||||||
obs_service.write_text("""[Unit]
|
obs_service.write_text("""[Unit]
|
||||||
Description=OBS Studio
|
Description=OBS Studio
|
||||||
After=graphical-session.target
|
After=graphical-session.target
|
||||||
Wants=graphical-session.target
|
Wants=graphical-session.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
# Ensure OBS sentinel files are cleaned up before starting the daemon
|
# Ensure OBS sentinel files are cleaned up before starting the daemon
|
||||||
ExecStartPre=-/usr/bin/rm -rf %h/.config/obs-studio/.sentinel
|
ExecStartPre=-/usr/bin/rm -rf %h/.config/obs-studio/.sentinel
|
||||||
ExecStart=obs --minimize-to-tray
|
ExecStart=obs --minimize-to-tray
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
RestartSec=3
|
RestartSec=3
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=default.target
|
WantedBy=default.target
|
||||||
""")
|
""")
|
||||||
|
|
||||||
daemon_service.write_text(f"""[Unit]
|
daemon_service.write_text(f"""[Unit]
|
||||||
Description=Rewind Daemon
|
Description=Rewind Daemon
|
||||||
After=obs.service
|
After=obs.service
|
||||||
Requires=obs.service
|
Requires=obs.service
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
ExecStart={program_path}
|
ExecStart={self.program_path}
|
||||||
Restart=always
|
Restart=always
|
||||||
RestartSec=5
|
RestartSec=5
|
||||||
Environment=PYTHONUNBUFFERED=1
|
Environment=PYTHONUNBUFFERED=1
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=default.target
|
WantedBy=default.target
|
||||||
""")
|
""")
|
||||||
|
|
||||||
def enable_autostart_linux(program_path: str):
|
def enable_autostart(self):
|
||||||
_create_systemd_service(program_path)
|
self._create_systemd_service()
|
||||||
_run(["systemctl", "--user", "daemon-reload"])
|
self._run(["systemctl", "--user", "daemon-reload"])
|
||||||
|
|
||||||
_run(["systemctl", "--user", "enable", "obs.service"])
|
self._run(["systemctl", "--user", "enable", "obs.service"])
|
||||||
_run(["systemctl", "--user", "enable", "rewind-daemon.service"])
|
self._run(["systemctl", "--user", "enable", "rewind-daemon.service"])
|
||||||
|
|
||||||
print("Installed OBS + rewind-daemon via systemd")
|
print("Installed OBS + rewind-daemon via systemd")
|
||||||
|
|
||||||
def disable_autostart_linux(program_path: str):
|
def disable_autostart(self):
|
||||||
_create_systemd_service(program_path)
|
self._create_systemd_service()
|
||||||
_run(["systemctl", "--user", "disable", "rewind-daemon.service"])
|
self._run(["systemctl", "--user", "disable", "rewind-daemon.service"])
|
||||||
_run(["systemctl", "--user", "disable", "obs.service"])
|
self._run(["systemctl", "--user", "disable", "obs.service"])
|
||||||
|
|
||||||
systemd_dir = Path.home() / ".config/systemd/user"
|
systemd_dir = Path.home() / ".config/systemd/user"
|
||||||
(systemd_dir / "rewind-daemon.service").unlink(missing_ok=True)
|
(systemd_dir / "rewind-daemon.service").unlink(missing_ok=True)
|
||||||
(systemd_dir / "obs.service").unlink(missing_ok=True)
|
(systemd_dir / "obs.service").unlink(missing_ok=True)
|
||||||
_run(["systemctl", "--user", "daemon-reload"])
|
self._run(["systemctl", "--user", "daemon-reload"])
|
||||||
|
|
||||||
def start_daemon_linux(program_path: str):
|
def start_daemon(self):
|
||||||
_create_systemd_service(program_path)
|
self._create_systemd_service()
|
||||||
_run(["systemctl", "--user", "start", "rewind-daemon.service"])
|
self._run(["systemctl", "--user", "start", "rewind-daemon.service"])
|
||||||
|
|
||||||
def stop_daemon_linux(program_path: str):
|
def stop_daemon(self):
|
||||||
_create_systemd_service(program_path)
|
self._create_systemd_service()
|
||||||
_run(["systemctl", "--user", "stop", "rewind-daemon.service"])
|
self._run(["systemctl", "--user", "stop", "rewind-daemon.service"])
|
||||||
_run(["systemctl", "--user", "stop", "obs.service"])
|
self._run(["systemctl", "--user", "stop", "obs.service"])
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
import platform
|
import platform
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
import rewind.autostart.linux as linux_autostart
|
from rewind.autostart.linux import LinuxBackend
|
||||||
|
|
||||||
APP_NAME = "rewind-daemon"
|
APP_NAME = "rewind-daemon"
|
||||||
|
|
||||||
@@ -12,38 +12,26 @@ def _find_executable():
|
|||||||
raise RuntimeError(f"{APP_NAME} not found in PATH")
|
raise RuntimeError(f"{APP_NAME} not found in PATH")
|
||||||
return path
|
return path
|
||||||
|
|
||||||
def enable_autostart():
|
def _get_backend():
|
||||||
system = platform.system()
|
system = platform.system()
|
||||||
program_path = _find_executable()
|
program_path = _find_executable()
|
||||||
|
|
||||||
if system == "Linux":
|
if system == "Linux":
|
||||||
linux_autostart.enable_autostart_linux(program_path)
|
return LinuxBackend(program_path)
|
||||||
else:
|
else:
|
||||||
raise RuntimeError(f"Autostart on OS {system} not compatible or not implemented")
|
raise RuntimeError(f"Autostart on OS {system} not compatible or not implemented")
|
||||||
|
|
||||||
|
def enable_autostart():
|
||||||
|
backend = _get_backend()
|
||||||
|
backend.enable_autostart()
|
||||||
|
|
||||||
def disable_autostart():
|
def disable_autostart():
|
||||||
system = platform.system()
|
backend = _get_backend()
|
||||||
program_path = _find_executable()
|
backend.disable_autostart()
|
||||||
|
|
||||||
if system == "Linux":
|
|
||||||
linux_autostart.disable_autostart_linux(program_path)
|
|
||||||
else:
|
|
||||||
raise RuntimeError(f"Autostart on OS {system} not compatible or not implemented")
|
|
||||||
|
|
||||||
def start_daemon():
|
def start_daemon():
|
||||||
system = platform.system()
|
backend = _get_backend()
|
||||||
program_path = _find_executable()
|
backend.start_daemon()
|
||||||
|
|
||||||
if system == "Linux":
|
|
||||||
linux_autostart.start_daemon_linux(program_path)
|
|
||||||
else:
|
|
||||||
raise RuntimeError(f"Autostart on OS {system} not compatible or not implemented")
|
|
||||||
|
|
||||||
def stop_daemon():
|
def stop_daemon():
|
||||||
system = platform.system()
|
backend = _get_backend()
|
||||||
program_path = _find_executable()
|
backend.stop_daemon()
|
||||||
|
|
||||||
if system == "Linux":
|
|
||||||
linux_autostart.stop_daemon_linux(program_path)
|
|
||||||
else:
|
|
||||||
raise RuntimeError(f"Autostart on OS {system} not compatible or not implemented")
|
|
||||||
@@ -16,7 +16,6 @@ from rewind.state import add_file_to_state, create_state_file_if_needed, cleanup
|
|||||||
running = True
|
running = True
|
||||||
LOG_FILE = get_state_dir() / "daemon.log"
|
LOG_FILE = get_state_dir() / "daemon.log"
|
||||||
INTERVAL = 10
|
INTERVAL = 10
|
||||||
SENTINEL_FILE = os.path.expanduser("~/.config/obs-studio/.sentinel")
|
|
||||||
OBS_MAX_RETRIES = 5
|
OBS_MAX_RETRIES = 5
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|||||||
Reference in New Issue
Block a user