Update for strings
This commit is contained in:
parent
0ba1ac4104
commit
52a5d35295
10 changed files with 477 additions and 389 deletions
|
@ -47,7 +47,7 @@ class LibrarySync(threading.Thread):
|
|||
|
||||
self.clientInfo = clientinfo.ClientInfo()
|
||||
self.addonName = self.clientInfo.getAddonName()
|
||||
self.doUtils = downloadutils.DownloadUtils()
|
||||
self.doUtils = downloadutils.DownloadUtils().downloadUrl
|
||||
self.user = userclient.UserClient()
|
||||
self.emby = embyserver.Read_EmbyServer()
|
||||
self.vnodes = videonodes.VideoNodes()
|
||||
|
@ -72,17 +72,19 @@ class LibrarySync(threading.Thread):
|
|||
return dialog
|
||||
|
||||
def startSync(self):
|
||||
|
||||
settings = utils.settings
|
||||
# Run at start up - optional to use the server plugin
|
||||
if utils.settings('SyncInstallRunDone') == "true":
|
||||
if settings('SyncInstallRunDone') == "true":
|
||||
|
||||
# Validate views
|
||||
self.refreshViews()
|
||||
completed = False
|
||||
# Verify if server plugin is installed.
|
||||
if utils.settings('serverSync') == "true":
|
||||
if settings('serverSync') == "true":
|
||||
# Try to use fast start up
|
||||
url = "{server}/emby/Plugins?format=json"
|
||||
result = self.doUtils.downloadUrl(url)
|
||||
result = self.doUtils(url)
|
||||
|
||||
for plugin in result:
|
||||
if plugin['Name'] == "Emby.Kodi Sync Queue":
|
||||
|
@ -100,30 +102,43 @@ class LibrarySync(threading.Thread):
|
|||
|
||||
def fastSync(self):
|
||||
|
||||
log = self.logMsg
|
||||
|
||||
doUtils = self.doUtils
|
||||
|
||||
lastSync = utils.settings('LastIncrementalSync')
|
||||
if not lastSync:
|
||||
lastSync = "2010-01-01T00:00:00Z"
|
||||
|
||||
lastSyncTime = utils.convertdate(lastSync)
|
||||
self.logMsg("Last sync run: %s" % lastSyncTime, 1)
|
||||
log("Last sync run: %s" % lastSyncTime, 1)
|
||||
|
||||
# get server RetentionDateTime
|
||||
url = "{server}/Emby.Kodi.SyncQueue/GetServerDateTime?format=json"
|
||||
result = self.doUtils.downloadUrl(url)
|
||||
result = doUtils(url)
|
||||
retention_time = "2010-01-01T00:00:00Z"
|
||||
if result and result.get('RetentionDateTime'):
|
||||
retention_time = result['RetentionDateTime']
|
||||
|
||||
#Try/except equivalent
|
||||
'''
|
||||
try:
|
||||
retention_time = result['RetentionDateTime']
|
||||
except (TypeError, KeyError):
|
||||
retention_time = "2010-01-01T00:00:00Z"
|
||||
'''
|
||||
|
||||
retention_time = utils.convertdate(retention_time)
|
||||
self.logMsg("RetentionDateTime: %s" % retention_time, 1)
|
||||
log("RetentionDateTime: %s" % retention_time, 1)
|
||||
|
||||
# if last sync before retention time do a full sync
|
||||
if retention_time > lastSyncTime:
|
||||
self.logMsg("Fast sync server retention insurficient, fall back to full sync", 1)
|
||||
log("Fast sync server retention insufficient, fall back to full sync", 1)
|
||||
return False
|
||||
|
||||
url = "{server}/emby/Emby.Kodi.SyncQueue/{UserId}/GetItems?format=json"
|
||||
params = {'LastUpdateDT': lastSync}
|
||||
result = self.doUtils.downloadUrl(url, parameters=params)
|
||||
result = doUtils(url, parameters=params)
|
||||
|
||||
try:
|
||||
processlist = {
|
||||
|
@ -135,36 +150,38 @@ class LibrarySync(threading.Thread):
|
|||
}
|
||||
|
||||
except (KeyError, TypeError):
|
||||
self.logMsg("Failed to retrieve latest updates using fast sync.", 1)
|
||||
log("Failed to retrieve latest updates using fast sync.", 1)
|
||||
return False
|
||||
|
||||
else:
|
||||
self.logMsg("Fast sync changes: %s" % result, 1)
|
||||
log("Fast sync changes: %s" % result, 1)
|
||||
for action in processlist:
|
||||
self.triage_items(action, processlist[action])
|
||||
|
||||
return True
|
||||
|
||||
def saveLastSync(self):
|
||||
|
||||
log = self.logMsg
|
||||
# Save last sync time
|
||||
overlap = 2
|
||||
|
||||
url = "{server}/Emby.Kodi.SyncQueue/GetServerDateTime?format=json"
|
||||
result = self.doUtils.downloadUrl(url)
|
||||
result = self.doUtils(url)
|
||||
try: # datetime fails when used more than once, TypeError
|
||||
server_time = result['ServerDateTime']
|
||||
server_time = utils.convertdate(server_time)
|
||||
|
||||
except Exception as e:
|
||||
# If the server plugin is not installed or an error happened.
|
||||
self.logMsg("An exception occurred: %s" % e, 1)
|
||||
log("An exception occurred: %s" % e, 1)
|
||||
time_now = datetime.utcnow()-timedelta(minutes=overlap)
|
||||
lastSync = time_now.strftime('%Y-%m-%dT%H:%M:%SZ')
|
||||
self.logMsg("New sync time: client time -%s min: %s" % (overlap, lastSync), 1)
|
||||
log("New sync time: client time -%s min: %s" % (overlap, lastSync), 1)
|
||||
|
||||
else:
|
||||
lastSync = (server_time - timedelta(minutes=overlap)).strftime('%Y-%m-%dT%H:%M:%SZ')
|
||||
self.logMsg("New sync time: server time -%s min: %s" % (overlap, lastSync), 1)
|
||||
log("New sync time: server time -%s min: %s" % (overlap, lastSync), 1)
|
||||
|
||||
finally:
|
||||
utils.settings('LastIncrementalSync', value=lastSync)
|
||||
|
@ -179,32 +196,39 @@ class LibrarySync(threading.Thread):
|
|||
return False
|
||||
|
||||
def dbCommit(self, connection):
|
||||
|
||||
log = self.logMsg
|
||||
window = utils.window
|
||||
# Central commit, verifies if Kodi database update is running
|
||||
kodidb_scan = utils.window('emby_kodiScan') == "true"
|
||||
kodidb_scan = window('emby_kodiScan') == "true"
|
||||
|
||||
while kodidb_scan:
|
||||
|
||||
self.logMsg("Kodi scan is running. Waiting...", 1)
|
||||
kodidb_scan = utils.window('emby_kodiScan') == "true"
|
||||
log("Kodi scan is running. Waiting...", 1)
|
||||
kodidb_scan = window('emby_kodiScan') == "true"
|
||||
|
||||
if self.shouldStop():
|
||||
self.logMsg("Commit unsuccessful. Sync terminated.", 1)
|
||||
log("Commit unsuccessful. Sync terminated.", 1)
|
||||
break
|
||||
|
||||
if self.monitor.waitForAbort(1):
|
||||
# Abort was requested while waiting. We should exit
|
||||
self.logMsg("Commit unsuccessful.", 1)
|
||||
log("Commit unsuccessful.", 1)
|
||||
break
|
||||
else:
|
||||
connection.commit()
|
||||
self.logMsg("Commit successful.", 1)
|
||||
log("Commit successful.", 1)
|
||||
|
||||
def fullSync(self, manualrun=False, repair=False):
|
||||
|
||||
log = self.logMsg
|
||||
window = utils.window
|
||||
settings = utils.settings
|
||||
# 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")
|
||||
window('emby_dbScan', value="true")
|
||||
# Add sources
|
||||
utils.sourcesXML()
|
||||
|
||||
|
@ -232,7 +256,7 @@ class LibrarySync(threading.Thread):
|
|||
message = "Repair sync"
|
||||
else:
|
||||
message = "Initial sync"
|
||||
utils.window('emby_initialScan', value="true")
|
||||
window('emby_initialScan', value="true")
|
||||
|
||||
pDialog = self.progressDialog("%s" % message, forced=True)
|
||||
starttotal = datetime.now()
|
||||
|
@ -253,7 +277,7 @@ class LibrarySync(threading.Thread):
|
|||
completed = process[itemtype](embycursor, kodicursor, pDialog)
|
||||
if not completed:
|
||||
|
||||
utils.window('emby_dbScan', clear=True)
|
||||
window('emby_dbScan', clear=True)
|
||||
if pDialog:
|
||||
pDialog.close()
|
||||
|
||||
|
@ -264,8 +288,7 @@ class LibrarySync(threading.Thread):
|
|||
self.dbCommit(kodiconn)
|
||||
embyconn.commit()
|
||||
elapsedTime = datetime.now() - startTime
|
||||
self.logMsg(
|
||||
"SyncDatabase (finished %s in: %s)"
|
||||
log("SyncDatabase (finished %s in: %s)"
|
||||
% (itemtype, str(elapsedTime).split('.')[0]), 1)
|
||||
else:
|
||||
# Close the Kodi cursor
|
||||
|
@ -281,7 +304,7 @@ class LibrarySync(threading.Thread):
|
|||
completed = self.music(embycursor, musiccursor, pDialog)
|
||||
if not completed:
|
||||
|
||||
utils.window('emby_dbScan', clear=True)
|
||||
window('emby_dbScan', clear=True)
|
||||
if pDialog:
|
||||
pDialog.close()
|
||||
|
||||
|
@ -292,8 +315,7 @@ class LibrarySync(threading.Thread):
|
|||
musicconn.commit()
|
||||
embyconn.commit()
|
||||
elapsedTime = datetime.now() - startTime
|
||||
self.logMsg(
|
||||
"SyncDatabase (finished music in: %s)"
|
||||
log("SyncDatabase (finished music in: %s)"
|
||||
% (str(elapsedTime).split('.')[0]), 1)
|
||||
musiccursor.close()
|
||||
|
||||
|
@ -302,18 +324,18 @@ class LibrarySync(threading.Thread):
|
|||
|
||||
embycursor.close()
|
||||
|
||||
utils.settings('SyncInstallRunDone', value="true")
|
||||
utils.settings("dbCreatedWithVersion", self.clientInfo.getVersion())
|
||||
settings('SyncInstallRunDone', value="true")
|
||||
settings("dbCreatedWithVersion", self.clientInfo.getVersion())
|
||||
self.saveLastSync()
|
||||
xbmc.executebuiltin('UpdateLibrary(video)')
|
||||
elapsedtotal = datetime.now() - starttotal
|
||||
|
||||
utils.window('emby_dbScan', clear=True)
|
||||
utils.window('emby_initialScan', clear=True)
|
||||
window('emby_dbScan', clear=True)
|
||||
window('emby_initialScan', clear=True)
|
||||
xbmcgui.Dialog().notification(
|
||||
heading="Emby for Kodi",
|
||||
message="%s completed in: %s" %
|
||||
(message, str(elapsedtotal).split('.')[0]),
|
||||
message="%s %s %s" %
|
||||
(message, utils.language(33025), str(elapsedtotal).split('.')[0]),
|
||||
icon="special://home/addons/plugin.video.emby/icon.png",
|
||||
sound=False)
|
||||
return True
|
||||
|
@ -336,6 +358,8 @@ class LibrarySync(threading.Thread):
|
|||
embycursor.close()
|
||||
|
||||
def maintainViews(self, embycursor, kodicursor):
|
||||
|
||||
log = self.logMsg
|
||||
# Compare the views to emby
|
||||
emby_db = embydb.Embydb_Functions(embycursor)
|
||||
kodi_db = kodidb.Kodidb_Functions(kodicursor)
|
||||
|
@ -344,14 +368,14 @@ class LibrarySync(threading.Thread):
|
|||
|
||||
# Get views
|
||||
url = "{server}/emby/Users/{UserId}/Views?format=json"
|
||||
result = doUtils.downloadUrl(url)
|
||||
result = doUtils(url)
|
||||
grouped_views = result['Items']
|
||||
|
||||
try:
|
||||
groupedFolders = self.user.userSettings['Configuration']['GroupedFolders']
|
||||
except TypeError:
|
||||
url = "{server}/emby/Users/{UserId}?format=json"
|
||||
result = doUtils.downloadUrl(url)
|
||||
result = doUtils(url)
|
||||
groupedFolders = result['Configuration']['GroupedFolders']
|
||||
|
||||
# total nodes for window properties
|
||||
|
@ -402,7 +426,7 @@ class LibrarySync(threading.Thread):
|
|||
emby_db.addView(folderid, foldername, viewtype, tagid)
|
||||
|
||||
else:
|
||||
self.logMsg(' '.join((
|
||||
log(' '.join((
|
||||
|
||||
"Found viewid: %s" % folderid,
|
||||
"viewname: %s" % current_viewname,
|
||||
|
@ -411,7 +435,7 @@ class LibrarySync(threading.Thread):
|
|||
|
||||
# View was modified, update with latest info
|
||||
if current_viewname != foldername:
|
||||
self.logMsg("viewid: %s new viewname: %s" % (folderid, foldername), 1)
|
||||
log("viewid: %s new viewname: %s" % (folderid, foldername), 1)
|
||||
tagid = kodi_db.createTag(foldername)
|
||||
|
||||
# Update view with new info
|
||||
|
@ -466,6 +490,9 @@ class LibrarySync(threading.Thread):
|
|||
utils.window('Emby.nodes.total', str(totalnodes))
|
||||
|
||||
def movies(self, embycursor, kodicursor, pdialog):
|
||||
|
||||
log = self.logMsg
|
||||
lang = utils.language
|
||||
# Get movies from emby
|
||||
emby = self.emby
|
||||
emby_db = embydb.Embydb_Functions(embycursor)
|
||||
|
@ -473,7 +500,7 @@ class LibrarySync(threading.Thread):
|
|||
|
||||
views = emby_db.getView_byType('movies')
|
||||
views += emby_db.getView_byType('mixed')
|
||||
self.logMsg("Media folders: %s" % views, 1)
|
||||
log("Media folders: %s" % views, 1)
|
||||
|
||||
##### PROCESS MOVIES #####
|
||||
for view in views:
|
||||
|
@ -488,7 +515,7 @@ class LibrarySync(threading.Thread):
|
|||
if pdialog:
|
||||
pdialog.update(
|
||||
heading="Emby for Kodi",
|
||||
message="Gathering movies from view: %s..." % viewName)
|
||||
message="%s %s..." % (lang(33017), viewName))
|
||||
|
||||
# Initial or repair sync
|
||||
all_embymovies = emby.getMovies(viewId, dialog=pdialog)
|
||||
|
@ -511,12 +538,12 @@ class LibrarySync(threading.Thread):
|
|||
count += 1
|
||||
movies.add_update(embymovie, viewName, viewId)
|
||||
else:
|
||||
self.logMsg("Movies finished.", 2)
|
||||
log("Movies finished.", 2)
|
||||
|
||||
|
||||
##### PROCESS BOXSETS #####
|
||||
if pdialog:
|
||||
pdialog.update(heading="Emby for Kodi", message="Gathering boxsets from server...")
|
||||
pdialog.update(heading="Emby for Kodi", message=lang(33018))
|
||||
|
||||
boxsets = emby.getBoxset(dialog=pdialog)
|
||||
total = boxsets['TotalRecordCount']
|
||||
|
@ -538,18 +565,20 @@ class LibrarySync(threading.Thread):
|
|||
count += 1
|
||||
movies.add_updateBoxset(boxset)
|
||||
else:
|
||||
self.logMsg("Boxsets finished.", 2)
|
||||
log("Boxsets finished.", 2)
|
||||
|
||||
return True
|
||||
|
||||
def musicvideos(self, embycursor, kodicursor, pdialog):
|
||||
|
||||
log = self.logMsg
|
||||
# Get musicvideos from emby
|
||||
emby = self.emby
|
||||
emby_db = embydb.Embydb_Functions(embycursor)
|
||||
mvideos = itemtypes.MusicVideos(embycursor, kodicursor)
|
||||
|
||||
views = emby_db.getView_byType('musicvideos')
|
||||
self.logMsg("Media folders: %s" % views, 1)
|
||||
log("Media folders: %s" % views, 1)
|
||||
|
||||
for view in views:
|
||||
|
||||
|
@ -563,7 +592,7 @@ class LibrarySync(threading.Thread):
|
|||
if pdialog:
|
||||
pdialog.update(
|
||||
heading="Emby for Kodi",
|
||||
message="Gathering musicvideos from view: %s..." % viewName)
|
||||
message="%s %s..." % (utils.language(33019), viewName))
|
||||
|
||||
# Initial or repair sync
|
||||
all_embymvideos = emby.getMusicVideos(viewId, dialog=pdialog)
|
||||
|
@ -586,11 +615,13 @@ class LibrarySync(threading.Thread):
|
|||
count += 1
|
||||
mvideos.add_update(embymvideo, viewName, viewId)
|
||||
else:
|
||||
self.logMsg("MusicVideos finished.", 2)
|
||||
log("MusicVideos finished.", 2)
|
||||
|
||||
return True
|
||||
|
||||
def tvshows(self, embycursor, kodicursor, pdialog):
|
||||
|
||||
log = self.logMsg
|
||||
# Get shows from emby
|
||||
emby = self.emby
|
||||
emby_db = embydb.Embydb_Functions(embycursor)
|
||||
|
@ -598,7 +629,7 @@ class LibrarySync(threading.Thread):
|
|||
|
||||
views = emby_db.getView_byType('tvshows')
|
||||
views += emby_db.getView_byType('mixed')
|
||||
self.logMsg("Media folders: %s" % views, 1)
|
||||
log("Media folders: %s" % views, 1)
|
||||
|
||||
for view in views:
|
||||
|
||||
|
@ -612,7 +643,7 @@ class LibrarySync(threading.Thread):
|
|||
if pdialog:
|
||||
pdialog.update(
|
||||
heading="Emby for Kodi",
|
||||
message="Gathering tvshows from view: %s..." % viewName)
|
||||
message="%s %s..." % (utils.language(33020), viewName))
|
||||
|
||||
all_embytvshows = emby.getShows(viewId, dialog=pdialog)
|
||||
total = all_embytvshows['TotalRecordCount']
|
||||
|
@ -648,7 +679,7 @@ class LibrarySync(threading.Thread):
|
|||
pdialog.update(percentage, message="%s - %s" % (title, episodetitle))
|
||||
tvshows.add_updateEpisode(episode)
|
||||
else:
|
||||
self.logMsg("TVShows finished.", 2)
|
||||
log("TVShows finished.", 2)
|
||||
|
||||
return True
|
||||
|
||||
|
@ -665,19 +696,19 @@ class LibrarySync(threading.Thread):
|
|||
'songs': [emby.getSongs, music.add_updateSong]
|
||||
}
|
||||
types = ['artists', 'albums', 'songs']
|
||||
for type in types:
|
||||
for itemtype in types:
|
||||
|
||||
if pdialog:
|
||||
pdialog.update(
|
||||
heading="Emby for Kodi",
|
||||
message="Gathering %s..." % type)
|
||||
message="%s %s..." % (utils.language(33021), itemtype))
|
||||
|
||||
all_embyitems = process[type][0](dialog=pdialog)
|
||||
all_embyitems = process[itemtype][0](dialog=pdialog)
|
||||
total = all_embyitems['TotalRecordCount']
|
||||
embyitems = all_embyitems['Items']
|
||||
|
||||
if pdialog:
|
||||
pdialog.update(heading="Processing %s / %s items" % (type, total))
|
||||
pdialog.update(heading="Processing %s / %s items" % (itemtype, total))
|
||||
|
||||
count = 0
|
||||
for embyitem in embyitems:
|
||||
|
@ -691,9 +722,9 @@ class LibrarySync(threading.Thread):
|
|||
pdialog.update(percentage, message=title)
|
||||
count += 1
|
||||
|
||||
process[type][1](embyitem)
|
||||
process[itemtype][1](embyitem)
|
||||
else:
|
||||
self.logMsg("%s finished." % type, 2)
|
||||
self.logMsg("%s finished." % itemtype, 2)
|
||||
|
||||
return True
|
||||
|
||||
|
@ -719,6 +750,8 @@ class LibrarySync(threading.Thread):
|
|||
|
||||
def incrementalSync(self):
|
||||
|
||||
log = self.logMsg
|
||||
|
||||
embyconn = utils.kodiSQL('emby')
|
||||
embycursor = embyconn.cursor()
|
||||
kodiconn = utils.kodiSQL('video')
|
||||
|
@ -788,7 +821,7 @@ class LibrarySync(threading.Thread):
|
|||
|
||||
if update_embydb:
|
||||
update_embydb = False
|
||||
self.logMsg("Updating emby database.", 1)
|
||||
log("Updating emby database.", 1)
|
||||
embyconn.commit()
|
||||
self.saveLastSync()
|
||||
|
||||
|
@ -797,7 +830,7 @@ class LibrarySync(threading.Thread):
|
|||
self.forceLibraryUpdate = False
|
||||
self.dbCommit(kodiconn)
|
||||
|
||||
self.logMsg("Updating video library.", 1)
|
||||
log("Updating video library.", 1)
|
||||
utils.window('emby_kodiScan', value="true")
|
||||
xbmc.executebuiltin('UpdateLibrary(video)')
|
||||
|
||||
|
@ -839,10 +872,16 @@ class LibrarySync(threading.Thread):
|
|||
|
||||
def run_internal(self):
|
||||
|
||||
log = self.logMsg
|
||||
lang = utils.language
|
||||
window = utils.window
|
||||
settings = utils.settings
|
||||
dialog = xbmcgui.Dialog()
|
||||
|
||||
startupComplete = False
|
||||
monitor = self.monitor
|
||||
|
||||
self.logMsg("---===### Starting LibrarySync ###===---", 0)
|
||||
log("---===### Starting LibrarySync ###===---", 0)
|
||||
|
||||
while not monitor.abortRequested():
|
||||
|
||||
|
@ -853,36 +892,24 @@ class LibrarySync(threading.Thread):
|
|||
# Abort was requested while waiting. We should exit
|
||||
break
|
||||
|
||||
if (utils.window('emby_dbCheck') != "true" and
|
||||
utils.settings('SyncInstallRunDone') == "true"):
|
||||
|
||||
if (window('emby_dbCheck') != "true" and settings('SyncInstallRunDone') == "true"):
|
||||
# Verify the validity of the database
|
||||
currentVersion = utils.settings('dbCreatedWithVersion')
|
||||
minVersion = utils.window('emby_minDBVersion')
|
||||
currentVersion = settings('dbCreatedWithVersion')
|
||||
minVersion = window('emby_minDBVersion')
|
||||
uptoDate = self.compareDBVersion(currentVersion, minVersion)
|
||||
|
||||
if not uptoDate:
|
||||
self.logMsg(
|
||||
"Db version out of date: %s minimum version required: %s"
|
||||
log("Database version out of date: %s minimum version required: %s"
|
||||
% (currentVersion, minVersion), 0)
|
||||
|
||||
resp = xbmcgui.Dialog().yesno(
|
||||
heading="Db Version",
|
||||
line1=(
|
||||
"Detected the database needs to be "
|
||||
"recreated for this version of Emby for Kodi. "
|
||||
"Proceed?"))
|
||||
resp = dialog.yesno("Emby for Kodi", lang(33022))
|
||||
if not resp:
|
||||
self.logMsg("Db version out of date! USER IGNORED!", 0)
|
||||
xbmcgui.Dialog().ok(
|
||||
heading="Emby for Kodi",
|
||||
line1=(
|
||||
"Emby for Kodi may not work correctly "
|
||||
"until the database is reset."))
|
||||
log("Database version is out of date! USER IGNORED!", 0)
|
||||
dialog.ok("Emby for Kodi", lang(33023))
|
||||
else:
|
||||
utils.reset()
|
||||
|
||||
utils.window('emby_dbCheck', value="true")
|
||||
window('emby_dbCheck', value="true")
|
||||
|
||||
|
||||
if not startupComplete:
|
||||
|
@ -890,58 +917,52 @@ class LibrarySync(threading.Thread):
|
|||
videoDb = utils.getKodiVideoDBPath()
|
||||
if not xbmcvfs.exists(videoDb):
|
||||
# Database does not exists
|
||||
self.logMsg(
|
||||
"The current Kodi version is incompatible "
|
||||
"with the Emby for Kodi add-on. Please visit "
|
||||
"https://github.com/MediaBrowser/Emby.Kodi/wiki "
|
||||
"to know which Kodi versions are supported.", 0)
|
||||
log(
|
||||
"The current Kodi version is incompatible "
|
||||
"with the Emby for Kodi add-on. Please visit "
|
||||
"https://github.com/MediaBrowser/Emby.Kodi/wiki "
|
||||
"to know which Kodi versions are supported.", 0)
|
||||
|
||||
xbmcgui.Dialog().ok(
|
||||
heading="Emby Warning",
|
||||
line1=(
|
||||
"Cancelling the database syncing process. "
|
||||
"Current Kodi versoin: %s is unsupported. "
|
||||
"Please verify your logs for more info."
|
||||
% xbmc.getInfoLabel('System.BuildVersion')))
|
||||
dialog.ok(
|
||||
heading="Emby for Kodi",
|
||||
line1=lang(33024))
|
||||
break
|
||||
|
||||
# Run start up sync
|
||||
self.logMsg("Db version: %s" % utils.settings('dbCreatedWithVersion'), 0)
|
||||
self.logMsg("SyncDatabase (started)", 1)
|
||||
log("Database version: %s" % settings('dbCreatedWithVersion'), 0)
|
||||
log("SyncDatabase (started)", 1)
|
||||
startTime = datetime.now()
|
||||
librarySync = self.startSync()
|
||||
elapsedTime = datetime.now() - startTime
|
||||
self.logMsg(
|
||||
"SyncDatabase (finished in: %s) %s"
|
||||
log("SyncDatabase (finished in: %s) %s"
|
||||
% (str(elapsedTime).split('.')[0], librarySync), 1)
|
||||
# Only try the initial sync once per kodi session regardless
|
||||
# This will prevent an infinite loop in case something goes wrong.
|
||||
startupComplete = True
|
||||
|
||||
# Process updates
|
||||
if utils.window('emby_dbScan') != "true":
|
||||
if window('emby_dbScan') != "true":
|
||||
self.incrementalSync()
|
||||
|
||||
if (utils.window('emby_onWake') == "true" and
|
||||
utils.window('emby_online') == "true"):
|
||||
if window('emby_onWake') == "true" and window('emby_online') == "true":
|
||||
# Kodi is waking up
|
||||
# Set in kodimonitor.py
|
||||
utils.window('emby_onWake', clear=True)
|
||||
if utils.window('emby_syncRunning') != "true":
|
||||
self.logMsg("SyncDatabase onWake (started)", 0)
|
||||
window('emby_onWake', clear=True)
|
||||
if window('emby_syncRunning') != "true":
|
||||
log("SyncDatabase onWake (started)", 0)
|
||||
librarySync = self.startSync()
|
||||
self.logMsg("SyncDatabase onWake (finished) %s" % librarySync, 0)
|
||||
log("SyncDatabase onWake (finished) %s" % librarySync, 0)
|
||||
|
||||
if self.stop_thread:
|
||||
# Set in service.py
|
||||
self.logMsg("Service terminated thread.", 2)
|
||||
log("Service terminated thread.", 2)
|
||||
break
|
||||
|
||||
if monitor.waitForAbort(1):
|
||||
# Abort was requested while waiting. We should exit
|
||||
break
|
||||
|
||||
self.logMsg("###===--- LibrarySync Stopped ---===###", 0)
|
||||
log("###===--- LibrarySync Stopped ---===###", 0)
|
||||
|
||||
def stopThread(self):
|
||||
self.stop_thread = True
|
||||
|
@ -966,6 +987,9 @@ class ManualSync(LibrarySync):
|
|||
|
||||
|
||||
def movies(self, embycursor, kodicursor, pdialog):
|
||||
|
||||
log = self.logMsg
|
||||
lang = utils.language
|
||||
# Get movies from emby
|
||||
emby = self.emby
|
||||
emby_db = embydb.Embydb_Functions(embycursor)
|
||||
|
@ -973,7 +997,7 @@ class ManualSync(LibrarySync):
|
|||
|
||||
views = emby_db.getView_byType('movies')
|
||||
views += emby_db.getView_byType('mixed')
|
||||
self.logMsg("Media folders: %s" % views, 1)
|
||||
log("Media folders: %s" % views, 1)
|
||||
|
||||
# Pull the list of movies and boxsets in Kodi
|
||||
try:
|
||||
|
@ -1003,7 +1027,7 @@ class ManualSync(LibrarySync):
|
|||
if pdialog:
|
||||
pdialog.update(
|
||||
heading="Emby for Kodi",
|
||||
message="Comparing movies from view: %s..." % viewName)
|
||||
message="%s %s..." % (lang(33026), viewName))
|
||||
|
||||
all_embymovies = emby.getMovies(viewId, basic=True, dialog=pdialog)
|
||||
for embymovie in all_embymovies['Items']:
|
||||
|
@ -1020,7 +1044,7 @@ class ManualSync(LibrarySync):
|
|||
# Only update if movie is not in Kodi or checksum is different
|
||||
updatelist.append(itemid)
|
||||
|
||||
self.logMsg("Movies to update for %s: %s" % (viewName, updatelist), 1)
|
||||
log("Movies to update for %s: %s" % (viewName, updatelist), 1)
|
||||
embymovies = emby.getFullItems(updatelist)
|
||||
total = len(updatelist)
|
||||
del updatelist[:]
|
||||
|
@ -1047,9 +1071,7 @@ class ManualSync(LibrarySync):
|
|||
embyboxsets = []
|
||||
|
||||
if pdialog:
|
||||
pdialog.update(
|
||||
heading="Emby for Kodi",
|
||||
message="Comparing boxsets...")
|
||||
pdialog.update("Emby for Kodi", lang(33027))
|
||||
|
||||
for boxset in boxsets['Items']:
|
||||
|
||||
|
@ -1066,7 +1088,7 @@ class ManualSync(LibrarySync):
|
|||
updatelist.append(itemid)
|
||||
embyboxsets.append(boxset)
|
||||
|
||||
self.logMsg("Boxsets to update: %s" % updatelist, 1)
|
||||
log("Boxsets to update: %s" % updatelist, 1)
|
||||
total = len(updatelist)
|
||||
|
||||
if pdialog:
|
||||
|
@ -1091,24 +1113,26 @@ class ManualSync(LibrarySync):
|
|||
if kodimovie not in all_embymoviesIds:
|
||||
movies.remove(kodimovie)
|
||||
else:
|
||||
self.logMsg("Movies compare finished.", 1)
|
||||
log("Movies compare finished.", 1)
|
||||
|
||||
for boxset in all_kodisets:
|
||||
if boxset not in all_embyboxsetsIds:
|
||||
movies.remove(boxset)
|
||||
else:
|
||||
self.logMsg("Boxsets compare finished.", 1)
|
||||
log("Boxsets compare finished.", 1)
|
||||
|
||||
return True
|
||||
|
||||
def musicvideos(self, embycursor, kodicursor, pdialog):
|
||||
|
||||
log = self.logMsg
|
||||
# Get musicvideos from emby
|
||||
emby = self.emby
|
||||
emby_db = embydb.Embydb_Functions(embycursor)
|
||||
mvideos = itemtypes.MusicVideos(embycursor, kodicursor)
|
||||
|
||||
views = emby_db.getView_byType('musicvideos')
|
||||
self.logMsg("Media folders: %s" % views, 1)
|
||||
log("Media folders: %s" % views, 1)
|
||||
|
||||
# Pull the list of musicvideos in Kodi
|
||||
try:
|
||||
|
@ -1131,7 +1155,7 @@ class ManualSync(LibrarySync):
|
|||
if pdialog:
|
||||
pdialog.update(
|
||||
heading="Emby for Kodi",
|
||||
message="Comparing musicvideos from view: %s..." % viewName)
|
||||
message="%s %s..." % (utils.language(33028), viewName))
|
||||
|
||||
all_embymvideos = emby.getMusicVideos(viewId, basic=True, dialog=pdialog)
|
||||
for embymvideo in all_embymvideos['Items']:
|
||||
|
@ -1148,7 +1172,7 @@ class ManualSync(LibrarySync):
|
|||
# Only update if musicvideo is not in Kodi or checksum is different
|
||||
updatelist.append(itemid)
|
||||
|
||||
self.logMsg("MusicVideos to update for %s: %s" % (viewName, updatelist), 1)
|
||||
log("MusicVideos to update for %s: %s" % (viewName, updatelist), 1)
|
||||
embymvideos = emby.getFullItems(updatelist)
|
||||
total = len(updatelist)
|
||||
del updatelist[:]
|
||||
|
@ -1176,11 +1200,14 @@ class ManualSync(LibrarySync):
|
|||
if kodimvideo not in all_embymvideosIds:
|
||||
mvideos.remove(kodimvideo)
|
||||
else:
|
||||
self.logMsg("MusicVideos compare finished.", 1)
|
||||
log("MusicVideos compare finished.", 1)
|
||||
|
||||
return True
|
||||
|
||||
def tvshows(self, embycursor, kodicursor, pdialog):
|
||||
|
||||
log = self.logMsg
|
||||
lang = utils.language
|
||||
# Get shows from emby
|
||||
emby = self.emby
|
||||
emby_db = embydb.Embydb_Functions(embycursor)
|
||||
|
@ -1188,7 +1215,7 @@ class ManualSync(LibrarySync):
|
|||
|
||||
views = emby_db.getView_byType('tvshows')
|
||||
views += emby_db.getView_byType('mixed')
|
||||
self.logMsg("Media folders: %s" % views, 1)
|
||||
log("Media folders: %s" % views, 1)
|
||||
|
||||
# Pull the list of tvshows and episodes in Kodi
|
||||
try:
|
||||
|
@ -1218,7 +1245,7 @@ class ManualSync(LibrarySync):
|
|||
if pdialog:
|
||||
pdialog.update(
|
||||
heading="Emby for Kodi",
|
||||
message="Comparing tvshows from view: %s..." % viewName)
|
||||
message="%s %s..." % (lang(33029), viewName))
|
||||
|
||||
all_embytvshows = emby.getShows(viewId, basic=True, dialog=pdialog)
|
||||
for embytvshow in all_embytvshows['Items']:
|
||||
|
@ -1235,7 +1262,7 @@ class ManualSync(LibrarySync):
|
|||
# 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)
|
||||
log("TVShows to update for %s: %s" % (viewName, updatelist), 1)
|
||||
embytvshows = emby.getFullItems(updatelist)
|
||||
total = len(updatelist)
|
||||
del updatelist[:]
|
||||
|
@ -1263,7 +1290,7 @@ class ManualSync(LibrarySync):
|
|||
if pdialog:
|
||||
pdialog.update(
|
||||
heading="Emby for Kodi",
|
||||
message="Comparing episodes from view: %s..." % viewName)
|
||||
message="%s %s..." % (lang(33030), viewName))
|
||||
|
||||
all_embyepisodes = emby.getEpisodes(viewId, basic=True, dialog=pdialog)
|
||||
for embyepisode in all_embyepisodes['Items']:
|
||||
|
@ -1279,7 +1306,7 @@ class ManualSync(LibrarySync):
|
|||
# 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)
|
||||
log("Episodes to update for %s: %s" % (viewName, updatelist), 1)
|
||||
embyepisodes = emby.getFullItems(updatelist)
|
||||
total = len(updatelist)
|
||||
del updatelist[:]
|
||||
|
@ -1305,17 +1332,19 @@ class ManualSync(LibrarySync):
|
|||
if koditvshow not in all_embytvshowsIds:
|
||||
tvshows.remove(koditvshow)
|
||||
else:
|
||||
self.logMsg("TVShows compare finished.", 1)
|
||||
log("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)
|
||||
log("Episodes compare finished.", 1)
|
||||
|
||||
return True
|
||||
|
||||
def music(self, embycursor, kodicursor, pdialog):
|
||||
|
||||
log = self.logMsg
|
||||
# Get music from emby
|
||||
emby = self.emby
|
||||
emby_db = embydb.Embydb_Functions(embycursor)
|
||||
|
@ -1354,7 +1383,7 @@ class ManualSync(LibrarySync):
|
|||
if pdialog:
|
||||
pdialog.update(
|
||||
heading="Emby for Kodi",
|
||||
message="Comparing %s..." % type)
|
||||
message="%s %s..." % (utils.language(33031), type))
|
||||
|
||||
if type != "artists":
|
||||
all_embyitems = process[type][0](basic=True, dialog=pdialog)
|
||||
|
@ -1383,7 +1412,7 @@ class ManualSync(LibrarySync):
|
|||
# Only update if songs is not in Kodi or checksum is different
|
||||
updatelist.append(itemid)
|
||||
|
||||
self.logMsg("%s to update: %s" % (type, updatelist), 1)
|
||||
log("%s to update: %s" % (type, updatelist), 1)
|
||||
embyitems = emby.getFullItems(updatelist)
|
||||
total = len(updatelist)
|
||||
del updatelist[:]
|
||||
|
@ -1411,18 +1440,18 @@ class ManualSync(LibrarySync):
|
|||
if kodiartist not in all_embyartistsIds and all_kodiartists[kodiartist] is not None:
|
||||
music.remove(kodiartist)
|
||||
else:
|
||||
self.logMsg("Artist compare finished.", 1)
|
||||
log("Artist compare finished.", 1)
|
||||
|
||||
for kodialbum in all_kodialbums:
|
||||
if kodialbum not in all_embyalbumsIds:
|
||||
music.remove(kodialbum)
|
||||
else:
|
||||
self.logMsg("Albums compare finished.", 1)
|
||||
log("Albums compare finished.", 1)
|
||||
|
||||
for kodisong in all_kodisongs:
|
||||
if kodisong not in all_embysongsIds:
|
||||
music.remove(kodisong)
|
||||
else:
|
||||
self.logMsg("Songs compare finished.", 1)
|
||||
log("Songs compare finished.", 1)
|
||||
|
||||
return True
|
|
@ -31,7 +31,7 @@ class PlaybackUtils():
|
|||
|
||||
self.clientInfo = clientinfo.ClientInfo()
|
||||
self.addonName = self.clientInfo.getAddonName()
|
||||
self.doUtils = downloadutils.DownloadUtils()
|
||||
self.doUtils = downloadutils.DownloadUtils().downloadUrl
|
||||
|
||||
self.userid = utils.window('emby_currUser')
|
||||
self.server = utils.window('emby_server%s' % self.userid)
|
||||
|
@ -48,7 +48,9 @@ class PlaybackUtils():
|
|||
|
||||
def play(self, itemid, dbid=None):
|
||||
|
||||
self.logMsg("Play called.", 1)
|
||||
log = self.logMsg
|
||||
window = utils.window
|
||||
settings = utils.settings
|
||||
|
||||
doUtils = self.doUtils
|
||||
item = self.item
|
||||
|
@ -56,6 +58,7 @@ class PlaybackUtils():
|
|||
listitem = xbmcgui.ListItem()
|
||||
playutils = putils.PlayUtils(item)
|
||||
|
||||
log("Play called.", 1)
|
||||
playurl = playutils.getPlayUrl()
|
||||
if not playurl:
|
||||
return xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, listitem)
|
||||
|
@ -74,13 +77,13 @@ class PlaybackUtils():
|
|||
sizePlaylist = playlist.size()
|
||||
currentPosition = startPos
|
||||
|
||||
propertiesPlayback = utils.window('emby_playbackProps') == "true"
|
||||
propertiesPlayback = window('emby_playbackProps') == "true"
|
||||
introsPlaylist = False
|
||||
dummyPlaylist = False
|
||||
|
||||
self.logMsg("Playlist start position: %s" % startPos, 1)
|
||||
self.logMsg("Playlist plugin position: %s" % currentPosition, 1)
|
||||
self.logMsg("Playlist size: %s" % sizePlaylist, 1)
|
||||
log("Playlist start position: %s" % startPos, 2)
|
||||
log("Playlist plugin position: %s" % currentPosition, 2)
|
||||
log("Playlist size: %s" % sizePlaylist, 2)
|
||||
|
||||
############### RESUME POINT ################
|
||||
|
||||
|
@ -91,13 +94,13 @@ class PlaybackUtils():
|
|||
# Otherwise we get a loop.
|
||||
if not propertiesPlayback:
|
||||
|
||||
utils.window('emby_playbackProps', value="true")
|
||||
self.logMsg("Setting up properties in playlist.", 1)
|
||||
window('emby_playbackProps', value="true")
|
||||
log("Setting up properties in playlist.", 1)
|
||||
|
||||
if (not homeScreen and not seektime and
|
||||
utils.window('emby_customPlaylist') != "true"):
|
||||
window('emby_customPlaylist') != "true"):
|
||||
|
||||
self.logMsg("Adding dummy file to playlist.", 2)
|
||||
log("Adding dummy file to playlist.", 2)
|
||||
dummyPlaylist = True
|
||||
playlist.add(playurl, listitem, index=startPos)
|
||||
# Remove the original item from playlist
|
||||
|
@ -108,27 +111,27 @@ class PlaybackUtils():
|
|||
|
||||
############### -- CHECK FOR INTROS ################
|
||||
|
||||
if utils.settings('enableCinema') == "true" and not seektime:
|
||||
if settings('enableCinema') == "true" and not seektime:
|
||||
# if we have any play them when the movie/show is not being resumed
|
||||
url = "{server}/emby/Users/{UserId}/Items/%s/Intros?format=json" % itemid
|
||||
intros = doUtils.downloadUrl(url)
|
||||
intros = doUtils(url)
|
||||
|
||||
if intros['TotalRecordCount'] != 0:
|
||||
getTrailers = True
|
||||
|
||||
if utils.settings('askCinema') == "true":
|
||||
resp = xbmcgui.Dialog().yesno("Emby Cinema Mode", "Play trailers?")
|
||||
if settings('askCinema') == "true":
|
||||
resp = xbmcgui.Dialog().yesno("Emby for Kodi", utils.language(33016))
|
||||
if not resp:
|
||||
# User selected to not play trailers
|
||||
getTrailers = False
|
||||
self.logMsg("Skip trailers.", 1)
|
||||
log("Skip trailers.", 1)
|
||||
|
||||
if getTrailers:
|
||||
for intro in intros['Items']:
|
||||
# The server randomly returns intros, process them.
|
||||
introListItem = xbmcgui.ListItem()
|
||||
introPlayurl = putils.PlayUtils(intro).getPlayUrl()
|
||||
self.logMsg("Adding Intro: %s" % introPlayurl, 1)
|
||||
log("Adding Intro: %s" % introPlayurl, 1)
|
||||
|
||||
# Set listitem and properties for intros
|
||||
pbutils = PlaybackUtils(intro)
|
||||
|
@ -144,7 +147,7 @@ class PlaybackUtils():
|
|||
if homeScreen and not seektime and not sizePlaylist:
|
||||
# Extend our current playlist with the actual item to play
|
||||
# only if there's no playlist first
|
||||
self.logMsg("Adding main item to playlist.", 1)
|
||||
log("Adding main item to playlist.", 1)
|
||||
self.pl.addtoPlaylist(dbid, item['Type'].lower())
|
||||
|
||||
# Ensure that additional parts are played after the main item
|
||||
|
@ -156,12 +159,12 @@ class PlaybackUtils():
|
|||
# Only add to the playlist after intros have played
|
||||
partcount = item['PartCount']
|
||||
url = "{server}/emby/Videos/%s/AdditionalParts?format=json" % itemid
|
||||
parts = doUtils.downloadUrl(url)
|
||||
parts = doUtils(url)
|
||||
for part in parts['Items']:
|
||||
|
||||
additionalListItem = xbmcgui.ListItem()
|
||||
additionalPlayurl = putils.PlayUtils(part).getPlayUrl()
|
||||
self.logMsg("Adding additional part: %s" % partcount, 1)
|
||||
log("Adding additional part: %s" % partcount, 1)
|
||||
|
||||
# Set listitem and properties for each additional parts
|
||||
pbutils = PlaybackUtils(part)
|
||||
|
@ -175,58 +178,60 @@ class PlaybackUtils():
|
|||
if dummyPlaylist:
|
||||
# Added a dummy file to the playlist,
|
||||
# because the first item is going to fail automatically.
|
||||
self.logMsg("Processed as a playlist. First item is skipped.", 1)
|
||||
log("Processed as a playlist. First item is skipped.", 1)
|
||||
return xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, listitem)
|
||||
|
||||
|
||||
# We just skipped adding properties. Reset flag for next time.
|
||||
elif propertiesPlayback:
|
||||
self.logMsg("Resetting properties playback flag.", 2)
|
||||
utils.window('emby_playbackProps', clear=True)
|
||||
log("Resetting properties playback flag.", 2)
|
||||
window('emby_playbackProps', clear=True)
|
||||
|
||||
#self.pl.verifyPlaylist()
|
||||
########## SETUP MAIN ITEM ##########
|
||||
|
||||
# For transcoding only, ask for audio/subs pref
|
||||
if utils.window('emby_%s.playmethod' % playurl) == "Transcode":
|
||||
if window('emby_%s.playmethod' % playurl) == "Transcode":
|
||||
playurl = playutils.audioSubsPref(playurl, listitem)
|
||||
utils.window('emby_%s.playmethod' % playurl, value="Transcode")
|
||||
window('emby_%s.playmethod' % playurl, value="Transcode")
|
||||
|
||||
listitem.setPath(playurl)
|
||||
self.setProperties(playurl, listitem)
|
||||
|
||||
############### PLAYBACK ################
|
||||
|
||||
if homeScreen and seektime and utils.window('emby_customPlaylist') != "true":
|
||||
self.logMsg("Play as a widget item.", 1)
|
||||
if homeScreen and seektime and window('emby_customPlaylist') != "true":
|
||||
log("Play as a widget item.", 1)
|
||||
self.setListItem(listitem)
|
||||
xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem)
|
||||
|
||||
elif ((introsPlaylist and utils.window('emby_customPlaylist') == "true") or
|
||||
(homeScreen and not sizePlaylist)):
|
||||
elif ((introsPlaylist and window('emby_customPlaylist') == "true") or
|
||||
(homeScreen and not sizePlaylist)):
|
||||
# Playlist was created just now, play it.
|
||||
self.logMsg("Play playlist.", 1)
|
||||
log("Play playlist.", 1)
|
||||
xbmc.Player().play(playlist, startpos=startPos)
|
||||
|
||||
else:
|
||||
self.logMsg("Play as a regular item.", 1)
|
||||
log("Play as a regular item.", 1)
|
||||
xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem)
|
||||
|
||||
def setProperties(self, playurl, listitem):
|
||||
|
||||
window = utils.window
|
||||
# Set all properties necessary for plugin path playback
|
||||
item = self.item
|
||||
itemid = item['Id']
|
||||
itemtype = item['Type']
|
||||
|
||||
embyitem = "emby_%s" % playurl
|
||||
utils.window('%s.runtime' % embyitem, value=str(item.get('RunTimeTicks')))
|
||||
utils.window('%s.type' % embyitem, value=itemtype)
|
||||
utils.window('%s.itemid' % embyitem, value=itemid)
|
||||
window('%s.runtime' % embyitem, value=str(item.get('RunTimeTicks')))
|
||||
window('%s.type' % embyitem, value=itemtype)
|
||||
window('%s.itemid' % embyitem, value=itemid)
|
||||
|
||||
if itemtype == "Episode":
|
||||
utils.window('%s.refreshid' % embyitem, value=item.get('SeriesId'))
|
||||
window('%s.refreshid' % embyitem, value=item.get('SeriesId'))
|
||||
else:
|
||||
utils.window('%s.refreshid' % embyitem, value=itemid)
|
||||
window('%s.refreshid' % embyitem, value=itemid)
|
||||
|
||||
# Append external subtitles to stream
|
||||
playmethod = utils.window('%s.playmethod' % embyitem)
|
||||
|
@ -316,7 +321,7 @@ class PlaybackUtils():
|
|||
def setListItem(self, listItem):
|
||||
|
||||
item = self.item
|
||||
type = item['Type']
|
||||
itemtype = item['Type']
|
||||
API = self.API
|
||||
people = API.getPeople()
|
||||
studios = API.getStudios()
|
||||
|
@ -336,7 +341,7 @@ class PlaybackUtils():
|
|||
'votes': item.get('VoteCount')
|
||||
}
|
||||
|
||||
if "Episode" in type:
|
||||
if "Episode" in itemtype:
|
||||
# Only for tv shows
|
||||
thumbId = item.get('SeriesId')
|
||||
season = item.get('ParentIndexNumber', -1)
|
||||
|
|
|
@ -32,7 +32,7 @@ class Player(xbmc.Player):
|
|||
|
||||
self.clientInfo = clientinfo.ClientInfo()
|
||||
self.addonName = self.clientInfo.getAddonName()
|
||||
self.doUtils = downloadutils.DownloadUtils()
|
||||
self.doUtils = downloadutils.DownloadUtils().downloadUrl
|
||||
self.ws = wsc.WebSocket_Client()
|
||||
self.xbmcplayer = xbmc.Player()
|
||||
|
||||
|
@ -47,7 +47,10 @@ class Player(xbmc.Player):
|
|||
def GetPlayStats(self):
|
||||
return self.playStats
|
||||
|
||||
def onPlayBackStarted( self ):
|
||||
def onPlayBackStarted(self):
|
||||
|
||||
log = self.logMsg
|
||||
window = utils.window
|
||||
# Will be called when xbmc starts playing a file
|
||||
xbmcplayer = self.xbmcplayer
|
||||
self.stopAll()
|
||||
|
@ -66,7 +69,7 @@ class Player(xbmc.Player):
|
|||
except: pass
|
||||
|
||||
if count == 5: # try 5 times
|
||||
self.logMsg("Cancelling playback report...", 1)
|
||||
log("Cancelling playback report...", 1)
|
||||
break
|
||||
else: count += 1
|
||||
|
||||
|
@ -76,36 +79,34 @@ class Player(xbmc.Player):
|
|||
self.currentFile = currentFile
|
||||
|
||||
# We may need to wait for info to be set in kodi monitor
|
||||
itemId = utils.window("emby_%s.itemid" % currentFile)
|
||||
itemId = window("emby_%s.itemid" % currentFile)
|
||||
tryCount = 0
|
||||
while not itemId:
|
||||
|
||||
xbmc.sleep(200)
|
||||
itemId = utils.window("emby_%s.itemid" % currentFile)
|
||||
itemId = window("emby_%s.itemid" % currentFile)
|
||||
if tryCount == 20: # try 20 times or about 10 seconds
|
||||
self.logMsg("Could not find itemId, cancelling playback report...", 1)
|
||||
log("Could not find itemId, cancelling playback report...", 1)
|
||||
break
|
||||
else: tryCount += 1
|
||||
|
||||
else:
|
||||
self.logMsg("ONPLAYBACK_STARTED: %s itemid: %s" % (currentFile, itemId), 0)
|
||||
log("ONPLAYBACK_STARTED: %s itemid: %s" % (currentFile, itemId), 0)
|
||||
|
||||
# Only proceed if an itemId was found.
|
||||
embyitem = "emby_%s" % currentFile
|
||||
runtime = utils.window("%s.runtime" % embyitem)
|
||||
refresh_id = utils.window("%s.refreshid" % embyitem)
|
||||
playMethod = utils.window("%s.playmethod" % embyitem)
|
||||
itemType = utils.window("%s.type" % embyitem)
|
||||
utils.window('emby_skipWatched%s' % itemId, value="true")
|
||||
runtime = window("%s.runtime" % embyitem)
|
||||
refresh_id = window("%s.refreshid" % embyitem)
|
||||
playMethod = window("%s.playmethod" % embyitem)
|
||||
itemType = window("%s.type" % embyitem)
|
||||
window('emby_skipWatched%s' % itemId, value="true")
|
||||
|
||||
|
||||
if (utils.window('emby_customPlaylist') == "true" and
|
||||
utils.window('emby_customPlaylist.seektime')):
|
||||
customseek = window('emby_customPlaylist.seektime')
|
||||
if window('emby_customPlaylist') == "true" and customseek:
|
||||
# Start at, when using custom playlist (play to Kodi from webclient)
|
||||
seektime = utils.window('emby_customPlaylist.seektime')
|
||||
self.logMsg("Seeking to: %s" % seektime, 1)
|
||||
xbmcplayer.seekTime(int(seektime)/10000000.0)
|
||||
utils.window('emby_customPlaylist.seektime', clear=True)
|
||||
log("Seeking to: %s" % customseek, 1)
|
||||
xbmcplayer.seekTime(int(customseek)/10000000.0)
|
||||
window('emby_customPlaylist.seektime', clear=True)
|
||||
|
||||
seekTime = xbmcplayer.getTime()
|
||||
|
||||
|
@ -144,9 +145,8 @@ class Player(xbmc.Player):
|
|||
# Get the current audio track and subtitles
|
||||
if playMethod == "Transcode":
|
||||
# property set in PlayUtils.py
|
||||
postdata['AudioStreamIndex'] = utils.window("%sAudioStreamIndex" % currentFile)
|
||||
postdata['SubtitleStreamIndex'] = utils.window("%sSubtitleStreamIndex"
|
||||
% currentFile)
|
||||
postdata['AudioStreamIndex'] = window("%sAudioStreamIndex" % currentFile)
|
||||
postdata['SubtitleStreamIndex'] = window("%sSubtitleStreamIndex" % currentFile)
|
||||
else:
|
||||
# Get the current kodi audio and subtitles and convert to Emby equivalent
|
||||
tracks_query = {
|
||||
|
@ -187,11 +187,11 @@ class Player(xbmc.Player):
|
|||
|
||||
# Number of audiotracks to help get Emby Index
|
||||
audioTracks = len(xbmc.Player().getAvailableAudioStreams())
|
||||
mapping = utils.window("%s.indexMapping" % embyitem)
|
||||
mapping = window("%s.indexMapping" % embyitem)
|
||||
|
||||
if mapping: # Set in playbackutils.py
|
||||
|
||||
self.logMsg("Mapping for external subtitles index: %s" % mapping, 2)
|
||||
log("Mapping for external subtitles index: %s" % mapping, 2)
|
||||
externalIndex = json.loads(mapping)
|
||||
|
||||
if externalIndex.get(str(indexSubs)):
|
||||
|
@ -209,15 +209,15 @@ class Player(xbmc.Player):
|
|||
|
||||
|
||||
# Post playback to server
|
||||
self.logMsg("Sending POST play started: %s." % postdata, 2)
|
||||
self.doUtils.downloadUrl(url, postBody=postdata, type="POST")
|
||||
log("Sending POST play started: %s." % postdata, 2)
|
||||
self.doUtils(url, postBody=postdata, type="POST")
|
||||
|
||||
# Ensure we do have a runtime
|
||||
try:
|
||||
runtime = int(runtime)
|
||||
except ValueError:
|
||||
runtime = xbmcplayer.getTotalTime()
|
||||
self.logMsg("Runtime is missing, Kodi runtime: %s" % runtime, 1)
|
||||
log("Runtime is missing, Kodi runtime: %s" % runtime, 1)
|
||||
|
||||
# Save data map for updates and position calls
|
||||
data = {
|
||||
|
@ -234,7 +234,7 @@ class Player(xbmc.Player):
|
|||
}
|
||||
|
||||
self.played_info[currentFile] = data
|
||||
self.logMsg("ADDING_FILE: %s" % self.played_info, 1)
|
||||
log("ADDING_FILE: %s" % self.played_info, 1)
|
||||
|
||||
# log some playback stats
|
||||
'''if(itemType != None):
|
||||
|
@ -253,7 +253,9 @@ class Player(xbmc.Player):
|
|||
|
||||
def reportPlayback(self):
|
||||
|
||||
self.logMsg("reportPlayback Called", 2)
|
||||
log = self.logMsg
|
||||
|
||||
log("reportPlayback Called", 2)
|
||||
xbmcplayer = self.xbmcplayer
|
||||
|
||||
# Get current file
|
||||
|
@ -281,7 +283,7 @@ class Player(xbmc.Player):
|
|||
|
||||
"properties": ["volume", "muted"]
|
||||
}
|
||||
}
|
||||
}
|
||||
result = xbmc.executeJSONRPC(json.dumps(volume_query))
|
||||
result = json.loads(result)
|
||||
result = result.get('result')
|
||||
|
@ -352,7 +354,7 @@ class Player(xbmc.Player):
|
|||
|
||||
if mapping: # Set in PlaybackUtils.py
|
||||
|
||||
self.logMsg("Mapping for external subtitles index: %s" % mapping, 2)
|
||||
log("Mapping for external subtitles index: %s" % mapping, 2)
|
||||
externalIndex = json.loads(mapping)
|
||||
|
||||
if externalIndex.get(str(indexSubs)):
|
||||
|
@ -372,7 +374,7 @@ class Player(xbmc.Player):
|
|||
|
||||
# Report progress via websocketclient
|
||||
postdata = json.dumps(postdata)
|
||||
self.logMsg("Report: %s" % postdata, 2)
|
||||
log("Report: %s" % postdata, 2)
|
||||
self.ws.sendProgressUpdate(postdata)
|
||||
|
||||
def onPlayBackPaused( self ):
|
||||
|
@ -407,12 +409,15 @@ class Player(xbmc.Player):
|
|||
self.reportPlayback()
|
||||
|
||||
def onPlayBackStopped( self ):
|
||||
|
||||
log = self.logMsg
|
||||
window = utils.window
|
||||
# Will be called when user stops xbmc playing a file
|
||||
self.logMsg("ONPLAYBACK_STOPPED", 2)
|
||||
utils.window('emby_customPlaylist', clear=True)
|
||||
utils.window('emby_customPlaylist.seektime', clear=True)
|
||||
utils.window('emby_playbackProps', clear=True)
|
||||
self.logMsg("Clear playlist properties.", 1)
|
||||
logMsg("ONPLAYBACK_STOPPED", 2)
|
||||
window('emby_customPlaylist', clear=True)
|
||||
window('emby_customPlaylist.seektime', clear=True)
|
||||
window('emby_playbackProps', clear=True)
|
||||
logMsg("Clear playlist properties.", 1)
|
||||
self.stopAll()
|
||||
|
||||
def onPlayBackEnded( self ):
|
||||
|
@ -423,20 +428,24 @@ class Player(xbmc.Player):
|
|||
|
||||
def stopAll(self):
|
||||
|
||||
log = self.logMsg
|
||||
lang = utils.language
|
||||
settings = utils.settings
|
||||
|
||||
doUtils = self.doUtils
|
||||
|
||||
if not self.played_info:
|
||||
return
|
||||
|
||||
self.logMsg("Played_information: %s" % self.played_info, 1)
|
||||
log("Played_information: %s" % self.played_info, 1)
|
||||
# Process each items
|
||||
for item in self.played_info:
|
||||
|
||||
data = self.played_info.get(item)
|
||||
if data:
|
||||
|
||||
self.logMsg("Item path: %s" % item, 2)
|
||||
self.logMsg("Item data: %s" % data, 2)
|
||||
log("Item path: %s" % item, 2)
|
||||
log("Item data: %s" % data, 2)
|
||||
|
||||
runtime = data['runtime']
|
||||
currentPosition = data['currentPosition']
|
||||
|
@ -453,9 +462,8 @@ class Player(xbmc.Player):
|
|||
# Runtime is 0.
|
||||
percentComplete = 0
|
||||
|
||||
markPlayedAt = float(utils.settings('markPlayed')) / 100
|
||||
self.logMsg(
|
||||
"Percent complete: %s Mark played at: %s"
|
||||
markPlayedAt = float(settings('markPlayed')) / 100
|
||||
log("Percent complete: %s Mark played at: %s"
|
||||
% (percentComplete, markPlayedAt), 1)
|
||||
|
||||
# Prevent manually mark as watched in Kodi monitor
|
||||
|
@ -464,34 +472,32 @@ class Player(xbmc.Player):
|
|||
self.stopPlayback(data)
|
||||
# Stop transcoding
|
||||
if playMethod == "Transcode":
|
||||
self.logMsg("Transcoding for %s terminated." % itemid, 1)
|
||||
log("Transcoding for %s terminated." % itemid, 1)
|
||||
deviceId = self.clientInfo.getDeviceId()
|
||||
url = "{server}/emby/Videos/ActiveEncodings?DeviceId=%s" % deviceId
|
||||
doUtils.downloadUrl(url, type="DELETE")
|
||||
doUtils(url, type="DELETE")
|
||||
|
||||
# Send the delete action to the server.
|
||||
offerDelete = False
|
||||
|
||||
if type == "Episode" and utils.settings('deleteTV') == "true":
|
||||
if type == "Episode" and settings('deleteTV') == "true":
|
||||
offerDelete = True
|
||||
elif type == "Movie" and utils.settings('deleteMovies') == "true":
|
||||
elif type == "Movie" and settings('deleteMovies') == "true":
|
||||
offerDelete = True
|
||||
|
||||
if utils.settings('offerDelete') != "true":
|
||||
if settings('offerDelete') != "true":
|
||||
# Delete could be disabled, even if the subsetting is enabled.
|
||||
offerDelete = False
|
||||
|
||||
if percentComplete >= markPlayedAt and offerDelete:
|
||||
resp = xbmcgui.Dialog().yesno(
|
||||
heading="Confirm delete",
|
||||
line1="Delete file on Emby Server?")
|
||||
resp = xbmcgui.Dialog().yesno(lang(30091), lang(33015))
|
||||
if not resp:
|
||||
self.logMsg("User skipped deletion.", 1)
|
||||
log("User skipped deletion.", 1)
|
||||
continue
|
||||
|
||||
url = "{server}/emby/Items/%s?format=json" % itemid
|
||||
self.logMsg("Deleting request: %s" % itemid)
|
||||
doUtils.downloadUrl(url, type="DELETE")
|
||||
log("Deleting request: %s" % itemid, 1)
|
||||
doUtils(url, type="DELETE")
|
||||
|
||||
self.played_info.clear()
|
||||
|
||||
|
@ -510,4 +516,4 @@ class Player(xbmc.Player):
|
|||
'MediaSourceId': itemId,
|
||||
'PositionTicks': positionTicks
|
||||
}
|
||||
self.doUtils.downloadUrl(url, postBody=postdata, type="POST")
|
||||
self.doUtils(url, postBody=postdata, type="POST")
|
|
@ -39,6 +39,9 @@ class Playlist():
|
|||
|
||||
def playAll(self, itemids, startat):
|
||||
|
||||
log = self.logMsg
|
||||
window = utils.window
|
||||
|
||||
embyconn = utils.kodiSQL('emby')
|
||||
embycursor = embyconn.cursor()
|
||||
emby_db = embydb.Embydb_Functions(embycursor)
|
||||
|
@ -47,15 +50,15 @@ class Playlist():
|
|||
playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
|
||||
playlist.clear()
|
||||
|
||||
self.logMsg("---*** PLAY ALL ***---", 1)
|
||||
self.logMsg("Items: %s and start at: %s" % (itemids, startat))
|
||||
log("---*** PLAY ALL ***---", 1)
|
||||
log("Items: %s and start at: %s" % (itemids, startat), 1)
|
||||
|
||||
started = False
|
||||
utils.window('emby_customplaylist', value="true")
|
||||
window('emby_customplaylist', value="true")
|
||||
|
||||
if startat != 0:
|
||||
# Seek to the starting position
|
||||
utils.window('emby_customplaylist.seektime', str(startat))
|
||||
window('emby_customplaylist.seektime', str(startat))
|
||||
|
||||
for itemid in itemids:
|
||||
embydb_item = emby_db.getItem_byId(itemid)
|
||||
|
@ -64,14 +67,14 @@ class Playlist():
|
|||
mediatype = embydb_item[4]
|
||||
except TypeError:
|
||||
# Item is not found in our database, add item manually
|
||||
self.logMsg("Item was not found in the database, manually adding item.", 1)
|
||||
log("Item was not found in the database, manually adding item.", 1)
|
||||
item = self.emby.getItem(itemid)
|
||||
self.addtoPlaylist_xbmc(playlist, item)
|
||||
else:
|
||||
# Add to playlist
|
||||
self.addtoPlaylist(dbid, mediatype)
|
||||
|
||||
self.logMsg("Adding %s to playlist." % itemid, 1)
|
||||
log("Adding %s to playlist." % itemid, 1)
|
||||
|
||||
if not started:
|
||||
started = True
|
||||
|
@ -82,12 +85,14 @@ class Playlist():
|
|||
|
||||
def modifyPlaylist(self, itemids):
|
||||
|
||||
log = self.logMsg
|
||||
|
||||
embyconn = utils.kodiSQL('emby')
|
||||
embycursor = embyconn.cursor()
|
||||
emby_db = embydb.Embydb_Functions(embycursor)
|
||||
|
||||
self.logMsg("---*** ADD TO PLAYLIST ***---", 1)
|
||||
self.logMsg("Items: %s" % itemids, 1)
|
||||
log("---*** ADD TO PLAYLIST ***---", 1)
|
||||
log("Items: %s" % itemids, 1)
|
||||
|
||||
player = xbmc.Player()
|
||||
playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
|
||||
|
@ -105,7 +110,7 @@ class Playlist():
|
|||
# Add to playlist
|
||||
self.addtoPlaylist(dbid, mediatype)
|
||||
|
||||
self.logMsg("Adding %s to playlist." % itemid, 1)
|
||||
log("Adding %s to playlist." % itemid, 1)
|
||||
|
||||
self.verifyPlaylist()
|
||||
embycursor.close()
|
||||
|
|
|
@ -33,43 +33,46 @@ class PlayUtils():
|
|||
|
||||
def getPlayUrl(self):
|
||||
|
||||
log = self.logMsg
|
||||
window = utils.window
|
||||
|
||||
item = self.item
|
||||
playurl = None
|
||||
|
||||
if (item.get('Type') in ("Recording", "TvChannel") and
|
||||
item.get('MediaSources') and item['MediaSources'][0]['Protocol'] == "Http"):
|
||||
# Play LiveTV or recordings
|
||||
self.logMsg("File protocol is http (livetv).", 1)
|
||||
log("File protocol is http (livetv).", 1)
|
||||
playurl = "%s/emby/Videos/%s/live.m3u8?static=true" % (self.server, item['Id'])
|
||||
utils.window('emby_%s.playmethod' % playurl, value="Transcode")
|
||||
window('emby_%s.playmethod' % playurl, value="Transcode")
|
||||
|
||||
elif item.get('MediaSources') and item['MediaSources'][0]['Protocol'] == "Http":
|
||||
# Only play as http, used for channels, or online hosting of content
|
||||
self.logMsg("File protocol is http.", 1)
|
||||
log("File protocol is http.", 1)
|
||||
playurl = self.httpPlay()
|
||||
utils.window('emby_%s.playmethod' % playurl, value="DirectStream")
|
||||
window('emby_%s.playmethod' % playurl, value="DirectStream")
|
||||
|
||||
elif self.isDirectPlay():
|
||||
|
||||
self.logMsg("File is direct playing.", 1)
|
||||
log("File is direct playing.", 1)
|
||||
playurl = self.directPlay()
|
||||
playurl = playurl.encode('utf-8')
|
||||
# Set playmethod property
|
||||
utils.window('emby_%s.playmethod' % playurl, value="DirectPlay")
|
||||
window('emby_%s.playmethod' % playurl, value="DirectPlay")
|
||||
|
||||
elif self.isDirectStream():
|
||||
|
||||
self.logMsg("File is direct streaming.", 1)
|
||||
log("File is direct streaming.", 1)
|
||||
playurl = self.directStream()
|
||||
# Set playmethod property
|
||||
utils.window('emby_%s.playmethod' % playurl, value="DirectStream")
|
||||
window('emby_%s.playmethod' % playurl, value="DirectStream")
|
||||
|
||||
elif self.isTranscoding():
|
||||
|
||||
self.logMsg("File is transcoding.", 1)
|
||||
log("File is transcoding.", 1)
|
||||
playurl = self.transcoding()
|
||||
# Set playmethod property
|
||||
utils.window('emby_%s.playmethod' % playurl, value="Transcode")
|
||||
window('emby_%s.playmethod' % playurl, value="Transcode")
|
||||
|
||||
return playurl
|
||||
|
||||
|
@ -90,16 +93,21 @@ class PlayUtils():
|
|||
|
||||
def isDirectPlay(self):
|
||||
|
||||
log = self.logMsg
|
||||
lang = utils.language
|
||||
settings = utils.settings
|
||||
dialog = xbmcgui.Dialog()
|
||||
|
||||
item = self.item
|
||||
|
||||
# Requirement: Filesystem, Accessible path
|
||||
if utils.settings('playFromStream') == "true":
|
||||
if settings('playFromStream') == "true":
|
||||
# User forcing to play via HTTP
|
||||
self.logMsg("Can't direct play, play from HTTP enabled.", 1)
|
||||
log("Can't direct play, play from HTTP enabled.", 1)
|
||||
return False
|
||||
|
||||
videotrack = item['MediaSources'][0]['Name']
|
||||
transcodeH265 = utils.settings('transcodeH265')
|
||||
transcodeH265 = settings('transcodeH265')
|
||||
|
||||
if transcodeH265 in ("1", "2", "3") and ("HEVC" in videotrack or "H265" in videotrack):
|
||||
# Avoid H265/HEVC depending on the resolution
|
||||
|
@ -110,46 +118,45 @@ class PlayUtils():
|
|||
'2': 720,
|
||||
'3': 1080
|
||||
}
|
||||
self.logMsg("Resolution is: %sP, transcode for resolution: %sP+"
|
||||
% (resolution, res[transcodeH265]), 1)
|
||||
log("Resolution is: %sP, transcode for resolution: %sP+"
|
||||
% (resolution, res[transcodeH265]), 1)
|
||||
if res[transcodeH265] <= resolution:
|
||||
return False
|
||||
|
||||
canDirectPlay = item['MediaSources'][0]['SupportsDirectPlay']
|
||||
# Make sure direct play is supported by the server
|
||||
if not canDirectPlay:
|
||||
self.logMsg("Can't direct play, server doesn't allow/support it.", 1)
|
||||
log("Can't direct play, server doesn't allow/support it.", 1)
|
||||
return False
|
||||
|
||||
location = item['LocationType']
|
||||
if location == "FileSystem":
|
||||
# Verify the path
|
||||
if not self.fileExists():
|
||||
self.logMsg("Unable to direct play.")
|
||||
log("Unable to direct play.")
|
||||
try:
|
||||
count = int(utils.settings('failCount'))
|
||||
count = int(settings('failCount'))
|
||||
except ValueError:
|
||||
count = 0
|
||||
self.logMsg("Direct play failed: %s times." % count, 1)
|
||||
log("Direct play failed: %s times." % count, 1)
|
||||
|
||||
if count < 2:
|
||||
# Let the user know that direct play failed
|
||||
utils.settings('failCount', value=str(count+1))
|
||||
xbmcgui.Dialog().notification(
|
||||
heading="Emby server",
|
||||
message="Unable to direct play.",
|
||||
icon="special://home/addons/plugin.video.emby/icon.png",
|
||||
sound=False)
|
||||
elif utils.settings('playFromStream') != "true":
|
||||
settings('failCount', value=str(count+1))
|
||||
dialog.notification(
|
||||
heading="Emby for Kodi",
|
||||
message=lang(33011),
|
||||
icon="special://home/addons/plugin.video.emby/icon.png",
|
||||
sound=False)
|
||||
elif settings('playFromStream') != "true":
|
||||
# Permanently set direct stream as true
|
||||
utils.settings('playFromStream', value="true")
|
||||
utils.settings('failCount', value="0")
|
||||
xbmcgui.Dialog().notification(
|
||||
heading="Emby server",
|
||||
message=("Direct play failed 3 times. Enabled play "
|
||||
"from HTTP in the add-on settings."),
|
||||
icon="special://home/addons/plugin.video.emby/icon.png",
|
||||
sound=False)
|
||||
settings('playFromStream', value="true")
|
||||
settings('failCount', value="0")
|
||||
dialog.notification(
|
||||
heading="Emby for Kodi",
|
||||
message=lang(33012),
|
||||
icon="special://home/addons/plugin.video.emby/icon.png",
|
||||
sound=False)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
@ -185,28 +192,32 @@ class PlayUtils():
|
|||
|
||||
def fileExists(self):
|
||||
|
||||
log = self.logMsg
|
||||
|
||||
if 'Path' not in self.item:
|
||||
# File has no path defined in server
|
||||
return False
|
||||
|
||||
# Convert path to direct play
|
||||
path = self.directPlay()
|
||||
self.logMsg("Verifying path: %s" % path, 1)
|
||||
log("Verifying path: %s" % path, 1)
|
||||
|
||||
if xbmcvfs.exists(path):
|
||||
self.logMsg("Path exists.", 1)
|
||||
log("Path exists.", 1)
|
||||
return True
|
||||
|
||||
elif ":" not in path:
|
||||
self.logMsg("Can't verify path, assumed linux. Still try to direct play.", 1)
|
||||
log("Can't verify path, assumed linux. Still try to direct play.", 1)
|
||||
return True
|
||||
|
||||
else:
|
||||
self.logMsg("Failed to find file.")
|
||||
log("Failed to find file.", 1)
|
||||
return False
|
||||
|
||||
def isDirectStream(self):
|
||||
|
||||
log = self.logMsg
|
||||
|
||||
item = self.item
|
||||
|
||||
videotrack = item['MediaSources'][0]['Name']
|
||||
|
@ -221,8 +232,8 @@ class PlayUtils():
|
|||
'2': 720,
|
||||
'3': 1080
|
||||
}
|
||||
self.logMsg("Resolution is: %sP, transcode for resolution: %sP+"
|
||||
% (resolution, res[transcodeH265]), 1)
|
||||
log("Resolution is: %sP, transcode for resolution: %sP+"
|
||||
% (resolution, res[transcodeH265]), 1)
|
||||
if res[transcodeH265] <= resolution:
|
||||
return False
|
||||
|
||||
|
@ -234,7 +245,7 @@ class PlayUtils():
|
|||
|
||||
# Verify the bitrate
|
||||
if not self.isNetworkSufficient():
|
||||
self.logMsg("The network speed is insufficient to direct stream file.", 1)
|
||||
log("The network speed is insufficient to direct stream file.", 1)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
@ -245,12 +256,12 @@ class PlayUtils():
|
|||
server = self.server
|
||||
|
||||
itemid = item['Id']
|
||||
type = item['Type']
|
||||
itemtype = item['Type']
|
||||
|
||||
if 'Path' in item and item['Path'].endswith('.strm'):
|
||||
# Allow strm loading when direct streaming
|
||||
playurl = self.directPlay()
|
||||
elif type == "Audio":
|
||||
elif itemtype == "Audio":
|
||||
playurl = "%s/emby/Audio/%s/stream.mp3" % (server, itemid)
|
||||
else:
|
||||
playurl = "%s/emby/Videos/%s/stream?static=true" % (server, itemid)
|
||||
|
@ -259,15 +270,17 @@ class PlayUtils():
|
|||
|
||||
def isNetworkSufficient(self):
|
||||
|
||||
log = self.logMsg
|
||||
|
||||
settings = self.getBitrate()*1000
|
||||
|
||||
try:
|
||||
sourceBitrate = int(self.item['MediaSources'][0]['Bitrate'])
|
||||
except (KeyError, TypeError):
|
||||
self.logMsg("Bitrate value is missing.", 1)
|
||||
log("Bitrate value is missing.", 1)
|
||||
else:
|
||||
self.logMsg("The add-on settings bitrate is: %s, the video bitrate required is: %s"
|
||||
% (settings, sourceBitrate), 1)
|
||||
log("The add-on settings bitrate is: %s, the video bitrate required is: %s"
|
||||
% (settings, sourceBitrate), 1)
|
||||
if settings < sourceBitrate:
|
||||
return False
|
||||
|
||||
|
@ -335,6 +348,10 @@ class PlayUtils():
|
|||
return bitrate.get(videoQuality, 2147483)
|
||||
|
||||
def audioSubsPref(self, url, listitem):
|
||||
|
||||
log = self.logMsg
|
||||
lang = utils.language
|
||||
dialog = xbmcgui.Dialog()
|
||||
# For transcoding only
|
||||
# Present the list of audio to select from
|
||||
audioStreamsList = {}
|
||||
|
@ -373,8 +390,6 @@ class PlayUtils():
|
|||
audioStreams.append(track)
|
||||
|
||||
elif 'Subtitle' in type:
|
||||
'''if stream['IsExternal']:
|
||||
continue'''
|
||||
try:
|
||||
track = "%s - %s" % (index, stream['Language'])
|
||||
except:
|
||||
|
@ -396,7 +411,7 @@ class PlayUtils():
|
|||
|
||||
|
||||
if len(audioStreams) > 1:
|
||||
resp = xbmcgui.Dialog().select("Choose the audio stream", audioStreams)
|
||||
resp = dialog.select(lang(33013), audioStreams)
|
||||
if resp > -1:
|
||||
# User selected audio
|
||||
selected = audioStreams[resp]
|
||||
|
@ -409,7 +424,7 @@ class PlayUtils():
|
|||
playurlprefs += "&AudioStreamIndex=%s" % selectAudioIndex
|
||||
|
||||
if len(subtitleStreams) > 1:
|
||||
resp = xbmcgui.Dialog().select("Choose the subtitle stream", subtitleStreams)
|
||||
resp = dialog.select(lang(33014), subtitleStreams)
|
||||
if resp == 0:
|
||||
# User selected no subtitles
|
||||
pass
|
||||
|
@ -424,7 +439,7 @@ class PlayUtils():
|
|||
itemid = item['Id']
|
||||
url = [("%s/Videos/%s/%s/Subtitles/%s/Stream.srt"
|
||||
% (self.server, itemid, itemid, selectSubsIndex))]
|
||||
self.logMsg("Set up subtitles: %s %s" % (selectSubsIndex, url), 1)
|
||||
log("Set up subtitles: %s %s" % (selectSubsIndex, url), 1)
|
||||
listitem.setSubtitles(url)
|
||||
else:
|
||||
# Burn subtitles
|
||||
|
|
|
@ -18,12 +18,14 @@ class Read_EmbyServer():
|
|||
|
||||
def __init__(self):
|
||||
|
||||
window = utils.window
|
||||
|
||||
self.clientInfo = clientinfo.ClientInfo()
|
||||
self.addonName = self.clientInfo.getAddonName()
|
||||
self.doUtils = downloadutils.DownloadUtils().downloadUrl
|
||||
|
||||
self.userId = utils.window('emby_currUser')
|
||||
self.server = utils.window('emby_server%s' % self.userId)
|
||||
self.userId = window('emby_currUser')
|
||||
self.server = window('emby_server%s' % self.userId)
|
||||
|
||||
def logMsg(self, msg, lvl=1):
|
||||
|
||||
|
@ -183,6 +185,8 @@ class Read_EmbyServer():
|
|||
|
||||
def getSection(self, parentid, itemtype=None, sortby="SortName", basic=False, dialog=None):
|
||||
|
||||
log = self.logMsg
|
||||
|
||||
doUtils = self.doUtils
|
||||
items = {
|
||||
|
||||
|
@ -208,7 +212,7 @@ class Read_EmbyServer():
|
|||
items['TotalRecordCount'] = total
|
||||
|
||||
except TypeError: # Failed to retrieve
|
||||
self.logMsg("%s:%s Failed to retrieve the server response." % (url, params), 2)
|
||||
log("%s:%s Failed to retrieve the server response." % (url, params), 2)
|
||||
|
||||
else:
|
||||
index = 0
|
||||
|
@ -250,27 +254,27 @@ class Read_EmbyServer():
|
|||
# Something happened to the connection
|
||||
if not throttled:
|
||||
throttled = True
|
||||
self.logMsg("Throttle activated.", 1)
|
||||
log("Throttle activated.", 1)
|
||||
|
||||
if jump == highestjump:
|
||||
# We already tried with the highestjump, but it failed. Reset value.
|
||||
self.logMsg("Reset highest value.", 1)
|
||||
log("Reset highest value.", 1)
|
||||
highestjump = 0
|
||||
|
||||
# Lower the number by half
|
||||
if highestjump:
|
||||
throttled = False
|
||||
jump = highestjump
|
||||
self.logMsg("Throttle deactivated.", 1)
|
||||
log("Throttle deactivated.", 1)
|
||||
else:
|
||||
jump = int(jump/4)
|
||||
self.logMsg("Set jump limit to recover: %s" % jump, 1)
|
||||
log("Set jump limit to recover: %s" % jump, 2)
|
||||
|
||||
retry = 0
|
||||
while utils.window('emby_online') != "true":
|
||||
# Wait server to come back online
|
||||
if retry == 3:
|
||||
self.logMsg("Unable to reconnect to server. Abort process.", 1)
|
||||
log("Unable to reconnect to server. Abort process.", 1)
|
||||
return
|
||||
|
||||
retry += 1
|
||||
|
@ -298,7 +302,7 @@ class Read_EmbyServer():
|
|||
increment = 10
|
||||
|
||||
jump += increment
|
||||
self.logMsg("Increase jump limit to: %s" % jump, 1)
|
||||
log("Increase jump limit to: %s" % jump, 1)
|
||||
return items
|
||||
|
||||
def getViews(self, type, root=False):
|
||||
|
|
|
@ -81,42 +81,46 @@ class UserClient(threading.Thread):
|
|||
|
||||
def getUserId(self):
|
||||
|
||||
log = self.logMsg
|
||||
window = utils.window
|
||||
settings = utils.settings
|
||||
|
||||
username = self.getUsername()
|
||||
w_userId = utils.window('emby_userId%s' % username)
|
||||
s_userId = utils.settings('userId%s' % username)
|
||||
w_userId = window('emby_currUser')
|
||||
s_userId = settings('userId%s' % username)
|
||||
|
||||
# Verify the window property
|
||||
if w_userId:
|
||||
if not s_userId:
|
||||
# Save access token if it's missing from settings
|
||||
utils.settings('userId%s' % username, value=w_userId)
|
||||
self.logMsg(
|
||||
"Returning userId from WINDOW for username: %s UserId: %s"
|
||||
settings('userId%s' % username, value=w_userId)
|
||||
log("Returning userId from WINDOW for username: %s UserId: %s"
|
||||
% (username, w_userId), 2)
|
||||
return w_userId
|
||||
# Verify the settings
|
||||
elif s_userId:
|
||||
self.logMsg(
|
||||
"Returning userId from SETTINGS for username: %s userId: %s"
|
||||
log("Returning userId from SETTINGS for username: %s userId: %s"
|
||||
% (username, s_userId), 2)
|
||||
return s_userId
|
||||
# No userId found
|
||||
else:
|
||||
self.logMsg("No userId saved for username: %s." % username, 1)
|
||||
log("No userId saved for username: %s." % username, 1)
|
||||
|
||||
def getServer(self, prefix=True):
|
||||
|
||||
alternate = utils.settings('altip') == "true"
|
||||
settings = utils.settings
|
||||
|
||||
alternate = settings('altip') == "true"
|
||||
if alternate:
|
||||
# Alternate host
|
||||
HTTPS = utils.settings('secondhttps') == "true"
|
||||
host = utils.settings('secondipaddress')
|
||||
port = utils.settings('secondport')
|
||||
HTTPS = settings('secondhttps') == "true"
|
||||
host = settings('secondipaddress')
|
||||
port = settings('secondport')
|
||||
else:
|
||||
# Original host
|
||||
HTTPS = utils.settings('https') == "true"
|
||||
host = utils.settings('ipaddress')
|
||||
port = utils.settings('port')
|
||||
HTTPS = settings('https') == "true"
|
||||
host = settings('ipaddress')
|
||||
port = settings('port')
|
||||
|
||||
server = host + ":" + port
|
||||
|
||||
|
@ -138,35 +142,40 @@ class UserClient(threading.Thread):
|
|||
|
||||
def getToken(self):
|
||||
|
||||
log = self.logMsg
|
||||
window = utils.window
|
||||
settings = utils.settings
|
||||
|
||||
username = self.getUsername()
|
||||
w_token = utils.window('emby_accessToken%s' % username)
|
||||
s_token = utils.settings('accessToken')
|
||||
userId = self.getUserId()
|
||||
w_token = window('emby_accessToken%s' % userId)
|
||||
s_token = settings('accessToken')
|
||||
|
||||
# Verify the window property
|
||||
if w_token:
|
||||
if not s_token:
|
||||
# Save access token if it's missing from settings
|
||||
utils.settings('accessToken', value=w_token)
|
||||
self.logMsg(
|
||||
"Returning accessToken from WINDOW for username: %s accessToken: %s"
|
||||
settings('accessToken', value=w_token)
|
||||
log("Returning accessToken from WINDOW for username: %s accessToken: %s"
|
||||
% (username, w_token), 2)
|
||||
return w_token
|
||||
# Verify the settings
|
||||
elif s_token:
|
||||
self.logMsg(
|
||||
"Returning accessToken from SETTINGS for username: %s accessToken: %s"
|
||||
log("Returning accessToken from SETTINGS for username: %s accessToken: %s"
|
||||
% (username, s_token), 2)
|
||||
utils.window('emby_accessToken%s' % username, value=s_token)
|
||||
window('emby_accessToken%s' % username, value=s_token)
|
||||
return s_token
|
||||
else:
|
||||
self.logMsg("No token found.", 1)
|
||||
log("No token found.", 1)
|
||||
return ""
|
||||
|
||||
def getSSLverify(self):
|
||||
# Verify host certificate
|
||||
s_sslverify = utils.settings('sslverify')
|
||||
if utils.settings('altip') == "true":
|
||||
s_sslverify = utils.settings('secondsslverify')
|
||||
settings = utils.settings
|
||||
|
||||
s_sslverify = settings('sslverify')
|
||||
if settings('altip') == "true":
|
||||
s_sslverify = settings('secondsslverify')
|
||||
|
||||
if s_sslverify == "true":
|
||||
return True
|
||||
|
@ -175,9 +184,11 @@ class UserClient(threading.Thread):
|
|||
|
||||
def getSSL(self):
|
||||
# Client side certificate
|
||||
s_cert = utils.settings('sslcert')
|
||||
if utils.settings('altip') == "true":
|
||||
s_cert = utils.settings('secondsslcert')
|
||||
settings = utils.settings
|
||||
|
||||
s_cert = settings('sslcert')
|
||||
if settings('altip') == "true":
|
||||
s_cert = settings('secondsslcert')
|
||||
|
||||
if s_cert == "None":
|
||||
return None
|
||||
|
@ -186,11 +197,11 @@ class UserClient(threading.Thread):
|
|||
|
||||
def setUserPref(self):
|
||||
|
||||
doUtils = self.doUtils
|
||||
doUtils = self.doUtils.downloadUrl
|
||||
art = artwork.Artwork()
|
||||
|
||||
url = "{server}/emby/Users/{UserId}?format=json"
|
||||
result = doUtils.downloadUrl(url)
|
||||
result = doUtils(url)
|
||||
self.userSettings = result
|
||||
# Set user image for skin display
|
||||
if result.get('PrimaryImageTag'):
|
||||
|
@ -198,7 +209,7 @@ class UserClient(threading.Thread):
|
|||
|
||||
# Set resume point max
|
||||
url = "{server}/emby/System/Configuration?format=json"
|
||||
result = doUtils.downloadUrl(url)
|
||||
result = doUtils(url)
|
||||
|
||||
utils.settings('markPlayed', value=str(result['MaxResumePct']))
|
||||
|
||||
|
@ -218,26 +229,31 @@ class UserClient(threading.Thread):
|
|||
|
||||
def hasAccess(self):
|
||||
# hasAccess is verified in service.py
|
||||
log = self.logMsg
|
||||
window = utils.window
|
||||
|
||||
url = "{server}/emby/Users?format=json"
|
||||
result = self.doUtils.downloadUrl(url)
|
||||
|
||||
if result == False:
|
||||
# Access is restricted, set in downloadutils.py via exception
|
||||
self.logMsg("Access is restricted.", 1)
|
||||
log("Access is restricted.", 1)
|
||||
self.HasAccess = False
|
||||
|
||||
elif utils.window('emby_online') != "true":
|
||||
elif window('emby_online') != "true":
|
||||
# Server connection failed
|
||||
pass
|
||||
|
||||
elif utils.window('emby_serverStatus') == "restricted":
|
||||
self.logMsg("Access is granted.", 1)
|
||||
elif window('emby_serverStatus') == "restricted":
|
||||
log("Access is granted.", 1)
|
||||
self.HasAccess = True
|
||||
utils.window('emby_serverStatus', clear=True)
|
||||
xbmcgui.Dialog().notification("Emby server", "Access is enabled.")
|
||||
window('emby_serverStatus', clear=True)
|
||||
xbmcgui.Dialog().notification("Emby for Kodi", utils.language(33007))
|
||||
|
||||
def loadCurrUser(self, authenticated=False):
|
||||
|
||||
window = utils.window
|
||||
|
||||
doUtils = self.doUtils
|
||||
username = self.getUsername()
|
||||
userId = self.getUserId()
|
||||
|
@ -252,8 +268,8 @@ class UserClient(threading.Thread):
|
|||
# Test the validity of current token
|
||||
if authenticated == False:
|
||||
url = "%s/emby/Users/%s?format=json" % (self.currServer, userId)
|
||||
utils.window('emby_currUser', value=userId)
|
||||
utils.window('emby_accessToken%s' % userId, value=self.currToken)
|
||||
window('emby_currUser', value=userId)
|
||||
window('emby_accessToken%s' % userId, value=self.currToken)
|
||||
result = doUtils.downloadUrl(url)
|
||||
|
||||
if result == 401:
|
||||
|
@ -262,10 +278,10 @@ class UserClient(threading.Thread):
|
|||
return False
|
||||
|
||||
# Set to windows property
|
||||
utils.window('emby_currUser', value=userId)
|
||||
utils.window('emby_accessToken%s' % userId, value=self.currToken)
|
||||
utils.window('emby_server%s' % userId, value=self.currServer)
|
||||
utils.window('emby_server_%s' % userId, value=self.getServer(prefix=False))
|
||||
window('emby_currUser', value=userId)
|
||||
window('emby_accessToken%s' % userId, value=self.currToken)
|
||||
window('emby_server%s' % userId, value=self.currServer)
|
||||
window('emby_server_%s' % userId, value=self.getServer(prefix=False))
|
||||
|
||||
# Set DownloadUtils values
|
||||
doUtils.setUsername(username)
|
||||
|
@ -284,6 +300,13 @@ class UserClient(threading.Thread):
|
|||
|
||||
|
||||
def authenticate(self):
|
||||
|
||||
log = self.logMsg
|
||||
lang = utils.language
|
||||
window = utils.window
|
||||
settings = utils.settings
|
||||
dialog = xbmcgui.Dialog()
|
||||
|
||||
# Get /profile/addon_data
|
||||
addondir = xbmc.translatePath(self.addon.getAddonInfo('profile')).decode('utf-8')
|
||||
hasSettings = xbmcvfs.exists("%ssettings.xml" % addondir)
|
||||
|
@ -293,12 +316,12 @@ class UserClient(threading.Thread):
|
|||
|
||||
# If there's no settings.xml
|
||||
if not hasSettings:
|
||||
self.logMsg("No settings.xml found.", 1)
|
||||
log("No settings.xml found.", 1)
|
||||
self.auth = False
|
||||
return
|
||||
# If no user information
|
||||
elif not server or not username:
|
||||
self.logMsg("Missing server information.", 1)
|
||||
log("Missing server information.", 1)
|
||||
self.auth = False
|
||||
return
|
||||
# If there's a token, load the user
|
||||
|
@ -308,9 +331,9 @@ class UserClient(threading.Thread):
|
|||
if result == False:
|
||||
pass
|
||||
else:
|
||||
self.logMsg("Current user: %s" % self.currUser, 1)
|
||||
self.logMsg("Current userId: %s" % self.currUserId, 1)
|
||||
self.logMsg("Current accessToken: %s" % self.currToken, 2)
|
||||
log("Current user: %s" % self.currUser, 1)
|
||||
log("Current userId: %s" % self.currUserId, 1)
|
||||
log("Current accessToken: %s" % self.currToken, 2)
|
||||
return
|
||||
|
||||
##### AUTHENTICATE USER #####
|
||||
|
@ -325,92 +348,93 @@ class UserClient(threading.Thread):
|
|||
if username.decode('utf-8') in name:
|
||||
# If user has password
|
||||
if user['HasPassword'] == True:
|
||||
password = xbmcgui.Dialog().input(
|
||||
heading="Enter password for user: %s" % username,
|
||||
password = dialog.input(
|
||||
heading="%s %s" % (lang(33008), username),
|
||||
option=xbmcgui.ALPHANUM_HIDE_INPUT)
|
||||
# If password dialog is cancelled
|
||||
if not password:
|
||||
self.logMsg("No password entered.", 0)
|
||||
utils.window('emby_serverStatus', value="Stop")
|
||||
log("No password entered.", 0)
|
||||
window('emby_serverStatus', value="Stop")
|
||||
self.auth = False
|
||||
return
|
||||
break
|
||||
else:
|
||||
# Manual login, user is hidden
|
||||
password = xbmcgui.Dialog().input(
|
||||
heading="Enter password for user: %s" % username,
|
||||
option=xbmcgui.ALPHANUM_HIDE_INPUT)
|
||||
password = dialog.input(
|
||||
heading="%s %s" % (lang(33008), username),
|
||||
option=xbmcgui.ALPHANUM_HIDE_INPUT)
|
||||
sha1 = hashlib.sha1(password)
|
||||
sha1 = sha1.hexdigest()
|
||||
|
||||
# Authenticate username and password
|
||||
url = "%s/emby/Users/AuthenticateByName?format=json" % server
|
||||
data = {'username': username, 'password': sha1}
|
||||
self.logMsg(data, 2)
|
||||
log(data, 2)
|
||||
|
||||
result = self.doUtils.downloadUrl(url, postBody=data, type="POST", authenticate=False)
|
||||
|
||||
try:
|
||||
self.logMsg("Auth response: %s" % result, 1)
|
||||
log("Auth response: %s" % result, 1)
|
||||
accessToken = result['AccessToken']
|
||||
|
||||
except (KeyError, TypeError):
|
||||
self.logMsg("Failed to retrieve the api key.", 1)
|
||||
log("Failed to retrieve the api key.", 1)
|
||||
accessToken = None
|
||||
|
||||
if accessToken is not None:
|
||||
self.currUser = username
|
||||
xbmcgui.Dialog().notification("Emby server", "Welcome %s!" % self.currUser)
|
||||
dialog.notification("Emby for Kodi", "%s %s!" % (lang(33000), self.currUser), 1)
|
||||
userId = result['User']['Id']
|
||||
utils.settings('accessToken', value=accessToken)
|
||||
utils.settings('userId%s' % username, value=userId)
|
||||
self.logMsg("User Authenticated: %s" % accessToken, 1)
|
||||
settings('accessToken', value=accessToken)
|
||||
settings('userId%s' % username, value=userId)
|
||||
log("User Authenticated: %s" % accessToken, 1)
|
||||
self.loadCurrUser(authenticated=True)
|
||||
utils.window('emby_serverStatus', clear=True)
|
||||
window('emby_serverStatus', clear=True)
|
||||
self.retry = 0
|
||||
else:
|
||||
self.logMsg("User authentication failed.", 1)
|
||||
utils.settings('accessToken', value="")
|
||||
utils.settings('userId%s' % username, value="")
|
||||
xbmcgui.Dialog().ok("Error connecting", "Invalid username or password.")
|
||||
log("User authentication failed.", 1)
|
||||
settings('accessToken', value="")
|
||||
settings('userId%s' % username, value="")
|
||||
dialog.ok(lang(33001), lang(33009))
|
||||
|
||||
# Give two attempts at entering password
|
||||
if self.retry == 2:
|
||||
self.logMsg(
|
||||
"""Too many retries. You can retry by resetting
|
||||
attempts in the addon settings.""", 1)
|
||||
utils.window('emby_serverStatus', value="Stop")
|
||||
xbmcgui.Dialog().ok(
|
||||
heading="Error connecting",
|
||||
line1="Failed to authenticate too many times.",
|
||||
line2="You can retry by resetting attempts in the addon settings.")
|
||||
log("Too many retries. "
|
||||
"You can retry by resetting attempts in the addon settings.", 1)
|
||||
window('emby_serverStatus', value="Stop")
|
||||
dialog.ok(lang(33001), lang(33010))
|
||||
|
||||
self.retry += 1
|
||||
self.auth = False
|
||||
|
||||
def resetClient(self):
|
||||
|
||||
self.logMsg("Reset UserClient authentication.", 1)
|
||||
username = self.getUsername()
|
||||
log = self.logMsg
|
||||
|
||||
log("Reset UserClient authentication.", 1)
|
||||
userId = self.getUserId()
|
||||
|
||||
if self.currToken is not None:
|
||||
# In case of 401, removed saved token
|
||||
utils.settings('accessToken', value="")
|
||||
utils.window('emby_accessToken%s' % username, clear=True)
|
||||
utils.window('emby_accessToken%s' % userId, clear=True)
|
||||
self.currToken = None
|
||||
self.logMsg("User token has been removed.", 1)
|
||||
log("User token has been removed.", 1)
|
||||
|
||||
self.auth = True
|
||||
self.currUser = None
|
||||
|
||||
def run(self):
|
||||
|
||||
log = self.logMsg
|
||||
window = utils.window
|
||||
|
||||
monitor = xbmc.Monitor()
|
||||
self.logMsg("----===## Starting UserClient ##===----", 0)
|
||||
log("----===## Starting UserClient ##===----", 0)
|
||||
|
||||
while not monitor.abortRequested():
|
||||
|
||||
status = utils.window('emby_serverStatus')
|
||||
status = window('emby_serverStatus')
|
||||
if status:
|
||||
# Verify the connection status to server
|
||||
if status == "restricted":
|
||||
|
@ -419,12 +443,12 @@ class UserClient(threading.Thread):
|
|||
|
||||
elif status == "401":
|
||||
# Unauthorized access, revoke token
|
||||
utils.window('emby_serverStatus', value="Auth")
|
||||
window('emby_serverStatus', value="Auth")
|
||||
self.resetClient()
|
||||
|
||||
if self.auth and (self.currUser is None):
|
||||
# Try to authenticate user
|
||||
status = utils.window('emby_serverStatus')
|
||||
status = window('emby_serverStatus')
|
||||
if not status or status == "Auth":
|
||||
# Set auth flag because we no longer need
|
||||
# to authenticate the user
|
||||
|
@ -436,13 +460,13 @@ class UserClient(threading.Thread):
|
|||
# If authenticate failed.
|
||||
server = self.getServer()
|
||||
username = self.getUsername()
|
||||
status = utils.window('emby_serverStatus')
|
||||
status = window('emby_serverStatus')
|
||||
|
||||
# The status Stop is for when user cancelled password dialog.
|
||||
if server and username and status != "Stop":
|
||||
# Only if there's information found to login
|
||||
self.logMsg("Server found: %s" % server, 2)
|
||||
self.logMsg("Username found: %s" % username, 2)
|
||||
log("Server found: %s" % server, 2)
|
||||
log("Username found: %s" % username, 2)
|
||||
self.auth = True
|
||||
|
||||
|
||||
|
@ -454,8 +478,8 @@ class UserClient(threading.Thread):
|
|||
# Abort was requested while waiting. We should exit
|
||||
break
|
||||
|
||||
self.doUtils.stopSession()
|
||||
self.logMsg("##===---- UserClient Stopped ----===##", 0)
|
||||
self.doUtils.stopSession()
|
||||
log("##===---- UserClient Stopped ----===##", 0)
|
||||
|
||||
def stopClient(self):
|
||||
# When emby for kodi terminates
|
||||
|
|
|
@ -23,7 +23,7 @@ class VideoNodes(object):
|
|||
clientInfo = clientinfo.ClientInfo()
|
||||
self.addonName = clientInfo.getAddonName()
|
||||
|
||||
self.kodiversion = int(xbmc.getInfoLabel("System.BuildVersion")[:2])
|
||||
self.kodiversion = int(xbmc.getInfoLabel('System.BuildVersion')[:2])
|
||||
|
||||
def logMsg(self, msg, lvl=1):
|
||||
|
||||
|
@ -75,7 +75,7 @@ class VideoNodes(object):
|
|||
xbmcvfs.exists(path)
|
||||
|
||||
# Create the node directory
|
||||
if not xbmcvfs.exists(nodepath) and not mediatype=="photos":
|
||||
if not xbmcvfs.exists(nodepath) and not mediatype == "photos":
|
||||
# We need to copy over the default items
|
||||
xbmcvfs.mkdirs(nodepath)
|
||||
else:
|
||||
|
@ -102,7 +102,7 @@ class VideoNodes(object):
|
|||
window('Emby.nodes.%s.index' % indexnumber, value=path)
|
||||
|
||||
# Root
|
||||
if not mediatype=="photos":
|
||||
if not mediatype == "photos":
|
||||
root = self.commonRoot(order=0, label=tagname, tagname=tagname, roottype=0)
|
||||
try:
|
||||
utils.indent(root)
|
||||
|
@ -181,7 +181,7 @@ class VideoNodes(object):
|
|||
nodeXML = "%s%s_%s.xml" % (nodepath, cleantagname, nodetype)
|
||||
# Get label
|
||||
stringid = nodes[node]
|
||||
if node != '1':
|
||||
if node != "1":
|
||||
label = utils.language(stringid)
|
||||
if not label:
|
||||
label = xbmc.getLocalizedString(stringid)
|
||||
|
@ -323,7 +323,7 @@ class VideoNodes(object):
|
|||
cleantagname = utils.normalize_nodes(tagname)
|
||||
nodepath = xbmc.translatePath("special://profile/library/video/").decode('utf-8')
|
||||
nodeXML = "%semby_%s.xml" % (nodepath, cleantagname)
|
||||
path = "library://video/emby_%s.xml" % (cleantagname)
|
||||
path = "library://video/emby_%s.xml" % cleantagname
|
||||
windowpath = "ActivateWindow(Video,%s,return)" % path
|
||||
|
||||
# Create the video node directory
|
||||
|
|
|
@ -324,4 +324,4 @@ class WebSocket_Client(threading.Thread):
|
|||
|
||||
self.stopWebsocket = True
|
||||
self.client.close()
|
||||
self.logMsg("Stopping thread.")
|
||||
self.logMsg("Stopping thread.", 1)
|
|
@ -277,14 +277,14 @@ class Service():
|
|||
|
||||
##### Emby thread is terminating. #####
|
||||
|
||||
if self.userclient_running:
|
||||
user.stopClient()
|
||||
|
||||
if self.library_running:
|
||||
library.stopThread()
|
||||
|
||||
if self.websocket_running:
|
||||
ws.stopClient()
|
||||
|
||||
if self.userclient_running:
|
||||
user.stopClient()
|
||||
|
||||
log("======== STOP %s ========" % self.addonName, 0)
|
||||
|
||||
|
|
Loading…
Reference in a new issue