2023-07-05 13:44:21 +01:00
|
|
|
import logging
|
|
|
|
|
|
|
|
import obsws_python as obsws
|
|
|
|
|
|
|
|
from . import configuration
|
|
|
|
from .layer import ILayer
|
|
|
|
from .states import OBSWSState
|
|
|
|
from .util import ensure_obsws
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
class OBSWS(ILayer):
|
|
|
|
def __init__(self, duckypad):
|
|
|
|
super().__init__(duckypad)
|
|
|
|
self.request = self.event = None
|
|
|
|
self._state = OBSWSState()
|
|
|
|
|
|
|
|
@property
|
|
|
|
def identifier(self):
|
|
|
|
return type(self).__name__
|
|
|
|
|
|
|
|
@property
|
|
|
|
def state(self):
|
|
|
|
return self._state
|
|
|
|
|
|
|
|
@state.setter
|
|
|
|
def state(self, val):
|
|
|
|
self._state = val
|
|
|
|
|
|
|
|
def reset_states(self):
|
|
|
|
resp = self.request.get_input_mute("Mic/Aux")
|
|
|
|
self.state.mute_mic = resp.input_muted
|
|
|
|
resp = self.request.get_stream_status()
|
|
|
|
self._duckypad.stream.is_live = resp.output_active
|
|
|
|
|
|
|
|
def obs_connect(self):
|
|
|
|
try:
|
|
|
|
conn = configuration.get("obsws")
|
|
|
|
assert conn is not None, "expected configuration for obs"
|
|
|
|
self.request = obsws.ReqClient(**conn)
|
|
|
|
self.reset_states()
|
|
|
|
self.event = obsws.EventClient(**conn)
|
|
|
|
self.event.callback.register(
|
|
|
|
[
|
|
|
|
self.on_stream_state_changed,
|
|
|
|
self.on_input_mute_state_changed,
|
|
|
|
self.on_current_program_scene_changed,
|
2023-07-08 20:43:30 +01:00
|
|
|
self.on_exit_started,
|
2023-07-05 13:44:21 +01:00
|
|
|
]
|
|
|
|
)
|
|
|
|
except (ConnectionRefusedError, TimeoutError) as e:
|
|
|
|
self.logger.error(f"{type(e).__name__}: {e}")
|
|
|
|
raise
|
|
|
|
|
|
|
|
def on_current_program_scene_changed(self, data):
|
|
|
|
self._duckypad.stream.current_scene = data.scene_name
|
|
|
|
self.logger.info(f"scene switched to {self._duckypad.stream.current_scene}")
|
|
|
|
if self._duckypad.stream.current_scene in ("START", "BRB", "END"):
|
|
|
|
self.mute_mic_state(True)
|
|
|
|
|
|
|
|
def on_input_mute_state_changed(self, data):
|
|
|
|
if data.input_name == "Mic/Aux":
|
|
|
|
self.state.mute_mic = data.input_muted
|
|
|
|
self.logger.info(f"mic was {'muted' if self.state.mute_mic else 'unmuted'}")
|
|
|
|
|
|
|
|
def on_stream_state_changed(self, data):
|
|
|
|
self._duckypad.stream.is_live = data.output_active
|
|
|
|
self.logger.info(
|
|
|
|
f"stream is {'live' if self._duckypad.stream.is_live else 'offline'}"
|
|
|
|
)
|
|
|
|
|
2023-07-08 20:43:30 +01:00
|
|
|
def on_exit_started(self, _):
|
|
|
|
self.event.unsubscribe()
|
|
|
|
|
2023-07-05 13:44:21 +01:00
|
|
|
@ensure_obsws
|
|
|
|
def call(self, fn_name, *args):
|
|
|
|
fn = getattr(self.request, fn_name)
|
|
|
|
resp = fn(*args)
|
|
|
|
return resp
|
|
|
|
|
|
|
|
def start(self):
|
|
|
|
self.call("set_current_program_scene", "START")
|
|
|
|
|
|
|
|
def brb(self):
|
|
|
|
self.call("set_current_program_scene", "BRB")
|
|
|
|
|
|
|
|
def end(self):
|
|
|
|
self.call("set_current_program_scene", "END")
|
|
|
|
|
|
|
|
def live(self):
|
|
|
|
self.call("set_current_program_scene", "LIVE")
|
|
|
|
|
|
|
|
def mute_mic_state(self, val):
|
|
|
|
self.call("set_input_mute", "Mic/Aux", val)
|
|
|
|
|
|
|
|
def toggle_mute_mic(self):
|
|
|
|
self.call("toggle_input_mute", "Mic/Aux")
|
|
|
|
|
|
|
|
def toggle_stream(self):
|
|
|
|
self.call("toggle_stream")
|