from urllib import urlencode
from xbmcaddon import Addon
from uuid import uuid4
+from utils import get_user_agent_for_current_platform
from UniversalAnalytics import Tracker
try:
import cPickle as pickle
"""Invalidates the memory cache"""
xbmcgui.Window(xbmcgui.getCurrentWindowId()).setProperty('memcache', pickle.dumps({}))
- def has_cached_item (self, cache_id):
- """Checks if the requested item is in memory cache
-
- Parameters
- ----------
- cache_id : :obj:`str`
- ID of the cache entry
-
- Returns
- -------
- bool
- Item is cached
- """
- cached_items = pickle.loads(xbmcgui.Window(xbmcgui.getCurrentWindowId()).getProperty('memcache'))
- return cache_id in cached_items.keys()
-
def get_cached_item (self, cache_id):
"""Returns an item from the in memory cache
Contents of the requested cache item or none
"""
cached_items = pickle.loads(xbmcgui.Window(xbmcgui.getCurrentWindowId()).getProperty('memcache'))
- if self.has_cached_item(cache_id) != True:
- return None
- return cached_items[cache_id]
+
+ return cached_items.get(cache_id)
def add_cached_item (self, cache_id, contents):
"""Adds an item to the in memory cache
Parameters
----------
- profiles : :obj:`dict` of :obj:`str`
+ profiles : :obj:`list` of :obj:`dict` of :obj:`str`
List of user profiles
action : :obj:`str`
bool
List could be build
"""
- for profile_id in profiles:
- profile = profiles[profile_id]
- url = build_url({'action': action, 'profile_id': profile_id})
+ for profile in profiles:
+ url = build_url({'action': action, 'profile_id': profile['id']})
li = xbmcgui.ListItem(label=profile['profileName'], iconImage=profile['avatar'])
li.setProperty('fanart_image', self.default_fanart)
xbmcplugin.addDirectoryItem(handle=self.plugin_handle, url=url, listitem=li, isFolder=True)
Dictionary of actions to build subsequent routes
type : :obj:`str`
- None or 'queue' f.e. when it´s a special video lists
+ None or 'queue' f.e. when it´s a special video lists
build_url : :obj:`fn`
Function to build the subsequent routes
li = xbmcgui.ListItem(label=video['title'])
# add some art to the item
li = self._generate_art_info(entry=video, li=li)
- # it´s a show, so we need a subfolder & route (for seasons)
- isFolder = True
- url = build_url({'action': actions[video['type']], 'show_id': video_list_id})
+ # add list item info
+ li, infos = self._generate_entry_info(entry=video, li=li)
+ li = self._generate_context_menu_items(entry=video, li=li)
# lists can be mixed with shows & movies, therefor we need to check if its a movie, so play it right away
if video_list[video_list_id]['type'] == 'movie':
- # it´s a movie, so we need no subfolder & a route to play it
+ # it´s a movie, so we need no subfolder & a route to play it
isFolder = False
- url = build_url({'action': 'play_video', 'video_id': video_list_id})
- # add list item info
- li = self._generate_entry_info(entry=video, li=li)
- li = self._generate_context_menu_items(entry=video, li=li)
+ url = build_url({'action': 'play_video', 'video_id': video_list_id, 'infoLabels': infos})
+ else:
+ # it´s a show, so we need a subfolder & route (for seasons)
+ isFolder = True
+ params = {'action': actions[video['type']], 'show_id': video_list_id}
+ if 'tvshowtitle' in infos:
+ params['tvshowtitle'] = infos.get('tvshowtitle', '').encode('utf-8')
+ url = build_url(params)
xbmcplugin.addDirectoryItem(handle=self.plugin_handle, url=url, listitem=li, isFolder=isFolder)
xbmcplugin.addSortMethod(handle=self.plugin_handle, sortMethod=xbmcplugin.SORT_METHOD_LABEL)
xbmcplugin.endOfDirectory(self.plugin_handle)
return True
- def build_season_listing (self, seasons_sorted, season_list, build_url):
+ def build_season_listing (self, seasons_sorted, build_url):
"""Builds the season list screen for a show
Parameters
----------
- seasons_sorted : :obj:`list` of :obj:`str`
- Sorted season indexes
-
- season_list : :obj:`dict` of :obj:`str`
- List of season entries
+ seasons_sorted : :obj:`list` of :obj:`dict` of :obj:`str`
+ Sorted list of season entries
build_url : :obj:`fn`
Function to build the subsequent routes
bool
List could be build
"""
- for index in seasons_sorted:
- for season_id in season_list:
- season = season_list[season_id]
- if int(season['idx']) == index:
- li = xbmcgui.ListItem(label=season['text'])
- # add some art to the item
- li = self._generate_art_info(entry=season, li=li)
- # add list item info
- li = self._generate_entry_info(entry=season, li=li, base_info={'mediatype': 'season'})
- li = self._generate_context_menu_items(entry=season, li=li)
- url = build_url({'action': 'episode_list', 'season_id': season_id})
- xbmcplugin.addDirectoryItem(handle=self.plugin_handle, url=url, listitem=li, isFolder=True)
+ for season in seasons_sorted:
+ li = xbmcgui.ListItem(label=season['text'])
+ # add some art to the item
+ li = self._generate_art_info(entry=season, li=li)
+ # add list item info
+ li, infos = self._generate_entry_info(entry=season, li=li, base_info={'mediatype': 'season'})
+ li = self._generate_context_menu_items(entry=season, li=li)
+ params = {'action': 'episode_list', 'season_id': season['id']}
+ if 'tvshowtitle' in infos:
+ params['tvshowtitle'] = infos.get('tvshowtitle', '').encode('utf-8')
+ url = build_url(params)
+ xbmcplugin.addDirectoryItem(handle=self.plugin_handle, url=url, listitem=li, isFolder=True)
xbmcplugin.addSortMethod(handle=self.plugin_handle, sortMethod=xbmcplugin.SORT_METHOD_NONE)
xbmcplugin.addSortMethod(handle=self.plugin_handle, sortMethod=xbmcplugin.SORT_METHOD_VIDEO_YEAR)
xbmcplugin.endOfDirectory(self.plugin_handle)
return True
- def build_episode_listing (self, episodes_sorted, episode_list, build_url):
+ def build_episode_listing (self, episodes_sorted, build_url):
"""Builds the episode list screen for a season of a show
Parameters
----------
- episodes_sorted : :obj:`list` of :obj:`str`
- Sorted episode indexes
-
- episode_list : :obj:`dict` of :obj:`str`
- List of episode entries
+ episodes_sorted : :obj:`list` of :obj:`dict` of :obj:`str`
+ Sorted list of episode entries
build_url : :obj:`fn`
Function to build the subsequent routes
bool
List could be build
"""
- for index in episodes_sorted:
- for episode_id in episode_list:
- episode = episode_list[episode_id]
- if int(episode['episode']) == index:
- li = xbmcgui.ListItem(label=episode['title'])
- # add some art to the item
- li = self._generate_art_info(entry=episode, li=li)
- # add list item info
- li = self._generate_entry_info(entry=episode, li=li, base_info={'mediatype': 'episode'})
- li = self._generate_context_menu_items(entry=episode, li=li)
- url = build_url({'action': 'play_video', 'video_id': episode_id, 'start_offset': episode['bookmark']})
- xbmcplugin.addDirectoryItem(handle=self.plugin_handle, url=url, listitem=li, isFolder=False)
+ for episode in episodes_sorted:
+ li = xbmcgui.ListItem(label=episode['title'])
+ # add some art to the item
+ li = self._generate_art_info(entry=episode, li=li)
+ # add list item info
+ li, infos = self._generate_entry_info(entry=episode, li=li, base_info={'mediatype': 'episode'})
+ li = self._generate_context_menu_items(entry=episode, li=li)
+ url = build_url({'action': 'play_video', 'video_id': episode['id'], 'start_offset': episode['bookmark'], 'infoLabels': infos})
+ xbmcplugin.addDirectoryItem(handle=self.plugin_handle, url=url, listitem=li, isFolder=False)
xbmcplugin.addSortMethod(handle=self.plugin_handle, sortMethod=xbmcplugin.SORT_METHOD_EPISODE)
xbmcplugin.addSortMethod(handle=self.plugin_handle, sortMethod=xbmcplugin.SORT_METHOD_NONE)
xbmcplugin.endOfDirectory(self.plugin_handle)
return True
- def play_item (self, esn, video_id, start_offset=-1):
+ def play_item (self, esn, video_id, start_offset=-1, infoLabels={}):
"""Plays a video
Parameters
start_offset : :obj:`str`
Offset to resume playback from (in seconds)
+
+ infoLabels : :obj:`str`
+ the listitem's infoLabels
Returns
-------
# inputstream addon properties
msl_service_url = 'http://localhost:' + str(addon.getSetting('msl_service_port'))
play_item = xbmcgui.ListItem(path=msl_service_url + '/manifest?id=' + video_id)
+ play_item.setContentLookup(False)
+ play_item.setMimeType('application/dash+xml')
+ play_item.setProperty(inputstream_addon + '.stream_headers', 'user-agent=' + get_user_agent_for_current_platform())
play_item.setProperty(inputstream_addon + '.license_type', 'com.widevine.alpha')
play_item.setProperty(inputstream_addon + '.manifest_type', 'mpd')
play_item.setProperty(inputstream_addon + '.license_key', msl_service_url + '/license?id=' + video_id + '||b{SSM}!b{SID}|')
# check if we have a bookmark e.g. start offset position
if int(start_offset) > 0:
play_item.setProperty('StartOffset', str(start_offset) + '.0')
+ # set infoLabels
+ if len(infoLabels) > 0:
+ play_item.setInfo('video', infoLabels)
return xbmcplugin.setResolvedUrl(self.plugin_handle, True, listitem=play_item)
def _generate_art_info (self, entry, li):
if 'type' in entry_keys:
if entry['type'] == 'movie' or entry['type'] == 'episode':
li.setProperty('IsPlayable', 'true')
+ elif entry['type'] == 'show':
+ infos.update({'tvshowtitle': entry['title']})
if 'mediatype' in entry_keys:
if entry['mediatype'] == 'movie' or entry['mediatype'] == 'episode':
li.setProperty('IsPlayable', 'true')
if entry['quality'] == '1080':
quality = {'width': '1920', 'height': '1080'}
li.addStreamInfo('video', quality)
+ if 'tvshowtitle' in entry_keys:
+ infos.update({'tvshowtitle': entry.get('tvshowtitle', '').encode('utf-8')})
li.setInfo('video', infos)
- return li
+ return li, infos
def _generate_context_menu_items (self, entry, li):
"""Adds context menue items to a Kodi list item
addon.setSetting('tracking_id', tracking_id)
# Send the tracking event
tracker = Tracker.create('UA-46081640-5', client_id=tracking_id)
- tracker.send('event', event)
+ tracker.send('event', event)
\ No newline at end of file