fix for the merge that didn't follow

Media path fix, and clean up of writeKodiVideoDB. Fix for library sync
for deletes.
This commit is contained in:
angelblue05 2015-07-18 03:08:05 -05:00
parent 3589c4b05d
commit 0c54257de6
4 changed files with 1281 additions and 1300 deletions

View file

@ -1,3 +1,4 @@
# -- coding: utf-8 --
# API.py # API.py
# This class helps translate more complex cases from the MediaBrowser API to the XBMC API # This class helps translate more complex cases from the MediaBrowser API to the XBMC API
@ -14,140 +15,155 @@ class API():
director = [] director = []
writer = [] writer = []
cast = [] cast = []
people = item.get("People")
if(people != None): try:
people = item['People']
except: pass
else:
for person in people: for person in people:
if(person.get("Type") == "Director"):
director.append(person.get("Name")) type = person['Type']
if(person.get("Type") == "Writing"): Name = person['Name']
writer.append(person.get("Name"))
if(person.get("Type") == "Writer"): if "Director" in type:
writer.append(person.get("Name")) director.append(Name)
if(person.get("Type") == "Actor"): elif "Writing" in type:
Name = person.get("Name") writer.append(Name)
Role = person.get("Role") elif "Writer" in type:
if Role == None: writer.append(Name)
Role = '' elif "Actor" in type:
cast.append(Name) cast.append(Name)
return {'Director' : director,
return {
'Director': director,
'Writer': writer, 'Writer': writer,
'Cast': cast 'Cast': cast
} }
def getTimeInfo(self, item): def getTimeInfo(self, item):
resumeTime = '' # Runtime and Resume point
userData = item.get("UserData") tempRuntime = 0
PlaybackPositionTicks = '100' runtime = 0
if userData.get("PlaybackPositionTicks") != None:
PlaybackPositionTicks = str(userData.get("PlaybackPositionTicks"))
reasonableTicks = int(userData.get("PlaybackPositionTicks")) / 1000
resumeTime = reasonableTicks / 10000
try:
tempDuration = str(int(item.get("RunTimeTicks", "0"))/(10000000*60))
except TypeError:
try:
tempDuration = str(int(item.get("CumulativeRunTimeTicks"))/(10000000*60))
except TypeError:
tempDuration = "0"
cappedPercentage = None
resume = 0 resume = 0
percentage=0
if (resumeTime != "" and int(resumeTime) > 0): try: # Get resume point
duration = float(tempDuration) userdata = item['UserData']
if(duration > 0): playbackPosition = userdata['PlaybackPositionTicks']
resume = float(resumeTime) / 60 resume = playbackPosition / 10000000.0
percentage = int((resume / duration) * 100.0) except: pass
return {'Duration' : tempDuration,
'TotalTime' : tempDuration, try: # Get total runtime
'Percent' : str(percentage), tempRuntime = item['RunTimeTicks']
'ResumeTime' : str(resume)
except:
try: tempRuntime = item['CumulativeRunTimeTicks']
except: pass
finally:
runtime = tempRuntime / 10000000.0
return {
'ResumeTime': resume,
'TotalTime': runtime
} }
def getStudios(self, item): def getStudios(self, item):
# Process Studio # Process Studio
studios = [] studios = []
if item.get("SeriesStudio") != None and item.get("SeriesStudio") != '':
studios.append(item.get("SeriesStudio")) try:
else: studio = item['SeriesStudio']
if(item.get("Studios") != []): studios.append(studio)
for studio_string in item.get("Studios"): except:
temp=studio_string.get("Name") try:
studios.append(temp) studioArray = item['Studios']
for studio in studioArray:
studios.append(studio['Name'])
except: pass
return studios return studios
def getMediaStreams(self, item, mediaSources=False): def getGenre(self,item):
# Process MediaStreams genre = ""
channels = '' genres = item.get("Genres")
videocodec = '' if genres != None and genres != []:
audiocodec = '' for genre_string in genres:
audiolanguage = '' if genre == "": #Just take the first genre
subtitlelanguage = '' genre = genre_string
height = ''
width = ''
aspectratio = '1:1'
aspectfloat = 1.85
Video3DFormat = ''
if mediaSources == True:
mediaSources = item.get("MediaSources")
if(mediaSources != None):
MediaStreams = mediaSources[0].get("MediaStreams")
else: else:
genre = genre + " / " + genre_string
elif item.get("SeriesGenres") != None and item.get("SeriesGenres") != '':
genres = item.get("SeriesGenres")
if genres != None and genres != []:
for genre_string in genres:
if genre == "": #Just take the first genre
genre = genre_string
else:
genre = genre + " / " + genre_string
return genre
def getMediaStreams(self, item, mediaSources = False):
videotracks = [] # Height, Width, Codec, AspectRatio, AspectFloat, 3D
audiotracks = [] # Codec, Channels, language
subtitlelanguages = [] # Language
if mediaSources:
try:
MediaStreams = item['MediaSources'][0]['MediaStreams']
except:
MediaStreams = None MediaStreams = None
else: else:
MediaStreams = item.get("MediaStreams") MediaStreams = item.get('MediaStreams')
if(MediaStreams != None):
#mediaStreams = MediaStreams[0].get("MediaStreams") if MediaStreams:
if(MediaStreams != None): # Sort through the Video, Audio, Subtitle tracks
for mediaStream in MediaStreams: for mediaStream in MediaStreams:
if(mediaStream.get("Type") == "Video"):
videocodec = mediaStream.get("Codec") type = mediaStream.get("Type", "")
if mediaStream.get("Height"):
height = int(mediaStream.get("Height")) if "Video" in type:
if mediaStream.get("Width"): videotrack = {}
width = int(mediaStream.get("Width")) videotrack['videocodec'] = mediaStream.get('Codec')
aspectratio = mediaStream.get("AspectRatio") videotrack['height'] = mediaStream.get('Height')
Video3DFormat = item.get("Video3DFormat") videotrack['width'] = mediaStream.get('Width')
if aspectratio != None and len(aspectratio) >= 3: videotrack['aspectratio'] = mediaStream.get('AspectRatio')
videotrack['Video3DFormat'] = item.get('Video3DFormat')
if len(videotrack['aspectratio']) >= 3:
try: try:
aspectwidth, aspectheight = aspectratio.split(':') aspectwidth, aspectheight = aspectratio.split(':')
aspectfloat = float(aspectwidth) / float(aspectheight) videotrack['aspectfloat'] = float(aspectwidth) / float(aspectheight)
except: except:
aspectfloat = 1.85 videotrack['aspectfloat'] = 1.85
if(mediaStream.get("Type") == "Audio"): videotracks.append(videotrack)
isdefault = mediaStream.get("IsDefault") == "true"
if audiocodec == '':
audiocodec = mediaStream.get("Codec")
if channels == '':
channels = mediaStream.get("Channels")
if audiolanguage == '':
audiolanguage = mediaStream.get("Language")
# only overwrite if default
if isdefault:
audiocodec = mediaStream.get("Codec")
channels = mediaStream.get("Channels")
audiolanguage = mediaStream.get("Language")
if(mediaStream.get("Type") == "Subtitle"):
isdefault = mediaStream.get("IsDefault") == "true"
if subtitlelanguage == '':
subtitlelanguage = mediaStream.get("Language")
# only overwrite if default
if isdefault:
subtitlelanguage = mediaStream.get("Language")
elif "Audio" in type:
audiotrack = {}
audiotrack['audiocodec'] = mediaStream.get('Codec')
audiotrack['channels'] = mediaStream.get('Channels')
audiotrack['audiolanguage'] = mediaStream.get('Language')
audiotracks.append(audiotrack)
return {'channels' : str(channels), elif "Subtitle" in type:
'videocodec' : videocodec, try:
'audiocodec' : audiocodec, subtitlelanguages.append(mediaStream['Language'])
'audiolanguage' : audiolanguage, except:
'subtitlelanguage' : subtitlelanguage, subtitlelanguages.append("Unknown")
'height' : height,
'width' : width, return {
'aspectratio' : aspectfloat,
'3dformat' : Video3DFormat 'videocodec' : videotracks,
'audiocodec' : audiotracks,
'subtitlelanguage' : subtitlelanguages
} }
def getChecksum(self, item): def getChecksum(self, item):
# use the etags checksum for this if available # use the etags checksum for this if available
# AND the userdata # AND the userdata
@ -169,75 +185,43 @@ class API():
return checksum return checksum
def getUserData(self, item): def getUserData(self, item):
userData = item.get("UserData") # Default
resumeTime = 0
if(userData != None):
if userData.get("Played") != True:
watched="True"
else:
watched="False"
if userData.get("IsFavorite") == True:
favorite=True
else:
favorite = False favorite = False
if(userData.get("Played") == True): playcount = None
# Cover the Emby scenario where item is played but playcount is 0. lastPlayedDate = None
playcount = userData.get('PlayCount') userKey = ""
try:
userdata = item['UserData']
except: # No userdata found.
pass
else:
favorite = userdata['IsFavorite']
userKey = userdata.get('Key', "")
watched = userdata['Played']
if watched:
# Playcount is tied to the watch status
playcount = userdata['PlayCount']
if playcount == 0: if playcount == 0:
playcount = 1 playcount = 1
else: else:
playcount="0" playcount = None
if userData.get('UnplayedItemCount') != None:
UnplayedItemCount = userData.get('UnplayedItemCount') lastPlayedDate = userdata.get('LastPlayedDate', None)
else: if lastPlayedDate:
UnplayedItemCount = "0" lastPlayedDate = lastPlayedDate.split('.')[0].replace('T', " ")
if userData.get('LastPlayedDate') != None:
#TODO--> is there some other way to do this ? return {
datestring = userData.get('LastPlayedDate').split('T')[0]
timestring = userData.get('LastPlayedDate').split('T')[1]
timestring = timestring.split('.')[0]
LastPlayedDate = datestring + " " + timestring
else:
LastPlayedDate = None
if userData.get('PlaybackPositionTicks') != None:
PlaybackPositionTicks = userData.get('PlaybackPositionTicks')
else:
PlaybackPositionTicks = ''
userKey = userData.get("Key", "")
return {'Watched' : watched,
'Favorite': favorite, 'Favorite': favorite,
'PlayCount': playcount, 'PlayCount': playcount,
'LastPlayedDate': LastPlayedDate, 'LastPlayedDate': lastPlayedDate,
'UnplayedItemCount' : UnplayedItemCount,
'PlaybackPositionTicks' : str(PlaybackPositionTicks),
'Key': userKey 'Key': userKey
} }
def getGenre(self,item):
genre = ""
genres = item.get("Genres")
if genres != None and genres != []:
for genre_string in genres:
if genre == "": #Just take the first genre
genre = genre_string
else:
genre = genre + " / " + genre_string
elif item.get("SeriesGenres") != None and item.get("SeriesGenres") != '':
genres = item.get("SeriesGenres")
if genres != None and genres != []:
for genre_string in genres:
if genre == "": #Just take the first genre
genre = genre_string
else:
genre = genre + " / " + genre_string
return genre
def getName(self, item):
Temp = item.get("Name")
if Temp == None:
Temp = ""
Name=Temp.encode('utf-8')
return Name
def getRecursiveItemCount(self, item): def getRecursiveItemCount(self, item):
if item.get("RecursiveItemCount") != None: if item.get("RecursiveItemCount") != None:
@ -245,33 +229,18 @@ class API():
else: else:
return "0" return "0"
def getSeriesName(self, item):
Temp = item.get("SeriesName")
if Temp == None:
Temp = ""
Name=Temp.encode('utf-8')
return Name
def getOverview(self, item): def getOverview(self, item):
Temp = item.get("Overview")
if Temp == None:
Temp=''
Overview1=Temp.encode('utf-8')
Overview=str(Overview1)
Overview=Overview.replace("\"", "\'")
Overview=Overview.replace("\n", " ")
Overview=Overview.replace("\r", " ")
return Overview
def getPremiereDate(self, item): overview = ""
if(item.get("PremiereDate") != None):
premieredatelist = (item.get("PremiereDate")).split("T") try:
premieredate = premieredatelist[0] overview = item['Overview']
else: overview = overview.replace("\"", "\'")
premieredate = "" overview = overview.replace("\n", " ")
Temp = premieredate overview = overview.replace("\r", " ")
premieredate = Temp.encode('utf-8') except: pass
return premieredate
return overview
def getTVInfo(self, item, userData): def getTVInfo(self, item, userData):
TotalSeasons = 0 if item.get("ChildCount")==None else item.get("ChildCount") TotalSeasons = 0 if item.get("ChildCount")==None else item.get("ChildCount")
@ -306,15 +275,105 @@ class API():
'Episode' : tempEpisode, 'Episode' : tempEpisode,
'SeriesName' : SeriesName 'SeriesName' : SeriesName
} }
def getDateCreated(self, item): def getDateCreated(self, item):
tempDate = item.get("DateCreated")
if tempDate != None: dateadded = None
tempDate = tempDate.split("T")[0]
date = tempDate.split("-") try:
tempDate = date[2] + "." + date[1] + "." +date[0] dateadded = item['DateCreated']
else: dateadded = dateadded.split('.')[0].replace('T', " ")
tempDate = "01.01.2000" except: pass
return tempDate
return dateadded
def getPremiereDate(self, item):
premiere = None
try:
premiere = item['PremiereDate']
premiere = premiere.split('.')[0].replace('T', " ")
except: pass
return premiere
def getTagline(self, item):
tagline = None
try:
tagline = item['Taglines'][0]
except: pass
return tagline
def getProvider(self, item, providername):
# Provider Name: imdb or tvdb
provider = None
try:
if "imdb" in providername:
provider = item['ProviderIds']['Imdb']
elif "tvdb" in providername:
provider = item['ProviderIds']['Tvdb']
except: pass
return provider
def getCountry(self, item):
country = None
try:
country = item['ProductionLocations'][0]
except: pass
return country
def getArtworks(self, data, type, mediaType = "", index = "0", getAll = False):
"""
Get all artwork, it will return an empty string
for the artwork type not found.
Index only matters when getAll is False.
mediaType: movie, boxset, tvshow, episode, season
Artwork type: Primary, Banner, Logo, Art, Thumb,
Disc Backdrop
"""
id = data['Id']
maxHeight = 10000
maxWidth = 10000
imageTag = "e3ab56fe27d389446754d0fb04910a34" # Place holder tag
if getAll:
allartworks = {
'Primary': "",
'Banner': "",
'Logo': "",
'Art': "",
'Thumb': "",
'Disc': "",
'Backdrop': ""
}
for keytype in allartworks:
type = keytype
url = ""
allartworks[keytype] = url
return allartworks
else: pass
def getArtwork(self, data, type, mediaType = "", index = "0", userParentInfo = False): def getArtwork(self, data, type, mediaType = "", index = "0", userParentInfo = False):
@ -417,6 +476,14 @@ class API():
return artwork return artwork
def imageUrl(self, id, type, index, width, height):
WINDOW = xbmcgui.Window(10000)
username = WINDOW.getProperty('currUser')
server = WINDOW.getProperty('server%s' % username)
# For people image - actors, directors, writers
return "%s/mediabrowser/Items/%s/Images/%s?MaxWidth=%s&MaxHeight=%s&Index=%s" % (server, id, type, width, height, index)
def getUserArtwork(self, data, type, index = "0"): def getUserArtwork(self, data, type, index = "0"):
# Load user information set by UserClient # Load user information set by UserClient

