From f78599744f95ef1b91523f16f1e0df48ce02bf84 Mon Sep 17 00:00:00 2001
From: MoojMidge <56883549+MoojMidge@users.noreply.github.com>
Date: Tue, 16 Apr 2024 22:24:25 +1000
Subject: [PATCH 01/16] Make "Support alternative player" and "Use YouTube
website urls with default player" mutually exclusive options
---
.../kodion/items/xbmc/xbmc_items.py | 6 +++--
.../kodion/settings/abstract_settings.py | 5 ++---
.../youtube_plugin/youtube/helper/yt_play.py | 2 +-
resources/settings.xml | 22 ++++++++++++-------
4 files changed, 21 insertions(+), 14 deletions(-)
diff --git a/resources/lib/youtube_plugin/kodion/items/xbmc/xbmc_items.py b/resources/lib/youtube_plugin/kodion/items/xbmc/xbmc_items.py
index 1ee9b860e..aff4f4803 100644
--- a/resources/lib/youtube_plugin/kodion/items/xbmc/xbmc_items.py
+++ b/resources/lib/youtube_plugin/kodion/items/xbmc/xbmc_items.py
@@ -381,8 +381,10 @@ def video_playback_item(context, video_item, show_fanart=None):
mime_type = uri.split('mime=', 1)[1].split('&', 1)[0]
mime_type = mime_type.replace('%2F', '/')
- if (not settings.support_alternative_player()
- and headers and uri.startswith('http')):
+ if (headers and uri.startswith('http') and not (
+ settings.default_player_web_urls()
+ or (is_external and settings.alternative_player_web_urls())
+ )):
kwargs['path'] = '|'.join((uri, headers))
list_item = xbmcgui.ListItem(**kwargs)
diff --git a/resources/lib/youtube_plugin/kodion/settings/abstract_settings.py b/resources/lib/youtube_plugin/kodion/settings/abstract_settings.py
index b73e21ae8..38d376e32 100644
--- a/resources/lib/youtube_plugin/kodion/settings/abstract_settings.py
+++ b/resources/lib/youtube_plugin/kodion/settings/abstract_settings.py
@@ -112,14 +112,13 @@ def default_player_web_urls(self, value=None):
if value is not None:
return self.set_bool(settings.DEFAULT_PLAYER_WEB_URLS, value)
if self.support_alternative_player():
- return self.get_bool(settings.DEFAULT_PLAYER_WEB_URLS, False)
- return False
+ return False
+ return self.get_bool(settings.DEFAULT_PLAYER_WEB_URLS, False)
def alternative_player_web_urls(self, value=None):
if value is not None:
return self.set_bool(settings.ALTERNATIVE_PLAYER_WEB_URLS, value)
if (self.support_alternative_player()
- and not self.default_player_web_urls()
and not self.alternative_player_adaptive()):
return self.get_bool(settings.ALTERNATIVE_PLAYER_WEB_URLS, False)
return False
diff --git a/resources/lib/youtube_plugin/youtube/helper/yt_play.py b/resources/lib/youtube_plugin/youtube/helper/yt_play.py
index 13e944752..f7fe89fa3 100644
--- a/resources/lib/youtube_plugin/youtube/helper/yt_play.py
+++ b/resources/lib/youtube_plugin/youtube/helper/yt_play.py
@@ -40,7 +40,7 @@ def play_video(provider, context):
is_external = ui.get_property(SWITCH_PLAYER_FLAG)
if ((is_external and settings.alternative_player_web_urls())
- or (not is_external and settings.default_player_web_urls())):
+ or settings.default_player_web_urls()):
video_stream = {
'url': 'https://www.youtube.com/watch?v={0}'.format(video_id),
}
diff --git a/resources/settings.xml b/resources/settings.xml
index 72c6237f4..c2a28f30d 100644
--- a/resources/settings.xml
+++ b/resources/settings.xml
@@ -573,16 +573,14 @@
- 0
- false
-
-
-
0
false
- true
+
+ true
+ false
+
@@ -595,7 +593,6 @@
true
false
- false
@@ -610,7 +607,6 @@
true
true
- true
false
@@ -618,6 +614,16 @@
+
+ 0
+ false
+
+
+ false
+
+
+
+
From 762a2d38e8bbe5f2c56e0b994961e9dcd2448839 Mon Sep 17 00:00:00 2001
From: MoojMidge <56883549+MoojMidge@users.noreply.github.com>
Date: Wed, 17 Apr 2024 00:04:54 +1000
Subject: [PATCH 02/16] Further fixes for multiple busy dialog crash workaround
# Possibly fix issues reported in comments of #704
---
.../kodion/constants/__init__.py | 2 +
.../kodion/player/xbmc/xbmc_playlist.py | 5 ++-
.../kodion/plugin/xbmc/xbmc_plugin.py | 38 +++++++++----------
3 files changed, 25 insertions(+), 20 deletions(-)
diff --git a/resources/lib/youtube_plugin/kodion/constants/__init__.py b/resources/lib/youtube_plugin/kodion/constants/__init__.py
index 8ab679579..cdc7218d4 100644
--- a/resources/lib/youtube_plugin/kodion/constants/__init__.py
+++ b/resources/lib/youtube_plugin/kodion/constants/__init__.py
@@ -34,6 +34,7 @@
BUSY_FLAG = 'busy'
SWITCH_PLAYER_FLAG = 'switch_player'
+PLAYLIST_POSITION = 'playlist_position'
WAIT_FLAG = 'builtin_running'
__all__ = (
@@ -42,6 +43,7 @@
'BUSY_FLAG',
'DATA_PATH',
'MEDIA_PATH',
+ 'PLAYLIST_POSITION',
'RESOURCE_PATH',
'SWITCH_PLAYER_FLAG',
'TEMP_PATH',
diff --git a/resources/lib/youtube_plugin/kodion/player/xbmc/xbmc_playlist.py b/resources/lib/youtube_plugin/kodion/player/xbmc/xbmc_playlist.py
index 9b66c6ae2..f35d7369e 100644
--- a/resources/lib/youtube_plugin/kodion/player/xbmc/xbmc_playlist.py
+++ b/resources/lib/youtube_plugin/kodion/player/xbmc/xbmc_playlist.py
@@ -171,12 +171,15 @@ def play_playlist_item(self, position, resume=False):
context.log_debug('Playing from playlist position: {0}'
.format(position))
+ if not resume:
+ xbmc.Player().play(self._playlist, startpos=position - 1)
+ return
# JSON Player.Open can be too slow but is needed if resuming is enabled
jsonrpc(method='Player.Open',
params={'item': {'playlistid': self._playlist.getPlayListId(),
# Convert 1 indexed to 0 indexed position
'position': position - 1}},
- options={'resume': resume},
+ options={'resume': True},
no_response=True)
def get_position(self, offset=0):
diff --git a/resources/lib/youtube_plugin/kodion/plugin/xbmc/xbmc_plugin.py b/resources/lib/youtube_plugin/kodion/plugin/xbmc/xbmc_plugin.py
index b70cd2d0a..16c3feb6c 100644
--- a/resources/lib/youtube_plugin/kodion/plugin/xbmc/xbmc_plugin.py
+++ b/resources/lib/youtube_plugin/kodion/plugin/xbmc/xbmc_plugin.py
@@ -13,7 +13,7 @@
from traceback import format_stack
from ..abstract_plugin import AbstractPlugin
-from ...constants import BUSY_FLAG
+from ...constants import BUSY_FLAG, PLAYLIST_POSITION
from ...compatibility import xbmcplugin
from ...exceptions import KodionException
from ...items import (
@@ -42,27 +42,22 @@ def run(self, provider, context):
ui = context.get_ui()
if ui.get_property(BUSY_FLAG).lower() == 'true':
- ui.clear_property(BUSY_FLAG)
if ui.busy_dialog_active():
- playlist = XbmcPlaylist('auto', context, retry=3)
- playlist.clear()
xbmcplugin.endOfDirectory(
self.handle,
succeeded=False,
updateListing=True,
)
+ playlist = XbmcPlaylist('auto', context, retry=3)
+ position, remaining = playlist.get_position()
+ items = playlist.get_items() if remaining else None
+ playlist.clear()
+
context.log_warning('Multiple busy dialogs active - '
'playlist cleared to avoid Kodi crash')
- num_items = 0
- items = ui.get_property('playlist')
- position = ui.get_property('position')
-
- if position and items:
- position = int(position)
- ui.clear_property('playlist')
-
+ if items:
max_wait_time = 30
while ui.busy_dialog_active():
max_wait_time -= 1
@@ -74,10 +69,12 @@ def run(self, provider, context):
context.log_warning('Multiple busy dialogs active - '
'reloading playlist')
- num_items = playlist.add_items(items, loads=True)
+ num_items = playlist.add_items(items)
+
+ old_position = ui.get_property(PLAYLIST_POSITION)
+ if old_position and position == int(old_position):
+ position += 1
- if position and num_items:
- position += 1
max_wait_time = min(position, num_items)
while ui.busy_dialog_active() or playlist.size() < position:
max_wait_time -= 1
@@ -89,8 +86,13 @@ def run(self, provider, context):
else:
playlist.play_playlist_item(position)
+ ui.clear_property(BUSY_FLAG)
+ ui.clear_property(PLAYLIST_POSITION)
return False
+ ui.clear_property(BUSY_FLAG)
+ ui.clear_property(PLAYLIST_POSITION)
+
if settings.is_setup_wizard_enabled():
provider.run_wizard(context)
@@ -169,10 +171,8 @@ def _set_resolved_url(self, context, base_item, show_fanart):
if not context.is_plugin_path(uri) and ui.busy_dialog_active():
ui.set_property(BUSY_FLAG, 'true')
playlist = XbmcPlaylist('auto', context)
- position, remaining = playlist.get_position()
- if remaining:
- ui.set_property('playlist', playlist.get_items(dumps=True))
- ui.set_property('position', str(position))
+ position, _ = playlist.get_position()
+ ui.set_property(PLAYLIST_POSITION, str(position))
item = playback_item(context, base_item, show_fanart)
xbmcplugin.setResolvedUrl(self.handle,
From 5ab565d4295c84accc0f70a225f04bfbd2e47c02 Mon Sep 17 00:00:00 2001
From: MoojMidge <56883549+MoojMidge@users.noreply.github.com>
Date: Wed, 17 Apr 2024 01:18:29 +1000
Subject: [PATCH 03/16] Update error checks to avoid unnecessary retries of
player request
---
.../youtube/helper/video_info.py | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/resources/lib/youtube_plugin/youtube/helper/video_info.py b/resources/lib/youtube_plugin/youtube/helper/video_info.py
index 8f2aea14d..0348a2c4d 100644
--- a/resources/lib/youtube_plugin/youtube/helper/video_info.py
+++ b/resources/lib/youtube_plugin/youtube/helper/video_info.py
@@ -1140,6 +1140,11 @@ def _get_video_info(self):
client_name = reason = status = None
client = playability_status = result = None
+ reasons = (
+ self._context.localize(574, 'country').lower(),
+ self._context.localize(10005, 'not available').lower(),
+ )
+
client_data = {'json': {'videoId': video_id}}
if self._access_token:
client_data['_access_token'] = self._access_token
@@ -1188,14 +1193,18 @@ def _get_video_info(self):
# Geo-blocked video with error reasons like:
# "This video contains content from XXX, who has blocked it in your country on copyright grounds"
# "The uploader has not made this video available in your country"
- if status == 'UNPLAYABLE' and 'country' in reason:
+ # Reason language will vary based on Accept-Language and
+ # client hl, Kodi localised language is used for comparison
+ # but may not match reason language
+ if (status == 'UNPLAYABLE'
+ and any(why in reason for why in reasons)):
break
if status != 'ERROR':
continue
# This is used to check for error like:
# "The following content is not available on this app."
- # Text will vary depending on Accept-Language and client hl
- # YouTube support url is checked instead
+ # Reason language will vary based on Accept-Language and
+ # client hl, so YouTube support url is checked instead
url = self._get_error_details(
playability_status,
details=(
@@ -1211,9 +1220,9 @@ def _get_video_info(self):
if url and url.startswith('//support.google.com/youtube/answer/12318250'):
status = 'CONTENT_NOT_AVAILABLE_IN_THIS_APP'
continue
- if video_id != video_details.get('videoId'):
+ if video_details and video_id != video_details.get('videoId'):
status = 'CONTENT_NOT_AVAILABLE_IN_THIS_APP'
- reason = 'WATCH_ON_LATEST_VERSION_OF_YOUTUBE'
+ reason = 'Watch on the latest version of YouTube'
continue
break
# Only attempt to remove Authorization header if clients iterable
From b8d0e557b06318c191e802f488103078aab03ba4 Mon Sep 17 00:00:00 2001
From: MoojMidge <56883549+MoojMidge@users.noreply.github.com>
Date: Wed, 17 Apr 2024 01:35:58 +1000
Subject: [PATCH 04/16] Version bump v7.0.6+beta.2
---
addon.xml | 2 +-
changelog.txt | 12 ++++++++++--
2 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/addon.xml b/addon.xml
index 6718c251a..d0c45af60 100644
--- a/addon.xml
+++ b/addon.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/changelog.txt b/changelog.txt
index b88bf0be0..3b3b14cca 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,3 +1,12 @@
+## v7.0.6+beta.2
+### Fixed
+- Further fixes for multiple busy dialog crash workaround
+ - Possibly fix issues reported in comments of #704
+- Update error checks to avoid unnecessary retries of player request
+
+### Changed
+- Make "Support alternative player" and "Use YouTube website urls with default player" mutually exclusive options
+
## v7.0.6+beta.1
### Fixed
- Improve updating containers and (re)loading windows #681
@@ -7,8 +16,7 @@
### Changed
- Setup Wizard default settings now disable pre-downloading subtitles if MPEG-DASH is enabled
-- Ask for quality, Play with subtitles, Play audio only context menu items only displayed if
- associated setting is not already enabled
+- Ask for quality, Play with subtitles, Play audio only context menu items only displayed if associated setting is not already enabled
- Only make extra request for subtitles for Android client when all subtitle languages are enabled
- Overhaul alternative player support due to Kodi changes and also improve external player support
From 11aa5a6985d15d9667dd8434153dcf6eea20797c Mon Sep 17 00:00:00 2001
From: MoojMidge <56883549+MoojMidge@users.noreply.github.com>
Date: Wed, 17 Apr 2024 14:05:04 +1000
Subject: [PATCH 05/16] Remove deprecated ISA manifest_type property in Kodi
v21+
---
resources/lib/youtube_plugin/kodion/items/xbmc/xbmc_items.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/resources/lib/youtube_plugin/kodion/items/xbmc/xbmc_items.py b/resources/lib/youtube_plugin/kodion/items/xbmc/xbmc_items.py
index aff4f4803..0d1f6ed8e 100644
--- a/resources/lib/youtube_plugin/kodion/items/xbmc/xbmc_items.py
+++ b/resources/lib/youtube_plugin/kodion/items/xbmc/xbmc_items.py
@@ -366,7 +366,9 @@ def video_playback_item(context, video_item, show_fanart=None):
if current_system_version.compatible(19, 0) else
'inputstreamaddon')
props[inputstream_property] = 'inputstream.adaptive'
- props['inputstream.adaptive.manifest_type'] = manifest_type
+
+ if not current_system_version.compatible(21, 0):
+ props['inputstream.adaptive.manifest_type'] = manifest_type
if headers:
props['inputstream.adaptive.manifest_headers'] = headers
From 9c9e448a8cbca7273b4836070877dd3a34e07520 Mon Sep 17 00:00:00 2001
From: MoojMidge <56883549+MoojMidge@users.noreply.github.com>
Date: Thu, 18 Apr 2024 02:37:34 +1000
Subject: [PATCH 06/16] Re-enable Opus audio by default, but only use it with
Kodi v21+
- Closes #537
- Underlying issue fixed by xbmc/xbmc#24748
---
.../kodion/context/xbmc/xbmc_context.py | 4 ++--
.../youtube/helper/yt_setup_wizard.py | 14 +++++++-------
resources/settings.xml | 3 +--
3 files changed, 10 insertions(+), 11 deletions(-)
diff --git a/resources/lib/youtube_plugin/kodion/context/xbmc/xbmc_context.py b/resources/lib/youtube_plugin/kodion/context/xbmc/xbmc_context.py
index ea3403aba..d22419e23 100644
--- a/resources/lib/youtube_plugin/kodion/context/xbmc/xbmc_context.py
+++ b/resources/lib/youtube_plugin/kodion/context/xbmc/xbmc_context.py
@@ -610,8 +610,8 @@ def use_inputstream_adaptive(self):
'ttml': loose_version('20.0.0'),
# audio codecs
'vorbis': loose_version('2.3.14'),
- # unknown when Opus audio support was implemented
- 'opus': loose_version('19.0.0'),
+ # Opus audio enabled in Kodi v21+ which fixes stalls after seek
+ 'opus': loose_version('21.0.0'),
'mp4a': True,
'ac-3': loose_version('2.1.15'),
'ec-3': loose_version('2.1.15'),
diff --git a/resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py b/resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py
index a7fbe306e..77422f836 100644
--- a/resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py
+++ b/resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py
@@ -373,7 +373,7 @@ def process_performance_settings(_provider, context, step, steps):
},
'1080p30_avc': {
'max_resolution': 4, # 1080p
- 'stream_features': ('avc1', 'vorbis', 'mp4a', 'filter'),
+ 'stream_features': ('avc1', 'vorbis', 'opus', 'mp4a', 'filter'),
'num_items': 10,
'settings': (
(settings.client_selection, (2,)),
@@ -381,32 +381,32 @@ def process_performance_settings(_provider, context, step, steps):
},
'1080p30': {
'max_resolution': 4, # 1080p
- 'stream_features': ('avc1', 'vp9', 'vorbis', 'mp4a', 'ssa', 'ac-3', 'ec-3', 'dts', 'filter'),
+ 'stream_features': ('avc1', 'vp9', 'vorbis', 'opus', 'mp4a', 'ssa', 'ac-3', 'ec-3', 'dts', 'filter'),
'num_items': 20,
},
'1080p60': {
'max_resolution': 4, # 1080p
- 'stream_features': ('avc1', 'vp9', 'hfr', 'vorbis', 'mp4a', 'ssa', 'ac-3', 'ec-3', 'dts', 'filter'),
+ 'stream_features': ('avc1', 'vp9', 'hfr', 'vorbis', 'opus', 'mp4a', 'ssa', 'ac-3', 'ec-3', 'dts', 'filter'),
'num_items': 30,
},
'4k30': {
'max_resolution': 6, # 4k
- 'stream_features': ('avc1', 'vp9', 'hdr', 'hfr', 'no_hfr_max', 'vorbis', 'mp4a', 'ssa', 'ac-3', 'ec-3', 'dts', 'filter'),
+ 'stream_features': ('avc1', 'vp9', 'hdr', 'hfr', 'no_hfr_max', 'vorbis', 'opus', 'mp4a', 'ssa', 'ac-3', 'ec-3', 'dts', 'filter'),
'num_items': 50,
},
'4k60': {
'max_resolution': 6, # 4k
- 'stream_features': ('avc1', 'vp9', 'hdr', 'hfr', 'vorbis', 'mp4a', 'ssa', 'ac-3', 'ec-3', 'dts', 'filter'),
+ 'stream_features': ('avc1', 'vp9', 'hdr', 'hfr', 'vorbis', 'opus', 'mp4a', 'ssa', 'ac-3', 'ec-3', 'dts', 'filter'),
'num_items': 50,
},
'4k60_av1': {
'max_resolution': 6, # 4k
- 'stream_features': ('avc1', 'vp9', 'av01', 'hdr', 'hfr', 'vorbis', 'mp4a', 'ssa', 'ac-3', 'ec-3', 'dts', 'filter'),
+ 'stream_features': ('avc1', 'vp9', 'av01', 'hdr', 'hfr', 'vorbis', 'opus', 'mp4a', 'ssa', 'ac-3', 'ec-3', 'dts', 'filter'),
'num_items': 50,
},
'max': {
'max_resolution': 7, # 8k
- 'stream_features': ('avc1', 'vp9', 'av01', 'hdr', 'hfr', 'vorbis', 'mp4a', 'ssa', 'ac-3', 'ec-3', 'dts', 'filter'),
+ 'stream_features': ('avc1', 'vp9', 'av01', 'hdr', 'hfr', 'vorbis', 'opus', 'mp4a', 'ssa', 'ac-3', 'ec-3', 'dts', 'filter'),
'num_items': 50,
},
}
diff --git a/resources/settings.xml b/resources/settings.xml
index c2a28f30d..8c250954a 100644
--- a/resources/settings.xml
+++ b/resources/settings.xml
@@ -115,12 +115,11 @@
0
- avc1,vp9,av01,hdr,hfr,vorbis,mp4a,ssa,ac-3,ec-3,dts,filter
+ avc1,vp9,av01,hdr,hfr,vorbis,opus,mp4a,ssa,ac-3,ec-3,dts,filter
From 71cc472680a6bb3c90f7aadd3718e0a2f21f6829 Mon Sep 17 00:00:00 2001
From: MoojMidge <56883549+MoojMidge@users.noreply.github.com>
Date: Thu, 18 Apr 2024 09:09:02 +1000
Subject: [PATCH 07/16] Prefer MPEG-DASH for live streams
- Close #680
---
resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py | 2 +-
resources/settings.xml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py b/resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py
index 77422f836..7aa362f3e 100644
--- a/resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py
+++ b/resources/lib/youtube_plugin/youtube/helper/yt_setup_wizard.py
@@ -322,7 +322,7 @@ def process_default_settings(_provider, context, step, steps):
settings.use_mpd_videos(True)
settings.stream_select(4 if settings.ask_for_video_quality() else 3)
settings.set_subtitle_download(False)
- settings.live_stream_type(2)
+ settings.live_stream_type(3)
if not xbmcvfs.exists('special://profile/playercorefactory.xml'):
settings.default_player_web_urls(False)
if settings.cache_size() < 20:
diff --git a/resources/settings.xml b/resources/settings.xml
index 8c250954a..fad839fd0 100644
--- a/resources/settings.xml
+++ b/resources/settings.xml
@@ -665,7 +665,7 @@
0
- 2
+ 3
From afe236cc9591613a96c18ec97f1c3cacb50a7384 Mon Sep 17 00:00:00 2001
From: MoojMidge <56883549+MoojMidge@users.noreply.github.com>
Date: Thu, 18 Apr 2024 09:14:21 +1000
Subject: [PATCH 08/16] Bump kodion.setup_wizard.forced_runs min value required
- Use forced Setup Wizard to update changes in default settings
---
.../lib/youtube_plugin/kodion/settings/abstract_settings.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/resources/lib/youtube_plugin/kodion/settings/abstract_settings.py b/resources/lib/youtube_plugin/kodion/settings/abstract_settings.py
index 38d376e32..7c825657a 100644
--- a/resources/lib/youtube_plugin/kodion/settings/abstract_settings.py
+++ b/resources/lib/youtube_plugin/kodion/settings/abstract_settings.py
@@ -96,7 +96,7 @@ def get_search_history_size(self):
def is_setup_wizard_enabled(self):
# Increment min_required on new release to enable oneshot on first run
- min_required = 2
+ min_required = 3
forced_runs = self.get_int(settings.SETUP_WIZARD_RUNS, min_required - 1)
if forced_runs < min_required:
self.set_int(settings.SETUP_WIZARD_RUNS, min_required)
From 7796ddc8dc102fea710ecac254579585614a3f7d Mon Sep 17 00:00:00 2001
From: MoojMidge <56883549+MoojMidge@users.noreply.github.com>
Date: Thu, 18 Apr 2024 19:57:30 +1000
Subject: [PATCH 09/16] Update conditions used enable http server after
settings change
- Align with initial conditions checked during ServiceMonitor.__init__ after 0d4afbe
---
.../lib/youtube_plugin/kodion/monitors/service_monitor.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/resources/lib/youtube_plugin/kodion/monitors/service_monitor.py b/resources/lib/youtube_plugin/kodion/monitors/service_monitor.py
index d11efb1f6..a97df29eb 100644
--- a/resources/lib/youtube_plugin/kodion/monitors/service_monitor.py
+++ b/resources/lib/youtube_plugin/kodion/monitors/service_monitor.py
@@ -85,7 +85,9 @@ def onSettingsChanged(self):
'plugin://{0}/'.format(ADDON_ID))):
xbmc.executebuiltin('Container.Refresh')
- use_httpd = settings.use_isa() or settings.api_config_page()
+ use_httpd = (settings.use_isa()
+ or settings.api_config_page()
+ or settings.support_alternative_player())
address, port = get_connect_address()
whitelist = settings.httpd_whitelist()
From a8827d830342c5ad2a401d2c9557f3cd75f54e76 Mon Sep 17 00:00:00 2001
From: MoojMidge <56883549+MoojMidge@users.noreply.github.com>
Date: Fri, 19 Apr 2024 06:57:26 +1000
Subject: [PATCH 10/16] Shutdown http server on idle
- Attempt to shutdown before network interface stops #699
- Can't use onScreensaverActivated/onScreensaverDeactivated as screensaver may not be enababled
---
.../kodion/context/abstract_context.py | 4 +++
.../kodion/context/xbmc/xbmc_context.py | 4 +++
.../kodion/monitors/service_monitor.py | 3 ++
.../youtube_plugin/kodion/service_runner.py | 28 +++++++++++++------
4 files changed, 30 insertions(+), 9 deletions(-)
diff --git a/resources/lib/youtube_plugin/kodion/context/abstract_context.py b/resources/lib/youtube_plugin/kodion/context/abstract_context.py
index c5eaecf87..e7012c7fe 100644
--- a/resources/lib/youtube_plugin/kodion/context/abstract_context.py
+++ b/resources/lib/youtube_plugin/kodion/context/abstract_context.py
@@ -386,6 +386,10 @@ def execute(command):
def sleep(timeout=None):
raise NotImplementedError()
+ @staticmethod
+ def get_infobool(name):
+ raise NotImplementedError()
+
@staticmethod
def get_infolabel(name):
raise NotImplementedError()
diff --git a/resources/lib/youtube_plugin/kodion/context/xbmc/xbmc_context.py b/resources/lib/youtube_plugin/kodion/context/xbmc/xbmc_context.py
index d22419e23..48a3c1cdf 100644
--- a/resources/lib/youtube_plugin/kodion/context/xbmc/xbmc_context.py
+++ b/resources/lib/youtube_plugin/kodion/context/xbmc/xbmc_context.py
@@ -660,6 +660,10 @@ def inputstream_adaptive_auto_stream_selection():
def abort_requested(self):
return self.get_ui().get_property('abort_requested').lower() == 'true'
+ @staticmethod
+ def get_infobool(name):
+ return xbmc.getCondVisibility(name)
+
@staticmethod
def get_infolabel(name):
return xbmc.getInfoLabel(name)
diff --git a/resources/lib/youtube_plugin/kodion/monitors/service_monitor.py b/resources/lib/youtube_plugin/kodion/monitors/service_monitor.py
index a97df29eb..bd0817701 100644
--- a/resources/lib/youtube_plugin/kodion/monitors/service_monitor.py
+++ b/resources/lib/youtube_plugin/kodion/monitors/service_monitor.py
@@ -168,3 +168,6 @@ def restart_httpd(self):
@staticmethod
def ping_httpd():
return httpd_status()
+
+ def httpd_required(self):
+ return self._use_httpd
diff --git a/resources/lib/youtube_plugin/kodion/service_runner.py b/resources/lib/youtube_plugin/kodion/service_runner.py
index f48e6c77d..447be67a8 100644
--- a/resources/lib/youtube_plugin/kodion/service_runner.py
+++ b/resources/lib/youtube_plugin/kodion/service_runner.py
@@ -10,7 +10,7 @@
from __future__ import absolute_import, division, unicode_literals
-from .constants import TEMP_PATH
+from .constants import ADDON_ID, TEMP_PATH
from .context import XbmcContext
from .monitors import PlayerMonitor, ServiceMonitor
from .utils import rm_dir
@@ -36,20 +36,30 @@ def run():
wait_interval = 10
ping_period = waited = 60
restart_attempts = 0
+ plugin_url = 'plugin://{0}/'.format(ADDON_ID)
while not monitor.abortRequested():
- if waited >= ping_period:
+ if not monitor.httpd:
+ if (monitor.httpd_required()
+ and not context.get_infobool('System.IdleTime(10)')):
+ monitor.start_httpd()
+ elif context.get_infobool('System.IdleTime(30)'):
+ monitor.shutdown_httpd()
+ elif waited >= ping_period:
waited = 0
-
- if monitor.httpd and not monitor.ping_httpd():
+ if monitor.ping_httpd():
+ restart_attempts = 0
+ elif restart_attempts < 5:
+ monitor.restart_httpd()
restart_attempts += 1
- if restart_attempts > 5:
- monitor.shutdown_httpd()
- restart_attempts = 0
- else:
- monitor.restart_httpd()
else:
+ monitor.shutdown_httpd()
restart_attempts = 0
+ if context.get_infolabel('Container.FolderPath').startswith(plugin_url):
+ wait_interval = 1
+ else:
+ wait_interval = 10
+
if monitor.waitForAbort(wait_interval):
break
waited += wait_interval
From d5b3935485ceec79b9198788b3fac8134314d790 Mon Sep 17 00:00:00 2001
From: MoojMidge <56883549+MoojMidge@users.noreply.github.com>
Date: Fri, 19 Apr 2024 08:08:03 +1000
Subject: [PATCH 11/16] Misc tidy ups
---
.../kodion/context/xbmc/xbmc_context.py | 10 +++++-----
resources/lib/youtube_plugin/kodion/plugin_runner.py | 11 +++++------
2 files changed, 10 insertions(+), 11 deletions(-)
diff --git a/resources/lib/youtube_plugin/kodion/context/xbmc/xbmc_context.py b/resources/lib/youtube_plugin/kodion/context/xbmc/xbmc_context.py
index 48a3c1cdf..15866b644 100644
--- a/resources/lib/youtube_plugin/kodion/context/xbmc/xbmc_context.py
+++ b/resources/lib/youtube_plugin/kodion/context/xbmc/xbmc_context.py
@@ -370,14 +370,14 @@ def format_time(time_obj, str_format=None):
@staticmethod
def get_language():
language = xbmc.getLanguage(format=xbmc.ISO_639_1, region=True)
- lang_code, seperator, region = language.partition('-')
+ lang_code, separator, region = language.partition('-')
if not lang_code:
language = xbmc.getLanguage(format=xbmc.ISO_639_2, region=False)
- lang_code, seperator, region = language.partition('-')
+ lang_code, separator, region = language.partition('-')
if not lang_code:
return 'en-US'
if region:
- return seperator.join((lang_code.lower(), region.upper()))
+ return separator.join((lang_code.lower(), region.upper()))
return lang_code
def get_language_name(self, lang_id=None):
@@ -549,7 +549,7 @@ def execute(self, command, wait=False, wait_for=None):
@staticmethod
def sleep(timeout=None):
- wait(timeout)
+ return wait(timeout)
def addon_enabled(self, addon_id):
response = jsonrpc(method='Addons.GetAddonDetails',
@@ -590,7 +590,7 @@ def use_inputstream_adaptive(self):
if self.addon_enabled('inputstream.adaptive'):
success = True
elif self.get_ui().on_yes_no_input(
- self.get_name(), self.localize('isa.enable.confirm')
+ self.get_name(), self.localize('isa.enable.confirm')
):
success = self.set_addon_enabled('inputstream.adaptive')
else:
diff --git a/resources/lib/youtube_plugin/kodion/plugin_runner.py b/resources/lib/youtube_plugin/kodion/plugin_runner.py
index 45a659881..44509c2b5 100644
--- a/resources/lib/youtube_plugin/kodion/plugin_runner.py
+++ b/resources/lib/youtube_plugin/kodion/plugin_runner.py
@@ -15,9 +15,12 @@
def run(provider, context=None):
- from .compatibility import xbmc
+ if not context:
+ from .context import XbmcContext
+
+ context = XbmcContext()
- profiler = xbmc.getCondVisibility('System.GetBool(debug.showloginfo)')
+ profiler = context.get_infobool('System.GetBool(debug.showloginfo)')
if profiler:
from .debug import Profiler
@@ -29,10 +32,6 @@ def run(provider, context=None):
from .plugin import XbmcPlugin
plugin = XbmcPlugin()
- if not context:
- from .context import XbmcContext
-
- context = XbmcContext()
context.log_debug('Starting Kodion framework by bromix...')
From 9f32064693f0bf54beeaf842c0503d9db0fd41b2 Mon Sep 17 00:00:00 2001
From: MoojMidge <56883549+MoojMidge@users.noreply.github.com>
Date: Thu, 18 Apr 2024 11:10:41 +1000
Subject: [PATCH 12/16] Update changelog
---
changelog.txt | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/changelog.txt b/changelog.txt
index 3b3b14cca..bc4ccf12c 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -2,10 +2,14 @@
### Fixed
- Further fixes for multiple busy dialog crash workaround
- Possibly fix issues reported in comments of #704
-- Update error checks to avoid unnecessary retries of player request
+- Update error checks to avoid unnecessary retries of player requests
### Changed
-- Make "Support alternative player" and "Use YouTube website urls with default player" mutually exclusive options
+- Make "Support alternative player" and "Use YouTube website urls with default player" mutually exclusive options #692
+- Enable OPUS audio by default #537
+- Enable MPEG-DASH for live streams by default #680
+- Setup Wizard will prompt to run when plugin first opens after updating, in order to update default settings
+- http server will shutdown on idle timeout #699
## v7.0.6+beta.1
### Fixed
From ab76a2eea97de621c20a8525c9a2aacd2514257e Mon Sep 17 00:00:00 2001
From: MoojMidge <56883549+MoojMidge@users.noreply.github.com>
Date: Fri, 19 Apr 2024 11:31:41 +1000
Subject: [PATCH 13/16] Only use first two letters of fallback ISO_639_2
language code/region
- With exception for fil -> fi
- Just in case xbmc.getLanguage ever gets fixed or even more broken
- Also tidy up related variable names
---
.../kodion/context/xbmc/xbmc_context.py | 3 +++
.../youtube_plugin/kodion/script_actions.py | 10 +++++-----
.../youtube/helper/subtitles.py | 20 ++++++++++---------
.../lib/youtube_plugin/youtube/provider.py | 8 ++++----
4 files changed, 23 insertions(+), 18 deletions(-)
diff --git a/resources/lib/youtube_plugin/kodion/context/xbmc/xbmc_context.py b/resources/lib/youtube_plugin/kodion/context/xbmc/xbmc_context.py
index 15866b644..eb5b9c099 100644
--- a/resources/lib/youtube_plugin/kodion/context/xbmc/xbmc_context.py
+++ b/resources/lib/youtube_plugin/kodion/context/xbmc/xbmc_context.py
@@ -374,6 +374,9 @@ def get_language():
if not lang_code:
language = xbmc.getLanguage(format=xbmc.ISO_639_2, region=False)
lang_code, separator, region = language.partition('-')
+ if lang_code != 'fil':
+ lang_code = lang_code[:2]
+ region = region[:2]
if not lang_code:
return 'en-US'
if region:
diff --git a/resources/lib/youtube_plugin/kodion/script_actions.py b/resources/lib/youtube_plugin/kodion/script_actions.py
index 9a85dfc00..f6db310f2 100644
--- a/resources/lib/youtube_plugin/kodion/script_actions.py
+++ b/resources/lib/youtube_plugin/kodion/script_actions.py
@@ -41,16 +41,16 @@ def _config_actions(context, action, *_args):
xbmc.executebuiltin('InstallAddon(script.module.inputstreamhelper)')
elif action == 'subtitles':
- sub_lang = context.get_subtitle_language()
+ kodi_sub_lang = context.get_subtitle_language()
plugin_lang = settings.get_language()
sub_selection = settings.get_subtitle_selection()
- if not sub_lang:
+ if not kodi_sub_lang:
preferred = (plugin_lang,)
- elif sub_lang.partition('-')[0] != plugin_lang.partition('-')[0]:
- preferred = (sub_lang, plugin_lang)
+ elif kodi_sub_lang.partition('-')[0] != plugin_lang.partition('-')[0]:
+ preferred = (kodi_sub_lang, plugin_lang)
else:
- preferred = (sub_lang,)
+ preferred = (kodi_sub_lang,)
fallback = ('ASR' if preferred[0].startswith('en') else
context.get_language_name('en'))
diff --git a/resources/lib/youtube_plugin/youtube/helper/subtitles.py b/resources/lib/youtube_plugin/youtube/helper/subtitles.py
index 2ee3f8c69..a669705af 100644
--- a/resources/lib/youtube_plugin/youtube/helper/subtitles.py
+++ b/resources/lib/youtube_plugin/youtube/helper/subtitles.py
@@ -66,16 +66,18 @@ def __init__(self, context, video_id):
else:
self.FORMATS['_default'] = 'vtt'
- sub_lang = context.get_subtitle_language()
- ui_lang = settings.get_language()
- if not sub_lang and ui_lang:
- self.preferred_lang = (ui_lang,)
- elif sub_lang:
- if (ui_lang and
- sub_lang.partition('-')[0] != ui_lang.partition('-')[0]):
- self.preferred_lang = (sub_lang, ui_lang)
+ kodi_sub_lang = context.get_subtitle_language()
+ plugin_lang = settings.get_language()
+ if not kodi_sub_lang and plugin_lang:
+ self.preferred_lang = (plugin_lang,)
+ elif kodi_sub_lang:
+ if not plugin_lang:
+ self.preferred_lang = (kodi_sub_lang,)
+ elif (plugin_lang.partition('-')[0]
+ != kodi_sub_lang.partition('-')[0]):
+ self.preferred_lang = (kodi_sub_lang, plugin_lang)
else:
- self.preferred_lang = (sub_lang,)
+ self.preferred_lang = (kodi_sub_lang,)
else:
self.preferred_lang = ('en',)
diff --git a/resources/lib/youtube_plugin/youtube/provider.py b/resources/lib/youtube_plugin/youtube/provider.py
index c6781d20e..c461e2e66 100644
--- a/resources/lib/youtube_plugin/youtube/provider.py
+++ b/resources/lib/youtube_plugin/youtube/provider.py
@@ -129,8 +129,8 @@ def get_client(self, context):
items_per_page = settings.items_per_page()
- language = settings.get_language()
- region = settings.get_region()
+ plugin_lang = settings.get_language()
+ plugin_region = settings.get_region()
api_last_origin = access_manager.get_last_origin()
@@ -220,8 +220,8 @@ def get_client(self, context):
context.log_debug('Access token count: |%d| Refresh token count: |%d|' % (len(access_tokens), len(refresh_tokens)))
client = YouTube(context=context,
- language=language,
- region=region,
+ language=plugin_lang,
+ region=plugin_region,
items_per_page=items_per_page,
config=dev_keys if dev_keys else youtube_config)
From ca4d3478bbff84aed4ef868327768a67c2458a89 Mon Sep 17 00:00:00 2001
From: MoojMidge <56883549+MoojMidge@users.noreply.github.com>
Date: Sun, 21 Apr 2024 02:22:09 +1000
Subject: [PATCH 14/16] Fix using empty str for date related infolabels if
value not set
---
.../kodion/compatibility/__init__.py | 8 ++----
.../youtube_plugin/kodion/items/base_item.py | 26 +++++++++---------
.../youtube_plugin/kodion/items/video_item.py | 27 +++++++++----------
3 files changed, 27 insertions(+), 34 deletions(-)
diff --git a/resources/lib/youtube_plugin/kodion/compatibility/__init__.py b/resources/lib/youtube_plugin/kodion/compatibility/__init__.py
index d8cf14ef9..b63f5ea75 100644
--- a/resources/lib/youtube_plugin/kodion/compatibility/__init__.py
+++ b/resources/lib/youtube_plugin/kodion/compatibility/__init__.py
@@ -132,12 +132,8 @@ def to_str(value):
# Kodi v20+
if hasattr(xbmcgui.ListItem, 'setDateTime'):
def datetime_infolabel(datetime_obj):
- if datetime_obj:
- return datetime_obj.replace(microsecond=0, tzinfo=None).isoformat()
- return ''
+ return datetime_obj.replace(microsecond=0, tzinfo=None).isoformat()
# Compatibility shims for Kodi v18 and v19
else:
def datetime_infolabel(datetime_obj):
- if datetime_obj:
- return datetime_obj.strftime('%d.%m.%Y')
- return ''
+ return datetime_obj.strftime('%d.%m.%Y')
diff --git a/resources/lib/youtube_plugin/kodion/items/base_item.py b/resources/lib/youtube_plugin/kodion/items/base_item.py
index 32e862c3d..c40f77239 100644
--- a/resources/lib/youtube_plugin/kodion/items/base_item.py
+++ b/resources/lib/youtube_plugin/kodion/items/base_item.py
@@ -143,14 +143,13 @@ def set_date_from_datetime(self, date_time):
self._date = date_time
def get_date(self, as_text=False, short=False, as_info_label=False):
- if not self._date:
- return ''
- if short:
- return self._date.date().strftime('%x')
- if as_text:
- return self._date.strftime('%x %X')
- if as_info_label:
- return datetime_infolabel(self._date)
+ if self._date:
+ if as_info_label:
+ return datetime_infolabel(self._date)
+ if short:
+ return self._date.date().strftime('%x')
+ if as_text:
+ return self._date.strftime('%x %X')
return self._date
def set_dateadded(self, year, month, day, hour=0, minute=0, second=0):
@@ -165,12 +164,11 @@ def set_dateadded_from_datetime(self, date_time):
self._dateadded = date_time
def get_dateadded(self, as_text=False, as_info_label=False):
- if not self._dateadded:
- return ''
- if as_text:
- return self._dateadded.strftime('%x %X')
- if as_info_label:
- return datetime_infolabel(self._date)
+ if self._dateadded:
+ if as_info_label:
+ return datetime_infolabel(self._dateadded)
+ if as_text:
+ return self._dateadded.strftime('%x %X')
return self._dateadded
def set_added_utc(self, date_time):
diff --git a/resources/lib/youtube_plugin/kodion/items/video_item.py b/resources/lib/youtube_plugin/kodion/items/video_item.py
index acfabd368..931b4a3f8 100644
--- a/resources/lib/youtube_plugin/kodion/items/video_item.py
+++ b/resources/lib/youtube_plugin/kodion/items/video_item.py
@@ -123,12 +123,11 @@ def set_premiered_from_datetime(self, date_time):
self._premiered = date_time.date()
def get_premiered(self, as_text=True, as_info_label=False):
- if not self._premiered:
- return ''
- if as_info_label:
- return self._premiered.isoformat()
- if as_text:
- return self._premiered.strftime('%x')
+ if self._premiered:
+ if as_info_label:
+ return self._premiered.isoformat()
+ if as_text:
+ return self._premiered.strftime('%x')
return self._premiered
def set_plot(self, plot):
@@ -228,12 +227,11 @@ def set_aired_from_datetime(self, date_time):
self._aired = date_time.date()
def get_aired(self, as_text=True, as_info_label=False):
- if not self._aired:
- return ''
- if as_info_label:
- return self._aired.isoformat()
- if as_text:
- return self._aired.strftime('%x')
+ if self._aired:
+ if as_info_label:
+ return self._aired.isoformat()
+ if as_text:
+ return self._aired.strftime('%x')
return self._aired
def set_scheduled_start_utc(self, date_time):
@@ -319,8 +317,9 @@ def set_last_played(self, last_played):
self._last_played = last_played
def get_last_played(self, as_info_label=False):
- if as_info_label:
- return datetime_infolabel(self._last_played)
+ if self._last_played:
+ if as_info_label:
+ return datetime_infolabel(self._last_played)
return self._last_played
def set_start_percent(self, start_percent):
From 2b58a0136da9fcc45a508dd86b1e7a18c4a773cf Mon Sep 17 00:00:00 2001
From: MoojMidge <56883549+MoojMidge@users.noreply.github.com>
Date: Sun, 21 Apr 2024 02:25:53 +1000
Subject: [PATCH 15/16] Fix Python 2 JSONEncoder internally trying to join
unicode values with str values
---
resources/lib/youtube_plugin/kodion/items/base_item.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/resources/lib/youtube_plugin/kodion/items/base_item.py b/resources/lib/youtube_plugin/kodion/items/base_item.py
index c40f77239..32af94419 100644
--- a/resources/lib/youtube_plugin/kodion/items/base_item.py
+++ b/resources/lib/youtube_plugin/kodion/items/base_item.py
@@ -239,4 +239,7 @@ def encode(self, obj, nested=False):
}
else:
output = obj
- return output if nested else super(_Encoder, self).encode(output)
+
+ if nested:
+ return to_str(output)
+ return super(_Encoder, self).encode(output)
From 3df4000ad5362e4d1bd94d2fa3225069dc80cefe Mon Sep 17 00:00:00 2001
From: MoojMidge <56883549+MoojMidge@users.noreply.github.com>
Date: Sun, 21 Apr 2024 15:44:58 +1000
Subject: [PATCH 16/16] Close stream that profiler stats are written to in
finally statement
- In case some other error causes the profiler to fail
---
resources/lib/youtube_plugin/kodion/debug.py | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/resources/lib/youtube_plugin/kodion/debug.py b/resources/lib/youtube_plugin/kodion/debug.py
index 81002d9c8..72712c0df 100644
--- a/resources/lib/youtube_plugin/kodion/debug.py
+++ b/resources/lib/youtube_plugin/kodion/debug.py
@@ -206,11 +206,12 @@ def get_stats(self, flush=True, reuse=False):
self._profiler,
stream=output_stream
).strip_dirs().sort_stats('cumulative', 'time').print_stats(50)
+ output = output_stream.getvalue()
# Occurs when no stats were able to be generated from profiler
except TypeError:
- pass
- output = output_stream.getvalue()
- output_stream.close()
+ output = 'Profiler: unable to generate stats'
+ finally:
+ output_stream.close()
if reuse:
# If stats are accumulating then enable existing/new profiler