Rewire Kodi ListItem stuff

This commit is contained in:
tomkat83 2017-03-19 12:14:16 +01:00
parent 264782c787
commit aa900c6b88
4 changed files with 101 additions and 110 deletions

View file

@ -14,18 +14,21 @@ def convert_PKC_to_listitem(PKC_listitem):
""" """
Insert a PKC_listitem and you will receive a valid XBMC listitem Insert a PKC_listitem and you will receive a valid XBMC listitem
""" """
listitem = ListItem() data = PKC_listitem.data
for func, args in PKC_listitem.data.items(): log.debug('data is: %s' % data)
if isinstance(args, list): listitem = ListItem(label=data.get('label'),
for arg in args: label2=data.get('label2'),
getattr(listitem, func)(*arg) path=data.get('path'))
elif isinstance(args, dict): if data['info']:
for arg in args.items(): listitem.setInfo(**data['info'])
getattr(listitem, func)(*arg) for stream in data['stream_info']:
elif args is None: listitem.addStreamInfo(**stream)
continue if data['art']:
else: listitem.setArt(data['art'])
getattr(listitem, func)(args) for key, value in data['property'].iteritems():
listitem.setProperty(key, value)
if data['subtitles']:
listitem.setSubtitles(data['subtitles'])
return listitem return listitem
@ -38,14 +41,14 @@ class PKC_ListItem(object):
""" """
def __init__(self, label=None, label2=None, path=None): def __init__(self, label=None, label2=None, path=None):
self.data = { self.data = {
'addStreamInfo': [], # (type, values: dict { label: value }) 'stream_info': [], # (type, values: dict { label: value })
'setArt': [], # dict: { label: value } 'art': {}, # dict
'setInfo': {}, # type: infoLabel (dict { label: value }) 'info': {}, # type: infoLabel (dict { label: value })
'setLabel': label, # string 'label': label, # string
'setLabel2': label2, # string 'label2': label2, # string
'setPath': path, # string 'path': path, # string
'setProperty': {}, # (key, value) 'property': {}, # (key, value)
'setSubtitles': [], # string 'subtitles': [], # strings
} }
def addContextMenuItems(self, items, replaceItems): def addContextMenuItems(self, items, replaceItems):
@ -87,19 +90,19 @@ class PKC_ListItem(object):
- Subtitle Values: - Subtitle Values:
- language : string (en) - language : string (en)
""" """
self.data['addStreamInfo'].append((type, values)) self.data['stream_info'].append({'type': type, 'values': values})
def getLabel(self): def getLabel(self):
""" """
Returns the listitem label Returns the listitem label
""" """
return self.data['setLabel'] return self.data.get('label')
def getLabel2(self): def getLabel2(self):
""" """
Returns the listitem label. Returns the listitem label.
""" """
return self.data['setLabel2'] return self.data.get('label2')
def getMusicInfoTag(self): def getMusicInfoTag(self):
""" """
@ -118,7 +121,7 @@ class PKC_ListItem(object):
Once you use a keyword, all following arguments require the keyword. Once you use a keyword, all following arguments require the keyword.
""" """
return self.data['setProperty'].get(key) return self.data['property'].get(key)
def getVideoInfoTag(self): def getVideoInfoTag(self):
""" """
@ -172,7 +175,7 @@ class PKC_ListItem(object):
- landscape : string - image filename - landscape : string - image filename
- icon : string - image filename - icon : string - image filename
""" """
self.data['setArt'].append(values) self.data['art'].update(values)
def setContentLookup(self, enable): def setContentLookup(self, enable):
""" """
@ -270,21 +273,21 @@ class PKC_ListItem(object):
- exif : string (See CPictureInfoTag::TranslateString in - exif : string (See CPictureInfoTag::TranslateString in
PictureInfoTag.cpp for valid strings) PictureInfoTag.cpp for valid strings)
""" """
self.data['setInfo'][type] = infoLabels self.data['info'] = {'type': type, 'infoLabels': infoLabels}
def setLabel(self, label): def setLabel(self, label):
""" """
Sets the listitem's label. Sets the listitem's label.
label : string or unicode - text string. label : string or unicode - text string.
""" """
self.data['setLabel'] = label self.data['label'] = label
def setLabel2(self, label): def setLabel2(self, label):
""" """
Sets the listitem's label2. Sets the listitem's label2.
label : string or unicode - text string. label : string or unicode - text string.
""" """
self.data['setLabel2'] = label self.data['label2'] = label
def setMimeType(self, mimetype): def setMimeType(self, mimetype):
""" """
@ -303,7 +306,7 @@ class PKC_ListItem(object):
*Note, You can use the above as keywords for arguments. *Note, You can use the above as keywords for arguments.
""" """
self.data['setPath'] = path self.data['path'] = path
def setProperty(self, key, value): def setProperty(self, key, value):
""" """
@ -321,7 +324,7 @@ class PKC_ListItem(object):
start playback of an item. Others may be used in the skin to add extra start playback of an item. Others may be used in the skin to add extra
information, such as 'WatchedCount' for tvshow items information, such as 'WatchedCount' for tvshow items
""" """
self.data['setProperty'][key] = value self.data['property'][key] = value
def setSubtitles(self, subtitles): def setSubtitles(self, subtitles):
""" """
@ -331,4 +334,4 @@ class PKC_ListItem(object):
- listitem.setSubtitles(['special://temp/example.srt', - listitem.setSubtitles(['special://temp/example.srt',
'http://example.com/example.srt' ]) 'http://example.com/example.srt' ])
""" """
self.data['setSubtitles'].extend(([subtitles],)) self.data['subtitles'].extend(subtitles)

