Get movie set information asynchronously
This commit is contained in:
parent
e460aea7e8
commit
0db29dd568
4 changed files with 107 additions and 28 deletions
|
@ -173,28 +173,36 @@ 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:
|
||||
# Get Plex artwork for collections - a pain
|
||||
if index == plex_set_id:
|
||||
set_xml = PF.GetPlexMetadata(coll_plex_id)
|
||||
try:
|
||||
set_xml.attrib
|
||||
except AttributeError:
|
||||
LOG.error('Could not get set metadata %s',
|
||||
coll_plex_id)
|
||||
continue
|
||||
set_api = API(set_xml[0])
|
||||
artwork.modify_artwork(set_api.artwork(),
|
||||
kodi_set_id,
|
||||
v.KODI_TYPE_SET,
|
||||
self.kodicursor)
|
||||
break
|
||||
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)
|
||||
try:
|
||||
set_xml.attrib
|
||||
except AttributeError:
|
||||
LOG.error('Could not get set metadata %s',
|
||||
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)
|
||||
self.kodi_db.modify_tags(kodi_id, v.KODI_TYPE_MOVIE, tags)
|
||||
# Process playstate
|
||||
self.kodi_db.set_resume(file_id,
|
||||
|
|
|
@ -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'],
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
return []
|
||||
return [(i.get('index'), i.get('ratingKey')) for i in xml]
|
||||
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 []
|
||||
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):
|
||||
"""
|
||||
|
|
Loading…
Reference in a new issue