mirror of
https://github.com/jellyfin/jellyfin-kodi.git
synced 2024-12-26 02:36:10 +00:00
Fix for merge
Create sources, fix for user pref login bug, create a dummy bookmark for homescreen, remove workaround for resume point
This commit is contained in:
parent
d974c4ed7c
commit
4e7cbc56ba
7 changed files with 125 additions and 159 deletions
|
@ -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 ###
|
||||
|
||||
|
|
|
@ -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"))
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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(
|
||||
|
||||
'<sources>\n\t'
|
||||
'<programs>\n\t\t'
|
||||
'<default pathversion="1"></default>\n\t'
|
||||
'</programs>\n\t'
|
||||
'<video>\n\t\t'
|
||||
'<default pathversion="1"></default>\n\t\t'
|
||||
'<source>\n\t\t\t'
|
||||
'<name>dummy one</name>\n\t\t\t'
|
||||
'<path pathversion="1">smb://embydummy/dummypath1/</path>\n\t\t\t'
|
||||
'<allowsharing>true</allowsharing>\n\t\t'
|
||||
'</source>\n\t\t'
|
||||
'<source>\n\t\t\t'
|
||||
'<name>dummy two</name>\n\t\t\t'
|
||||
'<path pathversion="1">smb://embydummy/dummypath2/</path>\n\t\t\t'
|
||||
'<allowsharing>true</allowsharing>\n\t\t'
|
||||
'</source>\n\t'
|
||||
'</video>\n\t'
|
||||
'<music>\n\t\t'
|
||||
'<default pathversion="1"></default>\n\t'
|
||||
'</music>\n\t'
|
||||
'<pictures>\n\t\t'
|
||||
'<default pathversion="1"></default>\n\t'
|
||||
'</pictures>\n\t'
|
||||
'<files>\n\t\t'
|
||||
'<default pathversion="1"></default>\n\t'
|
||||
'</files>\n'
|
||||
'</sources>'
|
||||
)
|
||||
|
||||
def CleanName(filename):
|
||||
validFilenameChars = "-_.() %s%s" % (string.ascii_letters, string.digits)
|
||||
cleanedFilename = unicodedata.normalize('NFKD', filename).encode('ASCII', 'ignore')
|
||||
|
|
|
@ -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 ):
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
<setting id="smbusername" type="text" label="30007" default="" visible="true" enable="true" />
|
||||
<setting id="smbpassword" type="text" label="30008" default="" option="hidden" visible="true" enable="true" />
|
||||
<setting type="sep" />
|
||||
<setting id="resumeJumpBack" type="slider" label="30114" default="10" range="0,1,120" option="int" visible="true" enable="true" />
|
||||
<setting id="offerDelete" type="bool" label="30114" visible="true" enable="true" default="false" />
|
||||
<setting id="offerDeleteTV" type="bool" label=" 30115" visible="eq(-1,true)" enable="true" default="false" />
|
||||
<setting id="offerDeleteMovies" type="bool" label="30116" visible="eq(-2,true)" enable="true" default="false" />
|
||||
|
|
Loading…
Reference in a new issue