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
@ -11,142 +12,157 @@ class API():
def getPeople(self, item): def getPeople(self, item):
# Process People # Process People
director=[] director = []
writer=[] writer = []
cast=[] cast = []
people = item.get("People")
if(people != None):
for person in people:
if(person.get("Type") == "Director"):
director.append(person.get("Name"))
if(person.get("Type") == "Writing"):
writer.append(person.get("Name"))
if(person.get("Type") == "Writer"):
writer.append(person.get("Name"))
if(person.get("Type") == "Actor"):
Name = person.get("Name")
Role = person.get("Role")
if Role == None:
Role = ''
cast.append(Name)
return {'Director' : director,
'Writer' : writer,
'Cast' : cast
}
def getTimeInfo(self, item):
resumeTime = ''
userData = item.get("UserData")
PlaybackPositionTicks = '100'
if userData.get("PlaybackPositionTicks") != None:
PlaybackPositionTicks = str(userData.get("PlaybackPositionTicks"))
reasonableTicks = int(userData.get("PlaybackPositionTicks")) / 1000
resumeTime = reasonableTicks / 10000
try: try:
tempDuration = str(int(item.get("RunTimeTicks", "0"))/(10000000*60)) people = item['People']
except TypeError:
try: except: pass
tempDuration = str(int(item.get("CumulativeRunTimeTicks"))/(10000000*60))
except TypeError: else:
tempDuration = "0"
cappedPercentage = None for person in people:
resume=0
percentage=0 type = person['Type']
if (resumeTime != "" and int(resumeTime) > 0): Name = person['Name']
duration = float(tempDuration)
if(duration > 0): if "Director" in type:
resume = float(resumeTime) / 60 director.append(Name)
percentage = int((resume / duration) * 100.0) elif "Writing" in type:
return {'Duration' : tempDuration, writer.append(Name)
'TotalTime' : tempDuration, elif "Writer" in type:
'Percent' : str(percentage), writer.append(Name)
'ResumeTime' : str(resume) elif "Actor" in type:
} cast.append(Name)
return {
'Director': director,
'Writer': writer,
'Cast': cast
}
def getTimeInfo(self, item):
# Runtime and Resume point
tempRuntime = 0
runtime = 0
resume = 0
try: # Get resume point
userdata = item['UserData']
playbackPosition = userdata['PlaybackPositionTicks']
resume = playbackPosition / 10000000.0
except: pass
try: # Get total runtime
tempRuntime = item['RunTimeTicks']
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 = '' else:
width = '' genre = genre + " / " + genre_string
aspectratio = '1:1' elif item.get("SeriesGenres") != None and item.get("SeriesGenres") != '':
aspectfloat = 1.85 genres = item.get("SeriesGenres")
Video3DFormat = '' 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
if mediaSources == True: def getMediaStreams(self, item, mediaSources = False):
mediaSources = item.get("MediaSources")
if(mediaSources != None): videotracks = [] # Height, Width, Codec, AspectRatio, AspectFloat, 3D
MediaStreams = mediaSources[0].get("MediaStreams") audiotracks = [] # Codec, Channels, language
else: 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')
try: videotrack['Video3DFormat'] = item.get('Video3DFormat')
aspectwidth,aspectheight = aspectratio.split(':') if len(videotrack['aspectratio']) >= 3:
aspectfloat = float(aspectwidth) / float(aspectheight) try:
except: aspectwidth, aspectheight = aspectratio.split(':')
aspectfloat = 1.85 videotrack['aspectfloat'] = float(aspectwidth) / float(aspectheight)
if(mediaStream.get("Type") == "Audio"): except:
isdefault = mediaStream.get("IsDefault") == "true" videotrack['aspectfloat'] = 1.85
if audiocodec == '': videotracks.append(videotrack)
audiocodec = mediaStream.get("Codec")
if channels == '': elif "Audio" in type:
channels = mediaStream.get("Channels") audiotrack = {}
if audiolanguage == '': audiotrack['audiocodec'] = mediaStream.get('Codec')
audiolanguage = mediaStream.get("Language") audiotrack['channels'] = mediaStream.get('Channels')
# only overwrite if default audiotrack['audiolanguage'] = mediaStream.get('Language')
if isdefault: audiotracks.append(audiotrack)
audiocodec = mediaStream.get("Codec")
channels = mediaStream.get("Channels") elif "Subtitle" in type:
audiolanguage = mediaStream.get("Language") try:
if(mediaStream.get("Type") == "Subtitle"): subtitlelanguages.append(mediaStream['Language'])
isdefault = mediaStream.get("IsDefault") == "true" except:
if subtitlelanguage == '': subtitlelanguages.append("Unknown")
subtitlelanguage = mediaStream.get("Language")
# only overwrite if default return {
if isdefault:
subtitlelanguage = mediaStream.get("Language") 'videocodec' : videotracks,
'audiocodec' : audiotracks,
'subtitlelanguage' : subtitlelanguages
return {'channels' : str(channels), }
'videocodec' : videocodec,
'audiocodec' : audiocodec,
'audiolanguage' : audiolanguage,
'subtitlelanguage' : subtitlelanguage,
'height' : height,
'width' : width,
'aspectratio' : aspectfloat,
'3dformat' : Video3DFormat
}
def getChecksum(self, item): def getChecksum(self, item):
# use the etags checksum for this if available # use the etags checksum for this if available
@ -169,109 +185,62 @@ class API():
return checksum return checksum
def getUserData(self, item): def getUserData(self, item):
userData = item.get("UserData") # Default
resumeTime = 0 favorite = False
if(userData != None): playcount = None
if userData.get("Played") != True: lastPlayedDate = None
watched="True" userKey = ""
else:
watched="False" try:
if userData.get("IsFavorite") == True: userdata = item['UserData']
favorite=True
else: except: # No userdata found.
favorite=False pass
if(userData.get("Played") == True):
# Cover the Emby scenario where item is played but playcount is 0. else:
playcount = userData.get('PlayCount') 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] 'Favorite': favorite,
timestring = timestring.split('.')[0] 'PlayCount': playcount,
LastPlayedDate = datestring + " " + timestring 'LastPlayedDate': lastPlayedDate,
else: 'Key': userKey
LastPlayedDate = None }
if userData.get('PlaybackPositionTicks') != None:
PlaybackPositionTicks = userData.get('PlaybackPositionTicks')
else:
PlaybackPositionTicks = ''
userKey = userData.get("Key", "")
return {'Watched' : watched,
'Favorite' : favorite,
'PlayCount': playcount,
'LastPlayedDate': LastPlayedDate,
'UnplayedItemCount' : UnplayedItemCount,
'PlaybackPositionTicks' : str(PlaybackPositionTicks),
'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:
return str(item.get("RecursiveItemCount")) return str(item.get("RecursiveItemCount"))
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: overview = ""
Temp=''
Overview1=Temp.encode('utf-8') try:
Overview=str(Overview1) overview = item['Overview']
Overview=Overview.replace("\"", "\'") overview = overview.replace("\"", "\'")
Overview=Overview.replace("\n", " ") overview = overview.replace("\n", " ")
Overview=Overview.replace("\r", " ") overview = overview.replace("\r", " ")
return Overview except: pass
def getPremiereDate(self, item): return overview
if(item.get("PremiereDate") != None):
premieredatelist = (item.get("PremiereDate")).split("T")
premieredate = premieredatelist[0]
else:
premieredate = ""
Temp = premieredate
premieredate = Temp.encode('utf-8')
return premieredate
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):
@ -416,6 +475,14 @@ class API():
artwork='' artwork=''
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"):

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)
url = "{server}/mediabrowser/Users/{UserId}/Items?Ids=%s&format=json" % itemIds
result = doUtils.downloadUrl(url)
if result is "":
# Websocket feedback
self.logMsg("Item %s is removed." % itemIds)
return
for item in result[u'Items']: # Database connection to myVideosXX.db
# Sort by type for database deletion connectionvideo = utils.KodiSQL()
itemId = item["Id"] cursorvideo = connectionvideo.cursor()
mediaType = item["MediaType"] # Database connection to myMusicXX.db
connectionmusic = utils.KodiSQL("music")
cursormusic = connectionmusic.cursor()
if "Video" in mediaType: for item in itemList:
video.append(itemId) # Sort by type for database deletion
elif "Audio" in mediaType: try: # Search video database
music.append(itemId) self.logMsg("Check video database.", 1)
cursorvideo.execute("SELECT media_type FROM emby WHERE emby_id = ?", (item,))
mediatype = cursorvideo.fetchone()[0]
video[item] = mediatype
#video.append(itemtype)
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:
#Process video library connection = connectionvideo
connection = utils.KodiSQL("video") cursor = cursorvideo
cursor = connection.cursor() # Process video library
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,35 +728,34 @@ 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:
url = "{server}/mediabrowser/Items/%s" % item url = "{server}/mediabrowser/Items/%s" % item
self.logMsg('Deleting via URL: %s' % url) self.logMsg('Deleting via URL: %s' % url)
doUtils.downloadUrl(url, type="DELETE") doUtils.downloadUrl(url, type = "DELETE")
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 playurl:
if not playurl: self.logMsg("File is direct playing.", 1)
# Let user know that direct play failed WINDOW.setProperty("%splaymethod" % playurl.encode('utf-8'), "DirectPlay")
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)
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 playurl:
if not playurl: self.logMsg("File is direct streaming.", 1)
# Try transcoding WINDOW.setProperty("%splaymethod" % playurl, "DirectStream")
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")
except:
return False
elif self.isTranscoding(result): else:# Try transcoding
try: playurl = self.transcoding(result, server, id)
# Try transcoding if playurl:
playurl = self.transcoding(result, server, id)
WINDOW.setProperty("transcoding%s" % id, "true")
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
@ -188,23 +158,24 @@ class PlayUtils():
return True return True
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)
elif "Video" in type:
playurl = "%s/mediabrowser/Videos/%s/stream?static=true" % (server, id) playurl = "%s/mediabrowser/Videos/%s/stream?static=true" % (server, id)
elif type == "Audio": # Verify audio and subtitles
mediaSources = result[u'MediaSources']
if mediaSources[0].get('DefaultAudioStreamIndex') != None:
playurl = "%s&AudioStreamIndex=%s" % (playurl, mediaSources[0].get('DefaultAudioStreamIndex'))
if mediaSources[0].get('DefaultSubtitleStreamIndex') != None:
playurl = "%s&SubtitleStreamIndex=%s" % (playurl, mediaSources[0].get('DefaultSubtitleStreamIndex'))
elif "Audio" in type:
playurl = "%s/mediabrowser/Audio/%s/stream.mp3" % (server, id) playurl = "%s/mediabrowser/Audio/%s/stream.mp3" % (server, id)
return playurl
mediaSources = result[u'MediaSources']
if mediaSources[0].get('DefaultAudioStreamIndex') != None:
playurl = "%s&AudioStreamIndex=%s" % (playurl, mediaSources[0].get('DefaultAudioStreamIndex'))
if mediaSources[0].get('DefaultSubtitleStreamIndex') != None:
playurl = "%s&SubtitleStreamIndex=%s" % (playurl, mediaSources[0].get('DefaultSubtitleStreamIndex'))
self.logMsg("Playurl: %s" % playurl)
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