From: sbkelley Date: Tue, 2 Dec 2025 19:33:50 +0000 (-0500) Subject: More doctstrings (and bug fix) X-Git-Url: https://skyeroc.xyz/gitweb/?a=commitdiff_plain;h=9eea53416efdd483ee75719f576e0b3cf7061d2e;p=obs-ctl More doctstrings (and bug fix) --- diff --git a/src/obs_ctl/interface/obs/__init__.py b/src/obs_ctl/interface/obs/__init__.py index 203e53b..7af709b 100644 --- a/src/obs_ctl/interface/obs/__init__.py +++ b/src/obs_ctl/interface/obs/__init__.py @@ -1,2 +1,2 @@ """Provides the OBS WebSocket API widget, 'API', and OBSStats dataclass""" -from obs import API, OBSStats \ No newline at end of file +from .obs import API, OBSStats \ No newline at end of file diff --git a/src/obs_ctl/interface/obs/obs.py b/src/obs_ctl/interface/obs/obs.py index 01f7f68..92b30bc 100644 --- a/src/obs_ctl/interface/obs/obs.py +++ b/src/obs_ctl/interface/obs/obs.py @@ -29,20 +29,22 @@ class OBSStats: obsws_connection_active: bool = False record_output_active: bool = False record_output_paused: bool = False - record_output_bytes: float = 0.0 + record_output_bytes: int = 0 """Total bytes to disk.""" record_output_duration: float = 0.0 + """Elapsed time in MS""" stream_output_active: bool = False - stream_output_skipped_frames: float = 0.0 - stream_output_total_frames: float = 0.0 - stats_render_skipped_frames: float = 0.0 - stats_render_total_frames: float = 0.0 - stats_output_skipped_frames: float = 0.0 - stats_output_total_frames: float = 0.0 + stream_output_skipped_frames: int = 0 + stream_output_total_frames: int = 0 + stats_render_skipped_frames: int = 0 + stats_render_total_frames: int = 0 + stats_output_skipped_frames: int = 0 + stats_output_total_frames: int = 0 cpu_usage_percent: float = 0.0 memory_usage_mb: float = 0.0 active_fps: float = 0.0 available_disk_space: float = 0.0 + """Available space in MB""" record_directory: str = "" @property @@ -56,7 +58,7 @@ class OBSStats: (self.available_disk_space * MB_TO_BYTES) / (self.record_output_bytes / self.record_output_duration) ) * MS_TO_HOURS - except: + except ZeroDivisionError: output = "N/A" return output @@ -65,8 +67,60 @@ class API(Static): """The API is a widget for access to textual's message pump. It stores no states. It reads, writes, and outputs states. - - Messages: StreamStateUpdated, RecordStateUpdated, Report""" + # Public Methods + |signature|description| + |---|---| + |start_stream() -> None|| + |stop_stream() -> None|| + |start_record() -> None|| + |stop_record() -> None|| + |start_pause() -> None|| + |stop_pause() -> None|| + |set_record_path(path: str) -> None|| + |get_obs_stats() -> OBSStats|| + |connect(host:str=None, port:int=None, password:str=None, timeout:str=None) -> None|Attempts to connect to the given OBS WebSocket. Parameters default to API's variables.| + |disconnect() -> None|| + # Enums + ## OutputStates(StrEnum) + Named output states from OBS WebSocket + |name |value |note | + |---|---|---| + |UNKNOWN|OBS_WEBSOCKET_OUTPUT_UNKNOWN|| + |STARTED|OBS_WEBSOCKET_OUTPUT_STARTED|| + |STARTING|OBS_WEBSOCKET_OUTPUT_STARTING|| + |PAUSED|OBS_WEBSOCKET_OUTPUT_PAUSED|| + |RESUMED|OBS_WEBSOCKET_OUTPUT_RESUMED|| + |STOPPED|OBS_WEBSOCKET_OUTPUT_STOPPED|| + |STOPPING|OBS_WEBSOCKET_OUTPUT_STOPPING|| + |RECONNECTING|OBS_WEBSOCKET_OUTPUT_RECONNECTING|| + |RECONNECTED|OBS_WEBSOCKET_OUTPUT_RECONNECTED|| + ## KnownReqErrs(IntEnum) + Known obs websocket request statuses/error codes + |name |value |note | + |---|---|---| + |NOT_READY|207|Try again after a delay| + |OUTPUT_RUNNING|500|| + |OUTPUT_NOT_RUNNING|501|| + |OUTPUT_PAUSED|502|| + |OUTPUT_NOT_PAUSED|503|| + + # Reactives + |name |type |description| + |--- |--- |--- | + |interval|float|Refresh interval, in seconds| + |ws_host|str|OBS WebSocket hostname| + |ws_port|str|OBS WebSocket port| + |ws_password|str|OBS WebSocket password (insecure!)| + |ws_timeout|float, int, None|Timeout in seconds for OBS WebSocket connection| + + # Messages + |name |description|members|member description | + |--- |--- |--- |--- | + |StreamStateUpdated |WebSocket event received|state |A state from OutputStates| + |RecordStateUpdated |WebSocket event received|state |A state from OutputStates| + |Report |Posted every interval seconds, a report on the state of the WebSocket.|data |An OBSStats object| + """ + event_client: obs.EventClient = None request_client: obs.ReqClient = None is_connected: reactive[bool] = False @@ -98,7 +152,7 @@ class API(Static): RECONNECTING = "OBS_WEBSOCKET_OUTPUT_RECONNECTING" RECONNECTED = "OBS_WEBSOCKET_OUTPUT_RECONNECTED" - class KnownReqErr(IntEnum): + class KnownReqErrs(IntEnum): """Known obs websocket request statuses/error codes""" NOT_READY = 207 """This usually occurs during OBS scene collection change or exit. @@ -128,7 +182,6 @@ class API(Static): """Posted when OBS WebSocket reports a change to the Record state. state should be something from API.OutputStates.""" - pass class Report(MSGBase): """Posted ever self.interval second. data is an OBSStats object.""" @@ -146,18 +199,16 @@ class API(Static): ws_port: int = 4455, ws_password: str = "", ws_timeout: int | float | None = None, - *, - content = "", - expand = False, - shrink = False, - markup = True, - name = None, - id = None, - classes = None, - disabled = False + *args, + **kwargs, ): + """Initialize the API. + + interval is the refresh rate. + ws_host, _port, _password, and _timeout are all passed to obs_ws.*Client, + and stored locally as members of this instance.""" logger.debug(f"Initializing obs.API widget: {self}") - super().__init__(content, expand=expand, shrink=shrink, markup=markup, name=name, id=id, classes=classes, disabled=disabled) + super().__init__(*args, **kwargs) self.set_reactive(API.interval, interval) self.set_reactive(API.ws_host, ws_host) self.set_reactive(API.ws_port, ws_port) @@ -321,14 +372,14 @@ class API(Static): output = request() handled = True except obs_error.OBSSDKRequestError as err: - if err.code == API.KnownReqErr.NOT_READY: + if err.code == API.KnownReqErrs.NOT_READY: logger.info(f"OBS WebSocket not ready; trying again in 3 seconds.") logger.debug(f"At most {_sentry} more tries.") time.sleep(TRY_AGAIN) continue - elif err.code in API.KnownReqErr: - logger.debug(f"Error handled: {API.KnownReqErr(err.code)}") + elif err.code in API.KnownReqErrs: + logger.debug(f"Error handled: {API.KnownReqErrs(err.code)}") handled = True else: