diff --git a/actions/ElgatoKeyLight/Core.py b/actions/ElgatoKeyLight/Core.py index 3e9f548..ca799b6 100644 --- a/actions/ElgatoKeyLight/Core.py +++ b/actions/ElgatoKeyLight/Core.py @@ -1,24 +1,29 @@ # Import StreamController modules +from gi.repository import Gtk, Adw +from ipaddress import ip_address from src.backend.PluginManager.ActionBase import ActionBase import os import gi import threading import time +import json +import requests gi.require_version("Gtk", "4.0") gi.require_version("Adw", "1") -import requests -from gi.repository import Gtk, Adw - class Core(ActionBase): + + data = {} + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.lm = self.plugin_base.locale_manager self.plugin_base.backend.on_light_state_changed.subscribe(self.update_icon) + self.plugin_base.backend.on_device_added.subscribe(self.update_device_list) self.supported_lights = { "ElgatoKeyLight": { @@ -27,6 +32,8 @@ def __init__(self, *args, **kwargs): "max_brightness": 100, "min_temperature": 143, "max_temperature": 344, + "min_k_temperature": 2900, + "max_k_temperature": 7000, } } @@ -37,6 +44,85 @@ def __init__(self, *args, **kwargs): self._last_request_number = 0 self._running_requests = 0 + def set_property(self, key, value): + ip_address = self.get_settings().get("ip_address") + + if not ip_address: + print("[Error]: No IP address configured") + return + + if ip_address not in Core.data: + self._add_data_dictonary(ip_address) + + if ip_address not in Core.data or Core.data[ip_address] is None: + print(f"[Error]: Failed to get data for {ip_address}") + return + + match key: + case "brightness": + self.plugin_base.backend.on_brightness_changed.emit() + Core.data[ip_address]["lights"][0][key] = value + + case "temperature": + self.plugin_base.backend.on_temperature_changed.emit() + Core.data[ip_address]["lights"][0][key] = value + case "on": + Core.data[ip_address]["lights"][0][key] = ( + 1 - Core.data[ip_address]["lights"][0][key] + ) + case _: + print("No actions passed") + + self._async_send() + + def _async_send(self): + threading.Thread( + target=self._send_to_api, daemon=True, name="_send_to_api" + ).start() + + def _send_to_api(self): + ip_address = self.get_settings().get("ip_address") + + if not ip_address: + print("[Error]: No IP address configured") + return + + if ip_address not in Core.data or Core.data[ip_address] is None: + print(f"[Error]: No data available for {ip_address}") + return + + payload = Core.data[ip_address].copy() + url = f"http://{ip_address}:9123/elgato/lights" + try: + r = requests.put(url, json=payload, timeout=10) + # self.update_icon() + self.plugin_base.backend.on_light_state_changed.emit() + + except Exception as e: + print( + f"[Error]: Couldn't send update to {ip_address}, request_body={payload}, error={e}" + ) + + def _get_from_api(self, ip): + url = f"http://{ip}:9123/elgato/lights" + try: + r = requests.get(url, timeout=10) + return r.json() + except: + print("[Error]: Couldnt Sent update") + return None + + def _add_data_dictonary(self, ip): + if ip in Core.data: + return 0 + Core.data[ip] = self._get_from_api(ip) + return None + + def _get_data_dictonary(self, ip): + if ip not in Core.data: + return {} + return Core.data[ip] + @property def running_requests(self): return self._running_requests @@ -56,133 +142,236 @@ def is_connected(self, value): self.set_banner_connection_info() @property - def current_brightness(self): - settings = self.plugin_base.get_settings() - return settings.get("brightness") or self.supported_lights["ElgatoKeyLight"]["min_brightness"] + def current_status(self): + ip = self.get_settings().get("ip_address") + if not ip: + return 0 + if ip not in Core.data: + self._add_data_dictonary(ip) + if ip not in Core.data or Core.data[ip] is None: + return 0 + cur_status = Core.data[ip]["lights"][0]["on"] + return cur_status or 0 - @current_brightness.setter - def current_brightness(self, value): - settings = self.plugin_base.get_settings() + @property + def current_brightness(self): + ip = self.get_settings().get("ip_address") + if not ip: + return 1 + if ip not in Core.data: + self._add_data_dictonary(ip) + if ip not in Core.data or Core.data[ip] is None: + return 1 + cur_status = Core.data[ip]["lights"][0]["brightness"] + return cur_status or 1 - _current_brightness = max(self.supported_lights["ElgatoKeyLight"]["min_brightness"], min(value, self.supported_lights["ElgatoKeyLight"]["max_brightness"])) + @property + def current_temperature(self): + ip = self.get_settings().get("ip_address") + if not ip: + return 143 + if ip not in Core.data: + self._add_data_dictonary(ip) + if ip not in Core.data or Core.data[ip] is None: + return 143 + cur_status = Core.data[ip]["lights"][0]["temperature"] + return cur_status or 143 - settings["brightness"] = int(_current_brightness) + @property + def current_k_temperature(self): + real_min, real_max = ( + self.supported_lights["ElgatoKeyLight"]["min_temperature"], + self.supported_lights["ElgatoKeyLight"]["max_temperature"], + ) + shown_min, shown_max = ( + self.supported_lights["ElgatoKeyLight"]["max_k_temperature"], + self.supported_lights["ElgatoKeyLight"]["min_k_temperature"], + ) + real_value = self.current_temperature + return ((real_value - real_min) / (real_max - real_min)) * ( + shown_max - shown_min + ) + shown_min - self.plugin_base.set_settings(settings) - self.plugin_base.backend.on_brightness_changed.emit() - threading.Thread(target=self.update_light, daemon=True, name="update_light").start() + def on_ready(self) -> None: + self.load_default_config() + self.update_icon() - @property - def current_temperature(self): - settings = self.plugin_base.get_settings() - return settings.get("temperature") or self.supported_lights["ElgatoKeyLight"]["min_temperature"] + def update_device_list(self): + if not hasattr(self, "registered_devices"): + return - @current_temperature.setter - def current_temperature(self, value): - settings = self.plugin_base.get_settings() + print(self.registered_devices) + self.registered_devices.splice(0, self.registered_devices.get_n_items()) + for device in self.plugin_base.backend.get_devices(): + self.registered_devices.append(str(device)) - _current_temperature = max(self.supported_lights["ElgatoKeyLight"]["min_temperature"], min(value, self.supported_lights["ElgatoKeyLight"]["max_temperature"])) + def get_config_rows(self) -> list: + self.add_new_ip_entry = Adw.EntryRow( + title=self.plugin_base.locale_manager.get("actions.add_ip_entry.title"), + input_purpose=Gtk.InputPurpose.FREE_FORM, + ) + self.add_light_button = Adw.ButtonRow( + title=self.plugin_base.locale_manager.get("actions.add_light_button.title") + ) - settings["temperature"] = int(_current_temperature) + # Disable button until we have a working connection + self.add_light_button - self.plugin_base.set_settings(settings) - self.plugin_base.backend.on_temperature_changed.emit() - threading.Thread(target=self.update_light, daemon=True, name="update_light").start() + self.add_light_button.connect("activated", self.on_ip_address_added) - def on_ready(self) -> None: - self.update_icon() + self.registered_devices = Gtk.StringList() + for device in self.plugin_base.backend.get_devices(): + self.registered_devices.append(str(device)) - def get_config_rows(self) -> list: - self.ip_entry = Adw.EntryRow(title=self.plugin_base.locale_manager.get("actions.ip_entry.title"), input_purpose=Gtk.InputPurpose.FREE_FORM) - self.ip_entry.connect("notify::text", self.on_ip_address_changed) + self.device_list = Adw.ComboRow( + title=self.plugin_base.locale_manager.get("actions.device_list.title"), + model=self.registered_devices, + ) + self.device_list.connect("notify::selected", self.set_ip_address) self.connection_banner = Adw.Banner() self.connection_banner.set_revealed(True) self.banner_is_visible = True + self.load_default_config() - return [self.ip_entry, self.connection_banner] + return [ + self.add_new_ip_entry, + self.add_light_button, + self.device_list, + self.connection_banner, + ] def set_banner_connection_info(self) -> None: if not self.banner_is_visible: return if self.running_requests > 0: - self.connection_banner.set_title(self.plugin_base.locale_manager.get("actions.connection_banner.loading")) + self.connection_banner.set_title( + self.plugin_base.locale_manager.get("actions.connection_banner.loading") + ) elif self.is_connected: - self.connection_banner.set_title(self.plugin_base.locale_manager.get("actions.connection_banner.connected")) + self.connection_banner.set_title( + self.plugin_base.locale_manager.get( + "actions.connection_banner.connected" + ) + ) else: - self.connection_banner.set_title(self.plugin_base.locale_manager.get("actions.connection_banner.not_connected")) + self.connection_banner.set_title( + self.plugin_base.locale_manager.get( + "actions.connection_banner.not_connected" + ) + ) + + def toggle_light(self): + self.set_property("on", None) - def modify_brightness(self, amount: int): - settings = self.plugin_base.get_settings() - new_brightness = int(settings.get("brightness") or 0) + amount - self.current_brightness = new_brightness + def load_default_config(self): + # Fallback for old global settings + global_settings = self.plugin_base.get_settings() + migrate_global_address_to_local_address = global_settings.get("ip_address") - def modify_temperature(self, amount: int): - settings = self.plugin_base.get_settings() - new_temperature = int(settings.get("temperature") or 0) + amount - self.current_temperature = new_temperature + settings = self.get_settings() - def toggle_light(self): - settings = self.plugin_base.get_settings() + if migrate_global_address_to_local_address: + settings["ip_address"] = migrate_global_address_to_local_address + del global_settings["ip_address"] + self.plugin_base.set_settings(global_settings) + print("Migrating global settings") + self.set_settings(settings) - if settings.get("light_active") == 0: - settings["light_active"] = 1 - else: - settings["light_active"] = 0 + saved_ip_address = settings.get("ip_address") - self.plugin_base.set_settings(settings) - self.plugin_base.backend.on_light_state_changed.emit() - self.update_light() + if saved_ip_address: + print("Saved ip address in config ", saved_ip_address) - def load_default_config(self): - settings = self.plugin_base.get_settings() - ip_address = settings.get("ip_address") + self.plugin_base.backend.register_new_device( + saved_ip_address, saved_ip_address + ) + self.preselect_device_by_ip(saved_ip_address) + self.ip_address = saved_ip_address - if ip_address: - self.ip_entry.set_text(ip_address) + def preselect_device_by_ip(self, ip): + if not hasattr(self, "device_list"): + return + base_devices = self.plugin_base.backend.get_devices() + for index, key in enumerate(base_devices): + if base_devices[key].ip_address == ip: + self.device_list.set_selected(index) + break + + def on_ip_address_added(self, entry): + new_ip_address = self.add_new_ip_entry.get_text() + + # Validate IP address + try: + ip_address(new_ip_address) + except ValueError: + print(f"[Error]: Invalid IP address: {new_ip_address}") + return + + self.plugin_base.backend.register_new_device(new_ip_address, new_ip_address) + self.device_list.set_selected(self.registered_devices.get_n_items() - 1) + self.set_ip_address(self.device_list) + + def set_ip_address(self, entry: Adw.EntryRow, *args): + settings = self.get_settings() + + ip_by_index = list(self.plugin_base.backend.get_devices().values())[ + entry.get_selected() + ].ip_address - def on_ip_address_changed(self, entry: Adw.EntryRow, text): - settings = self.plugin_base.get_settings() - settings["ip_address"] = entry.get_text() - self.plugin_base.set_settings(settings) - threading.Thread(target=self.update_light, daemon=True, name="update_light").start() + settings["ip_address"] = ip_by_index + + self.ip_address = ip_by_index + + self.set_settings(settings) + + self._add_data_dictonary(ip_by_index) + + # threading.Thread(target=self.update_light, daemon=True, + # name="update_light").start() def update_icon(self): - settings = self.plugin_base.get_settings() - if settings.get("light_active") == 1: - icon_path = os.path.join(self.plugin_base.PATH, "assets", "ring_light_on.png") + if self.current_status == 1: + icon_path = os.path.join( + self.plugin_base.PATH, "assets", "ring_light_on.png" + ) else: - icon_path = os.path.join(self.plugin_base.PATH, "assets", "ring_light_off.png") + icon_path = os.path.join( + self.plugin_base.PATH, "assets", "ring_light_off.png" + ) self.set_media(media_path=icon_path, size=0.75) - # TODO: Fetch data from light (singleton) + def get_light_data(self): - url = "" + ip_address = self.get_settings().get("ip_address") + url = f"http://{ip_address}:9123/elgato/lights" try: r = requests.get(url) - return r.text + return json.loads(r.text)["lights"][0] except: return "Failed to get lights" + def update_light(self, _is_light_active, _brightness, _temperature): - def update_light(self): - settings = self.plugin_base.get_settings() - ip_address = settings.get("ip_address") + ip_address = self.get_settings().get("ip_address") url = f"http://{ip_address}:9123/elgato/lights" + if _is_light_active is None: + _is_light_active = self.current_status + data = { - "numberOfLights": 1, - "lights": [ + "numberOfLights": 1, + "lights": [ { - "on": settings.get("light_active"), - "brightness": self.current_brightness, - "temperature": self.current_temperature + "on": _is_light_active, + "brightness": _brightness or self.current_brightness, + "temperature": _temperature or self.current_temperature, } - ] + ], } request_number = self._last_request_number + 1 diff --git a/actions/ElgatoKeyLight/Dial.py b/actions/ElgatoKeyLight/Dial.py index bfc83ae..e5e58d8 100644 --- a/actions/ElgatoKeyLight/Dial.py +++ b/actions/ElgatoKeyLight/Dial.py @@ -1,4 +1,5 @@ # Import StreamController modules +from gi.repository import Gtk, Adw from src.backend.DeckManagement.InputIdentifier import Input, InputEvent from enum import Enum @@ -6,18 +7,21 @@ # Import gtk modules - used for the config rows import gi + gi.require_version("Gtk", "4.0") gi.require_version("Adw", "1") -from gi.repository import Gtk, Adw + class DialProperty(Enum): Brightness = 0 Temperature = 1 + class ToggleProperty(Enum): ToggleLightOnOff = 0 ChangeBrightnessTemperature = 1 + class Dial(Core): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -26,7 +30,6 @@ def __init__(self, *args, **kwargs): self.current_dial_selection = 0 self.current_toggle_selection = 0 - def on_ready(self) -> None: self.load_local_saved_config() self.update_icon() @@ -35,13 +38,18 @@ def on_ready(self) -> None: self.plugin_base.backend.on_brightness_changed.subscribe(self.update_labels) self.plugin_base.backend.on_temperature_changed.subscribe(self.update_labels) - def get_config_rows(self) -> list: parent_entries = super().get_config_rows() self.toggle_property_selection = Gtk.StringList() - self.toggle_property_selection.append(self.plugin_base.locale_manager.get("actions.toggle_selection.light_on_off")) - self.toggle_property_selection.append(self.plugin_base.locale_manager.get("actions.toggle_selection.brightness_temperature")) + self.toggle_property_selection.append( + self.plugin_base.locale_manager.get("actions.toggle_selection.light_on_off") + ) + self.toggle_property_selection.append( + self.plugin_base.locale_manager.get( + "actions.toggle_selection.brightness_temperature" + ) + ) self.property_selection = Gtk.StringList() @@ -49,44 +57,55 @@ def get_config_rows(self) -> list: self.property_selection.append(property.name) self.step_size = Adw.SpinRow.new_with_range(1, 10, 1) - self.step_size.set_title(self.plugin_base.locale_manager.get("actions.step_size.title")) + self.step_size.set_title( + self.plugin_base.locale_manager.get("actions.step_size.title") + ) self.step_size.set_value(self.selected_step_size) - self.dial_selection = Adw.ComboRow(title=self.plugin_base.locale_manager.get("actions.dial_selection.title"), model=self.property_selection) + self.dial_selection = Adw.ComboRow( + title=self.plugin_base.locale_manager.get("actions.dial_selection.title"), + model=self.property_selection, + ) self.dial_selection.set_selected(self.current_dial_selection) - self.toggle_selection = Adw.ComboRow(title=self.plugin_base.locale_manager.get("actions.toggle_selection.title"), model=self.toggle_property_selection) + self.toggle_selection = Adw.ComboRow( + title=self.plugin_base.locale_manager.get("actions.toggle_selection.title"), + model=self.toggle_property_selection, + ) self.toggle_selection.set_selected(self.current_toggle_selection) self.step_size.connect("notify::text", self.on_step_size_changed) self.dial_selection.connect("notify::selected", self.on_dial_selection_changed) - self.toggle_selection.connect("notify::selected", self.on_toggle_selection_changed) - - return parent_entries + [self.dial_selection, self.toggle_selection, self.step_size] + self.toggle_selection.connect( + "notify::selected", self.on_toggle_selection_changed + ) + return parent_entries + [ + self.dial_selection, + self.toggle_selection, + self.step_size, + ] def on_step_size_changed(self, spinner: Adw.SpinRow, *args): self.selected_step_size = int(self.step_size.get_value()) self.save_settings() - def on_dial_selection_changed(self, spinner: Adw.ComboRow, *args): self.current_dial_selection = int(self.dial_selection.get_selected()) self.save_settings() - def on_toggle_selection_changed(self, spinner: Adw.ComboRow, *args): self.current_toggle_selection = int(self.toggle_selection.get_selected()) self.save_settings() - def load_local_saved_config(self): local_settings = self.get_settings() self.selected_step_size = local_settings.get("step_size") or 1 self.current_dial_selection = local_settings.get("current_dial_selection") or 0 - self.current_toggle_selection = local_settings.get("current_toggle_selection") or 0 - + self.current_toggle_selection = ( + local_settings.get("current_toggle_selection") or 0 + ) def save_settings(self): local_settings = self.get_settings() @@ -96,26 +115,28 @@ def save_settings(self): local_settings["current_toggle_selection"] = self.current_toggle_selection self.set_settings(local_settings) - def event_callback(self, event: InputEvent, data: dict) -> None: - if event == Input.Key.Events.DOWN or event == Input.Dial.Events.DOWN: - self.on_key_down() - return - - new_value = 0 - if str(event) == str(Input.Dial.Events.TURN_CW): - new_value = +self.selected_step_size - if str(event) == str(Input.Dial.Events.TURN_CCW): - new_value = -self.selected_step_size - - is_brightness = self.current_dial_selection == DialProperty.Brightness.value - if is_brightness: - self.modify_brightness(new_value) - else: - self.modify_temperature(new_value) - - self.update_labels() + if event == Input.Key.Events.DOWN or event == Input.Dial.Events.DOWN: + self.on_key_down() + return + + new_value = 0 + if str(event) == str(Input.Dial.Events.TURN_CW): + new_value = +self.selected_step_size + if str(event) == str(Input.Dial.Events.TURN_CCW): + new_value = -self.selected_step_size + + is_brightness = self.current_dial_selection == DialProperty.Brightness.value + if is_brightness: + self.set_property( + "brightness", max(1, min(self.current_brightness + new_value, 100)) + ) + else: + self.set_property( + "temperature", max(143, min(self.current_temperature + new_value, 344)) + ) + self.update_labels() def toggle_brightness_temperature(self): if self.current_dial_selection == DialProperty.Brightness.value: @@ -125,18 +146,34 @@ def toggle_brightness_temperature(self): self.save_settings() - def update_labels(self): if self.current_dial_selection == DialProperty.Brightness.value: - self.set_top_label(text=self.plugin_base.locale_manager.get("actions.current_brightness.title")) - self.set_bottom_label(text=self.plugin_base.locale_manager.get("actions.current_brightness.value") % self.current_brightness) + self.set_top_label( + text=self.plugin_base.locale_manager.get( + "actions.current_brightness.title" + ) + ) + self.set_bottom_label( + text=self.plugin_base.locale_manager.get( + "actions.current_brightness.value" + ) + % self.current_brightness + ) else: - self.set_top_label(text=self.plugin_base.locale_manager.get("actions.current_temperature.title")) - self.set_bottom_label(text=str(self.current_temperature)) - + self.set_top_label( + text=self.plugin_base.locale_manager.get( + "actions.current_temperature.title" + ) + ) + self.set_bottom_label( + text=self.plugin_base.locale_manager.get( + "actions.current_temperature.value" + ) + % int(self.current_k_temperature) + ) def on_key_down(self) -> None: if self.current_toggle_selection == ToggleProperty.ToggleLightOnOff.value: - self.toggle_light() + self.set_property("on", None) else: self.toggle_brightness_temperature() diff --git a/actions/ElgatoKeyLight/IncreaseDecreaseButton.py b/actions/ElgatoKeyLight/IncreaseDecreaseButton.py index 05ef1f0..a7d0949 100644 --- a/actions/ElgatoKeyLight/IncreaseDecreaseButton.py +++ b/actions/ElgatoKeyLight/IncreaseDecreaseButton.py @@ -1,4 +1,5 @@ # Import StreamController modules +from gi.repository import Gtk, Adw from src.backend.DeckManagement.InputIdentifier import Input, InputEvent from enum import Enum @@ -6,14 +7,16 @@ # Import gtk modules - used for the config rows import gi + gi.require_version("Gtk", "4.0") gi.require_version("Adw", "1") -from gi.repository import Gtk, Adw + class AvailableProperty(Enum): Brightness = 0 Temperature = 1 + class IncreaseDecreaseButton(Core): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -21,7 +24,6 @@ def __init__(self, *args, **kwargs): self.selected_step_size = 1 self.current_dial_selection = 0 - def on_ready(self) -> None: self.load_local_saved_config() self.update_icon() @@ -35,10 +37,15 @@ def get_config_rows(self) -> list: self.property_selection.append(property.name) self.step_size = Adw.SpinRow.new_with_range(-10, 10, 1) - self.step_size.set_title(self.plugin_base.locale_manager.get("actions.step_size.title")) + self.step_size.set_title( + self.plugin_base.locale_manager.get("actions.step_size.title") + ) self.step_size.set_value(self.selected_step_size) - self.dial_selection = Adw.ComboRow(title=self.plugin_base.locale_manager.get("actions.dial_selection.title"), model=self.property_selection) + self.dial_selection = Adw.ComboRow( + title=self.plugin_base.locale_manager.get("actions.dial_selection.title"), + model=self.property_selection, + ) self.dial_selection.set_selected(self.current_dial_selection) self.step_size.connect("notify::text", self.on_step_size_changed) @@ -46,12 +53,10 @@ def get_config_rows(self) -> list: return parent_entries + [self.dial_selection, self.step_size] - def on_step_size_changed(self, spinner: Adw.SpinRow, *args): self.selected_step_size = int(self.step_size.get_value()) self.save_settings() - def on_dial_selection_changed(self, spinner: Adw.ComboRow, *args): self.current_dial_selection = int(self.dial_selection.get_selected()) self.save_settings() @@ -62,7 +67,6 @@ def load_local_saved_config(self): self.selected_step_size = local_settings.get("step_size") or 1 self.current_dial_selection = local_settings.get("current_dial_selection") or 0 - def save_settings(self): local_settings = self.get_settings() @@ -73,8 +77,14 @@ def save_settings(self): def on_key_down(self) -> None: new_value = 0 new_value = +self.selected_step_size - is_brightness = self.current_dial_selection == AvailableProperty.Brightness.value + is_brightness = ( + self.current_dial_selection == AvailableProperty.Brightness.value + ) if is_brightness: - self.modify_brightness(new_value) + self.set_property( + "brightness", max(1, min(self.current_brightness + new_value, 100)) + ) else: - self.modify_temperature(new_value) + self.set_property( + "temperature", max(143, min(self.current_temperature + new_value, 344)) + ) diff --git a/actions/ElgatoKeyLight/SetButton.py b/actions/ElgatoKeyLight/SetButton.py index 7b98fd9..c3601c9 100644 --- a/actions/ElgatoKeyLight/SetButton.py +++ b/actions/ElgatoKeyLight/SetButton.py @@ -1,10 +1,11 @@ +from gi.repository import Adw from .Core import Core # Import gtk modules - used for the config rows import gi + gi.require_version("Gtk", "4.0") gi.require_version("Adw", "1") -from gi.repository import Adw class SetButton(Core): @@ -14,8 +15,14 @@ def __init__(self, *args, **kwargs): def on_ready(self) -> None: local_settings = self.get_settings() - self._custom_brightness = local_settings.get("custom_brightness") or self.supported_lights["ElgatoKeyLight"]["min_brightness"] - self._custom_temperature = local_settings.get("custom_temperature") or self.supported_lights["ElgatoKeyLight"]["min_temperature"] + self._custom_brightness = ( + local_settings.get("custom_brightness") + or self.supported_lights["ElgatoKeyLight"]["min_brightness"] + ) + self._custom_temperature = ( + local_settings.get("custom_temperature") + or self.supported_lights["ElgatoKeyLight"]["min_temperature"] + ) self._live_update = local_settings.get("live_update") or False self.update_icon() @@ -61,17 +68,33 @@ def get_config_rows(self) -> list: self.live_update.set_active(self.live_update_active) self.live_update.connect("notify::active", self.on_live_update_changed) - self.brightness_entry = Adw.SpinRow.new_with_range(self.supported_lights["ElgatoKeyLight"]["min_brightness"], self.supported_lights["ElgatoKeyLight"]["max_brightness"], 1) - self.brightness_entry.set_title(self.plugin_base.locale_manager.get("actions.brightness_entry.title")) + self.brightness_entry = Adw.SpinRow.new_with_range( + self.supported_lights["ElgatoKeyLight"]["min_brightness"], + self.supported_lights["ElgatoKeyLight"]["max_brightness"], + 1, + ) + self.brightness_entry.set_title( + self.plugin_base.locale_manager.get("actions.brightness_entry.title") + ) self.brightness_entry.set_value(self.custom_brightness) - self.temperature_entry = Adw.SpinRow.new_with_range(self.supported_lights["ElgatoKeyLight"]["min_temperature"], self.supported_lights["ElgatoKeyLight"]["max_temperature"], 1) - self.temperature_entry.set_title(self.plugin_base.locale_manager.get("actions.brightness_entry.title")) + self.temperature_entry = Adw.SpinRow.new_with_range( + self.supported_lights["ElgatoKeyLight"]["min_temperature"], + self.supported_lights["ElgatoKeyLight"]["max_temperature"], + 1, + ) + self.temperature_entry.set_title( + self.plugin_base.locale_manager.get("actions.brightness_entry.title") + ) self.temperature_entry.set_value(self.custom_temperature) self.brightness_entry.connect("notify::value", self.on_brightness_changed) self.temperature_entry.connect("notify::value", self.on_temperature_changed) - return parent_entries + [self.live_update, self.brightness_entry, self.temperature_entry] + return parent_entries + [ + self.live_update, + self.brightness_entry, + self.temperature_entry, + ] def on_live_update_changed(self, switch: Adw.SwitchRow, *args): self.live_update_active = switch.get_active() @@ -83,22 +106,20 @@ def on_brightness_changed(self, spinner: Adw.SpinRow, *args): self.custom_brightness = spinner.get_value() if self.live_update_active: - self.current_brightness = self.custom_brightness + self.set_property("brightness", self.custom_brightness) def on_temperature_changed(self, spinner: Adw.SpinRow, *args): self.custom_temperature = spinner.get_value() if self.live_update_active: - self.current_temperature = self.custom_temperature + self.set_property("temperature", self.custom_temperature) def on_key_down(self) -> None: self.push_light_properties() def push_light_properties(self): - settings = self.plugin_base.get_settings() - - self.current_brightness = self.custom_brightness - self.current_temperature = self.custom_temperature + self.set_property("brightness", self.custom_brightness) + self.set_property("temperature", self.custom_temperature) - if settings.get("light_active") == 0: - self.toggle_light() + if self.current_status == 0: + self.set_property("on", None) return diff --git a/actions/ElgatoKeyLight/ToggleButton.py b/actions/ElgatoKeyLight/ToggleButton.py index dbbfb29..9baed62 100644 --- a/actions/ElgatoKeyLight/ToggleButton.py +++ b/actions/ElgatoKeyLight/ToggleButton.py @@ -1,8 +1,16 @@ from .Core import Core + class ToggleButton(Core): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) def on_key_down(self) -> None: - self.toggle_light() + self.set_property("on", None) + + def on_ready(self): + self.update_icon() + + def get_config_rows(self) -> list: + parent_entries = super().get_config_rows() + return parent_entries diff --git a/backend/backend.py b/backend/backend.py index 980c45e..4e8729a 100644 --- a/backend/backend.py +++ b/backend/backend.py @@ -1,10 +1,5 @@ from streamcontroller_plugin_tools import BackendBase -import gi - -gi.require_version("Gtk", "4.0") -gi.require_version("Adw", "1") - class Event: def __init__(self): @@ -21,11 +16,40 @@ def emit(self, *args): listener(*args) +class Device: + def __init__(self, ip_address: str, name: str): + self.ip_address = ip_address + self.name = name + + class Backend(BackendBase): def __init__(self): super().__init__() self.on_brightness_changed = Event() self.on_temperature_changed = Event() self.on_light_state_changed = Event() + self.on_device_added = Event() + + self.devices: dict[str, Device] = {} + + def register_new_device(self, device_ip: str, device_name: str): + print("Registering new device: ", device_ip) + + if device_ip in self.devices: + return + + self.devices[device_ip] = Device(device_ip, device_name) + self.on_device_added.emit() + + def remove_device(self, device_ip: str): + del self.devices[device_ip] + self.on_device_removed.emit(device_ip) + + def get_devices(self) -> dict[str, Device]: + return self.devices + + def is_device_in_list(self, device_ip: str) -> bool: + return device_ip in self.devices + backend = Backend() diff --git a/locales/en_US.json b/locales/en_US.json index 55af2a2..de7444b 100644 --- a/locales/en_US.json +++ b/locales/en_US.json @@ -1,6 +1,7 @@ { "actions.live_update.title": "Live Update", - "actions.ip_entry.title": "IP Address", + "actions.add_ip_entry.title": "Add new IP Address", + "actions.add_light_button.title": "Add new IP Address", "actions.step_size.title": "Step Size", "actions.dial_selection.title": "Dial Selection", "actions.brightness_entry.title": "Brightness", @@ -11,7 +12,9 @@ "actions.current_brightness.title": "Brightness", "actions.current_brightness.value": "%s %%", "actions.current_temperature.title": "Temperature", + "actions.current_temperature.value": "%s K", "actions.toggle_selection.title": "On press", "actions.toggle_selection.light_on_off": "Toggle Light", - "actions.toggle_selection.brightness_temperature": "Change Brightness/Temperature" + "actions.toggle_selection.brightness_temperature": "Change Brightness/Temperature", + "actions.device_list.title": "Existing devices" } diff --git a/main.py b/main.py index 6e165c2..55fd3a7 100644 --- a/main.py +++ b/main.py @@ -12,6 +12,7 @@ import os + class PluginTemplate(PluginBase): def __init__(self): super().__init__() @@ -22,35 +23,41 @@ def __init__(self): ## Register actions self.set_light_action_holder = ActionHolder( - plugin_base = self, - action_base = SetButton, - action_id = "com_memclash_elgatokeylight::SetButton", # Change this to your own plugin id - action_name = "Set Light Properties", + plugin_base=self, + action_base=SetButton, + action_id="com_memclash_elgatokeylight::SetButton", # Change this to your own plugin id + action_name="Set Light Properties", action_support={Input.Key: ActionInputSupport.SUPPORTED}, ) self.increase_decrease_light_action_holder = ActionHolder( - plugin_base = self, - action_base = IncreaseDecreaseButton, - action_id = "com_memclash_elgatokeylight::IncreaseDecreaseButton", # Change this to your own plugin id - action_name = "Increase/Decrease Light Properties", + plugin_base=self, + action_base=IncreaseDecreaseButton, + action_id="com_memclash_elgatokeylight::IncreaseDecreaseButton", # Change this to your own plugin id + action_name="Increase/Decrease Light Properties", action_support={Input.Key: ActionInputSupport.SUPPORTED}, ) self.toggle_light_action_holder = ActionHolder( - plugin_base = self, - action_base = ToggleButton, - action_id = "com_memclash_elgatokeylight::ToggleButton", # Change this to your own plugin id - action_name = "Toggle Light", - action_support={Input.Key: ActionInputSupport.SUPPORTED, Input.Dial: ActionInputSupport.SUPPORTED}, + plugin_base=self, + action_base=ToggleButton, + action_id="com_memclash_elgatokeylight::ToggleButton", # Change this to your own plugin id + action_name="Toggle Light", + action_support={ + Input.Key: ActionInputSupport.SUPPORTED, + Input.Dial: ActionInputSupport.SUPPORTED, + }, ) self.dial_action_holder = ActionHolder( - plugin_base = self, - action_base = Dial, - action_id = "com_memclash_elgatokeylight::Dial", # Change this to your own plugin id - action_name = "Dial Brightness Temperature", - action_support={Input.Dial: ActionInputSupport.SUPPORTED, Input.Key: ActionInputSupport.UNSUPPORTED}, + plugin_base=self, + action_base=Dial, + action_id="com_memclash_elgatokeylight::Dial", # Change this to your own plugin id + action_name="Dial Brightness Temperature", + action_support={ + Input.Dial: ActionInputSupport.SUPPORTED, + Input.Key: ActionInputSupport.UNSUPPORTED, + }, ) self.add_action_holder(self.set_light_action_holder) @@ -58,11 +65,10 @@ def __init__(self): self.add_action_holder(self.toggle_light_action_holder) self.add_action_holder(self.dial_action_holder) - # Register plugin self.register( - plugin_name = "Elgato Key Light", - github_repo = "https://github.com/StreamController/PluginTemplate", - plugin_version = "0.3.0", - app_version = "1.1.1-alpha" + plugin_name="Elgato Key Light", + github_repo="https://github.com/cozybuild/StreamControllerElgatoKeyLight/", + plugin_version="0.3.0", + app_version="1.1.1-alpha", )