feat(autostart): implement daemon management features in cli

This commit is contained in:
2026-04-28 22:35:03 +01:00
parent 695320d30f
commit 3ef9955015
3 changed files with 91 additions and 37 deletions

View File

@@ -1,26 +1,14 @@
#!/usr/bin/env python3
import os
import platform
import shutil
import subprocess import subprocess
from pathlib import Path from pathlib import Path
APP_NAME = "rewind-daemon"
def _find_executable():
path = shutil.which(APP_NAME)
if not path:
raise RuntimeError(f"{APP_NAME} not found in PATH")
return path
def _run(cmd: list[str]): def _run(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 _install_linux(program_path: str): def _create_systemd_service(program_path: str):
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)
@@ -58,24 +46,30 @@ Environment=PYTHONUNBUFFERED=1
WantedBy=default.target WantedBy=default.target
""") """)
def enable_autostart_linux(program_path: str):
_create_systemd_service(program_path)
_run(["systemctl", "--user", "daemon-reload"]) _run(["systemctl", "--user", "daemon-reload"])
_run(["systemctl", "--user", "enable", "obs.service"]) _run(["systemctl", "--user", "enable", "obs.service"])
_run(["systemctl", "--user", "enable", "rewind-daemon.service"]) _run(["systemctl", "--user", "enable", "rewind-daemon.service"])
_run(["systemctl", "--user", "start", "obs.service"]) print("Installed OBS + rewind-daemon via systemd")
def disable_autostart_linux(program_path: str):
_create_systemd_service(program_path)
_run(["systemctl", "--user", "disable", "rewind-daemon.service"])
_run(["systemctl", "--user", "disable", "obs.service"])
systemd_dir = Path.home() / ".config/systemd/user"
(systemd_dir / "rewind-daemon.service").unlink(missing_ok=True)
(systemd_dir / "obs.service").unlink(missing_ok=True)
_run(["systemctl", "--user", "daemon-reload"])
def start_daemon_linux(program_path: str):
_create_systemd_service(program_path)
_run(["systemctl", "--user", "start", "rewind-daemon.service"]) _run(["systemctl", "--user", "start", "rewind-daemon.service"])
print("Installed and started OBS + rewind-daemon via systemd") def stop_daemon_linux(program_path: str):
_create_systemd_service(program_path)
def install(): _run(["systemctl", "--user", "stop", "rewind-daemon.service"])
system = platform.system() _run(["systemctl", "--user", "stop", "obs.service"])
program_path = _find_executable()
if system == "Linux":
_install_linux(program_path)
else:
raise RuntimeError(f"Autostart on OS {system} not compatible or not implemented")
if __name__ == "__main__":
install()

49
rewind/autostart/main.py Normal file
View File

@@ -0,0 +1,49 @@
#!/usr/bin/env python3
import platform
import shutil
import rewind.autostart.linux as linux_autostart
APP_NAME = "rewind-daemon"
def _find_executable():
path = shutil.which(APP_NAME)
if not path:
raise RuntimeError(f"{APP_NAME} not found in PATH")
return path
def enable_autostart():
system = platform.system()
program_path = _find_executable()
if system == "Linux":
linux_autostart.enable_autostart_linux(program_path)
else:
raise RuntimeError(f"Autostart on OS {system} not compatible or not implemented")
def disable_autostart():
system = platform.system()
program_path = _find_executable()
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():
system = platform.system()
program_path = _find_executable()
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():
system = platform.system()
program_path = _find_executable()
if system == "Linux":
linux_autostart.stop_daemon_linux(program_path)
else:
raise RuntimeError(f"Autostart on OS {system} not compatible or not implemented")

View File

@@ -3,7 +3,7 @@ import sys
import argparse import argparse
from rewind.core import clip, mark, save, print_markers from rewind.core import clip, mark, save, print_markers
from rewind.autostart import install from rewind.autostart.main import enable_autostart, disable_autostart, start_daemon, stop_daemon
from rewind.config import Config from rewind.config import Config
def build_clip_parser(subparsers: argparse._SubParsersAction) -> None: def build_clip_parser(subparsers: argparse._SubParsersAction) -> None:
@@ -43,12 +43,14 @@ def build_mark_parser(subparsers: argparse._SubParsersAction) -> None:
def build_list_parser(subparsers: argparse._SubParsersAction) -> None: def build_list_parser(subparsers: argparse._SubParsersAction) -> None:
list_parser = subparsers.add_parser("list", help="List all markers in the recording") list_parser = subparsers.add_parser("list", help="List all markers in the recording")
def build_install_parser(subparsers: argparse._SubParsersAction) -> None: def build_daemon_parser(subparsers: argparse._SubParsersAction) -> None:
subparsers.add_parser( daemon_parser = subparsers.add_parser("daemon", help="Control the rewind daemon")
"install", daemon_sub = daemon_parser.add_subparsers(dest="daemon_command")
help="Enable background recording daemon", daemon_sub.add_parser("start", help="Start the daemon")
description="Install and enable the rewind daemon using system autostart." daemon_sub.add_parser("stop", help="Stop the daemon")
) daemon_sub.add_parser("enable", help="Enable autostart for the daemon")
daemon_sub.add_parser("disable", help="Disable autostart for the daemon")
def build_config_parser(subparsers: argparse._SubParsersAction) -> None: def build_config_parser(subparsers: argparse._SubParsersAction) -> None:
config_parser = subparsers.add_parser("config", help="View or edit config values") config_parser = subparsers.add_parser("config", help="View or edit config values")
@@ -73,7 +75,7 @@ def build_parser() -> argparse.ArgumentParser:
build_mark_parser(sub) build_mark_parser(sub)
build_list_parser(sub) build_list_parser(sub)
build_save_parser(sub) build_save_parser(sub)
build_install_parser(sub) build_daemon_parser(sub)
build_config_parser(sub) build_config_parser(sub)
return parser return parser
@@ -92,8 +94,17 @@ def main(argv=None) -> int:
print_markers() print_markers()
elif args.command == "save": elif args.command == "save":
save(args.start, args.end) save(args.start, args.end)
elif args.command == "install": elif args.command == "daemon":
install() if args.daemon_command == "start":
start_daemon()
elif args.daemon_command == "stop":
stop_daemon()
elif args.daemon_command == "enable":
enable_autostart()
elif args.daemon_command == "disable":
disable_autostart()
else:
parser.error("Unknown daemon command: expected 'start' or 'stop'")
elif args.command == "config": elif args.command == "config":
if args.config_command == "set": if args.config_command == "set":
cfg.set(args.key, args.value) cfg.set(args.key, args.value)