Skip to content

Commit

Permalink
Improve player monitoring when seeking #746
Browse files Browse the repository at this point in the history
  • Loading branch information
MoojMidge committed May 7, 2024
1 parent 870ed79 commit f183da1
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 44 deletions.
2 changes: 2 additions & 0 deletions resources/lib/youtube_plugin/kodion/constants/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -51,6 +52,7 @@
'CHECK_SETTINGS',
'DATA_PATH',
'MEDIA_PATH',
'PLAYER_DATA',
'PLAYLIST_PATH',
'PLAYLIST_POSITION',
'RESOURCE_PATH',
Expand Down
86 changes: 45 additions & 41 deletions resources/lib/youtube_plugin/kodion/monitors/player_monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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':
Expand All @@ -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),
Expand All @@ -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,
Expand All @@ -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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -360,21 +359,25 @@ 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)
try:
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,
Expand All @@ -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)):
Expand Down
5 changes: 2 additions & 3 deletions resources/lib/youtube_plugin/youtube/helper/yt_play.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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', ''),
Expand Down

0 comments on commit f183da1

Please sign in to comment.