Support for Plex collection artwork (PKC settings toggle under Artwork )

- Fixes #408
This commit is contained in:
Croneter 2018-07-05 12:46:40 +02:00
parent 70ffc7b826
commit e62b909a75
7 changed files with 102 additions and 24 deletions

View file

@ -574,6 +574,11 @@ msgctxt "#30542"
msgid "Always pick best quality for trailers" msgid "Always pick best quality for trailers"
msgstr "" msgstr ""
# PKC Settings - Artwork
msgctxt "#30543"
msgid "Prefer Kodi artwork for collections/sets"
msgstr ""
msgctxt "#30544" msgctxt "#30544"
msgid "Artwork" msgid "Artwork"
msgstr "" msgstr ""

View file

@ -114,14 +114,23 @@ class Items(object):
self.kodicursor) self.kodicursor)
# Also get artwork for collections/movie sets # Also get artwork for collections/movie sets
if kodi_type == v.KODI_TYPE_MOVIE: if kodi_type == v.KODI_TYPE_MOVIE:
for setname in api.collection_list(): for _, setname in api.collection_list():
LOG.debug('Getting artwork for movie set %s', setname) LOG.debug('Getting artwork for movie set %s', setname)
setid = self.kodi_db.create_collection(setname) setid = self.kodi_db.create_collection(setname)
self.artwork.modify_artwork(api.set_artwork(), external_set_artwork = api.set_artwork()
if (external_set_artwork and
utils.settings('PreferKodiCollectionArt') == 'false'):
# Need to make sure we are not overwriting existing Plex
# collection artwork
plex_artwork = api.artwork(kodi_id=setid,
kodi_type=v.KODI_TYPE_SET)
for art in plex_artwork:
if art in external_set_artwork:
del external_set_artwork[art]
self.artwork.modify_artwork(external_set_artwork,
setid, setid,
v.KODI_TYPE_SET, v.KODI_TYPE_SET,
self.kodicursor) self.kodicursor)
self.kodi_db.assign_collection(setid, kodi_id)
return True return True
def updateUserdata(self, xml): def updateUserdata(self, xml):
@ -440,14 +449,32 @@ class Movies(Items):
self.kodi_db.modify_streams(fileid, api.mediastreams(), runtime) self.kodi_db.modify_streams(fileid, api.mediastreams(), runtime)
# Process studios # Process studios
self.kodi_db.modify_studios(movieid, v.KODI_TYPE_MOVIE, studios) self.kodi_db.modify_studios(movieid, v.KODI_TYPE_MOVIE, studios)
# Process tags: view, Plex collection tags
tags = [viewtag] tags = [viewtag]
tags.extend(collections)
if userdata['Favorite']: if userdata['Favorite']:
tags.append("Favorite movies") tags.append("Favorite movies")
if collections:
collections_match = api.collections_match()
for plex_set_id, set_name in collections:
tags.append(set_name)
# Add any sets from Plex collection tags
kodi_set_id = self.kodi_db.create_collection(set_name)
self.kodi_db.assign_collection(kodi_set_id, movieid)
for index, plex_id in collections_match:
# Get Plex artwork for collections - a pain
if index == plex_set_id:
set_xml = PF.GetPlexMetadata(plex_id)
try:
set_xml.attrib
except AttributeError:
LOG.error('Could not get set metadata %s', plex_id)
continue
set_api = API(set_xml[0])
artwork.modify_artwork(set_api.artwork(),
kodi_set_id,
v.KODI_TYPE_SET,
kodicursor)
break
self.kodi_db.modify_tags(movieid, v.KODI_TYPE_MOVIE, tags) self.kodi_db.modify_tags(movieid, v.KODI_TYPE_MOVIE, tags)
# Add any sets from Plex collection tags
self.kodi_db.add_sets(movieid, collections)
# Process playstates # Process playstates
self.kodi_db.set_resume(fileid, self.kodi_db.set_resume(fileid,
resume, resume,
@ -718,7 +745,7 @@ class TVShows(Items):
self.kodi_db.modify_studios(showid, v.KODI_TYPE_SHOW, studios) self.kodi_db.modify_studios(showid, v.KODI_TYPE_SHOW, studios)
# Process tags: view, PMS collection tags # Process tags: view, PMS collection tags
tags = [viewtag] tags = [viewtag]
tags.extend(collections) tags.extend([i for _, i in collections])
self.kodi_db.modify_tags(showid, v.KODI_TYPE_SHOW, tags) self.kodi_db.modify_tags(showid, v.KODI_TYPE_SHOW, tags)
@utils.catch_exceptions(warnuser=True) @utils.catch_exceptions(warnuser=True)

View file

@ -813,14 +813,6 @@ class KodiDBMethods(object):
''' '''
self.cursor.execute(query, (kodiid, mediatype, oldtag,)) self.cursor.execute(query, (kodiid, mediatype, oldtag,))
def add_sets(self, movieid, collections):
"""
Will add the movie to all collections (a list of unicodes)
"""
for setname in collections:
setid = self.create_collection(setname)
self.assign_collection(setid, movieid)
def create_collection(self, set_name): def create_collection(self, set_name):
""" """
Returns the collection/set id for set_name [unicode] Returns the collection/set id for set_name [unicode]

View file

@ -31,7 +31,8 @@ http://stackoverflow.com/questions/111945/is-there-any-way-to-do-http-put-in-pyt
""" """
from logging import getLogger from logging import getLogger
from re import sub from re import sub
from urllib import urlencode, unquote from urllib import urlencode, unquote, quote
from urlparse import parse_qsl
from xbmcgui import ListItem from xbmcgui import ListItem
from .downloadutils import DownloadUtils as DU from .downloadutils import DownloadUtils as DU
@ -326,13 +327,13 @@ class API(object):
def collection_list(self): def collection_list(self):
""" """
Returns a list of PMS collection tags or an empty list Returns a list of tuples of the collection id and tags or an empty list
[(<collection id 1>, <collection name 1>), ...]
""" """
collections = [] collections = []
for child in self.item: for child in self.item:
if child.tag == 'Collection': if child.tag == 'Collection':
if child.attrib['tag']: collections.append((child.get('id'), child.get('tag')))
collections.append(child.attrib['tag'])
return collections return collections
def people(self): def people(self):
@ -816,9 +817,22 @@ class API(object):
def _one_artwork(self, art_kind): def _one_artwork(self, art_kind):
artwork = self.item.get(art_kind) artwork = self.item.get(art_kind)
if artwork and not artwork.startswith('http'): if artwork and not artwork.startswith('http'):
artwork = self.attach_plex_token_to_url( if '/composite/' in artwork:
'%s/photo/:/transcode?width=4000&height=4000&' # e.g. Plex collections where artwork already contains width
'minSize=1&upscale=0&url=%s' % (self.server, artwork)) # and height. Need to upscale for better resolution
artwork, args = artwork.split('?')
args = dict(parse_qsl(args))
width = int(args.get('width', 400))
height = int(args.get('height', 400))
# Adjust to 4k resolution 3,840x2,160
scaling = 3840.0 / float(max(width, height))
width = int(scaling * width)
height = int(scaling * height)
artwork = '%s?width=%s&height=%s' % (artwork, width, height)
artwork = ('%s/photo/:/transcode?width=3840&height=3840&'
'minSize=1&upscale=0&url=%s'
% (self.server, quote(artwork)))
artwork = self.attach_plex_token_to_url(artwork)
return artwork return artwork
def artwork(self, kodi_id=None, kodi_type=None, full_artwork=False): def artwork(self, kodi_id=None, kodi_type=None, full_artwork=False):
@ -1189,6 +1203,25 @@ class API(object):
break break
return artworks return artworks
def library_section_id(self):
"""
Returns the id of the Plex library section (for e.g. a movies section)
or None
"""
return self.item.get('librarySectionID')
def collections_match(self):
"""
Downloads one additional xml from the PMS in order to return a list of
tuples [(collection_id, plex_id), ...] for all collections of the
current item's Plex library sectin
Pass in the collection id of e.g. the movie's metadata
"""
xml = PF.collections(self.library_section_id())
if not xml:
return []
return [(i.get('index'), i.get('ratingKey')) for i in xml]
def set_artwork(self): def set_artwork(self):
""" """
Gets the URLs to the Plex artwork, or empty string if not found. Gets the URLs to the Plex artwork, or empty string if not found.

View file

@ -735,6 +735,24 @@ def GetPMSStatus(token):
return answer return answer
def collections(section_id):
"""
Returns an etree with list of collections or None.
"""
url = '{server}/library/sections/%s/all' % section_id
params = {
'type': 18, # Collections
'includeCollections': 1,
}
xml = DU().downloadUrl(url, parameters=params)
try:
xml.attrib
except AttributeError:
LOG.error("Error retrieving collections for %s", url)
xml = None
return xml
def scrobble(ratingKey, state): def scrobble(ratingKey, state):
""" """
Tells the PMS to set an item's watched state to state="watched" or Tells the PMS to set an item's watched state to state="watched" or

View file

@ -143,6 +143,7 @@ PLEX_PLAYLIST_TYPE_FROM_KODI = {
PLEX_TYPE_VIDEO = 'video' PLEX_TYPE_VIDEO = 'video'
PLEX_TYPE_MOVIE = 'movie' PLEX_TYPE_MOVIE = 'movie'
PLEX_TYPE_CLIP = 'clip' # e.g. trailers PLEX_TYPE_CLIP = 'clip' # e.g. trailers
PLEX_TYPE_SET = 'collection' # sets/collections
PLEX_TYPE_EPISODE = 'episode' PLEX_TYPE_EPISODE = 'episode'
PLEX_TYPE_SEASON = 'season' PLEX_TYPE_SEASON = 'season'
@ -257,6 +258,7 @@ KODITYPE_FROM_PLEXTYPE = {
PLEX_TYPE_FROM_KODI_TYPE = { PLEX_TYPE_FROM_KODI_TYPE = {
KODI_TYPE_VIDEO: PLEX_TYPE_VIDEO, KODI_TYPE_VIDEO: PLEX_TYPE_VIDEO,
KODI_TYPE_MOVIE: PLEX_TYPE_MOVIE, KODI_TYPE_MOVIE: PLEX_TYPE_MOVIE,
KODI_TYPE_SET: PLEX_TYPE_SET,
KODI_TYPE_EPISODE: PLEX_TYPE_EPISODE, KODI_TYPE_EPISODE: PLEX_TYPE_EPISODE,
KODI_TYPE_SEASON: PLEX_TYPE_SEASON, KODI_TYPE_SEASON: PLEX_TYPE_SEASON,
KODI_TYPE_SHOW: PLEX_TYPE_SHOW, KODI_TYPE_SHOW: PLEX_TYPE_SHOW,

View file

@ -132,7 +132,8 @@
<category label="30544"><!-- artwork --> <category label="30544"><!-- artwork -->
<setting id="enableTextureCache" label="30512" type="bool" default="true" /> <!-- Cache all artwork for a smooth Kodi experience --> <setting id="enableTextureCache" label="30512" type="bool" default="true" /> <!-- Cache all artwork for a smooth Kodi experience -->
<setting id="FanartTV" label="30539" type="bool" default="false" /><!-- Download additional art from FanArtTV --> <setting id="FanartTV" label="30539" type="bool" default="false" /><!-- Download additional art from FanArtTV -->
<setting label="39222" type="action" action="RunPlugin(plugin://plugin.video.plexkodiconnect/?mode=fanart)" option="close" visible="eq(-1,true)" subsetting="true" /> <!-- Look for missing fanart on FanartTV now --> <setting id="PreferKodiCollectionArt" label="30543" type="bool" default="true" visible="eq(-1,true)" subsetting="true"/><!-- Prefer Kodi artwork for collections -->
<setting label="39222" type="action" action="RunPlugin(plugin://plugin.video.plexkodiconnect/?mode=fanart)" option="close" visible="eq(-2,true)" subsetting="true" /> <!-- Look for missing fanart on FanartTV now -->
<setting id="imageSyncNotifications" label="30008" type="bool" default="true" /><!-- Enable notifications for image caching --> <setting id="imageSyncNotifications" label="30008" type="bool" default="true" /><!-- Enable notifications for image caching -->
<setting id="imageSyncDuringPlayback" label="30009" type="bool" default="true" /><!-- Enable image caching during Kodi playback (restart Kodi!) --> <setting id="imageSyncDuringPlayback" label="30009" type="bool" default="true" /><!-- Enable image caching during Kodi playback (restart Kodi!) -->
<setting label="39020" type="action" action="RunPlugin(plugin://plugin.video.plexkodiconnect/?mode=texturecache)" option="close" /> <!-- Cache all images to Kodi texture cache now --> <setting label="39020" type="action" action="RunPlugin(plugin://plugin.video.plexkodiconnect/?mode=texturecache)" option="close" /> <!-- Cache all images to Kodi texture cache now -->