diff --git a/completions/caelestia.fish b/completions/caelestia.fish index 80f177cb..c2463254 100644 --- a/completions/caelestia.fish +++ b/completions/caelestia.fish @@ -106,6 +106,7 @@ complete -c caelestia -n "$seen screenshot" -s 'f' -l 'freeze' -d 'Freeze while complete -c caelestia -n "$seen record" -s 'r' -l 'region' -d 'Capture region' complete -c caelestia -n "$seen record" -s 's' -l 'sound' -d 'Capture sound' complete -c caelestia -n "$seen record" -s 'c' -l 'clipboard' -d 'Copy recording path to clipboard' +complete -c caelestia -n "$seen record" -s 'n' -l 'allow-notifs' -d 'Allow notifications to show during recording' # Clipboard complete -c caelestia -n "$seen clipboard" -s 'd' -l 'delete' -d 'Delete from cliboard history' diff --git a/default.nix b/default.nix index 22fb0b64..34c4cc6d 100644 --- a/default.nix +++ b/default.nix @@ -64,6 +64,8 @@ python3.pkgs.buildPythonApplication { --replace-fail '"qs", "-c", "caelestia"' '"caelestia-shell"' substituteInPlace src/caelestia/subcommands/screenshot.py \ --replace-fail '"qs", "-c", "caelestia"' '"caelestia-shell"' + substituteInPlace src/caelestia/subcommands/record.py \ + --replace-fail '"qs", "-c", "caelestia"' '"caelestia-shell"' # Use config bin instead of discord + fix todoist + fix app2unit substituteInPlace src/caelestia/subcommands/toggle.py \ diff --git a/src/caelestia/parser.py b/src/caelestia/parser.py index aafa8525..adcb876a 100644 --- a/src/caelestia/parser.py +++ b/src/caelestia/parser.py @@ -72,6 +72,9 @@ def parse_args() -> tuple[argparse.ArgumentParser, argparse.Namespace]: record_parser.add_argument("-s", "--sound", action="store_true", help="record audio") record_parser.add_argument("-p", "--pause", action="store_true", help="pause/resume the recording") record_parser.add_argument("-c", "--clipboard", action="store_true", help="copy recording path to clipboard") + record_parser.add_argument( + "-n", "--allow-notifs", action="store_true", help="allow notifications to show during recording" + ) # Create parser for clipboard opts clipboard_parser = command_parser.add_parser("clipboard", help="open clipboard history") diff --git a/src/caelestia/subcommands/record.py b/src/caelestia/subcommands/record.py index 1fa76c6d..c64481fe 100644 --- a/src/caelestia/subcommands/record.py +++ b/src/caelestia/subcommands/record.py @@ -8,7 +8,13 @@ from pathlib import Path from caelestia.utils.notify import close_notification, notify -from caelestia.utils.paths import recording_notif_path, recording_path, recordings_dir, user_config_path +from caelestia.utils.paths import ( + recording_dnd_state_path, + recording_notif_path, + recording_path, + recordings_dir, + user_config_path, +) RECORDER = "gpu-screen-recorder" @@ -33,6 +39,25 @@ def proc_running(self) -> bool: def intersects(self, a: tuple[int, int, int, int], b: tuple[int, int, int, int]) -> bool: return a[0] < b[0] + b[2] and a[0] + a[2] > b[0] and a[1] < b[1] + b[3] and a[1] + a[3] > b[1] + def set_dnd(self, enable: bool) -> None: + subprocess.run(["qs", "-c", "caelestia", "ipc", "call", "notifs", "enableDnd" if enable else "disableDnd"]) + + def save_dnd_state(self) -> None: + state = subprocess.check_output( + ["qs", "-c", "caelestia", "ipc", "call", "notifs", "isDndEnabled"], text=True + ).strip() == "true" + recording_dnd_state_path.write_text("true" if state else "false") + + def restore_dnd_state(self) -> None: + try: + state = recording_dnd_state_path.read_text().strip() == "true" + self.set_dnd(state) + except FileNotFoundError: + return + finally: + recording_dnd_state_path.unlink(missing_ok=True) + + def start(self) -> None: args = ["-w"] @@ -74,6 +99,10 @@ def start(self) -> None: raise ValueError(f"Config option 'record.extraArgs' should be an array: {e}") recording_path.parent.mkdir(parents=True, exist_ok=True) + + if not self.args.allow_notifs: + self.save_dnd_state() + self.set_dnd(True) proc = subprocess.Popen([RECORDER, *args, "-o", str(recording_path)], start_new_session=True) notif = notify("-p", "Recording started", "Recording...") @@ -81,6 +110,7 @@ def start(self) -> None: try: if proc.wait(1) != 0: + self.restore_dnd_state() close_notification(notif) notify( "Recording failed", @@ -93,6 +123,7 @@ def start(self) -> None: def stop(self) -> None: # Start killing recording process subprocess.run(["pkill", "-f", RECORDER], stdout=subprocess.DEVNULL) + self.restore_dnd_state() # Wait for recording to finish to avoid corrupted video file while self.proc_running(): diff --git a/src/caelestia/utils/paths.py b/src/caelestia/utils/paths.py index 3223b900..2f3ca6bd 100644 --- a/src/caelestia/utils/paths.py +++ b/src/caelestia/utils/paths.py @@ -40,6 +40,7 @@ recordings_dir: Path = Path(os.getenv("CAELESTIA_RECORDINGS_DIR", videos_dir / "Recordings")) recording_path: Path = c_state_dir / "record/recording.mp4" recording_notif_path: Path = c_state_dir / "record/notifid.txt" +recording_dnd_state_path: Path = c_state_dir / "record/dnd_state.txt" def compute_hash(path: Path | str) -> str: