Add toggle filter action
This commit is contained in:
parent
bf3bf6a070
commit
9c0613e416
|
@ -0,0 +1,217 @@
|
|||
from plugins.com_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 threading
|
||||
|
||||
# Import gtk modules
|
||||
import gi
|
||||
gi.require_version("Gtk", "4.0")
|
||||
gi.require_version("Adw", "1")
|
||||
from gi.repository import Gtk, Adw
|
||||
|
||||
class ToggleFilter(OBSActionBase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.current_state = -1
|
||||
|
||||
def on_ready(self):
|
||||
self.current_state = -1
|
||||
# Connect to obs if not connected
|
||||
if self.plugin_base.backend is not None:
|
||||
if not self.plugin_base.get_connected():
|
||||
self.reconnect_obs()
|
||||
|
||||
# Show current scene filter status
|
||||
threading.Thread(target=self.show_current_filter_status, daemon=True, name="show_current_filter_status").start()
|
||||
|
||||
def show_current_filter_status(self, new_paused = False):
|
||||
if self.plugin_base.backend is None:
|
||||
self.current_state = -1
|
||||
self.show_error()
|
||||
return
|
||||
if not self.plugin_base.backend.get_connected():
|
||||
self.current_state = -1
|
||||
self.show_error()
|
||||
return
|
||||
if not self.get_settings().get("filter"):
|
||||
self.current_state = -1
|
||||
self.show_error()
|
||||
return
|
||||
|
||||
status = self.plugin_base.backend.get_source_filter(self.get_settings().get("scene"), self.get_settings().get("filter"))
|
||||
if status is None:
|
||||
self.current_state = -1
|
||||
self.show_error()
|
||||
return
|
||||
if status["filterEnabled"]:
|
||||
self.show_for_state(1)
|
||||
else:
|
||||
self.show_for_state(0)
|
||||
|
||||
def show_for_state(self, state: int):
|
||||
"""
|
||||
0: Filter disabled
|
||||
1: Filter enabled
|
||||
"""
|
||||
if state == self.current_state:
|
||||
return
|
||||
|
||||
self.current_state = state
|
||||
image = "scene_item_disabled.png"
|
||||
|
||||
if state == -1:
|
||||
self.show_error()
|
||||
else:
|
||||
self.hide_error()
|
||||
|
||||
if state == 0:
|
||||
image = "scene_item_disabled.png"
|
||||
elif state == 1:
|
||||
image = "scene_item_enabled.png"
|
||||
|
||||
self.set_media(media_path=os.path.join(self.plugin_base.PATH, "assets", image), 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.filter_model = Gtk.StringList()
|
||||
self.filter_row = Adw.ComboRow(model=self.filter_model, title=self.plugin_base.lm.get("actions.toggle-scene-filter-enabled-row.label"))
|
||||
|
||||
self.connect_signals()
|
||||
|
||||
self.load_filter_model()
|
||||
self.load_configs()
|
||||
|
||||
super_rows.append(self.scene_row)
|
||||
super_rows.append(self.filter_row)
|
||||
return super_rows
|
||||
|
||||
def connect_signals(self):
|
||||
self.scene_row.connect("notify::selected", self.on_scene_selected)
|
||||
self.filter_row.connect("notify::selected", self.on_filter_selected)
|
||||
|
||||
def disconnect_signals(self):
|
||||
try:
|
||||
self.scene_row.disconnect_by_func(self.on_scene_selected)
|
||||
self.filter_row.disconnect_by_func(self.on_filter_selected)
|
||||
except TypeError as e:
|
||||
pass
|
||||
|
||||
def load_filter_model(self):
|
||||
self.disconnect_signals()
|
||||
# Clear model
|
||||
while self.scene_model.get_n_items() > 0:
|
||||
self.scene_model.remove(0)
|
||||
while self.filter_model.get_n_items() > 0:
|
||||
self.filter_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)
|
||||
# Ensure selection is made if there's only one scene
|
||||
if len(scenes) == 1:
|
||||
self.get_settings()["scene"] = scenes[0]
|
||||
self.scene_row.set_selected(0)
|
||||
self.load_filters_for_scene(scenes[0])
|
||||
|
||||
self.connect_signals()
|
||||
|
||||
def load_filters_for_scene(self, scene_name):
|
||||
# Clear filters model
|
||||
while self.filter_model.get_n_items() > 0:
|
||||
self.filter_model.remove(0)
|
||||
|
||||
if self.plugin_base.backend.get_connected():
|
||||
filters = self.plugin_base.backend.get_source_filters(scene_name)
|
||||
if filters is None:
|
||||
self.show_error()
|
||||
return
|
||||
for item in filters:
|
||||
self.filter_model.append(item.get("filterName"))
|
||||
# Ensure selection is made if there's only one item
|
||||
if len(filters) == 1:
|
||||
self.filter_row.set_selected(0)
|
||||
|
||||
def load_configs(self):
|
||||
self.load_config_values()
|
||||
|
||||
def load_config_values(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.load_filters_for_scene(scene_name.get_string())
|
||||
for j, item_name in enumerate(self.filter_model):
|
||||
if item_name.get_string() == settings.get("filter"):
|
||||
self.filter_row.set_selected(j)
|
||||
break
|
||||
self.connect_signals()
|
||||
return
|
||||
|
||||
self.scene_row.set_selected(Gtk.INVALID_LIST_POSITION)
|
||||
self.filter_row.set_selected(Gtk.INVALID_LIST_POSITION)
|
||||
self.connect_signals()
|
||||
|
||||
def on_scene_selected(self, *args):
|
||||
settings = self.get_settings()
|
||||
selected_index_scene = self.scene_row.get_selected()
|
||||
if selected_index_scene != Gtk.INVALID_LIST_POSITION:
|
||||
scene_name = self.scene_model[selected_index_scene].get_string()
|
||||
settings["scene"] = scene_name
|
||||
self.set_settings(settings)
|
||||
self.load_filters_for_scene(scene_name)
|
||||
|
||||
def on_filter_selected(self, *args):
|
||||
settings = self.get_settings()
|
||||
selected_index_item = self.filter_row.get_selected()
|
||||
if selected_index_item != Gtk.INVALID_LIST_POSITION:
|
||||
settings["filter"] = self.filter_model[selected_index_item].get_string()
|
||||
self.set_settings(settings)
|
||||
|
||||
def on_key_down(self):
|
||||
if self.plugin_base.backend is None:
|
||||
self.current_state = -1
|
||||
self.show_error()
|
||||
self.set_media(media_path=os.path.join(self.plugin_base.PATH, "assets", "error.png"))
|
||||
return
|
||||
if not self.plugin_base.backend.get_connected():
|
||||
self.current_state = -1
|
||||
self.show_error()
|
||||
self.set_media(media_path=os.path.join(self.plugin_base.PATH, "assets", "error.png"))
|
||||
return
|
||||
|
||||
scene_name = self.get_settings().get("scene")
|
||||
filter_name = self.get_settings().get("filter")
|
||||
if scene_name in [None, ""]:
|
||||
self.set_media(media_path=os.path.join(self.plugin_base.PATH, "assets", "error.png"))
|
||||
return
|
||||
if filter_name in [None, ""]:
|
||||
self.set_media(media_path=os.path.join(self.plugin_base.PATH, "assets", "error.png"))
|
||||
return
|
||||
|
||||
if self.current_state == 0:
|
||||
self.plugin_base.backend.set_source_filter_enabled(scene_name, filter_name, True)
|
||||
else:
|
||||
self.plugin_base.backend.set_source_filter_enabled(scene_name, filter_name, False)
|
||||
self.on_tick()
|
||||
|
||||
def on_tick(self):
|
||||
self.show_current_filter_status()
|
||||
|
||||
def reconnect_obs(self):
|
||||
super().reconnect_obs()
|
||||
if hasattr(self, "scene_model") and hasattr(self, "filter_model"):
|
||||
self.load_filter_model()
|
||||
self.load_configs()
|
|
@ -335,3 +335,23 @@ class OBSController(obsws):
|
|||
self.call(requests.SetCurrentSceneCollection(sceneCollectionName=sceneCollectionName))
|
||||
except (obswebsocket.exceptions.MessageTimeout, websocket._exceptions.WebSocketConnectionClosedException, KeyError) as e:
|
||||
log.error(e)
|
||||
|
||||
def get_source_filters(self, sourceName: str) -> list:
|
||||
try:
|
||||
source_filters = self.call(requests.GetSourceFilterList(sourceName=sourceName)).getfilters()
|
||||
return source_filters
|
||||
except (obswebsocket.exceptions.MessageTimeout, websocket._exceptions.WebSocketConnectionClosedException, KeyError) as e:
|
||||
log.error(e)
|
||||
|
||||
def set_source_filter_enabled(self, sourceName: str, filterName: str, enabled: bool) -> None:
|
||||
try:
|
||||
self.call(requests.SetSourceFilterEnabled(sourceName=sourceName, filterName=filterName, filterEnabled=enabled))
|
||||
except (obswebsocket.exceptions.MessageTimeout, websocket._exceptions.WebSocketConnectionClosedException, KeyError) as e:
|
||||
log.error(e)
|
||||
|
||||
def get_source_filter(self, sourceName: str, filterName: str) -> None:
|
||||
try:
|
||||
source_filter = self.call(requests.GetSourceFilter(sourceName=sourceName, filterName=filterName)).datain
|
||||
return source_filter
|
||||
except (obswebsocket.exceptions.MessageTimeout, websocket._exceptions.WebSocketConnectionClosedException, KeyError) as e:
|
||||
log.error(e)
|
|
@ -185,4 +185,13 @@ class Backend(BackendBase):
|
|||
def set_current_scene_collection(self, sceneCollectionName: str):
|
||||
return self.OBSController.set_current_scene_collection(sceneCollectionName)
|
||||
|
||||
def get_source_filters(self, sourceName: str) -> list:
|
||||
return self.OBSController.get_source_filters(sourceName)
|
||||
|
||||
def set_source_filter_enabled(self, sourceName: str, filterName: str, enabled: bool):
|
||||
self.OBSController.set_source_filter_enabled(sourceName, filterName, enabled)
|
||||
|
||||
def get_source_filter(self, sourceName: str, filterName: str) -> None:
|
||||
return self.OBSController.get_source_filter(sourceName, filterName)
|
||||
|
||||
backend = Backend()
|
|
@ -31,6 +31,9 @@
|
|||
"actions.base.status.no-connection": "Could not connect to OBS.",
|
||||
"actions.base.status.connected": "Successfully connected to OBS.",
|
||||
|
||||
"actions.toggle-scene-filter-enabled-row.label": "Filter:",
|
||||
"actions.toggle-filter.name": "Toggle Filter",
|
||||
|
||||
"actions.base.ip.label": "IP:",
|
||||
"actions.base.port.label": "Port:",
|
||||
"actions.base.password.label": "Password:"
|
||||
|
|
14
main.py
14
main.py
|
@ -39,6 +39,7 @@ from actions.InputDial.InputDial import InputDial
|
|||
|
||||
from actions.SwitchScene.SwitchScene import SwitchScene
|
||||
from actions.ToggleSceneItemEnabled.ToggleSceneItemEnabled import ToggleSceneItemEnabled
|
||||
from actions.ToggleFilter.ToggleFilter import ToggleFilter
|
||||
from actions.SwitchSceneCollection.SwitchSceneCollection import SwitchSceneCollection
|
||||
|
||||
class OBS(PluginBase):
|
||||
|
@ -239,6 +240,19 @@ class OBS(PluginBase):
|
|||
)
|
||||
self.add_action_holder(switch_scene_collection_action_holder)
|
||||
|
||||
toggle_filter_holder = ActionHolder(
|
||||
plugin_base=self,
|
||||
action_base=ToggleFilter,
|
||||
action_id_suffix="ToggleSceneFilter",
|
||||
action_name=self.lm.get("actions.toggle-filter.name"),
|
||||
action_support={
|
||||
Input.Key: ActionInputSupport.SUPPORTED,
|
||||
Input.Dial: ActionInputSupport.SUPPORTED,
|
||||
Input.Touchscreen: ActionInputSupport.SUPPORTED,
|
||||
}
|
||||
)
|
||||
self.add_action_holder(toggle_filter_holder)
|
||||
|
||||
# Load custom css
|
||||
self.add_css_stylesheet(os.path.join(self.PATH, "style.css"))
|
||||
|
||||
|
|
Loading…
Reference in New Issue