feat(install): add autostart functionality for rewind daemon
This commit is contained in:
85
rewind/autostart.py
Normal file
85
rewind/autostart.py
Normal 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()
|
||||||
@@ -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:
|
||||||
|
|||||||
Reference in New Issue
Block a user