View file

@ -1208,6 +1208,36 @@ class API():
ans = unquote(ans).decode('latin1') ans = unquote(ans).decode('latin1')
return ans return ans
def get_picture_path(self):
"""
Returns the item's picture path (transcode, if necessary) as string
"""
extension = self.item[0][0].attrib['key'][self.item[0][0].attrib['key'].rfind('.'):].lower()
if (window('plex_force_transcode_pix') == 'true' or
extension not in v.KODI_SUPPORTED_IMAGES):
# Let Plex transcode
# max width/height supported by plex image transcoder is 1920x1080
path = self.server + PlexAPI().getTranscodeImagePath(
self.item[0][0].attrib.get('key'),
window('pms_token'),
"%s%s" % (self.server, self.item[0][0].attrib.get('key')),
1920,
1080)
else:
# Don't transcode
if window('useDirectPaths') == 'true':
# Addon Mode. Just give the path of the file to Kodi
path = self.addPlexCredentialsToUrl(
'%s%s' % (window('pms_server'),
self.item[0][0].attrib['key']))
else:
# Native direct paths
path = self.validatePlayurl(
self.getFilePath(forceFirstMediaStream=True),
'photo')
path = tryEncode(path)
return path
def getTVShowPath(self): def getTVShowPath(self):
""" """
Returns the direct path to the TV show, e.g. '\\NAS\tv\series' Returns the direct path to the TV show, e.g. '\\NAS\tv\series'
@ -2275,18 +2305,6 @@ class API():
log.info('Found external subs: %s' % externalsubs) log.info('Found external subs: %s' % externalsubs)
return externalsubs return externalsubs
def CreateListItemFromPlexItem(self,
listItem=None,
appendShowTitle=False,
appendSxxExx=False):
if self.getType() == 'photo':
listItem = self._createPhotoListItem(listItem)
else:
listItem = self._createVideoListItem(listItem,
appendShowTitle,
appendSxxExx)
return listItem
def GetKodiPremierDate(self): def GetKodiPremierDate(self):
""" """
Takes Plex' originallyAvailableAt of the form "yyyy-mm-dd" and returns Takes Plex' originallyAvailableAt of the form "yyyy-mm-dd" and returns
@ -2301,7 +2319,24 @@ class API():
date = None date = None
return date return date
def _createPhotoListItem(self, listItem=None): def CreateListItemFromPlexItem(self,
listItem=None,
appendShowTitle=False,
appendSxxExx=False):
if self.getType() == v.PLEX_TYPE_PHOTO:
listItem = self.__createPhotoListItem(listItem)
# Only set the bare minimum of artwork
listItem.setArt({'icon': 'DefaultPicture.png',
'fanart': self.__getOneArtwork('thumb')})
else:
listItem = self.__createVideoListItem(listItem,
appendShowTitle,
appendSxxExx)
self.add_video_streams(listItem)
self.set_listitem_artwork(listItem)
return listItem
def __createPhotoListItem(self, listItem=None):
""" """
Use for photo items only Use for photo items only
""" """
@ -2310,63 +2345,21 @@ class API():
listItem = xbmcgui.ListItem(title) listItem = xbmcgui.ListItem(title)
else: else:
listItem.setLabel(title) listItem.setLabel(title)
listItem.setProperty('IsPlayable', 'true')
extension = self.item[0][0].attrib['key'][self.item[0][0].attrib['key'].rfind('.'):].lower()
if (window('plex_force_transcode_pix') == 'true' or
extension not in v.KODI_SUPPORTED_IMAGES):
# Let Plex transcode
# max width/height supported by plex image transcoder is 1920x1080
path = self.server + PlexAPI().getTranscodeImagePath(
self.item[0][0].attrib.get('key'),
window('pms_token'),
"%s%s" % (self.server, self.item[0][0].attrib.get('key')),
1920,
1080)
else:
# Don't transcode
if window('useDirectPaths') == 'true':
# Addon Mode. Just give the path of the file to Kodi
path = self.addPlexCredentialsToUrl(
'%s%s' % (window('pms_server'),
self.item[0][0].attrib['key']))
else:
# Native direct paths
path = self.validatePlayurl(
self.getFilePath(forceFirstMediaStream=True),
'photo')
path = tryEncode(path)
metadata = { metadata = {
'date': self.GetKodiPremierDate(), 'date': self.GetKodiPremierDate(),
'picturepath': path,
'size': long(self.item[0][0].attrib.get('size', 0)), 'size': long(self.item[0][0].attrib.get('size', 0)),
'exif:width': self.item[0].attrib.get('width', ''), 'exif:width': self.item[0].attrib.get('width', ''),
'exif:height': self.item[0].attrib.get('height', ''), 'exif:height': self.item[0].attrib.get('height', ''),
'title': title
} }
listItem.setInfo('pictures', infoLabels=metadata) listItem.setInfo(type='image', infoLabels=metadata)
try:
if int(metadata['exif:width']) > int(metadata['exif:height']):
# add image as fanart for use with skinhelper auto thumb/
# backgrund creation
listItem.setArt({'fanart': path})
except ValueError:
pass
# Stuff that we CANNOT set with listItem.setInfo
listItem.setProperty('path', path)
listItem.setProperty('plot', self.getPlot()) listItem.setProperty('plot', self.getPlot())
listItem.setProperty('plexid', self.getRatingKey()) listItem.setProperty('plexid', self.getRatingKey())
# We do NOT set these props
# listItem.setProperty('isPlayable', 'true')
# listItem.setProperty('isFolder', 'true')
# Further stuff
listItem.setArt({'icon': 'DefaultPicture.png'})
return listItem return listItem
def _createVideoListItem(self, def __createVideoListItem(self,
listItem=None, listItem=None,
appendShowTitle=False, appendShowTitle=False,
appendSxxExx=False): appendSxxExx=False):
""" """
Use for video items only Use for video items only
Call on a child level of PMS xml response (e.g. in a for loop) Call on a child level of PMS xml response (e.g. in a for loop)
@ -2383,7 +2376,8 @@ class API():
if listItem is None: if listItem is None:
listItem = xbmcgui.ListItem(title) listItem = xbmcgui.ListItem(title)
listItem.setProperty('IsPlayable', 'true') else:
listItem.setLabel(title)
# Video items, e.g. movies and episodes or clips # Video items, e.g. movies and episodes or clips
people = self.getPeople() people = self.getPeople()
@ -2410,8 +2404,7 @@ class API():
listItem.setProperty('resumetime', str(userdata['Resume'])) listItem.setProperty('resumetime', str(userdata['Resume']))
listItem.setProperty('totaltime', str(userdata['Runtime'])) listItem.setProperty('totaltime', str(userdata['Runtime']))
if typus == "episode": if typus == v.PLEX_TYPE_EPISODE:
# Only for tv shows
key, show, season, episode = self.getEpisodeDetails() key, show, season, episode = self.getEpisodeDetails()
season = -1 if season is None else int(season) season = -1 if season is None else int(season)
episode = -1 if episode is None else int(episode) episode = -1 if episode is None else int(episode)
@ -2426,7 +2419,9 @@ class API():
listItem.setArt({'icon': 'DefaultTVShows.png'}) listItem.setArt({'icon': 'DefaultTVShows.png'})
if appendShowTitle is True: if appendShowTitle is True:
title = "%s - %s " % (show, title) title = "%s - %s " % (show, title)
elif typus == "movie": if appendShowTitle or appendSxxExx:
listItem.setLabel(title)
elif typus == v.PLEX_TYPE_MOVIE:
listItem.setArt({'icon': 'DefaultMovies.png'}) listItem.setArt({'icon': 'DefaultMovies.png'})
else: else:
# E.g. clips, trailers, ... # E.g. clips, trailers, ...
@ -2442,11 +2437,10 @@ class API():
pass pass
# Expensive operation # Expensive operation
metadata['title'] = title metadata['title'] = title
listItem.setLabel(title)
listItem.setInfo('video', infoLabels=metadata) listItem.setInfo('video', infoLabels=metadata)
return listItem return listItem
def AddStreamInfo(self, listItem): def add_video_streams(self, listItem):
""" """
Add media stream information to xbmcgui.ListItem Add media stream information to xbmcgui.ListItem
""" """

