Merge remote-tracking branch 'MediaBrowser/master' into develop
This commit is contained in:
commit
4704d8e983
16 changed files with 195 additions and 90 deletions
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<addon id="plugin.video.plexkodiconnect"
|
||||
name="PlexKodiConnect"
|
||||
version="2.2.1"
|
||||
version="2.2.4"
|
||||
provider-name="croneter">
|
||||
<requires>
|
||||
<import addon="xbmc.python" version="2.1.0"/>
|
||||
|
|
|
@ -1,3 +1,14 @@
|
|||
version 2.2.4
|
||||
- Fix external subs being appended to direct play (via add-on playback)
|
||||
- First attempt at keeping Kodi awake during the initial sync
|
||||
|
||||
version 2.2.3
|
||||
- Fix resume
|
||||
|
||||
version 2.2.2
|
||||
- Fix dialog crash in the manual sync
|
||||
- Fix view duplicate views appearing via launching the emby add-on, when grouping views in emby
|
||||
|
||||
version 2.2.1
|
||||
- Fix artist/album link for music videos
|
||||
- Fix progress dialog when the manual sync runs at start up
|
||||
|
|
|
@ -65,7 +65,8 @@ class Main:
|
|||
'recentepisodes': entrypoint.getRecentEpisodes,
|
||||
'refreshplaylist': entrypoint.refreshPlaylist,
|
||||
'companion': entrypoint.plexCompanion,
|
||||
'switchuser': entrypoint.switchPlexUser
|
||||
'switchuser': entrypoint.switchPlexUser,
|
||||
'deviceid': entrypoint.resetDeviceId
|
||||
}
|
||||
|
||||
if "extrafanart" in sys.argv[0]:
|
||||
|
|
|
@ -297,6 +297,7 @@
|
|||
<string id="30532">Duration of the video library pop up (in seconds)</string>
|
||||
<string id="30533">Duration of the music library pop up (in seconds)</string>
|
||||
<string id="30534">Server messages</string>
|
||||
<string id="30535">Generate a new device Id</string>
|
||||
|
||||
<!-- service add-on -->
|
||||
<string id="33000">Welcome</string>
|
||||
|
@ -331,5 +332,7 @@
|
|||
<string id="33029">Comparing tv shows from:</string>
|
||||
<string id="33030">Comparing episodes from:</string>
|
||||
<string id="33031">Comparing:</string>
|
||||
<string id="33032">Failed to generate a new device Id. See your logs for more information.</string>
|
||||
<string id="33033">A new device Id has been generated. Kodi will now restart.</string>
|
||||
|
||||
</strings>
|
||||
|
|
|
@ -6,6 +6,7 @@ import json
|
|||
import requests
|
||||
import os
|
||||
import urllib
|
||||
from sqlite3 import OperationalError
|
||||
|
||||
import xbmc
|
||||
import xbmcgui
|
||||
|
@ -442,12 +443,15 @@ class Artwork():
|
|||
connection = utils.kodiSQL('texture')
|
||||
cursor = connection.cursor()
|
||||
|
||||
cursor.execute("SELECT cachedurl FROM texture WHERE url = ?", (url,))
|
||||
try:
|
||||
cursor.execute("SELECT cachedurl FROM texture WHERE url = ?", (url,))
|
||||
cachedurl = cursor.fetchone()[0]
|
||||
|
||||
except TypeError:
|
||||
self.logMsg("Could not find cached url.", 1)
|
||||
|
||||
except OperationalError:
|
||||
self.logMsg("Database is locked. Skip deletion process.", 1)
|
||||
|
||||
else: # Delete thumbnail as well as the entry
|
||||
thumbnails = xbmc.translatePath("special://thumbnails/%s" % cachedurl).decode('utf-8')
|
||||
|
@ -457,7 +461,7 @@ class Artwork():
|
|||
try:
|
||||
cursor.execute("DELETE FROM texture WHERE url = ?", (url,))
|
||||
connection.commit()
|
||||
except:
|
||||
except OperationalError:
|
||||
self.logMsg("Issue deleting url from cache. Skipping.", 2)
|
||||
|
||||
finally:
|
||||
|
|
|
@ -144,31 +144,32 @@ class DownloadUtils():
|
|||
|
||||
def startSession(self):
|
||||
|
||||
log = self.logMsg
|
||||
|
||||
self.deviceId = self.clientInfo.getDeviceId()
|
||||
|
||||
# User is identified from this point
|
||||
# Attach authenticated header to the session
|
||||
verify = None
|
||||
cert = None
|
||||
verify = False
|
||||
header = self.getHeader()
|
||||
|
||||
# If user enabled host certificate verification
|
||||
try:
|
||||
verify = self.sslverify
|
||||
cert = self.sslclient
|
||||
if self.sslclient is not None:
|
||||
verify = self.sslclient
|
||||
except:
|
||||
self.logMsg("Could not load SSL settings.", 1)
|
||||
log("Could not load SSL settings.", 1)
|
||||
|
||||
# Start session
|
||||
self.s = requests.Session()
|
||||
self.s.headers = header
|
||||
self.s.verify = verify
|
||||
self.s.cert = cert
|
||||
# Retry connections to the server
|
||||
self.s.mount("http://", requests.adapters.HTTPAdapter(max_retries=1))
|
||||
self.s.mount("https://", requests.adapters.HTTPAdapter(max_retries=1))
|
||||
|
||||
self.logMsg("Requests session started on: %s" % self.server, 1)
|
||||
log("Requests session started on: %s" % self.server, 1)
|
||||
|
||||
def stopSession(self):
|
||||
try:
|
||||
|
@ -232,7 +233,7 @@ class DownloadUtils():
|
|||
if utils.settings('sslverify') == "true":
|
||||
verifyssl = True
|
||||
if utils.settings('sslcert') != "None":
|
||||
cert = utils.settings('sslcert')
|
||||
verifyssl = utils.settings('sslcert')
|
||||
|
||||
# Replace for the real values
|
||||
url = url.replace("{server}", self.server)
|
||||
|
@ -245,7 +246,6 @@ class DownloadUtils():
|
|||
params=parameters,
|
||||
headers=header,
|
||||
timeout=timeout,
|
||||
cert=cert,
|
||||
verify=verifyssl)
|
||||
|
||||
elif type == "POST":
|
||||
|
@ -253,7 +253,6 @@ class DownloadUtils():
|
|||
json=postBody,
|
||||
headers=header,
|
||||
timeout=timeout,
|
||||
cert=cert,
|
||||
verify=verifyssl)
|
||||
|
||||
elif type == "DELETE":
|
||||
|
@ -261,7 +260,6 @@ class DownloadUtils():
|
|||
json=postBody,
|
||||
headers=header,
|
||||
timeout=timeout,
|
||||
cert=cert,
|
||||
verify=verifyssl)
|
||||
|
||||
elif type == "OPTIONS":
|
||||
|
@ -287,6 +285,8 @@ class DownloadUtils():
|
|||
# If user enables ssl verification
|
||||
try:
|
||||
verifyssl = self.sslverify
|
||||
if self.sslclient is not None:
|
||||
verifyssl = self.sslclient
|
||||
except AttributeError:
|
||||
if utils.settings('sslverify') == "true":
|
||||
verifyssl = True
|
||||
|
|
|
@ -143,6 +143,15 @@ class Embydb_Functions():
|
|||
))
|
||||
self.embycursor.execute(query, (name, tagid, mediafolderid))
|
||||
|
||||
def removeView(self, viewid):
|
||||
|
||||
query = ' '.join((
|
||||
|
||||
"DELETE FROM view",
|
||||
"WHERE view_id = ?"
|
||||
))
|
||||
self.embycursor.execute(query, (viewid,))
|
||||
|
||||
def getItem_byId(self, embyid):
|
||||
|
||||
embycursor = self.embycursor
|
||||
|
|
|
@ -203,6 +203,30 @@ def doMainListing():
|
|||
|
||||
xbmcplugin.endOfDirectory(int(sys.argv[1]))
|
||||
|
||||
|
||||
##### Generate a new deviceId
|
||||
def resetDeviceId():
|
||||
|
||||
dialog = xbmcgui.Dialog()
|
||||
language = utils.language
|
||||
|
||||
deviceId_old = utils.window('emby_deviceId')
|
||||
try:
|
||||
utils.window('emby_deviceId', clear=True)
|
||||
deviceId = clientinfo.ClientInfo().getDeviceId(reset=True)
|
||||
except Exception as e:
|
||||
utils.logMsg("EMBY", "Failed to generate a new device Id: %s" % e, 1)
|
||||
dialog.ok(
|
||||
heading="Emby for Kodi",
|
||||
line1=language(33032))
|
||||
else:
|
||||
utils.logMsg("EMBY", "Successfully removed old deviceId: %s New deviceId: %s"
|
||||
% (deviceId_old, deviceId), 1)
|
||||
dialog.ok(
|
||||
heading="Emby for Kodi",
|
||||
line1=language(33033))
|
||||
xbmc.executebuiltin('RestartApp')
|
||||
|
||||
##### ADD ADDITIONAL USERS #####
|
||||
def addUser():
|
||||
|
||||
|
|
|
@ -1191,12 +1191,12 @@ class TVShows(Items):
|
|||
season = -1
|
||||
|
||||
# Specials ordering within season
|
||||
# if item.get('AirsAfterSeasonNumber'):
|
||||
# airsBeforeSeason = item['AirsAfterSeasonNumber']
|
||||
# airsBeforeEpisode = 4096 # Kodi default number for afterseason ordering
|
||||
# else:
|
||||
# airsBeforeSeason = item.get('AirsBeforeSeasonNumber', "-1")
|
||||
# airsBeforeEpisode = item.get('AirsBeforeEpisodeNumber', "-1")
|
||||
if item.get('AirsAfterSeasonNumber'):
|
||||
airsBeforeSeason = item['AirsAfterSeasonNumber']
|
||||
airsBeforeEpisode = 4096 # Kodi default number for afterseason ordering
|
||||
else:
|
||||
airsBeforeSeason = item.get('AirsBeforeSeasonNumber')
|
||||
airsBeforeEpisode = item.get('AirsBeforeEpisodeNumber')
|
||||
|
||||
airsBeforeSeason = "-1"
|
||||
airsBeforeEpisode = "-1"
|
||||
|
|
|
@ -38,7 +38,9 @@ class KodiMonitor(xbmc.Monitor):
|
|||
|
||||
def onSettingsChanged(self):
|
||||
# Monitor emby settings
|
||||
currentPath = utils.settings('useDirectPaths')
|
||||
# Review reset setting at a later time, need to be adjusted to account for initial setup
|
||||
# changes.
|
||||
'''currentPath = utils.settings('useDirectPaths')
|
||||
if utils.window('emby_pluginpath') != currentPath:
|
||||
# Plugin path value changed. Offer to reset
|
||||
self.logMsg("Changed to playback mode detected", 1)
|
||||
|
@ -50,7 +52,7 @@ class KodiMonitor(xbmc.Monitor):
|
|||
"needs to be recreated for the change to be applied. "
|
||||
"Proceed?"))
|
||||
if resp:
|
||||
utils.reset()
|
||||
utils.reset()'''
|
||||
|
||||
currentLog = utils.settings('logLevel')
|
||||
if utils.window('emby_logLevel') != currentLog:
|
||||
|
|
|
@ -398,7 +398,6 @@ class LibrarySync(Thread):
|
|||
xbmc.executebuiltin('UpdateLibrary(video)')
|
||||
if self.enableMusic:
|
||||
xbmc.executebuiltin('UpdateLibrary(music)')
|
||||
|
||||
elapsedtotal = datetime.now() - starttotal
|
||||
utils.window('emby_initialScan', clear=True)
|
||||
self.showKodiNote("%s completed in: %s"
|
||||
|
@ -522,29 +521,6 @@ class LibrarySync(Thread):
|
|||
vnodes.clearProperties()
|
||||
totalnodes = 0
|
||||
|
||||
with embydb.GetEmbyDB() as emby_db:
|
||||
with kodidb.GetKodiDB('video') as kodi_db:
|
||||
for folderItem in result:
|
||||
self.processView(folderItem, kodi_db, emby_db, totalnodes)
|
||||
else:
|
||||
# Add video nodes listings
|
||||
vnodes.singleNode(totalnodes,
|
||||
"Favorite movies",
|
||||
"movies",
|
||||
"favourites")
|
||||
totalnodes += 1
|
||||
vnodes.singleNode(totalnodes,
|
||||
"Favorite tvshows",
|
||||
"tvshows",
|
||||
"favourites")
|
||||
totalnodes += 1
|
||||
vnodes.singleNode(totalnodes,
|
||||
"channels",
|
||||
"movies",
|
||||
"channels")
|
||||
totalnodes += 1
|
||||
# Save total
|
||||
utils.window('Emby.nodes.total', str(totalnodes))
|
||||
|
||||
# update views for all:
|
||||
self.views = emby_db.getAllViewInfo()
|
||||
|
@ -558,6 +534,8 @@ class LibrarySync(Thread):
|
|||
'itemtype': 'artist'
|
||||
}
|
||||
self.views.append(entry)
|
||||
nodes = [] # Prevent duplicate for nodes of the same type
|
||||
playlists = [] # Prevent duplicate for playlists of the same type
|
||||
|
||||
self.logMsg("views saved: %s" % self.views, 1)
|
||||
|
||||
|
@ -645,6 +623,17 @@ class LibrarySync(Thread):
|
|||
itemNumber = len(self.updatelist)
|
||||
if itemNumber == 0:
|
||||
return True
|
||||
# Validate the playlist exists or recreate it
|
||||
if (foldername not in playlists and
|
||||
mediatype in ('movies', 'tvshows', 'musicvideos')):
|
||||
utils.playlistXSP(mediatype, foldername, folderid, viewtype)
|
||||
playlists.append(foldername)
|
||||
if foldername not in nodes and mediatype != "musicvideos":
|
||||
vnodes.viewNode(sorted_views.index(foldername), foldername,
|
||||
mediatype, viewtype, folderid)
|
||||
if viewtype == "mixed": # Change the value
|
||||
sorted_views[sorted_views.index(foldername)] = "%ss" % foldername
|
||||
nodes.append(foldername)
|
||||
|
||||
# Run through self.updatelist, get XML metadata per item
|
||||
# Initiate threads
|
||||
|
@ -693,6 +682,10 @@ class LibrarySync(Thread):
|
|||
thread.start()
|
||||
threads.append(thread)
|
||||
self.logMsg("Kodi Infobox thread spawned", 1)
|
||||
# Remove any old referenced views
|
||||
log("Removing views: %s" % current_views, 1)
|
||||
for view in current_views:
|
||||
emby_db.removeView(view)
|
||||
|
||||
# Wait until finished
|
||||
getMetadataQueue.join()
|
||||
|
|
|
@ -274,6 +274,16 @@ class PlaybackUtils():
|
|||
else:
|
||||
window('%s.refreshid' % embyitem, value=itemid)
|
||||
|
||||
# Append external subtitles to stream
|
||||
playmethod = utils.window('%s.playmethod' % embyitem)
|
||||
# Only for direct stream
|
||||
if playmethod in ("DirectStream"):
|
||||
# Direct play automatically appends external
|
||||
subtitles = self.externalSubs(playurl)
|
||||
listitem.setSubtitles(subtitles)
|
||||
|
||||
self.setArtwork(listitem)
|
||||
|
||||
def externalSubs(self, playurl):
|
||||
|
||||
externalsubs = []
|
||||
|
|
|
@ -414,7 +414,7 @@ class Player(xbmc.Player):
|
|||
self.doUtils(
|
||||
"{server}/:/timeline?" + urlencode(postdata), type="GET")
|
||||
|
||||
def onPlayBackPaused( self ):
|
||||
def onPlayBackPaused(self):
|
||||
|
||||
currentFile = self.currentFile
|
||||
self.logMsg("PLAYBACK_PAUSED: %s" % currentFile, 2)
|
||||
|
@ -424,7 +424,7 @@ class Player(xbmc.Player):
|
|||
|
||||
self.reportPlayback()
|
||||
|
||||
def onPlayBackResumed( self ):
|
||||
def onPlayBackResumed(self):
|
||||
|
||||
currentFile = self.currentFile
|
||||
self.logMsg("PLAYBACK_RESUMED: %s" % currentFile, 2)
|
||||
|
@ -434,7 +434,7 @@ class Player(xbmc.Player):
|
|||
|
||||
self.reportPlayback()
|
||||
|
||||
def onPlayBackSeek( self, time, seekOffset ):
|
||||
def onPlayBackSeek(self, time, seekOffset):
|
||||
# Make position when seeking a bit more accurate
|
||||
currentFile = self.currentFile
|
||||
self.logMsg("PLAYBACK_SEEK: %s" % currentFile, 2)
|
||||
|
@ -445,7 +445,7 @@ class Player(xbmc.Player):
|
|||
|
||||
self.reportPlayback()
|
||||
|
||||
def onPlayBackStopped( self ):
|
||||
def onPlayBackStopped(self):
|
||||
|
||||
log = self.logMsg
|
||||
window = utils.window
|
||||
|
@ -458,7 +458,7 @@ class Player(xbmc.Player):
|
|||
log("Clear playlist properties.", 1)
|
||||
self.stopAll()
|
||||
|
||||
def onPlayBackEnded( self ):
|
||||
def onPlayBackEnded(self):
|
||||
# Will be called when xbmc stops playing a file
|
||||
self.logMsg("ONPLAYBACK_ENDED", 2)
|
||||
utils.window('emby_customPlaylist.seektime', clear=True)
|
||||
|
@ -494,6 +494,9 @@ class Player(xbmc.Player):
|
|||
type = data['Type']
|
||||
playMethod = data['playmethod']
|
||||
|
||||
# Prevent manually mark as watched in Kodi monitor
|
||||
utils.window('emby_skipWatched%s' % itemid, value="true")
|
||||
|
||||
if currentPosition and runtime:
|
||||
try:
|
||||
percentComplete = currentPosition / int(runtime)
|
||||
|
@ -505,16 +508,6 @@ class Player(xbmc.Player):
|
|||
log("Percent complete: %s Mark played at: %s"
|
||||
% (percentComplete, markPlayedAt), 1)
|
||||
|
||||
# Prevent manually mark as watched in Kodi monitor
|
||||
utils.window('emby_skipWatched%s' % itemid, value="true")
|
||||
|
||||
self.stopPlayback(data)
|
||||
# Stop transcoding
|
||||
if playMethod == "Transcode":
|
||||
log("Transcoding for %s terminated." % itemid, 1)
|
||||
url = "{server}/video/:/transcode/universal/stop?session=%s" % self.clientInfo.getDeviceId()
|
||||
doUtils(url, type="GET")
|
||||
|
||||
# Send the delete action to the server.
|
||||
offerDelete = False
|
||||
|
||||
|
@ -553,7 +546,15 @@ class Player(xbmc.Player):
|
|||
)
|
||||
for item in cleanup:
|
||||
utils.window(item, clear=True)
|
||||
self.stopPlayback(data)
|
||||
|
||||
# Stop transcoding
|
||||
if playMethod == "Transcode":
|
||||
log("Transcoding for %s terminated." % itemid, 1)
|
||||
deviceId = self.clientInfo.getDeviceId()
|
||||
url = "{server}/emby/Videos/ActiveEncodings?DeviceId=%s" % deviceId
|
||||
doUtils(url, type="DELETE")
|
||||
|
||||
self.played_info.clear()
|
||||
|
||||
def stopPlayback(self, data):
|
||||
|
|
|
@ -294,11 +294,11 @@ class Read_EmbyServer():
|
|||
log("Increase jump limit to: %s" % jump, 1)
|
||||
return items
|
||||
|
||||
def getViews(self, type, root=False):
|
||||
def getViews(self, mediatype="", root=False, sortedlist=False):
|
||||
# Build a list of user views
|
||||
doUtils = self.doUtils
|
||||
views = []
|
||||
type = type.lower()
|
||||
mediatype = mediatype.lower()
|
||||
|
||||
if not root:
|
||||
url = "{server}/emby/Users/{UserId}/Views?format=json"
|
||||
|
@ -308,10 +308,8 @@ class Read_EmbyServer():
|
|||
result = doUtils(url)
|
||||
try:
|
||||
items = result['Items']
|
||||
|
||||
except TypeError:
|
||||
self.logMsg("Error retrieving views for type: %s" % type, 2)
|
||||
|
||||
self.logMsg("Error retrieving views for type: %s" % mediatype, 2)
|
||||
else:
|
||||
for item in items:
|
||||
|
||||
|
@ -336,15 +334,25 @@ class Read_EmbyServer():
|
|||
if itemId == folder['Id']:
|
||||
itemtype = folder.get('CollectionType', "mixed")
|
||||
|
||||
if (name not in ('Collections', 'Trailers') and (itemtype == type or
|
||||
(itemtype == "mixed" and type in ("movies", "tvshows")))):
|
||||
if name not in ('Collections', 'Trailers'):
|
||||
|
||||
views.append({
|
||||
if sortedlist:
|
||||
views.append({
|
||||
|
||||
'name': name,
|
||||
'type': itemtype,
|
||||
'id': itemId
|
||||
})
|
||||
'name': name,
|
||||
'type': itemtype,
|
||||
'id': itemId
|
||||
})
|
||||
|
||||
elif (itemtype == mediatype or
|
||||
(itemtype == "mixed" and mediatype in ("movies", "tvshows"))):
|
||||
|
||||
views.append({
|
||||
|
||||
'name': name,
|
||||
'type': itemtype,
|
||||
'id': itemId
|
||||
})
|
||||
|
||||
return views
|
||||
|
||||
|
|
|
@ -296,7 +296,7 @@ def reset():
|
|||
deleteNodes()
|
||||
|
||||
# Wipe the kodi databases
|
||||
logMsg("EMBY", "Resetting the Kodi video database.")
|
||||
logMsg("EMBY", "Resetting the Kodi video database.", 0)
|
||||
connection = kodiSQL('video')
|
||||
cursor = connection.cursor()
|
||||
cursor.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"')
|
||||
|
@ -322,7 +322,7 @@ def reset():
|
|||
cursor.close()
|
||||
|
||||
# Wipe the emby database
|
||||
logMsg("EMBY", "Resetting the Emby database.")
|
||||
logMsg("EMBY", "Resetting the Emby database.", 0)
|
||||
connection = kodiSQL('emby')
|
||||
cursor = connection.cursor()
|
||||
cursor.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"')
|
||||
|
@ -331,15 +331,45 @@ def reset():
|
|||
tablename = row[0]
|
||||
if tablename != "version":
|
||||
cursor.execute("DELETE FROM " + tablename)
|
||||
cursor.execute('DROP table IF EXISTS emby')
|
||||
cursor.execute('DROP table IF EXISTS view')
|
||||
connection.commit()
|
||||
cursor.close()
|
||||
|
||||
# Offer to wipe cached thumbnails
|
||||
resp = dialog.yesno("Warning", "Removed all cached artwork?")
|
||||
if resp:
|
||||
logMsg("EMBY", "Resetting all cached artwork.", 0)
|
||||
# Remove all existing textures first
|
||||
path = xbmc.translatePath("special://thumbnails/").decode('utf-8')
|
||||
if xbmcvfs.exists(path):
|
||||
allDirs, allFiles = xbmcvfs.listdir(path)
|
||||
for dir in allDirs:
|
||||
allDirs, allFiles = xbmcvfs.listdir(path+dir)
|
||||
for file in allFiles:
|
||||
if os.path.supports_unicode_filenames:
|
||||
xbmcvfs.delete(os.path.join(path+dir.decode('utf-8'),file.decode('utf-8')))
|
||||
else:
|
||||
xbmcvfs.delete(os.path.join(path.encode('utf-8')+dir,file))
|
||||
|
||||
# remove all existing data from texture DB
|
||||
connection = kodiSQL('texture')
|
||||
cursor = connection.cursor()
|
||||
cursor.execute('SELECT tbl_name FROM sqlite_master WHERE type="table"')
|
||||
rows = cursor.fetchall()
|
||||
for row in rows:
|
||||
tableName = row[0]
|
||||
if(tableName != "version"):
|
||||
cursor.execute("DELETE FROM " + tableName)
|
||||
connection.commit()
|
||||
cursor.close()
|
||||
|
||||
# reset the install run flag
|
||||
settings('SyncInstallRunDone', value="false")
|
||||
|
||||
# Remove emby info
|
||||
resp = dialog.yesno("Warning", "Reset all Emby Addon settings?")
|
||||
if resp == 1:
|
||||
if resp:
|
||||
# Delete the settings
|
||||
addon = xbmcaddon.Addon()
|
||||
addondir = xbmc.translatePath(addon.getAddonInfo('profile')).decode('utf-8')
|
||||
|
@ -601,17 +631,17 @@ def passwordsXML():
|
|||
time=1000,
|
||||
sound=False)
|
||||
|
||||
def playlistXSP(mediatype, tagname, viewtype="", delete=False):
|
||||
def playlistXSP(mediatype, tagname, viewid, viewtype="", delete=False):
|
||||
# Tagname is in unicode - actions: add or delete
|
||||
tagname = tagname.encode('utf-8')
|
||||
cleantagname = normalize_nodes(tagname)
|
||||
|
||||
path = xbmc.translatePath("special://profile/playlists/video/").decode('utf-8')
|
||||
if viewtype == "mixed":
|
||||
plname = "%s - %s" % (tagname, mediatype)
|
||||
xsppath = "%sEmby %s - %s.xsp" % (path, cleantagname, mediatype)
|
||||
xsppath = "%sEmby %s - %s.xsp" % (path, viewid, mediatype)
|
||||
else:
|
||||
plname = tagname
|
||||
xsppath = "%sEmby %s.xsp" % (path, cleantagname)
|
||||
xsppath = "%sEmby %s.xsp" % (path, viewid)
|
||||
|
||||
# Create the playlist directory
|
||||
if not xbmcvfs.exists(path):
|
||||
|
@ -668,7 +698,13 @@ def deleteNodes():
|
|||
dirs, files = xbmcvfs.listdir(path)
|
||||
for dir in dirs:
|
||||
if dir.decode('utf-8').startswith('Emby'):
|
||||
shutil.rmtree("%s%s" % (path, dir.decode('utf-8')))
|
||||
try:
|
||||
shutil.rmtree("%s%s" % (path, dir.decode('utf-8')))
|
||||
except:
|
||||
logMsg("EMBY", "Failed to delete directory: %s" % dir.decode('utf-8'))
|
||||
for file in files:
|
||||
if file.decode('utf-8').startswith('emby'):
|
||||
xbmcvfs.delete("%s%s" % (path, file.decode('utf-8')))
|
||||
try:
|
||||
xbmcvfs.delete("%s%s" % (path, file.decode('utf-8')))
|
||||
except:
|
||||
logMsg("EMBY", "Failed to file: %s" % file.decode('utf-8'))
|
|
@ -40,16 +40,15 @@ class VideoNodes(object):
|
|||
|
||||
return root
|
||||
|
||||
def viewNode(self, indexnumber, tagname, mediatype, viewtype, delete=False):
|
||||
def viewNode(self, indexnumber, tagname, mediatype, viewtype, viewid, delete=False):
|
||||
|
||||
window = utils.window
|
||||
kodiversion = self.kodiversion
|
||||
|
||||
cleantagname = utils.normalize_nodes(tagname.encode('utf-8'))
|
||||
if viewtype == "mixed":
|
||||
dirname = "%s - %s" % (cleantagname, mediatype)
|
||||
dirname = "%s - %s" % (viewid, mediatype)
|
||||
else:
|
||||
dirname = cleantagname
|
||||
dirname = viewid
|
||||
|
||||
path = xbmc.translatePath("special://profile/library/video/").decode('utf-8')
|
||||
nodepath = xbmc.translatePath(
|
||||
|
@ -91,7 +90,11 @@ class VideoNodes(object):
|
|||
|
||||
# Root
|
||||
if not mediatype == "photos":
|
||||
root = self.commonRoot(order=0, label=tagname, tagname=tagname, roottype=0)
|
||||
if viewtype == "mixed":
|
||||
specialtag = "%s - %s" % (tagname, mediatype)
|
||||
root = self.commonRoot(order=0, label=specialtag, tagname=tagname, roottype=0)
|
||||
else:
|
||||
root = self.commonRoot(order=0, label=tagname, tagname=tagname, roottype=0)
|
||||
try:
|
||||
utils.indent(root)
|
||||
except: pass
|
||||
|
@ -166,7 +169,7 @@ class VideoNodes(object):
|
|||
for node in nodes:
|
||||
|
||||
nodetype = nodetypes[node]
|
||||
nodeXML = "%s%s_%s.xml" % (nodepath, cleantagname, nodetype)
|
||||
nodeXML = "%s%s_%s.xml" % (nodepath, viewid, nodetype)
|
||||
# Get label
|
||||
stringid = nodes[node]
|
||||
if node != "1":
|
||||
|
@ -193,7 +196,7 @@ class VideoNodes(object):
|
|||
# Custom query
|
||||
path = "plugin://plugin.video.plexkodiconnect/?id=%s&mode=inprogressepisodes&limit=25"% tagname
|
||||
else:
|
||||
path = "library://video/plex%s/%s_%s.xml" % (dirname, cleantagname, nodetype)
|
||||
path = "library://video/plex%s/%s_%s.xml" % (dirname, viewid, nodetype)
|
||||
|
||||
if mediatype == "photos":
|
||||
windowpath = "ActivateWindow(Pictures,%s,return)" % path
|
||||
|
@ -203,7 +206,7 @@ class VideoNodes(object):
|
|||
if nodetype == "all":
|
||||
|
||||
if viewtype == "mixed":
|
||||
templabel = dirname
|
||||
templabel = "%s - %s" % (tagname, mediatype)
|
||||
else:
|
||||
templabel = label
|
||||
|
||||
|
|
Loading…
Reference in a new issue