Merge remote-tracking branch 'MediaBrowser/master' into develop
This commit is contained in:
commit
9d50e8ef30
6 changed files with 166 additions and 42 deletions
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<addon id="plugin.video.plexkodiconnect"
|
||||
name="PlexKodiConnect"
|
||||
version="2.0.4"
|
||||
version="2.1.0"
|
||||
provider-name="croneter">
|
||||
<requires>
|
||||
<import addon="xbmc.python" version="2.1.0"/>
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
version 2.1.0
|
||||
- Add a throttle (automatically adjust the number of items requested at once) to prevent crashing during the initial sync
|
||||
- Do not update the video library when there's a music-only update
|
||||
|
||||
version 2.0.3
|
||||
- Add new retention time option that the latest server Sync plugin uses to help determine if full sync or inc sync should be used.
|
||||
- Add control over new content pop up display time. You will find the settings under Extras > Enable new content notification
|
||||
|
|
|
@ -100,6 +100,14 @@ class Main:
|
|||
if mode == "settings":
|
||||
xbmc.executebuiltin('Addon.OpenSettings(plugin.video.plexkodiconnect)')
|
||||
elif mode in ("manualsync", "repair"):
|
||||
if utils.window('emby_online') != "true":
|
||||
# Server is not online, do not run the sync
|
||||
xbmcgui.Dialog().ok(heading="Emby for Kodi",
|
||||
line1=("Unable to run the sync, the add-on is not "
|
||||
"connected to the Emby server."))
|
||||
utils.logMsg("EMBY", "Not connected to the emby server.", 1)
|
||||
return
|
||||
|
||||
if utils.window('emby_dbScan') != "true":
|
||||
import librarysync
|
||||
lib = librarysync.LibrarySync()
|
||||
|
|
|
@ -85,6 +85,7 @@ class Items(object):
|
|||
'Audio': Music
|
||||
}
|
||||
|
||||
update_videolibrary = False
|
||||
total = 0
|
||||
for item in items:
|
||||
total += len(items[item])
|
||||
|
@ -120,6 +121,7 @@ class Items(object):
|
|||
# Music is not enabled, do not proceed with itemtype
|
||||
continue
|
||||
else:
|
||||
update_videolibrary = True
|
||||
items_process = itemtypes[itemtype](embycursor, kodicursor)
|
||||
|
||||
if itemtype == "Movie":
|
||||
|
@ -214,10 +216,11 @@ class Items(object):
|
|||
|
||||
if musicconn is not None:
|
||||
# close connection for special types
|
||||
self.logMsg("Updating music database.", 1)
|
||||
musicconn.commit()
|
||||
musiccursor.close()
|
||||
|
||||
return True
|
||||
return (True, update_videolibrary)
|
||||
|
||||
def contentPop(self, name, time=5000):
|
||||
xbmcgui.Dialog().notification(
|
||||
|
|
|
@ -1016,6 +1016,117 @@ class LibrarySync(threading.Thread):
|
|||
|
||||
return True
|
||||
|
||||
# Reserved for websocket_client.py and fast start
|
||||
def triage_items(self, process, items):
|
||||
|
||||
processlist = {
|
||||
|
||||
'added': self.addedItems,
|
||||
'update': self.updateItems,
|
||||
'userdata': self.userdataItems,
|
||||
'remove': self.removeItems
|
||||
}
|
||||
if items:
|
||||
if process == "userdata":
|
||||
itemids = []
|
||||
for item in items:
|
||||
itemids.append(item['ItemId'])
|
||||
items = itemids
|
||||
|
||||
self.logMsg("Queue %s: %s" % (process, items), 1)
|
||||
processlist[process].extend(items)
|
||||
|
||||
def incrementalSync(self):
|
||||
|
||||
embyconn = utils.kodiSQL('emby')
|
||||
embycursor = embyconn.cursor()
|
||||
kodiconn = utils.kodiSQL('video')
|
||||
kodicursor = kodiconn.cursor()
|
||||
emby = self.emby
|
||||
emby_db = embydb.Embydb_Functions(embycursor)
|
||||
pDialog = None
|
||||
update_embydb = False
|
||||
|
||||
if self.refresh_views:
|
||||
# Received userconfig update
|
||||
self.refresh_views = False
|
||||
self.maintainViews(embycursor, kodicursor)
|
||||
self.forceLibraryUpdate = True
|
||||
update_embydb = True
|
||||
|
||||
if self.addedItems or self.updateItems or self.userdataItems or self.removeItems:
|
||||
# Only present dialog if we are going to process items
|
||||
pDialog = self.progressDialog('Incremental sync')
|
||||
|
||||
|
||||
process = {
|
||||
|
||||
'added': self.addedItems,
|
||||
'update': self.updateItems,
|
||||
'userdata': self.userdataItems,
|
||||
'remove': self.removeItems
|
||||
}
|
||||
types = ['added', 'update', 'userdata', 'remove']
|
||||
for type in types:
|
||||
|
||||
if process[type] and utils.window('emby_kodiScan') != "true":
|
||||
|
||||
listItems = list(process[type])
|
||||
del process[type][:] # Reset class list
|
||||
|
||||
items_process = itemtypes.Items(embycursor, kodicursor)
|
||||
update = False
|
||||
|
||||
# Prepare items according to process type
|
||||
if type == "added":
|
||||
items = emby.sortby_mediatype(listItems)
|
||||
|
||||
elif type in ("userdata", "remove"):
|
||||
items = emby_db.sortby_mediaType(listItems, unsorted=False)
|
||||
|
||||
else:
|
||||
items = emby_db.sortby_mediaType(listItems)
|
||||
if items.get('Unsorted'):
|
||||
sorted_items = emby.sortby_mediatype(items['Unsorted'])
|
||||
doupdate = items_process.itemsbyId(sorted_items, "added", pDialog)
|
||||
if doupdate:
|
||||
embyupdate, kodiupdate_video = doupdate
|
||||
if embyupdate:
|
||||
update_embydb = True
|
||||
if kodiupdate_video:
|
||||
self.forceLibraryUpdate = True
|
||||
del items['Unsorted']
|
||||
|
||||
doupdate = items_process.itemsbyId(items, type, pDialog)
|
||||
if doupdate:
|
||||
embyupdate, kodiupdate_video = doupdate
|
||||
if embyupdate:
|
||||
update_embydb = True
|
||||
if kodiupdate_video:
|
||||
self.forceLibraryUpdate = True
|
||||
|
||||
if update_embydb:
|
||||
update_embydb = False
|
||||
self.logMsg("Updating emby database.", 1)
|
||||
embyconn.commit()
|
||||
self.saveLastSync()
|
||||
|
||||
if self.forceLibraryUpdate:
|
||||
# Force update the Kodi library
|
||||
self.forceLibraryUpdate = False
|
||||
self.dbCommit(kodiconn)
|
||||
|
||||
self.logMsg("Updating video library.", 1)
|
||||
utils.window('emby_kodiScan', value="true")
|
||||
xbmc.executebuiltin('UpdateLibrary(video)')
|
||||
|
||||
if pDialog:
|
||||
pDialog.close()
|
||||
|
||||
kodicursor.close()
|
||||
embycursor.close()
|
||||
|
||||
|
||||
def compareDBVersion(self, current, minimum):
|
||||
# It returns True is database is up to date. False otherwise.
|
||||
self.logMsg("current: %s minimum: %s" % (current, minimum), 1)
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#################################################################################################
|
||||
|
||||
import xbmc
|
||||
|
||||
import utils
|
||||
import downloadutils
|
||||
|
||||
|
@ -15,7 +17,7 @@ class Read_EmbyServer():
|
|||
|
||||
def __init__(self):
|
||||
|
||||
self.doUtils = downloadutils.DownloadUtils()
|
||||
self.doUtils = downloadutils.DownloadUtils().downloadUrl
|
||||
|
||||
self.userId = utils.window('emby_currUser')
|
||||
self.server = utils.window('emby_server%s' % self.userId)
|
||||
|
@ -30,7 +32,7 @@ class Read_EmbyServer():
|
|||
item = {}
|
||||
|
||||
url = "{server}/emby/Users/{UserId}/Items/%s?format=json" % itemid
|
||||
result = self.doUtils.downloadUrl(url)
|
||||
result = self.doUtils(url)
|
||||
if result:
|
||||
item = result
|
||||
|
||||
|
@ -49,7 +51,7 @@ class Read_EmbyServer():
|
|||
'Ids': ",".join(itemlist),
|
||||
'Fields': "Etag"
|
||||
}
|
||||
result = self.doUtils.downloadUrl(url, parameters=params)
|
||||
result = self.doUtils(url, parameters=params)
|
||||
if result:
|
||||
items.extend(result['Items'])
|
||||
|
||||
|
@ -76,7 +78,7 @@ class Read_EmbyServer():
|
|||
"MediaSources"
|
||||
)
|
||||
}
|
||||
result = self.doUtils.downloadUrl(url, parameters=params)
|
||||
result = self.doUtils(url, parameters=params)
|
||||
if result:
|
||||
items.extend(result['Items'])
|
||||
|
||||
|
@ -86,7 +88,7 @@ class Read_EmbyServer():
|
|||
# Returns ancestors using embyId
|
||||
viewId = None
|
||||
url = "{server}/emby/Items/%s/Ancestors?UserId={UserId}&format=json" % itemid
|
||||
result = self.doUtils.downloadUrl(url)
|
||||
result = self.doUtils(url)
|
||||
|
||||
for view in result:
|
||||
|
||||
|
@ -138,7 +140,7 @@ class Read_EmbyServer():
|
|||
"CriticRating,CriticRatingSummary,Etag,ShortOverview,ProductionLocations,"
|
||||
"Tags,ProviderIds,ParentId,RemoteTrailers,SpecialEpisodeNumbers")
|
||||
}
|
||||
return doUtils.downloadUrl(url, parameters=params)
|
||||
return doUtils(url, parameters=params)
|
||||
|
||||
def getTvChannels(self):
|
||||
doUtils = self.doUtils
|
||||
|
@ -152,7 +154,7 @@ class Read_EmbyServer():
|
|||
"CriticRating,CriticRatingSummary,Etag,ShortOverview,ProductionLocations,"
|
||||
"Tags,ProviderIds,ParentId,RemoteTrailers,SpecialEpisodeNumbers")
|
||||
}
|
||||
return doUtils.downloadUrl(url, parameters=params)
|
||||
return doUtils(url, parameters=params)
|
||||
|
||||
def getTvRecordings(self, groupid):
|
||||
doUtils = self.doUtils
|
||||
|
@ -168,7 +170,7 @@ class Read_EmbyServer():
|
|||
"CriticRating,CriticRatingSummary,Etag,ShortOverview,ProductionLocations,"
|
||||
"Tags,ProviderIds,ParentId,RemoteTrailers,SpecialEpisodeNumbers")
|
||||
}
|
||||
return doUtils.downloadUrl(url, parameters=params)
|
||||
return doUtils(url, parameters=params)
|
||||
|
||||
def getSection(self, parentid, itemtype=None, sortby="SortName", basic=False, dialog=None):
|
||||
|
||||
|
@ -191,7 +193,7 @@ class Read_EmbyServer():
|
|||
'Recursive': True,
|
||||
'Limit': 1
|
||||
}
|
||||
result = doUtils.downloadUrl(url, parameters=params)
|
||||
result = doUtils(url, parameters=params)
|
||||
try:
|
||||
total = result['TotalRecordCount']
|
||||
items['TotalRecordCount'] = total
|
||||
|
@ -233,14 +235,16 @@ class Read_EmbyServer():
|
|||
"MediaSources"
|
||||
)
|
||||
result = doUtils(url, parameters=params)
|
||||
|
||||
if result == "":
|
||||
# Something happened to the connection.
|
||||
try:
|
||||
items['Items'].extend(result['Items'])
|
||||
except TypeError:
|
||||
# Something happened to the connection
|
||||
if not throttled:
|
||||
throttled = True
|
||||
self.logMsg("Throttle activated.", 1)
|
||||
elif jump == highestjump:
|
||||
# We already adjusted to highestjump, but it failed. Reset value
|
||||
|
||||
if jump == highestjump:
|
||||
# We already tried with the highestjump, but it failed. Reset value.
|
||||
self.logMsg("Reset highest value.", 1)
|
||||
highestjump = 0
|
||||
|
||||
|
@ -248,25 +252,24 @@ class Read_EmbyServer():
|
|||
if highestjump:
|
||||
throttled = False
|
||||
jump = highestjump
|
||||
self.logMsg("Throttle deactivated.", 1)
|
||||
else:
|
||||
jump = int(jump/2)
|
||||
jump = int(jump/4)
|
||||
self.logMsg("Set jump limit to recover: %s" % jump, 1)
|
||||
|
||||
self.logMsg("Set jump limit to recover: %s" % jump)
|
||||
retry = 0
|
||||
while utils.window('emby_online') != "true":
|
||||
# Wait server to come back online
|
||||
if retry == 3:
|
||||
self.logMsg("Server never came back online.")
|
||||
self.logMsg("Unable to reconnect to server. Abort process.", 1)
|
||||
return
|
||||
|
||||
|
||||
retry += 1
|
||||
if xbmc.Monitor().waitForAbort(1):
|
||||
# Abort was requested while waiting.
|
||||
return
|
||||
else:
|
||||
xbmc.Monitor().waitForAbort(3)
|
||||
else:
|
||||
items['Items'].extend(result['Items'])
|
||||
# Request succeeded
|
||||
index += jump
|
||||
|
||||
if dialog:
|
||||
|
@ -278,20 +281,15 @@ class Read_EmbyServer():
|
|||
highestjump = jump
|
||||
|
||||
if throttled:
|
||||
# We needed to adjust the number, keep increasing until.
|
||||
if jump < highestjump:
|
||||
# Found a number that already works, use it.
|
||||
throttled = False
|
||||
jump = highestjump
|
||||
self.logMsg("Throttle deactivated with jump limit set to: %s" % jump, 1)
|
||||
else:
|
||||
# keep increasing until the connection times out again
|
||||
increment = int(jump*0.33)
|
||||
if not increment: # Incase the increment is 0
|
||||
increment += 10
|
||||
# We needed to adjust the number of item requested.
|
||||
# keep increasing until the connection times out again
|
||||
# to find the highest value
|
||||
increment = int(jump*0.33)
|
||||
if not increment: # Incase the increment is 0
|
||||
increment = 10
|
||||
|
||||
jump += increment
|
||||
self.logMsg("Increase jump limit to: %s" % jump, 1)
|
||||
jump += increment
|
||||
self.logMsg("Increase jump limit to: %s" % jump, 1)
|
||||
return items
|
||||
|
||||
def getViews(self, type, root=False):
|
||||
|
@ -305,7 +303,7 @@ class Read_EmbyServer():
|
|||
else: # Views ungrouped
|
||||
url = "{server}/emby/Users/{UserId}/Items?Sortby=SortName&format=json"
|
||||
|
||||
result = doUtils.downloadUrl(url)
|
||||
result = doUtils(url)
|
||||
try:
|
||||
items = result['Items']
|
||||
|
||||
|
@ -330,7 +328,7 @@ class Read_EmbyServer():
|
|||
# Assumed missing is mixed then.
|
||||
if itemtype is None:
|
||||
url = "{server}/emby/Library/MediaFolders?format=json"
|
||||
result = doUtils.downloadUrl(url)
|
||||
result = doUtils(url)
|
||||
|
||||
for folder in result['Items']:
|
||||
if itemId == folder['Id']:
|
||||
|
@ -398,7 +396,7 @@ class Read_EmbyServer():
|
|||
'IsVirtualUnaired': False,
|
||||
'Fields': "Etag"
|
||||
}
|
||||
result = self.doUtils.downloadUrl(url, parameters=params)
|
||||
result = self.doUtils(url, parameters=params)
|
||||
if result:
|
||||
items = result
|
||||
|
||||
|
@ -438,7 +436,7 @@ class Read_EmbyServer():
|
|||
'Recursive': True,
|
||||
'Limit': 1
|
||||
}
|
||||
result = doUtils.downloadUrl(url, parameters=params)
|
||||
result = doUtils(url, parameters=params)
|
||||
try:
|
||||
total = result['TotalRecordCount']
|
||||
items['TotalRecordCount'] = total
|
||||
|
@ -468,7 +466,7 @@ class Read_EmbyServer():
|
|||
"AirTime,DateCreated,MediaStreams,People,ProviderIds,Overview"
|
||||
)
|
||||
}
|
||||
result = doUtils.downloadUrl(url, parameters=params)
|
||||
result = doUtils(url, parameters=params)
|
||||
items['Items'].extend(result['Items'])
|
||||
|
||||
index += jump
|
||||
|
@ -510,7 +508,7 @@ class Read_EmbyServer():
|
|||
}
|
||||
|
||||
url = "{server}/emby/Videos/%s/AdditionalParts?UserId={UserId}&format=json" % itemId
|
||||
result = self.doUtils.downloadUrl(url)
|
||||
result = self.doUtils(url)
|
||||
if result:
|
||||
items = result
|
||||
|
||||
|
|
Loading…
Reference in a new issue