From b803313921b3051426502a9a51fb7e4683bef86f Mon Sep 17 00:00:00 2001 From: MoojMidge <56883549+MoojMidge@users.noreply.github.com> Date: Sun, 4 Aug 2024 00:38:31 +1000 Subject: [PATCH 1/5] Rename kodion.utils.redact_ip_from_url to redact_ip --- .../lib/youtube_plugin/kodion/items/xbmc/xbmc_items.py | 4 ++-- .../lib/youtube_plugin/kodion/network/http_server.py | 4 ++-- resources/lib/youtube_plugin/kodion/utils/__init__.py | 4 ++-- resources/lib/youtube_plugin/kodion/utils/methods.py | 4 ++-- .../lib/youtube_plugin/youtube/helper/stream_info.py | 10 +++++----- 5 files changed, 13 insertions(+), 13 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 99569e4e8..6c95ae813 100644 --- a/resources/lib/youtube_plugin/kodion/items/xbmc/xbmc_items.py +++ b/resources/lib/youtube_plugin/kodion/items/xbmc/xbmc_items.py @@ -23,7 +23,7 @@ SUBSCRIPTION_ID, VIDEO_ID, ) -from ...utils import current_system_version, datetime_parser, redact_ip_from_url +from ...utils import current_system_version, datetime_parser, redact_ip def set_info(list_item, item, properties, set_play_count=True, resume=True): @@ -375,7 +375,7 @@ def set_info(list_item, item, properties, set_play_count=True, resume=True): def video_playback_item(context, video_item, show_fanart=None, **_kwargs): uri = video_item.get_uri() - context.log_debug('Converting VideoItem |%s|' % redact_ip_from_url(uri)) + context.log_debug('Converting VideoItem |%s|' % redact_ip(uri)) settings = context.get_settings() headers = video_item.get_headers() diff --git a/resources/lib/youtube_plugin/kodion/network/http_server.py b/resources/lib/youtube_plugin/kodion/network/http_server.py index 58c7f0e6d..2af4d96d2 100644 --- a/resources/lib/youtube_plugin/kodion/network/http_server.py +++ b/resources/lib/youtube_plugin/kodion/network/http_server.py @@ -28,7 +28,7 @@ ) from ..constants import ADDON_ID, LICENSE_TOKEN, LICENSE_URL, PATHS, TEMP_PATH from ..logger import log_debug, log_error -from ..utils import validate_ip_address, redact_ip_from_url, wait +from ..utils import validate_ip_address, redact_ip, wait class HTTPServer(TCPServer): @@ -97,7 +97,7 @@ def do_GET(self): stripped_path = self.path.rstrip('/') if stripped_path != PATHS.PING: log_debug('HTTPServer: GET |{path}|'.format( - path=redact_ip_from_url(self.path) + path=redact_ip(self.path) )) if not self.connection_allowed(): diff --git a/resources/lib/youtube_plugin/kodion/utils/__init__.py b/resources/lib/youtube_plugin/kodion/utils/__init__.py index 93ac49ae4..659ffb1de 100644 --- a/resources/lib/youtube_plugin/kodion/utils/__init__.py +++ b/resources/lib/youtube_plugin/kodion/utils/__init__.py @@ -21,7 +21,7 @@ loose_version, make_dirs, merge_dicts, - redact_ip_from_url, + redact_ip, rm_dir, seconds_to_duration, select_stream, @@ -45,7 +45,7 @@ 'loose_version', 'make_dirs', 'merge_dicts', - 'redact_ip_from_url', + 'redact_ip', 'rm_dir', 'seconds_to_duration', 'select_stream', diff --git a/resources/lib/youtube_plugin/kodion/utils/methods.py b/resources/lib/youtube_plugin/kodion/utils/methods.py index b46887155..99b93916d 100644 --- a/resources/lib/youtube_plugin/kodion/utils/methods.py +++ b/resources/lib/youtube_plugin/kodion/utils/methods.py @@ -107,7 +107,7 @@ def _stream_sort(_stream): original_value = log_data.get('url') if original_value: - log_data['url'] = redact_ip_from_url(original_value) + log_data['url'] = redact_ip(original_value) context.log_debug('Stream {0}:\n{1}'.format(idx, log_data)) @@ -312,5 +312,5 @@ def wait(timeout=None): return xbmc.Monitor().waitForAbort(timeout) -def redact_ip_from_url(url): +def redact_ip(url): return re.sub(r'([?&/])ip([=/])[^?&/]+', '\g<1>ip\g<2>', url) diff --git a/resources/lib/youtube_plugin/youtube/helper/stream_info.py b/resources/lib/youtube_plugin/youtube/helper/stream_info.py index aeedbf1b3..e9281a82b 100644 --- a/resources/lib/youtube_plugin/youtube/helper/stream_info.py +++ b/resources/lib/youtube_plugin/youtube/helper/stream_info.py @@ -34,7 +34,7 @@ ) from ...kodion.constants import PATHS, TEMP_PATH from ...kodion.network import get_connect_address -from ...kodion.utils import make_dirs, redact_ip_from_url +from ...kodion.utils import make_dirs, redact_ip class StreamInfo(YouTubeRequestClient): @@ -1092,7 +1092,7 @@ def _update_from_hls(self, ) if yt_format is None: self._context.log_debug('Unknown itag: {itag}\n{stream}'.format( - itag=itag, stream=redact_ip_from_url(match[0]), + itag=itag, stream=redact_ip(match[0]), )) if (not yt_format or (yt_format.get('hls/video') @@ -1169,11 +1169,11 @@ def _update_from_streams(self, ) if yt_format is None: if url: - stream_map['url'] = redact_ip_from_url(url) + stream_map['url'] = redact_ip(url) if conn: - stream_map['conn'] = redact_ip_from_url(conn) + stream_map['conn'] = redact_ip(conn) if stream: - stream_map['stream'] = redact_ip_from_url(stream) + stream_map['stream'] = redact_ip(stream) self._context.log_debug('Unknown itag: {itag}\n{stream}'.format( itag=itag, stream=stream_map, )) From cad487d3405445e587cecea872a7d21bbbc73653 Mon Sep 17 00:00:00 2001 From: MoojMidge <56883549+MoojMidge@users.noreply.github.com> Date: Sun, 4 Aug 2024 01:33:36 +1000 Subject: [PATCH 2/5] Misc tidy ups - replace more str.format calls --- .../kodion/constants/__init__.py | 6 +-- .../kodion/monitors/player_monitor.py | 2 +- .../youtube_plugin/kodion/utils/methods.py | 2 +- .../youtube_plugin/youtube/client/youtube.py | 4 +- .../youtube/helper/stream_info.py | 37 +++++++++---------- 5 files changed, 25 insertions(+), 26 deletions(-) diff --git a/resources/lib/youtube_plugin/kodion/constants/__init__.py b/resources/lib/youtube_plugin/kodion/constants/__init__.py index 46c6ab68d..e7935ae2a 100644 --- a/resources/lib/youtube_plugin/kodion/constants/__init__.py +++ b/resources/lib/youtube_plugin/kodion/constants/__init__.py @@ -20,11 +20,11 @@ # Addon paths ADDON_ID = 'plugin.video.youtube' -ADDON_PATH = 'special://home/addons/{id}'.format(id=ADDON_ID) -DATA_PATH = 'special://profile/addon_data/{id}'.format(id=ADDON_ID) +ADDON_PATH = 'special://home/addons/' + ADDON_ID +DATA_PATH = 'special://profile/addon_data/' + ADDON_ID MEDIA_PATH = ADDON_PATH + '/resources/media' RESOURCE_PATH = ADDON_PATH + '/resources' -TEMP_PATH = 'special://temp/{id}'.format(id=ADDON_ID) +TEMP_PATH = 'special://temp/' + ADDON_ID # Const values VALUE_FROM_STR = { diff --git a/resources/lib/youtube_plugin/kodion/monitors/player_monitor.py b/resources/lib/youtube_plugin/kodion/monitors/player_monitor.py index af6ca2f8d..59bb42c43 100644 --- a/resources/lib/youtube_plugin/kodion/monitors/player_monitor.py +++ b/resources/lib/youtube_plugin/kodion/monitors/player_monitor.py @@ -266,7 +266,7 @@ def run(self): if rating == 'none': rating_match = re.search( r'/(?P[^/]+)/(?P[^/]+)', - '/{0}/{1}/'.format(self.video_id, rating) + '/'.join(('', self.video_id, rating, '')) ) self._provider.on_video_x( self._provider, diff --git a/resources/lib/youtube_plugin/kodion/utils/methods.py b/resources/lib/youtube_plugin/kodion/utils/methods.py index 99b93916d..e0337b16a 100644 --- a/resources/lib/youtube_plugin/kodion/utils/methods.py +++ b/resources/lib/youtube_plugin/kodion/utils/methods.py @@ -270,7 +270,7 @@ def get_kodi_setting_value(setting, process=None): def get_kodi_setting_bool(setting): - return xbmc.getCondVisibility('System.GetBool({0})'.format(setting)) + return xbmc.getCondVisibility(setting.join(('System.GetBool(', ')'))) def validate_ip_address(ip_address): diff --git a/resources/lib/youtube_plugin/youtube/client/youtube.py b/resources/lib/youtube_plugin/youtube/client/youtube.py index f467d11f5..176ecb6dc 100644 --- a/resources/lib/youtube_plugin/youtube/client/youtube.py +++ b/resources/lib/youtube_plugin/youtube/client/youtube.py @@ -156,7 +156,7 @@ def update_watch_history(self, context, video_id, url, status=None): 'Accept': '*/*', 'Accept-Language': 'en-US,en;q=0.5', 'DNT': '1', - 'Referer': 'https://www.youtube.com/watch?v={0}'.format(video_id), + 'Referer': 'https://www.youtube.com/watch?v=' + video_id, 'User-Agent': ('Mozilla/5.0 (Linux; Android 10; SM-G981B)' ' AppleWebKit/537.36 (KHTML, like Gecko)' ' Chrome/80.0.3987.162 Mobile Safari/537.36'), @@ -1976,7 +1976,7 @@ def _error_hook(self, **kwargs): else: notification = message - title = '{0}: {1}'.format(self._context.get_name(), reason) + title = ': '.join((self._context.get_name(), reason)) if ok_dialog: self._context.get_ui().on_ok(title, notification) else: diff --git a/resources/lib/youtube_plugin/youtube/helper/stream_info.py b/resources/lib/youtube_plugin/youtube/helper/stream_info.py index e9281a82b..bd5555adb 100644 --- a/resources/lib/youtube_plugin/youtube/helper/stream_info.py +++ b/resources/lib/youtube_plugin/youtube/helper/stream_info.py @@ -862,9 +862,9 @@ def _get_stream_format(self, itag, info=None, max_height=None, **kwargs): def _get_player_page(self, client_name='web', embed=False): if embed: - url = 'https://www.youtube.com/embed/{0}'.format(self.video_id) + url = ''.join(('https://www.youtube.com/embed/', self.video_id)) else: - url = 'https://www.youtube.com/watch?v={0}'.format(self.video_id) + url = ''.join(('https://www.youtube.com/watch?v=', self.video_id)) # Manually configured cookies to avoid cookie consent redirect cookies = {'SOCS': 'CAISAiAD'} @@ -974,16 +974,14 @@ def _get_player_js(self): @staticmethod def _make_curl_headers(headers, cookies=None): - output = [] if cookies: - output.append('Cookie={0}'.format(quote('; '.join( - '{0.name}={0.value}'.format(cookie) - for cookie in cookies - )))) + headers['Cookie'] = '; '.join([ + '='.join((cookie.name, cookie.value)) for cookie in cookies + ]) # Headers used in xbmc_items.video_playback_item' - output.extend('{0}={1}'.format(key, quote(value)) - for key, value in headers.items()) - return '&'.join(output) + return '&'.join([ + '='.join((key, quote(value))) for key, value in headers.items() + ]) @staticmethod def _normalize_url(url): @@ -1243,7 +1241,7 @@ def _process_signature_cipher(self, stream_map): data_cache.set_item(encrypted_signature, {'sig': signature}) if signature: - url = '{0}&{1}={2}'.format(url, query_var, signature) + url = ''.join((url, '&', query_var, '=', signature)) return url return None @@ -1845,16 +1843,16 @@ def _process_stream_data(self, stream_data, default_lang_code='und'): role = 'alternate' label = self._context.localize('stream.alternate') - mime_group = '{0}_{1}.{2}'.format( - mime_type, language_code, role_type - ) + mime_group = ''.join(( + mime_type, '_', language_code, '.', role_type, + )) if language_code == self._language_base and ( not preferred_audio['id'] or role == 'main' or role_type > preferred_audio['role_type'] ): preferred_audio = { - 'id': '_{0}.{1}'.format(language_code, role_type), + 'id': ''.join(('_', language_code, '.', role_type)), 'language_code': language_code, 'role_type': role_type, } @@ -1870,9 +1868,10 @@ def _process_stream_data(self, stream_data, default_lang_code='und'): language = self._context.get_language_name(language_code) label = '{0} ({1} kbps)'.format(label, bitrate // 1000) if channels > 2 or 'auto' not in stream_select: - quality_group = '{0}_{1}_{2}.{3}'.format( - container, codec, language_code, role_type - ) + quality_group = ''.join(( + container, '_', codec, '_', language_code, + '.', role_type, + )) else: quality_group = mime_group elif audio_only: @@ -1937,7 +1936,7 @@ def _process_stream_data(self, stream_data, default_lang_code='und'): fps if fps > 30 else '', ' HDR' if hdr else '', ) - quality_group = '{0}_{1}_{2}'.format(container, codec, label) + quality_group = '_'.join((container, codec, label)) if mime_group not in data: data[mime_group] = {} From d6192e49e6c95733b6981cefd3493654ab31153e Mon Sep 17 00:00:00 2001 From: MoojMidge <56883549+MoojMidge@users.noreply.github.com> Date: Sun, 4 Aug 2024 01:37:14 +1000 Subject: [PATCH 3/5] Improve handling of progressive streams --- .../youtube/helper/stream_info.py | 148 +++++++++--------- 1 file changed, 73 insertions(+), 75 deletions(-) diff --git a/resources/lib/youtube_plugin/youtube/helper/stream_info.py b/resources/lib/youtube_plugin/youtube/helper/stream_info.py index bd5555adb..8d92dfd3c 100644 --- a/resources/lib/youtube_plugin/youtube/helper/stream_info.py +++ b/resources/lib/youtube_plugin/youtube/helper/stream_info.py @@ -997,13 +997,13 @@ def _normalize_url(url): def _update_from_hls(self, stream_list, - url, + urls, is_live=False, - meta_info=None, headers=None, + meta_info=None, playback_stats=None): - if not url: - return [] + if not urls: + return if not headers and self._selected_client: client_name = self._selected_client['_name'] @@ -1016,21 +1016,6 @@ def _update_from_hls(self, headers = self.build_client(client_name, client_data)['headers'] curl_headers = self._make_curl_headers(headers, cookies=None) - result = self.request( - url, - headers=headers, - response_hook=self._response_hook_text, - error_title='Failed to get HLS manifest', - error_hook=self._error_hook, - error_hook_kwargs={ - 'video_id': self.video_id, - 'client': client_name, - 'auth': False, - }, - ) - if not result: - return () - if meta_info is None: meta_info = {'video': {}, 'channel': {}, @@ -1040,26 +1025,6 @@ def _update_from_hls(self, if playback_stats is None: playback_stats = {} - if is_live: - for yt_format in ('9995', '9996'): - stream_list[yt_format] = self._get_stream_format( - itag=yt_format, - title='', - url=url, - meta=meta_info, - headers=curl_headers, - playback_stats=playback_stats, - ) - else: - stream_list['9994'] = self._get_stream_format( - itag='9994', - title='', - url=url, - meta=meta_info, - headers=curl_headers, - playback_stats=playback_stats, - ) - settings = self._context.get_settings() if self._use_mpd: qualities = settings.mpd_video_qualities() @@ -1067,48 +1032,77 @@ def _update_from_hls(self, else: selected_height = settings.fixed_video_quality() - # The playlist might include a #EXT-X-MEDIA entry, but it's usually for - # a small default stream with itag 133 (240p) and can be ignored. - # Capture the URL of a .m3u8 playlist and the itag value from that URL. - re_playlist_data = re.compile( - r'#EXT-X-STREAM-INF[^#]+' - r'(?Phttp\S+/itag/(?P\d+)\S+)' - ) - for match in re_playlist_data.finditer(result): - itag = match.group('itag') - if itag in stream_list: + for url in urls: + result = self.request( + url, + headers=headers, + response_hook=self._response_hook_text, + error_title='Failed to get HLS manifest', + error_hook=self._error_hook, + error_hook_kwargs={ + 'video_id': self.video_id, + 'client': client_name, + 'auth': False, + }, + ) + if not result: continue - yt_format = self._get_stream_format( - itag=itag, - max_height=selected_height, - title='', - url=match.group('url'), - meta=meta_info, - headers=curl_headers, - playback_stats=playback_stats, + for itag in ('9995', '9996') if is_live else ('9994', ): + if itag in stream_list: + continue + + stream_list[itag] = self._get_stream_format( + itag=itag, + title='', + url=url, + headers=curl_headers, + meta=meta_info, + playback_stats=playback_stats, + ) + + # The playlist might include a #EXT-X-MEDIA entry, but it's usually + # for a default stream with itag 133 (240p) and can be ignored. + # Capture the URL of a .m3u8 playlist and the itag from that URL. + re_playlist_data = re.compile( + r'#EXT-X-STREAM-INF[^#]+' + r'(?Phttp\S+/itag/(?P\d+)\S+)' ) - if yt_format is None: - self._context.log_debug('Unknown itag: {itag}\n{stream}'.format( - itag=itag, stream=redact_ip(match[0]), - )) - if (not yt_format - or (yt_format.get('hls/video') - and not yt_format.get('hls/audio'))): - continue + for match in re_playlist_data.finditer(result): + itag = match.group('itag') + if itag in stream_list: + continue - if is_live: - yt_format['live'] = True - yt_format['title'] = 'Live ' + yt_format['title'] + yt_format = self._get_stream_format( + itag=itag, + max_height=selected_height, + title='', + url=match.group('url'), + meta=meta_info, + headers=curl_headers, + playback_stats=playback_stats, + ) + if yt_format is None: + self._context.log_debug('Unknown itag: {itag}\n{stream}' + .format(itag=itag, + stream=redact_ip(match[0]))) + if (not yt_format + or (yt_format.get('hls/video') + and not yt_format.get('hls/audio'))): + continue - stream_list[itag] = yt_format + if is_live: + yt_format['live'] = True + yt_format['title'] = 'Live ' + yt_format['title'] + + stream_list[itag] = yt_format def _update_from_streams(self, stream_list, streams, is_live=False, - meta_info=None, headers=None, + meta_info=None, playback_stats=None): if not headers and self._selected_client: headers = self._selected_client['headers'].copy() @@ -1125,6 +1119,7 @@ def _update_from_streams(self, 'channel': {}, 'thumbnails': {}, 'subtitles': []} + if playback_stats is None: playback_stats = {} @@ -1358,6 +1353,7 @@ def load_stream_info(self, video_id): streaming_data = {} adaptive_fmts = [] progressive_fmts = [] + hls_playlists = [] video_info_url = 'https://www.youtube.com/youtubei/v1/player' @@ -1389,7 +1385,7 @@ def load_stream_info(self, video_id): continue if name == 'mpd' and not use_mpd: continue - if name == 'ask' and not ask_for_quality and self._selected_client: + if name == 'ask' and use_mpd and not ask_for_quality: continue status = None @@ -1489,6 +1485,8 @@ def load_stream_info(self, video_id): adaptive_fmts.extend( _streaming_data.get('adaptiveFormats', []) ) + if 'hlsManifestUrl' in _streaming_data: + hls_playlists.append(_streaming_data['hlsManifestUrl']) streaming_data.update(_streaming_data) if not self._selected_client: @@ -1628,7 +1626,7 @@ def load_stream_info(self, video_id): license_info=license_info, playback_stats=playback_stats, ) - if 'hlsManifestUrl' in streaming_data and ( + if hls_playlists and ( is_live or live_dvr or ask_for_quality @@ -1636,10 +1634,10 @@ def load_stream_info(self, video_id): ): self._update_from_hls( stream_list, - streaming_data['hlsManifestUrl'], + hls_playlists, is_live, - meta_info, client['headers'], + meta_info, playback_stats, ) @@ -1743,8 +1741,8 @@ def load_stream_info(self, video_id): stream_list, progressive_fmts, is_live, - meta_info, client['headers'], + meta_info, playback_stats, ) From 0c41d2ab15b4fcee2afbab810d6f5cd9941acf6d Mon Sep 17 00:00:00 2001 From: MoojMidge <56883549+MoojMidge@users.noreply.github.com> Date: Sun, 4 Aug 2024 04:02:23 +1000 Subject: [PATCH 4/5] Improve handling of HLS ISA stream selection --- .../kodion/constants/const_settings.py | 1 + .../kodion/items/xbmc/xbmc_items.py | 12 +++-- .../kodion/settings/abstract_settings.py | 12 +++-- resources/settings.xml | 45 +++++++++++++------ 4 files changed, 51 insertions(+), 19 deletions(-) diff --git a/resources/lib/youtube_plugin/kodion/constants/const_settings.py b/resources/lib/youtube_plugin/kodion/constants/const_settings.py index 68b624bfa..54acaab2a 100644 --- a/resources/lib/youtube_plugin/kodion/constants/const_settings.py +++ b/resources/lib/youtube_plugin/kodion/constants/const_settings.py @@ -19,6 +19,7 @@ MPD_STREAM_SELECT = 'kodion.mpd.stream.select' # (int) MPD_QUALITY_SELECTION = 'kodion.mpd.quality.selection' # (int) MPD_STREAM_FEATURES = 'kodion.mpd.stream.features' # (list[str]) +VIDEO_STREAM_SELECT = 'kodion.video.stream.select' # (int) VIDEO_QUALITY_ASK = 'kodion.video.quality.ask' # (bool) VIDEO_QUALITY = 'kodion.video.quality' # (int) AUDIO_ONLY = 'kodion.audio_only' # (bool) 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 6c95ae813..a5bc7ecb4 100644 --- a/resources/lib/youtube_plugin/kodion/items/xbmc/xbmc_items.py +++ b/resources/lib/youtube_plugin/kodion/items/xbmc/xbmc_items.py @@ -402,15 +402,21 @@ def video_playback_item(context, video_item, show_fanart=None, **_kwargs): } if video_item.use_isa_video() and context.use_inputstream_adaptive(): - if video_item.use_mpd_video(): + use_mpd = video_item.use_mpd_video() + if use_mpd: manifest_type = 'mpd' mime_type = 'application/dash+xml' - if 'auto' in settings.stream_select(): - props['inputstream.adaptive.stream_selection_type'] = 'adaptive' else: manifest_type = 'hls' mime_type = 'application/x-mpegURL' + stream_select = settings.stream_select() + if not use_mpd and 'list' in stream_select: + props['inputstream.adaptive.stream_selection_type'] = 'manual-osd' + elif 'auto' in stream_select: + props['inputstream.adaptive.stream_selection_type'] = 'adaptive' + props['inputstream.adaptive.chooser_resolution_max'] = 'auto' + if current_system_version.compatible(19, 0): props['inputstream'] = 'inputstream.adaptive' else: diff --git a/resources/lib/youtube_plugin/kodion/settings/abstract_settings.py b/resources/lib/youtube_plugin/kodion/settings/abstract_settings.py index e6baeafac..928f09e0e 100644 --- a/resources/lib/youtube_plugin/kodion/settings/abstract_settings.py +++ b/resources/lib/youtube_plugin/kodion/settings/abstract_settings.py @@ -388,10 +388,16 @@ def stream_features(self, value=None): } def stream_select(self, value=None): + if self.use_mpd_videos(): + setting = SETTINGS.MPD_STREAM_SELECT + default = 3 + else: + setting = SETTINGS.VIDEO_STREAM_SELECT + default = 2 + if value is not None: - return self.set_int(SETTINGS.MPD_STREAM_SELECT, value) - default = 3 - value = self.get_int(SETTINGS.MPD_STREAM_SELECT, default) + return self.set_int(setting, value) + value = self.get_int(setting, default) if value in self._STREAM_SELECT: return self._STREAM_SELECT[value] return self._STREAM_SELECT[default] diff --git a/resources/settings.xml b/resources/settings.xml index 3150c4105..cb6b23b2b 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -48,19 +48,6 @@ - - 0 - false - - - - false - false - - - - - 0 4 @@ -86,6 +73,38 @@ + + 0 + 2 + + + + + + + + + + true + false + + + + + + + 0 + false + + + + false + false + + + + + 0 3 From 15a4319c0b92bab082be17465da609fb6dba40c4 Mon Sep 17 00:00:00 2001 From: MoojMidge <56883549+MoojMidge@users.noreply.github.com> Date: Sun, 4 Aug 2024 04:23:26 +1000 Subject: [PATCH 5/5] Version bump v7.0.9+beta.7 --- addon.xml | 2 +- changelog.txt | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index a93428c05..2796a91c8 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + diff --git a/changelog.txt b/changelog.txt index 8ef55cb1d..392836642 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,8 @@ +## v7.0.9+beta.7 +### New +- Improve use of progressive streams +- Improve stream selection for HLS stream in InputStream.Adaptive + ## v7.0.9+beta.6 ### Fixed - Fix http server not working in Kodi 18