Switch to threaded Movie metadata processing

This commit is contained in:
tomkat83 2016-01-07 17:27:48 +01:00
parent e86b8c2358
commit 8c18879271
4 changed files with 559 additions and 153 deletions

View file

@ -845,6 +845,7 @@ class PlexAPI():
"""
plexToken = utils.settings('plexToken')
users = self.MyPlexListHomeUsers(plexToken)
url = ''
# If an error is encountered, set to False
if not users:
self.logMsg("Could not get userlist from plex.tv.", 1)
@ -1188,12 +1189,15 @@ class PlexAPI():
mediatype String or list of strings with possible values
'movie', 'show', 'artist', 'photo'
Output:
Collection containing only mediatype. List with entry of the form:
List with an entry of the form:
{
'name': xxx Plex title for the media section
'type': xxx Plex type: 'movie', 'show', 'artist', 'photo'
'id': xxx Plex unique key for the section
'id': xxx Plex unique key for the section (1, 2, 3...)
'uuid': xxx Other unique Plex key, e.g.
74aec9f2-a312-4723-9436-de2ea43843c1
}
Returns an empty list if nothing is found.
"""
collections = []
url = "{server}/library/sections"
@ -1208,17 +1212,19 @@ class PlexAPI():
if contentType in mediatype:
name = item['title']
contentId = item['key']
uuid = item['uuid']
collections.append({
'name': name,
'type': contentType,
'id': str(contentId)
'id': str(contentId),
'uuid': uuid
})
return collections
def GetPlexSectionResults(self, viewId):
"""
Returns a list (raw API dump) of all Plex movies in the Plex section
with key = viewId.
Returns a list (raw JSON API dump) of all Plex items in the Plex
section with key = viewId.
"""
result = []
url = "{server}/library/sections/%s/all" % viewId
@ -1226,10 +1232,17 @@ class PlexAPI():
try:
result = jsondata['_children']
except KeyError:
self.logMsg("Error retrieving all movies for section %s" % viewId, 1)
self.logMsg("Error retrieving all items for Plex section %s" % viewId, 1)
pass
return result
def GetPlexSubitems(self, key):
"""
Returns a list (raw JSON API dump) of all Plex subitems for the key.
(e.g. key=/library/metadata/194853/children pointing to a season)
"""
def GetPlexMetadata(self, key):
"""
Returns raw API metadata for key.

View file

@ -26,12 +26,7 @@ import PlexAPI
class Items(object):
def __init__(self, embycursor, kodicursor):
self.embycursor = embycursor
self.kodicursor = kodicursor
def __init__(self):
self.clientInfo = clientinfo.ClientInfo()
self.addonName = self.clientInfo.getAddonName()
self.doUtils = downloadutils.DownloadUtils()
@ -43,8 +38,25 @@ class Items(object):
self.artwork = artwork.Artwork()
self.emby = embyserver.Read_EmbyServer()
self.emby_db = embydb.Embydb_Functions(embycursor)
self.kodi_db = kodidb.Kodidb_Functions(kodicursor)
def __enter__(self):
self.embyconn = utils.kodiSQL('emby')
self.embycursor = self.embyconn.cursor()
self.kodiconn = utils.kodiSQL('video')
self.kodicursor = self.kodiconn.cursor()
self.emby_db = embydb.Embydb_Functions(self.embycursor)
self.kodi_db = kodidb.Kodidb_Functions(self.kodicursor)
return self
def __exit__(self, exc_type, exc_val, exc_tb):
"""
Make sure DB changes are committed and connection to DB is closed.
"""
self.embyconn.commit()
self.kodiconn.commit()
self.embyconn.close()
self.kodiconn.close()
return self
def logMsg(self, msg, lvl=1):
@ -230,10 +242,6 @@ class Items(object):
class Movies(Items):
def __init__(self, embycursor, kodicursor):
Items.__init__(self, embycursor, kodicursor)
def added(self, items, pdialog):
total = len(items)
@ -265,7 +273,6 @@ class Movies(Items):
count += 1
self.add_updateBoxset(boxset)
def add_update(self, item, viewtag=None, viewid=None):
# Process single movie
kodicursor = self.kodicursor
@ -296,6 +303,7 @@ class Movies(Items):
kodicursor.execute("select coalesce(max(idMovie),0) from movie")
movieid = kodicursor.fetchone()[0] + 1
# if not viewtag or not viewid:
# # Get view tag from emby
# viewtag, viewid, mediatype = self.emby.getView_embyId(itemid)

View file

@ -2,9 +2,8 @@
##################################################################################################
import sqlite3
import threading
from datetime import datetime, timedelta, time
from datetime import datetime, timedelta
import xbmc
import xbmcgui
@ -22,10 +21,171 @@ import userclient
import videonodes
import PlexAPI
import Queue
import time
##################################################################################################
class ThreadedGetMetadata(threading.Thread):
"""
Threaded download of Plex XML metadata for a certain library item.
Fills the out_queue with the downloaded etree XML objects
Input:
queue Queue.Queue() object that you'll need to fill up
with Plex itemIds
out_queue Queue.Queue() object where this thread will store
the downloaded metadata XMLs as etree objects
lock threading.Lock(), used for counting where we are
userStop Handle to a function where True is used to stop
this Thread
"""
def __init__(self, queue, out_queue, lock, userStop):
self.queue = queue
self.out_queue = out_queue
self.lock = lock
self.userStop = userStop
self._shouldstop = threading.Event()
threading.Thread.__init__(self)
def run(self):
plx = PlexAPI.PlexAPI()
global getMetadataCount
while self.stopped() is False:
# grabs Plex item from queue
try:
itemId = self.queue.get(block=False)
# Empty queue
except:
continue
# Download Metadata
plexElement = plx.GetPlexMetadata(itemId)
# place item into out queue
self.out_queue.put(plexElement)
# Keep track of where we are at
with self.lock:
getMetadataCount += 1
# signals to queue job is done
self.queue.task_done()
def stopThread(self):
self._shouldstop.set()
def stopped(self):
return self._shouldstop.isSet() or self.userStop()
class ThreadedProcessMetadata(threading.Thread):
"""
Not yet implemented - if ever. Only to be called by ONE thread!
Processes the XML metadata in the queue
Input:
queue: Queue.Queue() object that you'll need to fill up with
the downloaded XML eTree objects
data = {
'itemType': as used to call functions in itemtypes.py
e.g. 'Movies' => itemtypes.Movies()
'viewName' Plex str for library view (e.g. 'Movies')
'viewId' Plex Id to identifiy the library view
}
lock: threading.Lock(), used for counting where we are
userStop Handle to a function where True is used to stop this Thread
"""
def __init__(self, queue, data, lock, userStop):
self.queue = queue
self.lock = lock
self.data = data
self.userStop = userStop
self._shouldstop = threading.Event()
threading.Thread.__init__(self)
def run(self):
# Constructs the method name, e.g. itemtypes.Movies
itemFkt = getattr(itemtypes, self.data['itemType'])
viewName = self.data['viewName']
viewId = self.data['viewId']
global processMetadataCount
with itemFkt() as item:
while self.stopped() is False:
# grabs item from queue
try:
plexitem = self.queue.get(block=False)
# Empty queue
except:
continue
# Do the work; lock to be sure we've only got 1 Thread
with self.lock:
item.add_update(
plexitem,
viewtag=viewName,
viewid=viewId
)
# Keep track of where we are at
processMetadataCount += 1
# signals to queue job is done
self.queue.task_done()
def stopThread(self):
self._shouldstop.set()
def stopped(self):
return self._shouldstop.isSet() or self.userStop()
class ThreadedShowSyncInfo(threading.Thread):
"""
Threaded class to show the Kodi statusbar of the metadata download.
Input:
dialog xbmcgui.DialogProgressBG() object to show progress
locks = [downloadLock, processLock] Locks() to the other threads
total: Total number of items to get
viewName: Name of library we're getting
"""
def __init__(self, dialog, locks, total, viewName):
self.locks = locks
self.total = total
self.viewName = viewName
self.addonName = clientinfo.ClientInfo().getAddonName()
self._shouldstop = threading.Event()
self.dialog = dialog
threading.Thread.__init__(self)
def run(self):
total = self.total
downloadLock = self.locks[0]
processLock = self.locks[1]
self.dialog.create(
self.addonName + ": Sync " + self.viewName,
"Starting"
)
global getMetadataCount
global processMetadataCount
total = 2 * total
totalProgress = 0
while self.stopped() is not True:
with downloadLock:
getMetadataProgress = getMetadataCount
with processLock:
processMetadataProgress = processMetadataCount
totalProgress = getMetadataProgress + processMetadataProgress
percentage = int(float(totalProgress) / float(total)*100.0)
self.dialog.update(
percentage,
message="Downloaded: %s, Processed: %s" %
(getMetadataProgress, processMetadataProgress)
)
time.sleep(0.5)
def stopThread(self):
self._shouldstop.set()
def stopped(self):
return self._shouldstop.isSet()
class LibrarySync(threading.Thread):
_shared_state = {}
@ -54,6 +214,7 @@ class LibrarySync(threading.Thread):
self.emby = embyserver.Read_EmbyServer()
self.vnodes = videonodes.VideoNodes()
self.plx = PlexAPI.PlexAPI()
self.syncThreadNumber = int(utils.settings('syncThreadNumber'))
threading.Thread.__init__(self)
@ -84,12 +245,6 @@ class LibrarySync(threading.Thread):
# Verify if server plugin is installed.
if utils.settings('serverSync') == "true":
# Try to use fast start up
url = "{server}/emby/Plugins?format=json"
result = self.doUtils.downloadUrl(url)
for plugin in result:
if plugin['Name'] == "Emby.Kodi Sync Queue":
self.logMsg("Found server plugin.", 2)
completed = self.fastSync()
if not completed:
@ -186,15 +341,7 @@ class LibrarySync(threading.Thread):
connection.commit()
self.logMsg("Commit successful.", 1)
def fullSync(self, manualrun=False, repair=False):
# Only run once when first setting up. Can be run manually.
emby = self.emby
music_enabled = utils.settings('enableMusic') == "true"
utils.window('emby_dbScan', value="true")
# Add sources
utils.sourcesXML()
def initializeDBs(self):
embyconn = utils.kodiSQL('emby')
embycursor = embyconn.cursor()
# Create the tables for the emby database
@ -210,8 +357,17 @@ class LibrarySync(threading.Thread):
embyconn.commit()
# content sync: movies, tvshows, musicvideos, music
kodiconn = utils.kodiSQL('video')
kodicursor = kodiconn.cursor()
embyconn.close()
return
def fullSync(self, manualrun=False, repair=False):
# Only run once when first setting up. Can be run manually.
self.compare = manualrun
music_enabled = utils.settings('enableMusic') == "true"
utils.window('emby_dbScan', value="true")
# Add sources
utils.sourcesXML()
if manualrun:
message = "Manual sync"
@ -221,13 +377,12 @@ class LibrarySync(threading.Thread):
message = "Initial sync"
utils.window('emby_initialScan', value="true")
pDialog = self.progressDialog("%s" % message, forced=True)
starttotal = datetime.now()
# Set views
# self.maintainViews(embycursor, kodicursor)
# embyconn.commit()
self.initializeDBs()
# Sync video library
process = {
@ -238,59 +393,47 @@ class LibrarySync(threading.Thread):
}
process = {
'movies': self.PlexMovies,
'movies': self.PlexMovies
# 'tvshows': self.PlexTVShows
}
for itemtype in process:
startTime = datetime.now()
completed = process[itemtype](embycursor, kodicursor, pDialog, compare=manualrun)
completed = process[itemtype]()
if not completed:
utils.window('emby_dbScan', clear=True)
if pDialog:
pDialog.close()
embycursor.close()
kodicursor.close()
return False
else:
self.dbCommit(kodiconn)
embyconn.commit()
elapsedTime = datetime.now() - startTime
self.logMsg(
"SyncDatabase (finished %s in: %s)"
% (itemtype, str(elapsedTime).split('.')[0]), 1)
% (itemtype, str(elapsedTime).split('.')[0]), 0)
# sync music
if music_enabled:
# # sync music
# if music_enabled:
musicconn = utils.kodiSQL('music')
musiccursor = musicconn.cursor()
# musicconn = utils.kodiSQL('music')
# musiccursor = musicconn.cursor()
startTime = datetime.now()
completed = self.music(embycursor, musiccursor, pDialog, compare=manualrun)
if not completed:
# startTime = datetime.now()
# completed = self.music(embycursor, musiccursor, pDialog, compare=manualrun)
# if not completed:
utils.window('emby_dbScan', clear=True)
if pDialog:
pDialog.close()
# utils.window('emby_dbScan', clear=True)
embycursor.close()
musiccursor.close()
return False
else:
musicconn.commit()
embyconn.commit()
elapsedTime = datetime.now() - startTime
self.logMsg(
"SyncDatabase (finished music in: %s)"
% (str(elapsedTime).split('.')[0]), 1)
musiccursor.close()
if pDialog:
pDialog.close()
embycursor.close()
kodicursor.close()
# embycursor.close()
# musiccursor.close()
# return False
# else:
# musicconn.commit()
# embyconn.commit()
# elapsedTime = datetime.now() - startTime
# self.logMsg(
# "SyncDatabase (finished music in: %s)"
# % (str(elapsedTime).split('.')[0]), 1)
# musiccursor.close()
utils.settings('SyncInstallRunDone', value="true")
utils.settings("dbCreatedWithVersion", self.clientInfo.getVersion())
@ -465,98 +608,174 @@ class LibrarySync(threading.Thread):
# Save total
utils.window('Emby.nodes.total', str(totalnodes))
def GetUpdatelist(self, elementList):
"""
Adds items to self.updatelist as well as self.allPlexElementsId dict
Input:
elementList: List of elements, e.g. a list of '_children'
movie elements as received via JSON from PMS
def PlexMovies(self, embycursor, kodicursor, pdialog, compare=False):
Output: self.updatelist, self.allPlexElementsId
self.updatelist APPENDED(!!) list itemids (Plex Keys as
as received from API.getKey())
self.allPlexElementsId APPENDED(!!) dic
= {itemid: checksum}
"""
if self.compare:
# Manual sync
for plexmovie in elementList:
if self.shouldStop():
return False
API = PlexAPI.API(plexmovie)
plex_checksum = API.getChecksum()
itemid = API.getKey()
self.allPlexElementsId[itemid] = plex_checksum
kodi_checksum = self.allKodiElementsId.get(itemid)
if kodi_checksum != plex_checksum:
# Only update if movie is not in Kodi or checksum is
# different
self.updatelist.append(itemid)
else:
# Initial or repair sync: get all Plex movies
for plexmovie in elementList:
API = PlexAPI.API(plexmovie)
itemid = API.getKey()
plex_checksum = API.getChecksum()
self.allPlexElementsId[itemid] = plex_checksum
self.updatelist.append(itemid)
# Update the Kodi popup info
return self.updatelist, self.allPlexElementsId
def PlexMovies(self):
# Initialize
plx = PlexAPI.PlexAPI()
compare = self.compare
self.updatelist = []
self.allPlexElementsId = {}
# Initialze DBs
embyconn = utils.kodiSQL('emby')
embycursor = embyconn.cursor()
# Get movies from Plex server
emby_db = embydb.Embydb_Functions(embycursor)
movies = itemtypes.Movies(embycursor, kodicursor)
views = plx.GetPlexCollections('movie')
self.logMsg("Media folders: %s" % views, 1)
if compare:
# Pull the list of movies and boxsets in Kodi
try:
all_kodimoviesId = dict(emby_db.getChecksum('Movie'))
self.allKodiElementsId = dict(emby_db.getChecksum('Movie'))
except ValueError:
all_kodimoviesId = {}
all_plexmoviesIds = {}
self.allKodiElementsId = {}
else:
# Getting all metadata, hence set Kodi elements to {}
self.allKodiElementsId = {}
embyconn.close()
##### PROCESS MOVIES #####
for view in views:
updatelist = []
self.updatelist = []
if self.shouldStop():
return False
# Get items per view
viewId = view['id']
viewName = view['name']
if pdialog:
pdialog.update(
heading=self.addonName,
message="Gathering movies from view: %s..." % viewName
)
all_plexmovies = plx.GetPlexSectionResults(viewId)
# Populate self.updatelist and self.allPlexElementsId
self.GetUpdatelist(all_plexmovies)
self.logMsg("Processed view %s with ID %s" % (viewName, viewId), 1)
if compare:
# Manual sync
if pdialog:
pdialog.update(
heading=self.addonName,
message="Comparing movies from view: %s..." % viewName
self.logMsg("self.updatelist: %s" % self.updatelist, 2)
self.logMsg("self.allPlexElementsId: %s" % self.allPlexElementsId, 2)
self.logMsg("self.allKodiElementsId: %s" % self.allKodiElementsId, 2)
# Run through self.updatelist, get XML metadata per item
# Initiate threads
self.logMsg("=====================", 1)
self.logMsg("Starting sync threads", 1)
self.logMsg("=====================", 1)
getMetadataQueue = Queue.Queue()
processMetadataQueue = Queue.Queue()
getMetadataLock = threading.Lock()
processMetadataLock = threading.Lock()
# To keep track
global getMetadataCount
getMetadataCount = 0
global processMetadataCount
processMetadataCount = 0
# Spawn GetMetadata threads
threads = []
for i in range(self.syncThreadNumber):
t = ThreadedGetMetadata(
getMetadataQueue,
processMetadataQueue,
getMetadataLock,
self.shouldStop
)
for plexmovie in all_plexmovies:
if self.shouldStop():
return False
API = PlexAPI.API(plexmovie)
plex_checksum = API.getChecksum()
itemid = API.getKey()
kodi_checksum = all_kodimoviesId.get(itemid)
all_plexmoviesIds[itemid] = plex_checksum
if kodi_checksum != plex_checksum:
# Only update if movie is not in Kodi or checksum is different
updatelist.append(itemid)
else:
# Initial or repair sync: get all Plex movies
for plexmovie in all_plexmovies:
API = PlexAPI.API(plexmovie)
itemid = API.getKey()
plex_checksum = API.getChecksum()
all_plexmoviesIds[itemid] = plex_checksum
updatelist.append(itemid)
t.setDaemon(True)
t.start()
threads.append(t)
self.logMsg("%s download threads spawned" % self.syncThreadNumber, 1)
# Populate queue: GetMetadata
for itemId in self.updatelist:
getMetadataQueue.put(itemId)
self.logMsg("Queue populated", 1)
# Spawn one more thread to process Metadata, once downloaded
data = {
'itemType': 'Movies',
'viewName': viewName,
'viewId': viewId
}
thread = ThreadedProcessMetadata(
processMetadataQueue,
data,
processMetadataLock,
self.shouldStop
)
thread.setDaemon(True)
thread.start()
threads.append(thread)
self.logMsg("Processing thread spawned", 1)
total = len(updatelist)
if pdialog:
pdialog.update(heading="Processing %s / %s items" % (viewName, total))
count = 0
for itemid in updatelist:
# Process individual movies
if self.shouldStop():
return False
# Download Metadata
plexmovie = plx.GetPlexMetadata(itemid)
# Check whether metadata is valid
title = plexmovie[0].attrib['title']
if pdialog:
percentage = int((float(count) / float(total))*100)
pdialog.update(percentage, message=title)
count += 1
# Download individual metadata
self.logMsg("Start parsing metadata for movie: %s" % title, 0)
movies.add_update(plexmovie, viewName, viewId)
else:
self.logMsg("Movies finished.", 2)
# Start one thread to show sync progress
dialog = xbmcgui.DialogProgressBG()
total = len(self.updatelist)
thread = ThreadedShowSyncInfo(
dialog,
[getMetadataLock, processMetadataLock],
total,
viewName
)
thread.setDaemon(True)
thread.start()
threads.append(thread)
self.logMsg("Kodi Infobox thread spawned", 1)
# Wait until finished
getMetadataQueue.join()
processMetadataQueue.join()
# Kill threads
self.logMsg("Waiting to kill threads", 1)
for thread in threads:
thread.stopThread()
self.logMsg("Stop sent to all threads", 1)
# Wait till threads are indeed dead
for thread in threads:
thread.join()
dialog.close()
self.logMsg("=====================", 1)
self.logMsg("Sync threads finished", 1)
self.logMsg("=====================", 1)
##### PROCESS DELETES #####
self.logMsg("all_plexmoviesIds: %s" % all_plexmoviesIds, 0)
self.logMsg("all_kodimoviesId: %s" % all_kodimoviesId, 0)
if compare:
# Manual sync, process deletes
for kodimovie in all_kodimoviesId:
if kodimovie not in all_plexmoviesIds:
movies.remove(kodimovie)
itemFkt = getattr(itemtypes, 'Movies')
with itemFkt() as item:
for kodimovie in self.allKodiElementsId:
if kodimovie not in self.allPlexElementsId:
item.remove(kodimovie)
else:
self.logMsg("Movies compare finished.", 1)
return True
@ -915,6 +1134,176 @@ class LibrarySync(threading.Thread):
return True
def PlexTVShows(self, embycursor, kodicursor):
# Initialize
plx = PlexAPI.PlexAPI()
compare = self.compare
pdialog = self.pDialog
self.updatelist = []
self.allPlexElementsId = {}
# Get shows from emby
emby_db = embydb.Embydb_Functions(embycursor)
tvshows = itemtypes.TVShows(embycursor, kodicursor)
views = plx.GetPlexCollections('show')
self.logMsg("Media folders: %s" % views, 1)
self.allKodiElementsId = {}
if compare:
# Pull the list of TV shows already in Kodi
try:
all_koditvshows = dict(emby_db.getChecksum('Series'))
self.allKodiElementsId.update(all_koditvshows)
except ValueError:
pass
# Same for the episodes (sub-element of shows/series)
try:
all_kodiepisodes = dict(emby_db.getChecksum('Episode'))
self.allKodiElementsId.update(all_kodiepisodes)
except ValueError:
pass
for view in views:
self.updatelist = []
if self.shouldStop():
return False
# Get items per view
viewId = view['id']
viewName = view['name']
if pdialog:
pdialog.update(
heading=self.addonName,
message="Gathering TV Shows from view: %s..." % viewName)
all_plexTvShows = plx.GetPlexSectionResults(viewId)
# Populate self.updatelist with TV shows and self.allPlexElementsId
self.GetUpdatelist(all_plexTvShows, viewName)
# Run through self.updatelist, get XML metadata per item and safe
# to Kodi
self.ProcessUpdateList(tvshows, view)
if compare:
# Manual sync
for plexTvShow in all_plexTvShows:
if self.shouldStop():
return False
API = plx(plexTvShow)
plex_checksum = API.getChecksum()
itemid = API.getKey()
kodi_checksum = all_kodimoviesId.get(itemid)
all_plextvshowsIds[itemid] = itemid
kodi_checksum = all_koditvshows.get(itemid)
#if kodi_checksum != plex_checksum:
if all_koditvshows.get(itemid) != API.getChecksum():
# Only update if movie is not in Kodi or checksum is different
updatelist.append(itemid)
self.logMsg("TVShows to update for %s: %s" % (viewName, updatelist), 1)
embytvshows = emby.getFullItems(updatelist)
total = len(updatelist)
del updatelist[:]
else:
all_embytvshows = emby.getShows(viewId)
total = all_embytvshows['TotalRecordCount']
embytvshows = all_embytvshows['Items']
if pdialog:
pdialog.update(heading="Processing %s / %s items" % (viewName, total))
count = 0
for embytvshow in embytvshows:
# Process individual show
if self.shouldStop():
return False
itemid = embytvshow['Id']
title = embytvshow['Name']
if pdialog:
percentage = int((float(count) / float(total))*100)
pdialog.update(percentage, message=title)
count += 1
tvshows.add_update(embytvshow, viewName, viewId)
if not compare:
# Process episodes
all_episodes = emby.getEpisodesbyShow(itemid)
for episode in all_episodes['Items']:
# Process individual show
if self.shouldStop():
return False
episodetitle = episode['Name']
if pdialog:
pdialog.update(percentage, message="%s - %s" % (title, episodetitle))
tvshows.add_updateEpisode(episode)
else:
if compare:
# Get all episodes in view
if pdialog:
pdialog.update(
heading="Emby for Kodi",
message="Comparing episodes from view: %s..." % viewName)
all_embyepisodes = emby.getEpisodes(viewId, basic=True)
for embyepisode in all_embyepisodes['Items']:
if self.shouldStop():
return False
API = api.API(embyepisode)
itemid = embyepisode['Id']
all_embyepisodesIds.add(itemid)
if all_kodiepisodes.get(itemid) != API.getChecksum():
# Only update if movie is not in Kodi or checksum is different
updatelist.append(itemid)
self.logMsg("Episodes to update for %s: %s" % (viewName, updatelist), 1)
embyepisodes = emby.getFullItems(updatelist)
total = len(updatelist)
del updatelist[:]
count = 0
for episode in embyepisodes:
# Process individual episode
if self.shouldStop():
return False
title = episode['SeriesName']
episodetitle = episode['Name']
if pdialog:
percentage = int((float(count) / float(total))*100)
pdialog.update(percentage, message="%s - %s" % (title, episodetitle))
count += 1
tvshows.add_updateEpisode(episode)
else:
self.logMsg("TVShows finished.", 2)
##### PROCESS DELETES #####
if compare:
# Manual sync, process deletes
for koditvshow in all_koditvshows:
if koditvshow not in all_embytvshowsIds:
tvshows.remove(koditvshow)
else:
self.logMsg("TVShows compare finished.", 1)
for kodiepisode in all_kodiepisodes:
if kodiepisode not in all_embyepisodesIds:
tvshows.remove(kodiepisode)
else:
self.logMsg("Episodes compare finished.", 1)
return True
def tvshows(self, embycursor, kodicursor, pdialog, compare=False):
# Get shows from emby
emby = self.emby
@ -1117,16 +1506,11 @@ class LibrarySync(threading.Thread):
for type in types:
if pdialog:
pdialog.update(
heading="Emby for Kodi",
message="Gathering %s..." % type)
pass
if compare:
# Manual Sync
if pdialog:
pdialog.update(
heading="Emby for Kodi",
message="Comparing %s..." % type)
pass
if type != "artists":
all_embyitems = process[type][0](basic=True)
@ -1165,7 +1549,7 @@ class LibrarySync(threading.Thread):
embyitems = all_embyitems['Items']
if pdialog:
pdialog.update(heading="Processing %s / %s items" % (type, total))
pass
count = 0
for embyitem in embyitems:

View file

@ -68,5 +68,6 @@
<setting id="restartMsg" type="bool" label="Enable server message when it's restarting" default="false" />
<setting id="newContent" type="bool" label="Enable new content notification" default="false" />
<setting label="30239" type="action" action="RunPlugin(plugin://plugin.video.plexkodiconnect?mode=reset)" option="close" />
<setting id="syncThreadNumber" type="number" label="Number of parallel threads while syncing" default="20" option="int"/>
</category>
</settings>