diff --git a/resources/lib/intro_skipper.py b/resources/lib/intro_skipper.py index 86be68be..9eb5c1e3 100644 --- a/resources/lib/intro_skipper.py +++ b/resources/lib/intro_skipper.py @@ -13,11 +13,9 @@ from resources.lib.utils import seconds_to_ticks, ticks_to_seconds, translate_path from resources.lib.intro_skipper_utils import get_setting_skip_action, set_correct_skip_info - from .lazylogger import LazyLogger from .dialogs import SkipDialog - -from typing import Literal +from .play_utils import get_playing_data log = LazyLogger(__name__) @@ -33,125 +31,94 @@ def __init__(self, play_monitor): def run(self): - from .play_utils import get_jellyfin_playing_item settings = xbmcaddon.Addon() plugin_path = settings.getAddonInfo('path') plugin_path_real = translate_path(os.path.join(plugin_path)) - - skip_intro_dialog = None - skip_credit_dialog = None - skip_commercial_dialog = None - skip_preview_dialog = None - skip_recap_dialog = None - + + skip_dialog = {} + segments = None playing_item_id = None - + log.debug("SkipService: starting service") - + while not xbmc.Monitor().abortRequested() and not self.stop_thread: player = xbmc.Player() if player.isPlaying(): - item_id = get_jellyfin_playing_item() + play_data = get_playing_data() + item_id = play_data.get("item_id", None) if item_id is not None: log.debug("SkipService: playing item is from jellyfin : {0}".format(item_id)) - + + log.debug("SkipService: segments : {0}".format(segments)) # If item id has changed or is new, retrieve segments - if playing_item_id is None or playing_item_id != item_id : + if playing_item_id is None or playing_item_id != item_id: log.debug("SkipService: item is new, retrieving media segments : {0}".format(item_id)) segments = get_media_segments(item_id) - + # Setting global playing item to current playing item playing_item_id = item_id - - # Handle skip only on jellyfin items - current_ticks = seconds_to_ticks(player.getTime()) - - # Handle Intros - skip_intro_dialog = self.handle_dialog(plugin_path_real, skip_intro_dialog, item_id, current_ticks, player, segments, "Intro") - # Handle Credits - skip_credit_dialog = self.handle_dialog(plugin_path_real, skip_credit_dialog, item_id, current_ticks, player, segments, "Outro") - # Handle commercial - skip_commercial_dialog = self.handle_dialog(plugin_path_real, skip_commercial_dialog, item_id, current_ticks, player, segments, "Commercial") - # Handle preview - skip_preview_dialog = self.handle_dialog(plugin_path_real, skip_preview_dialog, item_id, current_ticks, player, segments, "Preview") - # Handle recap - skip_recap_dialog = self.handle_dialog(plugin_path_real, skip_recap_dialog, item_id, current_ticks, player, segments, "Recap") + + current_ticks = seconds_to_ticks(play_data.get("current_position")) + + for segment in segments: + segment_type = segment.get("Type") + dialog = skip_dialog.get(segment_type, None) + log.debug("SkipService: dialog is: {}".format(dialog)) + skip_dialog[segment_type] = self.handle_dialog(plugin_path_real, dialog, item_id, current_ticks, player, segment) else: playing_item_id = None - if skip_intro_dialog is not None: - log.debug("SkipService: Playback stopped, killing Intro dialog") - skip_intro_dialog.close() - skip_intro_dialog = None - - if skip_credit_dialog is not None: - log.debug("SkipService: Playback stopped, killing Outro dialog") - skip_credit_dialog.close() - skip_credit_dialog = None - - if skip_commercial_dialog is not None: - log.debug("SkipService: Playback stopped, killing Commercial dialog") - skip_commercial_dialog.close() - skip_commercial_dialog = None - - if skip_preview_dialog is not None: - log.debug("SkipService: Playback stopped, killing Preview dialog") - skip_preview_dialog.close() - skip_preview_dialog = None - - if skip_recap_dialog is not None: - log.debug("SkipService: Playback stopped, killing Recap dialog") - skip_recap_dialog.close() - skip_recap_dialog = None + segments = None + skip_dialog = {} + log.debug("SkipService: Playback stopped, setting variables to None") if xbmc.Monitor().waitForAbort(1): break - + xbmc.sleep(200) - - def handle_dialog(self, plugin_path_real: str, dialog: SkipDialog, item_id: str, current_ticks: float, player: xbmc.Player, segments, type: Literal["Commercial", "Preview", "Recap", "Outro", "Intro"]): - skip_action = get_setting_skip_action(type) - + def handle_dialog(self, plugin_path_real: str, dialog: SkipDialog, item_id: str, current_ticks: float, player: xbmc.Player, segment: dict): + segment_type = segment.get("Type") + skip_action = get_setting_skip_action(segment_type) + # In case do nothing is selected return if skip_action == "2": log.debug("SkipService: ignore {0} is selected".format(type)) return None - + if dialog is None: log.debug("SkipService: init dialog") dialog = SkipDialog("SkipDialog.xml", plugin_path_real, "default", "720p") - - set_correct_skip_info(item_id, dialog, segments, type) - + + set_correct_skip_info(item_id, dialog, segment) + is_segment = False if dialog.start is not None and dialog.end is not None: # Resets the dismiss var so that button can reappear in case of navigation in the timecodes if (current_ticks < dialog.start or current_ticks > dialog.end) and dialog.has_been_dissmissed is True: log.debug("SkipService: {0} skip was dismissed. It is reset beacause timecode is outside of segment") dialog.has_been_dissmissed = False - + # Checks if segment is playing is_segment = current_ticks >= dialog.start and current_ticks <= dialog.end - + if skip_action == "1" and is_segment: - log.debug("SkipService: {0} is set to automatic skip, skipping segment".format(type)) + log.debug("SkipService: {0} is set to automatic skip, skipping segment".format(segment_type)) # If auto skip is enabled, skips to semgent ends automatically player.seekTime(ticks_to_seconds(dialog.end)) - xbmcgui.Dialog().notification("JellyCon", "{0} Skipped".format(type)) + xbmcgui.Dialog().notification("JellyCon", "{0} Skipped".format(segment_type)) elif skip_action == "0": # Otherwise show skip dialog if is_segment and not dialog.has_been_dissmissed: - log.debug("SkipService: {0} is playing, showing dialog".format(type)) + log.debug("SkipService: {0} is playing, showing dialog".format(segment_type)) dialog.show() else: # Could not find doc on what happens when closing a closed dialog, but it seems fine - log.debug("SkipService: {0} is not playing, closing dialog".format(type)) + log.debug("SkipService: {0} is not playing, closing dialog".format(segment_type)) dialog.close() - + return dialog - def stop_service(self): log.debug("IntroSkipperService Stop Called") diff --git a/resources/lib/intro_skipper_utils.py b/resources/lib/intro_skipper_utils.py index 1a9e46f0..c004bf0a 100644 --- a/resources/lib/intro_skipper_utils.py +++ b/resources/lib/intro_skipper_utils.py @@ -22,7 +22,7 @@ def get_setting_skip_action(type: Literal["Commercial", "Preview", "Recap", "Out elif (type == "Intro"): return settings.getSetting("intro_skipper_action") return "" - + def get_setting_skip_start_offset(type: Literal["Commercial", "Preview", "Recap", "Outro", "Intro"]): settings = xbmcaddon.Addon() if (type == "Commercial"): @@ -36,7 +36,7 @@ def get_setting_skip_start_offset(type: Literal["Commercial", "Preview", "Recap" elif (type == "Intro"): return settings.getSettingInt("intro_skipper_start_offset") return 0 - + def get_setting_skip_end_offset(type: Literal["Commercial", "Preview", "Recap", "Outro", "Intro"]): settings = xbmcaddon.Addon() if (type == "Commercial"): @@ -50,18 +50,18 @@ def get_setting_skip_end_offset(type: Literal["Commercial", "Preview", "Recap", elif (type == "Intro"): return settings.getSettingInt("intro_skipper_end_offset") return 0 - -def set_correct_skip_info(item_id: str, skip_dialog: SkipDialog, segments, type: Literal["Commercial", "Preview", "Recap", "Outro", "Intro"]): + +def set_correct_skip_info(item_id: str, skip_dialog: SkipDialog, segment: dict): if (skip_dialog.media_id is None or skip_dialog.media_id != item_id) and item_id is not None: # If playback item has changed (or is new), sets its id and set media segments info log.debug("SkipDialogInfo : Media Id has changed to {0}, setting segments".format(item_id)) skip_dialog.media_id = item_id skip_dialog.has_been_dissmissed = False - if segments is not None: + if segment is not None: # Find the intro and outro timings - start = next((segment["StartTicks"] for segment in segments if segment["Type"] == type), None) - end = next((segment["EndTicks"] for segment in segments if segment["Type"] == type), None) - + start = segment.get("StartTicks") + end = segment.get("EndTicks") + # Sets timings with offsets if defined in settings if start is not None: skip_dialog.start = start + seconds_to_ticks(get_setting_skip_start_offset(type)) @@ -69,4 +69,3 @@ def set_correct_skip_info(item_id: str, skip_dialog: SkipDialog, segments, type: if end is not None: skip_dialog.end = end - seconds_to_ticks(get_setting_skip_end_offset(type)) log.debug("SkipDialogInfo : Setting {0} end to {1}".format(type, skip_dialog.end)) - \ No newline at end of file diff --git a/resources/lib/play_utils.py b/resources/lib/play_utils.py index 69587bd9..b42fdec1 100644 --- a/resources/lib/play_utils.py +++ b/resources/lib/play_utils.py @@ -743,7 +743,7 @@ def set_list_item_props(item_id, list_item, result, server, extra_props, title): album = result.get("Album") if album: details['album'] = album - + list_item.setInfo("Music", infoLabels=details) else: @@ -1096,6 +1096,7 @@ def stop_all_playback(): clear_entries = [] home_window.clear_property("currently_playing_id") + home_window.clear_property("now_playing") for item in played_information: data = played_information.get(item) @@ -1152,7 +1153,7 @@ def get_playing_data(): play_data = json.loads(play_data_string) except ValueError: # This isn't a JellyCon item - return None + return {} played_information_string = home_window.get_property('played_information') if played_information_string: @@ -1173,7 +1174,7 @@ def get_playing_data(): playing_file = player.getPlayingFile() except Exception as e: log.error("get_playing_data : getPlayingFile() : {0}".format(e)) - return None + return {} log.debug("get_playing_data : getPlayingFile() : {0}".format(playing_file)) if server in playing_file and item_id is not None: play_time = player.getTime() @@ -1194,16 +1195,6 @@ def get_playing_data(): return {} -def get_jellyfin_playing_item(): - home_window = HomeWindow() - play_data_string = home_window.get_property('now_playing') - try: - play_data = json.loads(play_data_string) - except ValueError: - # This isn't a JellyCon item - return None - - return play_data.get("item_id") def get_play_url(media_source, play_session_id, channel_id=None): log.debug("get_play_url - media_source: {0}", media_source) @@ -1367,7 +1358,7 @@ def onPlayBackStarted(self): play_data = get_playing_data() - if play_data is None: + if not play_data: return play_data["paused"] = False @@ -1716,6 +1707,7 @@ def get_item_playback_info(item_id, force_transcode): return play_info_result + def get_media_segments(item_id): url = "/MediaSegments/{}".format(item_id) result = api.get(url)