View file

@ -624,8 +624,6 @@ def getOnDeck(viewid, mediatype, tagname, limit):
listitem = api.CreateListItemFromPlexItem( listitem = api.CreateListItemFromPlexItem(
appendShowTitle=appendShowTitle, appendShowTitle=appendShowTitle,
appendSxxExx=appendSxxExx) appendSxxExx=appendSxxExx)
api.AddStreamInfo(listitem)
api.set_listitem_artwork(listitem)
if directpaths: if directpaths:
url = api.getFilePath() url = api.getFilePath()
else: else:
@ -815,10 +813,10 @@ def browse_plex(key=None, plex_section_id=None):
albums = False albums = False
musicvideos = False musicvideos = False
for item in xml: for item in xml:
typus = item.attrib.get('type')
if item.tag == 'Directory': if item.tag == 'Directory':
__build_folder(item, plex_section_id=plex_section_id) __build_folder(item, plex_section_id=plex_section_id)
else: else:
typus = item.attrib.get('type')
__build_item(item) __build_item(item)
if typus == v.PLEX_TYPE_PHOTO: if typus == v.PLEX_TYPE_PHOTO:
photos = True photos = True
@ -905,11 +903,6 @@ def __build_folder(xml_element, plex_section_id=None):
def __build_item(xml_element): def __build_item(xml_element):
api = API(xml_element) api = API(xml_element)
listitem = api.CreateListItemFromPlexItem() listitem = api.CreateListItemFromPlexItem()
try:
api.AddStreamInfo(listitem)
except:
pass
api.set_listitem_artwork(listitem)
if (api.getKey().startswith('/system/services') or if (api.getKey().startswith('/system/services') or
api.getKey().startswith('http')): api.getKey().startswith('http')):
params = { params = {
@ -917,14 +910,17 @@ def __build_item(xml_element):
'key': xml_element.attrib.get('key'), 'key': xml_element.attrib.get('key'),
'view_offset': xml_element.attrib.get('viewOffset', '0'), 'view_offset': xml_element.attrib.get('viewOffset', '0'),
} }
url = "plugin://%s?%s" % (v.ADDON_ID, urlencode(params))
elif api.getType() == v.PLEX_TYPE_PHOTO:
url = api.get_picture_path()
else: else:
params = { params = {
'mode': 'play',
'filename': api.getKey(), 'filename': api.getKey(),
'id': api.getRatingKey(), 'id': api.getRatingKey(),
'dbid': listitem.getProperty('dbid'), 'dbid': listitem.getProperty('dbid')
'mode': "play"
} }
url = "plugin://%s?%s" % (v.ADDON_ID, urlencode(params)) url = "plugin://%s?%s" % (v.ADDON_ID, urlencode(params))
xbmcplugin.addDirectoryItem(handle=HANDLE, xbmcplugin.addDirectoryItem(handle=HANDLE,
url=url, url=url,
listitem=listitem) listitem=listitem)

View file

@ -55,8 +55,6 @@ class Playback_Starter(Thread):
result = Playback_Successful() result = Playback_Successful()
listitem = PKC_ListItem() listitem = PKC_ListItem()
listitem = api.CreateListItemFromPlexItem(listitem) listitem = api.CreateListItemFromPlexItem(listitem)
api.AddStreamInfo(listitem)
api.set_listitem_artwork(listitem)
result.listitem = listitem result.listitem = listitem
else: else:
# Video and Music # Video and Music