diff --git a/resources/lib/LibrarySync.py b/resources/lib/LibrarySync.py
index 7610558c..a33f1dbe 100644
--- a/resources/lib/LibrarySync.py
+++ b/resources/lib/LibrarySync.py
@@ -85,6 +85,12 @@ class LibrarySync(threading.Thread):
### BUILD VIDEO NODES LISTING ###
VideoNodes().buildVideoNodesListing()
+ ### CREATE SOURCES ###
+ if addon.getSetting("Sources") != "true":
+ # Only create sources once
+ self.logMsg("Sources.xml created.", 0)
+ utils.createSources()
+ addon.setSetting("Sources", "true")
### PROCESS VIDEO LIBRARY ###
diff --git a/resources/lib/PlaybackUtils.py b/resources/lib/PlaybackUtils.py
index 026ebeaa..c841c37c 100644
--- a/resources/lib/PlaybackUtils.py
+++ b/resources/lib/PlaybackUtils.py
@@ -117,27 +117,6 @@ class PlaybackUtils():
WINDOW.setProperty(playurl+"positionurl", positionurl)
WINDOW.setProperty(playurl+"deleteurl", "")
WINDOW.setProperty(playurl+"deleteurl", deleteurl)
-
- #show the additional resume dialog if launched from a widget
- if xbmc.getCondVisibility("Window.IsActive(home)"):
- if userData.get("PlaybackPositionTicks") != 0:
- reasonableTicks = int(userData.get("PlaybackPositionTicks")) / 1000
- seekTime = reasonableTicks / 10000
- if seekTime != 0:
- displayTime = str(datetime.timedelta(seconds=seekTime))
- display_list = [ self.language(30106) + ' ' + displayTime, self.language(30107)]
- resumeScreen = xbmcgui.Dialog()
- resume_result = resumeScreen.select(self.language(30105), display_list)
- if resume_result == 0:
- WINDOW.setProperty(playurl+"seektime", str(seekTime))
- elif resume_result < 0:
- # User cancelled dialog
- xbmc.log("Emby player -> User cancelled resume dialog.")
- return
- else:
- WINDOW.clearProperty(playurl+"seektime")
- else:
- WINDOW.clearProperty(playurl+"seektime")
if result.get("Type")=="Episode":
WINDOW.setProperty(playurl+"refresh_id", result.get("SeriesId"))
@@ -169,12 +148,7 @@ class PlaybackUtils():
self.setListItemProps(server, id, listItem, result)
xbmc.Player().play(playurl,listItem)
elif setup == "default":
- #artwork only works from widgets (home screen) with player command as there is no listitem selected
- if xbmc.getCondVisibility("Window.IsActive(home)"):
- self.setListItemProps(server, id, listItem, result)
- xbmc.Player().play(playurl,listItem)
- else:
- xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listItem)
+ xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listItem)
def setArt(self, list,name,path):
if name=='thumb' or name=='fanart_image' or name=='small_poster' or name=='tiny_poster' or name == "medium_landscape" or name=='medium_poster' or name=='small_fanartimage' or name=='medium_fanartimage' or name=='fanart_noindicators':
@@ -255,7 +229,7 @@ class PlaybackUtils():
xbmc.sleep(500)
#Jump to resume point
- jumpBackSec = 10#int(self.settings.getSetting("resumeJumpBack"))
+ jumpBackSec = int(addon.getSetting("resumeJumpBack"))
seekToTime = seekTo - jumpBackSec
count = 0
while xbmc.Player().getTime() < (seekToTime - 5) and count < 11: # only try 10 times
@@ -382,7 +356,7 @@ class PlaybackUtils():
if item.get("Type") == "Episode" and addon.getSetting("offerDeleteTV")=="true":
WINDOW.setProperty(playurl + "deleteurl", deleteurl)
if item.get("Type") == "Movie" and addon.getSetting("offerDeleteMovies")=="true":
- WINDOW.setProperty(playurl + "deleteurl", deleteurl)
+ WINDOW.setProperty(playurl + "deleteurl", deleteurl)
WINDOW.setProperty(playurl + "runtimeticks", str(item.get("RunTimeTicks")))
WINDOW.setProperty(playurl+"type", item.get("Type"))
diff --git a/resources/lib/Player.py b/resources/lib/Player.py
index 3e5fd9cd..9e59e789 100644
--- a/resources/lib/Player.py
+++ b/resources/lib/Player.py
@@ -239,121 +239,6 @@ class Player( xbmc.Player ):
currentFile = xbmcplayer.getPlayingFile()
except: pass
self.logMsg("onPlayBackStarted: %s" % currentFile, 0)
-
- playMethod = WINDOW.getProperty(currentFile + "playmethod")
-
- # Set audio and subtitles automatically
- # Following Emby user preference.
- '''if self.audioPref == "default" and self.subsPref == "default":
- self.logMsg("No Emby user preferences found.", 2)
- # Emby user preferences are not set.
- pass
- elif playMethod == "DirectPlay" or playMethod == "DirectStream":
- # Only currently compatible with DirectPlay.
- # Tested on plugin://, unsure about direct paths.
- self.logMsg("Audio Pref: %s Subtitles Pref: %s" % (self.audioPref, self.subsPref), 1)
- audiotracks = xbmcplayer.getAvailableAudioStreams()
- subs = xbmcplayer.getAvailableSubtitleStreams()
- self.logMsg("%s %s" % (audiotracks, subs), 1)
- defaultsubs = WINDOW.getProperty("%ssubs" % currentFile)
-
- codecs = [
- # Possible codecs
- 'und','Stereo','AC3','DTS', '5.1'
- #'Stereo - Stereo','AC3 5.1', 'DTS 5.1', 'DTS-HD MA 5.1'
- ]
-
- if len(audiotracks) == 1 and len(subs) == 0:
- # There's only one audio track and no subtitles
- xbmcplayer.showSubtitles(False)
-
- else:
- # More complex cases
- codec_intrack = False
- for codec in codecs:
- if codec in '\n'.join(audiotracks):
- codec_intrack = True
-
- if self.audioPref in audiotracks:
- self.logMsg("Door 1", 1)
- # Audio pref is available
- index = audiotracks.index(self.audioPref)
- xbmcplayer.setAudioStream(index)
-
- if addon.getSetting('subsoverride') == "true":
- if self.subsPref in subs:
- self.logMsg("Door 1.1", 1)
- # Subs are forced.
- index = subs.index(self.subsPref)
- xbmcplayer.setSubtitleStream(index)
- else:
- # Use default subs
- if defaultsubs == "ssa" or defaultsubs == "srt":
- # For some reason, Kodi sees SSA as ''
- self.logMsg("Door 1.2", 1)
- index = subs.index('')
- xbmcplayer.setSubtitleStream(index)
- elif defaultsubs:
- self.logMsg("Door 1.3", 1)
- index = subs.index(defaultsubs)
- xbmcplayer.setSubtitleStream(index)
- else:
- xbmcplayer.showSubtitles(False)
-
- elif (len(audiotracks) == 1) and not codec_intrack:
- self.logMsg("Door 2", 1)
- # 1. There's one audio track.
- # 2. The audio is defined as a language.
- # 3. Audio pref is not available, guaranteed.
- if self.subsPref in subs:
- self.logMsg("Door 2.1", 1)
- # Subs pref is available.
- index = subs.index(self.subsPref)
- xbmcplayer.setSubtitleStream(index)
- else:
- # Use default subs
- if defaultsubs == "ssa" or defaultsubs == "srt":
- # For some reason, Kodi sees SSA as ''
- self.logMsg("Door 2.2", 1)
- index = subs.index('')
- xbmcplayer.setSubtitleStream(index)
- elif defaultsubs:
- self.logMsg("Door 2.3", 1)
- index = subs.index(defaultsubs)
- xbmcplayer.setSubtitleStream(index)
-
- elif len(audiotracks) == 1 and codec_intrack:
- self.logMsg("Door 3", 1)
- # 1. There one audio track.
- # 2. The audio is undefined or a codec.
- # 3. Audio track is mislabeled.
- if self.subsPref in subs:
- # If the subtitle is available, only display
- # if the setting is enabled.
- if addon.getSetting('subsoverride') == "true":
- # Subs are forced.
- self.logMsg("Door 3.2", 1)
- index = subs.index(self.subsPref)
- xbmcplayer.setSubtitleStream(index)
- else:
- # Let the user decide, since track is mislabeled.
- self.logMsg("Door 3.3")
- xbmcplayer.showSubtitles(False)
- else:
- # Use default subs
- if defaultsubs == "ssa" or defaultsubs == "srt":
- # For some reason, Kodi sees SSA as ''
- self.logMsg("Door 3.4", 1)
- index = subs.index('')
- xbmcplayer.setSubtitleStream(index)
- elif defaultsubs:
- self.logMsg("Door 3.5", 1)
- index = subs.index(defaultsubs)
- xbmcplayer.setSubtitleStream(index)
- else:
- # Nothing matches, let the user decide.
- self.logMsg("Door 3.6", 1)
- xbmcplayer.showSubtitles(False)'''
# we may need to wait until the info is available
item_id = WINDOW.getProperty(currentFile + "item_id")
@@ -374,7 +259,6 @@ class Player( xbmc.Player ):
subtitleindex = WINDOW.getProperty(currentFile + "SubtitleStreamIndex")
playMethod = WINDOW.getProperty(currentFile + "playmethod")
itemType = WINDOW.getProperty(currentFile + "type")
- seekTime = WINDOW.getProperty(currentFile + "seektime")
# Get playback volume
volume_query = '{"jsonrpc": "2.0", "method": "Application.GetProperties", "params": {"properties": ["volume","muted"]}, "id": 1}'
@@ -382,11 +266,8 @@ class Player( xbmc.Player ):
result = json.loads(result)
volume = result.get(u'result').get(u'volume')
muted = result.get(u'result').get(u'muted')
-
- if seekTime:
- PlaybackUtils().seekToPosition(int(seekTime))
- else:
- seekTime = 0
+
+ seekTime = xbmc.Player().getTime()
url = "{server}/mediabrowser/Sessions/Playing"
postdata = {
diff --git a/resources/lib/UserClient.py b/resources/lib/UserClient.py
index f5915164..104bc337 100644
--- a/resources/lib/UserClient.py
+++ b/resources/lib/UserClient.py
@@ -239,7 +239,7 @@ class UserClient(threading.Thread):
url = "%s/mediabrowser/Users/%s" % (self.currServer, self.currUserId)
WINDOW.setProperty("currUser", username)
WINDOW.setProperty("accessToken%s" % username, self.currToken)
- result = doUtils.downloadUrl(url, type="POST")
+ result = doUtils.downloadUrl(url)
if result == 401:
# Token is no longer valid
self.resetClient()
diff --git a/resources/lib/Utils.py b/resources/lib/Utils.py
index 5ea5bcfa..eec80d54 100644
--- a/resources/lib/Utils.py
+++ b/resources/lib/Utils.py
@@ -157,6 +157,43 @@ def stopProfiling(pr, profileName):
f.write(str(ncalls) + "\t" + "{0}".format(total_time) + "\t" + "{0}".format(cumulative_time) + "\t" + func_name + "\t" + filename + "\r\n")
f.close()
+def createSources():
+ # To make Master lock compatible
+ path = xbmc.translatePath("special://profile/").decode("utf-8")
+ xmlpath = "%ssources.xml" % path
+
+ sources = open(xmlpath, 'w')
+ sources.write(
+
+ '\n\t'
+ '\n\t\t'
+ '\n\t'
+ '\n\t'
+ '\n\t'
+ '\n\t\t'
+ '\n\t'
+ '\n\t'
+ '\n\t\t'
+ '\n\t'
+ '\n\t'
+ '\n\t\t'
+ '\n\t'
+ '\n'
+ ''
+ )
+
def CleanName(filename):
validFilenameChars = "-_.() %s%s" % (string.ascii_letters, string.digits)
cleanedFilename = unicodedata.normalize('NFKD', filename).encode('ASCII', 'ignore')
diff --git a/resources/lib/WriteKodiVideoDB.py b/resources/lib/WriteKodiVideoDB.py
index f4327ab9..be023ba3 100644
--- a/resources/lib/WriteKodiVideoDB.py
+++ b/resources/lib/WriteKodiVideoDB.py
@@ -62,9 +62,9 @@ class WriteKodiVideoDB():
# Found the Emby Id, let Emby server know of new playcount
watchedurl = "{server}/mediabrowser/Users/{UserId}/PlayedItems/%s" % emby_id
if playcount != 0:
- doUtils.downloadUtils(watchedurl, type = "POST")
+ doUtils.downloadUrl(watchedurl, type = "POST")
else:
- doUtils.downloadUtils(watchedurl, type = "DELETE")
+ doUtils.downloadUrl(watchedurl, type = "DELETE")
# Erase any resume point associated
self.setKodiResumePoint(id, 0, 0, cursor)
finally:
@@ -252,6 +252,39 @@ class WriteKodiVideoDB():
# To avoid negative bookmark
resume = resume - jumpback
self.setKodiResumePoint(fileid, resume, total, cursor)
+
+ # Create a dummy bookmark for homescreen - widgets
+ if not self.directpath:
+ plugindummy = "plugin://plugin.video.emby/"
+ cursor.execute("SELECT idPath as pathid FROM path WHERE strPath = ?", (plugindummy,))
+ try:
+ pathid = cursor.fetchone()[0]
+ except:
+ # Top level path does not exist yet
+ cursor.execute("select coalesce(max(idPath),0) as tlpathid from path")
+ pathid = cursor.fetchone()[0] + 1
+ query = "INSERT INTO path(idPath, strPath, strContent, strScraper, noUpdate) values(?, ?, ?, ?, ?)"
+ cursor.execute(query, (pathid, plugindummy, "tvshows", "metadata.local", 1))
+
+ # Validate the file in database
+ cursor.execute("SELECT idFile as fileid FROM files WHERE strFilename = ? and idPath = ?", (filename, pathid,))
+ try:
+ fileid = cursor.fetchone()[0]
+ except:
+ # File does not exist yet
+ if resume:
+ cursor.execute("select coalesce(max(idFile),0) as fileid from files")
+ fileid = cursor.fetchone()[0] + 1
+ query = "INSERT INTO files(idFile, idPath, strFilename, playCount, lastPlayed, dateAdded) values(?, ?, ?, ?, ?, ?)"
+ cursor.execute(query, (fileid, pathid, filename, playcount, dateplayed, dateadded))
+ self.setKodiResumePoint(fileid, resume, total, cursor)
+ else: # File exists
+ if not resume:
+ cursor.execute("DELETE FROM files WHERE idFile = ?", (fileid,))
+ else:
+ query = "UPDATE files SET playCount = ?, lastPlayed = ? WHERE idFile = ?"
+ cursor.execute(query, (playcount, dateplayed, fileid))
+ self.setKodiResumePoint(fileid, resume, total, cursor)
def addOrUpdateMusicVideoToKodiLibrary(self, embyId ,connection, cursor):
@@ -652,6 +685,12 @@ class WriteKodiVideoDB():
# Update or insert actors
self.AddPeopleToMedia(episodeid, MBitem.get('People'), "episode", connection, cursor)
+ # Add streamdetails
+ self.AddStreamDetailsToMedia(API().getMediaStreams(MBitem), fileid, cursor)
+
+ # Update artwork
+ self.addOrUpdateArt(API().getArtwork(MBitem, "Primary", mediaType = "episode"), episodeid, "episode", "thumb", cursor)
+
# Set resume point and round to 6th decimal
resume = round(float(timeInfo.get('ResumeTime')), 6)
total = round(float(timeInfo.get('TotalTime')), 6)
@@ -660,12 +699,40 @@ class WriteKodiVideoDB():
# To avoid negative bookmark
resume = resume - jumpback
self.setKodiResumePoint(fileid, resume, total, cursor)
-
- # Add streamdetails
- self.AddStreamDetailsToMedia(API().getMediaStreams(MBitem), fileid, cursor)
-
- # Update artwork
- self.addOrUpdateArt(API().getArtwork(MBitem, "Primary", mediaType = "episode"), episodeid, "episode", "thumb", cursor)
+
+ if not self.directpath:
+ # Create a dummy bookmark for homescreen - widgets
+ plugindummy = "plugin://plugin.video.emby/"
+ cursor.execute("SELECT idPath as pathid FROM path WHERE strPath = ?", (plugindummy,))
+ try:
+ pathid = cursor.fetchone()[0]
+ except:
+ # Top level path does not exist yet
+ cursor.execute("select coalesce(max(idPath),0) as tlpathid from path")
+ pathid = cursor.fetchone()[0] + 1
+ query = "INSERT INTO path(idPath, strPath, strContent, strScraper, noUpdate) values(?, ?, ?, ?, ?)"
+ cursor.execute(query, (pathid, plugindummy, "tvshows", "metadata.local", 1))
+
+ # Validate the file in database
+ cursor.execute("SELECT idFile as fileid FROM files WHERE strFilename = ? and idPath = ?", (filename, pathid,))
+ try:
+ fileid = cursor.fetchone()[0]
+ except:
+ # File does not exist yet
+ if resume:
+ cursor.execute("select coalesce(max(idFile),0) as fileid from files")
+ fileid = cursor.fetchone()[0] + 1
+ query = "INSERT INTO files(idFile, idPath, strFilename, playCount, lastPlayed, dateAdded) values(?, ?, ?, ?, ?, ?)"
+ cursor.execute(query, (fileid, pathid, filename, playcount, dateplayed, dateadded))
+ self.setKodiResumePoint(fileid, resume, total, cursor)
+ else: # File exists
+ if not resume:
+ cursor.execute("DELETE FROM files WHERE idFile = ?", (fileid,))
+ else:
+ query = "UPDATE files SET playCount = ?, lastPlayed = ? WHERE idFile = ?"
+ cursor.execute(query, (playcount, dateplayed, fileid))
+ self.setKodiResumePoint(fileid, resume, total, cursor)
+
def deleteItemFromKodiLibrary(self, id, connection, cursor ):
diff --git a/resources/settings.xml b/resources/settings.xml
index 83ea2959..4e168207 100644
--- a/resources/settings.xml
+++ b/resources/settings.xml
@@ -25,6 +25,7 @@
+