3 Commits

Author SHA1 Message Date
dc7bec3ed0 fix docstring. 2023-10-08 14:47:40 +01:00
e4a87609ee fix desc 2023-10-08 03:55:29 +01:00
79a056a5c8 adds projector methods with deprecation warning 2023-10-08 03:53:47 +01:00
7 changed files with 65 additions and 115 deletions

View File

@@ -17,12 +17,6 @@ class Observer:
print(f"Registered events: {self._client.callback.get()}") print(f"Registered events: {self._client.callback.get()}")
self.running = True self.running = True
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, exc_traceback):
self._client.disconnect()
def on_current_program_scene_changed(self, data): def on_current_program_scene_changed(self, data):
"""The current program scene has changed.""" """The current program scene has changed."""
print(f"Switched to scene {data.scene_name}") print(f"Switched to scene {data.scene_name}")
@@ -37,11 +31,13 @@ class Observer:
def on_exit_started(self, _): def on_exit_started(self, _):
"""OBS has begun the shutdown process.""" """OBS has begun the shutdown process."""
print("OBS closing!") print(f"OBS closing!")
self._client.unsubscribe()
self.running = False self.running = False
if __name__ == "__main__": if __name__ == "__main__":
with Observer() as observer: observer = Observer()
while observer.running:
time.sleep(0.1) while observer.running:
time.sleep(0.1)

View File

@@ -1,7 +1,6 @@
import inspect import inspect
import keyboard import keyboard
import obsws_python as obs import obsws_python as obs
@@ -11,12 +10,6 @@ class Observer:
self._client.callback.register(self.on_current_program_scene_changed) self._client.callback.register(self.on_current_program_scene_changed)
print(f"Registered events: {self._client.callback.get()}") print(f"Registered events: {self._client.callback.get()}")
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, exc_traceback):
self._client.disconnect()
@property @property
def event_identifier(self): def event_identifier(self):
return inspect.stack()[1].function return inspect.stack()[1].function
@@ -38,12 +31,13 @@ def set_scene(scene, *args):
if __name__ == "__main__": if __name__ == "__main__":
with obs.ReqClient() as req_client: req_client = obs.ReqClient()
with Observer() as observer: observer = Observer()
keyboard.add_hotkey("0", version)
keyboard.add_hotkey("1", set_scene, args=("START",))
keyboard.add_hotkey("2", set_scene, args=("BRB",))
keyboard.add_hotkey("3", set_scene, args=("END",))
print("press ctrl+enter to quit") keyboard.add_hotkey("0", version)
keyboard.wait("ctrl+enter") keyboard.add_hotkey("1", set_scene, args=("START",))
keyboard.add_hotkey("2", set_scene, args=("BRB",))
keyboard.add_hotkey("3", set_scene, args=("END",))
print("press ctrl+enter to quit")
keyboard.wait("ctrl+enter")

View File

@@ -9,8 +9,6 @@ LEVELTYPE = IntEnum(
start=0, start=0,
) )
DEVICE = "Desktop Audio"
def on_input_mute_state_changed(data): def on_input_mute_state_changed(data):
"""An input's mute state has changed.""" """An input's mute state has changed."""
@@ -34,14 +32,15 @@ def on_input_volume_meters(data):
def main(): def main():
with obs.EventClient( client = obs.EventClient(subs=(obs.Subs.LOW_VOLUME | obs.Subs.INPUTVOLUMEMETERS))
subs=(obs.Subs.LOW_VOLUME | obs.Subs.INPUTVOLUMEMETERS) client.callback.register([on_input_volume_meters, on_input_mute_state_changed])
) as client:
client.callback.register([on_input_volume_meters, on_input_mute_state_changed])
while _ := input("Press <Enter> to exit\n"): while cmd := input("<Enter> to exit>\n"):
pass if not cmd:
break
if __name__ == "__main__": if __name__ == "__main__":
DEVICE = "Desktop Audio"
main() main()

View File

