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)
|
self.kodi_db.modify_studios(kodi_id, v.KODI_TYPE_MOVIE, studios)
|
||||||
tags = [section_name]
|
tags = [section_name]
|
||||||
if collections:
|
if collections:
|
||||||
collections_match = api.collections_match()
|
|
||||||
for plex_set_id, set_name in collections:
|
for plex_set_id, set_name in collections:
|
||||||
tags.append(set_name)
|
tags.append(set_name)
|
||||||
# Add any sets from Plex collection tags
|
# Add any sets from Plex collection tags
|
||||||
kodi_set_id = self.kodi_db.create_collection(set_name)
|
kodi_set_id = self.kodi_db.create_collection(set_name)
|
||||||
self.kodi_db.assign_collection(kodi_set_id, kodi_id)
|
self.kodi_db.assign_collection(kodi_set_id, kodi_id)
|
||||||
for index, coll_plex_id in collections_match:
|
if children is None:
|
||||||
# Get Plex artwork for collections - a pain
|
# e.g. when added via websocket
|
||||||
if index == plex_set_id:
|
LOG.debug('Costly looking up Plex collection %s: %s',
|
||||||
set_xml = PF.GetPlexMetadata(coll_plex_id)
|
plex_set_id, set_name)
|
||||||
try:
|
for index, coll_plex_id in api.collections_match():
|
||||||
set_xml.attrib
|
# Get Plex artwork for collections - a pain
|
||||||
except AttributeError:
|
if index == plex_set_id:
|
||||||
LOG.error('Could not get set metadata %s',
|
set_xml = PF.GetPlexMetadata(coll_plex_id)
|
||||||
coll_plex_id)
|
try:
|
||||||
continue
|
set_xml.attrib
|
||||||
set_api = API(set_xml[0])
|
except AttributeError:
|
||||||
artwork.modify_artwork(set_api.artwork(),
|
LOG.error('Could not get set metadata %s',
|
||||||
kodi_set_id,
|
coll_plex_id)
|
||||||
v.KODI_TYPE_SET,
|
continue
|
||||||
self.kodicursor)
|
set_api = API(set_xml[0])
|
||||||
break
|
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)
|
self.kodi_db.modify_tags(kodi_id, v.KODI_TYPE_MOVIE, tags)
|
||||||
# Process playstate
|
# Process playstate
|
||||||
self.kodi_db.set_resume(file_id,
|
self.kodi_db.set_resume(file_id,
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
|
||||||
from .get_metadata import GetMetadataTask
|
from .get_metadata import GetMetadataTask, reset_collections
|
||||||
from . import common, process_metadata, sections
|
from . import common, process_metadata, sections
|
||||||
from .. import utils, backgroundthread, variables as v, state
|
from .. import utils, backgroundthread, variables as v, state
|
||||||
from .. import plex_functions as PF, itemtypes
|
from .. import plex_functions as PF, itemtypes
|
||||||
|
@ -56,7 +56,7 @@ class FullSync(common.libsync_mixin):
|
||||||
self.current_sync)
|
self.current_sync)
|
||||||
return
|
return
|
||||||
task = GetMetadataTask()
|
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)
|
self.threader.addTask(task)
|
||||||
|
|
||||||
def process_delete(self):
|
def process_delete(self):
|
||||||
|
@ -119,6 +119,7 @@ class FullSync(common.libsync_mixin):
|
||||||
continue
|
continue
|
||||||
LOG.debug('Waiting for processing thread to finish section')
|
LOG.debug('Waiting for processing thread to finish section')
|
||||||
self.queue.join()
|
self.queue.join()
|
||||||
|
reset_collections()
|
||||||
try:
|
try:
|
||||||
# Sync playstate of every item
|
# Sync playstate of every item
|
||||||
iterator = PF.SectionItems(section['section_id'],
|
iterator = PF.SectionItems(section['section_id'],
|
||||||
|
|
|
@ -3,13 +3,28 @@ from __future__ import absolute_import, division, unicode_literals
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
|
||||||
from . import common
|
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__)
|
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):
|
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
|
queue Queue.Queue() object where this thread will store
|
||||||
the downloaded metadata XMLs as etree objects
|
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.queue = queue
|
||||||
self.plex_id = plex_id
|
self.plex_id = plex_id
|
||||||
|
self.plex_type = plex_type
|
||||||
self.get_children = get_children
|
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):
|
def run(self):
|
||||||
"""
|
"""
|
||||||
Do the work
|
Do the work
|
||||||
|
@ -47,6 +98,17 @@ class GetMetadataTask(backgroundthread.Task, common.libsync_mixin):
|
||||||
'Cancelling sync for now')
|
'Cancelling sync for now')
|
||||||
utils.window('plex_scancrashed', value='401')
|
utils.window('plex_scancrashed', value='401')
|
||||||
return
|
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:
|
if not self.isCanceled() and self.get_children:
|
||||||
children_xml = PF.GetAllPlexChildren(self.plex_id)
|
children_xml = PF.GetAllPlexChildren(self.plex_id)
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -67,6 +67,7 @@ class API(object):
|
||||||
# which media part in the XML response shall we look at?
|
# which media part in the XML response shall we look at?
|
||||||
self.part = 0
|
self.part = 0
|
||||||
self.mediastream = None
|
self.mediastream = None
|
||||||
|
self.collections = None
|
||||||
self.server = utils.window('pms_server')
|
self.server = utils.window('pms_server')
|
||||||
|
|
||||||
def set_part_number(self, number=None):
|
def set_part_number(self, number=None):
|
||||||
|
@ -345,7 +346,8 @@ class API(object):
|
||||||
collections = []
|
collections = []
|
||||||
for child in self.item:
|
for child in self.item:
|
||||||
if child.tag == 'Collection':
|
if child.tag == 'Collection':
|
||||||
collections.append((child.get('id'), child.get('tag')))
|
collections.append((cast(int, child.get('id')),
|
||||||
|
child.get('tag')))
|
||||||
return collections
|
return collections
|
||||||
|
|
||||||
def people(self):
|
def people(self):
|
||||||
|
@ -1270,10 +1272,16 @@ class API(object):
|
||||||
current item's Plex library sectin
|
current item's Plex library sectin
|
||||||
Pass in the collection id of e.g. the movie's metadata
|
Pass in the collection id of e.g. the movie's metadata
|
||||||
"""
|
"""
|
||||||
xml = PF.collections(self.library_section_id())
|
if self.collections is None:
|
||||||
if xml is None:
|
self.collections = PF.collections(self.library_section_id())
|
||||||
return []
|
if self.collections is None:
|
||||||
return [(i.get('index'), i.get('ratingKey')) for i in xml]
|
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):
|
def set_artwork(self):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in a new issue