From 9a9517b6f4fffe94d03b15ddaecb49a41ae452b9 Mon Sep 17 00:00:00 2001 From: Core447 Date: Tue, 26 Mar 2024 15:30:17 +0100 Subject: [PATCH] Add Change Scene action --- actions/SwitchScene/SwitchScene.py | 99 +++++++++++++++++++++++++++++ assets/transition_slide.png | Bin 0 -> 1020 bytes backend/backend.py | 12 ++++ locales/en_US.json | 4 +- main.py | 9 +++ 5 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 actions/SwitchScene/SwitchScene.py create mode 100644 assets/transition_slide.png diff --git a/actions/SwitchScene/SwitchScene.py b/actions/SwitchScene/SwitchScene.py new file mode 100644 index 0000000..61be043 --- /dev/null +++ b/actions/SwitchScene/SwitchScene.py @@ -0,0 +1,99 @@ +from plugins.dev_core447_OBSPlugin.OBSActionBase import OBSActionBase +from src.backend.DeckManagement.DeckController import DeckController +from src.backend.PageManagement.Page import Page +from src.backend.PluginManager.PluginBase import PluginBase +from GtkHelper.GtkHelper import ComboRow + +import os + +# Import gtk modules +import gi +gi.require_version("Gtk", "4.0") +gi.require_version("Adw", "1") +from gi.repository import Gtk, Adw + +class SwitchScene(OBSActionBase): + def __init__(self, action_id: str, action_name: str, + deck_controller: "DeckController", page: Page, coords: str, plugin_base: PluginBase): + super().__init__(action_id=action_id, action_name=action_name, + deck_controller=deck_controller, page=page, coords=coords, plugin_base=plugin_base) + + def on_ready(self): + # Connect to obs if not connected + if not self.plugin_base.backend.get_connected(): # self.plugin_base.obs.connect_to(host="localhost", port=4444, timeout=3, legacy=False) + self.reconnect_obs() + + media_path = os.path.join(self.plugin_base.PATH, "assets", "transition_slide.png") + self.set_media(media_path=media_path, size=0.75) + + def get_config_rows(self) -> list: + super_rows = super().get_config_rows() + + self.scene_model = Gtk.StringList() + self.scene_row = Adw.ComboRow(model=self.scene_model, title=self.plugin_base.lm.get("actions.switch.scene-row.label")) + + self.connect_signals() + + self.load_scene_model() + self.load_configs() + + super_rows.append(self.scene_row) + return super_rows + + def connect_signals(self): + self.scene_row.connect("notify::selected", self.on_change_scene) + + def disconnect_signals(self): + try: + self.scene_row.disconnect_by_func(self.on_change_scene) + except TypeError as e: + pass + + def load_scene_model(self): + self.disconnect_signals() + # Clear model + while self.scene_model.get_n_items() > 0: + self.scene_model.remove(0) + + # Load model + if self.plugin_base.backend.get_connected(): + scenes = self.plugin_base.backend.get_scene_names() + if scenes is None: + return + for scene in scenes: + self.scene_model.append(scene) + + self.connect_signals() + + def load_configs(self): + self.load_selected_device() + + def load_selected_device(self): + self.disconnect_signals() + settings = self.get_settings() + for i, scene_name in enumerate(self.scene_model): + if scene_name.get_string() == settings.get("scene"): + self.scene_row.set_selected(i) + self.connect_signals() + return + + self.scene_row.set_selected(Gtk.INVALID_LIST_POSITION) + self.connect_signals() + + def on_change_scene(self, *args): + settings = self.get_settings() + selected_index = self.scene_row.get_selected() + settings["scene"] = self.scene_model[selected_index].get_string() + self.set_settings(settings) + + def on_key_down(self): + scene_name = self.get_settings().get("scene") + if scene_name in [None, ""]: + return + self.plugin_base.backend.switch_to_scene(scene_name) + + def reconnect_obs(self): + super().reconnect_obs() + if hasattr(self, "scene_model"): + self.load_scene_model() + self.load_configs() \ No newline at end of file diff --git a/assets/transition_slide.png b/assets/transition_slide.png new file mode 100644 index 0000000000000000000000000000000000000000..054d0b1f8cd186708a357ef7a23515bc79c752a5 GIT binary patch literal 1020 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7Ro>U~I{Bb`J1#c2+1T%1_J8No8Qr zm{>c}*5j~)%+dJhrAoSdWfLAvSZEdbfxB=`sD@K(fcBPG2}Li(O)@=#Vq{paH#N(5 zhq8;O$I8aAI(}e2a`T|)MOUvs@j)4aj}I2w-@99VXD{=gvs%Gt=dmovnl{l>wKb+L zlw+S#gT^6=<1I&gYW+kme~^j){^8?Sy>pxQod0Wi$m?KAgTI2G!QBlV<{jx~x^q9< z6}C)OZT&H);>-eWA^W1(vY)-hCll?@_ek74V^i1?p;5Z=&e1hFD~?<~V(5BRfCwZ%d zv-ZevuW)RA^5fwD2j$z-3bQWxa;Y}n6TkgWg0X40!|KG__m6M8YsJWP{=n30AFt0k z@J9V*Z=aYo6Wg}N?$>>4?-{3CAGk1CPjZqnYsRl`*9U)l_G$9-+++HiotOW%c8(oG z@} z5zYdS$YNj&UI$@DCym(^Ktc8rPhVH|7tB(;hJvp?d6ffW@~5YZV@SoVw|D&YoC77= zK7P->!s0E^Ik7W=dupC*xpLEl4MIzzCnWeNZDlrHbACzEgMXIazsa<}{>i)Zt>yjN zFJ@})OhBW-AU3^Je8=y;CCr}8p06i`WyO6`%T&tLd3or}JMo(d-Cv8ljrZ@?-~D^$ z?(=*0&fGnJSGE1+Upu$XuDAPBdZahT{H9CO*JACt`@@U)`&4+9>vY;D@kz(XSO2}^ z^?duJ^mn^8sV~qrY~Fo{KkmqH*!V-k;Mm=LWLp*S-AX+RP`Emt_B7 zR^zU0`zL~5v@*9o@|~9@c5}^-yI0O!%aU{KUN=8_@y~9iil_E`X<^08oA=pmU-tVw z=gs{R4h&2U3@i+c91KhX3@i!^91aWu4Ganlj3h}s_#UnG<7S8`yV}m*kC|TkGOzdC zT9qZ{^6{{9DsTTjPS)mr z{@-lL%)6de{u>%M@0vZo;_scNXaE0bzj3#-`myTa#iM`wWMgZtKKt`x-|qP?7JGj0 zc>3_J;kEy~?d9R;H$FJu<>t8F;7=Nmvv4FO#o#!!7cy* literal 0 HcmV?d00001 diff --git a/backend/backend.py b/backend/backend.py index c4f489e..8fc9c48 100644 --- a/backend/backend.py +++ b/backend/backend.py @@ -45,6 +45,18 @@ class Backend(BackendBase): def connect_to(self, *args, **kwargs): self.OBSController.connect_to(*args, **kwargs) + + def get_controller(self) -> OBSController: + """ + Calling methods on the returned controller will raise a circular reference error from Pyro + """ + return self.OBSController + + def get_scene_names(self) -> list[str]: + return self.OBSController.get_scenes() + + def switch_to_scene(self, scene:str): + self.OBSController.switch_to_scene(scene) print("init backend") backend = Backend() diff --git a/locales/en_US.json b/locales/en_US.json index 60dd084..372a40d 100644 --- a/locales/en_US.json +++ b/locales/en_US.json @@ -6,5 +6,7 @@ "actions.base.status.connected": "Successfully connected to OBS.", "actions.base.ip.label": "IP:", "actions.base.port.label": "Port:", - "actions.base.password.label": "Password:" + "actions.base.password.label": "Password:", + "actions.switch.scene-row.label": "Scene:", + "actions.switch-scene.name": "Switch Scene" } \ No newline at end of file diff --git a/main.py b/main.py index 9f01ab3..05c9641 100644 --- a/main.py +++ b/main.py @@ -21,6 +21,7 @@ from OBSActionBase import OBSActionBase from actions.ToggleRecord.ToggleRecord import ToggleRecord from actions.RecPlayPause.RecPlayPause import RecPlayPause +from actions.SwitchScene.SwitchScene import SwitchScene class OBS(PluginBase): def __init__(self): @@ -58,5 +59,13 @@ class OBS(PluginBase): ) self.add_action_holder(rec_play_pause_action_holder) + switch_scene_action_holder = ActionHolder( + plugin_base=self, + action_base=SwitchScene, + action_id="dev_core447_OBSPlugin::SwitchScene", + action_name=self.lm.get("actions.switch-scene.name") + ) + self.add_action_holder(switch_scene_action_holder) + # Load custom css self.add_css_stylesheet(os.path.join(self.PATH, "style.css")) \ No newline at end of file