Get movie set information asynchronously

This commit is contained in:
croneter 2018-11-07 10:37:32 +01:00
parent e460aea7e8
commit 0db29dd568
4 changed files with 107 additions and 28 deletions

View file

@ -173,13 +173,16 @@ class Movie(ItemBase):
self.kodi_db.modify_studios(kodi_id, v.KODI_TYPE_MOVIE, studios)
tags = [section_name]
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, kodi_id)
for index, coll_plex_id in collections_match:
if children is None:
# e.g. when added via websocket
LOG.debug('Costly looking up Plex collection %s: %s',
plex_set_id, set_name)
for index, coll_plex_id in api.collections_match():
# Get Plex artwork for collections - a pain
if index == plex_set_id:
set_xml = PF.GetPlexMetadata(coll_plex_id)
@ -190,11 +193,16 @@ class Movie(ItemBase):
coll_plex_id)
continue
set_api = API(set_xml[0])
break
elif plex_set_id in children:
# Provided by get_metadata thread
set_api = API(children[plex_set_id][0])
else:
continue
artwork.modify_artwork(set_api.artwork(),
kodi_set_id,
v.KODI_TYPE_SET,
self.kodicursor)
break
self.kodi_db.modify_tags(kodi_id, v.KODI_TYPE_MOVIE, tags)
# Process playstate
self.kodi_db.set_resume(file_id,

View file

@ -3,7 +3,7 @@
from __future__ import absolute_import, division, unicode_literals
from logging import getLogger
from .get_metadata import GetMetadataTask
from .get_metadata import GetMetadataTask, reset_collections
from . import common, process_metadata, sections
from .. import utils, backgroundthread, variables as v, state
from .. import plex_functions as PF, itemtypes
@ -56,7 +56,7 @@ class FullSync(common.libsync_mixin):
self.current_sync)
return
task = GetMetadataTask()
task.setup(self.queue, plex_id, self.get_children)
task.setup(self.queue, plex_id, self.plex_type, self.get_children)
self.threader.addTask(task)
def process_delete(self):
@ -119,6 +119,7 @@ class FullSync(common.libsync_mixin):
continue
LOG.debug('Waiting for processing thread to finish section')
self.queue.join()
reset_collections()
try:
# Sync playstate of every item
iterator = PF.SectionItems(section['section_id'],

View file

@ -3,13 +3,28 @@ from __future__ import absolute_import, division, unicode_literals
from logging import getLogger
from . import common
from .. import plex_functions as PF, backgroundthread, utils
from ..plex_api import API
from .. import plex_functions as PF, backgroundthread, utils, variables as v
###############################################################################
LOG = getLogger("PLEX." + __name__)
###############################################################################
LOCK = backgroundthread.threading.Lock()
# List of tuples: (collection index [as in an item's metadata with "Collection
# id"], collection plex id)
COLLECTION_MATCH = None
# Dict with entries of the form <collection index>: <collection xml>
COLLECTION_XMLS = {}
def reset_collections():
"""
Collections seem unique to Plex sections
"""
global LOCK, COLLECTION_MATCH, COLLECTION_XMLS
with LOCK:
COLLECTION_MATCH = None
COLLECTION_XMLS = {}
class GetMetadataTask(backgroundthread.Task, common.libsync_mixin):
@ -21,11 +36,47 @@ class GetMetadataTask(backgroundthread.Task, common.libsync_mixin):
queue Queue.Queue() object where this thread will store
the downloaded metadata XMLs as etree objects
"""
def setup(self, queue, plex_id, get_children=False):
def setup(self, queue, plex_id, plex_type, get_children=False):
self.queue = queue
self.plex_id = plex_id
self.plex_type = plex_type
self.get_children = get_children
def _collections(self, item):
global COLLECTION_MATCH, COLLECTION_XMLS
api = API(item['xml'][0])
if not COLLECTION_MATCH:
COLLECTION_MATCH = PF.collections(api.library_section_id())
if not COLLECTION_MATCH:
LOG.error('Could not download collections')
return
# Extract what we need to know
COLLECTION_MATCH = \
[(utils.cast(int, x.get('index')),
utils.cast(int, x.get('ratingKey'))) for x in COLLECTION_MATCH]
item['children'] = {}
for plex_set_id, set_name in api.collection_list():
if self.isCanceled():
return
if plex_set_id not in COLLECTION_XMLS:
# Get Plex metadata for collections - a pain
for index, collection_plex_id in COLLECTION_MATCH:
if index == plex_set_id:
collection_xml = PF.GetPlexMetadata(collection_plex_id)
try:
collection_xml[0].attrib
except (TypeError, IndexError, AttributeError):
LOG.error('Could not get collection %s %s',
collection_plex_id, set_name)
continue
COLLECTION_XMLS[plex_set_id] = collection_xml
break
else:
LOG.error('Did not find Plex collection %s %s',
plex_set_id, set_name)
continue
item['children'][plex_set_id] = COLLECTION_XMLS[plex_set_id]
def run(self):
"""
Do the work
@ -47,6 +98,17 @@ class GetMetadataTask(backgroundthread.Task, common.libsync_mixin):
'Cancelling sync for now')
utils.window('plex_scancrashed', value='401')
return
if not self.isCanceled() and self.plex_type == v.PLEX_TYPE_MOVIE:
# Check for collections/sets
collections = False
for child in item['xml'][0]:
if child.tag == 'Collection':
collections = True
break
if collections:
global LOCK
with LOCK:
self._collections(item)
if not self.isCanceled() and self.get_children:
children_xml = PF.GetAllPlexChildren(self.plex_id)
try:

View file

@ -67,6 +67,7 @@ class API(object):
# which media part in the XML response shall we look at?
self.part = 0
self.mediastream = None
self.collections = None
self.server = utils.window('pms_server')
def set_part_number(self, number=None):
@ -345,7 +346,8 @@ class API(object):
collections = []
for child in self.item:
if child.tag == 'Collection':
collections.append((child.get('id'), child.get('tag')))
collections.append((cast(int, child.get('id')),
child.get('tag')))
return collections
def people(self):
@ -1270,10 +1272,16 @@ class API(object):
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 xml is None:
if self.collections is None:
self.collections = PF.collections(self.library_section_id())
if self.collections is None:
LOG.error('Could not download collections for %s',
self.library_section_id())
return []
return [(i.get('index'), i.get('ratingKey')) for i in xml]
self.collections = \
[(utils.cast(int, x.get('index')),
utils.cast(int, x.get('ratingKey'))) for x in self.collections]
return self.collections
def set_artwork(self):
"""