matrix patch

This commit is contained in:
anxdpanic 2020-02-07 16:44:38 -05:00 committed by anxdpanic
parent b07f541b04
commit d371a9b863
14 changed files with 277 additions and 24 deletions

View file

@ -99,3 +99,4 @@
<disclaimer lang="zh_TW">此附加元件未由Google支持</disclaimer>
</extension>
</addon>
<!-- unofficial -->

View file

@ -73,10 +73,29 @@ class AbstractProvider(object):
self._dict_path[re_path] = method_name
def _process_wizard(self, context):
def _setup_views(_context, _view):
view_manager = utils.ViewManager(_context)
if not view_manager.update_view_mode(_context.localize(self._local_map['kodion.wizard.view.%s' % _view]),
_view):
return
_context.get_settings().set_bool(constants.setting.VIEW_OVERRIDE, True)
# start the setup wizard
wizard_steps = []
if context.get_settings().is_setup_wizard_enabled():
context.get_settings().set_bool(constants.setting.SETUP_WIZARD, False)
if utils.ViewManager(context).has_supported_views():
views = self.get_wizard_supported_views()
for view in views:
if view in utils.ViewManager.SUPPORTED_VIEWS:
wizard_steps.append((_setup_views, [context, view]))
else:
context.log_warning('[Setup-Wizard] Unsupported view "%s"' % view)
else:
skin_id = context.get_ui().get_skin_id()
context.log("ViewManager: Unknown skin id '%s'" % skin_id)
wizard_steps.extend(self.get_wizard_steps(context))
if wizard_steps and context.get_ui().on_yes_no_input(context.get_name(),
@ -279,7 +298,7 @@ class AbstractProvider(object):
query = query.decode('utf-8')
return self.on_search(query, context, re_match)
else:
context.set_content_type(constants.content_type.FILES)
context.set_content_type(constants.content_type.VIDEOS)
result = []
location = str(context.get_param('location', False)).lower() == 'true'

View file

@ -35,6 +35,10 @@ HIDE_SHORT_VIDEOS = 'youtube.hide_shorts' # (bool)
SUPPORT_ALTERNATIVE_PLAYER = 'kodion.support.alternative_player' # (bool)
ALTERNATIVE_PLAYER_WEB_URLS = 'kodion.alternative_player.web.urls' # (bool)
VIEW_OVERRIDE = 'kodion.view.override' # (bool)
VIEW_DEFAULT = 'kodion.view.default' # (int)
VIEW_X = 'kodion.view.%s' # (int)
ALLOW_DEV_KEYS = 'youtube.allow.dev.keys' # (bool)
DASH_VIDEOS = 'kodion.mpd.videos' # (bool)

View file

@ -16,6 +16,12 @@ class AbstractContextUI(object):
def create_progress_dialog(self, heading, text=None, background=False):
raise NotImplementedError()
def set_view_mode(self, view_mode):
raise NotImplementedError()
def get_view_mode(self):
raise NotImplementedError()
def get_skin_id(self):
raise NotImplementedError()

View file

@ -90,6 +90,9 @@ class AbstractSettings(object):
def is_setup_wizard_enabled(self):
return self.get_bool(constants.setting.SETUP_WIZARD, False)
def is_override_view_enabled(self):
return self.get_bool(constants.setting.VIEW_OVERRIDE, False)
def is_support_alternative_player_enabled(self):
return self.get_bool(constants.setting.SUPPORT_ALTERNATIVE_PLAYER, False)

View file

@ -208,6 +208,7 @@ class XbmcContext(AbstractContext):
def set_content_type(self, content_type):
self.log_debug('Setting content-type: "%s" for "%s"' % (content_type, self.get_path()))
xbmcplugin.setContent(self._plugin_handle, content_type)
self.get_ui().set_view_mode(content_type)
def add_sort_method(self, *sort_methods):
for sort_method in sort_methods:

View file

@ -9,6 +9,7 @@
"""
from six import PY3
from six import string_types
import xbmc
import xbmcgui
@ -35,6 +36,18 @@ class XbmcContextUI(AbstractContextUI):
return XbmcProgressDialog(heading, text)
def set_view_mode(self, view_mode):
if isinstance(view_mode, string_types):
view_mode = self._context.get_settings().get_int(constants.setting.VIEW_X % view_mode, self._context.get_settings().get_int(constants.setting.VIEW_DEFAULT, 50))
self._view_mode = view_mode
def get_view_mode(self):
if self._view_mode is not None:
return self._view_mode
return self._context.get_settings().get_int(constants.setting.VIEW_DEFAULT, 50)
def get_skin_id(self):
return xbmc.getSkinDir()

View file

@ -8,6 +8,7 @@
See LICENSES/GPL-2.0-only for more information.
"""
import xbmc
import xbmcgui
import xbmcplugin
@ -66,6 +67,13 @@ class XbmcRunner(AbstractProviderRunner):
self.handle, succeeded=True,
updateListing=options.get(AbstractProvider.RESULT_UPDATE_LISTING, False),
cacheToDisc=options.get(AbstractProvider.RESULT_CACHE_TO_DISC, True))
# set alternative view mode
if context.get_settings().is_override_view_enabled():
view_mode = context.get_ui().get_view_mode()
if view_mode is not None:
context.log_debug('Override view mode to "%d"' % view_mode)
xbmc.executebuiltin('Container.SetViewMode(%d)' % view_mode)
else:
# handle exception
pass

View file

@ -16,6 +16,7 @@ from .favorite_list import FavoriteList
from .watch_later_list import WatchLaterList
from .function_cache import FunctionCache
from .access_manager import AccessManager
from .view_manager import ViewManager
from .http_server import get_http_server, is_httpd_live, get_client_ip_address
from .monitor import YouTubeMonitor
from .player import YouTubePlayer
@ -25,7 +26,7 @@ from .system_version import SystemVersion
from . import ip_api
__all__ = ['SearchHistory', 'FavoriteList', 'WatchLaterList', 'FunctionCache', 'AccessManager',
__all__ = ['SearchHistory', 'FavoriteList', 'WatchLaterList', 'FunctionCache', 'AccessManager', 'ViewManager',
'strip_html_from_text', 'create_path', 'create_uri_path', 'find_best_fit', 'to_unicode', 'to_utf8',
'datetime_parser', 'select_stream', 'get_http_server', 'is_httpd_live', 'YouTubeMonitor',
'make_dirs', 'loose_version', 'ip_api', 'PlaybackHistory', 'DataCache', 'get_client_ip_address',

View file

@ -0,0 +1,166 @@
# -*- coding: utf-8 -*-
"""
Copyright (C) 2014-2016 bromix (plugin.video.youtube)
Copyright (C) 2016-2018 plugin.video.youtube
SPDX-License-Identifier: GPL-2.0-only
See LICENSES/GPL-2.0-only for more information.
"""
from .. import constants
class ViewManager(object):
SUPPORTED_VIEWS = ['default', 'movies', 'tvshows', 'episodes', 'musicvideos', 'songs', 'albums', 'artists']
SKIN_DATA = {
'skin.confluence': {
'default': [
{'name': 'List', 'id': 50},
{'name': 'Big List', 'id': 51},
{'name': 'Thumbnail', 'id': 500}
],
'movies': [
{'name': 'List', 'id': 50},
{'name': 'Big List', 'id': 51},
{'name': 'Thumbnail', 'id': 500},
{'name': 'Media info', 'id': 504},
{'name': 'Media info 2', 'id': 503}
],
'episodes': [
{'name': 'List', 'id': 50},
{'name': 'Big List', 'id': 51},
{'name': 'Thumbnail', 'id': 500},
{'name': 'Media info', 'id': 504},
{'name': 'Media info 2', 'id': 503}
],
'tvshows': [
{'name': 'List', 'id': 50},
{'name': 'Big List', 'id': 51},
{'name': 'Thumbnail', 'id': 500},
{'name': 'Poster', 'id': 500},
{'name': 'Wide', 'id': 505},
{'name': 'Media info', 'id': 504},
{'name': 'Media info 2', 'id': 503},
{'name': 'Fanart', 'id': 508}
],
'musicvideos': [
{'name': 'List', 'id': 50},
{'name': 'Big List', 'id': 51},
{'name': 'Thumbnail', 'id': 500},
{'name': 'Media info', 'id': 504},
{'name': 'Media info 2', 'id': 503}
],
'songs': [
{'name': 'List', 'id': 50},
{'name': 'Big List', 'id': 51},
{'name': 'Thumbnail', 'id': 500},
{'name': 'Media info', 'id': 506}
],
'albums': [
{'name': 'List', 'id': 50},
{'name': 'Big List', 'id': 51},
{'name': 'Thumbnail', 'id': 500},
{'name': 'Media info', 'id': 506}
],
'artists': [
{'name': 'List', 'id': 50},
{'name': 'Big List', 'id': 51},
{'name': 'Thumbnail', 'id': 500},
{'name': 'Media info', 'id': 506}
]
},
'skin.aeon.nox.5': {
'default': [
{'name': 'List', 'id': 50},
{'name': 'Episodes', 'id': 502},
{'name': 'LowList', 'id': 501},
{'name': 'BannerWall', 'id': 58},
{'name': 'Shift', 'id': 57},
{'name': 'Posters', 'id': 56},
{'name': 'ShowCase', 'id': 53},
{'name': 'Landscape', 'id': 52},
{'name': 'InfoWall', 'id': 51}
]
},
'skin.xperience1080+': {
'default': [
{'name': 'List', 'id': 50},
{'name': 'Thumbnail', 'id': 500},
],
'episodes': [
{'name': 'List', 'id': 50},
{'name': 'Info list', 'id': 52},
{'name': 'Fanart', 'id': 502},
{'name': 'Landscape', 'id': 54},
{'name': 'Poster', 'id': 55},
{'name': 'Thumbnail', 'id': 500},
{'name': 'Banner', 'id': 60}
],
},
'skin.xperience1080': {
'default': [
{'name': 'List', 'id': 50},
{'name': 'Thumbnail', 'id': 500},
],
'episodes': [
{'name': 'List', 'id': 50},
{'name': 'Info list', 'id': 52},
{'name': 'Fanart', 'id': 502},
{'name': 'Landscape', 'id': 54},
{'name': 'Poster', 'id': 55},
{'name': 'Thumbnail', 'id': 500},
{'name': 'Banner', 'id': 60}
],
},
'skin.estuary': {
'default': [
{'name': 'Shift', 'id': 53},
{'name': 'InfoWall', 'id': 54},
{'name': 'Wall', 'id': 500},
{'name': 'WideList', 'id': 55},
],
'episodes': [
{'name': 'InfoWall', 'id': 54},
{'name': 'Wall', 'id': 500},
{'name': 'WideList', 'id': 55},
]
}
}
def __init__(self, context):
self._context = context
def has_supported_views(self):
"""
Returns True if the View of the current skin are supported
:return: True if the View of the current skin are supported
"""
return self._context.get_ui().get_skin_id() in self.SKIN_DATA
def update_view_mode(self, title, view='default'):
view_id = -1
settings = self._context.get_settings()
skin_id = self._context.get_ui().get_skin_id()
skin_data = self.SKIN_DATA.get(skin_id, {}).get(view, [])
if skin_data:
items = []
for view_data in skin_data:
items.append((view_data['name'], view_data['id']))
view_id = self._context.get_ui().on_select(title, items)
else:
self._context.log_notice("ViewManager: Unknown skin id '%s'" % skin_id)
if view_id == -1:
old_value = settings.get_string(constants.setting.VIEW_X % view, '')
if old_value:
result, view_id = self._context.get_ui().on_numeric_input(title, old_value)
if not result:
view_id = -1
if view_id > -1:
settings.set_int(constants.setting.VIEW_X % view, view_id)
return True
return False

View file

@ -258,7 +258,7 @@ def update_video_infos(provider, context, video_id_dict, playlist_item_id_dict=N
video_item = video_id_dict[video_id]
# set mediatype
video_item.set_mediatype('video') # using video
video_item.set_mediatype('episode') # using video
if not yt_item:
continue

View file

@ -15,7 +15,7 @@ from . import utils
def _process_related_videos(provider, context):
provider.set_content_type(context, kodion.constants.content_type.VIDEOS)
provider.set_content_type(context, kodion.constants.content_type.EPISODES)
result = []
page_token = context.get_param('page_token', '')
@ -60,7 +60,7 @@ def _process_child_comments(provider, context):
def _process_recommendations(provider, context):
provider.set_content_type(context, kodion.constants.content_type.VIDEOS)
provider.set_content_type(context, kodion.constants.content_type.EPISODES)
result = []
page_token = context.get_param('page_token', '')
@ -72,7 +72,7 @@ def _process_recommendations(provider, context):
def _process_popular_right_now(provider, context):
provider.set_content_type(context, kodion.constants.content_type.VIDEOS)
provider.set_content_type(context, kodion.constants.content_type.EPISODES)
result = []
page_token = context.get_param('page_token', '')
@ -85,7 +85,7 @@ def _process_popular_right_now(provider, context):
def _process_browse_channels(provider, context):
provider.set_content_type(context, kodion.constants.content_type.FILES)
provider.set_content_type(context, kodion.constants.content_type.VIDEOS)
result = []
# page_token = context.get_param('page_token', '')
@ -107,7 +107,7 @@ def _process_browse_channels(provider, context):
def _process_disliked_videos(provider, context):
provider.set_content_type(context, kodion.constants.content_type.VIDEOS)
provider.set_content_type(context, kodion.constants.content_type.EPISODES)
result = []
page_token = context.get_param('page_token', '')
@ -122,7 +122,7 @@ def _process_live_events(provider, context, event_type='live'):
def _sort(x):
return x.get_aired()
provider.set_content_type(context, kodion.constants.content_type.VIDEOS)
provider.set_content_type(context, kodion.constants.content_type.EPISODES)
result = []
# TODO: cache result
@ -142,7 +142,7 @@ def _process_description_links(provider, context):
addon_id = context.get_param('addon_id', '')
def _extract_urls(_video_id):
provider.set_content_type(context, kodion.constants.content_type.VIDEOS)
provider.set_content_type(context, kodion.constants.content_type.EPISODES)
url_resolver = UrlResolver(context)
result = []
@ -304,7 +304,7 @@ def _process_purchases_tv(provider, context):
def _process_new_uploaded_videos_tv(provider, context):
provider.set_content_type(context, kodion.constants.content_type.VIDEOS)
provider.set_content_type(context, kodion.constants.content_type.EPISODES)
result = []
next_page_token = context.get_param('next_page_token', '')
@ -316,7 +316,7 @@ def _process_new_uploaded_videos_tv(provider, context):
def _process_new_uploaded_videos_tv_filtered(provider, context):
provider.set_content_type(context, kodion.constants.content_type.VIDEOS)
provider.set_content_type(context, kodion.constants.content_type.EPISODES)
result = []
next_page_token = context.get_param('next_page_token', '')

View file

@ -437,7 +437,7 @@ class Provider(kodion.AbstractProvider):
@kodion.RegisterProviderPath('^/playlist/(?P<playlist_id>[^/]+)/$')
def _on_playlist(self, context, re_match):
self.set_content_type(context, kodion.constants.content_type.VIDEOS)
self.set_content_type(context, kodion.constants.content_type.EPISODES)
result = []
@ -461,7 +461,7 @@ class Provider(kodion.AbstractProvider):
@kodion.RegisterProviderPath('^/channel/(?P<channel_id>[^/]+)/playlist/(?P<playlist_id>[^/]+)/$')
def _on_channel_playlist(self, context, re_match):
self.set_content_type(context, kodion.constants.content_type.VIDEOS)
self.set_content_type(context, kodion.constants.content_type.EPISODES)
client = self.get_client(context)
result = []
@ -484,7 +484,7 @@ class Provider(kodion.AbstractProvider):
@kodion.RegisterProviderPath('^/channel/(?P<channel_id>[^/]+)/playlists/$')
def _on_channel_playlists(self, context, re_match):
self.set_content_type(context, kodion.constants.content_type.FILES)
self.set_content_type(context, kodion.constants.content_type.VIDEOS)
result = []
channel_id = re_match.group('channel_id')
@ -525,7 +525,7 @@ class Provider(kodion.AbstractProvider):
@kodion.RegisterProviderPath('^/channel/(?P<channel_id>[^/]+)/live/$')
def _on_channel_live(self, context, re_match):
self.set_content_type(context, kodion.constants.content_type.VIDEOS)
self.set_content_type(context, kodion.constants.content_type.EPISODES)
result = []
channel_id = re_match.group('channel_id')
@ -560,7 +560,7 @@ class Provider(kodion.AbstractProvider):
if method == 'channel' and not channel_id:
return False
self.set_content_type(context, kodion.constants.content_type.VIDEOS)
self.set_content_type(context, kodion.constants.content_type.EPISODES)
resource_manager = self.get_resource_manager(context)
@ -648,7 +648,7 @@ class Provider(kodion.AbstractProvider):
# noinspection PyUnusedLocal
@kodion.RegisterProviderPath('^/location/mine/$')
def _on_my_location(self, context, re_match):
self.set_content_type(context, kodion.constants.content_type.FILES)
self.set_content_type(context, kodion.constants.content_type.VIDEOS)
settings = context.get_settings()
result = list()
@ -793,7 +793,7 @@ class Provider(kodion.AbstractProvider):
subscriptions = yt_subscriptions.process(method, self, context)
if method == 'list':
self.set_content_type(context, kodion.constants.content_type.FILES)
self.set_content_type(context, kodion.constants.content_type.VIDEOS)
channel_ids = []
for subscription in subscriptions:
channel_ids.append(subscription.get_channel_id())
@ -1025,9 +1025,9 @@ class Provider(kodion.AbstractProvider):
context.set_param('q', search_text)
if search_type == 'video':
self.set_content_type(context, kodion.constants.content_type.VIDEOS)
self.set_content_type(context, kodion.constants.content_type.EPISODES)
else:
self.set_content_type(context, kodion.constants.content_type.FILES)
self.set_content_type(context, kodion.constants.content_type.VIDEOS)
if page == 1 and search_type == 'video' and not event_type and not hide_folders:
if not channel_id and not location:
@ -1361,7 +1361,7 @@ class Provider(kodion.AbstractProvider):
settings = context.get_settings()
_ = self.get_client(context) # required for self.is_logged_in()
self.set_content_type(context, kodion.constants.content_type.FILES)
self.set_content_type(context, kodion.constants.content_type.VIDEOS)
result = []
@ -1596,7 +1596,7 @@ class Provider(kodion.AbstractProvider):
@staticmethod
def set_content_type(context, content_type):
context.set_content_type(content_type)
if content_type == kodion.constants.content_type.VIDEOS:
if content_type == kodion.constants.content_type.EPISODES:
context.add_sort_method(kodion.constants.sort_method.UNSORTED,
kodion.constants.sort_method.VIDEO_RUNTIME,
kodion.constants.sort_method.DATE_ADDED,

View file

@ -610,6 +610,37 @@
</setting>
</group>
<group id="3">
<setting help="" id="kodion.view.override" label="30026" type="boolean">
<level>0</level>
<default>false</default>
<control type="toggle"/>
</setting>
<setting help="" id="kodion.view.default" label="30027" type="integer">
<level>0</level>
<default>50</default>
<dependencies>
<dependency type="enable">
<condition operator="is" setting="kodion.view.override">true</condition>
</dependency>
</dependencies>
<control format="integer" type="edit">
<heading>30027</heading>
</control>
</setting>
<setting help="" id="kodion.view.episodes" label="30028" type="integer">
<level>0</level>
<default>50</default>
<dependencies>
<dependency type="enable">
<condition operator="is" setting="kodion.view.override">true</condition>
</dependency>
</dependencies>
<control format="integer" type="edit">
<heading>30028</heading>
</control>
</setting>
</group>
<group id="4">
<setting help="" id="kodion.cache.size" label="30024" type="integer">
<level>0</level>
<default>10</default>
@ -628,7 +659,7 @@
<control type="toggle"/>
</setting>
</group>
<group id="4">
<group id="5">
<setting help="" id="youtube.language" label="30523" type="string">
<level>0</level>
<default>en-US</default>