Reorganise constants and simplify window property usage

- Remove need for script action for external player switching
This commit is contained in:
MoojMidge 2024-06-19 07:00:38 +10:00
parent 3726193d18
commit fca610cb25
23 changed files with 379 additions and 346 deletions

View file

@ -12,7 +12,7 @@ from __future__ import absolute_import, division, unicode_literals
import re import re
from .constants import CHECK_SETTINGS, REROUTE, content, paths from .constants import CHECK_SETTINGS, CONTENT, PATHS, REROUTE_PATH
from .exceptions import KodionException from .exceptions import KodionException
from .items import ( from .items import (
DirectoryItem, DirectoryItem,
@ -36,49 +36,49 @@ class AbstractProvider(object):
# register some default paths # register some default paths
self.register_path(r''.join(( self.register_path(r''.join((
'^', '^',
'(?:', paths.HOME, ')?/?$' '(?:', PATHS.HOME, ')?/?$'
)), self._internal_root) )), self._internal_root)
self.register_path(r''.join(( self.register_path(r''.join((
'^', '^',
paths.ROUTE, PATHS.ROUTE,
'(?P<path>/[^?]+?)(?:/*[?].+|/*)$' '(?P<path>/[^?]+?)(?:/*[?].+|/*)$'
)), self.reroute) )), self.reroute)
self.register_path(r''.join(( self.register_path(r''.join((
'^', '^',
paths.GOTO_PAGE, PATHS.GOTO_PAGE,
'(?P<page>/[0-9]+)?' '(?P<page>/[0-9]+)?'
'(?P<path>/[^?]+?)(?:/*[?].+|/*)$' '(?P<path>/[^?]+?)(?:/*[?].+|/*)$'
)), self._internal_goto_page) )), self._internal_goto_page)
self.register_path(r''.join(( self.register_path(r''.join((
'^', '^',
paths.COMMAND, PATHS.COMMAND,
'/(?P<command>[^?]+?)(?:/*[?].+|/*)$' '/(?P<command>[^?]+?)(?:/*[?].+|/*)$'
)), self._on_command) )), self._on_command)
self.register_path(r''.join(( self.register_path(r''.join((
'^', '^',
paths.WATCH_LATER, PATHS.WATCH_LATER,
'/(?P<command>add|clear|list|remove)/?$' '/(?P<command>add|clear|list|remove)/?$'
)), self.on_watch_later) )), self.on_watch_later)
self.register_path(r''.join(( self.register_path(r''.join((
'^', '^',
paths.BOOKMARKS, PATHS.BOOKMARKS,
'/(?P<command>add|clear|list|remove)/?$' '/(?P<command>add|clear|list|remove)/?$'
)), self.on_bookmarks) )), self.on_bookmarks)
self.register_path(r''.join(( self.register_path(r''.join((
'^', '^',
'(', paths.SEARCH, '|', paths.EXTERNAL_SEARCH, ')', '(', PATHS.SEARCH, '|', PATHS.EXTERNAL_SEARCH, ')',
'/(?P<command>input|query|list|remove|clear|rename)?/?$' '/(?P<command>input|query|list|remove|clear|rename)?/?$'
)), self._internal_search) )), self._internal_search)
self.register_path(r''.join(( self.register_path(r''.join((
'^', '^',
paths.HISTORY, PATHS.HISTORY,
'/?$' '/?$'
)), self.on_playback_history) )), self.on_playback_history)
@ -237,7 +237,7 @@ class AbstractProvider(object):
finally: finally:
if not result: if not result:
return False return False
context.get_ui().set_property(REROUTE, path) context.get_ui().set_property(REROUTE_PATH, path)
context.execute('ActivateWindow(Videos, {0}{1})'.format( context.execute('ActivateWindow(Videos, {0}{1})'.format(
context.create_uri(path, params), context.create_uri(path, params),
', return' if window_return else '', ', return' if window_return else '',
@ -312,10 +312,10 @@ class AbstractProvider(object):
if not params.get('incognito') and not params.get('channel_id'): if not params.get('incognito') and not params.get('channel_id'):
search_history.update(query) search_history.update(query)
context.set_path(paths.SEARCH, 'query') context.set_path(PATHS.SEARCH, 'query')
return self.on_search(query, context, re_match) return self.on_search(query, context, re_match)
context.set_content(content.LIST_CONTENT) context.set_content(CONTENT.LIST_CONTENT)
result = [] result = []
location = context.get_param('location', False) location = context.get_param('location', False)

View file

@ -11,13 +11,14 @@
from __future__ import absolute_import, division, unicode_literals from __future__ import absolute_import, division, unicode_literals
from . import ( from . import (
const_content_types as content, const_content_types as CONTENT,
const_paths as paths, const_paths as PATHS,
const_settings as settings, const_settings as SETTINGS,
const_sort_methods as sort, const_sort_methods as SORT,
) )
# Addon paths
ADDON_ID = 'plugin.video.youtube' ADDON_ID = 'plugin.video.youtube'
ADDON_PATH = 'special://home/addons/{id}'.format(id=ADDON_ID) ADDON_PATH = 'special://home/addons/{id}'.format(id=ADDON_ID)
DATA_PATH = 'special://profile/addon_data/{id}'.format(id=ADDON_ID) DATA_PATH = 'special://profile/addon_data/{id}'.format(id=ADDON_ID)
@ -25,6 +26,7 @@ MEDIA_PATH = ADDON_PATH + '/resources/media'
RESOURCE_PATH = ADDON_PATH + '/resources' RESOURCE_PATH = ADDON_PATH + '/resources'
TEMP_PATH = 'special://temp/{id}'.format(id=ADDON_ID) TEMP_PATH = 'special://temp/{id}'.format(id=ADDON_ID)
# Const values
VALUE_FROM_STR = { VALUE_FROM_STR = {
'0': False, '0': False,
'1': True, '1': True,
@ -32,75 +34,99 @@ VALUE_FROM_STR = {
'true': True, 'true': True,
} }
# Flags
ABORT_FLAG = 'abort_requested' ABORT_FLAG = 'abort_requested'
BUSY_FLAG = 'busy' BUSY_FLAG = 'busy'
SLEEPING = 'sleeping'
WAIT_FLAG = 'builtin_running'
# ListItem Properties
CHANNEL_ID = 'channel_id' CHANNEL_ID = 'channel_id'
CHECK_SETTINGS = 'check_settings'
DEVELOPER_CONFIGS = 'configs'
CONTENT_TYPE = 'content_type'
LICENSE_TOKEN = 'license_token'
LICENSE_URL = 'license_url'
PLAY_COUNT = 'video_play_count' PLAY_COUNT = 'video_play_count'
PLAY_FORCE_AUDIO = 'audio_only' PLAYLIST_ID = 'playlist_id'
PLAY_PROMPT_QUALITY = 'ask_for_quality' PLAYLISTITEM_ID = 'playlistitem_id'
PLAY_PROMPT_SUBTITLES = 'prompt_for_subtitles' SUBSCRIPTION_ID = 'subscription_id'
VIDEO_ID = 'video_id'
# Events
CHECK_SETTINGS = 'check_settings'
PLAYBACK_INIT = 'playback_init' PLAYBACK_INIT = 'playback_init'
PLAYBACK_STARTED = 'playback_started' PLAYBACK_STARTED = 'playback_started'
PLAYBACK_STOPPED = 'playback_stopped' PLAYBACK_STOPPED = 'playback_stopped'
PLAYER_DATA = 'player_json'
PLAYLIST_ID = 'playlist_id'
PLAYLISTITEM_ID = 'playlistitem_id'
PLAYLIST_PATH = 'playlist_path'
PLAYLIST_POSITION = 'playlist_position'
REFRESH_CONTAINER = 'refresh_container' REFRESH_CONTAINER = 'refresh_container'
RELOAD_ACCESS_MANAGER = 'reload_access_manager' RELOAD_ACCESS_MANAGER = 'reload_access_manager'
REROUTE = 'reroute'
SLEEPING = 'sleeping'
SUBSCRIPTION_ID = 'subscription_id'
SWITCH_PLAYER_FLAG = 'switch_player'
VIDEO_ID = 'video_id'
WAIT_FLAG = 'builtin_running'
WAKEUP = 'wakeup' WAKEUP = 'wakeup'
# Play options
PLAY_FORCE_AUDIO = 'audio_only'
PLAY_PROMPT_QUALITY = 'ask_for_quality'
PLAY_PROMPT_SUBTITLES = 'prompt_for_subtitles'
PLAY_WITH = 'play_with'
# Stored data
CONTENT_TYPE = 'content_type'
DEVELOPER_CONFIGS = 'configs'
LICENSE_TOKEN = 'license_token'
LICENSE_URL = 'license_url'
PLAYER_DATA = 'player_json'
PLAYLIST_PATH = 'playlist_path'
PLAYLIST_POSITION = 'playlist_position'
REROUTE_PATH = 'reroute_path'
__all__ = ( __all__ = (
'ABORT_FLAG', # Addon paths
'ADDON_ID', 'ADDON_ID',
'ADDON_PATH', 'ADDON_PATH',
'BUSY_FLAG',
'CHANNEL_ID',
'CHECK_SETTINGS',
'CONTENT_TYPE',
'DATA_PATH', 'DATA_PATH',
'DEVELOPER_CONFIGS',
'LICENSE_TOKEN',
'LICENSE_URL',
'MEDIA_PATH', 'MEDIA_PATH',
'RESOURCE_PATH',
'TEMP_PATH',
# Const values
'VALUE_FROM_STR',
# Flags
'ABORT_FLAG',
'BUSY_FLAG',
'SLEEPING',
'WAIT_FLAG',
# ListItem properties
'CHANNEL_ID',
'PLAY_COUNT', 'PLAY_COUNT',
'PLAY_FORCE_AUDIO', 'PLAYLIST_ID',
'PLAY_PROMPT_QUALITY', 'PLAYLISTITEM_ID',
'PLAY_PROMPT_SUBTITLES', 'SUBSCRIPTION_ID',
'VIDEO_ID',
# Events
'CHECK_SETTINGS',
'PLAYBACK_INIT', 'PLAYBACK_INIT',
'PLAYBACK_STARTED', 'PLAYBACK_STARTED',
'PLAYBACK_STOPPED', 'PLAYBACK_STOPPED',
'PLAYER_DATA',
'PLAYLIST_ID',
'PLAYLISTITEM_ID',
'PLAYLIST_PATH',
'PLAYLIST_POSITION',
'REFRESH_CONTAINER', 'REFRESH_CONTAINER',
'RELOAD_ACCESS_MANAGER', 'RELOAD_ACCESS_MANAGER',
'RESOURCE_PATH',
'REROUTE',
'SLEEPING',
'SUBSCRIPTION_ID',
'SWITCH_PLAYER_FLAG',
'TEMP_PATH',
'VALUE_FROM_STR',
'VIDEO_ID',
'WAIT_FLAG',
'WAKEUP', 'WAKEUP',
'content',
'paths', # Play options
'settings', 'PLAY_FORCE_AUDIO',
'sort', 'PLAY_PROMPT_QUALITY',
'PLAY_PROMPT_SUBTITLES',
'PLAY_WITH',
# Stored data
'CONTENT_TYPE',
'DEVELOPER_CONFIGS',
'LICENSE_TOKEN',
'LICENSE_URL',
'PLAYER_DATA',
'PLAYLIST_PATH',
'PLAYLIST_POSITION',
'REROUTE_PATH',
# Other constants
'CONTENT',
'PATHS',
'SETTINGS',
'SORT',
) )

View file

@ -14,7 +14,13 @@ import os
from .. import logger from .. import logger
from ..compatibility import quote, to_str, urlencode from ..compatibility import quote, to_str, urlencode
from ..constants import VALUE_FROM_STR from ..constants import (
PLAY_FORCE_AUDIO,
PLAY_PROMPT_QUALITY,
PLAY_PROMPT_SUBTITLES,
PLAY_WITH,
VALUE_FROM_STR,
)
from ..json_store import AccessManager from ..json_store import AccessManager
from ..sql_store import ( from ..sql_store import (
BookmarksList, BookmarksList,
@ -34,8 +40,10 @@ class AbstractContext(object):
_settings = None _settings = None
_BOOL_PARAMS = { _BOOL_PARAMS = {
'ask_for_quality', PLAY_FORCE_AUDIO,
'audio_only', PLAY_PROMPT_SUBTITLES,
PLAY_PROMPT_QUALITY,
PLAY_WITH,
'confirmed', 'confirmed',
'clip', 'clip',
'enable', 'enable',
@ -47,7 +55,6 @@ class AbstractContext(object):
'location', 'location',
'logged_in', 'logged_in',
'play', 'play',
'prompt_for_subtitles',
'resume', 'resume',
'screensaver', 'screensaver',
'strm', 'strm',

View file

@ -27,10 +27,10 @@ from ...compatibility import (
from ...constants import ( from ...constants import (
ABORT_FLAG, ABORT_FLAG,
ADDON_ID, ADDON_ID,
CONTENT,
CONTENT_TYPE, CONTENT_TYPE,
SORT,
WAKEUP, WAKEUP,
content,
sort,
) )
from ...player import XbmcPlayer, XbmcPlaylist from ...player import XbmcPlayer, XbmcPlaylist
from ...settings import XbmcPluginSettings from ...settings import XbmcPluginSettings
@ -534,43 +534,43 @@ class XbmcContext(AbstractContext):
detailed_labels = self.get_settings().show_detailed_labels() detailed_labels = self.get_settings().show_detailed_labels()
if sub_type == 'history': if sub_type == 'history':
self.add_sort_method( self.add_sort_method(
(sort.LASTPLAYED, '%T \u2022 %P', '%D | %J'), (SORT.LASTPLAYED, '%T \u2022 %P', '%D | %J'),
(sort.PLAYCOUNT, '%T \u2022 %P', '%D | %J'), (SORT.PLAYCOUNT, '%T \u2022 %P', '%D | %J'),
(sort.UNSORTED, '%T \u2022 %P', '%D | %J'), (SORT.UNSORTED, '%T \u2022 %P', '%D | %J'),
(sort.LABEL, '%T \u2022 %P', '%D | %J'), (SORT.LABEL, '%T \u2022 %P', '%D | %J'),
) if detailed_labels else self.add_sort_method( ) if detailed_labels else self.add_sort_method(
(sort.LASTPLAYED,), (SORT.LASTPLAYED,),
(sort.PLAYCOUNT,), (SORT.PLAYCOUNT,),
(sort.UNSORTED,), (SORT.UNSORTED,),
(sort.LABEL,), (SORT.LABEL,),
) )
else: else:
self.add_sort_method( self.add_sort_method(
(sort.UNSORTED, '%T \u2022 %P', '%D | %J'), (SORT.UNSORTED, '%T \u2022 %P', '%D | %J'),
(sort.LABEL, '%T \u2022 %P', '%D | %J'), (SORT.LABEL, '%T \u2022 %P', '%D | %J'),
) if detailed_labels else self.add_sort_method( ) if detailed_labels else self.add_sort_method(
(sort.UNSORTED,), (SORT.UNSORTED,),
(sort.LABEL,), (SORT.LABEL,),
) )
if content_type == content.VIDEO_CONTENT: if content_type == CONTENT.VIDEO_CONTENT:
self.add_sort_method( self.add_sort_method(
(sort.CHANNEL, '[%A - ]%T \u2022 %P', '%D | %J'), (SORT.CHANNEL, '[%A - ]%T \u2022 %P', '%D | %J'),
(sort.ARTIST, '%T \u2022 %P | %D | %J', '%A'), (SORT.ARTIST, '%T \u2022 %P | %D | %J', '%A'),
(sort.PROGRAM_COUNT, '%T \u2022 %P | %D | %J', '%C'), (SORT.PROGRAM_COUNT, '%T \u2022 %P | %D | %J', '%C'),
(sort.VIDEO_RATING, '%T \u2022 %P | %D | %J', '%R'), (SORT.VIDEO_RATING, '%T \u2022 %P | %D | %J', '%R'),
(sort.DATE, '%T \u2022 %P | %D', '%J'), (SORT.DATE, '%T \u2022 %P | %D', '%J'),
(sort.DATEADDED, '%T \u2022 %P | %D', '%a'), (SORT.DATEADDED, '%T \u2022 %P | %D', '%a'),
(sort.VIDEO_RUNTIME, '%T \u2022 %P | %J', '%D'), (SORT.VIDEO_RUNTIME, '%T \u2022 %P | %J', '%D'),
(sort.TRACKNUM, '[%N. ]%T \u2022 %P', '%D | %J'), (SORT.TRACKNUM, '[%N. ]%T \u2022 %P', '%D | %J'),
) if detailed_labels else self.add_sort_method( ) if detailed_labels else self.add_sort_method(
(sort.CHANNEL, '[%A - ]%T'), (SORT.CHANNEL, '[%A - ]%T'),
(sort.ARTIST,), (SORT.ARTIST,),
(sort.PROGRAM_COUNT,), (SORT.PROGRAM_COUNT,),
(sort.VIDEO_RATING,), (SORT.VIDEO_RATING,),
(sort.DATE,), (SORT.DATE,),
(sort.DATEADDED,), (SORT.DATEADDED,),
(sort.VIDEO_RUNTIME,), (SORT.VIDEO_RUNTIME,),
(sort.TRACKNUM, '[%N. ]%T '), (SORT.TRACKNUM, '[%N. ]%T '),
) )
def add_sort_method(self, *sort_methods): def add_sort_method(self, *sort_methods):

View file

@ -12,7 +12,7 @@ from __future__ import absolute_import, division, unicode_literals
from . import menu_items from . import menu_items
from .directory_item import DirectoryItem from .directory_item import DirectoryItem
from ..constants import paths from ..constants import PATHS
class CommandItem(DirectoryItem): class CommandItem(DirectoryItem):
@ -25,7 +25,7 @@ class CommandItem(DirectoryItem):
plot=None): plot=None):
super(CommandItem, self).__init__( super(CommandItem, self).__init__(
name, name,
context.create_uri((paths.COMMAND, command)), context.create_uri((PATHS.COMMAND, command)),
image=image, image=image,
fanart=fanart, fanart=fanart,
plot=plot, plot=plot,

View file

@ -10,7 +10,13 @@
from __future__ import absolute_import, division, unicode_literals from __future__ import absolute_import, division, unicode_literals
from ..constants import ADDON_ID, paths from ..constants import (
PATHS,
PLAY_FORCE_AUDIO,
PLAY_PROMPT_QUALITY,
PLAY_PROMPT_SUBTITLES,
PLAY_WITH,
)
def more_for_video(context, video_id, logged_in=False, refresh=False): def more_for_video(context, video_id, logged_in=False, refresh=False):
@ -33,7 +39,7 @@ def related_videos(context, video_id):
return ( return (
context.localize('related_videos'), context.localize('related_videos'),
'RunPlugin({0})'.format(context.create_uri( 'RunPlugin({0})'.format(context.create_uri(
(paths.ROUTE, 'special', 'related_videos',), (PATHS.ROUTE, 'special', 'related_videos',),
{ {
'video_id': video_id, 'video_id': video_id,
}, },
@ -45,7 +51,7 @@ def video_comments(context, video_id):
return ( return (
context.localize('video.comments'), context.localize('video.comments'),
'RunPlugin({0})'.format(context.create_uri( 'RunPlugin({0})'.format(context.create_uri(
(paths.ROUTE, 'special', 'parent_comments',), (PATHS.ROUTE, 'special', 'parent_comments',),
{ {
'video_id': video_id, 'video_id': video_id,
}, },
@ -57,7 +63,7 @@ def content_from_description(context, video_id):
return ( return (
context.localize('video.description.links'), context.localize('video.description.links'),
'RunPlugin({0})'.format(context.create_uri( 'RunPlugin({0})'.format(context.create_uri(
(paths.ROUTE, 'special', 'description_links',), (PATHS.ROUTE, 'special', 'description_links',),
{ {
'video_id': video_id, 'video_id': video_id,
}, },
@ -65,10 +71,16 @@ def content_from_description(context, video_id):
) )
def play_with(context): def play_with(context, video_id):
return ( return (
context.localize('video.play.with'), context.localize('video.play.with'),
'RunScript({addon_id},action/play_with)'.format(addon_id=ADDON_ID), 'RunPlugin({0})'.format(context.create_uri(
('play',),
{
'video_id': video_id,
PLAY_WITH: True,
},
))
) )
@ -77,7 +89,7 @@ def refresh(context):
return ( return (
context.localize('refresh'), context.localize('refresh'),
'RunPlugin({0})'.format(context.create_uri( 'RunPlugin({0})'.format(context.create_uri(
(paths.ROUTE, context.get_path(),), (PATHS.ROUTE, context.get_path(),),
dict(params, refresh=params.get('refresh', 0) + 1), dict(params, refresh=params.get('refresh', 0) + 1),
)) ))
) )
@ -279,7 +291,7 @@ def watch_later_local_add(context, item):
return ( return (
context.localize('watch_later.add'), context.localize('watch_later.add'),
'RunPlugin({0})'.format(context.create_uri( 'RunPlugin({0})'.format(context.create_uri(
(paths.WATCH_LATER, 'add',), (PATHS.WATCH_LATER, 'add',),
{ {
'video_id': item.video_id, 'video_id': item.video_id,
'item': repr(item), 'item': repr(item),
@ -292,7 +304,7 @@ def watch_later_local_remove(context, video_id):
return ( return (
context.localize('watch_later.remove'), context.localize('watch_later.remove'),
'RunPlugin({0})'.format(context.create_uri( 'RunPlugin({0})'.format(context.create_uri(
(paths.WATCH_LATER, 'remove',), (PATHS.WATCH_LATER, 'remove',),
{ {
'video_id': video_id, 'video_id': video_id,
}, },
@ -304,7 +316,7 @@ def watch_later_local_clear(context):
return ( return (
context.localize('watch_later.clear'), context.localize('watch_later.clear'),
'RunPlugin({0})'.format(context.create_uri( 'RunPlugin({0})'.format(context.create_uri(
(paths.WATCH_LATER, 'clear',), (PATHS.WATCH_LATER, 'clear',),
)) ))
) )
@ -313,7 +325,7 @@ def go_to_channel(context, channel_id, channel_name):
return ( return (
context.localize('go_to_channel') % context.get_ui().bold(channel_name), context.localize('go_to_channel') % context.get_ui().bold(channel_name),
'RunPlugin({0})'.format(context.create_uri( 'RunPlugin({0})'.format(context.create_uri(
(paths.ROUTE, 'channel', channel_id,), (PATHS.ROUTE, 'channel', channel_id,),
)) ))
) )
@ -357,7 +369,7 @@ def play_with_subtitles(context, video_id):
('play',), ('play',),
{ {
'video_id': video_id, 'video_id': video_id,
'prompt_for_subtitles': True, PLAY_PROMPT_SUBTITLES: True,
}, },
)) ))
) )
@ -370,7 +382,7 @@ def play_audio_only(context, video_id):
('play',), ('play',),
{ {
'video_id': video_id, 'video_id': video_id,
'audio_only': True, PLAY_FORCE_AUDIO: True,
}, },
)) ))
) )
@ -383,7 +395,7 @@ def play_ask_for_quality(context, video_id):
('play',), ('play',),
{ {
'video_id': video_id, 'video_id': video_id,
'ask_for_quality': True, PLAY_PROMPT_QUALITY: True,
}, },
)) ))
) )
@ -393,7 +405,7 @@ def history_remove(context, video_id):
return ( return (
context.localize('history.remove'), context.localize('history.remove'),
'RunPlugin({0})'.format(context.create_uri( 'RunPlugin({0})'.format(context.create_uri(
(paths.HISTORY,), (PATHS.HISTORY,),
{ {
'action': 'remove', 'action': 'remove',
'video_id': video_id 'video_id': video_id
@ -406,7 +418,7 @@ def history_clear(context):
return ( return (
context.localize('history.clear'), context.localize('history.clear'),
'RunPlugin({0})'.format(context.create_uri( 'RunPlugin({0})'.format(context.create_uri(
(paths.HISTORY,), (PATHS.HISTORY,),
{ {
'action': 'clear' 'action': 'clear'
}, },
@ -418,7 +430,7 @@ def history_mark_watched(context, video_id):
return ( return (
context.localize('history.mark.watched'), context.localize('history.mark.watched'),
'RunPlugin({0})'.format(context.create_uri( 'RunPlugin({0})'.format(context.create_uri(
(paths.HISTORY,), (PATHS.HISTORY,),
{ {
'video_id': video_id, 'video_id': video_id,
'action': 'mark_watched', 'action': 'mark_watched',
@ -431,7 +443,7 @@ def history_mark_unwatched(context, video_id):
return ( return (
context.localize('history.mark.unwatched'), context.localize('history.mark.unwatched'),
'RunPlugin({0})'.format(context.create_uri( 'RunPlugin({0})'.format(context.create_uri(
(paths.HISTORY,), (PATHS.HISTORY,),
{ {
'video_id': video_id, 'video_id': video_id,
'action': 'mark_unwatched', 'action': 'mark_unwatched',
@ -444,7 +456,7 @@ def history_reset_resume(context, video_id):
return ( return (
context.localize('history.reset.resume_point'), context.localize('history.reset.resume_point'),
'RunPlugin({0})'.format(context.create_uri( 'RunPlugin({0})'.format(context.create_uri(
(paths.HISTORY,), (PATHS.HISTORY,),
{ {
'video_id': video_id, 'video_id': video_id,
'action': 'reset_resume', 'action': 'reset_resume',
@ -457,7 +469,7 @@ def bookmarks_add(context, item):
return ( return (
context.localize('bookmarks.add'), context.localize('bookmarks.add'),
'RunPlugin({0})'.format(context.create_uri( 'RunPlugin({0})'.format(context.create_uri(
(paths.BOOKMARKS, 'add',), (PATHS.BOOKMARKS, 'add',),
{ {
'item_id': item.get_id(), 'item_id': item.get_id(),
'item': repr(item), 'item': repr(item),
@ -473,7 +485,7 @@ def bookmarks_add_channel(context, channel_id, channel_name=''):
context.localize(19029) context.localize(19029)
)), )),
'RunPlugin({0})'.format(context.create_uri( 'RunPlugin({0})'.format(context.create_uri(
(paths.BOOKMARKS, 'add',), (PATHS.BOOKMARKS, 'add',),
{ {
'item_id': channel_id, 'item_id': channel_id,
'item': None, 'item': None,
@ -486,7 +498,7 @@ def bookmarks_remove(context, item_id):
return ( return (
context.localize('bookmarks.remove'), context.localize('bookmarks.remove'),
'RunPlugin({0})'.format(context.create_uri( 'RunPlugin({0})'.format(context.create_uri(
(paths.BOOKMARKS, 'remove',), (PATHS.BOOKMARKS, 'remove',),
{ {
'item_id': item_id, 'item_id': item_id,
}, },
@ -498,7 +510,7 @@ def bookmarks_clear(context):
return ( return (
context.localize('bookmarks.clear'), context.localize('bookmarks.clear'),
'RunPlugin({0})'.format(context.create_uri( 'RunPlugin({0})'.format(context.create_uri(
(paths.BOOKMARKS, 'clear',), (PATHS.BOOKMARKS, 'clear',),
)) ))
) )
@ -507,7 +519,7 @@ def search_remove(context, query):
return ( return (
context.localize('search.remove'), context.localize('search.remove'),
'RunPlugin({0})'.format(context.create_uri( 'RunPlugin({0})'.format(context.create_uri(
(paths.SEARCH, 'remove',), (PATHS.SEARCH, 'remove',),
{ {
'q': query, 'q': query,
}, },
@ -519,7 +531,7 @@ def search_rename(context, query):
return ( return (
context.localize('search.rename'), context.localize('search.rename'),
'RunPlugin({0})'.format(context.create_uri( 'RunPlugin({0})'.format(context.create_uri(
(paths.SEARCH, 'rename',), (PATHS.SEARCH, 'rename',),
{ {
'q': query, 'q': query,
}, },
@ -531,7 +543,7 @@ def search_clear(context):
return ( return (
context.localize('search.clear'), context.localize('search.clear'),
'RunPlugin({0})'.format(context.create_uri( 'RunPlugin({0})'.format(context.create_uri(
(paths.SEARCH, 'clear',), (PATHS.SEARCH, 'clear',),
)) ))
) )
@ -547,7 +559,7 @@ def goto_home(context):
return ( return (
context.localize(10000), context.localize(10000),
'RunPlugin({0})'.format(context.create_uri( 'RunPlugin({0})'.format(context.create_uri(
(paths.ROUTE, paths.HOME,), (PATHS.ROUTE, PATHS.HOME,),
{ {
'window_return': False, 'window_return': False,
}, },
@ -559,7 +571,7 @@ def goto_quick_search(context):
return ( return (
context.localize('search.quick'), context.localize('search.quick'),
'RunPlugin({0})'.format(context.create_uri( 'RunPlugin({0})'.format(context.create_uri(
(paths.ROUTE, paths.SEARCH, 'input',), (PATHS.ROUTE, PATHS.SEARCH, 'input',),
)) ))
) )
@ -568,7 +580,7 @@ def goto_page(context, params=None):
return ( return (
context.localize('page.choose'), context.localize('page.choose'),
'RunPlugin({0})'.format(context.create_uri( 'RunPlugin({0})'.format(context.create_uri(
(paths.GOTO_PAGE, context.get_path(),), (PATHS.GOTO_PAGE, context.get_path(),),
params or context.get_params(), params or context.get_params(),
)) ))
) )

View file

@ -11,7 +11,7 @@
from __future__ import absolute_import, division, unicode_literals from __future__ import absolute_import, division, unicode_literals
from .directory_item import DirectoryItem from .directory_item import DirectoryItem
from ..constants import paths from ..constants import PATHS
class NewSearchItem(DirectoryItem): class NewSearchItem(DirectoryItem):
@ -42,7 +42,7 @@ class NewSearchItem(DirectoryItem):
super(NewSearchItem, self).__init__(name, super(NewSearchItem, self).__init__(name,
context.create_uri( context.create_uri(
(paths.SEARCH, 'input',), (PATHS.SEARCH, 'input',),
params=params, params=params,
), ),
image=image, image=image,

View file

@ -12,7 +12,7 @@ from __future__ import absolute_import, division, unicode_literals
from . import menu_items from . import menu_items
from .directory_item import DirectoryItem from .directory_item import DirectoryItem
from ..constants import paths from ..constants import PATHS
class SearchHistoryItem(DirectoryItem): class SearchHistoryItem(DirectoryItem):
@ -26,7 +26,7 @@ class SearchHistoryItem(DirectoryItem):
super(SearchHistoryItem, self).__init__(query, super(SearchHistoryItem, self).__init__(query,
context.create_uri( context.create_uri(
(paths.SEARCH, 'query',), (PATHS.SEARCH, 'query',),
params=params, params=params,
), ),
image=image, image=image,

View file

@ -11,7 +11,7 @@
from __future__ import absolute_import, division, unicode_literals from __future__ import absolute_import, division, unicode_literals
from .directory_item import DirectoryItem from .directory_item import DirectoryItem
from ..constants import paths from ..constants import PATHS
class SearchItem(DirectoryItem): class SearchItem(DirectoryItem):
@ -33,7 +33,7 @@ class SearchItem(DirectoryItem):
super(SearchItem, self).__init__(name, super(SearchItem, self).__init__(name,
context.create_uri( context.create_uri(
(paths.SEARCH, 'list',), (PATHS.SEARCH, 'list',),
params=params, params=params,
), ),
image=image, image=image,

View file

@ -11,7 +11,7 @@
from __future__ import absolute_import, division, unicode_literals from __future__ import absolute_import, division, unicode_literals
from .directory_item import DirectoryItem from .directory_item import DirectoryItem
from ..constants import paths from ..constants import PATHS
class WatchLaterItem(DirectoryItem): class WatchLaterItem(DirectoryItem):
@ -24,7 +24,7 @@ class WatchLaterItem(DirectoryItem):
super(WatchLaterItem, self).__init__(name, super(WatchLaterItem, self).__init__(name,
context.create_uri( context.create_uri(
(paths.WATCH_LATER, 'list',), (PATHS.WATCH_LATER, 'list',),
), ),
image=image, image=image,
fanart=fanart) fanart=fanart)

View file

@ -16,11 +16,11 @@ from .. import AudioItem, DirectoryItem, ImageItem, VideoItem
from ...compatibility import to_str, xbmc, xbmcgui from ...compatibility import to_str, xbmc, xbmcgui
from ...constants import ( from ...constants import (
CHANNEL_ID, CHANNEL_ID,
PLAY_COUNT,
PLAYLIST_ID,
PLAYLISTITEM_ID, PLAYLISTITEM_ID,
PLAYLIST_ID,
PLAY_COUNT,
PLAY_WITH,
SUBSCRIPTION_ID, SUBSCRIPTION_ID,
SWITCH_PLAYER_FLAG,
VIDEO_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_from_url
@ -380,7 +380,7 @@ def video_playback_item(context, video_item, show_fanart=None, **_kwargs):
settings = context.get_settings() settings = context.get_settings()
headers = video_item.get_headers() headers = video_item.get_headers()
license_key = video_item.get_license_key() license_key = video_item.get_license_key()
is_external = context.get_ui().get_property(SWITCH_PLAYER_FLAG) is_external = context.get_ui().get_property(PLAY_WITH)
is_strm = context.get_param('strm') is_strm = context.get_param('strm')
mime_type = None mime_type = None

View file

@ -19,8 +19,8 @@ from ..constants import (
PLAYBACK_STARTED, PLAYBACK_STARTED,
PLAYBACK_STOPPED, PLAYBACK_STOPPED,
PLAYER_DATA, PLAYER_DATA,
PLAY_WITH,
REFRESH_CONTAINER, REFRESH_CONTAINER,
SWITCH_PLAYER_FLAG,
) )
@ -352,12 +352,12 @@ class PlayerMonitor(xbmc.Player):
self.threads = active_threads self.threads = active_threads
def onPlayBackStarted(self): def onPlayBackStarted(self):
if self._ui.get_property(SWITCH_PLAYER_FLAG): if self._ui.get_property(PLAY_WITH):
self._context.execute('Action(SwitchPlayer)') self._context.execute('Action(SwitchPlayer)')
self._context.execute('Action(Stop)') self._context.execute('Action(Stop)')
def onAVStarted(self): def onAVStarted(self):
if self._ui.get_property(SWITCH_PLAYER_FLAG): if self._ui.get_property(PLAY_WITH):
return return
if not self._ui.busy_dialog_active(): if not self._ui.busy_dialog_active():
@ -393,8 +393,8 @@ class PlayerMonitor(xbmc.Player):
if not self._ui.busy_dialog_active(): if not self._ui.busy_dialog_active():
self._ui.clear_property(BUSY_FLAG) self._ui.clear_property(BUSY_FLAG)
if self._ui.get_property(SWITCH_PLAYER_FLAG): if self._ui.get_property(PLAY_WITH):
self._ui.clear_property(SWITCH_PLAYER_FLAG) self._ui.clear_property(PLAY_WITH)
self.stop_threads() self.stop_threads()
self.cleanup_threads() self.cleanup_threads()

View file

@ -26,7 +26,7 @@ from ..compatibility import (
xbmcgui, xbmcgui,
xbmcvfs, xbmcvfs,
) )
from ..constants import ADDON_ID, LICENSE_TOKEN, LICENSE_URL, TEMP_PATH, paths from ..constants import ADDON_ID, LICENSE_TOKEN, LICENSE_URL, PATHS, TEMP_PATH
from ..logger import log_debug, log_error 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_from_url, wait
@ -81,7 +81,7 @@ class RequestHandler(BaseHTTPRequestHandler, object):
if not conn_allowed: if not conn_allowed:
log_debug('HTTPServer: Connection from |{client_ip| not allowed' log_debug('HTTPServer: Connection from |{client_ip| not allowed'
.format(client_ip=client_ip)) .format(client_ip=client_ip))
elif self.path != paths.PING: elif self.path != PATHS.PING:
log_debug(' '.join(log_lines)) log_debug(' '.join(log_lines))
return conn_allowed return conn_allowed
@ -93,7 +93,7 @@ class RequestHandler(BaseHTTPRequestHandler, object):
# Strip trailing slash if present # Strip trailing slash if present
stripped_path = self.path.rstrip('/') stripped_path = self.path.rstrip('/')
if stripped_path != paths.PING: if stripped_path != PATHS.PING:
log_debug('HTTPServer: GET |{path}|'.format( log_debug('HTTPServer: GET |{path}|'.format(
path=redact_ip_from_url(self.path) path=redact_ip_from_url(self.path)
)) ))
@ -101,7 +101,7 @@ class RequestHandler(BaseHTTPRequestHandler, object):
if not self.connection_allowed(): if not self.connection_allowed():
self.send_error(403) self.send_error(403)
elif stripped_path == paths.IP: elif stripped_path == PATHS.IP:
client_json = json.dumps({"ip": "{ip}" client_json = json.dumps({"ip": "{ip}"
.format(ip=self.client_address[0])}) .format(ip=self.client_address[0])})
self.send_response(200) self.send_response(200)
@ -110,8 +110,8 @@ class RequestHandler(BaseHTTPRequestHandler, object):
self.end_headers() self.end_headers()
self.wfile.write(client_json.encode('utf-8')) self.wfile.write(client_json.encode('utf-8'))
elif stripped_path.startswith(paths.MPD): elif stripped_path.startswith(PATHS.MPD):
filepath = os.path.join(self.BASE_PATH, self.path[len(paths.MPD):]) filepath = os.path.join(self.BASE_PATH, self.path[len(PATHS.MPD):])
file_chunk = True file_chunk = True
try: try:
with open(filepath, 'rb') as f: with open(filepath, 'rb') as f:
@ -129,7 +129,7 @@ class RequestHandler(BaseHTTPRequestHandler, object):
.format(path=self.path, filepath=filepath)) .format(path=self.path, filepath=filepath))
self.send_error(404, response) self.send_error(404, response)
elif api_config_enabled and stripped_path == paths.API: elif api_config_enabled and stripped_path == PATHS.API:
html = self.api_config_page() html = self.api_config_page()
html = html.encode('utf-8') html = html.encode('utf-8')
@ -141,7 +141,7 @@ class RequestHandler(BaseHTTPRequestHandler, object):
for chunk in self.get_chunks(html): for chunk in self.get_chunks(html):
self.wfile.write(chunk) self.wfile.write(chunk)
elif api_config_enabled and stripped_path.startswith(paths.API_SUBMIT): elif api_config_enabled and stripped_path.startswith(PATHS.API_SUBMIT):
xbmc.executebuiltin('Dialog.Close(addonsettings,true)') xbmc.executebuiltin('Dialog.Close(addonsettings,true)')
query = urlsplit(self.path).query query = urlsplit(self.path).query
@ -199,10 +199,10 @@ class RequestHandler(BaseHTTPRequestHandler, object):
for chunk in self.get_chunks(html): for chunk in self.get_chunks(html):
self.wfile.write(chunk) self.wfile.write(chunk)
elif stripped_path == paths.PING: elif stripped_path == PATHS.PING:
self.send_error(204) self.send_error(204)
elif stripped_path.startswith(paths.REDIRECT): elif stripped_path.startswith(PATHS.REDIRECT):
url = parse_qs(urlsplit(self.path).query).get('url') url = parse_qs(urlsplit(self.path).query).get('url')
if url: if url:
wait(1) wait(1)
@ -222,8 +222,8 @@ class RequestHandler(BaseHTTPRequestHandler, object):
if not self.connection_allowed(): if not self.connection_allowed():
self.send_error(403) self.send_error(403)
elif self.path.startswith(paths.MPD): elif self.path.startswith(PATHS.MPD):
filepath = os.path.join(self.BASE_PATH, self.path[len(paths.MPD):]) filepath = os.path.join(self.BASE_PATH, self.path[len(PATHS.MPD):])
if not os.path.isfile(filepath): if not os.path.isfile(filepath):
response = ('File Not Found: |{path}| -> |{filepath}|' response = ('File Not Found: |{path}| -> |{filepath}|'
.format(path=self.path, filepath=filepath)) .format(path=self.path, filepath=filepath))
@ -235,7 +235,7 @@ class RequestHandler(BaseHTTPRequestHandler, object):
str(os.path.getsize(filepath))) str(os.path.getsize(filepath)))
self.end_headers() self.end_headers()
elif self.path.startswith(paths.REDIRECT): elif self.path.startswith(PATHS.REDIRECT):
self.send_error(404) self.send_error(404)
else: else:
@ -248,7 +248,7 @@ class RequestHandler(BaseHTTPRequestHandler, object):
if not self.connection_allowed(): if not self.connection_allowed():
self.send_error(403) self.send_error(403)
elif self.path.startswith(paths.DRM): elif self.path.startswith(PATHS.DRM):
home = xbmcgui.Window(10000) home = xbmcgui.Window(10000)
lic_url = home.getProperty('-'.join((ADDON_ID, LICENSE_URL))) lic_url = home.getProperty('-'.join((ADDON_ID, LICENSE_URL)))
@ -408,7 +408,7 @@ class Pages(object):
</div> </div>
</body> </body>
</html> </html>
'''.format(action_url=paths.API_SUBMIT)), '''.format(action_url=PATHS.API_SUBMIT)),
'css': ''.join('\t\t\t'.expandtabs(2) + line for line in dedent(''' 'css': ''.join('\t\t\t'.expandtabs(2) + line for line in dedent('''
body { body {
background: #141718; background: #141718;
@ -579,7 +579,7 @@ def httpd_status(context):
address, port = get_connect_address(context) address, port = get_connect_address(context)
url = 'http://{address}:{port}{path}'.format(address=address, url = 'http://{address}:{port}{path}'.format(address=address,
port=port, port=port,
path=paths.PING) path=PATHS.PING)
response = RequestHandler.requests.request(url) response = RequestHandler.requests.request(url)
result = response and response.status_code result = response and response.status_code
if result == 204: if result == 204:
@ -597,7 +597,7 @@ def get_client_ip_address(context):
address, port = get_connect_address(context) address, port = get_connect_address(context)
url = 'http://{address}:{port}{path}'.format(address=address, url = 'http://{address}:{port}{path}'.format(address=address,
port=port, port=port,
path=paths.IP) path=PATHS.IP)
response = RequestHandler.requests.request(url) response = RequestHandler.requests.request(url)
if response and response.status_code == 200: if response and response.status_code == 200:
response_json = response.json() response_json = response.json()

View file

@ -21,7 +21,7 @@ from ...constants import (
PLAYLIST_POSITION, PLAYLIST_POSITION,
REFRESH_CONTAINER, REFRESH_CONTAINER,
RELOAD_ACCESS_MANAGER, RELOAD_ACCESS_MANAGER,
REROUTE, REROUTE_PATH,
SLEEPING, SLEEPING,
VIDEO_ID, VIDEO_ID,
) )
@ -154,7 +154,7 @@ class XbmcPlugin(AbstractPlugin):
provider.run_wizard(context) provider.run_wizard(context)
try: try:
route = ui.get_property(REROUTE) route = ui.get_property(REROUTE_PATH)
if route: if route:
function_cache = context.get_function_cache() function_cache = context.get_function_cache()
result, options = function_cache.run( result, options = function_cache.run(
@ -163,7 +163,7 @@ class XbmcPlugin(AbstractPlugin):
_scope=function_cache.SCOPE_NONE, _scope=function_cache.SCOPE_NONE,
context=context.clone(route), context=context.clone(route),
) )
ui.clear_property(REROUTE) ui.clear_property(REROUTE_PATH)
else: else:
result, options = provider.navigate(context) result, options = provider.navigate(context)
except KodionException as exc: except KodionException as exc:

View file

@ -16,7 +16,6 @@ from .compatibility import parse_qsl, urlsplit, xbmc, xbmcaddon, xbmcvfs
from .constants import ( from .constants import (
DATA_PATH, DATA_PATH,
RELOAD_ACCESS_MANAGER, RELOAD_ACCESS_MANAGER,
SWITCH_PLAYER_FLAG,
TEMP_PATH, TEMP_PATH,
WAIT_FLAG, WAIT_FLAG,
) )
@ -345,11 +344,6 @@ def run(argv):
xbmcaddon.Addon().openSettings() xbmcaddon.Addon().openSettings()
return return
if action == 'play_with':
ui.set_property(SWITCH_PLAYER_FLAG)
xbmc.executebuiltin('Action(Play)')
return
if category == 'config': if category == 'config':
_config_actions(context, action, params) _config_actions(context, action, params)
return return

View file

@ -12,13 +12,13 @@ from __future__ import absolute_import, division, unicode_literals
import sys import sys
from ..constants import settings from ..constants import SETTINGS
from ..utils import current_system_version, validate_ip_address from ..utils import current_system_version, validate_ip_address
class AbstractSettings(object): class AbstractSettings(object):
_vars = vars() _vars = vars()
for name, value in settings.__dict__.items(): for name, value in SETTINGS.__dict__.items():
_vars[name] = value _vars[name] = value
del _vars del _vars
@ -59,8 +59,8 @@ class AbstractSettings(object):
def items_per_page(self, value=None): def items_per_page(self, value=None):
if value is not None: if value is not None:
return self.set_int(settings.ITEMS_PER_PAGE, value) return self.set_int(SETTINGS.ITEMS_PER_PAGE, value)
return self.get_int(settings.ITEMS_PER_PAGE, 50) return self.get_int(SETTINGS.ITEMS_PER_PAGE, 50)
_VIDEO_QUALITY_MAP = { _VIDEO_QUALITY_MAP = {
0: 240, 0: 240,
@ -73,94 +73,94 @@ class AbstractSettings(object):
def fixed_video_quality(self, value=None): def fixed_video_quality(self, value=None):
default = 3 default = 3
if value is None: if value is None:
_value = self.get_int(settings.VIDEO_QUALITY, default) _value = self.get_int(SETTINGS.VIDEO_QUALITY, default)
else: else:
_value = value _value = value
if _value not in self._VIDEO_QUALITY_MAP: if _value not in self._VIDEO_QUALITY_MAP:
_value = default _value = default
if value is not None: if value is not None:
self.set_int(settings.VIDEO_QUALITY, _value) self.set_int(SETTINGS.VIDEO_QUALITY, _value)
return self._VIDEO_QUALITY_MAP[_value] return self._VIDEO_QUALITY_MAP[_value]
def ask_for_video_quality(self): def ask_for_video_quality(self):
return (self.get_bool(settings.VIDEO_QUALITY_ASK, False) return (self.get_bool(SETTINGS.VIDEO_QUALITY_ASK, False)
or self.get_int(settings.MPD_STREAM_SELECT) == 4) or self.get_int(SETTINGS.MPD_STREAM_SELECT) == 4)
def fanart_selection(self): def fanart_selection(self):
return self.get_int(settings.FANART_SELECTION, 2) return self.get_int(SETTINGS.FANART_SELECTION, 2)
def cache_size(self, value=None): def cache_size(self, value=None):
if value is not None: if value is not None:
return self.set_int(settings.CACHE_SIZE, value) return self.set_int(SETTINGS.CACHE_SIZE, value)
return self.get_int(settings.CACHE_SIZE, 20) return self.get_int(SETTINGS.CACHE_SIZE, 20)
def get_search_history_size(self): def get_search_history_size(self):
return self.get_int(settings.SEARCH_SIZE, 10) return self.get_int(SETTINGS.SEARCH_SIZE, 10)
def setup_wizard_enabled(self, value=None): def setup_wizard_enabled(self, value=None):
# Increment min_required on new release to enable oneshot on first run # Increment min_required on new release to enable oneshot on first run
min_required = 4 min_required = 4
if value is False: if value is False:
self.set_int(settings.SETUP_WIZARD_RUNS, min_required) self.set_int(SETTINGS.SETUP_WIZARD_RUNS, min_required)
return self.set_bool(settings.SETUP_WIZARD, False) return self.set_bool(SETTINGS.SETUP_WIZARD, False)
if value is True: if value is True:
self.set_int(settings.SETUP_WIZARD_RUNS, 0) self.set_int(SETTINGS.SETUP_WIZARD_RUNS, 0)
return self.set_bool(settings.SETUP_WIZARD, True) return self.set_bool(SETTINGS.SETUP_WIZARD, True)
forced_runs = self.get_int(settings.SETUP_WIZARD_RUNS, 0) forced_runs = self.get_int(SETTINGS.SETUP_WIZARD_RUNS, 0)
if forced_runs < min_required: if forced_runs < min_required:
self.set_int(settings.SETUP_WIZARD_RUNS, min_required) self.set_int(SETTINGS.SETUP_WIZARD_RUNS, min_required)
self.set_bool(settings.SETTINGS_END, True) self.set_bool(SETTINGS.SETTINGS_END, True)
return True return True
return self.get_bool(settings.SETUP_WIZARD, False) return self.get_bool(SETTINGS.SETUP_WIZARD, False)
def support_alternative_player(self, value=None): def support_alternative_player(self, value=None):
if value is not None: if value is not None:
return self.set_bool(settings.SUPPORT_ALTERNATIVE_PLAYER, value) return self.set_bool(SETTINGS.SUPPORT_ALTERNATIVE_PLAYER, value)
return self.get_bool(settings.SUPPORT_ALTERNATIVE_PLAYER, False) return self.get_bool(SETTINGS.SUPPORT_ALTERNATIVE_PLAYER, False)
def default_player_web_urls(self, value=None): def default_player_web_urls(self, value=None):
if value is not None: if value is not None:
return self.set_bool(settings.DEFAULT_PLAYER_WEB_URLS, value) return self.set_bool(SETTINGS.DEFAULT_PLAYER_WEB_URLS, value)
if self.support_alternative_player(): if self.support_alternative_player():
return False return False
return self.get_bool(settings.DEFAULT_PLAYER_WEB_URLS, False) return self.get_bool(SETTINGS.DEFAULT_PLAYER_WEB_URLS, False)
def alternative_player_web_urls(self, value=None): def alternative_player_web_urls(self, value=None):
if value is not None: if value is not None:
return self.set_bool(settings.ALTERNATIVE_PLAYER_WEB_URLS, value) return self.set_bool(SETTINGS.ALTERNATIVE_PLAYER_WEB_URLS, value)
if (self.support_alternative_player() if (self.support_alternative_player()
and not self.alternative_player_adaptive()): and not self.alternative_player_adaptive()):
return self.get_bool(settings.ALTERNATIVE_PLAYER_WEB_URLS, False) return self.get_bool(SETTINGS.ALTERNATIVE_PLAYER_WEB_URLS, False)
return False return False
def alternative_player_adaptive(self, value=None): def alternative_player_adaptive(self, value=None):
if value is not None: if value is not None:
return self.set_bool(settings.ALTERNATIVE_PLAYER_ADAPTIVE, value) return self.set_bool(SETTINGS.ALTERNATIVE_PLAYER_ADAPTIVE, value)
if self.support_alternative_player(): if self.support_alternative_player():
return self.get_bool(settings.ALTERNATIVE_PLAYER_ADAPTIVE, False) return self.get_bool(SETTINGS.ALTERNATIVE_PLAYER_ADAPTIVE, False)
return False return False
def use_isa(self, value=None): def use_isa(self, value=None):
if value is not None: if value is not None:
return self.set_bool(settings.USE_ISA, value) return self.set_bool(SETTINGS.USE_ISA, value)
return self.get_bool(settings.USE_ISA, False) return self.get_bool(SETTINGS.USE_ISA, False)
def subtitle_download(self): def subtitle_download(self):
return self.get_bool(settings.SUBTITLE_DOWNLOAD, False) return self.get_bool(SETTINGS.SUBTITLE_DOWNLOAD, False)
def audio_only(self): def audio_only(self):
return self.get_bool(settings.AUDIO_ONLY, False) return self.get_bool(SETTINGS.AUDIO_ONLY, False)
def get_subtitle_selection(self): def get_subtitle_selection(self):
return self.get_int(settings.SUBTITLE_SELECTION, 0) return self.get_int(SETTINGS.SUBTITLE_SELECTION, 0)
def set_subtitle_selection(self, value): def set_subtitle_selection(self, value):
return self.set_int(settings.SUBTITLE_SELECTION, value) return self.set_int(SETTINGS.SUBTITLE_SELECTION, value)
def set_subtitle_download(self, value): def set_subtitle_download(self, value):
return self.set_bool(settings.SUBTITLE_DOWNLOAD, value) return self.set_bool(SETTINGS.SUBTITLE_DOWNLOAD, value)
_THUMB_SIZES = { _THUMB_SIZES = {
0: { # Medium (16:9) 0: { # Medium (16:9)
@ -180,38 +180,38 @@ class AbstractSettings(object):
def get_thumbnail_size(self, value=None): def get_thumbnail_size(self, value=None):
default = 1 default = 1
if value is None: if value is None:
value = self.get_int(settings.THUMB_SIZE, default) value = self.get_int(SETTINGS.THUMB_SIZE, default)
if value in self._THUMB_SIZES: if value in self._THUMB_SIZES:
return self._THUMB_SIZES[value] return self._THUMB_SIZES[value]
return self._THUMB_SIZES[default] return self._THUMB_SIZES[default]
def safe_search(self): def safe_search(self):
index = self.get_int(settings.SAFE_SEARCH, 0) index = self.get_int(SETTINGS.SAFE_SEARCH, 0)
values = {0: 'moderate', 1: 'none', 2: 'strict'} values = {0: 'moderate', 1: 'none', 2: 'strict'}
return values[index] return values[index]
def age_gate(self): def age_gate(self):
return self.get_bool(settings.AGE_GATE, True) return self.get_bool(SETTINGS.AGE_GATE, True)
def verify_ssl(self): def verify_ssl(self):
verify = self.get_bool(settings.VERIFY_SSL, False) verify = self.get_bool(SETTINGS.VERIFY_SSL, False)
if sys.version_info <= (2, 7, 9): if sys.version_info <= (2, 7, 9):
verify = False verify = False
return verify return verify
def get_timeout(self): def get_timeout(self):
connect_timeout = self.get_int(settings.CONNECT_TIMEOUT, 9) + 0.5 connect_timeout = self.get_int(SETTINGS.CONNECT_TIMEOUT, 9) + 0.5
read_timout = self.get_int(settings.READ_TIMEOUT, 27) read_timout = self.get_int(SETTINGS.READ_TIMEOUT, 27)
return connect_timeout, read_timout return connect_timeout, read_timout
def allow_dev_keys(self): def allow_dev_keys(self):
return self.get_bool(settings.ALLOW_DEV_KEYS, False) return self.get_bool(SETTINGS.ALLOW_DEV_KEYS, False)
def use_mpd_videos(self, value=None): def use_mpd_videos(self, value=None):
if self.use_isa(): if self.use_isa():
if value is not None: if value is not None:
return self.set_bool(settings.MPD_VIDEOS, value) return self.set_bool(SETTINGS.MPD_VIDEOS, value)
return self.get_bool(settings.MPD_VIDEOS, True) return self.get_bool(SETTINGS.MPD_VIDEOS, True)
return False return False
_LIVE_STREAM_TYPES = { _LIVE_STREAM_TYPES = {
@ -224,10 +224,10 @@ class AbstractSettings(object):
def live_stream_type(self, value=None): def live_stream_type(self, value=None):
if self.use_isa(): if self.use_isa():
default = 2 default = 2
setting = settings.LIVE_STREAMS + '.1' setting = SETTINGS.LIVE_STREAMS + '.1'
else: else:
default = 0 default = 0
setting = settings.LIVE_STREAMS + '.2' setting = SETTINGS.LIVE_STREAMS + '.2'
if value is not None: if value is not None:
return self.set_int(setting, value) return self.set_int(setting, value)
value = self.get_int(setting, default) value = self.get_int(setting, default)
@ -237,19 +237,19 @@ class AbstractSettings(object):
def use_isa_live_streams(self): def use_isa_live_streams(self):
if self.use_isa(): if self.use_isa():
return self.get_int(settings.LIVE_STREAMS + '.1', 2) > 1 return self.get_int(SETTINGS.LIVE_STREAMS + '.1', 2) > 1
return False return False
def use_mpd_live_streams(self): def use_mpd_live_streams(self):
if self.use_isa(): if self.use_isa():
return self.get_int(settings.LIVE_STREAMS + '.1', 2) == 3 return self.get_int(SETTINGS.LIVE_STREAMS + '.1', 2) == 3
return False return False
def httpd_port(self, value=None): def httpd_port(self, value=None):
default = 50152 default = 50152
if value is None: if value is None:
port = self.get_int(settings.HTTPD_PORT, default) port = self.get_int(SETTINGS.HTTPD_PORT, default)
else: else:
port = value port = value
@ -259,14 +259,14 @@ class AbstractSettings(object):
port = default port = default
if value is not None: if value is not None:
return self.set_int(settings.HTTPD_PORT, port) return self.set_int(SETTINGS.HTTPD_PORT, port)
return port return port
def httpd_listen(self, value=None): def httpd_listen(self, value=None):
default = '0.0.0.0' default = '0.0.0.0'
if value is None: if value is None:
ip_address = self.get_string(settings.HTTPD_LISTEN, default) ip_address = self.get_string(SETTINGS.HTTPD_LISTEN, default)
else: else:
ip_address = value ip_address = value
@ -274,11 +274,11 @@ class AbstractSettings(object):
ip_address = '.'.join(map(str, octets)) ip_address = '.'.join(map(str, octets))
if value is not None: if value is not None:
return self.set_string(settings.HTTPD_LISTEN, ip_address) return self.set_string(SETTINGS.HTTPD_LISTEN, ip_address)
return ip_address return ip_address
def httpd_whitelist(self): def httpd_whitelist(self):
whitelist = self.get_string(settings.HTTPD_WHITELIST, '') whitelist = self.get_string(SETTINGS.HTTPD_WHITELIST, '')
whitelist = ''.join(whitelist.split()).split(',') whitelist = ''.join(whitelist.split()).split(',')
allow_list = [] allow_list = []
for ip_address in whitelist: for ip_address in whitelist:
@ -289,28 +289,28 @@ class AbstractSettings(object):
return allow_list return allow_list
def api_config_page(self): def api_config_page(self):
return self.get_bool(settings.API_CONFIG_PAGE, False) return self.get_bool(SETTINGS.API_CONFIG_PAGE, False)
def api_id(self, new_id=None): def api_id(self, new_id=None):
if new_id is not None: if new_id is not None:
self.set_string(settings.API_ID, new_id) self.set_string(SETTINGS.API_ID, new_id)
return new_id return new_id
return self.get_string(settings.API_ID) return self.get_string(SETTINGS.API_ID)
def api_key(self, new_key=None): def api_key(self, new_key=None):
if new_key is not None: if new_key is not None:
self.set_string(settings.API_KEY, new_key) self.set_string(SETTINGS.API_KEY, new_key)
return new_key return new_key
return self.get_string(settings.API_KEY) return self.get_string(SETTINGS.API_KEY)
def api_secret(self, new_secret=None): def api_secret(self, new_secret=None):
if new_secret is not None: if new_secret is not None:
self.set_string(settings.API_SECRET, new_secret) self.set_string(SETTINGS.API_SECRET, new_secret)
return new_secret return new_secret
return self.get_string(settings.API_SECRET) return self.get_string(SETTINGS.API_SECRET)
def get_location(self): def get_location(self):
location = self.get_string(settings.LOCATION, '').replace(' ', '').strip() location = self.get_string(SETTINGS.LOCATION, '').replace(' ', '').strip()
coords = location.split(',') coords = location.split(',')
latitude = longitude = None latitude = longitude = None
if len(coords) == 2: if len(coords) == 2:
@ -328,19 +328,19 @@ class AbstractSettings(object):
return '' return ''
def set_location(self, value): def set_location(self, value):
self.set_string(settings.LOCATION, value) self.set_string(SETTINGS.LOCATION, value)
def get_location_radius(self): def get_location_radius(self):
return ''.join((self.get_int(settings.LOCATION_RADIUS, 500, str), 'km')) return ''.join((self.get_int(SETTINGS.LOCATION_RADIUS, 500, str), 'km'))
def get_play_count_min_percent(self): def get_play_count_min_percent(self):
return self.get_int(settings.PLAY_COUNT_MIN_PERCENT, 0) return self.get_int(SETTINGS.PLAY_COUNT_MIN_PERCENT, 0)
def use_local_history(self): def use_local_history(self):
return self.get_bool(settings.USE_LOCAL_HISTORY, False) return self.get_bool(SETTINGS.USE_LOCAL_HISTORY, False)
def use_remote_history(self): def use_remote_history(self):
return self.get_bool(settings.USE_REMOTE_HISTORY, False) return self.get_bool(SETTINGS.USE_REMOTE_HISTORY, False)
# Selections based on max width and min height at common (utra-)wide aspect ratios # Selections based on max width and min height at common (utra-)wide aspect ratios
_QUALITY_SELECTIONS = { # Setting | Resolution _QUALITY_SELECTIONS = { # Setting | Resolution
@ -359,10 +359,10 @@ class AbstractSettings(object):
def mpd_video_qualities(self, value=None): def mpd_video_qualities(self, value=None):
if value is not None: if value is not None:
return self.set_int(settings.MPD_QUALITY_SELECTION, value) return self.set_int(SETTINGS.MPD_QUALITY_SELECTION, value)
if not self.use_mpd_videos(): if not self.use_mpd_videos():
return [] return []
value = self.get_int(settings.MPD_QUALITY_SELECTION, 4) value = self.get_int(SETTINGS.MPD_QUALITY_SELECTION, 4)
return [quality return [quality
for key, quality in sorted(self._QUALITY_SELECTIONS.items(), for key, quality in sorted(self._QUALITY_SELECTIONS.items(),
reverse=True) reverse=True)
@ -370,8 +370,8 @@ class AbstractSettings(object):
def stream_features(self, value=None): def stream_features(self, value=None):
if value is not None: if value is not None:
return self.set_string_list(settings.MPD_STREAM_FEATURES, value) return self.set_string_list(SETTINGS.MPD_STREAM_FEATURES, value)
return frozenset(self.get_string_list(settings.MPD_STREAM_FEATURES)) return frozenset(self.get_string_list(SETTINGS.MPD_STREAM_FEATURES))
_STREAM_SELECT = { _STREAM_SELECT = {
1: 'auto', 1: 'auto',
@ -382,9 +382,9 @@ class AbstractSettings(object):
def stream_select(self, value=None): def stream_select(self, value=None):
if value is not None: if value is not None:
return self.set_int(settings.MPD_STREAM_SELECT, value) return self.set_int(SETTINGS.MPD_STREAM_SELECT, value)
default = 3 default = 3
value = self.get_int(settings.MPD_STREAM_SELECT, default) value = self.get_int(SETTINGS.MPD_STREAM_SELECT, default)
if value in self._STREAM_SELECT: if value in self._STREAM_SELECT:
return self._STREAM_SELECT[value] return self._STREAM_SELECT[value]
return self._STREAM_SELECT[default] return self._STREAM_SELECT[default]
@ -400,7 +400,7 @@ class AbstractSettings(object):
} }
def item_filter(self, update=None): def item_filter(self, update=None):
types = dict.fromkeys(self.get_string_list(settings.HIDE_VIDEOS), False) types = dict.fromkeys(self.get_string_list(SETTINGS.HIDE_VIDEOS), False)
types = dict(self._DEFAULT_FILTER, **types) types = dict(self._DEFAULT_FILTER, **types)
if update: if update:
if 'live_folder' in update: if 'live_folder' in update:
@ -421,46 +421,46 @@ class AbstractSettings(object):
def client_selection(self, value=None): def client_selection(self, value=None):
if value is not None: if value is not None:
return self.set_int(settings.CLIENT_SELECTION, value) return self.set_int(SETTINGS.CLIENT_SELECTION, value)
return self.get_int(settings.CLIENT_SELECTION, 0) return self.get_int(SETTINGS.CLIENT_SELECTION, 0)
def show_detailed_description(self, value=None): def show_detailed_description(self, value=None):
if value is not None: if value is not None:
return self.set_bool(settings.DETAILED_DESCRIPTION, value) return self.set_bool(SETTINGS.DETAILED_DESCRIPTION, value)
return self.get_bool(settings.DETAILED_DESCRIPTION, True) return self.get_bool(SETTINGS.DETAILED_DESCRIPTION, True)
def show_detailed_labels(self, value=None): def show_detailed_labels(self, value=None):
if value is not None: if value is not None:
return self.set_bool(settings.DETAILED_LABELS, value) return self.set_bool(SETTINGS.DETAILED_LABELS, value)
return self.get_bool(settings.DETAILED_LABELS, True) return self.get_bool(SETTINGS.DETAILED_LABELS, True)
def get_language(self): def get_language(self):
return self.get_string(settings.LANGUAGE, 'en_US').replace('_', '-') return self.get_string(SETTINGS.LANGUAGE, 'en_US').replace('_', '-')
def set_language(self, language_id): def set_language(self, language_id):
return self.set_string(settings.LANGUAGE, language_id) return self.set_string(SETTINGS.LANGUAGE, language_id)
def get_region(self): def get_region(self):
return self.get_string(settings.REGION, 'US') return self.get_string(SETTINGS.REGION, 'US')
def set_region(self, region_id): def set_region(self, region_id):
return self.set_string(settings.REGION, region_id) return self.set_string(SETTINGS.REGION, region_id)
def get_watch_later_playlist(self): def get_watch_later_playlist(self):
return self.get_string(settings.WATCH_LATER_PLAYLIST, '').strip() return self.get_string(SETTINGS.WATCH_LATER_PLAYLIST, '').strip()
def set_watch_later_playlist(self, value): def set_watch_later_playlist(self, value):
return self.set_string(settings.WATCH_LATER_PLAYLIST, value) return self.set_string(SETTINGS.WATCH_LATER_PLAYLIST, value)
def get_history_playlist(self): def get_history_playlist(self):
return self.get_string(settings.HISTORY_PLAYLIST, '').strip() return self.get_string(SETTINGS.HISTORY_PLAYLIST, '').strip()
def set_history_playlist(self, value): def set_history_playlist(self, value):
return self.set_string(settings.HISTORY_PLAYLIST, value) return self.set_string(SETTINGS.HISTORY_PLAYLIST, value)
if current_system_version.compatible(20, 0): if current_system_version.compatible(20, 0):
def get_label_color(self, label_part): def get_label_color(self, label_part):
setting_name = '.'.join((settings.LABEL_COLOR, label_part)) setting_name = '.'.join((SETTINGS.LABEL_COLOR, label_part))
return self.get_string(setting_name, 'white') return self.get_string(setting_name, 'white')
else: else:
_COLOR_MAP = { _COLOR_MAP = {
@ -474,4 +474,4 @@ class AbstractSettings(object):
return self._COLOR_MAP.get(label_part, 'white') return self._COLOR_MAP.get(label_part, 'white')
def get_channel_name_aliases(self): def get_channel_name_aliases(self):
return frozenset(self.get_string_list(settings.CHANNEL_NAME_ALIASES)) return frozenset(self.get_string_list(SETTINGS.CHANNEL_NAME_ALIASES))

View file

@ -82,9 +82,11 @@ class Subtitles(object):
self.preferred_lang = ('en',) self.preferred_lang = ('en',)
ui = context.get_ui() ui = context.get_ui()
self.prompt_override = (ui.get_property(PLAY_PROMPT_SUBTITLES) if ui.get_property(PLAY_PROMPT_SUBTITLES):
== video_id) self.prompt_override = True
ui.clear_property(PLAY_PROMPT_SUBTITLES) ui.clear_property(PLAY_PROMPT_SUBTITLES)
else:
self.prompt_override = False
def load(self, captions, headers=None): def load(self, captions, headers=None):
if headers: if headers:

View file

@ -14,7 +14,7 @@ import re
import time import time
from math import log10 from math import log10
from ...kodion.constants import LICENSE_TOKEN, LICENSE_URL, content, paths from ...kodion.constants import CONTENT, LICENSE_TOKEN, LICENSE_URL, PATHS
from ...kodion.items import DirectoryItem, menu_items from ...kodion.items import DirectoryItem, menu_items
from ...kodion.utils import ( from ...kodion.utils import (
datetime_parser, datetime_parser,
@ -151,7 +151,7 @@ def update_channel_infos(provider, context, channel_id_dict,
path = context.get_path() path = context.get_path()
filter_list = None filter_list = None
if path.startswith(paths.SUBSCRIPTIONS): if path.startswith(PATHS.SUBSCRIPTIONS):
in_bookmarks_list = False in_bookmarks_list = False
in_subscription_list = True in_subscription_list = True
if settings.get_bool('youtube.folder.my_subscriptions_filtered.show', if settings.get_bool('youtube.folder.my_subscriptions_filtered.show',
@ -162,7 +162,7 @@ def update_channel_infos(provider, context, channel_id_dict,
filter_string = filter_string.replace(', ', ',') filter_string = filter_string.replace(', ', ',')
filter_list = filter_string.split(',') filter_list = filter_string.split(',')
filter_list = [x.lower() for x in filter_list] filter_list = [x.lower() for x in filter_list]
elif path.startswith(paths.BOOKMARKS): elif path.startswith(PATHS.BOOKMARKS):
in_bookmarks_list = True in_bookmarks_list = True
in_subscription_list = False in_subscription_list = False
else: else:
@ -256,10 +256,10 @@ def update_playlist_infos(provider, context, playlist_id_dict,
thumb_size = context.get_settings().get_thumbnail_size() thumb_size = context.get_settings().get_thumbnail_size()
# if the path directs to a playlist of our own, set channel id to 'mine' # if the path directs to a playlist of our own, set channel id to 'mine'
if path.startswith(paths.MY_PLAYLISTS): if path.startswith(PATHS.MY_PLAYLISTS):
in_bookmarks_list = False in_bookmarks_list = False
in_my_playlists = True in_my_playlists = True
elif path.startswith(paths.BOOKMARKS): elif path.startswith(PATHS.BOOKMARKS):
in_bookmarks_list = True in_bookmarks_list = True
in_my_playlists = False in_my_playlists = False
else: else:
@ -389,17 +389,17 @@ def update_video_infos(provider, context, video_id_dict,
path = context.get_path() path = context.get_path()
ui = context.get_ui() ui = context.get_ui()
if path.startswith(paths.MY_SUBSCRIPTIONS): if path.startswith(PATHS.MY_SUBSCRIPTIONS):
in_bookmarks_list = False in_bookmarks_list = False
in_my_subscriptions_list = True in_my_subscriptions_list = True
in_watched_later_list = False in_watched_later_list = False
playlist_match = False playlist_match = False
elif path.startswith(paths.WATCH_LATER): elif path.startswith(PATHS.WATCH_LATER):
in_bookmarks_list = False in_bookmarks_list = False
in_my_subscriptions_list = False in_my_subscriptions_list = False
in_watched_later_list = True in_watched_later_list = True
playlist_match = False playlist_match = False
elif path.startswith(paths.BOOKMARKS): elif path.startswith(PATHS.BOOKMARKS):
in_bookmarks_list = True in_bookmarks_list = True
in_my_subscriptions_list = False in_my_subscriptions_list = False
in_watched_later_list = False in_watched_later_list = False
@ -414,7 +414,7 @@ def update_video_infos(provider, context, video_id_dict,
video_item = video_id_dict[video_id] video_item = video_id_dict[video_id]
# set mediatype # set mediatype
video_item.set_mediatype(content.VIDEO_TYPE) video_item.set_mediatype(CONTENT.VIDEO_TYPE)
if not yt_item or 'snippet' not in yt_item: if not yt_item or 'snippet' not in yt_item:
continue continue
@ -768,7 +768,7 @@ def update_video_infos(provider, context, video_id_dict,
) )
# more... # more...
refresh = path.startswith((paths.LIKED_VIDEOS, paths.DISLIKED_VIDEOS)) refresh = path.startswith((PATHS.LIKED_VIDEOS, PATHS.DISLIKED_VIDEOS))
context_menu.append( context_menu.append(
menu_items.more_for_video( menu_items.more_for_video(
context, context,
@ -780,7 +780,7 @@ def update_video_infos(provider, context, video_id_dict,
# 'play with...' (external player) # 'play with...' (external player)
if alternate_player: if alternate_player:
context_menu.append(menu_items.play_with(context)) context_menu.append(menu_items.play_with(context, video_id))
if not subtitles_prompt: if not subtitles_prompt:
context_menu.append( context_menu.append(

View file

@ -23,7 +23,7 @@ from .utils import (
update_video_infos, update_video_infos,
) )
from ...kodion import KodionException from ...kodion import KodionException
from ...kodion.constants import paths from ...kodion.constants import PATHS
from ...kodion.items import CommandItem, DirectoryItem, NextPageItem, VideoItem from ...kodion.items import CommandItem, DirectoryItem, NextPageItem, VideoItem
@ -149,7 +149,7 @@ def _process_list_response(provider, context, json_data, item_filter):
elif kind == 'playlist': elif kind == 'playlist':
# set channel id to 'mine' if the path is for a playlist of our own # set channel id to 'mine' if the path is for a playlist of our own
if context.get_path().startswith(paths.MY_PLAYLISTS): if context.get_path().startswith(PATHS.MY_PLAYLISTS):
channel_id = 'mine' channel_id = 'mine'
else: else:
channel_id = snippet['channelId'] channel_id = snippet['channelId']

View file

@ -32,7 +32,7 @@ from ...kodion.compatibility import (
urlsplit, urlsplit,
xbmcvfs, xbmcvfs,
) )
from ...kodion.constants import TEMP_PATH, paths from ...kodion.constants import PATHS, TEMP_PATH
from ...kodion.network import get_connect_address 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_from_url
@ -1518,7 +1518,7 @@ class VideoInfo(YouTubeRequestClient):
'proxy': 'http://{address}:{port}{path}||R{{SSM}}|'.format( 'proxy': 'http://{address}:{port}{path}||R{{SSM}}|'.format(
address=address, address=address,
port=port, port=port,
path=paths.DRM, path=PATHS.DRM,
), ),
'token': self._access_token, 'token': self._access_token,
} }
@ -2247,7 +2247,7 @@ class VideoInfo(YouTubeRequestClient):
return 'http://{address}:{port}{path}{file}'.format( return 'http://{address}:{port}{path}{file}'.format(
address=address, address=address,
port=port, port=port,
path=paths.MPD, path=PATHS.MPD,
file=filename, file=filename,
), main_stream ), main_stream
return None, None return None, None

View file

@ -18,12 +18,12 @@ from ..helper import utils, v3
from ..youtube_exceptions import YouTubeException from ..youtube_exceptions import YouTubeException
from ...kodion.compatibility import urlencode, urlunsplit from ...kodion.compatibility import urlencode, urlunsplit
from ...kodion.constants import ( from ...kodion.constants import (
PLAY_FORCE_AUDIO, PATHS,
PLAY_PROMPT_QUALITY,
PLAYBACK_INIT, PLAYBACK_INIT,
PLAYER_DATA, PLAYER_DATA,
SWITCH_PLAYER_FLAG, PLAY_FORCE_AUDIO,
paths, PLAY_PROMPT_QUALITY,
PLAY_WITH,
) )
from ...kodion.items import VideoItem from ...kodion.items import VideoItem
from ...kodion.network import get_connect_address from ...kodion.network import get_connect_address
@ -45,7 +45,7 @@ def play_video(provider, context):
incognito = params.get('incognito', False) incognito = params.get('incognito', False)
screensaver = params.get('screensaver', False) screensaver = params.get('screensaver', False)
is_external = ui.get_property(SWITCH_PLAYER_FLAG) is_external = ui.get_property(PLAY_WITH)
if ((is_external and settings.alternative_player_web_urls()) if ((is_external and settings.alternative_player_web_urls())
or settings.default_player_web_urls()): or settings.default_player_web_urls()):
video_stream = { video_stream = {
@ -53,12 +53,12 @@ def play_video(provider, context):
} }
else: else:
ask_for_quality = None ask_for_quality = None
if not screensaver and ui.get_property(PLAY_PROMPT_QUALITY) == video_id: if not screensaver and ui.get_property(PLAY_PROMPT_QUALITY):
ask_for_quality = True ask_for_quality = True
ui.clear_property(PLAY_PROMPT_QUALITY) ui.clear_property(PLAY_PROMPT_QUALITY)
audio_only = None audio_only = None
if ui.get_property(PLAY_FORCE_AUDIO) == video_id: if ui.get_property(PLAY_FORCE_AUDIO):
ask_for_quality = False ask_for_quality = False
audio_only = True audio_only = True
ui.clear_property(PLAY_FORCE_AUDIO) ui.clear_property(PLAY_FORCE_AUDIO)
@ -110,7 +110,7 @@ def play_video(provider, context):
url = urlunsplit(( url = urlunsplit((
'http', 'http',
get_connect_address(context=context, as_netloc=True), get_connect_address(context=context, as_netloc=True),
paths.REDIRECT, PATHS.REDIRECT,
urlencode({'url': video_stream['url']}), urlencode({'url': video_stream['url']}),
'', '',
)) ))

View file

@ -12,14 +12,14 @@ from __future__ import absolute_import, division, unicode_literals
from . import UrlResolver, UrlToItemConverter, tv, utils, v3 from . import UrlResolver, UrlToItemConverter, tv, utils, v3
from ...kodion import KodionException from ...kodion import KodionException
from ...kodion.constants import content from ...kodion.constants import CONTENT
from ...kodion.items import DirectoryItem, UriItem from ...kodion.items import DirectoryItem, UriItem
from ...kodion.utils import strip_html_from_text from ...kodion.utils import strip_html_from_text
from ...kodion.utils.datetime_parser import yt_datetime_offset from ...kodion.utils.datetime_parser import yt_datetime_offset
def _process_related_videos(provider, context, client): def _process_related_videos(provider, context, client):
context.set_content(content.VIDEO_CONTENT) context.set_content(CONTENT.VIDEO_CONTENT)
function_cache = context.get_function_cache() function_cache = context.get_function_cache()
params = context.get_params() params = context.get_params()
@ -49,7 +49,7 @@ def _process_related_videos(provider, context, client):
def _process_parent_comments(provider, context, client): def _process_parent_comments(provider, context, client):
context.set_content(content.LIST_CONTENT) context.set_content(CONTENT.LIST_CONTENT)
video_id = context.get_param('video_id', '') video_id = context.get_param('video_id', '')
if not video_id: if not video_id:
@ -65,7 +65,7 @@ def _process_parent_comments(provider, context, client):
def _process_child_comments(provider, context, client): def _process_child_comments(provider, context, client):
context.set_content(content.LIST_CONTENT) context.set_content(CONTENT.LIST_CONTENT)
parent_id = context.get_param('parent_id', '') parent_id = context.get_param('parent_id', '')
if not parent_id: if not parent_id:
@ -81,7 +81,7 @@ def _process_child_comments(provider, context, client):
def _process_recommendations(provider, context, client): def _process_recommendations(provider, context, client):
context.set_content(content.VIDEO_CONTENT) context.set_content(CONTENT.VIDEO_CONTENT)
params = context.get_params() params = context.get_params()
function_cache = context.get_function_cache() function_cache = context.get_function_cache()
@ -100,7 +100,7 @@ def _process_recommendations(provider, context, client):
def _process_trending(provider, context, client): def _process_trending(provider, context, client):
context.set_content(content.VIDEO_CONTENT) context.set_content(CONTENT.VIDEO_CONTENT)
json_data = client.get_trending_videos( json_data = client.get_trending_videos(
page_token=context.get_param('page_token', '') page_token=context.get_param('page_token', '')
@ -112,7 +112,7 @@ def _process_trending(provider, context, client):
def _process_browse_channels(provider, context, client): def _process_browse_channels(provider, context, client):
context.set_content(content.LIST_CONTENT) context.set_content(CONTENT.LIST_CONTENT)
guide_id = context.get_param('guide_id', '') guide_id = context.get_param('guide_id', '')
if guide_id: if guide_id:
@ -129,7 +129,7 @@ def _process_browse_channels(provider, context, client):
def _process_disliked_videos(provider, context, client): def _process_disliked_videos(provider, context, client):
context.set_content(content.VIDEO_CONTENT) context.set_content(CONTENT.VIDEO_CONTENT)
json_data = client.get_disliked_videos( json_data = client.get_disliked_videos(
page_token=context.get_param('page_token', '') page_token=context.get_param('page_token', '')
@ -141,7 +141,7 @@ def _process_disliked_videos(provider, context, client):
def _process_live_events(provider, context, client, event_type='live'): def _process_live_events(provider, context, client, event_type='live'):
context.set_content(content.VIDEO_CONTENT) context.set_content(CONTENT.VIDEO_CONTENT)
# TODO: cache result # TODO: cache result
json_data = client.get_live_events( json_data = client.get_live_events(
@ -165,7 +165,7 @@ def _process_description_links(provider, context):
addon_id = params.get('addon_id', '') addon_id = params.get('addon_id', '')
def _extract_urls(video_id): def _extract_urls(video_id):
context.set_content(content.VIDEO_CONTENT) context.set_content(CONTENT.VIDEO_CONTENT)
url_resolver = UrlResolver(context) url_resolver = UrlResolver(context)
with context.get_ui().create_progress_dialog( with context.get_ui().create_progress_dialog(
@ -282,7 +282,7 @@ def _process_description_links(provider, context):
def _process_saved_playlists_tv(provider, context, client): def _process_saved_playlists_tv(provider, context, client):
context.set_content(content.LIST_CONTENT) context.set_content(CONTENT.LIST_CONTENT)
json_data = client.get_saved_playlists( json_data = client.get_saved_playlists(
page_token=context.get_param('next_page_token', 0), page_token=context.get_param('next_page_token', 0),
@ -295,7 +295,7 @@ def _process_saved_playlists_tv(provider, context, client):
def _process_new_uploaded_videos_tv(provider, context, client, filtered=False): def _process_new_uploaded_videos_tv(provider, context, client, filtered=False):
context.set_content(content.VIDEO_CONTENT) context.set_content(CONTENT.VIDEO_CONTENT)
function_cache = context.get_function_cache() function_cache = context.get_function_cache()

View file

@ -35,12 +35,13 @@ from ..kodion import AbstractProvider, RegisterProviderPath
from ..kodion.constants import ( from ..kodion.constants import (
ADDON_ID, ADDON_ID,
CHANNEL_ID, CHANNEL_ID,
CONTENT,
DEVELOPER_CONFIGS, DEVELOPER_CONFIGS,
PATHS,
PLAY_FORCE_AUDIO, PLAY_FORCE_AUDIO,
PLAY_PROMPT_QUALITY, PLAY_PROMPT_QUALITY,
PLAY_PROMPT_SUBTITLES, PLAY_PROMPT_SUBTITLES,
content, PLAY_WITH,
paths,
) )
from ..kodion.items import ( from ..kodion.items import (
BaseItem, BaseItem,
@ -330,7 +331,7 @@ class Provider(AbstractProvider):
@RegisterProviderPath('^(?:/channel/(?P<channel_id>[^/]+))?/playlist/(?P<playlist_id>[^/]+)/?$') @RegisterProviderPath('^(?:/channel/(?P<channel_id>[^/]+))?/playlist/(?P<playlist_id>[^/]+)/?$')
def _on_playlist(self, context, re_match): def _on_playlist(self, context, re_match):
context.set_content(content.VIDEO_CONTENT) context.set_content(CONTENT.VIDEO_CONTENT)
resource_manager = self.get_resource_manager(context) resource_manager = self.get_resource_manager(context)
batch_id = (re_match.group('playlist_id'), batch_id = (re_match.group('playlist_id'),
@ -350,7 +351,7 @@ class Provider(AbstractProvider):
@RegisterProviderPath('^/channel/(?P<channel_id>[^/]+)/playlists/?$') @RegisterProviderPath('^/channel/(?P<channel_id>[^/]+)/playlists/?$')
def _on_channel_playlists(self, context, re_match): def _on_channel_playlists(self, context, re_match):
context.set_content(content.LIST_CONTENT) context.set_content(CONTENT.LIST_CONTENT)
channel_id = re_match.group('channel_id') channel_id = re_match.group('channel_id')
@ -407,7 +408,7 @@ class Provider(AbstractProvider):
@RegisterProviderPath('^/channel/(?P<channel_id>[^/]+)/live/?$') @RegisterProviderPath('^/channel/(?P<channel_id>[^/]+)/live/?$')
def _on_channel_live(self, context, re_match): def _on_channel_live(self, context, re_match):
context.set_content(content.VIDEO_CONTENT) context.set_content(CONTENT.VIDEO_CONTENT)
result = [] result = []
channel_id = re_match.group('channel_id') channel_id = re_match.group('channel_id')
@ -471,7 +472,7 @@ class Provider(AbstractProvider):
if method == 'channel' and not channel_id: if method == 'channel' and not channel_id:
return False return False
context.set_content(content.VIDEO_CONTENT) context.set_content(CONTENT.VIDEO_CONTENT)
resource_manager = self.get_resource_manager(context) resource_manager = self.get_resource_manager(context)
@ -588,7 +589,7 @@ class Provider(AbstractProvider):
# noinspection PyUnusedLocal # noinspection PyUnusedLocal
@RegisterProviderPath('^/location/mine/?$') @RegisterProviderPath('^/location/mine/?$')
def _on_my_location(self, context, re_match): def _on_my_location(self, context, re_match):
context.set_content(content.LIST_CONTENT) context.set_content(CONTENT.LIST_CONTENT)
create_uri = context.create_uri create_uri = context.create_uri
localize = context.localize localize = context.localize
@ -641,11 +642,12 @@ class Provider(AbstractProvider):
return result return result
""" """
Plays a video. Plays a video, playlist, or channel live stream.
path for video: '/play/?video_id=XXXXXXX' Video: '/play/?video_id=XXXXXX'
path for playlist: '/play/?playlist_id=XXXXXXX&mode=[OPTION]' Playlist: '/play/?playlist_id=XXXXXX[&order=ORDER][&action=ACTION]'
OPTION: [normal(default)|reverse|shuffle] ORDER: [normal(default)|reverse|shuffle] optional playlist ordering
ACTION: [list|play|queue|None(default)] optional action to perform
Channel live streams: '/play/?channel_id=UCXXXXXX[&live=X] Channel live streams: '/play/?channel_id=UCXXXXXX[&live=X]
X: optional index of live stream to play if channel has multiple live X: optional index of live stream to play if channel has multiple live
@ -657,11 +659,11 @@ class Provider(AbstractProvider):
def on_play(self, context, re_match): def on_play(self, context, re_match):
ui = context.get_ui() ui = context.get_ui()
force_play = False
params = context.get_params() params = context.get_params()
param_keys = params.keys()
if ({'channel_id', 'playlist_id', 'playlist_ids', 'video_id'} if ({'channel_id', 'playlist_id', 'playlist_ids', 'video_id'}
.isdisjoint(params.keys())): .isdisjoint(param_keys)):
listitem_path = context.get_listitem_info('FileNameAndPath') listitem_path = context.get_listitem_info('FileNameAndPath')
if context.is_plugin_path(listitem_path, 'play'): if context.is_plugin_path(listitem_path, 'play'):
video_id = find_video_id(listitem_path) video_id = find_video_id(listitem_path)
@ -676,28 +678,18 @@ class Provider(AbstractProvider):
video_id = params.get('video_id') video_id = params.get('video_id')
playlist_id = params.get('playlist_id') playlist_id = params.get('playlist_id')
if ui.get_property(PLAY_PROMPT_SUBTITLES) != video_id: force_play = False
ui.clear_property(PLAY_PROMPT_SUBTITLES) for param in {PLAY_FORCE_AUDIO,
PLAY_PROMPT_QUALITY,
if ui.get_property(PLAY_FORCE_AUDIO) != video_id: PLAY_PROMPT_SUBTITLES,
ui.clear_property(PLAY_FORCE_AUDIO) PLAY_WITH}.intersection(param_keys):
del params[param]
if ui.get_property(PLAY_PROMPT_QUALITY) != video_id: ui.set_property(param)
ui.clear_property(PLAY_PROMPT_QUALITY) force_play = True
if video_id and not playlist_id: if video_id and not playlist_id:
if params.pop(PLAY_PROMPT_SUBTITLES, None): # This is required to trigger Kodi resume prompt, along with using
ui.set_property(PLAY_PROMPT_SUBTITLES, video_id) # RunPlugin. Prompt will not be used if using PlayMedia
force_play = True
if params.pop('audio_only', None):
ui.set_property(PLAY_FORCE_AUDIO, video_id)
force_play = True
if params.pop('ask_for_quality', None):
ui.set_property(PLAY_PROMPT_QUALITY, video_id)
force_play = True
if force_play: if force_play:
context.execute('Action(Play)') context.execute('Action(Play)')
return False return False
@ -735,7 +727,7 @@ class Provider(AbstractProvider):
subscriptions = yt_subscriptions.process(method, self, context) subscriptions = yt_subscriptions.process(method, self, context)
if method == 'list': if method == 'list':
context.set_content(content.LIST_CONTENT) context.set_content(CONTENT.LIST_CONTENT)
return subscriptions return subscriptions
@ -809,9 +801,9 @@ class Provider(AbstractProvider):
safe_search = context.get_settings().safe_search() safe_search = context.get_settings().safe_search()
if search_type == 'video': if search_type == 'video':
context.set_content(content.VIDEO_CONTENT) context.set_content(CONTENT.VIDEO_CONTENT)
else: else:
context.set_content(content.LIST_CONTENT) context.set_content(CONTENT.LIST_CONTENT)
if (page == 1 if (page == 1
and search_type == 'video' and search_type == 'video'
@ -1032,7 +1024,7 @@ class Provider(AbstractProvider):
playback_history = context.get_playback_history() playback_history = context.get_playback_history()
if action == 'list': if action == 'list':
context.set_content(content.VIDEO_CONTENT, sub_type='history') context.set_content(CONTENT.VIDEO_CONTENT, sub_type='history')
items = playback_history.get_items() items = playback_history.get_items()
if not items: if not items:
return True return True
@ -1118,7 +1110,7 @@ class Provider(AbstractProvider):
logged_in = self.is_logged_in() logged_in = self.is_logged_in()
# _.get_my_playlists() # _.get_my_playlists()
# context.set_content(content.LIST_CONTENT) # context.set_content(CONTENT.LIST_CONTENT)
result = [] result = []
@ -1247,7 +1239,7 @@ class Provider(AbstractProvider):
else: else:
watch_history_item = DirectoryItem( watch_history_item = DirectoryItem(
localize('watch_later'), localize('watch_later'),
create_uri((paths.WATCH_LATER, 'list')), create_uri((PATHS.WATCH_LATER, 'list')),
image='{media}/watch_later.png', image='{media}/watch_later.png',
) )
result.append(watch_history_item) result.append(watch_history_item)
@ -1297,7 +1289,7 @@ class Provider(AbstractProvider):
elif local_history: elif local_history:
watch_history_item = DirectoryItem( watch_history_item = DirectoryItem(
localize('history'), localize('history'),
create_uri((paths.HISTORY,), params={'action': 'list'}), create_uri((PATHS.HISTORY,), params={'action': 'list'}),
image='{media}/history.png', image='{media}/history.png',
) )
result.append(watch_history_item) result.append(watch_history_item)
@ -1334,7 +1326,7 @@ class Provider(AbstractProvider):
if settings.get_bool('youtube.folder.bookmarks.show', True): if settings.get_bool('youtube.folder.bookmarks.show', True):
bookmarks_item = DirectoryItem( bookmarks_item = DirectoryItem(
localize('bookmarks'), localize('bookmarks'),
create_uri((paths.BOOKMARKS, 'list')), create_uri((PATHS.BOOKMARKS, 'list')),
image='{media}/bookmarks.png', image='{media}/bookmarks.png',
) )
result.append(bookmarks_item) result.append(bookmarks_item)
@ -1422,7 +1414,7 @@ class Provider(AbstractProvider):
return False return False
if command == 'list': if command == 'list':
context.set_content(content.VIDEO_CONTENT) context.set_content(CONTENT.VIDEO_CONTENT)
bookmarks_list = context.get_bookmarks_list() bookmarks_list = context.get_bookmarks_list()
items = bookmarks_list.get_items() items = bookmarks_list.get_items()
if not items: if not items:
@ -1499,7 +1491,7 @@ class Provider(AbstractProvider):
return False return False
if command == 'list': if command == 'list':
context.set_content(content.VIDEO_CONTENT, sub_type='watch_later') context.set_content(CONTENT.VIDEO_CONTENT, sub_type='watch_later')
items = context.get_watch_later_list().get_items() items = context.get_watch_later_list().get_items()
if not items: if not items:
return True return True