Skip to content

Commit

Permalink
Make video action methods consistent
Browse files Browse the repository at this point in the history
Remove old debug code
Optimize menu, reduce cache hits
In menu, don't offer scene actions when service is disabled
  • Loading branch information
zim514 committed Nov 3, 2024
1 parent a0eadd9 commit 42979cf
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 137 deletions.
2 changes: 1 addition & 1 deletion script.service.hue/addon.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<addon id="script.service.hue" name="Hue Service" provider-name="zim514" version="2.0.13">
<addon id="script.service.hue" name="Hue Service" provider-name="zim514" version="2.0.14">
<requires>
<import addon="xbmc.python" version="3.0.0"/>
<import addon="script.module.requests" version="2.31.0"/>
Expand Down
2 changes: 1 addition & 1 deletion script.service.hue/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
from resources.lib import menu, reporting

try:
menu.menu()
menu.Menu()
except Exception as exc:
reporting.process_exception(exc)
2 changes: 1 addition & 1 deletion script.service.hue/resources/lib/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from .language import get_string as _


def core():
def core_dispatcher():
settings_monitor = settings.SettingsMonitor()

if len(sys.argv) > 1:
Expand Down
89 changes: 48 additions & 41 deletions script.service.hue/resources/lib/lightgroup.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,28 +55,28 @@ def onAVStarted(self):
elif not self.bridge.connected:
log(f"[SCRIPT.SERVICE.HUE] Bridge not connected")
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")
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
Expand All @@ -86,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
Expand All @@ -102,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))
Expand Down
179 changes: 87 additions & 92 deletions script.service.hue/resources/lib/menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion script.service.hue/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
from resources.lib import core, reporting

try:
core.core()
core.core_dispatcher()
except Exception as exc:
reporting.process_exception(exc)

0 comments on commit 42979cf

Please sign in to comment.