feat(install): add autostart functionality for rewind daemon

This commit is contained in:
2026-04-26 23:42:45 +01:00
parent 8b3fe98423
commit 0af780a95c
2 changed files with 96 additions and 0 deletions

85
rewind/autostart.py Normal file
View File

@@ -0,0 +1,85 @@
#!/usr/bin/env python3
import os
import platform
import shutil
import subprocess
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]):
result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
if result.returncode != 0:
raise RuntimeError(f"Command failed: {' '.join(cmd)}\n{result.stderr}")
return result
def _install_linux(program_path: str):
systemd_dir = Path.home() / ".config/systemd/user"
systemd_dir.mkdir(parents=True, exist_ok=True)
obs_service = systemd_dir / "obs.service"
daemon_service = systemd_dir / "rewind-daemon.service"
if obs_service.exists():
print("obs.service already exists, skipping creation")
else:
obs_service.write_text("""[Unit]
Description=OBS Studio
After=graphical-session.target
Wants=graphical-session.target
[Service]
ExecStart=obs --minimize-to-tray
Restart=on-failure
RestartSec=3
[Install]
WantedBy=default.target
""")
if daemon_service.exists():
print("rewind-daemon.service already exists, skipping creation")
else:
daemon_service.write_text(f"""[Unit]
Description=Rewind Daemon
After=obs.service
Requires=obs.service
[Service]
ExecStart={program_path}
Restart=always
RestartSec=5
Environment=PYTHONUNBUFFERED=1
[Install]
WantedBy=default.target
""")
_run(["systemctl", "--user", "daemon-reload"])
_run(["systemctl", "--user", "enable", "obs.service"])
_run(["systemctl", "--user", "enable", "rewind-daemon.service"])
_run(["systemctl", "--user", "start", "obs.service"])
_run(["systemctl", "--user", "start", "rewind-daemon.service"])
print("Installed and started OBS + rewind-daemon via systemd")
def install():
system = platform.system()
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()

View File

@@ -3,6 +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
def build_clip_parser(subparsers: argparse._SubParsersAction) -> None: def build_clip_parser(subparsers: argparse._SubParsersAction) -> None:
clip_parser = subparsers.add_parser("clip", help="Clips the last 'x' seconds") clip_parser = subparsers.add_parser("clip", help="Clips the last 'x' seconds")
@@ -41,6 +42,13 @@ 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):
subparsers.add_parser(
"install",
help="Enable background recording daemon",
description="Install and enable the rewind daemon using system autostart."
)
def build_parser() -> argparse.ArgumentParser: def build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
prog="rewind", prog="rewind",
@@ -53,6 +61,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)
return parser return parser
@@ -69,6 +78,8 @@ 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":
install()
else: else:
parser.error("Unknown command") parser.error("Unknown command")
except Exception as e: except Exception as e: