Update for strings

This commit is contained in:
angelblue05 2016-02-17 02:13:37 -06:00
parent 0ba1ac4104
commit 52a5d35295
10 changed files with 477 additions and 389 deletions

View file

@ -47,7 +47,7 @@ class LibrarySync(threading.Thread):
self.clientInfo = clientinfo.ClientInfo() self.clientInfo = clientinfo.ClientInfo()
self.addonName = self.clientInfo.getAddonName() self.addonName = self.clientInfo.getAddonName()
self.doUtils = downloadutils.DownloadUtils() self.doUtils = downloadutils.DownloadUtils().downloadUrl
self.user = userclient.UserClient() self.user = userclient.UserClient()
self.emby = embyserver.Read_EmbyServer() self.emby = embyserver.Read_EmbyServer()
self.vnodes = videonodes.VideoNodes() self.vnodes = videonodes.VideoNodes()
@ -72,17 +72,19 @@ class LibrarySync(threading.Thread):
return dialog return dialog
def startSync(self): def startSync(self):
settings = utils.settings
# Run at start up - optional to use the server plugin # Run at start up - optional to use the server plugin
if utils.settings('SyncInstallRunDone') == "true": if settings('SyncInstallRunDone') == "true":
# Validate views # Validate views
self.refreshViews() self.refreshViews()
completed = False completed = False
# Verify if server plugin is installed. # Verify if server plugin is installed.
if utils.settings('serverSync') == "true": if settings('serverSync') == "true":
# Try to use fast start up # Try to use fast start up
url = "{server}/emby/Plugins?format=json" url = "{server}/emby/Plugins?format=json"
result = self.doUtils.downloadUrl(url) result = self.doUtils(url)
for plugin in result: for plugin in result:
if plugin['Name'] == "Emby.Kodi Sync Queue": if plugin['Name'] == "Emby.Kodi Sync Queue":
@ -100,30 +102,43 @@ class LibrarySync(threading.Thread):
def fastSync(self): def fastSync(self):
log = self.logMsg
doUtils = self.doUtils
lastSync = utils.settings('LastIncrementalSync') lastSync = utils.settings('LastIncrementalSync')
if not lastSync: if not lastSync:
lastSync = "2010-01-01T00:00:00Z" lastSync = "2010-01-01T00:00:00Z"
lastSyncTime = utils.convertdate(lastSync) lastSyncTime = utils.convertdate(lastSync)
self.logMsg("Last sync run: %s" % lastSyncTime, 1) log("Last sync run: %s" % lastSyncTime, 1)
# get server RetentionDateTime # get server RetentionDateTime
url = "{server}/Emby.Kodi.SyncQueue/GetServerDateTime?format=json" url = "{server}/Emby.Kodi.SyncQueue/GetServerDateTime?format=json"
result = self.doUtils.downloadUrl(url) result = doUtils(url)
retention_time = "2010-01-01T00:00:00Z" retention_time = "2010-01-01T00:00:00Z"
if result and result.get('RetentionDateTime'): if result and result.get('RetentionDateTime'):
retention_time = result['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) 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 last sync before retention time do a full sync
if retention_time > lastSyncTime: 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 return False
url = "{server}/emby/Emby.Kodi.SyncQueue/{UserId}/GetItems?format=json" url = "{server}/emby/Emby.Kodi.SyncQueue/{UserId}/GetItems?format=json"
params = {'LastUpdateDT': lastSync} params = {'LastUpdateDT': lastSync}
result = self.doUtils.downloadUrl(url, parameters=params) result = doUtils(url, parameters=params)
try: try:
processlist = { processlist = {
@ -135,36 +150,38 @@ class LibrarySync(threading.Thread):
} }
except (KeyError, TypeError): 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 return False
else: else:
self.logMsg("Fast sync changes: %s" % result, 1) log("Fast sync changes: %s" % result, 1)
for action in processlist: for action in processlist:
self.triage_items(action, processlist[action]) self.triage_items(action, processlist[action])
return True return True
def saveLastSync(self): def saveLastSync(self):
log = self.logMsg
# Save last sync time # Save last sync time
overlap = 2 overlap = 2
url = "{server}/Emby.Kodi.SyncQueue/GetServerDateTime?format=json" 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 try: # datetime fails when used more than once, TypeError
server_time = result['ServerDateTime'] server_time = result['ServerDateTime']
server_time = utils.convertdate(server_time) server_time = utils.convertdate(server_time)
except Exception as e: except Exception as e:
# If the server plugin is not installed or an error happened. # 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) time_now = datetime.utcnow()-timedelta(minutes=overlap)
lastSync = time_now.strftime('%Y-%m-%dT%H:%M:%SZ') 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: else:
lastSync = (server_time - timedelta(minutes=overlap)).strftime('%Y-%m-%dT%H:%M:%SZ') 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: finally:
utils.settings('LastIncrementalSync', value=lastSync) utils.settings('LastIncrementalSync', value=lastSync)
@ -179,32 +196,39 @@ class LibrarySync(threading.Thread):
return False return False
def dbCommit(self, connection): def dbCommit(self, connection):
log = self.logMsg
window = utils.window
# Central commit, verifies if Kodi database update is running # 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: while kodidb_scan:
self.logMsg("Kodi scan is running. Waiting...", 1) log("Kodi scan is running. Waiting...", 1)
kodidb_scan = utils.window('emby_kodiScan') == "true" kodidb_scan = window('emby_kodiScan') == "true"
if self.shouldStop(): if self.shouldStop():
self.logMsg("Commit unsuccessful. Sync terminated.", 1) log("Commit unsuccessful. Sync terminated.", 1)
break break
if self.monitor.waitForAbort(1): if self.monitor.waitForAbort(1):
# Abort was requested while waiting. We should exit # Abort was requested while waiting. We should exit
self.logMsg("Commit unsuccessful.", 1) log("Commit unsuccessful.", 1)
break break
else: else:
connection.commit() connection.commit()
self.logMsg("Commit successful.", 1) log("Commit successful.", 1)
def fullSync(self, manualrun=False, repair=False): 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. # Only run once when first setting up. Can be run manually.
emby = self.emby emby = self.emby
music_enabled = utils.settings('enableMusic') == "true" music_enabled = utils.settings('enableMusic') == "true"
utils.window('emby_dbScan', value="true") window('emby_dbScan', value="true")
# Add sources # Add sources
utils.sourcesXML() utils.sourcesXML()
@ -232,7 +256,7 @@ class LibrarySync(threading.Thread):
message = "Repair sync" message = "Repair sync"
else: else:
message = "Initial sync" message = "Initial sync"
utils.window('emby_initialScan', value="true") window('emby_initialScan', value="true")
pDialog = self.progressDialog("%s" % message, forced=True) pDialog = self.progressDialog("%s" % message, forced=True)
starttotal = datetime.now() starttotal = datetime.now()
@ -253,7 +277,7 @@ class LibrarySync(threading.Thread):
completed = process[itemtype](embycursor, kodicursor, pDialog) completed = process[itemtype](embycursor, kodicursor, pDialog)
if not completed: if not completed:
utils.window('emby_dbScan', clear=True) window('emby_dbScan', clear=True)
if pDialog: if pDialog:
pDialog.close() pDialog.close()
@ -264,8 +288,7 @@ class LibrarySync(threading.Thread):
self.dbCommit(kodiconn) self.dbCommit(kodiconn)
embyconn.commit() embyconn.commit()
elapsedTime = datetime.now() - startTime elapsedTime = datetime.now() - startTime
self.logMsg( log("SyncDatabase (finished %s in: %s)"
"SyncDatabase (finished %s in: %s)"
% (itemtype, str(elapsedTime).split('.')[0]), 1) % (itemtype, str(elapsedTime).split('.')[0]), 1)
else: else:
# Close the Kodi cursor # Close the Kodi cursor
@ -281,7 +304,7 @@ class LibrarySync(threading.Thread):
completed = self.music(embycursor, musiccursor, pDialog) completed = self.music(embycursor, musiccursor, pDialog)
if not completed: if not completed:
utils.window('emby_dbScan', clear=True) window('emby_dbScan', clear=True)
if pDialog: if pDialog:
pDialog.close() pDialog.close()
@ -292,8 +315,7 @@ class LibrarySync(threading.Thread):
musicconn.commit() musicconn.commit()
embyconn.commit() embyconn.commit()
elapsedTime = datetime.now() - startTime elapsedTime = datetime.now() - startTime
self.logMsg( log("SyncDatabase (finished music in: %s)"
"SyncDatabase (finished music in: %s)"
% (str(elapsedTime).split('.')[0]), 1) % (str(elapsedTime).split('.')[0]), 1)
musiccursor.close() musiccursor.close()
@ -302,18 +324,18 @@ class LibrarySync(threading.Thread):
embycursor.close() embycursor.close()
utils.settings('SyncInstallRunDone', value="true") settings('SyncInstallRunDone', value="true")
utils.settings("dbCreatedWithVersion", self.clientInfo.getVersion()) settings("dbCreatedWithVersion", self.clientInfo.getVersion())
self.saveLastSync() self.saveLastSync()
xbmc.executebuiltin('UpdateLibrary(video)') xbmc.executebuiltin('UpdateLibrary(video)')
elapsedtotal = datetime.now() - starttotal elapsedtotal = datetime.now() - starttotal
utils.window('emby_dbScan', clear=True) window('emby_dbScan', clear=True)
utils.window('emby_initialScan', clear=True) window('emby_initialScan', clear=True)
xbmcgui.Dialog().notification( xbmcgui.Dialog().notification(
heading="Emby for Kodi", heading="Emby for Kodi",
message="%s completed in: %s" % message="%s %s %s" %
(message, str(elapsedtotal).split('.')[0]), (message, utils.language(33025), str(elapsedtotal).split('.')[0]),
icon="special://home/addons/plugin.video.emby/icon.png", icon="special://home/addons/plugin.video.emby/icon.png",
sound=False) sound=False)
return True return True
@ -336,6 +358,8 @@ class LibrarySync(threading.Thread):
embycursor.close() embycursor.close()
def maintainViews(self, embycursor, kodicursor): def maintainViews(self, embycursor, kodicursor):
log = self.logMsg
# Compare the views to emby # Compare the views to emby
emby_db = embydb.Embydb_Functions(embycursor) emby_db = embydb.Embydb_Functions(embycursor)
kodi_db = kodidb.Kodidb_Functions(kodicursor) kodi_db = kodidb.Kodidb_Functions(kodicursor)
@ -344,14 +368,14 @@ class LibrarySync(threading.Thread):
# Get views # Get views
url = "{server}/emby/Users/{UserId}/Views?format=json" url = "{server}/emby/Users/{UserId}/Views?format=json"
result = doUtils.downloadUrl(url) result = doUtils(url)
grouped_views = result['Items'] grouped_views = result['Items']
try: try:
groupedFolders = self.user.userSettings['Configuration']['GroupedFolders'] groupedFolders = self.user.userSettings['Configuration']['GroupedFolders']
except TypeError: except TypeError:
url = "{server}/emby/Users/{UserId}?format=json" url = "{server}/emby/Users/{UserId}?format=json"
result = doUtils.downloadUrl(url) result = doUtils(url)
groupedFolders = result['Configuration']['GroupedFolders'] groupedFolders = result['Configuration']['GroupedFolders']
# total nodes for window properties # total nodes for window properties
@ -402,7 +426,7 @@ class LibrarySync(threading.Thread):
emby_db.addView(folderid, foldername, viewtype, tagid) emby_db.addView(folderid, foldername, viewtype, tagid)
else: else:
self.logMsg(' '.join(( log(' '.join((
"Found viewid: %s" % folderid, "Found viewid: %s" % folderid,
"viewname: %s" % current_viewname, "viewname: %s" % current_viewname,
@ -411,7 +435,7 @@ class LibrarySync(threading.Thread):
# View was modified, update with latest info # View was modified, update with latest info
if current_viewname != foldername: 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) tagid = kodi_db.createTag(foldername)
# Update view with new info # Update view with new info
@ -466,6 +490,9 @@ class LibrarySync(threading.Thread):
utils.window('Emby.nodes.total', str(totalnodes)) utils.window('Emby.nodes.total', str(totalnodes))
def movies(self, embycursor, kodicursor, pdialog): def movies(self, embycursor, kodicursor, pdialog):
log = self.logMsg
lang = utils.language
# Get movies from emby # Get movies from emby
emby = self.emby emby = self.emby
emby_db = embydb.Embydb_Functions(embycursor) 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('movies')
views += emby_db.getView_byType('mixed') views += emby_db.getView_byType('mixed')
self.logMsg("Media folders: %s" % views, 1) log("Media folders: %s" % views, 1)
##### PROCESS MOVIES ##### ##### PROCESS MOVIES #####
for view in views: for view in views:
@ -488,7 +515,7 @@ class LibrarySync(threading.Thread):
if pdialog: if pdialog:
pdialog.update( pdialog.update(
heading="Emby for Kodi", heading="Emby for Kodi",
message="Gathering movies from view: %s..." % viewName) message="%s %s..." % (lang(33017), viewName))
# Initial or repair sync # Initial or repair sync
all_embymovies = emby.getMovies(viewId, dialog=pdialog) all_embymovies = emby.getMovies(viewId, dialog=pdialog)
@ -511,12 +538,12 @@ class LibrarySync(threading.Thread):
count += 1 count += 1
movies.add_update(embymovie, viewName, viewId) movies.add_update(embymovie, viewName, viewId)
else: else:
self.logMsg("Movies finished.", 2) log("Movies finished.", 2)
##### PROCESS BOXSETS ##### ##### PROCESS BOXSETS #####
if pdialog: 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) boxsets = emby.getBoxset(dialog=pdialog)
total = boxsets['TotalRecordCount'] total = boxsets['TotalRecordCount']
@ -538,18 +565,20 @@ class LibrarySync(threading.Thread):
count += 1 count += 1
movies.add_updateBoxset(boxset) movies.add_updateBoxset(boxset)
else: else:
self.logMsg("Boxsets finished.", 2) log("Boxsets finished.", 2)
return True return True
def musicvideos(self, embycursor, kodicursor, pdialog): def musicvideos(self, embycursor, kodicursor, pdialog):
log = self.logMsg
# Get musicvideos from emby # Get musicvideos from emby
emby = self.emby emby = self.emby
emby_db = embydb.Embydb_Functions(embycursor) emby_db = embydb.Embydb_Functions(embycursor)
mvideos = itemtypes.MusicVideos(embycursor, kodicursor) mvideos = itemtypes.MusicVideos(embycursor, kodicursor)
views = emby_db.getView_byType('musicvideos') views = emby_db.getView_byType('musicvideos')
self.logMsg("Media folders: %s" % views, 1) log("Media folders: %s" % views, 1)
for view in views: for view in views:
@ -563,7 +592,7 @@ class LibrarySync(threading.Thread):
if pdialog: if pdialog:
pdialog.update( pdialog.update(
heading="Emby for Kodi", heading="Emby for Kodi",
message="Gathering musicvideos from view: %s..." % viewName) message="%s %s..." % (utils.language(33019), viewName))
# Initial or repair sync # Initial or repair sync
all_embymvideos = emby.getMusicVideos(viewId, dialog=pdialog) all_embymvideos = emby.getMusicVideos(viewId, dialog=pdialog)
@ -586,11 +615,13 @@ class LibrarySync(threading.Thread):
count += 1 count += 1
mvideos.add_update(embymvideo, viewName, viewId) mvideos.add_update(embymvideo, viewName, viewId)
else: else:
self.logMsg("MusicVideos finished.", 2) log("MusicVideos finished.", 2)
return True return True
def tvshows(self, embycursor, kodicursor, pdialog): def tvshows(self, embycursor, kodicursor, pdialog):
log = self.logMsg
# Get shows from emby # Get shows from emby
emby = self.emby emby = self.emby
emby_db = embydb.Embydb_Functions(embycursor) 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('tvshows')
views += emby_db.getView_byType('mixed') views += emby_db.getView_byType('mixed')
self.logMsg("Media folders: %s" % views, 1) log("Media folders: %s" % views, 1)
for view in views: for view in views:
@ -612,7 +643,7 @@ class LibrarySync(threading.Thread):
if pdialog: if pdialog:
pdialog.update( pdialog.update(
heading="Emby for Kodi", 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) all_embytvshows = emby.getShows(viewId, dialog=pdialog)
total = all_embytvshows['TotalRecordCount'] total = all_embytvshows['TotalRecordCount']
@ -648,7 +679,7 @@ class LibrarySync(threading.Thread):
pdialog.update(percentage, message="%s - %s" % (title, episodetitle)) pdialog.update(percentage, message="%s - %s" % (title, episodetitle))
tvshows.add_updateEpisode(episode) tvshows.add_updateEpisode(episode)
else: else:
self.logMsg("TVShows finished.", 2) log("TVShows finished.", 2)
return True return True
@ -665,19 +696,19 @@ class LibrarySync(threading.Thread):
'songs': [emby.getSongs, music.add_updateSong] 'songs': [emby.getSongs, music.add_updateSong]
} }
types = ['artists', 'albums', 'songs'] types = ['artists', 'albums', 'songs']
for type in types: for itemtype in types:
if pdialog: if pdialog:
pdialog.update( pdialog.update(
heading="Emby for Kodi", 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'] total = all_embyitems['TotalRecordCount']
embyitems = all_embyitems['Items'] embyitems = all_embyitems['Items']
if pdialog: if pdialog:
pdialog.update(heading="Processing %s / %s items" % (type, total)) pdialog.update(heading="Processing %s / %s items" % (itemtype, total))
count = 0 count = 0
for embyitem in embyitems: for embyitem in embyitems:
@ -691,9 +722,9 @@ class LibrarySync(threading.Thread):
pdialog.update(percentage, message=title) pdialog.update(percentage, message=title)
count += 1 count += 1
process[type][1](embyitem) process[itemtype][1](embyitem)
else: else:
self.logMsg("%s finished." % type, 2) self.logMsg("%s finished." % itemtype, 2)
return True return True
@ -719,6 +750,8 @@ class LibrarySync(threading.Thread):
def incrementalSync(self): def incrementalSync(self):
log = self.logMsg
embyconn = utils.kodiSQL('emby') embyconn = utils.kodiSQL('emby')
embycursor = embyconn.cursor() embycursor = embyconn.cursor()
kodiconn = utils.kodiSQL('video') kodiconn = utils.kodiSQL('video')
@ -788,7 +821,7 @@ class LibrarySync(threading.Thread):
if update_embydb: if update_embydb:
update_embydb = False update_embydb = False
self.logMsg("Updating emby database.", 1) log("Updating emby database.", 1)
embyconn.commit() embyconn.commit()
self.saveLastSync() self.saveLastSync()
@ -797,7 +830,7 @@ class LibrarySync(threading.Thread):
self.forceLibraryUpdate = False self.forceLibraryUpdate = False
self.dbCommit(kodiconn) self.dbCommit(kodiconn)
self.logMsg("Updating video library.", 1) log("Updating video library.", 1)
utils.window('emby_kodiScan', value="true") utils.window('emby_kodiScan', value="true")
xbmc.executebuiltin('UpdateLibrary(video)') xbmc.executebuiltin('UpdateLibrary(video)')
@ -839,10 +872,16 @@ class LibrarySync(threading.Thread):
def run_internal(self): def run_internal(self):
log = self.logMsg
lang = utils.language
window = utils.window
settings = utils.settings
dialog = xbmcgui.Dialog()
startupComplete = False startupComplete = False
monitor = self.monitor monitor = self.monitor
self.logMsg("---===### Starting LibrarySync ###===---", 0) log("---===### Starting LibrarySync ###===---", 0)
while not monitor.abortRequested(): while not monitor.abortRequested():
@ -853,36 +892,24 @@ class LibrarySync(threading.Thread):
# Abort was requested while waiting. We should exit # Abort was requested while waiting. We should exit
break break
if (utils.window('emby_dbCheck') != "true" and if (window('emby_dbCheck') != "true" and settings('SyncInstallRunDone') == "true"):
utils.settings('SyncInstallRunDone') == "true"):
# Verify the validity of the database # Verify the validity of the database
currentVersion = utils.settings('dbCreatedWithVersion') currentVersion = settings('dbCreatedWithVersion')
minVersion = utils.window('emby_minDBVersion') minVersion = window('emby_minDBVersion')
uptoDate = self.compareDBVersion(currentVersion, minVersion) uptoDate = self.compareDBVersion(currentVersion, minVersion)
if not uptoDate: if not uptoDate:
self.logMsg( log("Database version out of date: %s minimum version required: %s"
"Db version out of date: %s minimum version required: %s"
% (currentVersion, minVersion), 0) % (currentVersion, minVersion), 0)
resp = xbmcgui.Dialog().yesno( resp = dialog.yesno("Emby for Kodi", lang(33022))
heading="Db Version",
line1=(
"Detected the database needs to be "
"recreated for this version of Emby for Kodi. "
"Proceed?"))
if not resp: if not resp:
self.logMsg("Db version out of date! USER IGNORED!", 0) log("Database version is out of date! USER IGNORED!", 0)
xbmcgui.Dialog().ok( dialog.ok("Emby for Kodi", lang(33023))
heading="Emby for Kodi",
line1=(
"Emby for Kodi may not work correctly "
"until the database is reset."))
else: else:
utils.reset() utils.reset()
utils.window('emby_dbCheck', value="true") window('emby_dbCheck', value="true")
if not startupComplete: if not startupComplete:
@ -890,58 +917,52 @@ class LibrarySync(threading.Thread):
videoDb = utils.getKodiVideoDBPath() videoDb = utils.getKodiVideoDBPath()
if not xbmcvfs.exists(videoDb): if not xbmcvfs.exists(videoDb):
# Database does not exists # Database does not exists
self.logMsg( log(
"The current Kodi version is incompatible " "The current Kodi version is incompatible "
"with the Emby for Kodi add-on. Please visit " "with the Emby for Kodi add-on. Please visit "
"https://github.com/MediaBrowser/Emby.Kodi/wiki " "https://github.com/MediaBrowser/Emby.Kodi/wiki "
"to know which Kodi versions are supported.", 0) "to know which Kodi versions are supported.", 0)
xbmcgui.Dialog().ok( dialog.ok(
heading="Emby Warning", heading="Emby for Kodi",
line1=( line1=lang(33024))
"Cancelling the database syncing process. "
"Current Kodi versoin: %s is unsupported. "
"Please verify your logs for more info."
% xbmc.getInfoLabel('System.BuildVersion')))
break break
# Run start up sync # Run start up sync
self.logMsg("Db version: %s" % utils.settings('dbCreatedWithVersion'), 0) log("Database version: %s" % settings('dbCreatedWithVersion'), 0)
self.logMsg("SyncDatabase (started)", 1) log("SyncDatabase (started)", 1)
startTime = datetime.now() startTime = datetime.now()
librarySync = self.startSync() librarySync = self.startSync()
elapsedTime = datetime.now() - startTime elapsedTime = datetime.now() - startTime
self.logMsg( log("SyncDatabase (finished in: %s) %s"
"SyncDatabase (finished in: %s) %s"
% (str(elapsedTime).split('.')[0], librarySync), 1) % (str(elapsedTime).split('.')[0], librarySync), 1)
# Only try the initial sync once per kodi session regardless # Only try the initial sync once per kodi session regardless
# This will prevent an infinite loop in case something goes wrong. # This will prevent an infinite loop in case something goes wrong.
startupComplete = True startupComplete = True
# Process updates # Process updates
if utils.window('emby_dbScan') != "true": if window('emby_dbScan') != "true":
self.incrementalSync() self.incrementalSync()
if (utils.window('emby_onWake') == "true" and if window('emby_onWake') == "true" and window('emby_online') == "true":
utils.window('emby_online') == "true"):
# Kodi is waking up # Kodi is waking up
# Set in kodimonitor.py # Set in kodimonitor.py
utils.window('emby_onWake', clear=True) window('emby_onWake', clear=True)
if utils.window('emby_syncRunning') != "true": if window('emby_syncRunning') != "true":
self.logMsg("SyncDatabase onWake (started)", 0) log("SyncDatabase onWake (started)", 0)
librarySync = self.startSync() librarySync = self.startSync()
self.logMsg("SyncDatabase onWake (finished) %s" % librarySync, 0) log("SyncDatabase onWake (finished) %s" % librarySync, 0)
if self.stop_thread: if self.stop_thread:
# Set in service.py # Set in service.py
self.logMsg("Service terminated thread.", 2) log("Service terminated thread.", 2)
break break
if monitor.waitForAbort(1): if monitor.waitForAbort(1):
# Abort was requested while waiting. We should exit # Abort was requested while waiting. We should exit
break break
self.logMsg("###===--- LibrarySync Stopped ---===###", 0) log("###===--- LibrarySync Stopped ---===###", 0)
def stopThread(self): def stopThread(self):
self.stop_thread = True self.stop_thread = True
@ -966,6 +987,9 @@ class ManualSync(LibrarySync):
def movies(self, embycursor, kodicursor, pdialog): def movies(self, embycursor, kodicursor, pdialog):
log = self.logMsg
lang = utils.language
# Get movies from emby # Get movies from emby
emby = self.emby emby = self.emby
emby_db = embydb.Embydb_Functions(embycursor) emby_db = embydb.Embydb_Functions(embycursor)
@ -973,7 +997,7 @@ class ManualSync(LibrarySync):
views = emby_db.getView_byType('movies') views = emby_db.getView_byType('movies')
views += emby_db.getView_byType('mixed') 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 # Pull the list of movies and boxsets in Kodi
try: try:
@ -1003,7 +1027,7 @@ class ManualSync(LibrarySync):
if pdialog: if pdialog:
pdialog.update( pdialog.update(
heading="Emby for Kodi", 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) all_embymovies = emby.getMovies(viewId, basic=True, dialog=pdialog)
for embymovie in all_embymovies['Items']: 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 # Only update if movie is not in Kodi or checksum is different
updatelist.append(itemid) 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) embymovies = emby.getFullItems(updatelist)
total = len(updatelist) total = len(updatelist)
del updatelist[:] del updatelist[:]
@ -1047,9 +1071,7 @@ class ManualSync(LibrarySync):
embyboxsets = [] embyboxsets = []
if pdialog: if pdialog:
pdialog.update( pdialog.update("Emby for Kodi", lang(33027))
heading="Emby for Kodi",
message="Comparing boxsets...")
for boxset in boxsets['Items']: for boxset in boxsets['Items']:
@ -1066,7 +1088,7 @@ class ManualSync(LibrarySync):
updatelist.append(itemid) updatelist.append(itemid)
embyboxsets.append(boxset) embyboxsets.append(boxset)
self.logMsg("Boxsets to update: %s" % updatelist, 1) log("Boxsets to update: %s" % updatelist, 1)
total = len(updatelist) total = len(updatelist)
if pdialog: if pdialog:
@ -1091,24 +1113,26 @@ class ManualSync(LibrarySync):
if kodimovie not in all_embymoviesIds: if kodimovie not in all_embymoviesIds:
movies.remove(kodimovie) movies.remove(kodimovie)
else: else:
self.logMsg("Movies compare finished.", 1) log("Movies compare finished.", 1)
for boxset in all_kodisets: for boxset in all_kodisets:
if boxset not in all_embyboxsetsIds: if boxset not in all_embyboxsetsIds:
movies.remove(boxset) movies.remove(boxset)
else: else:
self.logMsg("Boxsets compare finished.", 1) log("Boxsets compare finished.", 1)
return True return True
def musicvideos(self, embycursor, kodicursor, pdialog): def musicvideos(self, embycursor, kodicursor, pdialog):
log = self.logMsg
# Get musicvideos from emby # Get musicvideos from emby
emby = self.emby emby = self.emby
emby_db = embydb.Embydb_Functions(embycursor) emby_db = embydb.Embydb_Functions(embycursor)
mvideos = itemtypes.MusicVideos(embycursor, kodicursor) mvideos = itemtypes.MusicVideos(embycursor, kodicursor)
views = emby_db.getView_byType('musicvideos') 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 # Pull the list of musicvideos in Kodi
try: try:
@ -1131,7 +1155,7 @@ class ManualSync(LibrarySync):
if pdialog: if pdialog:
pdialog.update( pdialog.update(
heading="Emby for Kodi", 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) all_embymvideos = emby.getMusicVideos(viewId, basic=True, dialog=pdialog)
for embymvideo in all_embymvideos['Items']: 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 # Only update if musicvideo is not in Kodi or checksum is different
updatelist.append(itemid) 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) embymvideos = emby.getFullItems(updatelist)
total = len(updatelist) total = len(updatelist)
del updatelist[:] del updatelist[:]
@ -1176,11 +1200,14 @@ class ManualSync(LibrarySync):
if kodimvideo not in all_embymvideosIds: if kodimvideo not in all_embymvideosIds:
mvideos.remove(kodimvideo) mvideos.remove(kodimvideo)
else: else:
self.logMsg("MusicVideos compare finished.", 1) log("MusicVideos compare finished.", 1)
return True return True
def tvshows(self, embycursor, kodicursor, pdialog): def tvshows(self, embycursor, kodicursor, pdialog):
log = self.logMsg
lang = utils.language
# Get shows from emby # Get shows from emby
emby = self.emby emby = self.emby
emby_db = embydb.Embydb_Functions(embycursor) emby_db = embydb.Embydb_Functions(embycursor)
@ -1188,7 +1215,7 @@ class ManualSync(LibrarySync):
views = emby_db.getView_byType('tvshows') views = emby_db.getView_byType('tvshows')
views += emby_db.getView_byType('mixed') 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 # Pull the list of tvshows and episodes in Kodi
try: try:
@ -1218,7 +1245,7 @@ class ManualSync(LibrarySync):
if pdialog: if pdialog:
pdialog.update( pdialog.update(
heading="Emby for Kodi", 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) all_embytvshows = emby.getShows(viewId, basic=True, dialog=pdialog)
for embytvshow in all_embytvshows['Items']: 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 # Only update if movie is not in Kodi or checksum is different
updatelist.append(itemid) 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) embytvshows = emby.getFullItems(updatelist)
total = len(updatelist) total = len(updatelist)
del updatelist[:] del updatelist[:]
@ -1263,7 +1290,7 @@ class ManualSync(LibrarySync):
if pdialog: if pdialog:
pdialog.update( pdialog.update(
heading="Emby for Kodi", 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) all_embyepisodes = emby.getEpisodes(viewId, basic=True, dialog=pdialog)
for embyepisode in all_embyepisodes['Items']: 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 # Only update if movie is not in Kodi or checksum is different
updatelist.append(itemid) 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) embyepisodes = emby.getFullItems(updatelist)
total = len(updatelist) total = len(updatelist)
del updatelist[:] del updatelist[:]
@ -1305,17 +1332,19 @@ class ManualSync(LibrarySync):
if koditvshow not in all_embytvshowsIds: if koditvshow not in all_embytvshowsIds:
tvshows.remove(koditvshow) tvshows.remove(koditvshow)
else: else:
self.logMsg("TVShows compare finished.", 1) log("TVShows compare finished.", 1)
for kodiepisode in all_kodiepisodes: for kodiepisode in all_kodiepisodes:
if kodiepisode not in all_embyepisodesIds: if kodiepisode not in all_embyepisodesIds:
tvshows.remove(kodiepisode) tvshows.remove(kodiepisode)
else: else:
self.logMsg("Episodes compare finished.", 1) log("Episodes compare finished.", 1)
return True return True
def music(self, embycursor, kodicursor, pdialog): def music(self, embycursor, kodicursor, pdialog):
log = self.logMsg
# Get music from emby # Get music from emby
emby = self.emby emby = self.emby
emby_db = embydb.Embydb_Functions(embycursor) emby_db = embydb.Embydb_Functions(embycursor)
@ -1354,7 +1383,7 @@ class ManualSync(LibrarySync):
if pdialog: if pdialog:
pdialog.update( pdialog.update(
heading="Emby for Kodi", heading="Emby for Kodi",
message="Comparing %s..." % type) message="%s %s..." % (utils.language(33031), type))
if type != "artists": if type != "artists":
all_embyitems = process[type][0](basic=True, dialog=pdialog) 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 # Only update if songs is not in Kodi or checksum is different
updatelist.append(itemid) updatelist.append(itemid)
self.logMsg("%s to update: %s" % (type, updatelist), 1) log("%s to update: %s" % (type, updatelist), 1)
embyitems = emby.getFullItems(updatelist) embyitems = emby.getFullItems(updatelist)
total = len(updatelist) total = len(updatelist)
del updatelist[:] del updatelist[:]
@ -1411,18 +1440,18 @@ class ManualSync(LibrarySync):
if kodiartist not in all_embyartistsIds and all_kodiartists[kodiartist] is not None: if kodiartist not in all_embyartistsIds and all_kodiartists[kodiartist] is not None:
music.remove(kodiartist) music.remove(kodiartist)
else: else:
self.logMsg("Artist compare finished.", 1) log("Artist compare finished.", 1)
for kodialbum in all_kodialbums: for kodialbum in all_kodialbums:
if kodialbum not in all_embyalbumsIds: if kodialbum not in all_embyalbumsIds:
music.remove(kodialbum) music.remove(kodialbum)
else: else:
self.logMsg("Albums compare finished.", 1) log("Albums compare finished.", 1)
for kodisong in all_kodisongs: for kodisong in all_kodisongs:
if kodisong not in all_embysongsIds: if kodisong not in all_embysongsIds:
music.remove(kodisong) music.remove(kodisong)
else: else:
self.logMsg("Songs compare finished.", 1) log("Songs compare finished.", 1)
return True return True

View file

@ -31,7 +31,7 @@ class PlaybackUtils():
self.clientInfo = clientinfo.ClientInfo() self.clientInfo = clientinfo.ClientInfo()
self.addonName = self.clientInfo.getAddonName() self.addonName = self.clientInfo.getAddonName()
self.doUtils = downloadutils.DownloadUtils() self.doUtils = downloadutils.DownloadUtils().downloadUrl
self.userid = utils.window('emby_currUser') self.userid = utils.window('emby_currUser')
self.server = utils.window('emby_server%s' % self.userid) self.server = utils.window('emby_server%s' % self.userid)
@ -48,7 +48,9 @@ class PlaybackUtils():
def play(self, itemid, dbid=None): def play(self, itemid, dbid=None):
self.logMsg("Play called.", 1) log = self.logMsg
window = utils.window
settings = utils.settings
doUtils = self.doUtils doUtils = self.doUtils
item = self.item item = self.item
@ -56,6 +58,7 @@ class PlaybackUtils():
listitem = xbmcgui.ListItem() listitem = xbmcgui.ListItem()
playutils = putils.PlayUtils(item) playutils = putils.PlayUtils(item)
log("Play called.", 1)
playurl = playutils.getPlayUrl() playurl = playutils.getPlayUrl()
if not playurl: if not playurl:
return xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, listitem) return xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, listitem)
@ -74,13 +77,13 @@ class PlaybackUtils():
sizePlaylist = playlist.size() sizePlaylist = playlist.size()
currentPosition = startPos currentPosition = startPos
propertiesPlayback = utils.window('emby_playbackProps') == "true" propertiesPlayback = window('emby_playbackProps') == "true"
introsPlaylist = False introsPlaylist = False
dummyPlaylist = False dummyPlaylist = False
self.logMsg("Playlist start position: %s" % startPos, 1) log("Playlist start position: %s" % startPos, 2)
self.logMsg("Playlist plugin position: %s" % currentPosition, 1) log("Playlist plugin position: %s" % currentPosition, 2)
self.logMsg("Playlist size: %s" % sizePlaylist, 1) log("Playlist size: %s" % sizePlaylist, 2)
############### RESUME POINT ################ ############### RESUME POINT ################
@ -91,13 +94,13 @@ class PlaybackUtils():
# Otherwise we get a loop. # Otherwise we get a loop.
if not propertiesPlayback: if not propertiesPlayback:
utils.window('emby_playbackProps', value="true") window('emby_playbackProps', value="true")
self.logMsg("Setting up properties in playlist.", 1) log("Setting up properties in playlist.", 1)
if (not homeScreen and not seektime and 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 dummyPlaylist = True
playlist.add(playurl, listitem, index=startPos) playlist.add(playurl, listitem, index=startPos)
# Remove the original item from playlist # Remove the original item from playlist
@ -108,27 +111,27 @@ class PlaybackUtils():
############### -- CHECK FOR INTROS ################ ############### -- 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 # 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 url = "{server}/emby/Users/{UserId}/Items/%s/Intros?format=json" % itemid
intros = doUtils.downloadUrl(url) intros = doUtils(url)
if intros['TotalRecordCount'] != 0: if intros['TotalRecordCount'] != 0:
getTrailers = True getTrailers = True
if utils.settings('askCinema') == "true": if settings('askCinema') == "true":
resp = xbmcgui.Dialog().yesno("Emby Cinema Mode", "Play trailers?") resp = xbmcgui.Dialog().yesno("Emby for Kodi", utils.language(33016))
if not resp: if not resp:
# User selected to not play trailers # User selected to not play trailers
getTrailers = False getTrailers = False
self.logMsg("Skip trailers.", 1) log("Skip trailers.", 1)
if getTrailers: if getTrailers:
for intro in intros['Items']: for intro in intros['Items']:
# The server randomly returns intros, process them. # The server randomly returns intros, process them.
introListItem = xbmcgui.ListItem() introListItem = xbmcgui.ListItem()
introPlayurl = putils.PlayUtils(intro).getPlayUrl() introPlayurl = putils.PlayUtils(intro).getPlayUrl()
self.logMsg("Adding Intro: %s" % introPlayurl, 1) log("Adding Intro: %s" % introPlayurl, 1)
# Set listitem and properties for intros # Set listitem and properties for intros
pbutils = PlaybackUtils(intro) pbutils = PlaybackUtils(intro)
@ -144,7 +147,7 @@ class PlaybackUtils():
if homeScreen and not seektime and not sizePlaylist: if homeScreen and not seektime and not sizePlaylist:
# Extend our current playlist with the actual item to play # Extend our current playlist with the actual item to play
# only if there's no playlist first # 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()) self.pl.addtoPlaylist(dbid, item['Type'].lower())
# Ensure that additional parts are played after the main item # 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 # Only add to the playlist after intros have played
partcount = item['PartCount'] partcount = item['PartCount']
url = "{server}/emby/Videos/%s/AdditionalParts?format=json" % itemid url = "{server}/emby/Videos/%s/AdditionalParts?format=json" % itemid
parts = doUtils.downloadUrl(url) parts = doUtils(url)
for part in parts['Items']: for part in parts['Items']:
additionalListItem = xbmcgui.ListItem() additionalListItem = xbmcgui.ListItem()
additionalPlayurl = putils.PlayUtils(part).getPlayUrl() 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 # Set listitem and properties for each additional parts
pbutils = PlaybackUtils(part) pbutils = PlaybackUtils(part)
@ -175,58 +178,60 @@ class PlaybackUtils():
if dummyPlaylist: if dummyPlaylist:
# Added a dummy file to the playlist, # Added a dummy file to the playlist,
# because the first item is going to fail automatically. # 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) return xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, listitem)
# We just skipped adding properties. Reset flag for next time. # We just skipped adding properties. Reset flag for next time.
elif propertiesPlayback: elif propertiesPlayback:
self.logMsg("Resetting properties playback flag.", 2) log("Resetting properties playback flag.", 2)
utils.window('emby_playbackProps', clear=True) window('emby_playbackProps', clear=True)
#self.pl.verifyPlaylist() #self.pl.verifyPlaylist()
########## SETUP MAIN ITEM ########## ########## SETUP MAIN ITEM ##########
# For transcoding only, ask for audio/subs pref # 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) playurl = playutils.audioSubsPref(playurl, listitem)
utils.window('emby_%s.playmethod' % playurl, value="Transcode") window('emby_%s.playmethod' % playurl, value="Transcode")
listitem.setPath(playurl) listitem.setPath(playurl)
self.setProperties(playurl, listitem) self.setProperties(playurl, listitem)
############### PLAYBACK ################ ############### PLAYBACK ################
if homeScreen and seektime and utils.window('emby_customPlaylist') != "true": if homeScreen and seektime and window('emby_customPlaylist') != "true":
self.logMsg("Play as a widget item.", 1) log("Play as a widget item.", 1)
self.setListItem(listitem) self.setListItem(listitem)
xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem) xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem)
elif ((introsPlaylist and utils.window('emby_customPlaylist') == "true") or elif ((introsPlaylist and window('emby_customPlaylist') == "true") or
(homeScreen and not sizePlaylist)): (homeScreen and not sizePlaylist)):
# Playlist was created just now, play it. # Playlist was created just now, play it.
self.logMsg("Play playlist.", 1) log("Play playlist.", 1)
xbmc.Player().play(playlist, startpos=startPos) xbmc.Player().play(playlist, startpos=startPos)
else: else:
self.logMsg("Play as a regular item.", 1) log("Play as a regular item.", 1)
xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem) xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem)
def setProperties(self, playurl, listitem): def setProperties(self, playurl, listitem):
window = utils.window
# Set all properties necessary for plugin path playback # Set all properties necessary for plugin path playback
item = self.item item = self.item
itemid = item['Id'] itemid = item['Id']
itemtype = item['Type'] itemtype = item['Type']
embyitem = "emby_%s" % playurl embyitem = "emby_%s" % playurl
utils.window('%s.runtime' % embyitem, value=str(item.get('RunTimeTicks'))) window('%s.runtime' % embyitem, value=str(item.get('RunTimeTicks')))
utils.window('%s.type' % embyitem, value=itemtype) window('%s.type' % embyitem, value=itemtype)
utils.window('%s.itemid' % embyitem, value=itemid) window('%s.itemid' % embyitem, value=itemid)
if itemtype == "Episode": if itemtype == "Episode":
utils.window('%s.refreshid' % embyitem, value=item.get('SeriesId')) window('%s.refreshid' % embyitem, value=item.get('SeriesId'))
else: else:
utils.window('%s.refreshid' % embyitem, value=itemid) window('%s.refreshid' % embyitem, value=itemid)
# Append external subtitles to stream # Append external subtitles to stream
playmethod = utils.window('%s.playmethod' % embyitem) playmethod = utils.window('%s.playmethod' % embyitem)
@ -316,7 +321,7 @@ class PlaybackUtils():
def setListItem(self, listItem): def setListItem(self, listItem):
item = self.item item = self.item
type = item['Type'] itemtype = item['Type']
API = self.API API = self.API
people = API.getPeople() people = API.getPeople()
studios = API.getStudios() studios = API.getStudios()
@ -336,7 +341,7 @@ class PlaybackUtils():
'votes': item.get('VoteCount') 'votes': item.get('VoteCount')
} }
if "Episode" in type: if "Episode" in itemtype:
# Only for tv shows # Only for tv shows
thumbId = item.get('SeriesId') thumbId = item.get('SeriesId')
season = item.get('ParentIndexNumber', -1) season = item.get('ParentIndexNumber', -1)

View file

@ -32,7 +32,7 @@ class Player(xbmc.Player):
self.clientInfo = clientinfo.ClientInfo() self.clientInfo = clientinfo.ClientInfo()
self.addonName = self.clientInfo.getAddonName() self.addonName = self.clientInfo.getAddonName()
self.doUtils = downloadutils.DownloadUtils() self.doUtils = downloadutils.DownloadUtils().downloadUrl
self.ws = wsc.WebSocket_Client() self.ws = wsc.WebSocket_Client()
self.xbmcplayer = xbmc.Player() self.xbmcplayer = xbmc.Player()
@ -47,7 +47,10 @@ class Player(xbmc.Player):
def GetPlayStats(self): def GetPlayStats(self):
return self.playStats return self.playStats
def onPlayBackStarted( self ): def onPlayBackStarted(self):
log = self.logMsg
window = utils.window
# Will be called when xbmc starts playing a file # Will be called when xbmc starts playing a file
xbmcplayer = self.xbmcplayer xbmcplayer = self.xbmcplayer
self.stopAll() self.stopAll()
@ -66,7 +69,7 @@ class Player(xbmc.Player):
except: pass except: pass
if count == 5: # try 5 times if count == 5: # try 5 times
self.logMsg("Cancelling playback report...", 1) log("Cancelling playback report...", 1)
break break
else: count += 1 else: count += 1
@ -76,36 +79,34 @@ class Player(xbmc.Player):
self.currentFile = currentFile self.currentFile = currentFile
# We may need to wait for info to be set in kodi monitor # 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 tryCount = 0
while not itemId: while not itemId:
xbmc.sleep(200) 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 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 break
else: tryCount += 1 else: tryCount += 1
else: 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. # Only proceed if an itemId was found.
embyitem = "emby_%s" % currentFile embyitem = "emby_%s" % currentFile
runtime = utils.window("%s.runtime" % embyitem) runtime = window("%s.runtime" % embyitem)
refresh_id = utils.window("%s.refreshid" % embyitem) refresh_id = window("%s.refreshid" % embyitem)
playMethod = utils.window("%s.playmethod" % embyitem) playMethod = window("%s.playmethod" % embyitem)
itemType = utils.window("%s.type" % embyitem) itemType = window("%s.type" % embyitem)
utils.window('emby_skipWatched%s' % itemId, value="true") window('emby_skipWatched%s' % itemId, value="true")
customseek = window('emby_customPlaylist.seektime')
if (utils.window('emby_customPlaylist') == "true" and if window('emby_customPlaylist') == "true" and customseek:
utils.window('emby_customPlaylist.seektime')):
# Start at, when using custom playlist (play to Kodi from webclient) # Start at, when using custom playlist (play to Kodi from webclient)
seektime = utils.window('emby_customPlaylist.seektime') log("Seeking to: %s" % customseek, 1)
self.logMsg("Seeking to: %s" % seektime, 1) xbmcplayer.seekTime(int(customseek)/10000000.0)
xbmcplayer.seekTime(int(seektime)/10000000.0) window('emby_customPlaylist.seektime', clear=True)
utils.window('emby_customPlaylist.seektime', clear=True)
seekTime = xbmcplayer.getTime() seekTime = xbmcplayer.getTime()
@ -144,9 +145,8 @@ class Player(xbmc.Player):
# Get the current audio track and subtitles # Get the current audio track and subtitles
if playMethod == "Transcode": if playMethod == "Transcode":
# property set in PlayUtils.py # property set in PlayUtils.py
postdata['AudioStreamIndex'] = utils.window("%sAudioStreamIndex" % currentFile) postdata['AudioStreamIndex'] = window("%sAudioStreamIndex" % currentFile)
postdata['SubtitleStreamIndex'] = utils.window("%sSubtitleStreamIndex" postdata['SubtitleStreamIndex'] = window("%sSubtitleStreamIndex" % currentFile)
% currentFile)
else: else:
# Get the current kodi audio and subtitles and convert to Emby equivalent # Get the current kodi audio and subtitles and convert to Emby equivalent
tracks_query = { tracks_query = {
@ -187,11 +187,11 @@ class Player(xbmc.Player):
# Number of audiotracks to help get Emby Index # Number of audiotracks to help get Emby Index
audioTracks = len(xbmc.Player().getAvailableAudioStreams()) audioTracks = len(xbmc.Player().getAvailableAudioStreams())
mapping = utils.window("%s.indexMapping" % embyitem) mapping = window("%s.indexMapping" % embyitem)
if mapping: # Set in playbackutils.py 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) externalIndex = json.loads(mapping)
if externalIndex.get(str(indexSubs)): if externalIndex.get(str(indexSubs)):
@ -209,15 +209,15 @@ class Player(xbmc.Player):
# Post playback to server # Post playback to server
self.logMsg("Sending POST play started: %s." % postdata, 2) log("Sending POST play started: %s." % postdata, 2)
self.doUtils.downloadUrl(url, postBody=postdata, type="POST") self.doUtils(url, postBody=postdata, type="POST")
# Ensure we do have a runtime # Ensure we do have a runtime
try: try:
runtime = int(runtime) runtime = int(runtime)
except ValueError: except ValueError:
runtime = xbmcplayer.getTotalTime() 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 # Save data map for updates and position calls
data = { data = {
@ -234,7 +234,7 @@ class Player(xbmc.Player):
} }
self.played_info[currentFile] = data 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 # log some playback stats
'''if(itemType != None): '''if(itemType != None):
@ -253,7 +253,9 @@ class Player(xbmc.Player):
def reportPlayback(self): def reportPlayback(self):
self.logMsg("reportPlayback Called", 2) log = self.logMsg
log("reportPlayback Called", 2)
xbmcplayer = self.xbmcplayer xbmcplayer = self.xbmcplayer
# Get current file # Get current file
@ -281,7 +283,7 @@ class Player(xbmc.Player):
"properties": ["volume", "muted"] "properties": ["volume", "muted"]
} }
} }
result = xbmc.executeJSONRPC(json.dumps(volume_query)) result = xbmc.executeJSONRPC(json.dumps(volume_query))
result = json.loads(result) result = json.loads(result)
result = result.get('result') result = result.get('result')
@ -352,7 +354,7 @@ class Player(xbmc.Player):
if mapping: # Set in PlaybackUtils.py 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) externalIndex = json.loads(mapping)
if externalIndex.get(str(indexSubs)): if externalIndex.get(str(indexSubs)):
@ -372,7 +374,7 @@ class Player(xbmc.Player):
# Report progress via websocketclient # Report progress via websocketclient
postdata = json.dumps(postdata) postdata = json.dumps(postdata)
self.logMsg("Report: %s" % postdata, 2) log("Report: %s" % postdata, 2)
self.ws.sendProgressUpdate(postdata) self.ws.sendProgressUpdate(postdata)
def onPlayBackPaused( self ): def onPlayBackPaused( self ):
@ -407,12 +409,15 @@ class Player(xbmc.Player):
self.reportPlayback() self.reportPlayback()
def onPlayBackStopped( self ): def onPlayBackStopped( self ):
log = self.logMsg
window = utils.window
# Will be called when user stops xbmc playing a file # Will be called when user stops xbmc playing a file
self.logMsg("ONPLAYBACK_STOPPED", 2) logMsg("ONPLAYBACK_STOPPED", 2)
utils.window('emby_customPlaylist', clear=True) window('emby_customPlaylist', clear=True)
utils.window('emby_customPlaylist.seektime', clear=True) window('emby_customPlaylist.seektime', clear=True)
utils.window('emby_playbackProps', clear=True) window('emby_playbackProps', clear=True)
self.logMsg("Clear playlist properties.", 1) logMsg("Clear playlist properties.", 1)
self.stopAll() self.stopAll()
def onPlayBackEnded( self ): def onPlayBackEnded( self ):
@ -423,20 +428,24 @@ class Player(xbmc.Player):
def stopAll(self): def stopAll(self):
log = self.logMsg
lang = utils.language
settings = utils.settings
doUtils = self.doUtils doUtils = self.doUtils
if not self.played_info: if not self.played_info:
return return
self.logMsg("Played_information: %s" % self.played_info, 1) log("Played_information: %s" % self.played_info, 1)
# Process each items # Process each items
for item in self.played_info: for item in self.played_info:
data = self.played_info.get(item) data = self.played_info.get(item)
if data: if data:
self.logMsg("Item path: %s" % item, 2) log("Item path: %s" % item, 2)
self.logMsg("Item data: %s" % data, 2) log("Item data: %s" % data, 2)
runtime = data['runtime'] runtime = data['runtime']
currentPosition = data['currentPosition'] currentPosition = data['currentPosition']
@ -453,9 +462,8 @@ class Player(xbmc.Player):
# Runtime is 0. # Runtime is 0.
percentComplete = 0 percentComplete = 0
markPlayedAt = float(utils.settings('markPlayed')) / 100 markPlayedAt = float(settings('markPlayed')) / 100
self.logMsg( log("Percent complete: %s Mark played at: %s"
"Percent complete: %s Mark played at: %s"
% (percentComplete, markPlayedAt), 1) % (percentComplete, markPlayedAt), 1)
# Prevent manually mark as watched in Kodi monitor # Prevent manually mark as watched in Kodi monitor
@ -464,34 +472,32 @@ class Player(xbmc.Player):
self.stopPlayback(data) self.stopPlayback(data)
# Stop transcoding # Stop transcoding
if playMethod == "Transcode": if playMethod == "Transcode":
self.logMsg("Transcoding for %s terminated." % itemid, 1) log("Transcoding for %s terminated." % itemid, 1)
deviceId = self.clientInfo.getDeviceId() deviceId = self.clientInfo.getDeviceId()
url = "{server}/emby/Videos/ActiveEncodings?DeviceId=%s" % deviceId url = "{server}/emby/Videos/ActiveEncodings?DeviceId=%s" % deviceId
doUtils.downloadUrl(url, type="DELETE") doUtils(url, type="DELETE")
# Send the delete action to the server. # Send the delete action to the server.
offerDelete = False offerDelete = False
if type == "Episode" and utils.settings('deleteTV') == "true": if type == "Episode" and settings('deleteTV') == "true":
offerDelete = True offerDelete = True
elif type == "Movie" and utils.settings('deleteMovies') == "true": elif type == "Movie" and settings('deleteMovies') == "true":
offerDelete = True offerDelete = True
if utils.settings('offerDelete') != "true": if settings('offerDelete') != "true":
# Delete could be disabled, even if the subsetting is enabled. # Delete could be disabled, even if the subsetting is enabled.
offerDelete = False offerDelete = False
if percentComplete >= markPlayedAt and offerDelete: if percentComplete >= markPlayedAt and offerDelete:
resp = xbmcgui.Dialog().yesno( resp = xbmcgui.Dialog().yesno(lang(30091), lang(33015))
heading="Confirm delete",
line1="Delete file on Emby Server?")
if not resp: if not resp:
self.logMsg("User skipped deletion.", 1) log("User skipped deletion.", 1)
continue continue
url = "{server}/emby/Items/%s?format=json" % itemid url = "{server}/emby/Items/%s?format=json" % itemid
self.logMsg("Deleting request: %s" % itemid) log("Deleting request: %s" % itemid, 1)
doUtils.downloadUrl(url, type="DELETE") doUtils(url, type="DELETE")
self.played_info.clear() self.played_info.clear()
@ -510,4 +516,4 @@ class Player(xbmc.Player):
'MediaSourceId': itemId, 'MediaSourceId': itemId,
'PositionTicks': positionTicks 'PositionTicks': positionTicks
} }
self.doUtils.downloadUrl(url, postBody=postdata, type="POST") self.doUtils(url, postBody=postdata, type="POST")

View file

@ -39,6 +39,9 @@ class Playlist():
def playAll(self, itemids, startat): def playAll(self, itemids, startat):
log = self.logMsg
window = utils.window
embyconn = utils.kodiSQL('emby') embyconn = utils.kodiSQL('emby')
embycursor = embyconn.cursor() embycursor = embyconn.cursor()
emby_db = embydb.Embydb_Functions(embycursor) emby_db = embydb.Embydb_Functions(embycursor)
@ -47,15 +50,15 @@ class Playlist():
playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO) playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
playlist.clear() playlist.clear()
self.logMsg("---*** PLAY ALL ***---", 1) log("---*** PLAY ALL ***---", 1)
self.logMsg("Items: %s and start at: %s" % (itemids, startat)) log("Items: %s and start at: %s" % (itemids, startat), 1)
started = False started = False
utils.window('emby_customplaylist', value="true") window('emby_customplaylist', value="true")
if startat != 0: if startat != 0:
# Seek to the starting position # Seek to the starting position
utils.window('emby_customplaylist.seektime', str(startat)) window('emby_customplaylist.seektime', str(startat))
for itemid in itemids: for itemid in itemids:
embydb_item = emby_db.getItem_byId(itemid) embydb_item = emby_db.getItem_byId(itemid)
@ -64,14 +67,14 @@ class Playlist():
mediatype = embydb_item[4] mediatype = embydb_item[4]
except TypeError: except TypeError:
# Item is not found in our database, add item manually # 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) item = self.emby.getItem(itemid)
self.addtoPlaylist_xbmc(playlist, item) self.addtoPlaylist_xbmc(playlist, item)
else: else:
# Add to playlist # Add to playlist
self.addtoPlaylist(dbid, mediatype) self.addtoPlaylist(dbid, mediatype)
self.logMsg("Adding %s to playlist." % itemid, 1) log("Adding %s to playlist." % itemid, 1)
if not started: if not started:
started = True started = True
@ -82,12 +85,14 @@ class Playlist():
def modifyPlaylist(self, itemids): def modifyPlaylist(self, itemids):
log = self.logMsg
embyconn = utils.kodiSQL('emby') embyconn = utils.kodiSQL('emby')
embycursor = embyconn.cursor() embycursor = embyconn.cursor()
emby_db = embydb.Embydb_Functions(embycursor) emby_db = embydb.Embydb_Functions(embycursor)
self.logMsg("---*** ADD TO PLAYLIST ***---", 1) log("---*** ADD TO PLAYLIST ***---", 1)
self.logMsg("Items: %s" % itemids, 1) log("Items: %s" % itemids, 1)
player = xbmc.Player() player = xbmc.Player()
playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO) playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
@ -105,7 +110,7 @@ class Playlist():
# Add to playlist # Add to playlist
self.addtoPlaylist(dbid, mediatype) self.addtoPlaylist(dbid, mediatype)
self.logMsg("Adding %s to playlist." % itemid, 1) log("Adding %s to playlist." % itemid, 1)
self.verifyPlaylist() self.verifyPlaylist()
embycursor.close() embycursor.close()

View file

@ -33,43 +33,46 @@ class PlayUtils():
def getPlayUrl(self): def getPlayUrl(self):
log = self.logMsg
window = utils.window
item = self.item item = self.item
playurl = None playurl = None
if (item.get('Type') in ("Recording", "TvChannel") and if (item.get('Type') in ("Recording", "TvChannel") and
item.get('MediaSources') and item['MediaSources'][0]['Protocol'] == "Http"): item.get('MediaSources') and item['MediaSources'][0]['Protocol'] == "Http"):
# Play LiveTV or recordings # 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']) 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": elif item.get('MediaSources') and item['MediaSources'][0]['Protocol'] == "Http":
# Only play as http, used for channels, or online hosting of content # 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() playurl = self.httpPlay()
utils.window('emby_%s.playmethod' % playurl, value="DirectStream") window('emby_%s.playmethod' % playurl, value="DirectStream")
elif self.isDirectPlay(): elif self.isDirectPlay():
self.logMsg("File is direct playing.", 1) log("File is direct playing.", 1)
playurl = self.directPlay() playurl = self.directPlay()
playurl = playurl.encode('utf-8') playurl = playurl.encode('utf-8')
# Set playmethod property # Set playmethod property
utils.window('emby_%s.playmethod' % playurl, value="DirectPlay") window('emby_%s.playmethod' % playurl, value="DirectPlay")
elif self.isDirectStream(): elif self.isDirectStream():
self.logMsg("File is direct streaming.", 1) log("File is direct streaming.", 1)
playurl = self.directStream() playurl = self.directStream()
# Set playmethod property # Set playmethod property
utils.window('emby_%s.playmethod' % playurl, value="DirectStream") window('emby_%s.playmethod' % playurl, value="DirectStream")
elif self.isTranscoding(): elif self.isTranscoding():
self.logMsg("File is transcoding.", 1) log("File is transcoding.", 1)
playurl = self.transcoding() playurl = self.transcoding()
# Set playmethod property # Set playmethod property
utils.window('emby_%s.playmethod' % playurl, value="Transcode") window('emby_%s.playmethod' % playurl, value="Transcode")
return playurl return playurl
@ -90,16 +93,21 @@ class PlayUtils():
def isDirectPlay(self): def isDirectPlay(self):
log = self.logMsg
lang = utils.language
settings = utils.settings
dialog = xbmcgui.Dialog()
item = self.item item = self.item
# Requirement: Filesystem, Accessible path # Requirement: Filesystem, Accessible path
if utils.settings('playFromStream') == "true": if settings('playFromStream') == "true":
# User forcing to play via HTTP # 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 return False
videotrack = item['MediaSources'][0]['Name'] 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): if transcodeH265 in ("1", "2", "3") and ("HEVC" in videotrack or "H265" in videotrack):
# Avoid H265/HEVC depending on the resolution # Avoid H265/HEVC depending on the resolution
@ -110,46 +118,45 @@ class PlayUtils():
'2': 720, '2': 720,
'3': 1080 '3': 1080
} }
self.logMsg("Resolution is: %sP, transcode for resolution: %sP+" log("Resolution is: %sP, transcode for resolution: %sP+"
% (resolution, res[transcodeH265]), 1) % (resolution, res[transcodeH265]), 1)
if res[transcodeH265] <= resolution: if res[transcodeH265] <= resolution:
return False return False
canDirectPlay = item['MediaSources'][0]['SupportsDirectPlay'] canDirectPlay = item['MediaSources'][0]['SupportsDirectPlay']
# Make sure direct play is supported by the server # Make sure direct play is supported by the server
if not canDirectPlay: 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 return False
location = item['LocationType'] location = item['LocationType']
if location == "FileSystem": if location == "FileSystem":
# Verify the path # Verify the path
if not self.fileExists(): if not self.fileExists():
self.logMsg("Unable to direct play.") log("Unable to direct play.")
try: try:
count = int(utils.settings('failCount')) count = int(settings('failCount'))
except ValueError: except ValueError:
count = 0 count = 0
self.logMsg("Direct play failed: %s times." % count, 1) log("Direct play failed: %s times." % count, 1)
if count < 2: if count < 2:
# Let the user know that direct play failed # Let the user know that direct play failed
utils.settings('failCount', value=str(count+1)) settings('failCount', value=str(count+1))
xbmcgui.Dialog().notification( dialog.notification(
heading="Emby server", heading="Emby for Kodi",
message="Unable to direct play.", message=lang(33011),
icon="special://home/addons/plugin.video.emby/icon.png", icon="special://home/addons/plugin.video.emby/icon.png",
sound=False) sound=False)
elif utils.settings('playFromStream') != "true": elif settings('playFromStream') != "true":
# Permanently set direct stream as true # Permanently set direct stream as true
utils.settings('playFromStream', value="true") settings('playFromStream', value="true")
utils.settings('failCount', value="0") settings('failCount', value="0")
xbmcgui.Dialog().notification( dialog.notification(
heading="Emby server", heading="Emby for Kodi",
message=("Direct play failed 3 times. Enabled play " message=lang(33012),
"from HTTP in the add-on settings."), icon="special://home/addons/plugin.video.emby/icon.png",
icon="special://home/addons/plugin.video.emby/icon.png", sound=False)
sound=False)
return False return False
return True return True
@ -185,28 +192,32 @@ class PlayUtils():
def fileExists(self): def fileExists(self):
log = self.logMsg
if 'Path' not in self.item: if 'Path' not in self.item:
# File has no path defined in server # File has no path defined in server
return False return False
# Convert path to direct play # Convert path to direct play
path = self.directPlay() path = self.directPlay()
self.logMsg("Verifying path: %s" % path, 1) log("Verifying path: %s" % path, 1)
if xbmcvfs.exists(path): if xbmcvfs.exists(path):
self.logMsg("Path exists.", 1) log("Path exists.", 1)
return True return True
elif ":" not in path: 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 return True
else: else:
self.logMsg("Failed to find file.") log("Failed to find file.", 1)
return False return False
def isDirectStream(self): def isDirectStream(self):
log = self.logMsg
item = self.item item = self.item
videotrack = item['MediaSources'][0]['Name'] videotrack = item['MediaSources'][0]['Name']
@ -221,8 +232,8 @@ class PlayUtils():
'2': 720, '2': 720,
'3': 1080 '3': 1080
} }
self.logMsg("Resolution is: %sP, transcode for resolution: %sP+" log("Resolution is: %sP, transcode for resolution: %sP+"
% (resolution, res[transcodeH265]), 1) % (resolution, res[transcodeH265]), 1)
if res[transcodeH265] <= resolution: if res[transcodeH265] <= resolution:
return False return False
@ -234,7 +245,7 @@ class PlayUtils():
# Verify the bitrate # Verify the bitrate
if not self.isNetworkSufficient(): 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 False
return True return True
@ -245,12 +256,12 @@ class PlayUtils():
server = self.server server = self.server
itemid = item['Id'] itemid = item['Id']
type = item['Type'] itemtype = item['Type']
if 'Path' in item and item['Path'].endswith('.strm'): if 'Path' in item and item['Path'].endswith('.strm'):
# Allow strm loading when direct streaming # Allow strm loading when direct streaming
playurl = self.directPlay() playurl = self.directPlay()
elif type == "Audio": elif itemtype == "Audio":
playurl = "%s/emby/Audio/%s/stream.mp3" % (server, itemid) playurl = "%s/emby/Audio/%s/stream.mp3" % (server, itemid)
else: else:
playurl = "%s/emby/Videos/%s/stream?static=true" % (server, itemid) playurl = "%s/emby/Videos/%s/stream?static=true" % (server, itemid)
@ -259,15 +270,17 @@ class PlayUtils():
def isNetworkSufficient(self): def isNetworkSufficient(self):
log = self.logMsg
settings = self.getBitrate()*1000 settings = self.getBitrate()*1000
try: try:
sourceBitrate = int(self.item['MediaSources'][0]['Bitrate']) sourceBitrate = int(self.item['MediaSources'][0]['Bitrate'])
except (KeyError, TypeError): except (KeyError, TypeError):
self.logMsg("Bitrate value is missing.", 1) log("Bitrate value is missing.", 1)
else: else:
self.logMsg("The add-on settings bitrate is: %s, the video bitrate required is: %s" log("The add-on settings bitrate is: %s, the video bitrate required is: %s"
% (settings, sourceBitrate), 1) % (settings, sourceBitrate), 1)
if settings < sourceBitrate: if settings < sourceBitrate:
return False return False
@ -335,6 +348,10 @@ class PlayUtils():
return bitrate.get(videoQuality, 2147483) return bitrate.get(videoQuality, 2147483)
def audioSubsPref(self, url, listitem): def audioSubsPref(self, url, listitem):
log = self.logMsg
lang = utils.language
dialog = xbmcgui.Dialog()
# For transcoding only # For transcoding only
# Present the list of audio to select from # Present the list of audio to select from
audioStreamsList = {} audioStreamsList = {}
@ -373,8 +390,6 @@ class PlayUtils():
audioStreams.append(track) audioStreams.append(track)
elif 'Subtitle' in type: elif 'Subtitle' in type:
'''if stream['IsExternal']:
continue'''
try: try:
track = "%s - %s" % (index, stream['Language']) track = "%s - %s" % (index, stream['Language'])
except: except:
@ -396,7 +411,7 @@ class PlayUtils():
if len(audioStreams) > 1: if len(audioStreams) > 1:
resp = xbmcgui.Dialog().select("Choose the audio stream", audioStreams) resp = dialog.select(lang(33013), audioStreams)
if resp > -1: if resp > -1:
# User selected audio # User selected audio
selected = audioStreams[resp] selected = audioStreams[resp]
@ -409,7 +424,7 @@ class PlayUtils():
playurlprefs += "&AudioStreamIndex=%s" % selectAudioIndex playurlprefs += "&AudioStreamIndex=%s" % selectAudioIndex
if len(subtitleStreams) > 1: if len(subtitleStreams) > 1:
resp = xbmcgui.Dialog().select("Choose the subtitle stream", subtitleStreams) resp = dialog.select(lang(33014), subtitleStreams)
if resp == 0: if resp == 0:
# User selected no subtitles # User selected no subtitles
pass pass
@ -424,7 +439,7 @@ class PlayUtils():
itemid = item['Id'] itemid = item['Id']
url = [("%s/Videos/%s/%s/Subtitles/%s/Stream.srt" url = [("%s/Videos/%s/%s/Subtitles/%s/Stream.srt"
% (self.server, itemid, itemid, selectSubsIndex))] % (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) listitem.setSubtitles(url)
else: else:
# Burn subtitles # Burn subtitles

View file

@ -18,12 +18,14 @@ class Read_EmbyServer():
def __init__(self): def __init__(self):
window = utils.window
self.clientInfo = clientinfo.ClientInfo() self.clientInfo = clientinfo.ClientInfo()
self.addonName = self.clientInfo.getAddonName() self.addonName = self.clientInfo.getAddonName()
self.doUtils = downloadutils.DownloadUtils().downloadUrl self.doUtils = downloadutils.DownloadUtils().downloadUrl
self.userId = utils.window('emby_currUser') self.userId = window('emby_currUser')
self.server = utils.window('emby_server%s' % self.userId) self.server = window('emby_server%s' % self.userId)
def logMsg(self, msg, lvl=1): 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): def getSection(self, parentid, itemtype=None, sortby="SortName", basic=False, dialog=None):
log = self.logMsg
doUtils = self.doUtils doUtils = self.doUtils
items = { items = {
@ -208,7 +212,7 @@ class Read_EmbyServer():
items['TotalRecordCount'] = total items['TotalRecordCount'] = total
except TypeError: # Failed to retrieve 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: else:
index = 0 index = 0
@ -250,27 +254,27 @@ class Read_EmbyServer():
# Something happened to the connection # Something happened to the connection
if not throttled: if not throttled:
throttled = True throttled = True
self.logMsg("Throttle activated.", 1) log("Throttle activated.", 1)
if jump == highestjump: if jump == highestjump:
# We already tried with the highestjump, but it failed. Reset value. # We already tried with the highestjump, but it failed. Reset value.
self.logMsg("Reset highest value.", 1) log("Reset highest value.", 1)
highestjump = 0 highestjump = 0
# Lower the number by half # Lower the number by half
if highestjump: if highestjump:
throttled = False throttled = False
jump = highestjump jump = highestjump
self.logMsg("Throttle deactivated.", 1) log("Throttle deactivated.", 1)
else: else:
jump = int(jump/4) 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 retry = 0
while utils.window('emby_online') != "true": while utils.window('emby_online') != "true":
# Wait server to come back online # Wait server to come back online
if retry == 3: if retry == 3:
self.logMsg("Unable to reconnect to server. Abort process.", 1) log("Unable to reconnect to server. Abort process.", 1)
return return
retry += 1 retry += 1
@ -298,7 +302,7 @@ class Read_EmbyServer():
increment = 10 increment = 10
jump += increment jump += increment
self.logMsg("Increase jump limit to: %s" % jump, 1) log("Increase jump limit to: %s" % jump, 1)
return items return items
def getViews(self, type, root=False): def getViews(self, type, root=False):

View file

@ -81,42 +81,46 @@ class UserClient(threading.Thread):
def getUserId(self): def getUserId(self):
log = self.logMsg
window = utils.window
settings = utils.settings
username = self.getUsername() username = self.getUsername()
w_userId = utils.window('emby_userId%s' % username) w_userId = window('emby_currUser')
s_userId = utils.settings('userId%s' % username) s_userId = settings('userId%s' % username)
# Verify the window property # Verify the window property
if w_userId: if w_userId:
if not s_userId: if not s_userId:
# Save access token if it's missing from settings # Save access token if it's missing from settings
utils.settings('userId%s' % username, value=w_userId) settings('userId%s' % username, value=w_userId)
self.logMsg( log("Returning userId from WINDOW for username: %s UserId: %s"
"Returning userId from WINDOW for username: %s UserId: %s"
% (username, w_userId), 2) % (username, w_userId), 2)
return w_userId return w_userId
# Verify the settings # Verify the settings
elif s_userId: elif s_userId:
self.logMsg( log("Returning userId from SETTINGS for username: %s userId: %s"
"Returning userId from SETTINGS for username: %s userId: %s"
% (username, s_userId), 2) % (username, s_userId), 2)
return s_userId return s_userId
# No userId found # No userId found
else: 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): def getServer(self, prefix=True):
alternate = utils.settings('altip') == "true" settings = utils.settings
alternate = settings('altip') == "true"
if alternate: if alternate:
# Alternate host # Alternate host
HTTPS = utils.settings('secondhttps') == "true" HTTPS = settings('secondhttps') == "true"
host = utils.settings('secondipaddress') host = settings('secondipaddress')
port = utils.settings('secondport') port = settings('secondport')
else: else:
# Original host # Original host
HTTPS = utils.settings('https') == "true" HTTPS = settings('https') == "true"
host = utils.settings('ipaddress') host = settings('ipaddress')
port = utils.settings('port') port = settings('port')
server = host + ":" + port server = host + ":" + port
@ -138,35 +142,40 @@ class UserClient(threading.Thread):
def getToken(self): def getToken(self):
log = self.logMsg
window = utils.window
settings = utils.settings
username = self.getUsername() username = self.getUsername()
w_token = utils.window('emby_accessToken%s' % username) userId = self.getUserId()
s_token = utils.settings('accessToken') w_token = window('emby_accessToken%s' % userId)
s_token = settings('accessToken')
# Verify the window property # Verify the window property
if w_token: if w_token:
if not s_token: if not s_token:
# Save access token if it's missing from settings # Save access token if it's missing from settings
utils.settings('accessToken', value=w_token) settings('accessToken', value=w_token)
self.logMsg( log("Returning accessToken from WINDOW for username: %s accessToken: %s"
"Returning accessToken from WINDOW for username: %s accessToken: %s"
% (username, w_token), 2) % (username, w_token), 2)
return w_token return w_token
# Verify the settings # Verify the settings
elif s_token: elif s_token:
self.logMsg( log("Returning accessToken from SETTINGS for username: %s accessToken: %s"
"Returning accessToken from SETTINGS for username: %s accessToken: %s"
% (username, s_token), 2) % (username, s_token), 2)
utils.window('emby_accessToken%s' % username, value=s_token) window('emby_accessToken%s' % username, value=s_token)
return s_token return s_token
else: else:
self.logMsg("No token found.", 1) log("No token found.", 1)
return "" return ""
def getSSLverify(self): def getSSLverify(self):
# Verify host certificate # Verify host certificate
s_sslverify = utils.settings('sslverify') settings = utils.settings
if utils.settings('altip') == "true":
s_sslverify = utils.settings('secondsslverify') s_sslverify = settings('sslverify')
if settings('altip') == "true":
s_sslverify = settings('secondsslverify')
if s_sslverify == "true": if s_sslverify == "true":
return True return True
@ -175,9 +184,11 @@ class UserClient(threading.Thread):
def getSSL(self): def getSSL(self):
# Client side certificate # Client side certificate
s_cert = utils.settings('sslcert') settings = utils.settings
if utils.settings('altip') == "true":
s_cert = utils.settings('secondsslcert') s_cert = settings('sslcert')
if settings('altip') == "true":
s_cert = settings('secondsslcert')
if s_cert == "None": if s_cert == "None":
return None return None
@ -186,11 +197,11 @@ class UserClient(threading.Thread):
def setUserPref(self): def setUserPref(self):
doUtils = self.doUtils doUtils = self.doUtils.downloadUrl
art = artwork.Artwork() art = artwork.Artwork()
url = "{server}/emby/Users/{UserId}?format=json" url = "{server}/emby/Users/{UserId}?format=json"
result = doUtils.downloadUrl(url) result = doUtils(url)
self.userSettings = result self.userSettings = result
# Set user image for skin display # Set user image for skin display
if result.get('PrimaryImageTag'): if result.get('PrimaryImageTag'):
@ -198,7 +209,7 @@ class UserClient(threading.Thread):
# Set resume point max # Set resume point max
url = "{server}/emby/System/Configuration?format=json" url = "{server}/emby/System/Configuration?format=json"
result = doUtils.downloadUrl(url) result = doUtils(url)
utils.settings('markPlayed', value=str(result['MaxResumePct'])) utils.settings('markPlayed', value=str(result['MaxResumePct']))
@ -218,26 +229,31 @@ class UserClient(threading.Thread):
def hasAccess(self): def hasAccess(self):
# hasAccess is verified in service.py # hasAccess is verified in service.py
log = self.logMsg
window = utils.window
url = "{server}/emby/Users?format=json" url = "{server}/emby/Users?format=json"
result = self.doUtils.downloadUrl(url) result = self.doUtils.downloadUrl(url)
if result == False: if result == False:
# Access is restricted, set in downloadutils.py via exception # Access is restricted, set in downloadutils.py via exception
self.logMsg("Access is restricted.", 1) log("Access is restricted.", 1)
self.HasAccess = False self.HasAccess = False
elif utils.window('emby_online') != "true": elif window('emby_online') != "true":
# Server connection failed # Server connection failed
pass pass
elif utils.window('emby_serverStatus') == "restricted": elif window('emby_serverStatus') == "restricted":
self.logMsg("Access is granted.", 1) log("Access is granted.", 1)
self.HasAccess = True self.HasAccess = True
utils.window('emby_serverStatus', clear=True) window('emby_serverStatus', clear=True)
xbmcgui.Dialog().notification("Emby server", "Access is enabled.") xbmcgui.Dialog().notification("Emby for Kodi", utils.language(33007))
def loadCurrUser(self, authenticated=False): def loadCurrUser(self, authenticated=False):
window = utils.window
doUtils = self.doUtils doUtils = self.doUtils
username = self.getUsername() username = self.getUsername()
userId = self.getUserId() userId = self.getUserId()
@ -252,8 +268,8 @@ class UserClient(threading.Thread):
# Test the validity of current token # Test the validity of current token
if authenticated == False: if authenticated == False:
url = "%s/emby/Users/%s?format=json" % (self.currServer, userId) url = "%s/emby/Users/%s?format=json" % (self.currServer, userId)
utils.window('emby_currUser', value=userId) window('emby_currUser', value=userId)
utils.window('emby_accessToken%s' % userId, value=self.currToken) window('emby_accessToken%s' % userId, value=self.currToken)
result = doUtils.downloadUrl(url) result = doUtils.downloadUrl(url)
if result == 401: if result == 401:
@ -262,10 +278,10 @@ class UserClient(threading.Thread):
return False return False
# Set to windows property # Set to windows property
utils.window('emby_currUser', value=userId) window('emby_currUser', value=userId)
utils.window('emby_accessToken%s' % userId, value=self.currToken) window('emby_accessToken%s' % userId, value=self.currToken)
utils.window('emby_server%s' % userId, value=self.currServer) window('emby_server%s' % userId, value=self.currServer)
utils.window('emby_server_%s' % userId, value=self.getServer(prefix=False)) window('emby_server_%s' % userId, value=self.getServer(prefix=False))
# Set DownloadUtils values # Set DownloadUtils values
doUtils.setUsername(username) doUtils.setUsername(username)
@ -284,6 +300,13 @@ class UserClient(threading.Thread):
def authenticate(self): def authenticate(self):
log = self.logMsg
lang = utils.language
window = utils.window
settings = utils.settings
dialog = xbmcgui.Dialog()
# Get /profile/addon_data # Get /profile/addon_data
addondir = xbmc.translatePath(self.addon.getAddonInfo('profile')).decode('utf-8') addondir = xbmc.translatePath(self.addon.getAddonInfo('profile')).decode('utf-8')
hasSettings = xbmcvfs.exists("%ssettings.xml" % addondir) hasSettings = xbmcvfs.exists("%ssettings.xml" % addondir)
@ -293,12 +316,12 @@ class UserClient(threading.Thread):
# If there's no settings.xml # If there's no settings.xml
if not hasSettings: if not hasSettings:
self.logMsg("No settings.xml found.", 1) log("No settings.xml found.", 1)
self.auth = False self.auth = False
return return
# If no user information # If no user information
elif not server or not username: elif not server or not username:
self.logMsg("Missing server information.", 1) log("Missing server information.", 1)
self.auth = False self.auth = False
return return
# If there's a token, load the user # If there's a token, load the user
@ -308,9 +331,9 @@ class UserClient(threading.Thread):
if result == False: if result == False:
pass pass
else: else:
self.logMsg("Current user: %s" % self.currUser, 1) log("Current user: %s" % self.currUser, 1)
self.logMsg("Current userId: %s" % self.currUserId, 1) log("Current userId: %s" % self.currUserId, 1)
self.logMsg("Current accessToken: %s" % self.currToken, 2) log("Current accessToken: %s" % self.currToken, 2)
return return
##### AUTHENTICATE USER ##### ##### AUTHENTICATE USER #####
@ -325,92 +348,93 @@ class UserClient(threading.Thread):
if username.decode('utf-8') in name: if username.decode('utf-8') in name:
# If user has password # If user has password
if user['HasPassword'] == True: if user['HasPassword'] == True:
password = xbmcgui.Dialog().input( password = dialog.input(
heading="Enter password for user: %s" % username, heading="%s %s" % (lang(33008), username),
option=xbmcgui.ALPHANUM_HIDE_INPUT) option=xbmcgui.ALPHANUM_HIDE_INPUT)
# If password dialog is cancelled # If password dialog is cancelled
if not password: if not password:
self.logMsg("No password entered.", 0) log("No password entered.", 0)
utils.window('emby_serverStatus', value="Stop") window('emby_serverStatus', value="Stop")
self.auth = False self.auth = False
return return
break break
else: else:
# Manual login, user is hidden # Manual login, user is hidden
password = xbmcgui.Dialog().input( password = dialog.input(
heading="Enter password for user: %s" % username, heading="%s %s" % (lang(33008), username),
option=xbmcgui.ALPHANUM_HIDE_INPUT) option=xbmcgui.ALPHANUM_HIDE_INPUT)
sha1 = hashlib.sha1(password) sha1 = hashlib.sha1(password)
sha1 = sha1.hexdigest() sha1 = sha1.hexdigest()
# Authenticate username and password # Authenticate username and password
url = "%s/emby/Users/AuthenticateByName?format=json" % server url = "%s/emby/Users/AuthenticateByName?format=json" % server
data = {'username': username, 'password': sha1} data = {'username': username, 'password': sha1}
self.logMsg(data, 2) log(data, 2)
result = self.doUtils.downloadUrl(url, postBody=data, type="POST", authenticate=False) result = self.doUtils.downloadUrl(url, postBody=data, type="POST", authenticate=False)
try: try:
self.logMsg("Auth response: %s" % result, 1) log("Auth response: %s" % result, 1)
accessToken = result['AccessToken'] accessToken = result['AccessToken']
except (KeyError, TypeError): except (KeyError, TypeError):
self.logMsg("Failed to retrieve the api key.", 1) log("Failed to retrieve the api key.", 1)
accessToken = None accessToken = None
if accessToken is not None: if accessToken is not None:
self.currUser = username 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'] userId = result['User']['Id']
utils.settings('accessToken', value=accessToken) settings('accessToken', value=accessToken)
utils.settings('userId%s' % username, value=userId) settings('userId%s' % username, value=userId)
self.logMsg("User Authenticated: %s" % accessToken, 1) log("User Authenticated: %s" % accessToken, 1)
self.loadCurrUser(authenticated=True) self.loadCurrUser(authenticated=True)
utils.window('emby_serverStatus', clear=True) window('emby_serverStatus', clear=True)
self.retry = 0 self.retry = 0
else: else:
self.logMsg("User authentication failed.", 1) log("User authentication failed.", 1)
utils.settings('accessToken', value="") settings('accessToken', value="")
utils.settings('userId%s' % username, value="") settings('userId%s' % username, value="")
xbmcgui.Dialog().ok("Error connecting", "Invalid username or password.") dialog.ok(lang(33001), lang(33009))
# Give two attempts at entering password # Give two attempts at entering password
if self.retry == 2: if self.retry == 2:
self.logMsg( log("Too many retries. "
"""Too many retries. You can retry by resetting "You can retry by resetting attempts in the addon settings.", 1)
attempts in the addon settings.""", 1) window('emby_serverStatus', value="Stop")
utils.window('emby_serverStatus', value="Stop") dialog.ok(lang(33001), lang(33010))
xbmcgui.Dialog().ok(
heading="Error connecting",
line1="Failed to authenticate too many times.",
line2="You can retry by resetting attempts in the addon settings.")
self.retry += 1 self.retry += 1
self.auth = False self.auth = False
def resetClient(self): def resetClient(self):
self.logMsg("Reset UserClient authentication.", 1) log = self.logMsg
username = self.getUsername()
log("Reset UserClient authentication.", 1)
userId = self.getUserId()
if self.currToken is not None: if self.currToken is not None:
# In case of 401, removed saved token # In case of 401, removed saved token
utils.settings('accessToken', value="") utils.settings('accessToken', value="")
utils.window('emby_accessToken%s' % username, clear=True) utils.window('emby_accessToken%s' % userId, clear=True)
self.currToken = None self.currToken = None
self.logMsg("User token has been removed.", 1) log("User token has been removed.", 1)
self.auth = True self.auth = True
self.currUser = None self.currUser = None
def run(self): def run(self):
log = self.logMsg
window = utils.window
monitor = xbmc.Monitor() monitor = xbmc.Monitor()
self.logMsg("----===## Starting UserClient ##===----", 0) log("----===## Starting UserClient ##===----", 0)
while not monitor.abortRequested(): while not monitor.abortRequested():
status = utils.window('emby_serverStatus') status = window('emby_serverStatus')
if status: if status:
# Verify the connection status to server # Verify the connection status to server
if status == "restricted": if status == "restricted":
@ -419,12 +443,12 @@ class UserClient(threading.Thread):
elif status == "401": elif status == "401":
# Unauthorized access, revoke token # Unauthorized access, revoke token
utils.window('emby_serverStatus', value="Auth") window('emby_serverStatus', value="Auth")
self.resetClient() self.resetClient()
if self.auth and (self.currUser is None): if self.auth and (self.currUser is None):
# Try to authenticate user # Try to authenticate user
status = utils.window('emby_serverStatus') status = window('emby_serverStatus')
if not status or status == "Auth": if not status or status == "Auth":
# Set auth flag because we no longer need # Set auth flag because we no longer need
# to authenticate the user # to authenticate the user
@ -436,13 +460,13 @@ class UserClient(threading.Thread):
# If authenticate failed. # If authenticate failed.
server = self.getServer() server = self.getServer()
username = self.getUsername() username = self.getUsername()
status = utils.window('emby_serverStatus') status = window('emby_serverStatus')
# The status Stop is for when user cancelled password dialog. # The status Stop is for when user cancelled password dialog.
if server and username and status != "Stop": if server and username and status != "Stop":
# Only if there's information found to login # Only if there's information found to login
self.logMsg("Server found: %s" % server, 2) log("Server found: %s" % server, 2)
self.logMsg("Username found: %s" % username, 2) log("Username found: %s" % username, 2)
self.auth = True self.auth = True
@ -455,7 +479,7 @@ class UserClient(threading.Thread):
break break
self.doUtils.stopSession() self.doUtils.stopSession()
self.logMsg("##===---- UserClient Stopped ----===##", 0) log("##===---- UserClient Stopped ----===##", 0)
def stopClient(self): def stopClient(self):
# When emby for kodi terminates # When emby for kodi terminates

View file

@ -23,7 +23,7 @@ class VideoNodes(object):
clientInfo = clientinfo.ClientInfo() clientInfo = clientinfo.ClientInfo()
self.addonName = clientInfo.getAddonName() 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): def logMsg(self, msg, lvl=1):
@ -75,7 +75,7 @@ class VideoNodes(object):
xbmcvfs.exists(path) xbmcvfs.exists(path)
# Create the node directory # 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 # We need to copy over the default items
xbmcvfs.mkdirs(nodepath) xbmcvfs.mkdirs(nodepath)
else: else:
@ -102,7 +102,7 @@ class VideoNodes(object):
window('Emby.nodes.%s.index' % indexnumber, value=path) window('Emby.nodes.%s.index' % indexnumber, value=path)
# Root # Root
if not mediatype=="photos": if not mediatype == "photos":
root = self.commonRoot(order=0, label=tagname, tagname=tagname, roottype=0) root = self.commonRoot(order=0, label=tagname, tagname=tagname, roottype=0)
try: try:
utils.indent(root) utils.indent(root)
@ -181,7 +181,7 @@ class VideoNodes(object):
nodeXML = "%s%s_%s.xml" % (nodepath, cleantagname, nodetype) nodeXML = "%s%s_%s.xml" % (nodepath, cleantagname, nodetype)
# Get label # Get label
stringid = nodes[node] stringid = nodes[node]
if node != '1': if node != "1":
label = utils.language(stringid) label = utils.language(stringid)
if not label: if not label:
label = xbmc.getLocalizedString(stringid) label = xbmc.getLocalizedString(stringid)
@ -323,7 +323,7 @@ class VideoNodes(object):
cleantagname = utils.normalize_nodes(tagname) cleantagname = utils.normalize_nodes(tagname)
nodepath = xbmc.translatePath("special://profile/library/video/").decode('utf-8') nodepath = xbmc.translatePath("special://profile/library/video/").decode('utf-8')
nodeXML = "%semby_%s.xml" % (nodepath, cleantagname) 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 windowpath = "ActivateWindow(Video,%s,return)" % path
# Create the video node directory # Create the video node directory

View file

@ -324,4 +324,4 @@ class WebSocket_Client(threading.Thread):
self.stopWebsocket = True self.stopWebsocket = True
self.client.close() self.client.close()
self.logMsg("Stopping thread.") self.logMsg("Stopping thread.", 1)

View file

@ -277,15 +277,15 @@ class Service():
##### Emby thread is terminating. ##### ##### Emby thread is terminating. #####
if self.userclient_running:
user.stopClient()
if self.library_running: if self.library_running:
library.stopThread() library.stopThread()
if self.websocket_running: if self.websocket_running:
ws.stopClient() ws.stopClient()
if self.userclient_running:
user.stopClient()
log("======== STOP %s ========" % self.addonName, 0) log("======== STOP %s ========" % self.addonName, 0)
# Delay option # Delay option