From 2eb48556edcc562eb02fb4f11fe424cc4e689b11 Mon Sep 17 00:00:00 2001 From: onyx-and-iris Date: Sun, 29 Jun 2025 16:35:00 +0100 Subject: [PATCH] implement get/set recording directory closes #3 minor bump --- pyproject.toml | 2 +- src/simple_recorder/cli.py | 3 +- src/simple_recorder/directory.py | 36 +++++++++++++++++ src/simple_recorder/gui.py | 68 ++++++++++++++++++++++++++------ 4 files changed, 94 insertions(+), 15 deletions(-) create mode 100644 src/simple_recorder/directory.py diff --git a/pyproject.toml b/pyproject.toml index 701c40c..c4d28e1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "simple-recorder" -version = "0.2.0" +version = "0.3.0" description = "A simple OBS recorder" authors = [{ name = "onyx-and-iris", email = "code@onyxandiris.online" }] dependencies = [ diff --git a/src/simple_recorder/cli.py b/src/simple_recorder/cli.py index 094eddf..b1b9ad0 100644 --- a/src/simple_recorder/cli.py +++ b/src/simple_recorder/cli.py @@ -3,6 +3,7 @@ import logging from clypi import ClypiConfig, ClypiException, Command, arg, configure from typing_extensions import override +from .directory import Directory from .errors import SimpleRecorderError from .gui import SimpleRecorderWindow from .pause import Pause @@ -37,7 +38,7 @@ def theme_parser(value: str) -> str: class SimpleRecorder(Command): - subcommand: Start | Stop | Pause | Resume | None = None + subcommand: Start | Stop | Pause | Resume | Directory | None = None host: str = arg(default="localhost", env="OBS_HOST", help="OBS WebSocket host") port: int = arg(default=4455, env="OBS_PORT", help="OBS WebSocket port") password: str | None = arg( diff --git a/src/simple_recorder/directory.py b/src/simple_recorder/directory.py new file mode 100644 index 0000000..340a5e7 --- /dev/null +++ b/src/simple_recorder/directory.py @@ -0,0 +1,36 @@ +import obsws_python as obsws +from clypi import Command, Positional, arg +from typing_extensions import override + +from .errors import SimpleRecorderError +from .styler import highlight + + +class Directory(Command): + """Get or set the recording directory.""" + + directory: Positional[str] = arg( + default=None, + help="Directory to set for recordings. If not provided, the current directory will be displayed.", + ) + host: str = arg(inherited=True) + port: int = arg(inherited=True) + password: str = arg(inherited=True) + + @override + async def run(self): + try: + with obsws.ReqClient( + host=self.host, port=self.port, password=self.password + ) as client: + if self.directory: + client.set_record_directory(self.directory) + print(f"Recording directory set to: {highlight(self.directory)}") + else: + resp = client.get_record_directory() + print( + f"Current recording directory: {highlight(resp.record_directory)}" + ) + return resp.record_directory + except Exception as e: + raise SimpleRecorderError(f"Failed to get recording directory: {e}") diff --git a/src/simple_recorder/gui.py b/src/simple_recorder/gui.py index db25518..85e3dcd 100644 --- a/src/simple_recorder/gui.py +++ b/src/simple_recorder/gui.py @@ -3,6 +3,7 @@ import logging import FreeSimpleGUI as fsg import obsws_python as obsws +from .directory import Directory from .errors import SimpleRecorderError from .pause import Pause from .resume import Resume @@ -26,6 +27,8 @@ class SimpleRecorderWindow(fsg.Window): ) as client: resp = client.get_version() status_message = f"Connected to OBS {resp.obs_version} ✓" + resp = client.get_record_directory() + current_directory = resp.record_directory except (ConnectionRefusedError, TimeoutError): status_message = "Failed to connect to OBS. Is it running?" @@ -59,7 +62,7 @@ class SimpleRecorderWindow(fsg.Window): [ fsg.Text( f"Status: {status_message}", - key="-OUTPUT-", + key="-OUTPUT-RECORDER-", text_color="white" if status_message.startswith("Connected") else "red", @@ -70,7 +73,12 @@ class SimpleRecorderWindow(fsg.Window): settings_layout = [ [fsg.Text("Enter the filepath for the recording:")], - [fsg.InputText("", key="-FILEPATH-", size=(45, 1))], + [fsg.InputText(current_directory, key="-FILEPATH-", size=(45, 1))], + [ + fsg.Button("Get Current", key="-GET-CURRENT-", size=(10, 1)), + fsg.Button("Update", key="-UPDATE-", size=(10, 1)), + ], + [fsg.Text("", key="-OUTPUT-SETTINGS-", text_color="white")], ] settings_tab = fsg.Tab("Settings", settings_layout) @@ -110,11 +118,11 @@ class SimpleRecorderWindow(fsg.Window): port=self.port, password=self.password, ).run() - self["-OUTPUT-"].update( + self["-OUTPUT-RECORDER-"].update( "Recording started successfully", text_color="green" ) except SimpleRecorderError as e: - self["-OUTPUT-"].update( + self["-OUTPUT-RECORDER-"].update( f"Error: {e.raw_message}", text_color="red" ) @@ -123,11 +131,11 @@ class SimpleRecorderWindow(fsg.Window): await Stop( host=self.host, port=self.port, password=self.password ).run() - self["-OUTPUT-"].update( + self["-OUTPUT-RECORDER-"].update( "Recording stopped successfully", text_color="green" ) except SimpleRecorderError as e: - self["-OUTPUT-"].update( + self["-OUTPUT-RECORDER-"].update( f"Error: {e.raw_message}", text_color="red" ) @@ -136,11 +144,11 @@ class SimpleRecorderWindow(fsg.Window): await Pause( host=self.host, port=self.port, password=self.password ).run() - self["-OUTPUT-"].update( + self["-OUTPUT-RECORDER-"].update( "Recording paused successfully", text_color="green" ) except SimpleRecorderError as e: - self["-OUTPUT-"].update( + self["-OUTPUT-RECORDER-"].update( f"Error: {e.raw_message}", text_color="red" ) @@ -149,21 +157,21 @@ class SimpleRecorderWindow(fsg.Window): await Resume( host=self.host, port=self.port, password=self.password ).run() - self["-OUTPUT-"].update( + self["-OUTPUT-RECORDER-"].update( "Recording resumed successfully", text_color="green" ) except SimpleRecorderError as e: - self["-OUTPUT-"].update( + self["-OUTPUT-RECORDER-"].update( f"Error: {e.raw_message}", text_color="red" ) case ["Add Chapter", "FOCUS" | "LEAVE" as focus_event]: if focus_event == "FOCUS": - self["-OUTPUT-"].update( + self["-OUTPUT-RECORDER-"].update( "Right-click to set a chapter name", text_color="white" ) else: - self["-OUTPUT-"].update("", text_color="white") + self["-OUTPUT-RECORDER-"].update("", text_color="white") case ["Add Chapter", "RIGHT_CLICK"]: _ = fsg.popup_get_text( @@ -173,10 +181,44 @@ class SimpleRecorderWindow(fsg.Window): ) case ["Split Recording" | "Add Chapter"]: - self["-OUTPUT-"].update( + self["-OUTPUT-RECORDER-"].update( "This feature is not implemented yet", text_color="orange" ) + case ["-GET-CURRENT-"]: + try: + current_directory = await Directory( + host=self.host, port=self.port, password=self.password + ).run() + self["-FILEPATH-"].update(current_directory) + except SimpleRecorderError as e: + self["-OUTPUT-SETTINGS-"].update( + f"Error: {e.raw_message}", text_color="red" + ) + + case ["-UPDATE-"]: + filepath = values["-FILEPATH-"] + if not filepath: + self["-OUTPUT-SETTINGS-"].update( + "Filepath cannot be empty", text_color="red" + ) + else: + try: + await Directory( + directory=filepath, + host=self.host, + port=self.port, + password=self.password, + ).run() + self["-OUTPUT-SETTINGS-"].update( + "Recording directory updated successfully.", + text_color="green", + ) + except SimpleRecorderError as e: + self["-OUTPUT-SETTINGS-"].update( + f"Error: {e.raw_message}", text_color="red" + ) + case _: self.logger.debug(f"Unhandled event: {e}")