From 2ea8e6c4d9f64883db63f07dc7d4eac03444af33 Mon Sep 17 00:00:00 2001 From: zim514 Date: Tue, 26 Nov 2024 18:49:55 +0000 Subject: [PATCH] [script.service.hue] 2.0.15 --- script.service.hue/addon.xml | 11 +- script.service.hue/plugin.py | 2 +- script.service.hue/resources/lib/ambigroup.py | 2 +- script.service.hue/resources/lib/core.py | 2 +- .../resources/lib/lightgroup.py | 99 +++++----- script.service.hue/resources/lib/menu.py | 179 +++++++++--------- script.service.hue/service.py | 2 +- 7 files changed, 152 insertions(+), 145 deletions(-) diff --git a/script.service.hue/addon.xml b/script.service.hue/addon.xml index 3d54b2ec3..4784ae4fa 100644 --- a/script.service.hue/addon.xml +++ b/script.service.hue/addon.xml @@ -1,4 +1,4 @@ - + @@ -20,11 +20,10 @@ https://github.com/zim514/script.service.hue https://forum.kodi.tv/showthread.php?tid=344886 - v2.0.12 -- Fix schedule / activation checks -- Fix Music support -- Localisation updates from Weblate -- Fix Ambilight support + v2.0.15 +- Hide disabled menu action when service is disabled +- Fix inconsistent activation code +- Crash fix Automatitza les llums Hue amb la reproducció de Kodi diff --git a/script.service.hue/plugin.py b/script.service.hue/plugin.py index b00dc13f6..4d58629b7 100644 --- a/script.service.hue/plugin.py +++ b/script.service.hue/plugin.py @@ -6,6 +6,6 @@ from resources.lib import menu, reporting try: - menu.menu() + menu.Menu() except Exception as exc: reporting.process_exception(exc) diff --git a/script.service.hue/resources/lib/ambigroup.py b/script.service.hue/resources/lib/ambigroup.py index b7d808a00..4cd77e0cc 100644 --- a/script.service.hue/resources/lib/ambigroup.py +++ b/script.service.hue/resources/lib/ambigroup.py @@ -135,7 +135,7 @@ def _ambi_loop(self): self.settings_monitor.waitForAbort(update_interval) # seconds - executor.shutdown(wait=False) + executor.shutdown(wait=False) #stop _update_hue_rgb thread(s) if not self.settings_monitor.abortRequested(): # ignore writing average process time if Kodi is shutting down average_process_time = self._perf_average(PROCESS_TIMES) diff --git a/script.service.hue/resources/lib/core.py b/script.service.hue/resources/lib/core.py index c97d814eb..cf00441ee 100644 --- a/script.service.hue/resources/lib/core.py +++ b/script.service.hue/resources/lib/core.py @@ -16,7 +16,7 @@ from .language import get_string as _ -def core(): +def core_dispatcher(): settings_monitor = settings.SettingsMonitor() if len(sys.argv) > 1: diff --git a/script.service.hue/resources/lib/lightgroup.py b/script.service.hue/resources/lib/lightgroup.py index 98e284a08..9fbb2d3aa 100644 --- a/script.service.hue/resources/lib/lightgroup.py +++ b/script.service.hue/resources/lib/lightgroup.py @@ -46,30 +46,37 @@ def onAVStarted(self): log(f"[SCRIPT.SERVICE.HUE] LightGroup[{self.light_group_id}] onPlaybackStarted. Group enabled: {enabled}, Bridge connected: {self.bridge.connected}, mediaType: {self.media_type}") - if not enabled or not self.bridge.connected: + if not enabled: + log(f"[SCRIPT.SERVICE.HUE] LightGroup[{self.light_group_id}] not enabled, doing nothing") return - - log(f"[SCRIPT.SERVICE.HUE] LightGroup[{self.light_group_id}] onPlaybackStarted. play_behavior: {play_enabled}, media_type: {self.media_type} == playback_type: {self._playback_type()}") - if play_enabled and self.media_type == self._playback_type() and self._playback_type() == VIDEO: - try: - self.info_tag = self.getVideoInfoTag() - except (AttributeError, TypeError) as x: - log(f"[SCRIPT.SERVICE.HUE] LightGroup{self.light_group_id}: OnAV Started: Can't read VideoInfoTag") - reporting.process_exception(x) - elif play_enabled and self.media_type == self._playback_type() and self._playback_type() == AUDIO: - try: - self.info_tag = self.getMusicInfoTag() - except (AttributeError, TypeError) as x: - log(f"[SCRIPT.SERVICE.HUE] LightGroup{self.light_group_id}: OnAV Started: Can't read AudioInfoTag") - reporting.process_exception(x) - - if self.activation_check.validate(play_scene): - contents = inspect.getmembers(self.info_tag) - log(f"[SCRIPT.SERVICE.HUE] Start InfoTag: {contents}") - - #log(f"[SCRIPT.SERVICE.HUE] InfoTag: {self.info_tag}, {self.info_tag.getDuration()}") - log(f"[SCRIPT.SERVICE.HUE] LightGroup[{self.light_group_id}] Running Play action") - self.run_action("play") + elif not play_enabled: + log(f"[SCRIPT.SERVICE.HUE] LightGroup[{self.light_group_id}] play action not enabled") + return + elif not self.bridge.connected: + log(f"[SCRIPT.SERVICE.HUE] Bridge not connected") + return + else: + log(f"[SCRIPT.SERVICE.HUE] LightGroup[{self.light_group_id}] onPlaybackStarted. play_behavior: {play_enabled}, media_type: {self.media_type} == playback_type: {self._playback_type()}") + if self.media_type == self._playback_type() and self._playback_type() == VIDEO: + try: + self.info_tag = self.getVideoInfoTag() + except (AttributeError, TypeError) as x: + log(f"[SCRIPT.SERVICE.HUE] LightGroup{self.light_group_id}: OnAV Started: Can't read VideoInfoTag") + reporting.process_exception(x) + elif play_enabled and self.media_type == self._playback_type() and self._playback_type() == AUDIO: + try: + self.info_tag = self.getMusicInfoTag() + except (AttributeError, TypeError) as x: + log(f"[SCRIPT.SERVICE.HUE] LightGroup{self.light_group_id}: OnAV Started: Can't read AudioInfoTag") + reporting.process_exception(x) + + if self.activation_check.validate(play_scene): + contents = inspect.getmembers(self.info_tag) + log(f"[SCRIPT.SERVICE.HUE] Start InfoTag: {contents}") + + #log(f"[SCRIPT.SERVICE.HUE] InfoTag: {self.info_tag}, {self.info_tag.getDuration()}") + log(f"[SCRIPT.SERVICE.HUE] LightGroup[{self.light_group_id}] Running Play action") + self.run_action("play") def onPlayBackPaused(self): self.state = STATE_PAUSED @@ -79,13 +86,21 @@ def onPlayBackPaused(self): log(f"[SCRIPT.SERVICE.HUE] LightGroup[{self.light_group_id}] onPlaybackPaused. Group enabled: {enabled}, Bridge connected: {self.bridge.connected}") - if not enabled or not self.bridge.connected: + if not enabled: + log(f"[SCRIPT.SERVICE.HUE] LightGroup[{self.light_group_id}] not enabled, doing nothing") + return + elif not pause_enabled: + log(f"[SCRIPT.SERVICE.HUE] LightGroup[{self.light_group_id}] Pause action not enabled") return + elif not self.bridge.connected: + log(f"[SCRIPT.SERVICE.HUE] Bridge not connected") + return + else: - if pause_enabled and self.media_type == self._playback_type(): - if self.activation_check.validate(pause_scene): - log(f"[SCRIPT.SERVICE.HUE] LightGroup[{self.light_group_id}] Running Pause action") - self.run_action("pause") + if self.media_type == self._playback_type(): + if self.activation_check.validate(pause_scene): + log(f"[SCRIPT.SERVICE.HUE] LightGroup[{self.light_group_id}] Running Pause action") + self.run_action("pause") def onPlayBackStopped(self): self.state = STATE_STOPPED @@ -95,22 +110,21 @@ def onPlayBackStopped(self): log(f"[SCRIPT.SERVICE.HUE] LightGroup[{self.light_group_id}] onPlaybackStopped. Group enabled: {enabled}, Bridge connected: {self.bridge.connected}") - if not enabled or not self.bridge.connected: + if not enabled: + log(f"[SCRIPT.SERVICE.HUE] LightGroup[{self.light_group_id}] not enabled, doing nothing") return + elif not stop_enabled: + log(f"[SCRIPT.SERVICE.HUE] LightGroup[{self.light_group_id}] Pause action not enabled") + return + elif not self.bridge.connected: + log(f"[SCRIPT.SERVICE.HUE] Bridge not connected") + return + else: + if self.media_type == self.last_media_type or self.media_type == self._playback_type(): - if stop_enabled and (self.media_type == self.last_media_type or self.media_type == self._playback_type()): - ########### TODO: Remove debug block - #xbmc.sleep(5000) - contents = inspect.getmembers(self.info_tag) - log(f"[SCRIPT.SERVICE.HUE] Stop[{self.light_group_id}] InfoTag Inspect Contents: {contents}") - - duration = self.info_tag.getDuration() - log(f"[SCRIPT.SERVICE.HUE] Stop[{self.light_group_id}]: {self.info_tag}, {duration}") - ############ - - if self.activation_check.validate(stop_scene): - log(f"[SCRIPT.SERVICE.HUE] LightGroup[{self.light_group_id}] Running Stop action") - self.run_action("stop") + if self.activation_check.validate(stop_scene): + log(f"[SCRIPT.SERVICE.HUE] LightGroup[{self.light_group_id}] Running Stop action") + self.run_action("stop") def onPlayBackResumed(self): # log("[SCRIPT.SERVICE.HUE] In LightGroup[{}], onPlaybackResumed()".format(self.light_group_id)) @@ -346,4 +360,3 @@ def validate(self, scene=None): return True log("[SCRIPT.SERVICE.HUE] Validate Audio: Checks not passed, not activating") return False - diff --git a/script.service.hue/resources/lib/menu.py b/script.service.hue/resources/lib/menu.py index e97d9e769..082e8de9c 100644 --- a/script.service.hue/resources/lib/menu.py +++ b/script.service.hue/resources/lib/menu.py @@ -16,97 +16,92 @@ from .language import get_string as _ -def menu(): - route = sys.argv[0] - addon_handle = int(sys.argv[1]) - base_url = sys.argv[0] - command = sys.argv[2][1:] - parsed = parse_qs(command) - log(f"[SCRIPT.SERVICE.HUE] menu: {route}, {addon_handle}, {base_url}, {command}, {parsed}") - - if route == f"plugin://{ADDONID}/": - handle_route(base_url, addon_handle, command) - elif route == f"plugin://{ADDONID}/actions": - handle_actions_route(parsed, base_url, addon_handle) - else: - log(f"[SCRIPT.SERVICE.HUE] Unknown command. Handle: {addon_handle}, route: {route}, Arguments: {sys.argv}") - - -def handle_route(base_url, addon_handle, command): - if not command: - build_menu(base_url, addon_handle) - elif command == "settings": - ADDON.openSettings() +class Menu(): + def __init__(self): + route = sys.argv[0] + addon_handle = int(sys.argv[1]) + base_url = sys.argv[0] + command = sys.argv[2][1:] + parsed = parse_qs(command) + log(f"[SCRIPT.SERVICE.HUE] menu: {route}, {addon_handle}, {base_url}, {command}, {parsed}") + + self.enabled = cache_get("service_enabled") + self.daytime = cache_get("daytime") + + if route == f"plugin://{ADDONID}/": + self.handle_route(base_url, addon_handle, command) + elif route == f"plugin://{ADDONID}/actions": + self.handle_actions_route(parsed, base_url, addon_handle) + else: + log(f"[SCRIPT.SERVICE.HUE] Unknown command. Handle: {addon_handle}, route: {route}, Arguments: {sys.argv}") + + def handle_route(self, base_url, addon_handle, command): + if not command: + self.build_menu(base_url, addon_handle) + elif command == "settings": + ADDON.openSettings() + xbmc.executebuiltin('Container.Refresh') + elif command == "toggle": + self.handle_toggle_command() + + def handle_toggle_command(self): + if self.enabled and self._get_status() != "Disabled by daytime": + log("[SCRIPT.SERVICE.HUE] Disable service") + cache_set("service_enabled", False) + elif self._get_status() != "Disabled by daytime": + log("[SCRIPT.SERVICE.HUE] Enable service") + cache_set("service_enabled", True) + else: + log("[SCRIPT.SERVICE.HUE] Disabled by daytime, ignoring") xbmc.executebuiltin('Container.Refresh') - elif command == "toggle": - handle_toggle_command() - - -def handle_toggle_command(): - if cache_get("service_enabled") and _get_status() != "Disabled by daytime": - log("[SCRIPT.SERVICE.HUE] Disable service") - cache_set("service_enabled", False) - elif _get_status() != "Disabled by daytime": - log("[SCRIPT.SERVICE.HUE] Enable service") - cache_set("service_enabled", True) - else: - log("[SCRIPT.SERVICE.HUE] Disabled by daytime, ignoring") - xbmc.executebuiltin('Container.Refresh') - - -def handle_actions_route(parsed, base_url, addon_handle): - action = parsed['action'][0] - light_group_id = parsed['light_group_id'][0] - log(f"[SCRIPT.SERVICE.HUE] Actions: {action}, light_group_id: {light_group_id}") - if action == "menu": - xbmcplugin.addDirectoryItem(addon_handle, base_url + "?action=play&light_group_id=" + light_group_id, ListItem(_("Play"))) - xbmcplugin.addDirectoryItem(addon_handle, base_url + "?action=pause&light_group_id=" + light_group_id, ListItem(_("Pause"))) - xbmcplugin.addDirectoryItem(addon_handle, base_url + "?action=stop&light_group_id=" + light_group_id, ListItem(_("Stop"))) - xbmcplugin.endOfDirectory(handle=addon_handle, cacheToDisc=True) - else: - cache_set("action", (action, light_group_id)) - - -def build_menu(base_url, addon_handle): - log(f"[SCRIPT.SERVICE.HUE] build_menu: status: {_get_status()}") - status_item = ListItem(_("Hue Status: ") + _get_status()) - status_icon = _get_status_icon() - if status_icon: - status_item.setArt({"icon": status_icon}) - log(f"[SCRIPT.SERVICE.HUE] status_icon: {status_icon}") - settings_item = ListItem(_("Settings")) - settings_item.setArt({"icon": xbmcvfs.makeLegalFilename(ADDONPATH + "resources/icons/settings.png")}) - add_directory_items(base_url, addon_handle, status_item, settings_item) - xbmcplugin.endOfDirectory(handle=addon_handle, cacheToDisc=False) - - -def add_directory_items(base_url, addon_handle, status_item, settings_item): - xbmcplugin.addDirectoryItem(addon_handle, base_url + "/actions?light_group_id=1&action=menu", ListItem(_("Video Scenes")), True) - xbmcplugin.addDirectoryItem(addon_handle, base_url + "/actions?light_group_id=2&action=menu", ListItem(_("Audio Scenes")), True) - xbmcplugin.addDirectoryItem(addon_handle, base_url + "?toggle", status_item) - xbmcplugin.addDirectoryItem(addon_handle, base_url + "?settings", settings_item) - - -def _get_status(): - enabled = cache_get("service_enabled") - daytime = cache_get("daytime") - daytime_disable = ADDON.getSettingBool("daylightDisable") # Legacy setting name, it's daytime everywhere now - log(f"[SCRIPT.SERVICE.HUE] _get_status enabled: {enabled} - {type(enabled)}, daytime: {daytime}, daytime_disable: {daytime_disable}") - if daytime and daytime_disable: - return "Disabled by daytime" - elif enabled: - return "Enabled" - else: - return "Disabled" - -def _get_status_icon(): - enabled = cache_get("service_enabled") - daytime = cache_get("daytime") - daytime_disable = ADDON.getSettingBool("daylightDisable") - # log("[SCRIPT.SERVICE.HUE] Current status: {}".format(daytime_disable)) - if daytime and daytime_disable: - return xbmcvfs.makeLegalFilename(ADDONPATH + "resources/icons/daylight.png") # Disabled by daytime, legacy icon name - elif enabled: - return xbmcvfs.makeLegalFilename(ADDONPATH + "resources/icons/enabled.png") # Enabled - return xbmcvfs.makeLegalFilename(ADDONPATH + "resources/icons/disabled.png") # Disabled + def handle_actions_route(self, parsed, base_url, addon_handle): + action = parsed['action'][0] + light_group_id = parsed['light_group_id'][0] + log(f"[SCRIPT.SERVICE.HUE] Actions: {action}, light_group_id: {light_group_id}") + if action == "menu": + xbmcplugin.addDirectoryItem(addon_handle, base_url + "?action=play&light_group_id=" + light_group_id, ListItem(_("Play"))) + xbmcplugin.addDirectoryItem(addon_handle, base_url + "?action=pause&light_group_id=" + light_group_id, ListItem(_("Pause"))) + xbmcplugin.addDirectoryItem(addon_handle, base_url + "?action=stop&light_group_id=" + light_group_id, ListItem(_("Stop"))) + xbmcplugin.endOfDirectory(handle=addon_handle, cacheToDisc=True) + else: + cache_set("action", (action, light_group_id)) + + def build_menu(self, base_url, addon_handle): + log(f"[SCRIPT.SERVICE.HUE] build_menu: status: {self._get_status()}") + status_item = ListItem(_("Hue Status: ") + self._get_status()) + status_icon = self._get_status_icon() + if status_icon: + status_item.setArt({"icon": status_icon}) + log(f"[SCRIPT.SERVICE.HUE] status_icon: {status_icon}") + settings_item = ListItem(_("Settings")) + settings_item.setArt({"icon": xbmcvfs.makeLegalFilename(ADDONPATH + "resources/icons/settings.png")}) + self.add_directory_items(base_url, addon_handle, status_item, settings_item) + xbmcplugin.endOfDirectory(handle=addon_handle, cacheToDisc=False) + + def add_directory_items(self, base_url, addon_handle, status_item, settings_item): + xbmcplugin.addDirectoryItem(addon_handle, base_url + "?toggle", status_item) + xbmcplugin.addDirectoryItem(addon_handle, base_url + "?settings", settings_item) + if self.enabled: + xbmcplugin.addDirectoryItem(addon_handle, base_url + "/actions?light_group_id=1&action=menu", ListItem(_("Video Scenes")), True) + xbmcplugin.addDirectoryItem(addon_handle, base_url + "/actions?light_group_id=2&action=menu", ListItem(_("Audio Scenes")), True) + + def _get_status(self): + daytime_disable = ADDON.getSettingBool("daylightDisable") # Legacy setting name, it's daytime everywhere now + log(f"[SCRIPT.SERVICE.HUE] _get_status enabled: {self.enabled} - {type(self.enabled)}, daytime: {self.daytime}, daytime_disable: {daytime_disable}") + if self.daytime and daytime_disable: + return "Disabled by daytime" + elif self.enabled: + return "Enabled" + else: + return "Disabled" + + def _get_status_icon(self): + + daytime_disable = ADDON.getSettingBool("daylightDisable") + # log("[SCRIPT.SERVICE.HUE] Current status: {}".format(daytime_disable)) + if self.daytime and daytime_disable: + return xbmcvfs.makeLegalFilename(ADDONPATH + "resources/icons/daylight.png") # Disabled by daytime, legacy icon name + elif self.enabled: + return xbmcvfs.makeLegalFilename(ADDONPATH + "resources/icons/enabled.png") # Enabled + return xbmcvfs.makeLegalFilename(ADDONPATH + "resources/icons/disabled.png") # Disabled diff --git a/script.service.hue/service.py b/script.service.hue/service.py index 8b56d132c..1b96b3380 100644 --- a/script.service.hue/service.py +++ b/script.service.hue/service.py @@ -6,6 +6,6 @@ from resources.lib import core, reporting try: - core.core() + core.core_dispatcher() except Exception as exc: reporting.process_exception(exc)