@@ -1,8 +1,9 @@
import json import json
import logging import logging
import threading import time
from threading import Thread
from websocket import WebSocketConnectionClosedException, WebSocketTimeoutException from websocket import WebSocketTimeoutException
from .baseclient import ObsClient from .baseclient import ObsClient
from .callback import Callback from .callback import Callback
@@ -19,6 +20,8 @@ logger = logging.getLogger(__name__)
class EventClient: class EventClient:
DELAY = 0.001
def __init__(self, **kwargs): def __init__(self, **kwargs):
self.logger = logger.getChild(self.__class__.__name__) self.logger = logger.getChild(self.__class__.__name__)
defaultkwargs = {"subs": Subs.LOW_VOLUME} defaultkwargs = {"subs": Subs.LOW_VOLUME}
@@ -35,12 +38,6 @@ class EventClient:
self.callback = Callback() self.callback = Callback()
self.subscribe() self.subscribe()
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, exc_traceback):
self.disconnect()
def __repr__(self): def __repr__(self):
return type( return type(
self self
@@ -52,40 +49,33 @@ class EventClient:
return type(self).__name__ return type(self).__name__
def subscribe(self): def subscribe(self):
self.base_client.ws.settimeout(None) worker = Thread(target=self.trigger, daemon=True)
stop_event = threading.Event() worker.start()
self.worker = threading.Thread(
target=self.trigger, daemon=True, args=(stop_event,)
)
self.worker.start()
def trigger(self, stop_event): def trigger(self):
""" """
Continuously listen for events. Continuously listen for events.
Triggers a callback on event received. Triggers a callback on event received.
""" """
while not stop_event.is_set(): self.running = True
while self.running:
try: try:
if response := self.base_client.ws.recv(): event = json.loads(self.base_client.ws.recv())
event = json.loads(response)
self.logger.debug(f"Event received {event}")
type_, data = (
event["d"].get("eventType"),
event["d"].get("eventData"),
)
self.callback.trigger(type_, data if data else {})
except WebSocketTimeoutException as e: except WebSocketTimeoutException as e:
self.logger.exception(f"{type(e).__name__}: {e}") self.logger.exception(f"{type(e).__name__}: {e}")
raise OBSSDKTimeoutError("Timeout while waiting for event") from e raise OBSSDKTimeoutError("Timeout while waiting for event") from e
except (WebSocketConnectionClosedException, OSError) as e: self.logger.debug(f"Event received {event}")
self.logger.debug(f"{type(e).__name__} terminating the event thread") type_, data = (
stop_event.set() event["d"].get("eventType"),
event["d"].get("eventData"),
def disconnect(self): )
"""stop listening for events""" self.callback.trigger(type_, data if data else {})
time.sleep(self.DELAY)
def unsubscribe(self):
"""
stop listening for events
"""
self.running = False
self.base_client.ws.close() self.base_client.ws.close()
self.worker.join()
unsubscribe = disconnect

View File

@@ -31,7 +31,7 @@ class ReqClient:
return self return self
def __exit__(self, exc_type, exc_value, exc_traceback): def __exit__(self, exc_type, exc_value, exc_traceback):
self.disconnect() self.base_client.ws.close()
def __repr__(self): def __repr__(self):
return type( return type(
@@ -42,9 +42,6 @@ class ReqClient:
def __str__(self): def __str__(self):
return type(self).__name__ return type(self).__name__
def disconnect(self):
self.base_client.ws.close()
def send(self, param, data=None, raw=False): def send(self, param, data=None, raw=False):
try: try:
@@ -436,19 +433,6 @@ class ReqClient:
""" """
return self.send("GetRecordDirectory") return self.send("GetRecordDirectory")
def set_record_directory(self, recordDirectory):
"""
Sets the current directory that the record output writes files to.
IMPORTANT NOTE: Requires obs websocket v5.3 or higher.
:param recordDirectory: Output directory
:type recordDirectory: str
"""
payload = {
"recordDirectory": recordDirectory,
}
return self.send("SetRecordDirectory", payload)
def get_source_active(self, name): def get_source_active(self, name):
""" """
Gets the active and show state of a source Gets the active and show state of a source
@@ -1962,24 +1946,16 @@ class ReqClient:
""" """
Opens a projector for a specific output video mix. Opens a projector for a specific output video mix.
The available mix types are: :param videoMixType: Type of mix to open
OBS_WEBSOCKET_VIDEO_MIX_TYPE_PREVIEW :type videoMixType: str
OBS_WEBSOCKET_VIDEO_MIX_TYPE_PROGRAM :param monitorIndex: Monitor index, use GetMonitorList to obtain index
OBS_WEBSOCKET_VIDEO_MIX_TYPE_MULTIVIEW :type monitorIndex: int
:param projectorGeometry: Size/Position data for a windowed projector, in Qt Base64 encoded format. Mutually exclusive with monitorIndex
:param video_mix_type: Type of mix to open. :type projectorGeometry: str
:type video_mix_type: str
:param monitor_index: Monitor index, use GetMonitorList to obtain index
:type monitor_index: int
:param projector_geometry:
Size/Position data for a windowed projector, in Qt Base64 encoded format.
Mutually exclusive with monitorIndex
:type projector_geometry: str
""" """
warn( warn(
"open_video_mix_projector request serves to provide feature parity with 4.x. " "open_video_mix_projector request serves to provide feature parity with 4.x. It is very likely to be changed/deprecated in a future release.",
"It is very likely to be changed/deprecated in a future release.",
DeprecationWarning, DeprecationWarning,
stacklevel=2, stacklevel=2,
) )
@@ -1996,19 +1972,16 @@ class ReqClient:
""" """
Opens a projector for a source. Opens a projector for a source.
:param source_name: Name of the source to open a projector for :param sourceName: Name of the source to open a projector for
:type source_name: str :type sourceName: str
:param monitor_index: Monitor index, use GetMonitorList to obtain index :param monitorIndex: Monitor index, use GetMonitorList to obtain index
:type monitor_index: int :type monitorIndex: int
:param projector_geometry: :param projectorGeometry: Size/Position data for a windowed projector, in Qt Base64 encoded format. Mutually exclusive with monitorIndex
Size/Position data for a windowed projector, in Qt Base64 encoded format. :type projectorGeometry: str
Mutually exclusive with monitorIndex
:type projector_geometry: str
""" """
warn( warn(
"open_source_projector request serves to provide feature parity with 4.x. " "open_source_projector request serves to provide feature parity with 4.x. It is very likely to be changed/deprecated in a future release.",
"It is very likely to be changed/deprecated in a future release.",
DeprecationWarning, DeprecationWarning,
stacklevel=2, stacklevel=2,
) )

View File

@@ -1 +1 @@
version = "1.7.0" version = "1.6.0"

View File

@@ -15,9 +15,9 @@ class TestRequests:
resp = req_cl.get_hot_key_list() resp = req_cl.get_hot_key_list()
obsbasic_hotkey_list = [ obsbasic_hotkey_list = [
"OBSBasic.SelectScene", "OBSBasic.SelectScene",
"OBSBasic.QuickTransition.1", "OBSBasic.SelectScene",
"OBSBasic.QuickTransition.2", "OBSBasic.SelectScene",
"OBSBasic.QuickTransition.3", "OBSBasic.SelectScene",
"OBSBasic.StartStreaming", "OBSBasic.StartStreaming",
"OBSBasic.StopStreaming", "OBSBasic.StopStreaming",
"OBSBasic.ForceStopStreaming", "OBSBasic.ForceStopStreaming",
@@ -25,17 +25,15 @@ class TestRequests:
"OBSBasic.StopRecording", "OBSBasic.StopRecording",
"OBSBasic.PauseRecording", "OBSBasic.PauseRecording",
"OBSBasic.UnpauseRecording", "OBSBasic.UnpauseRecording",
"OBSBasic.SplitFile",
"OBSBasic.StartReplayBuffer", "OBSBasic.StartReplayBuffer",
"OBSBasic.StopReplayBuffer", "OBSBasic.StopReplayBuffer",
"OBSBasic.StartVirtualCam", "OBSBasic.StartVirtualCam",
"OBSBasic.StopVirtualCam", "OBSBasic.StopVirtualCam",
"OBSBasic.EnablePreview", "OBSBasic.EnablePreview",
"OBSBasic.DisablePreview", "OBSBasic.DisablePreview",
"OBSBasic.EnablePreviewProgram",
"OBSBasic.DisablePreviewProgram",
"OBSBasic.ShowContextBar", "OBSBasic.ShowContextBar",
"OBSBasic.HideContextBar", "OBSBasic.HideContextBar",
"OBSBasic.TogglePreviewProgram",
"OBSBasic.Transition", "OBSBasic.Transition",
"OBSBasic.ResetStats", "OBSBasic.ResetStats",
"OBSBasic.Screenshot", "OBSBasic.Screenshot",