parent
88ef5f9eda
commit
678544d236
7 changed files with 592 additions and 625 deletions
|
@ -136,6 +136,7 @@ class KodiMonitor(xbmc.Monitor):
|
||||||
LOG.debug("Method: %s Data: %s", method, data)
|
LOG.debug("Method: %s Data: %s", method, data)
|
||||||
|
|
||||||
if method == "Player.OnPlay":
|
if method == "Player.OnPlay":
|
||||||
|
state.SUSPEND_SYNC = True
|
||||||
self.PlayBackStart(data)
|
self.PlayBackStart(data)
|
||||||
elif method == "Player.OnStop":
|
elif method == "Player.OnStop":
|
||||||
# Should refresh our video nodes, e.g. on deck
|
# Should refresh our video nodes, e.g. on deck
|
||||||
|
@ -149,6 +150,7 @@ class KodiMonitor(xbmc.Monitor):
|
||||||
_playback_cleanup(ended=True)
|
_playback_cleanup(ended=True)
|
||||||
else:
|
else:
|
||||||
_playback_cleanup()
|
_playback_cleanup()
|
||||||
|
state.SUSPEND_SYNC = False
|
||||||
elif method == 'Playlist.OnAdd':
|
elif method == 'Playlist.OnAdd':
|
||||||
self._playlist_onadd(data)
|
self._playlist_onadd(data)
|
||||||
elif method == 'Playlist.OnRemove':
|
elif method == 'Playlist.OnRemove':
|
||||||
|
|
|
@ -12,15 +12,16 @@ import variables as v
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
log = getLogger("PLEX."+__name__)
|
LOG = getLogger("PLEX." + __name__)
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
|
||||||
@thread_methods(add_suspends=['SUSPEND_LIBRARY_THREAD',
|
@thread_methods(add_suspends=['SUSPEND_LIBRARY_THREAD',
|
||||||
'DB_SCAN',
|
'DB_SCAN',
|
||||||
'STOP_SYNC'])
|
'STOP_SYNC',
|
||||||
class Process_Fanart_Thread(Thread):
|
'SUSPEND_SYNC'])
|
||||||
|
class ThreadedProcessFanart(Thread):
|
||||||
"""
|
"""
|
||||||
Threaded download of additional fanart in the background
|
Threaded download of additional fanart in the background
|
||||||
|
|
||||||
|
@ -39,21 +40,10 @@ class Process_Fanart_Thread(Thread):
|
||||||
Thread.__init__(self)
|
Thread.__init__(self)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""
|
|
||||||
Catch all exceptions and log them
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
self.__run()
|
|
||||||
except Exception as e:
|
|
||||||
log.error('Exception %s' % e)
|
|
||||||
import traceback
|
|
||||||
log.error("Traceback:\n%s" % traceback.format_exc())
|
|
||||||
|
|
||||||
def __run(self):
|
|
||||||
"""
|
"""
|
||||||
Do the work
|
Do the work
|
||||||
"""
|
"""
|
||||||
log.debug("---===### Starting FanartSync ###===---")
|
LOG.debug("---===### Starting FanartSync ###===---")
|
||||||
stopped = self.stopped
|
stopped = self.stopped
|
||||||
suspended = self.suspended
|
suspended = self.suspended
|
||||||
queue = self.queue
|
queue = self.queue
|
||||||
|
@ -63,7 +53,7 @@ class Process_Fanart_Thread(Thread):
|
||||||
# Set in service.py
|
# Set in service.py
|
||||||
if stopped():
|
if stopped():
|
||||||
# Abort was requested while waiting. We should exit
|
# Abort was requested while waiting. We should exit
|
||||||
log.info("---===### Stopped FanartSync ###===---")
|
LOG.info("---===### Stopped FanartSync ###===---")
|
||||||
return
|
return
|
||||||
sleep(1000)
|
sleep(1000)
|
||||||
# grabs Plex item from queue
|
# grabs Plex item from queue
|
||||||
|
@ -73,15 +63,14 @@ class Process_Fanart_Thread(Thread):
|
||||||
sleep(200)
|
sleep(200)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
log.debug('Get additional fanart for Plex id %s' % item['plex_id'])
|
LOG.debug('Get additional fanart for Plex id %s', item['plex_id'])
|
||||||
with getattr(itemtypes,
|
with getattr(itemtypes,
|
||||||
v.ITEMTYPE_FROM_PLEXTYPE[item['plex_type']])() as cls:
|
v.ITEMTYPE_FROM_PLEXTYPE[item['plex_type']])() as item_type:
|
||||||
result = cls.getfanart(item['plex_id'],
|
result = item_type.getfanart(item['plex_id'],
|
||||||
refresh=item['refresh'])
|
refresh=item['refresh'])
|
||||||
if result is True:
|
if result is True:
|
||||||
log.debug('Done getting fanart for Plex id %s'
|
LOG.debug('Done getting fanart for Plex id %s', item['plex_id'])
|
||||||
% item['plex_id'])
|
|
||||||
with plexdb.Get_Plex_DB() as plex_db:
|
with plexdb.Get_Plex_DB() as plex_db:
|
||||||
plex_db.set_fanart_synched(item['plex_id'])
|
plex_db.set_fanart_synched(item['plex_id'])
|
||||||
queue.task_done()
|
queue.task_done()
|
||||||
log.debug("---===### Stopped FanartSync ###===---")
|
LOG.debug("---===### Stopped FanartSync ###===---")
|
||||||
|
|
|
@ -11,20 +11,22 @@ import sync_info
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
log = getLogger("PLEX."+__name__)
|
LOG = getLogger("PLEX." + __name__)
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
|
||||||
@thread_methods(add_stops=['SUSPEND_LIBRARY_THREAD', 'STOP_SYNC'])
|
@thread_methods(add_stops=['SUSPEND_LIBRARY_THREAD',
|
||||||
class Threaded_Get_Metadata(Thread):
|
'STOP_SYNC',
|
||||||
|
'SUSPEND_SYNC'])
|
||||||
|
class ThreadedGetMetadata(Thread):
|
||||||
"""
|
"""
|
||||||
Threaded download of Plex XML metadata for a certain library item.
|
Threaded download of Plex XML metadata for a certain library item.
|
||||||
Fills the out_queue with the downloaded etree XML objects
|
Fills the out_queue with the downloaded etree XML objects
|
||||||
|
|
||||||
Input:
|
Input:
|
||||||
queue Queue.Queue() object that you'll need to fill up
|
queue Queue.Queue() object that you'll need to fill up
|
||||||
with Plex itemIds
|
with plex_ids
|
||||||
out_queue Queue() object where this thread will store
|
out_queue Queue() object where this thread will store
|
||||||
the downloaded metadata XMLs as etree objects
|
the downloaded metadata XMLs as etree objects
|
||||||
"""
|
"""
|
||||||
|
@ -60,21 +62,10 @@ class Threaded_Get_Metadata(Thread):
|
||||||
self.out_queue.task_done()
|
self.out_queue.task_done()
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""
|
|
||||||
Catch all exceptions and log them
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
self.__run()
|
|
||||||
except Exception as e:
|
|
||||||
log.error('Exception %s' % e)
|
|
||||||
import traceback
|
|
||||||
log.error("Traceback:\n%s" % traceback.format_exc())
|
|
||||||
|
|
||||||
def __run(self):
|
|
||||||
"""
|
"""
|
||||||
Do the work
|
Do the work
|
||||||
"""
|
"""
|
||||||
log.debug('Starting get metadata thread')
|
LOG.debug('Starting get metadata thread')
|
||||||
# cache local variables because it's faster
|
# cache local variables because it's faster
|
||||||
queue = self.queue
|
queue = self.queue
|
||||||
out_queue = self.out_queue
|
out_queue = self.out_queue
|
||||||
|
@ -88,11 +79,11 @@ class Threaded_Get_Metadata(Thread):
|
||||||
sleep(20)
|
sleep(20)
|
||||||
continue
|
continue
|
||||||
# Download Metadata
|
# Download Metadata
|
||||||
xml = GetPlexMetadata(item['itemId'])
|
xml = GetPlexMetadata(item['plex_id'])
|
||||||
if xml is None:
|
if xml is None:
|
||||||
# Did not receive a valid XML - skip that item for now
|
# Did not receive a valid XML - skip that item for now
|
||||||
log.error("Could not get metadata for %s. Skipping that item "
|
LOG.error("Could not get metadata for %s. Skipping that item "
|
||||||
"for now" % item['itemId'])
|
"for now", item['plex_id'])
|
||||||
# Increase BOTH counters - since metadata won't be processed
|
# Increase BOTH counters - since metadata won't be processed
|
||||||
with sync_info.LOCK:
|
with sync_info.LOCK:
|
||||||
sync_info.GET_METADATA_COUNT += 1
|
sync_info.GET_METADATA_COUNT += 1
|
||||||
|
@ -100,21 +91,21 @@ class Threaded_Get_Metadata(Thread):
|
||||||
queue.task_done()
|
queue.task_done()
|
||||||
continue
|
continue
|
||||||
elif xml == 401:
|
elif xml == 401:
|
||||||
log.error('HTTP 401 returned by PMS. Too much strain? '
|
LOG.error('HTTP 401 returned by PMS. Too much strain? '
|
||||||
'Cancelling sync for now')
|
'Cancelling sync for now')
|
||||||
window('plex_scancrashed', value='401')
|
window('plex_scancrashed', value='401')
|
||||||
# Kill remaining items in queue (for main thread to cont.)
|
# Kill remaining items in queue (for main thread to cont.)
|
||||||
queue.task_done()
|
queue.task_done()
|
||||||
break
|
break
|
||||||
|
|
||||||
item['XML'] = xml
|
item['xml'] = xml
|
||||||
if item.get('get_children') is True:
|
if item.get('get_children') is True:
|
||||||
children_xml = GetAllPlexChildren(item['itemId'])
|
children_xml = GetAllPlexChildren(item['plex_id'])
|
||||||
try:
|
try:
|
||||||
children_xml[0].attrib
|
children_xml[0].attrib
|
||||||
except (TypeError, IndexError, AttributeError):
|
except (TypeError, IndexError, AttributeError):
|
||||||
log.error('Could not get children for Plex id %s'
|
LOG.error('Could not get children for Plex id %s',
|
||||||
% item['itemId'])
|
item['plex_id'])
|
||||||
item['children'] = []
|
item['children'] = []
|
||||||
else:
|
else:
|
||||||
item['children'] = children_xml
|
item['children'] = children_xml
|
||||||
|
@ -128,4 +119,4 @@ class Threaded_Get_Metadata(Thread):
|
||||||
queue.task_done()
|
queue.task_done()
|
||||||
# Empty queue in case PKC was shut down (main thread hangs otherwise)
|
# Empty queue in case PKC was shut down (main thread hangs otherwise)
|
||||||
self.terminate_now()
|
self.terminate_now()
|
||||||
log.debug('Get metadata thread terminated')
|
LOG.debug('Get metadata thread terminated')
|
||||||
|
|
|
@ -10,13 +10,15 @@ import itemtypes
|
||||||
import sync_info
|
import sync_info
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
log = getLogger("PLEX."+__name__)
|
LOG = getLogger("PLEX." + __name__)
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
|
||||||
@thread_methods(add_stops=['SUSPEND_LIBRARY_THREAD', 'STOP_SYNC'])
|
@thread_methods(add_stops=['SUSPEND_LIBRARY_THREAD',
|
||||||
class Threaded_Process_Metadata(Thread):
|
'STOP_SYNC',
|
||||||
|
'SUSPEND_SYNC'])
|
||||||
|
class ThreadedProcessMetadata(Thread):
|
||||||
"""
|
"""
|
||||||
Not yet implemented for more than 1 thread - if ever. Only to be called by
|
Not yet implemented for more than 1 thread - if ever. Only to be called by
|
||||||
ONE thread!
|
ONE thread!
|
||||||
|
@ -25,12 +27,12 @@ class Threaded_Process_Metadata(Thread):
|
||||||
Input:
|
Input:
|
||||||
queue: Queue.Queue() object that you'll need to fill up with
|
queue: Queue.Queue() object that you'll need to fill up with
|
||||||
the downloaded XML eTree objects
|
the downloaded XML eTree objects
|
||||||
item_type: as used to call functions in itemtypes.py e.g. 'Movies' =>
|
item_class: as used to call functions in itemtypes.py e.g. 'Movies' =>
|
||||||
itemtypes.Movies()
|
itemtypes.Movies()
|
||||||
"""
|
"""
|
||||||
def __init__(self, queue, item_type):
|
def __init__(self, queue, item_class):
|
||||||
self.queue = queue
|
self.queue = queue
|
||||||
self.item_type = item_type
|
self.item_class = item_class
|
||||||
Thread.__init__(self)
|
Thread.__init__(self)
|
||||||
|
|
||||||
def terminate_now(self):
|
def terminate_now(self):
|
||||||
|
@ -49,23 +51,12 @@ class Threaded_Process_Metadata(Thread):
|
||||||
self.queue.task_done()
|
self.queue.task_done()
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""
|
|
||||||
Catch all exceptions and log them
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
self.__run()
|
|
||||||
except Exception as e:
|
|
||||||
log.error('Exception %s' % e)
|
|
||||||
import traceback
|
|
||||||
log.error("Traceback:\n%s" % traceback.format_exc())
|
|
||||||
|
|
||||||
def __run(self):
|
|
||||||
"""
|
"""
|
||||||
Do the work
|
Do the work
|
||||||
"""
|
"""
|
||||||
log.debug('Processing thread started')
|
LOG.debug('Processing thread started')
|
||||||
# Constructs the method name, e.g. itemtypes.Movies
|
# Constructs the method name, e.g. itemtypes.Movies
|
||||||
item_fct = getattr(itemtypes, self.item_type)
|
item_fct = getattr(itemtypes, self.item_class)
|
||||||
# cache local variables because it's faster
|
# cache local variables because it's faster
|
||||||
queue = self.queue
|
queue = self.queue
|
||||||
stopped = self.stopped
|
stopped = self.stopped
|
||||||
|
@ -79,24 +70,19 @@ class Threaded_Process_Metadata(Thread):
|
||||||
continue
|
continue
|
||||||
# Do the work
|
# Do the work
|
||||||
item_method = getattr(item_class, item['method'])
|
item_method = getattr(item_class, item['method'])
|
||||||
if item.get('children') is not None:
|
if item.get('children'):
|
||||||
item_method(item['XML'][0],
|
item_method(item['xml'][0],
|
||||||
viewtag=item['viewName'],
|
viewtag=item['view_name'],
|
||||||
viewid=item['viewId'],
|
viewid=item['view_id'],
|
||||||
children=item['children'])
|
children=item['children'])
|
||||||
else:
|
else:
|
||||||
item_method(item['XML'][0],
|
item_method(item['xml'][0],
|
||||||
viewtag=item['viewName'],
|
viewtag=item['view_name'],
|
||||||
viewid=item['viewId'])
|
viewid=item['view_id'])
|
||||||
# Keep track of where we are at
|
# Keep track of where we are at
|
||||||
try:
|
|
||||||
log.debug('found child: %s'
|
|
||||||
% item['children'].attrib)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
with sync_info.LOCK:
|
with sync_info.LOCK:
|
||||||
sync_info.PROCESS_METADATA_COUNT += 1
|
sync_info.PROCESS_METADATA_COUNT += 1
|
||||||
sync_info.PROCESSING_VIEW_NAME = item['title']
|
sync_info.PROCESSING_VIEW_NAME = item['title']
|
||||||
queue.task_done()
|
queue.task_done()
|
||||||
self.terminate_now()
|
self.terminate_now()
|
||||||
log.debug('Processing thread terminated')
|
LOG.debug('Processing thread terminated')
|
||||||
|
|
|
@ -2,14 +2,14 @@
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from threading import Thread, Lock
|
from threading import Thread, Lock
|
||||||
|
|
||||||
from xbmc import sleep, Player
|
from xbmc import sleep
|
||||||
from xbmcgui import DialogProgressBG
|
from xbmcgui import DialogProgressBG
|
||||||
|
|
||||||
from utils import thread_methods, language as lang
|
from utils import thread_methods, language as lang
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
log = getLogger("PLEX."+__name__)
|
LOG = getLogger("PLEX." + __name__)
|
||||||
|
|
||||||
GET_METADATA_COUNT = 0
|
GET_METADATA_COUNT = 0
|
||||||
PROCESS_METADATA_COUNT = 0
|
PROCESS_METADATA_COUNT = 0
|
||||||
|
@ -19,8 +19,10 @@ LOCK = Lock()
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
|
||||||
@thread_methods(add_stops=['SUSPEND_LIBRARY_THREAD', 'STOP_SYNC'])
|
@thread_methods(add_stops=['SUSPEND_LIBRARY_THREAD',
|
||||||
class Threaded_Show_Sync_Info(Thread):
|
'STOP_SYNC',
|
||||||
|
'SUSPEND_SYNC'])
|
||||||
|
class ThreadedShowSyncInfo(Thread):
|
||||||
"""
|
"""
|
||||||
Threaded class to show the Kodi statusbar of the metadata download.
|
Threaded class to show the Kodi statusbar of the metadata download.
|
||||||
|
|
||||||
|
@ -34,38 +36,26 @@ class Threaded_Show_Sync_Info(Thread):
|
||||||
Thread.__init__(self)
|
Thread.__init__(self)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""
|
|
||||||
Catch all exceptions and log them
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
self.__run()
|
|
||||||
except Exception as e:
|
|
||||||
log.error('Exception %s' % e)
|
|
||||||
import traceback
|
|
||||||
log.error("Traceback:\n%s" % traceback.format_exc())
|
|
||||||
|
|
||||||
def __run(self):
|
|
||||||
"""
|
"""
|
||||||
Do the work
|
Do the work
|
||||||
"""
|
"""
|
||||||
log.debug('Show sync info thread started')
|
LOG.debug('Show sync info thread started')
|
||||||
# cache local variables because it's faster
|
# cache local variables because it's faster
|
||||||
total = self.total
|
total = self.total
|
||||||
dialog = DialogProgressBG('dialoglogProgressBG')
|
dialog = DialogProgressBG('dialoglogProgressBG')
|
||||||
dialog.create("%s %s: %s %s"
|
dialog.create("%s %s: %s %s"
|
||||||
% (lang(39714), self.item_type, str(total), lang(39715)))
|
% (lang(39714), self.item_type, str(total), lang(39715)))
|
||||||
player = Player()
|
|
||||||
|
|
||||||
total = 2 * total
|
total = 2 * total
|
||||||
totalProgress = 0
|
total_progress = 0
|
||||||
while self.stopped() is False and not player.isPlaying():
|
while not self.stopped():
|
||||||
with LOCK:
|
with LOCK:
|
||||||
get_progress = GET_METADATA_COUNT
|
get_progress = GET_METADATA_COUNT
|
||||||
process_progress = PROCESS_METADATA_COUNT
|
process_progress = PROCESS_METADATA_COUNT
|
||||||
viewName = PROCESSING_VIEW_NAME
|
view_name = PROCESSING_VIEW_NAME
|
||||||
totalProgress = get_progress + process_progress
|
total_progress = get_progress + process_progress
|
||||||
try:
|
try:
|
||||||
percentage = int(float(totalProgress) / float(total)*100.0)
|
percentage = int(float(total_progress) / float(total)*100.0)
|
||||||
except ZeroDivisionError:
|
except ZeroDivisionError:
|
||||||
percentage = 0
|
percentage = 0
|
||||||
dialog.update(percentage,
|
dialog.update(percentage,
|
||||||
|
@ -74,8 +64,8 @@ class Threaded_Show_Sync_Info(Thread):
|
||||||
lang(39712),
|
lang(39712),
|
||||||
process_progress,
|
process_progress,
|
||||||
lang(39713),
|
lang(39713),
|
||||||
viewName))
|
view_name))
|
||||||
# Sleep for x milliseconds
|
# Sleep for x milliseconds
|
||||||
sleep(200)
|
sleep(200)
|
||||||
dialog.close()
|
dialog.close()
|
||||||
log.debug('Show sync info thread terminated')
|
LOG.debug('Show sync info thread terminated')
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -10,6 +10,9 @@ STOP_PKC = False
|
||||||
SUSPEND_LIBRARY_THREAD = False
|
SUSPEND_LIBRARY_THREAD = False
|
||||||
# Set if user decided to cancel sync
|
# Set if user decided to cancel sync
|
||||||
STOP_SYNC = False
|
STOP_SYNC = False
|
||||||
|
# Set e.g. during media playback if PKC should not do any syncs. Will NOT
|
||||||
|
# suspend synching of playstate progress
|
||||||
|
SUSPEND_SYNC = False
|
||||||
# Could we access the paths?
|
# Could we access the paths?
|
||||||
PATH_VERIFIED = False
|
PATH_VERIFIED = False
|
||||||
# Set if a Plex-Kodi DB sync is being done - along with
|
# Set if a Plex-Kodi DB sync is being done - along with
|
||||||
|
@ -36,8 +39,6 @@ FORCE_RELOAD_SKIN = True
|
||||||
# Stemming from the PKC settings.xml
|
# Stemming from the PKC settings.xml
|
||||||
# Shall we show Kodi dialogs when synching?
|
# Shall we show Kodi dialogs when synching?
|
||||||
SYNC_DIALOG = True
|
SYNC_DIALOG = True
|
||||||
# Have we already checked the Kodi DB on consistency?
|
|
||||||
KODI_DB_CHECKED = False
|
|
||||||
# Is synching of Plex music enabled?
|
# Is synching of Plex music enabled?
|
||||||
ENABLE_MUSIC = True
|
ENABLE_MUSIC = True
|
||||||
# How often shall we sync?
|
# How often shall we sync?
|
||||||
|
|
Loading…
Reference in a new issue