View file

@ -659,61 +659,67 @@ class LibrarySync(threading.Thread):
# Delete from Kodi before Emby # Delete from Kodi before Emby
# To be able to get mediaType # To be able to get mediaType
doUtils = DownloadUtils() doUtils = DownloadUtils()
video = {}
video = []
music = [] music = []
itemIds = ','.join(itemList) # Database connection to myVideosXX.db
url = "{server}/mediabrowser/Users/{UserId}/Items?Ids=%s&format=json" % itemIds connectionvideo = utils.KodiSQL()
result = doUtils.downloadUrl(url) cursorvideo = connectionvideo.cursor()
# Database connection to myMusicXX.db
connectionmusic = utils.KodiSQL("music")
cursormusic = connectionmusic.cursor()
if result is "": for item in itemList:
# Websocket feedback
self.logMsg("Item %s is removed." % itemIds)
return
for item in result[u'Items']:
# Sort by type for database deletion # Sort by type for database deletion
itemId = item["Id"] try: # Search video database
mediaType = item["MediaType"] self.logMsg("Check video database.", 1)
cursorvideo.execute("SELECT media_type FROM emby WHERE emby_id = ?", (item,))
if "Video" in mediaType: mediatype = cursorvideo.fetchone()[0]
video.append(itemId) video[item] = mediatype
elif "Audio" in mediaType: #video.append(itemtype)
music.append(itemId) except:
self.logMsg("Check music database.", 1)
try: # Search music database
cursormusic.execute("SELECT media_type FROM emby WHERE emby_id = ?", (item,))
cursormusic.fetchone()[0]
music.append(item)
except: self.logMsg("Item %s is not found in Kodi database." % item, 1)
if len(video) > 0: if len(video) > 0:
connection = connectionvideo
cursor = cursorvideo
# Process video library # Process video library
connection = utils.KodiSQL("video")
cursor = connection.cursor()
for item in video: for item in video:
type = ReadKodiDB().getTypeByEmbyId(item, connection, cursor)
self.logMsg("Type: %s" % type) type = video[item]
self.logMsg("Message: Doing LibraryChanged: Items Removed: Calling deleteItemFromKodiLibrary: %s" % item, 0) self.logMsg("Doing LibraryChanged: Items Removed: Calling deleteItemFromKodiLibrary: %s" % item, 1)
if "episode" in type: if "episode" in type:
# Get the TV Show Id for reference later # Get the TV Show Id for reference later
showId = ReadKodiDB().getShowIdByEmbyId(item, connection, cursor) showId = ReadKodiDB().getShowIdByEmbyId(item, connection, cursor)
self.logMsg("ShowId: %s" % showId, 0) self.logMsg("ShowId: %s" % showId, 1)
WriteKodiVideoDB().deleteItemFromKodiLibrary(item, connection, cursor) WriteKodiVideoDB().deleteItemFromKodiLibrary(item, connection, cursor)
# Verification # Verification
if "episode" in type: if "episode" in type:
showTotalCount = ReadKodiDB().getShowTotalCount(showId, connection, cursor) showTotalCount = ReadKodiDB().getShowTotalCount(showId, connection, cursor)
self.logMsg("ShowTotalCount: %s" % showTotalCount, 0) self.logMsg("ShowTotalCount: %s" % showTotalCount, 1)
# If there are no episodes left # If there are no episodes left
if showTotalCount == 0 or showTotalCount == None: if showTotalCount == 0 or showTotalCount == None:
# Delete show # Delete show
embyId = ReadKodiDB().getEmbyIdByKodiId(showId, "tvshow", connection, cursor) embyId = ReadKodiDB().getEmbyIdByKodiId(showId, "tvshow", connection, cursor)
self.logMsg("Message: Doing LibraryChanged: Deleting show: %s" % embyId, 0) self.logMsg("Message: Doing LibraryChanged: Deleting show: %s" % embyId, 1)
WriteKodiVideoDB().deleteItemFromKodiLibrary(embyId, connection, cursor) WriteKodiVideoDB().deleteItemFromKodiLibrary(embyId, connection, cursor)
connection.commit() connection.commit()
cursor.close() # Close connection
cursorvideo.close()
if len(music) > 0: if len(music) > 0:
connection = connectionmusic
cursor = cursormusic
#Process music library #Process music library
addon = xbmcaddon.Addon(id='plugin.video.emby') addon = xbmcaddon.Addon()
if addon.getSetting("enableMusicSync") is "true": if addon.getSetting('enableMusicSync') == "true":
connection = utils.KodiSQL("music") connection = utils.KodiSQL("music")
cursor = connection.cursor() cursor = connection.cursor()
@ -722,7 +728,8 @@ class LibrarySync(threading.Thread):
WriteKodiMusicDB().deleteItemFromKodiLibrary(item, connection, cursor) WriteKodiMusicDB().deleteItemFromKodiLibrary(item, connection, cursor)
connection.commit() connection.commit()
cursor.close() # Close connection
cursormusic.close()
if deleteEmbyItem: if deleteEmbyItem:
for item in itemList: for item in itemList:
@ -732,25 +739,23 @@ class LibrarySync(threading.Thread):
xbmc.executebuiltin("Container.Refresh") xbmc.executebuiltin("Container.Refresh")
def remove_items(self, itemsRemoved): def remove_items(self, itemsRemoved):
# websocket client
self.removeItems.extend(itemsRemoved) self.removeItems.extend(itemsRemoved)
def update_items(self, itemsToUpdate): def update_items(self, itemsToUpdate):
# doing adds and updates # websocket client
if(len(itemsToUpdate) > 0): if(len(itemsToUpdate) > 0):
self.logMsg("Message : Doing LibraryChanged : Processing Added and Updated : " + str(itemsToUpdate), 0) self.logMsg("Doing LibraryChanged : Processing Added and Updated : " + str(itemsToUpdate), 0)
self.updateItems.extend(itemsToUpdate) self.updateItems.extend(itemsToUpdate)
self.doIncrementalSync = True
def user_data_update(self, userDataList): def user_data_update(self, userDataList):
# do full playcount update for now # websocket client
for userData in userDataList: for userData in userDataList:
itemId = userData.get("ItemId") itemId = userData.get("ItemId")
if(itemId != None): if(itemId != None):
self.updateItems.append(itemId) self.updateItems.append(itemId)
if(len(self.updateItems) > 0): if(len(self.updateItems) > 0):
self.logMsg("Message : Doing UserDataChanged : Processing Updated : " + str(self.updateItems), 0) self.logMsg("Doing UserDataChanged : Processing Updated : " + str(self.updateItems), 0)
self.doIncrementalSync = True
def ShouldStop(self): def ShouldStop(self):
@ -770,32 +775,44 @@ class LibrarySync(threading.Thread):
while not self.KodiMonitor.abortRequested(): while not self.KodiMonitor.abortRequested():
# In the event the server goes offline after
# the thread has already been started.
while self.suspendClient == True:
# The service.py will change self.suspendClient to False
if self.KodiMonitor.waitForAbort(5):
# Abort was requested while waiting. We should exit
break
# Library sync # Library sync
if not startupComplete: if not startupComplete:
# Run full sync # Run full sync
self.logMsg("Doing_Db_Sync: syncDatabase (Started)", 1) self.logMsg("Doing_Db_Sync: syncDatabase (Started)", 1)
startTime = datetime.now()
libSync = self.FullLibrarySync() libSync = self.FullLibrarySync()
self.logMsg("Doing_Db_Sync: syncDatabase (Finished) %s" % libSync, 1) elapsedTime = datetime.now() - startTime
self.logMsg("Doing_Db_Sync: syncDatabase (Finished in: %s) %s" % (str(elapsedTime).split('.')[0], libSync), 1)
if libSync: if libSync:
startupComplete = True startupComplete = True
if WINDOW.getProperty("OnWakeSync") == "true": # Set via Kodi Monitor event
if WINDOW.getProperty("OnWakeSync") == "true" and WINDOW.getProperty('Server_online') == "true":
WINDOW.clearProperty("OnWakeSync") WINDOW.clearProperty("OnWakeSync")
if WINDOW.getProperty("SyncDatabaseRunning") != "true": if WINDOW.getProperty("SyncDatabaseRunning") != "true":
utils.logMsg("Doing_Db_Sync Post Resume: syncDatabase (Started)",0) self.logMsg("Doing_Db_Sync Post Resume: syncDatabase (Started)", 0)
libSync = self.FullLibrarySync() libSync = self.FullLibrarySync()
utils.logMsg("Doing_Db_Sync Post Resume: syncDatabase (Finished) " + str(libSync),0) self.logMsg("Doing_Db_Sync Post Resume: syncDatabase (Finished) " + str(libSync), 0)
if self.doIncrementalSync: if len(self.updateItems) > 0:
# Add or update item to Kodi library # Add or update items
self.logMsg("Processing items: %s" % (str(self.updateItems)), 1)
listItems = self.updateItems listItems = self.updateItems
self.updateItems = [] self.updateItems = []
self.doIncrementalSync = False
self.IncrementalSync(listItems) self.IncrementalSync(listItems)
if len(self.removeItems) > 0: if len(self.removeItems) > 0:
# Remove item from Kodi library # Remove item from Kodi library
self.logMsg("Removing items: %s" % self.removeItems, 1)
listItems = self.removeItems listItems = self.removeItems
self.removeItems = [] self.removeItems = []
self.removefromDB(listItems) self.removefromDB(listItems)
@ -805,3 +822,11 @@ class LibrarySync(threading.Thread):
break break
self.logMsg("--- Library Sync Thread stopped ---", 0) self.logMsg("--- Library Sync Thread stopped ---", 0)
def suspendClient(self):
self.suspendClient = True
self.logMsg("--- Library Sync Thread paused ---", 0)
def resumeClient(self):
self.suspendClient = False
self.logMsg("--- Library Sync Thread resumed ---", 0)

