diff --git a/resources/lib/youtube_plugin/kodion/constants/__init__.py b/resources/lib/youtube_plugin/kodion/constants/__init__.py index 58bdc8a5f..d9eca4807 100644 --- a/resources/lib/youtube_plugin/kodion/constants/__init__.py +++ b/resources/lib/youtube_plugin/kodion/constants/__init__.py @@ -35,6 +35,7 @@ ABORT_FLAG = 'abort_requested' BUSY_FLAG = 'busy' CHECK_SETTINGS = 'check_settings' +PLAYER_DATA = 'player_json' PLAYLIST_PATH = 'playlist_path' PLAYLIST_POSITION = 'playlist_position' REROUTE = 'reroute' @@ -51,6 +52,7 @@ 'CHECK_SETTINGS', 'DATA_PATH', 'MEDIA_PATH', + 'PLAYER_DATA', 'PLAYLIST_PATH', 'PLAYLIST_POSITION', 'RESOURCE_PATH', diff --git a/resources/lib/youtube_plugin/kodion/monitors/player_monitor.py b/resources/lib/youtube_plugin/kodion/monitors/player_monitor.py index 0c1bddaf5..3bdbda931 100644 --- a/resources/lib/youtube_plugin/kodion/monitors/player_monitor.py +++ b/resources/lib/youtube_plugin/kodion/monitors/player_monitor.py @@ -14,7 +14,7 @@ import threading from ..compatibility import xbmc -from ..constants import BUSY_FLAG, SWITCH_PLAYER_FLAG +from ..constants import BUSY_FLAG, PLAYER_DATA, SWITCH_PLAYER_FLAG class PlayerMonitorThread(threading.Thread): @@ -34,8 +34,8 @@ def __init__(self, player, provider, context, monitor, playback_json): self.channel_id = self.playback_json.get('channel_id') self.video_status = self.playback_json.get('video_status') - self.total_time = 0.0 self.current_time = 0.0 + self.total_time = 0.0 self.progress = 0 self.daemon = True @@ -62,7 +62,7 @@ def run(self): timeout_period = 5 waited = 0 - wait_interval = 0.2 + wait_interval = 0.5 while not player.isPlaying(): if self._context.abort_requested(): break @@ -98,70 +98,62 @@ def run(self): video_id_param = 'video_id=%s' % self.video_id report_url = use_remote_history and playback_stats.get('watchtime_url') - segment_start = 0 - played_time = -1.0 - wait_interval = 0.5 + segment_start = 0.0 + report_time = -1.0 + wait_interval = 1 report_period = waited = 10 while not self.abort_now(): try: current_file = player.getPlayingFile() - self.current_time = player.getTime() - self.total_time = player.getTotalTime() + played_time = player.getTime() + total_time = player.getTotalTime() + player.current_time = played_time + player.total_time = total_time except RuntimeError: self.stop() break - if (current_file != playing_file and not ( + if ((current_file != playing_file and not ( self._context.is_plugin_path(current_file, 'play/') - and video_id_param in current_file)): + and video_id_param in current_file + )) or total_time <= 0): self.stop() break - if self.current_time < 0: - self.current_time = 0.0 - - if self.total_time <= 0: - self.stop() - break - self.progress = int(100 * self.current_time / self.total_time) + _seek_time = player.start_time or player.seek_time + if waited and _seek_time and played_time < _seek_time: + waited = 0 + player.seekTime(_seek_time) + continue - if player.start_time or player.seek_time: - _seek_time = player.start_time or player.seek_time - if self.current_time < _seek_time: - player.seekTime(_seek_time) - try: - self.current_time = player.getTime() - except RuntimeError: - self.stop() - break - - if player.end_time and self.current_time >= player.end_time: - if clip and player.start_time: + if player.end_time and played_time >= player.end_time: + if waited and clip and player.start_time: + waited = 0 player.seekTime(player.start_time) - else: - player.stop() + continue + player.stop() if waited >= report_period: waited = 0 last_state = state - if self.current_time == played_time: + if played_time == report_time: state = 'paused' else: state = 'playing' - played_time = self.current_time + report_time = played_time if logged_in and report_url: if state == 'playing': - segment_end = self.current_time + segment_end = played_time else: segment_end = segment_start if segment_start > segment_end: segment_end = segment_start + report_period - if segment_end > self.total_time: - segment_end = self.total_time + if segment_end > total_time: + segment_end = total_time # only report state='paused' once if state == 'playing' or last_state == 'playing': @@ -173,7 +165,7 @@ def run(self): self._context, self.video_id, report_url, - status=(self.current_time, + status=(played_time, segment_start, segment_end, state), @@ -184,6 +176,11 @@ def run(self): self._monitor.waitForAbort(wait_interval) waited += wait_interval + self.current_time = player.current_time + self.total_time = player.total_time + if self.total_time > 0: + self.progress = int(100 * self.current_time / self.total_time) + state = 'stopped' self._context.send_notification('PlaybackStopped', { 'video_id': self.video_id, @@ -204,7 +201,7 @@ def run(self): if self.progress >= settings.get_play_count_min_percent(): play_count += 1 - self.current_time = 0.0 + self.current_time = 0 segment_end = self.total_time else: segment_end = self.current_time @@ -305,6 +302,8 @@ def __init__(self, provider, context, monitor): self.seek_time = None self.start_time = None self.end_time = None + self.current_time = None + self.total_time = None def stop_threads(self): for thread in self.threads: @@ -360,10 +359,10 @@ def onAVStarted(self): if not self._ui.busy_dialog_active(): self._ui.clear_property(BUSY_FLAG) - playback_json = self._ui.get_property('playback_json') + playback_json = self._ui.get_property(PLAYER_DATA) if not playback_json: return - self._ui.clear_property('playback_json') + self._ui.clear_property(PLAYER_DATA) self.cleanup_threads() playback_json = json.loads(playback_json) @@ -371,10 +370,14 @@ def onAVStarted(self): self.seek_time = float(playback_json.get('seek_time')) self.start_time = float(playback_json.get('start_time')) self.end_time = float(playback_json.get('end_time')) - except (ValueError, TypeError): + self.current_time = max(0.0, self.getTime()) + self.total_time = max(0.0, self.getTotalTime()) + except (ValueError, TypeError, RuntimeError): self.seek_time = None self.start_time = None self.end_time = None + self.current_time = 0.0 + self.total_time = 0.0 self.threads.append(PlayerMonitorThread(self, self._provider, @@ -400,6 +403,7 @@ def onPlayBackError(self): def onPlayBackSeek(self, time, seekOffset): time_s = time / 1000 + self.current_time = time_s self.seek_time = None if ((self.end_time and time_s > self.end_time + 1) or (self.start_time and time_s < self.start_time - 1)): diff --git a/resources/lib/youtube_plugin/youtube/helper/yt_play.py b/resources/lib/youtube_plugin/youtube/helper/yt_play.py index f7fe89fa3..d09675bee 100644 --- a/resources/lib/youtube_plugin/youtube/helper/yt_play.py +++ b/resources/lib/youtube_plugin/youtube/helper/yt_play.py @@ -17,7 +17,7 @@ from ..helper import utils, v3 from ..youtube_exceptions import YouTubeException from ...kodion.compatibility import urlencode, urlunsplit -from ...kodion.constants import SWITCH_PLAYER_FLAG, paths +from ...kodion.constants import PLAYER_DATA, SWITCH_PLAYER_FLAG, paths from ...kodion.items import VideoItem from ...kodion.network import get_connect_address from ...kodion.utils import select_stream @@ -147,8 +147,7 @@ def play_video(provider, context): 'refresh_only': screensaver } - ui.set_property('playback_json', json.dumps(playback_json, - ensure_ascii=False)) + ui.set_property(PLAYER_DATA, json.dumps(playback_json, ensure_ascii=False)) context.send_notification('PlaybackInit', { 'video_id': video_id, 'channel_id': playback_json.get('channel_id', ''),