Support for Plex collection artwork (PKC settings toggle under Artwork )
- Fixes #408
This commit is contained in:
parent
70ffc7b826
commit
e62b909a75
7 changed files with 102 additions and 24 deletions
|
@ -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 ""
|
||||||
|
|
|
@ -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")
|
||||||
self.kodi_db.modify_tags(movieid, v.KODI_TYPE_MOVIE, tags)
|
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
|
# Add any sets from Plex collection tags
|
||||||
self.kodi_db.add_sets(movieid, collections)
|
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)
|
||||||
# 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)
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 -->
|
||||||
|
|
Loading…
Reference in a new issue