View file

@ -1,3 +1,5 @@
# -*- coding: utf-8 -*-
################################################################################################# #################################################################################################
# utils class # utils class
################################################################################################# #################################################################################################
@ -19,8 +21,7 @@ class PlayUtils():
clientInfo = ClientInformation() clientInfo = ClientInformation()
addonName = clientInfo.getAddonName() addonName = clientInfo.getAddonName()
addonId = clientInfo.getAddonId() addon = xbmcaddon.Addon()
addon = xbmcaddon.Addon(id=addonId)
audioPref = addon.getSetting('Audiopref') audioPref = addon.getSetting('Audiopref')
subsPref = addon.getSetting('Subspref') subsPref = addon.getSetting('Subspref')
@ -35,76 +36,36 @@ class PlayUtils():
def getPlayUrl(self, server, id, result): def getPlayUrl(self, server, id, result):
addon = self.addon
WINDOW = xbmcgui.Window(10000) WINDOW = xbmcgui.Window(10000)
username = WINDOW.getProperty('currUser') username = WINDOW.getProperty('currUser')
server = WINDOW.getProperty('server%s' % username) server = WINDOW.getProperty('server%s' % username)
if self.isDirectPlay(result): if self.isDirectPlay(result,True):
try:
# Try direct play # Try direct play
playurl = self.directPlay(result) playurl = self.directPlay(result)
if not playurl: if playurl:
# Let user know that direct play failed
resp = xbmcgui.Dialog().select('Warning: Unable to direct play.', ['Play from HTTP', 'Play from HTTP and remember next time.'])
if resp > -1:
# Play from HTTP
playurl = self.directStream(result, server, id)
if resp == 1:
# Remember next time
addon.setSetting('playFromStream', "true")
if not playurl:
# Try transcoding
playurl = self.transcoding(result, server, id)
WINDOW.setProperty("transcoding%s" % id, "true")
self.logMsg("File is transcoding.", 1)
WINDOW.setProperty("%splaymethod" % playurl, "Transcode")
else:
self.logMsg("File is direct streaming.", 1)
WINDOW.setProperty("%splaymethod" % playurl, "DirectStream")
else:
# User decided not to proceed.
self.logMsg("Unable to direct play. Verify the following path is accessible by the device: %s. You might also need to add SMB credentials in the addon settings." % result[u'MediaSources'][0][u'Path'])
return False
else:
self.logMsg("File is direct playing.", 1) self.logMsg("File is direct playing.", 1)
WINDOW.setProperty("%splaymethod" % playurl.encode('utf-8'), "DirectPlay") WINDOW.setProperty("%splaymethod" % playurl.encode('utf-8'), "DirectPlay")
except:
return False
elif self.isDirectStream(result): elif self.isDirectStream(result):
try:
# Try direct stream # Try direct stream
playurl = self.directStream(result, server, id) playurl = self.directStream(result, server, id)
if not playurl: if playurl:
# Try transcoding
playurl = self.transcoding(result, server, id)
WINDOW.setProperty("transcoding%s" % id, "true")
self.logMsg("File is transcoding.", 1)
WINDOW.setProperty("%splaymethod" % playurl, "Transcode")
else:
self.logMsg("File is direct streaming.", 1) self.logMsg("File is direct streaming.", 1)
WINDOW.setProperty("%splaymethod" % playurl, "DirectStream") WINDOW.setProperty("%splaymethod" % playurl, "DirectStream")
except:
return False
elif self.isTranscoding(result): else:# Try transcoding
try:
# Try transcoding
playurl = self.transcoding(result, server, id) playurl = self.transcoding(result, server, id)
WINDOW.setProperty("transcoding%s" % id, "true") if playurl:
self.logMsg("File is transcoding.", 1) self.logMsg("File is transcoding.", 1)
WINDOW.setProperty("%splaymethod" % playurl, "Transcode") WINDOW.setProperty("%splaymethod" % playurl, "Transcode")
except:
return False
return playurl.encode('utf-8') return playurl.encode('utf-8')
def isDirectPlay(self, result, dialog=False):
def isDirectPlay(self, result):
# Requirements for Direct play: # Requirements for Direct play:
# FileSystem, Accessible path # FileSystem, Accessible path
self.addon = xbmcaddon.Addon(id=self.addonId) self.addon = xbmcaddon.Addon()
playhttp = self.addon.getSetting('playFromStream') playhttp = self.addon.getSetting('playFromStream')
# User forcing to play via HTTP instead of SMB # User forcing to play via HTTP instead of SMB
@ -126,17 +87,30 @@ class PlayUtils():
return True return True
else: else:
self.logMsg("Can't direct play: Unable to locate the content.", 1) self.logMsg("Can't direct play: Unable to locate the content.", 1)
if dialog:
# Let user know that direct play failed
resp = xbmcgui.Dialog().select('Warning: Unable to direct play.', ['Play from HTTP', 'Play from HTTP and remember next time.'])
if resp == 1:
# Remember next time
addon.setSetting('playFromStream', "true")
else:
# User decided not to proceed.
self.logMsg("Unable to direct play. Verify the following path is accessible by the device: %s. You might also need to add SMB credentials in the addon settings." % result[u'MediaSources'][0][u'Path'])
return False return False
def directPlay(self, result): def directPlay(self, result):
addon = self.addon addon = self.addon
try: try:
# Item can be played directly try:
playurl = result[u'MediaSources'][0][u'Path'] playurl = result[u'MediaSources'][0][u'Path']
except:
playurl = result[u'Path']
except:
self.logMsg("Direct play failed. Trying Direct stream.", 1)
return False
else:
if u'VideoType' in result: if u'VideoType' in result:
# Specific format modification # Specific format modification
if u'Dvd' in result[u'VideoType']: if u'Dvd' in result[u'VideoType']:
@ -156,19 +130,15 @@ class PlayUtils():
playurl = playurl.replace("\\", "/") playurl = playurl.replace("\\", "/")
if "apple.com" in playurl: if "apple.com" in playurl:
USER_AGENT = 'QuickTime/7.7.4' USER_AGENT = "QuickTime/7.7.4"
playurl += "?|User-Agent=%s" % USER_AGENT playurl += "?|User-Agent=%s" % USER_AGENT
if ":" not in playurl: if ":" not in playurl:
self.logMsg("Path seems invalid: %s" % playurl) self.logMsg("Path seems invalid: %s" % playurl, 1)
return False return False
return playurl return playurl
except:
self.logMsg("Direct play failed. Trying Direct stream.", 1)
return False
def isDirectStream(self, result): def isDirectStream(self, result):
# Requirements for Direct stream: # Requirements for Direct stream:
# FileSystem or Remote, BitRate, supported encoding # FileSystem or Remote, BitRate, supported encoding
@ -191,20 +161,21 @@ class PlayUtils():
def directStream(self, result, server, id, type = "Video"): def directStream(self, result, server, id, type = "Video"):
try: try:
if type == "Video": if "ThemeVideo" in type:
# Play with Direct Stream
playurl ="%s/mediabrowser/Videos/%s/stream?static=true" % (server, id) playurl ="%s/mediabrowser/Videos/%s/stream?static=true" % (server, id)
elif type == "Audio":
playurl = "%s/mediabrowser/Audio/%s/stream.mp3" % (server, id)
return playurl
elif "Video" in type:
playurl = "%s/mediabrowser/Videos/%s/stream?static=true" % (server, id)
# Verify audio and subtitles
mediaSources = result[u'MediaSources'] mediaSources = result[u'MediaSources']
if mediaSources[0].get('DefaultAudioStreamIndex') != None: if mediaSources[0].get('DefaultAudioStreamIndex') != None:
playurl = "%s&AudioStreamIndex=%s" % (playurl, mediaSources[0].get('DefaultAudioStreamIndex')) playurl = "%s&AudioStreamIndex=%s" % (playurl, mediaSources[0].get('DefaultAudioStreamIndex'))
if mediaSources[0].get('DefaultSubtitleStreamIndex') != None: if mediaSources[0].get('DefaultSubtitleStreamIndex') != None:
playurl = "%s&SubtitleStreamIndex=%s" % (playurl, mediaSources[0].get('DefaultSubtitleStreamIndex')) playurl = "%s&SubtitleStreamIndex=%s" % (playurl, mediaSources[0].get('DefaultSubtitleStreamIndex'))
self.logMsg("Playurl: %s" % playurl) elif "Audio" in type:
playurl = "%s/mediabrowser/Audio/%s/stream.mp3" % (server, id)
return playurl return playurl
except: except:
@ -329,7 +300,7 @@ class PlayUtils():
# Local or Network path # Local or Network path
self.logMsg("Path exists.", 2) self.logMsg("Path exists.", 2)
return True return True
elif ":\\" not in path: elif "nfs:" in path.lower():
# Give benefit of the doubt. # Give benefit of the doubt.
self.logMsg("Can't verify path. Still try direct play.", 2) self.logMsg("Can't verify path. Still try direct play.", 2)
return True return True

File diff suppressed because it is too large Load diff