commit
94a86b43c1
4 changed files with 117 additions and 75 deletions
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
<addon id="plugin.video.plexkodiconnect" name="PlexKodiConnect" version="2.12.9" provider-name="croneter">
|
<addon id="plugin.video.plexkodiconnect" name="PlexKodiConnect" version="2.12.10" provider-name="croneter">
|
||||||
<requires>
|
<requires>
|
||||||
<import addon="xbmc.python" version="2.1.0"/>
|
<import addon="xbmc.python" version="2.1.0"/>
|
||||||
<import addon="script.module.requests" version="2.9.1" />
|
<import addon="script.module.requests" version="2.9.1" />
|
||||||
|
@ -83,7 +83,10 @@
|
||||||
<summary lang="lt_LT">Natūralioji „Plex“ integracija į „Kodi“</summary>
|
<summary lang="lt_LT">Natūralioji „Plex“ integracija į „Kodi“</summary>
|
||||||
<description lang="lt_LT">Prijunkite „Kodi“ prie „Plex Medija Serverio“. Šiame papildinyje daroma prielaida, kad valdote visus savo vaizdo įrašus naudodami „Plex“ (ir nė vieno su „Kodi“). Galite prarasti jau saugomus „Kodi“ vaizdo įrašų ir muzikos duomenų bazių duomenis (kadangi šis papildinys juos tiesiogiai pakeičia). Naudokite savo pačių rizika!</description>
|
<description lang="lt_LT">Prijunkite „Kodi“ prie „Plex Medija Serverio“. Šiame papildinyje daroma prielaida, kad valdote visus savo vaizdo įrašus naudodami „Plex“ (ir nė vieno su „Kodi“). Galite prarasti jau saugomus „Kodi“ vaizdo įrašų ir muzikos duomenų bazių duomenis (kadangi šis papildinys juos tiesiogiai pakeičia). Naudokite savo pačių rizika!</description>
|
||||||
<disclaimer lang="lt_LT">Naudokite savo pačių rizika</disclaimer>
|
<disclaimer lang="lt_LT">Naudokite savo pačių rizika</disclaimer>
|
||||||
<news>version 2.12.9:
|
<news>version 2.12.10:
|
||||||
|
- Fix pictures from Plex picture libraries not working/displaying
|
||||||
|
|
||||||
|
version 2.12.9:
|
||||||
- Fix Local variable 'user' referenced before assignement
|
- Fix Local variable 'user' referenced before assignement
|
||||||
|
|
||||||
version 2.12.8:
|
version 2.12.8:
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
version 2.12.10:
|
||||||
|
- Fix pictures from Plex picture libraries not working/displaying
|
||||||
|
|
||||||
version 2.12.9:
|
version 2.12.9:
|
||||||
- Fix Local variable 'user' referenced before assignement
|
- Fix Local variable 'user' referenced before assignement
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,25 @@ class Media(object):
|
||||||
answ['bitDepth'] = None
|
answ['bitDepth'] = None
|
||||||
return answ
|
return answ
|
||||||
|
|
||||||
|
def picture_codec(self):
|
||||||
|
"""
|
||||||
|
Returns the exif metadata of pictures. This does NOT seem to be used
|
||||||
|
reliably by Kodi skins! (e.g. not at all)
|
||||||
|
"""
|
||||||
|
return {
|
||||||
|
'exif:CameraMake': self.xml[0].get('make'), # e.g. 'Canon'
|
||||||
|
'exif:CameraModel': self.xml[0].get('model'), # e.g. 'Canon XYZ'
|
||||||
|
'exif:DateTime': self.xml.get('originallyAvailableAt', '').replace('-', ':') or None, # e.g. '2017-11-05'
|
||||||
|
'exif:Height': self.xml[0].get('height'), # e.g. '2160'
|
||||||
|
'exif:Width': self.xml[0].get('width'), # e.g. '3240'
|
||||||
|
'exif:Orientation': self.xml[0][self.part].get('orientation'), # e.g. '1'
|
||||||
|
'exif:FocalLength': self.xml[0].get('focalLength'), # TO BE VALIDATED
|
||||||
|
'exif:ExposureTime': self.xml[0].get('exposure'), # e.g. '1/1000'
|
||||||
|
'exif:ApertureFNumber': self.xml[0].get('aperture'), # e.g. 'f/5.0'
|
||||||
|
'exif:ISOequivalent': self.xml[0].get('iso'), # e.g. '1600'
|
||||||
|
# missing on Kodi side: lens, e.g. "EF50mm f/1.8 II"
|
||||||
|
}
|
||||||
|
|
||||||
def mediastreams(self):
|
def mediastreams(self):
|
||||||
"""
|
"""
|
||||||
Returns the media streams for metadata purposes
|
Returns the media streams for metadata purposes
|
||||||
|
|
|
@ -136,74 +136,84 @@ def _generate_content(api):
|
||||||
# other fields - let's use the PMS answer to be safe
|
# other fields - let's use the PMS answer to be safe
|
||||||
# See https://github.com/croneter/PlexKodiConnect/issues/1129
|
# See https://github.com/croneter/PlexKodiConnect/issues/1129
|
||||||
if not api.kodi_id or 'title' not in item:
|
if not api.kodi_id or 'title' not in item:
|
||||||
cast = [{
|
if api.plex_type == v.PLEX_TYPE_PHOTO:
|
||||||
'name': x[0],
|
item = {
|
||||||
'thumbnail': x[1],
|
'title': api.title(),
|
||||||
'role': x[2],
|
'label': api.title(),
|
||||||
'order': x[3],
|
'type': api.kodi_type,
|
||||||
} for x in api.people()['actor']]
|
'dateadded': api.date_created(), # e.g '2019-01-03 19:40:59'
|
||||||
item = {
|
'lastplayed': api.lastplayed(), # e.g. '2019-01-04 16:05:03'
|
||||||
'cast': cast,
|
'playcount': api.viewcount(),
|
||||||
'country': api.countries(),
|
}
|
||||||
'dateadded': api.date_created(), # e.g '2019-01-03 19:40:59'
|
item.update(api.picture_codec())
|
||||||
'director': api.directors(), # list of [str]
|
else:
|
||||||
'duration': api.runtime(),
|
cast = [{
|
||||||
'episode': api.index(),
|
'name': x[0],
|
||||||
# 'file': '', # e.g. 'videodb://tvshows/titles/20'
|
'thumbnail': x[1],
|
||||||
'genre': api.genres(),
|
'role': x[2],
|
||||||
# 'imdbnumber': '', # e.g.'341663'
|
'order': x[3],
|
||||||
'label': api.title(), # e.g. '1x05. Category 55 Emergency Doomsday Crisis'
|
} for x in api.people()['actor']]
|
||||||
'lastplayed': api.lastplayed(), # e.g. '2019-01-04 16:05:03'
|
item = {
|
||||||
'mpaa': api.content_rating(), # e.g. 'TV-MA'
|
'cast': cast,
|
||||||
'originaltitle': '', # e.g. 'Titans (2018)'
|
'country': api.countries(),
|
||||||
'playcount': api.viewcount(), # [int]
|
'dateadded': api.date_created(), # e.g '2019-01-03 19:40:59'
|
||||||
'plot': api.plot(), # [str]
|
'director': api.directors(), # list of [str]
|
||||||
'plotoutline': api.tagline(),
|
'duration': api.runtime(),
|
||||||
'premiered': api.premiere_date(), # '2018-10-12'
|
'episode': api.index(),
|
||||||
'rating': api.rating(), # [float]
|
# 'file': '', # e.g. 'videodb://tvshows/titles/20'
|
||||||
'season': api.season_number(),
|
'genre': api.genres(),
|
||||||
'sorttitle': api.sorttitle(), # 'Titans (2018)'
|
# 'imdbnumber': '', # e.g.'341663'
|
||||||
'studio': api.studios(),
|
'label': api.title(), # e.g. '1x05. Category 55 Emergency Doomsday Crisis'
|
||||||
'tag': [], # List of tags this item belongs to
|
'lastplayed': api.lastplayed(), # e.g. '2019-01-04 16:05:03'
|
||||||
'tagline': api.tagline(),
|
'mpaa': api.content_rating(), # e.g. 'TV-MA'
|
||||||
'thumbnail': '', # e.g. 'image://https%3a%2f%2fassets.tv'
|
'originaltitle': '', # e.g. 'Titans (2018)'
|
||||||
'title': api.title(), # 'Titans (2018)'
|
'playcount': api.viewcount(), # [int]
|
||||||
'type': api.kodi_type,
|
'plot': api.plot(), # [str]
|
||||||
'trailer': api.trailer(),
|
'plotoutline': api.tagline(),
|
||||||
'tvshowtitle': api.show_title(),
|
'premiered': api.premiere_date(), # '2018-10-12'
|
||||||
'uniqueid': {
|
'rating': api.rating(), # [float]
|
||||||
'imdbnumber': api.guids.get('imdb') or '',
|
'season': api.season_number(),
|
||||||
'tvdb_id': api.guids.get('tvdb') or '',
|
'sorttitle': api.sorttitle(), # 'Titans (2018)'
|
||||||
'tmdb_id': api.guids.get('tmdb') or ''
|
'studio': api.studios(),
|
||||||
},
|
'tag': [], # List of tags this item belongs to
|
||||||
'votes': '0', # [str]!
|
'tagline': api.tagline(),
|
||||||
'writer': api.writers(), # list of [str]
|
'thumbnail': '', # e.g. 'image://https%3a%2f%2fassets.tv'
|
||||||
'year': api.year(), # [int]
|
'title': api.title(), # 'Titans (2018)'
|
||||||
}
|
'type': api.kodi_type,
|
||||||
|
'trailer': api.trailer(),
|
||||||
if plex_type in (v.PLEX_TYPE_EPISODE, v.PLEX_TYPE_SEASON, v.PLEX_TYPE_SHOW):
|
'tvshowtitle': api.show_title(),
|
||||||
leaves = api.leave_count()
|
'uniqueid': {
|
||||||
if leaves:
|
'imdbnumber': api.guids.get('imdb') or '',
|
||||||
item['extraproperties'] = leaves
|
'tvdb_id': api.guids.get('tvdb') or '',
|
||||||
|
'tmdb_id': api.guids.get('tmdb') or ''
|
||||||
|
},
|
||||||
|
'votes': '0', # [str]!
|
||||||
|
'writer': api.writers(), # list of [str]
|
||||||
|
'year': api.year(), # [int]
|
||||||
|
}
|
||||||
|
# Add all info for e.g. video and audio streams
|
||||||
|
item['streamdetails'] = api.mediastreams()
|
||||||
|
# Cleanup required due to the way metadatautils works
|
||||||
|
if not item['lastplayed']:
|
||||||
|
del item['lastplayed']
|
||||||
|
for stream in item['streamdetails']['video']:
|
||||||
|
stream['height'] = utils.cast(int, stream['height'])
|
||||||
|
stream['width'] = utils.cast(int, stream['width'])
|
||||||
|
stream['aspect'] = utils.cast(float, stream['aspect'])
|
||||||
|
item['streamdetails']['subtitle'] = [{'language': x} for x in item['streamdetails']['subtitle']]
|
||||||
|
# Resume point
|
||||||
|
resume = api.resume_point()
|
||||||
|
if resume:
|
||||||
|
item['resume'] = {
|
||||||
|
'position': resume,
|
||||||
|
'total': api.runtime()
|
||||||
|
}
|
||||||
|
if plex_type in (v.PLEX_TYPE_EPISODE, v.PLEX_TYPE_SEASON, v.PLEX_TYPE_SHOW):
|
||||||
|
leaves = api.leave_count()
|
||||||
|
if leaves:
|
||||||
|
item['extraproperties'] = leaves
|
||||||
# Add all the artwork we can
|
# Add all the artwork we can
|
||||||
item['art'] = api.artwork(full_artwork=True)
|
item['art'] = api.artwork(full_artwork=True)
|
||||||
# Add all info for e.g. video and audio streams
|
|
||||||
item['streamdetails'] = api.mediastreams()
|
|
||||||
# Cleanup required due to the way metadatautils works
|
|
||||||
if not item['lastplayed']:
|
|
||||||
del item['lastplayed']
|
|
||||||
for stream in item['streamdetails']['video']:
|
|
||||||
stream['height'] = utils.cast(int, stream['height'])
|
|
||||||
stream['width'] = utils.cast(int, stream['width'])
|
|
||||||
stream['aspect'] = utils.cast(float, stream['aspect'])
|
|
||||||
item['streamdetails']['subtitle'] = [{'language': x} for x in item['streamdetails']['subtitle']]
|
|
||||||
# Resume point
|
|
||||||
resume = api.resume_point()
|
|
||||||
if resume:
|
|
||||||
item['resume'] = {
|
|
||||||
'position': resume,
|
|
||||||
'total': api.runtime()
|
|
||||||
}
|
|
||||||
|
|
||||||
item['icon'] = v.ICON_FROM_PLEXTYPE[plex_type]
|
item['icon'] = v.ICON_FROM_PLEXTYPE[plex_type]
|
||||||
# Some customization
|
# Some customization
|
||||||
|
@ -472,16 +482,18 @@ def create_listitem(item, as_tuple=True, offscreen=True,
|
||||||
elif "plugin://script.skin.helper" not in item['file']:
|
elif "plugin://script.skin.helper" not in item['file']:
|
||||||
liz.setProperty('IsPlayable', 'true')
|
liz.setProperty('IsPlayable', 'true')
|
||||||
|
|
||||||
nodetype = "Video"
|
|
||||||
if item["type"] in ["song", "album", "artist"]:
|
if item["type"] in ["song", "album", "artist"]:
|
||||||
nodetype = "Music"
|
nodetype = "music"
|
||||||
|
elif item['type'] == 'photo':
|
||||||
|
nodetype = 'pictures'
|
||||||
|
else:
|
||||||
|
nodetype = 'video'
|
||||||
|
|
||||||
# extra properties
|
# extra properties
|
||||||
for key, value in item["extraproperties"].iteritems():
|
for key, value in item["extraproperties"].iteritems():
|
||||||
liz.setProperty(key, value)
|
liz.setProperty(key, value)
|
||||||
|
|
||||||
# video infolabels
|
if nodetype == 'video':
|
||||||
if nodetype == "Video":
|
|
||||||
infolabels = {
|
infolabels = {
|
||||||
"title": item.get("title"),
|
"title": item.get("title"),
|
||||||
"size": item.get("size"),
|
"size": item.get("size"),
|
||||||
|
@ -532,8 +544,7 @@ def create_listitem(item, as_tuple=True, offscreen=True,
|
||||||
if "date" in item:
|
if "date" in item:
|
||||||
infolabels["date"] = item["date"]
|
infolabels["date"] = item["date"]
|
||||||
|
|
||||||
# music infolabels
|
elif nodetype == 'music':
|
||||||
else:
|
|
||||||
infolabels = {
|
infolabels = {
|
||||||
"title": item.get("title"),
|
"title": item.get("title"),
|
||||||
"size": item.get("size"),
|
"size": item.get("size"),
|
||||||
|
@ -553,12 +564,18 @@ def create_listitem(item, as_tuple=True, offscreen=True,
|
||||||
if "lastplayed" in item:
|
if "lastplayed" in item:
|
||||||
infolabels["lastplayed"] = item["lastplayed"]
|
infolabels["lastplayed"] = item["lastplayed"]
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Pictures
|
||||||
|
infolabels = {
|
||||||
|
"title": item.get("title"),
|
||||||
|
'picturepath': item['file']
|
||||||
|
}
|
||||||
# setting the dbtype and dbid is supported from kodi krypton and up
|
# setting the dbtype and dbid is supported from kodi krypton and up
|
||||||
# PKC hack: ignore empty type
|
# PKC hack: ignore empty type
|
||||||
if item["type"] not in ["recording", "channel", "favourite", ""]:
|
if item["type"] not in ["recording", "channel", "favourite", ""]:
|
||||||
infolabels["mediatype"] = item["type"]
|
infolabels["mediatype"] = item["type"]
|
||||||
# setting the dbid on music items is not supported ?
|
# setting the dbid on music items is not supported ?
|
||||||
if nodetype == "Video" and "DBID" in item["extraproperties"]:
|
if nodetype == "video" and "DBID" in item["extraproperties"]:
|
||||||
infolabels["dbid"] = item["extraproperties"]["DBID"]
|
infolabels["dbid"] = item["extraproperties"]["DBID"]
|
||||||
|
|
||||||
if "lastplayed" in item:
|
if "lastplayed" in item:
|
||||||
|
|
Loading…
Reference in a new issue