From 3e28f5aa7caf0c5c68791869c16f3f447246c3d6 Mon Sep 17 00:00:00 2001 From: faush01 Date: Wed, 1 Jul 2020 14:34:27 +1000 Subject: [PATCH] add play next episode prompt when approaching the end of the current episode --- addon.xml | 2 +- .../resource.language.en_gb/strings.po | 10 +- resources/lib/playnext.py | 138 ++++++++++++++++++ resources/settings.xml | 4 + .../skins/default/720p/PlayNextDialog.xml | 67 +++++++++ service.py | 11 ++ 6 files changed, 230 insertions(+), 2 deletions(-) create mode 100644 resources/lib/playnext.py create mode 100644 resources/skins/default/720p/PlayNextDialog.xml diff --git a/addon.xml b/addon.xml index 95d4931..9b06709 100644 --- a/addon.xml +++ b/addon.xml @@ -1,7 +1,7 @@ diff --git a/resources/language/resource.language.en_gb/strings.po b/resources/language/resource.language.en_gb/strings.po index d08bbf1..2cd771d 100644 --- a/resources/language/resource.language.en_gb/strings.po +++ b/resources/language/resource.language.en_gb/strings.po @@ -167,7 +167,7 @@ msgid "Show load progress" msgstr "" msgctxt "#30121" -msgid "On Resume" +msgid "On resume" msgstr "" msgctxt "#30125" @@ -1065,3 +1065,11 @@ msgstr "" msgctxt "#30438" msgid "Play cinema intros" msgstr "" + +msgctxt "#30439" +msgid "Show play next episode at time left" +msgstr "" + +msgctxt "#30440" +msgid "Play next" +msgstr "" diff --git a/resources/lib/playnext.py b/resources/lib/playnext.py new file mode 100644 index 0000000..064a7f8 --- /dev/null +++ b/resources/lib/playnext.py @@ -0,0 +1,138 @@ +import os +import threading + +import xbmc +import xbmcgui +import xbmcaddon + +from .simple_logging import SimpleLogging +from .play_utils import get_playing_data, send_event_notification + +log = SimpleLogging(__name__) + + +class PlayNextService(threading.Thread): + + stop_thread = False + monitor = None + + def __init__(self, play_monitor): + super(PlayNextService, self).__init__() + self.monitor = play_monitor + + def run(self): + + settings = xbmcaddon.Addon() + play_next_trigger_time = int(settings.getSetting('play_next_trigger_time')) + + plugin_path = settings.getAddonInfo('path') + plugin_path_real = xbmc.translatePath(os.path.join(plugin_path)) + play_next_dialog = None + play_next_triggered = False + is_playing = False + + while not xbmc.Monitor().abortRequested() and not self.stop_thread: + + player = xbmc.Player() + if player.isPlaying(): + + if not is_playing: + play_next_trigger_time = int(settings.getSetting('play_next_trigger_time')) + + duration = player.getTotalTime() + position = player.getTime() + trigger_time = play_next_trigger_time # 300 + time_to_end = (duration - position) + + if not play_next_triggered and (trigger_time > time_to_end) and play_next_dialog is None: + play_next_triggered = True + log.debug("play_next_triggered hit at {0} seconds from end", time_to_end) + + play_data = get_playing_data(self.monitor.played_information) + log.debug("play_next_triggered play_data : {0}", play_data) + + next_episode = play_data.get("next_episode") + item_type = play_data.get("item_type") + + if next_episode is not None and item_type == "Episode": + play_next_dialog = PlayNextDialog("PlayNextDialog.xml", plugin_path_real, "default", "720p") + play_next_dialog.set_episode_info(next_episode) + if play_next_dialog is not None: + play_next_dialog.show() + + is_playing = True + + else: + play_next_triggered = False + if play_next_dialog is not None: + play_next_dialog.close() + del play_next_dialog + play_next_dialog = None + + is_playing = False + + if xbmc.Monitor().waitForAbort(1): + break + + def stop_servcie(self): + log.debug("PlayNextService Stop Called") + self.stop_thread = True + + +class PlayNextDialog(xbmcgui.WindowXMLDialog): + + action_exitkeys_id = None + episode_info = None + + def __init__(self, *args, **kwargs): + log.debug("PlayNextDialog: __init__") + xbmcgui.WindowXML.__init__(self, *args, **kwargs) + + def onInit(self): + log.debug("PlayNextDialog: onInit") + self.action_exitkeys_id = [10, 13] + + index = self.episode_info.get("IndexNumber", -1) + series_name = self.episode_info.get("SeriesName") + next_epp_name = "Episode %02d - (%s)" % (index, self.episode_info.get("Name", "n/a")) + + series_label = self.getControl(3011) + series_label.setLabel(series_name) + + series_label = self.getControl(3012) + series_label.setLabel(next_epp_name) + + def onFocus(self, control_id): + pass + + def doAction(self, action_id): + pass + + def onMessage(self, message): + log.debug("PlayNextDialog: onMessage: {0}", message) + + def onAction(self, action): + + if action.getId() == 10: # ACTION_PREVIOUS_MENU + self.close() + elif action.getId() == 92: # ACTION_NAV_BACK + self.close() + else: + log.debug("PlayNextDialog: onAction: {0}", action.getId()) + + def onClick(self, control_id): + if control_id == 3013: + log.debug("PlayNextDialog: Play Next Episode") + self.close() + next_item_id = self.episode_info.get("Id") + log.debug("Playing Next Episode: {0}", next_item_id) + play_info = {} + play_info["item_id"] = next_item_id + play_info["auto_resume"] = "-1" + play_info["force_transcode"] = False + send_event_notification("embycon_play_action", play_info) + elif control_id == 3014: + self.close() + + def set_episode_info(self, info): + self.episode_info = info diff --git a/resources/settings.xml b/resources/settings.xml index c2d4e20..c1b1575 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -55,6 +55,10 @@ + + + + diff --git a/resources/skins/default/720p/PlayNextDialog.xml b/resources/skins/default/720p/PlayNextDialog.xml new file mode 100644 index 0000000..44da5ce --- /dev/null +++ b/resources/skins/default/720p/PlayNextDialog.xml @@ -0,0 +1,67 @@ + + + 3013 + 2 + + 1 + 0 + 0 + + + + + 0 + 0 + 1280 + 52 + bg.png + + + + 20 + 0 + 390 + 45 + + font45_title + left + + + + 390 + 5 + 500 + 35 + + font14 + center + + + + 1020 + -8 + 150 + 65 + true + + center + white.png + font12 + 3014 + + + + 1140 + -8 + 150 + 65 + true + + center + white.png + font12 + 3013 + + + + \ No newline at end of file diff --git a/service.py b/service.py index c2093fa..9b778e9 100644 --- a/service.py +++ b/service.py @@ -21,6 +21,7 @@ from resources.lib.library_change_monitor import LibraryChangeMonitor from resources.lib.datamanager import clear_old_cache_data from resources.lib.tracking import set_timing_enabled from resources.lib.image_server import HttpImageServerThread +from resources.lib.playnext import PlayNextService settings = xbmcaddon.Addon() @@ -86,6 +87,12 @@ websocket_client = WebSocketClient(library_change_monitor) if remote_control: websocket_client.start() +play_next_service = None +play_next_trigger_time = int(settings.getSetting('play_next_trigger_time')) +if play_next_trigger_time > 0: + play_next_service = PlayNextService(monitor) + play_next_service.start() + # Start the context menu monitor context_monitor = None context_menu = settings.getSetting('override_contextmenu') == "true" @@ -184,6 +191,10 @@ image_server.stop() # call stop on the library update monitor library_change_monitor.stop() +# stop the play next episdoe service +if play_next_service: + play_next_service.stop_servcie() + # call stop on the context menu monitor if context_monitor: context_monitor.stop_monitor()