Merge remote-tracking branch 'MediaBrowser/master' into develop
This commit is contained in:
commit
450437b812
18 changed files with 1428 additions and 1622 deletions
|
@ -147,7 +147,7 @@ if __name__ == '__main__':
|
||||||
doUtils = downloadutils.DownloadUtils()
|
doUtils = downloadutils.DownloadUtils()
|
||||||
url = "{server}/emby/Items/%s?format=json" % embyid
|
url = "{server}/emby/Items/%s?format=json" % embyid
|
||||||
logMsg("Deleting request: %s" % embyid, 0)
|
logMsg("Deleting request: %s" % embyid, 0)
|
||||||
doUtils.downloadUrl(url, type="DELETE")
|
doUtils.downloadUrl(url, action_type="DELETE")
|
||||||
|
|
||||||
'''if utils.settings('skipContextMenu') != "true":
|
'''if utils.settings('skipContextMenu') != "true":
|
||||||
if xbmcgui.Dialog().yesno(
|
if xbmcgui.Dialog().yesno(
|
||||||
|
@ -156,8 +156,7 @@ if __name__ == '__main__':
|
||||||
"also delete the file(s) from disk!")):
|
"also delete the file(s) from disk!")):
|
||||||
import downloadutils
|
import downloadutils
|
||||||
doUtils = downloadutils.DownloadUtils()
|
doUtils = downloadutils.DownloadUtils()
|
||||||
url = "{server}/emby/Items/%s?format=json" % embyid
|
doUtils.downloadUrl("{server}/emby/Items/%s?format=json" % embyid, action_type="DELETE")'''
|
||||||
doUtils.downloadUrl(url, type="DELETE")'''
|
|
||||||
|
|
||||||
xbmc.sleep(500)
|
xbmc.sleep(500)
|
||||||
xbmc.executebuiltin("Container.Update")
|
xbmc.executebuiltin("Container.Update")
|
|
@ -328,7 +328,7 @@
|
||||||
<string id="33020">Gathering tv shows from:</string>
|
<string id="33020">Gathering tv shows from:</string>
|
||||||
<string id="33021">Gathering:</string>
|
<string id="33021">Gathering:</string>
|
||||||
<string id="33022">Detected the database needs to be recreated for this version of Emby for Kodi. Proceed?</string>
|
<string id="33022">Detected the database needs to be recreated for this version of Emby for Kodi. Proceed?</string>
|
||||||
<string id="33023">Emby for Kod may not work correctly until the database is reset.</string>
|
<string id="33023">Emby for Kodi may not work correctly until the database is reset.</string>
|
||||||
<string id="33024">Cancelling the database syncing process. The current Kodi version is unsupported.</string>
|
<string id="33024">Cancelling the database syncing process. The current Kodi version is unsupported.</string>
|
||||||
<string id="33025">completed in:</string>
|
<string id="33025">completed in:</string>
|
||||||
<string id="33026">Comparing movies from:</string>
|
<string id="33026">Comparing movies from:</string>
|
||||||
|
|
|
@ -28,7 +28,7 @@ class Artwork():
|
||||||
xbmc_port = None
|
xbmc_port = None
|
||||||
xbmc_username = None
|
xbmc_username = None
|
||||||
xbmc_password = None
|
xbmc_password = None
|
||||||
|
|
||||||
imageCacheThreads = []
|
imageCacheThreads = []
|
||||||
imageCacheLimitThreads = 0
|
imageCacheLimitThreads = 0
|
||||||
|
|
||||||
|
@ -36,9 +36,9 @@ class Artwork():
|
||||||
|
|
||||||
self.enableTextureCache = utils.settings('enableTextureCache') == "true"
|
self.enableTextureCache = utils.settings('enableTextureCache') == "true"
|
||||||
self.imageCacheLimitThreads = int(utils.settings("imageCacheLimit"))
|
self.imageCacheLimitThreads = int(utils.settings("imageCacheLimit"))
|
||||||
self.imageCacheLimitThreads = int(self.imageCacheLimitThreads * 5);
|
self.imageCacheLimitThreads = int(self.imageCacheLimitThreads * 5)
|
||||||
utils.logMsg("Using Image Cache Thread Count: " + str(self.imageCacheLimitThreads), 1)
|
utils.logMsg("Using Image Cache Thread Count: " + str(self.imageCacheLimitThreads), 1)
|
||||||
|
|
||||||
if not self.xbmc_port and self.enableTextureCache:
|
if not self.xbmc_port and self.enableTextureCache:
|
||||||
self.setKodiWebServerDetails()
|
self.setKodiWebServerDetails()
|
||||||
|
|
||||||
|
@ -48,11 +48,11 @@ class Artwork():
|
||||||
def double_urlencode(self, text):
|
def double_urlencode(self, text):
|
||||||
text = self.single_urlencode(text)
|
text = self.single_urlencode(text)
|
||||||
text = self.single_urlencode(text)
|
text = self.single_urlencode(text)
|
||||||
|
|
||||||
return text
|
return text
|
||||||
|
|
||||||
def single_urlencode(self, text):
|
def single_urlencode(self, text):
|
||||||
|
|
||||||
text = urllib.urlencode({'blahblahblah':text.encode("utf-8")}) #urlencode needs a utf- string
|
text = urllib.urlencode({'blahblahblah':text.encode("utf-8")}) #urlencode needs a utf- string
|
||||||
text = text[13:]
|
text = text[13:]
|
||||||
|
|
||||||
|
@ -74,9 +74,9 @@ class Artwork():
|
||||||
result = json.loads(result)
|
result = json.loads(result)
|
||||||
try:
|
try:
|
||||||
xbmc_webserver_enabled = result['result']['value']
|
xbmc_webserver_enabled = result['result']['value']
|
||||||
except KeyError, TypeError:
|
except (KeyError, TypeError):
|
||||||
xbmc_webserver_enabled = False
|
xbmc_webserver_enabled = False
|
||||||
|
|
||||||
if not xbmc_webserver_enabled:
|
if not xbmc_webserver_enabled:
|
||||||
# Enable the webserver, it is disabled
|
# Enable the webserver, it is disabled
|
||||||
web_port = {
|
web_port = {
|
||||||
|
@ -159,7 +159,7 @@ class Artwork():
|
||||||
self.xbmc_password = result['result']['value']
|
self.xbmc_password = result['result']['value']
|
||||||
except TypeError:
|
except TypeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def FullTextureCacheSync(self):
|
def FullTextureCacheSync(self):
|
||||||
# This method will sync all Kodi artwork to textures13.db
|
# This method will sync all Kodi artwork to textures13.db
|
||||||
# and cache them locally. This takes diskspace!
|
# and cache them locally. This takes diskspace!
|
||||||
|
@ -169,12 +169,12 @@ class Artwork():
|
||||||
if not xbmcgui.Dialog().yesno(
|
if not xbmcgui.Dialog().yesno(
|
||||||
"Image Texture Cache", string(39250).encode('utf-8')):
|
"Image Texture Cache", string(39250).encode('utf-8')):
|
||||||
return
|
return
|
||||||
|
|
||||||
self.logMsg("Doing Image Cache Sync", 1)
|
self.logMsg("Doing Image Cache Sync", 1)
|
||||||
|
|
||||||
dialog = xbmcgui.DialogProgress()
|
dialog = xbmcgui.DialogProgress()
|
||||||
dialog.create("Emby for Kodi", "Image Cache Sync")
|
dialog.create("Emby for Kodi", "Image Cache Sync")
|
||||||
|
|
||||||
# ask to rest all existing or not
|
# ask to rest all existing or not
|
||||||
if xbmcgui.Dialog().yesno(
|
if xbmcgui.Dialog().yesno(
|
||||||
"Image Texture Cache", string(39251).encode('utf-8'), ""):
|
"Image Texture Cache", string(39251).encode('utf-8'), ""):
|
||||||
|
@ -190,7 +190,7 @@ class Artwork():
|
||||||
xbmcvfs.delete(os.path.join(path+dir.decode('utf-8'),file.decode('utf-8')))
|
xbmcvfs.delete(os.path.join(path+dir.decode('utf-8'),file.decode('utf-8')))
|
||||||
else:
|
else:
|
||||||
xbmcvfs.delete(os.path.join(path.encode('utf-8')+dir,file))
|
xbmcvfs.delete(os.path.join(path.encode('utf-8')+dir,file))
|
||||||
|
|
||||||
# remove all existing data from texture DB
|
# remove all existing data from texture DB
|
||||||
textureconnection = utils.kodiSQL('texture')
|
textureconnection = utils.kodiSQL('texture')
|
||||||
texturecursor = textureconnection.cursor()
|
texturecursor = textureconnection.cursor()
|
||||||
|
@ -209,8 +209,8 @@ class Artwork():
|
||||||
cursor.execute("SELECT url FROM art WHERE media_type != 'actor'") # dont include actors
|
cursor.execute("SELECT url FROM art WHERE media_type != 'actor'") # dont include actors
|
||||||
result = cursor.fetchall()
|
result = cursor.fetchall()
|
||||||
total = len(result)
|
total = len(result)
|
||||||
count = 1
|
count = 1
|
||||||
percentage = 0
|
percentage = 0
|
||||||
self.logMsg("Image cache sync about to process " + str(total) + " images", 1)
|
self.logMsg("Image cache sync about to process " + str(total) + " images", 1)
|
||||||
for url in result:
|
for url in result:
|
||||||
if dialog.iscanceled():
|
if dialog.iscanceled():
|
||||||
|
@ -221,26 +221,26 @@ class Artwork():
|
||||||
self.CacheTexture(url[0])
|
self.CacheTexture(url[0])
|
||||||
count += 1
|
count += 1
|
||||||
cursor.close()
|
cursor.close()
|
||||||
|
|
||||||
# Cache all entries in music DB
|
# Cache all entries in music DB
|
||||||
connection = utils.kodiSQL('music')
|
connection = utils.kodiSQL('music')
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
cursor.execute("SELECT url FROM art")
|
cursor.execute("SELECT url FROM art")
|
||||||
result = cursor.fetchall()
|
result = cursor.fetchall()
|
||||||
total = len(result)
|
total = len(result)
|
||||||
count = 1
|
count = 1
|
||||||
percentage = 0
|
percentage = 0
|
||||||
self.logMsg("Image cache sync about to process " + str(total) + " images", 1)
|
self.logMsg("Image cache sync about to process " + str(total) + " images", 1)
|
||||||
for url in result:
|
for url in result:
|
||||||
if dialog.iscanceled():
|
if dialog.iscanceled():
|
||||||
break
|
break
|
||||||
percentage = int((float(count) / float(total))*100)
|
percentage = int((float(count) / float(total))*100)
|
||||||
textMessage = str(count) + " of " + str(total)
|
textMessage = str(count) + " of " + str(total)
|
||||||
dialog.update(percentage, "Updating Image Cache: " + textMessage)
|
dialog.update(percentage, "Updating Image Cache: " + textMessage)
|
||||||
self.CacheTexture(url[0])
|
self.CacheTexture(url[0])
|
||||||
count += 1
|
count += 1
|
||||||
cursor.close()
|
cursor.close()
|
||||||
|
|
||||||
dialog.update(100, "Waiting for all threads to exit: " + str(len(self.imageCacheThreads)))
|
dialog.update(100, "Waiting for all threads to exit: " + str(len(self.imageCacheThreads)))
|
||||||
self.logMsg("Waiting for all threads to exit", 1)
|
self.logMsg("Waiting for all threads to exit", 1)
|
||||||
while len(self.imageCacheThreads) > 0:
|
while len(self.imageCacheThreads) > 0:
|
||||||
|
@ -250,16 +250,16 @@ class Artwork():
|
||||||
dialog.update(100, "Waiting for all threads to exit: " + str(len(self.imageCacheThreads)))
|
dialog.update(100, "Waiting for all threads to exit: " + str(len(self.imageCacheThreads)))
|
||||||
self.logMsg("Waiting for all threads to exit: " + str(len(self.imageCacheThreads)), 1)
|
self.logMsg("Waiting for all threads to exit: " + str(len(self.imageCacheThreads)), 1)
|
||||||
xbmc.sleep(500)
|
xbmc.sleep(500)
|
||||||
|
|
||||||
dialog.close()
|
dialog.close()
|
||||||
|
|
||||||
def addWorkerImageCacheThread(self, urlToAdd):
|
def addWorkerImageCacheThread(self, urlToAdd):
|
||||||
|
|
||||||
while(True):
|
while(True):
|
||||||
# removed finished
|
# removed finished
|
||||||
for thread in self.imageCacheThreads:
|
for thread in self.imageCacheThreads:
|
||||||
if thread.isFinished:
|
if thread.isFinished:
|
||||||
self.imageCacheThreads.remove(thread)
|
self.imageCacheThreads.remove(thread)
|
||||||
|
|
||||||
# add a new thread or wait and retry if we hit our limit
|
# add a new thread or wait and retry if we hit our limit
|
||||||
if(len(self.imageCacheThreads) < self.imageCacheLimitThreads):
|
if(len(self.imageCacheThreads) < self.imageCacheLimitThreads):
|
||||||
|
@ -273,14 +273,14 @@ class Artwork():
|
||||||
else:
|
else:
|
||||||
self.logMsg("Waiting for empty queue spot: " + str(len(self.imageCacheThreads)), 2)
|
self.logMsg("Waiting for empty queue spot: " + str(len(self.imageCacheThreads)), 2)
|
||||||
xbmc.sleep(50)
|
xbmc.sleep(50)
|
||||||
|
|
||||||
|
|
||||||
def CacheTexture(self, url):
|
def CacheTexture(self, url):
|
||||||
# Cache a single image url to the texture cache
|
# Cache a single image url to the texture cache
|
||||||
if url and self.enableTextureCache:
|
if url and self.enableTextureCache:
|
||||||
if(self.imageCacheLimitThreads == 0 or self.imageCacheLimitThreads == None):
|
if(self.imageCacheLimitThreads == 0 or self.imageCacheLimitThreads == None):
|
||||||
#Add image to texture cache by simply calling it at the http endpoint
|
#Add image to texture cache by simply calling it at the http endpoint
|
||||||
|
|
||||||
url = self.double_urlencode(url)
|
url = self.double_urlencode(url)
|
||||||
try: # Extreme short timeouts so we will have a exception.
|
try: # Extreme short timeouts so we will have a exception.
|
||||||
response = requests.head(
|
response = requests.head(
|
||||||
|
@ -291,7 +291,7 @@ class Artwork():
|
||||||
timeout=(0.01, 0.01))
|
timeout=(0.01, 0.01))
|
||||||
# We don't need the result
|
# We don't need the result
|
||||||
except: pass
|
except: pass
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.addWorkerImageCacheThread(url)
|
self.addWorkerImageCacheThread(url)
|
||||||
|
|
||||||
|
@ -349,13 +349,13 @@ class Artwork():
|
||||||
mediaType=mediaType,
|
mediaType=mediaType,
|
||||||
imageType="%s%s" % ("fanart", index),
|
imageType="%s%s" % ("fanart", index),
|
||||||
cursor=cursor)
|
cursor=cursor)
|
||||||
|
|
||||||
if backdropsNumber > 1:
|
if backdropsNumber > 1:
|
||||||
try: # Will only fail on the first try, str to int.
|
try: # Will only fail on the first try, str to int.
|
||||||
index += 1
|
index += 1
|
||||||
except TypeError:
|
except TypeError:
|
||||||
index = 1
|
index = 1
|
||||||
|
|
||||||
elif art == "Primary":
|
elif art == "Primary":
|
||||||
# Primary art is processed as thumb and poster for Kodi.
|
# Primary art is processed as thumb and poster for Kodi.
|
||||||
for artType in kodiart[art]:
|
for artType in kodiart[art]:
|
||||||
|
@ -365,7 +365,7 @@ class Artwork():
|
||||||
mediaType=mediaType,
|
mediaType=mediaType,
|
||||||
imageType=artType,
|
imageType=artType,
|
||||||
cursor=cursor)
|
cursor=cursor)
|
||||||
|
|
||||||
elif kodiart.get(art):
|
elif kodiart.get(art):
|
||||||
# Process the rest artwork type that Kodi can use
|
# Process the rest artwork type that Kodi can use
|
||||||
self.addOrUpdateArt(
|
self.addOrUpdateArt(
|
||||||
|
@ -391,9 +391,11 @@ class Artwork():
|
||||||
cursor.execute(query, (kodiId, mediaType, imageType,))
|
cursor.execute(query, (kodiId, mediaType, imageType,))
|
||||||
try: # Update the artwork
|
try: # Update the artwork
|
||||||
url = cursor.fetchone()[0]
|
url = cursor.fetchone()[0]
|
||||||
|
|
||||||
except TypeError: # Add the artwork
|
except TypeError: # Add the artwork
|
||||||
cacheimage = True
|
cacheimage = True
|
||||||
|
self.logMsg("Adding Art Link for kodiId: %s (%s)" % (kodiId, imageUrl), 2)
|
||||||
|
|
||||||
query = (
|
query = (
|
||||||
'''
|
'''
|
||||||
INSERT INTO art(media_id, media_type, type, url)
|
INSERT INTO art(media_id, media_type, type, url)
|
||||||
|
@ -402,17 +404,21 @@ class Artwork():
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
cursor.execute(query, (kodiId, mediaType, imageType, imageUrl))
|
cursor.execute(query, (kodiId, mediaType, imageType, imageUrl))
|
||||||
|
|
||||||
else: # Only cache artwork if it changed
|
else: # Only cache artwork if it changed
|
||||||
if url != imageUrl:
|
if url != imageUrl:
|
||||||
cacheimage = True
|
cacheimage = True
|
||||||
|
|
||||||
# Only for the main backdrop, poster
|
# Only for the main backdrop, poster
|
||||||
if (utils.window('emby_initialScan') != "true" and
|
if (utils.window('emby_initialScan') != "true" and
|
||||||
imageType in ("fanart", "poster")):
|
imageType in ("fanart", "poster")):
|
||||||
# Delete current entry before updating with the new one
|
# Delete current entry before updating with the new one
|
||||||
self.deleteCachedArtwork(url)
|
self.deleteCachedArtwork(url)
|
||||||
|
|
||||||
|
self.logMsg(
|
||||||
|
"Updating Art url for %s kodiId: %s (%s) -> (%s)"
|
||||||
|
% (imageType, kodiId, url, imageUrl), 1)
|
||||||
|
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
"UPDATE art",
|
"UPDATE art",
|
||||||
|
@ -422,7 +428,7 @@ class Artwork():
|
||||||
"AND type = ?"
|
"AND type = ?"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (imageUrl, kodiId, mediaType, imageType))
|
cursor.execute(query, (imageUrl, kodiId, mediaType, imageType))
|
||||||
|
|
||||||
# Cache fanart and poster in Kodi texture cache
|
# Cache fanart and poster in Kodi texture cache
|
||||||
if cacheimage and imageType in ("fanart", "poster", "thumb"):
|
if cacheimage and imageType in ("fanart", "poster", "thumb"):
|
||||||
self.CacheTexture(imageUrl)
|
self.CacheTexture(imageUrl)
|
||||||
|
@ -453,24 +459,24 @@ class Artwork():
|
||||||
try:
|
try:
|
||||||
cursor.execute("SELECT cachedurl FROM texture WHERE url = ?", (url,))
|
cursor.execute("SELECT cachedurl FROM texture WHERE url = ?", (url,))
|
||||||
cachedurl = cursor.fetchone()[0]
|
cachedurl = cursor.fetchone()[0]
|
||||||
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
self.logMsg("Could not find cached url.", 1)
|
self.logMsg("Could not find cached url.", 1)
|
||||||
|
|
||||||
except OperationalError:
|
except OperationalError:
|
||||||
self.logMsg("Database is locked. Skip deletion process.", 1)
|
self.logMsg("Database is locked. Skip deletion process.", 1)
|
||||||
|
|
||||||
else: # Delete thumbnail as well as the entry
|
else: # Delete thumbnail as well as the entry
|
||||||
thumbnails = xbmc.translatePath("special://thumbnails/%s" % cachedurl).decode('utf-8')
|
thumbnails = xbmc.translatePath("special://thumbnails/%s" % cachedurl).decode('utf-8')
|
||||||
self.logMsg("Deleting cached thumbnail: %s" % thumbnails, 1)
|
self.logMsg("Deleting cached thumbnail: %s" % thumbnails, 1)
|
||||||
xbmcvfs.delete(thumbnails)
|
xbmcvfs.delete(thumbnails)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
cursor.execute("DELETE FROM texture WHERE url = ?", (url,))
|
cursor.execute("DELETE FROM texture WHERE url = ?", (url,))
|
||||||
connection.commit()
|
connection.commit()
|
||||||
except OperationalError:
|
except OperationalError:
|
||||||
self.logMsg("Issue deleting url from cache. Skipping.", 2)
|
self.logMsg("Issue deleting url from cache. Skipping.", 2)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
cursor.close()
|
cursor.close()
|
||||||
|
|
||||||
|
@ -487,7 +493,7 @@ class Artwork():
|
||||||
"%s/emby/Items/%s/Images/Primary?"
|
"%s/emby/Items/%s/Images/Primary?"
|
||||||
"MaxWidth=400&MaxHeight=400&Index=0&Tag=%s"
|
"MaxWidth=400&MaxHeight=400&Index=0&Tag=%s"
|
||||||
% (self.server, personId, tag))
|
% (self.server, personId, tag))
|
||||||
|
|
||||||
person['imageurl'] = image
|
person['imageurl'] = image
|
||||||
|
|
||||||
return people
|
return people
|
||||||
|
@ -501,8 +507,6 @@ class Artwork():
|
||||||
|
|
||||||
def getAllArtwork(self, item, parentInfo=False):
|
def getAllArtwork(self, item, parentInfo=False):
|
||||||
|
|
||||||
server = self.server
|
|
||||||
|
|
||||||
itemid = item['Id']
|
itemid = item['Id']
|
||||||
artworks = item['ImageTags']
|
artworks = item['ImageTags']
|
||||||
backdrops = item.get('BackdropImageTags',[])
|
backdrops = item.get('BackdropImageTags',[])
|
||||||
|
@ -527,13 +531,13 @@ def getAllArtwork(self, item, parentInfo=False):
|
||||||
'Disc': "",
|
'Disc': "",
|
||||||
'Backdrop': []
|
'Backdrop': []
|
||||||
}
|
}
|
||||||
|
|
||||||
# Process backdrops
|
# Process backdrops
|
||||||
for index, tag in enumerate(backdrops):
|
for index, tag in enumerate(backdrops):
|
||||||
artwork = (
|
artwork = (
|
||||||
"%s/emby/Items/%s/Images/Backdrop/%s?"
|
"%s/emby/Items/%s/Images/Backdrop/%s?"
|
||||||
"MaxWidth=%s&MaxHeight=%s&Format=original&Tag=%s%s"
|
"MaxWidth=%s&MaxHeight=%s&Format=original&Tag=%s%s"
|
||||||
% (server, itemid, index, maxWidth, maxHeight, tag, customquery))
|
% (self.server, itemid, index, maxWidth, maxHeight, tag, customquery))
|
||||||
allartworks['Backdrop'].append(artwork)
|
allartworks['Backdrop'].append(artwork)
|
||||||
|
|
||||||
# Process the rest of the artwork
|
# Process the rest of the artwork
|
||||||
|
@ -544,15 +548,15 @@ def getAllArtwork(self, item, parentInfo=False):
|
||||||
artwork = (
|
artwork = (
|
||||||
"%s/emby/Items/%s/Images/%s/0?"
|
"%s/emby/Items/%s/Images/%s/0?"
|
||||||
"MaxWidth=%s&MaxHeight=%s&Format=original&Tag=%s%s"
|
"MaxWidth=%s&MaxHeight=%s&Format=original&Tag=%s%s"
|
||||||
% (server, itemid, art, maxWidth, maxHeight, tag, customquery))
|
% (self.server, itemid, art, maxWidth, maxHeight, tag, customquery))
|
||||||
allartworks[art] = artwork
|
allartworks[art] = artwork
|
||||||
|
|
||||||
# Process parent items if the main item is missing artwork
|
# Process parent items if the main item is missing artwork
|
||||||
if parentInfo:
|
if parentInfo:
|
||||||
|
|
||||||
# Process parent backdrops
|
# Process parent backdrops
|
||||||
if not allartworks['Backdrop']:
|
if not allartworks['Backdrop']:
|
||||||
|
|
||||||
parentId = item.get('ParentBackdropItemId')
|
parentId = item.get('ParentBackdropItemId')
|
||||||
if parentId:
|
if parentId:
|
||||||
# If there is a parentId, go through the parent backdrop list
|
# If there is a parentId, go through the parent backdrop list
|
||||||
|
@ -562,7 +566,7 @@ def getAllArtwork(self, item, parentInfo=False):
|
||||||
artwork = (
|
artwork = (
|
||||||
"%s/emby/Items/%s/Images/Backdrop/%s?"
|
"%s/emby/Items/%s/Images/Backdrop/%s?"
|
||||||
"MaxWidth=%s&MaxHeight=%s&Format=original&Tag=%s%s"
|
"MaxWidth=%s&MaxHeight=%s&Format=original&Tag=%s%s"
|
||||||
% (server, parentId, index, maxWidth, maxHeight, tag, customquery))
|
% (self.server, parentId, index, maxWidth, maxHeight, tag, customquery))
|
||||||
allartworks['Backdrop'].append(artwork)
|
allartworks['Backdrop'].append(artwork)
|
||||||
|
|
||||||
# Process the rest of the artwork
|
# Process the rest of the artwork
|
||||||
|
@ -570,15 +574,15 @@ def getAllArtwork(self, item, parentInfo=False):
|
||||||
for parentart in parentartwork:
|
for parentart in parentartwork:
|
||||||
|
|
||||||
if not allartworks[parentart]:
|
if not allartworks[parentart]:
|
||||||
|
|
||||||
parentId = item.get('Parent%sItemId' % parentart)
|
parentId = item.get('Parent%sItemId' % parentart)
|
||||||
if parentId:
|
if parentId:
|
||||||
|
|
||||||
parentTag = item['Parent%sImageTag' % parentart]
|
parentTag = item['Parent%sImageTag' % parentart]
|
||||||
artwork = (
|
artwork = (
|
||||||
"%s/emby/Items/%s/Images/%s/0?"
|
"%s/emby/Items/%s/Images/%s/0?"
|
||||||
"MaxWidth=%s&MaxHeight=%s&Format=original&Tag=%s%s"
|
"MaxWidth=%s&MaxHeight=%s&Format=original&Tag=%s%s"
|
||||||
% (server, parentId, parentart,
|
% (self.server, parentId, parentart,
|
||||||
maxWidth, maxHeight, parentTag, customquery))
|
maxWidth, maxHeight, parentTag, customquery))
|
||||||
allartworks[parentart] = artwork
|
allartworks[parentart] = artwork
|
||||||
|
|
||||||
|
@ -587,12 +591,12 @@ def getAllArtwork(self, item, parentInfo=False):
|
||||||
|
|
||||||
parentId = item.get('AlbumId')
|
parentId = item.get('AlbumId')
|
||||||
if parentId and item.get('AlbumPrimaryImageTag'):
|
if parentId and item.get('AlbumPrimaryImageTag'):
|
||||||
|
|
||||||
parentTag = item['AlbumPrimaryImageTag']
|
parentTag = item['AlbumPrimaryImageTag']
|
||||||
artwork = (
|
artwork = (
|
||||||
"%s/emby/Items/%s/Images/Primary/0?"
|
"%s/emby/Items/%s/Images/Primary/0?"
|
||||||
"MaxWidth=%s&MaxHeight=%s&Format=original&Tag=%s%s"
|
"MaxWidth=%s&MaxHeight=%s&Format=original&Tag=%s%s"
|
||||||
% (server, parentId, maxWidth, maxHeight, parentTag, customquery))
|
% (self.server, parentId, maxWidth, maxHeight, parentTag, customquery))
|
||||||
allartworks['Primary'] = artwork
|
allartworks['Primary'] = artwork
|
||||||
|
|
||||||
return allartworks
|
return allartworks
|
||||||
|
|
|
@ -21,7 +21,7 @@ requests.packages.urllib3.disable_warnings(InsecurePlatformWarning)
|
||||||
|
|
||||||
|
|
||||||
class ConnectUtils():
|
class ConnectUtils():
|
||||||
|
|
||||||
# Borg - multiple instances, shared state
|
# Borg - multiple instances, shared state
|
||||||
_shared_state = {}
|
_shared_state = {}
|
||||||
clientInfo = clientinfo.ClientInfo()
|
clientInfo = clientinfo.ClientInfo()
|
||||||
|
@ -60,8 +60,6 @@ class ConnectUtils():
|
||||||
|
|
||||||
def startSession(self):
|
def startSession(self):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
|
|
||||||
self.deviceId = self.clientInfo.getDeviceId()
|
self.deviceId = self.clientInfo.getDeviceId()
|
||||||
|
|
||||||
# User is identified from this point
|
# User is identified from this point
|
||||||
|
@ -75,8 +73,8 @@ class ConnectUtils():
|
||||||
if self.sslclient is not None:
|
if self.sslclient is not None:
|
||||||
verify = self.sslclient
|
verify = self.sslclient
|
||||||
except:
|
except:
|
||||||
log("Could not load SSL settings.", 1)
|
self.logMsg("Could not load SSL settings.", 1)
|
||||||
|
|
||||||
# Start session
|
# Start session
|
||||||
self.c = requests.Session()
|
self.c = requests.Session()
|
||||||
self.c.headers = header
|
self.c.headers = header
|
||||||
|
@ -85,7 +83,7 @@ class ConnectUtils():
|
||||||
self.c.mount("http://", requests.adapters.HTTPAdapter(max_retries=1))
|
self.c.mount("http://", requests.adapters.HTTPAdapter(max_retries=1))
|
||||||
self.c.mount("https://", requests.adapters.HTTPAdapter(max_retries=1))
|
self.c.mount("https://", requests.adapters.HTTPAdapter(max_retries=1))
|
||||||
|
|
||||||
log("Requests session started on: %s" % self.server, 1)
|
self.logMsg("Requests session started on: %s" % self.server, 1)
|
||||||
|
|
||||||
def stopSession(self):
|
def stopSession(self):
|
||||||
try:
|
try:
|
||||||
|
@ -95,8 +93,7 @@ class ConnectUtils():
|
||||||
|
|
||||||
def getHeader(self, authenticate=True):
|
def getHeader(self, authenticate=True):
|
||||||
|
|
||||||
clientInfo = self.clientInfo
|
version = self.clientInfo.getVersion()
|
||||||
version = clientInfo.getVersion()
|
|
||||||
|
|
||||||
if not authenticate:
|
if not authenticate:
|
||||||
# If user is not authenticated
|
# If user is not authenticated
|
||||||
|
@ -105,9 +102,9 @@ class ConnectUtils():
|
||||||
'X-Application': "Kodi/%s" % version,
|
'X-Application': "Kodi/%s" % version,
|
||||||
'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||||
'Accept': "application/json"
|
'Accept': "application/json"
|
||||||
}
|
}
|
||||||
self.logMsg("Header: %s" % header, 1)
|
self.logMsg("Header: %s" % header, 1)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
token = self.token
|
token = self.token
|
||||||
# Attached to the requests session
|
# Attached to the requests session
|
||||||
|
@ -117,18 +114,17 @@ class ConnectUtils():
|
||||||
'Accept': "application/json",
|
'Accept': "application/json",
|
||||||
'X-Application': "Kodi/%s" % version,
|
'X-Application': "Kodi/%s" % version,
|
||||||
'X-Connect-UserToken': token
|
'X-Connect-UserToken': token
|
||||||
}
|
}
|
||||||
self.logMsg("Header: %s" % header, 1)
|
self.logMsg("Header: %s" % header, 1)
|
||||||
|
|
||||||
return header
|
return header
|
||||||
|
|
||||||
def doUrl(self, url, data=None, postBody=None, rtype="GET",
|
def doUrl(self, url, data=None, postBody=None, rtype="GET",
|
||||||
parameters=None, authenticate=True, timeout=None):
|
parameters=None, authenticate=True, timeout=None):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
window = utils.window
|
window = utils.window
|
||||||
|
|
||||||
log("=== ENTER connectUrl ===", 2)
|
self.logMsg("=== ENTER connectUrl ===", 2)
|
||||||
default_link = ""
|
default_link = ""
|
||||||
if timeout is None:
|
if timeout is None:
|
||||||
timeout = self.timeout
|
timeout = self.timeout
|
||||||
|
@ -137,7 +133,7 @@ class ConnectUtils():
|
||||||
try:
|
try:
|
||||||
# If connect user is authenticated
|
# If connect user is authenticated
|
||||||
if authenticate:
|
if authenticate:
|
||||||
try:
|
try:
|
||||||
c = self.c
|
c = self.c
|
||||||
# Replace for the real values
|
# Replace for the real values
|
||||||
url = url.replace("{server}", self.server)
|
url = url.replace("{server}", self.server)
|
||||||
|
@ -167,7 +163,7 @@ class ConnectUtils():
|
||||||
verifyssl = self.sslclient
|
verifyssl = self.sslclient
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Prepare request
|
# Prepare request
|
||||||
if rtype == "GET":
|
if rtype == "GET":
|
||||||
r = requests.get(url,
|
r = requests.get(url,
|
||||||
|
@ -195,7 +191,7 @@ class ConnectUtils():
|
||||||
verifyssl = self.sslclient
|
verifyssl = self.sslclient
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Prepare request
|
# Prepare request
|
||||||
if rtype == "GET":
|
if rtype == "GET":
|
||||||
r = requests.get(url,
|
r = requests.get(url,
|
||||||
|
@ -213,28 +209,28 @@ class ConnectUtils():
|
||||||
verify=verifyssl)
|
verify=verifyssl)
|
||||||
|
|
||||||
##### THE RESPONSE #####
|
##### THE RESPONSE #####
|
||||||
log(r.url, 1)
|
self.logMsg(r.url, 1)
|
||||||
log(r, 1)
|
self.logMsg(r, 1)
|
||||||
|
|
||||||
if r.status_code == 204:
|
if r.status_code == 204:
|
||||||
# No body in the response
|
# No body in the response
|
||||||
log("====== 204 Success ======", 1)
|
self.logMsg("====== 204 Success ======", 1)
|
||||||
|
|
||||||
elif r.status_code == requests.codes.ok:
|
elif r.status_code == requests.codes.ok:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# UNICODE - JSON object
|
# UNICODE - JSON object
|
||||||
r = r.json()
|
r = r.json()
|
||||||
log("====== 200 Success ======", 1)
|
self.logMsg("====== 200 Success ======", 1)
|
||||||
log("Response: %s" % r, 1)
|
self.logMsg("Response: %s" % r, 1)
|
||||||
return r
|
return r
|
||||||
|
|
||||||
except:
|
except:
|
||||||
if r.headers.get('content-type') != "text/html":
|
if r.headers.get('content-type') != "text/html":
|
||||||
log("Unable to convert the response for: %s" % url, 1)
|
self.logMsg("Unable to convert the response for: %s" % url, 1)
|
||||||
else:
|
else:
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
|
|
||||||
##### EXCEPTIONS #####
|
##### EXCEPTIONS #####
|
||||||
|
|
||||||
except requests.exceptions.ConnectionError as e:
|
except requests.exceptions.ConnectionError as e:
|
||||||
|
@ -242,8 +238,8 @@ class ConnectUtils():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
except requests.exceptions.ConnectTimeout as e:
|
except requests.exceptions.ConnectTimeout as e:
|
||||||
log("Server timeout at: %s" % url, 0)
|
self.logMsg("Server timeout at: %s" % url, 0)
|
||||||
log(e, 1)
|
self.logMsg(e, 1)
|
||||||
|
|
||||||
except requests.exceptions.HTTPError as e:
|
except requests.exceptions.HTTPError as e:
|
||||||
|
|
||||||
|
@ -259,11 +255,11 @@ class ConnectUtils():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
except requests.exceptions.SSLError as e:
|
except requests.exceptions.SSLError as e:
|
||||||
log("Invalid SSL certificate for: %s" % url, 0)
|
self.logMsg("Invalid SSL certificate for: %s" % url, 0)
|
||||||
log(e, 1)
|
self.logMsg(e, 1)
|
||||||
|
|
||||||
except requests.exceptions.RequestException as e:
|
except requests.exceptions.RequestException as e:
|
||||||
log("Unknown error connecting to: %s" % url, 0)
|
self.logMsg("Unknown error connecting to: %s" % url, 0)
|
||||||
log(e, 1)
|
self.logMsg(e, 1)
|
||||||
|
|
||||||
return default_link
|
return default_link
|
||||||
|
|
|
@ -34,7 +34,6 @@ class Embydb_Functions():
|
||||||
|
|
||||||
def getViews(self):
|
def getViews(self):
|
||||||
|
|
||||||
embycursor = self.embycursor
|
|
||||||
views = []
|
views = []
|
||||||
|
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
@ -42,8 +41,8 @@ class Embydb_Functions():
|
||||||
"SELECT view_id",
|
"SELECT view_id",
|
||||||
"FROM view"
|
"FROM view"
|
||||||
))
|
))
|
||||||
embycursor.execute(query)
|
self.embycursor.execute(query)
|
||||||
rows = embycursor.fetchall()
|
rows = self.embycursor.fetchall()
|
||||||
for row in rows:
|
for row in rows:
|
||||||
views.append(row[0])
|
views.append(row[0])
|
||||||
return views
|
return views
|
||||||
|
@ -68,7 +67,6 @@ class Embydb_Functions():
|
||||||
|
|
||||||
def getView_byId(self, viewid):
|
def getView_byId(self, viewid):
|
||||||
|
|
||||||
embycursor = self.embycursor
|
|
||||||
|
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
|
@ -76,13 +74,13 @@ class Embydb_Functions():
|
||||||
"FROM view",
|
"FROM view",
|
||||||
"WHERE view_id = ?"
|
"WHERE view_id = ?"
|
||||||
))
|
))
|
||||||
embycursor.execute(query, (viewid,))
|
self.embycursor.execute(query, (viewid,))
|
||||||
view = embycursor.fetchone()
|
view = self.embycursor.fetchone()
|
||||||
|
|
||||||
return view
|
return view
|
||||||
|
|
||||||
def getView_byType(self, mediatype):
|
def getView_byType(self, mediatype):
|
||||||
|
|
||||||
embycursor = self.embycursor
|
|
||||||
views = []
|
views = []
|
||||||
|
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
@ -91,8 +89,8 @@ class Embydb_Functions():
|
||||||
"FROM view",
|
"FROM view",
|
||||||
"WHERE media_type = ?"
|
"WHERE media_type = ?"
|
||||||
))
|
))
|
||||||
embycursor.execute(query, (mediatype,))
|
self.embycursor.execute(query, (mediatype,))
|
||||||
rows = embycursor.fetchall()
|
rows = self.embycursor.fetchall()
|
||||||
for row in rows:
|
for row in rows:
|
||||||
views.append({
|
views.append({
|
||||||
|
|
||||||
|
@ -105,17 +103,16 @@ class Embydb_Functions():
|
||||||
|
|
||||||
def getView_byName(self, tagname):
|
def getView_byName(self, tagname):
|
||||||
|
|
||||||
embycursor = self.embycursor
|
|
||||||
|
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
"SELECT view_id",
|
"SELECT view_id",
|
||||||
"FROM view",
|
"FROM view",
|
||||||
"WHERE view_name = ?"
|
"WHERE view_name = ?"
|
||||||
))
|
))
|
||||||
embycursor.execute(query, (tagname,))
|
self.embycursor.execute(query, (tagname,))
|
||||||
try:
|
try:
|
||||||
view = embycursor.fetchone()[0]
|
view = self.embycursor.fetchone()[0]
|
||||||
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
view = None
|
view = None
|
||||||
|
|
||||||
|
@ -190,8 +187,6 @@ class Embydb_Functions():
|
||||||
|
|
||||||
def getItem_byId(self, embyid):
|
def getItem_byId(self, embyid):
|
||||||
|
|
||||||
embycursor = self.embycursor
|
|
||||||
|
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
"SELECT kodi_id, kodi_fileid, kodi_pathid, parent_id, media_type, emby_type",
|
"SELECT kodi_id, kodi_fileid, kodi_pathid, parent_id, media_type, emby_type",
|
||||||
|
@ -199,40 +194,32 @@ class Embydb_Functions():
|
||||||
"WHERE emby_id = ?"
|
"WHERE emby_id = ?"
|
||||||
))
|
))
|
||||||
try:
|
try:
|
||||||
embycursor.execute(query, (embyid,))
|
self.embycursor.execute(query, (embyid,))
|
||||||
item = embycursor.fetchone()
|
item = self.embycursor.fetchone()
|
||||||
return item
|
return item
|
||||||
except: return None
|
except: return None
|
||||||
|
|
||||||
def getItem_byWildId(self, embyid):
|
def getItem_byWildId(self, embyid):
|
||||||
|
|
||||||
embycursor = self.embycursor
|
|
||||||
|
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
"SELECT kodi_id, media_type",
|
"SELECT kodi_id, media_type",
|
||||||
"FROM emby",
|
"FROM emby",
|
||||||
"WHERE emby_id LIKE ?"
|
"WHERE emby_id LIKE ?"
|
||||||
))
|
))
|
||||||
embycursor.execute(query, (embyid+"%",))
|
self.embycursor.execute(query, (embyid+"%",))
|
||||||
items = embycursor.fetchall()
|
return self.embycursor.fetchall()
|
||||||
|
|
||||||
return items
|
|
||||||
|
|
||||||
def getItem_byView(self, mediafolderid):
|
def getItem_byView(self, mediafolderid):
|
||||||
|
|
||||||
embycursor = self.embycursor
|
|
||||||
|
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
"SELECT kodi_id",
|
"SELECT kodi_id",
|
||||||
"FROM emby",
|
"FROM emby",
|
||||||
"WHERE media_folder = ?"
|
"WHERE media_folder = ?"
|
||||||
))
|
))
|
||||||
embycursor.execute(query, (mediafolderid,))
|
self.embycursor.execute(query, (mediafolderid,))
|
||||||
items = embycursor.fetchall()
|
return self.embycursor.fetchall()
|
||||||
|
|
||||||
return items
|
|
||||||
|
|
||||||
def getPlexId(self, kodiid, mediatype):
|
def getPlexId(self, kodiid, mediatype):
|
||||||
"""
|
"""
|
||||||
|
@ -253,8 +240,6 @@ class Embydb_Functions():
|
||||||
|
|
||||||
def getItem_byKodiId(self, kodiid, mediatype):
|
def getItem_byKodiId(self, kodiid, mediatype):
|
||||||
|
|
||||||
embycursor = self.embycursor
|
|
||||||
|
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
"SELECT emby_id, parent_id",
|
"SELECT emby_id, parent_id",
|
||||||
|
@ -262,15 +247,11 @@ class Embydb_Functions():
|
||||||
"WHERE kodi_id = ?",
|
"WHERE kodi_id = ?",
|
||||||
"AND media_type = ?"
|
"AND media_type = ?"
|
||||||
))
|
))
|
||||||
embycursor.execute(query, (kodiid, mediatype,))
|
self.embycursor.execute(query, (kodiid, mediatype,))
|
||||||
item = embycursor.fetchone()
|
return self.embycursor.fetchone()
|
||||||
|
|
||||||
return item
|
|
||||||
|
|
||||||
def getItem_byParentId(self, parentid, mediatype):
|
def getItem_byParentId(self, parentid, mediatype):
|
||||||
|
|
||||||
embycursor = self.embycursor
|
|
||||||
|
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
"SELECT emby_id, kodi_id, kodi_fileid",
|
"SELECT emby_id, kodi_id, kodi_fileid",
|
||||||
|
@ -278,15 +259,11 @@ class Embydb_Functions():
|
||||||
"WHERE parent_id = ?",
|
"WHERE parent_id = ?",
|
||||||
"AND media_type = ?"
|
"AND media_type = ?"
|
||||||
))
|
))
|
||||||
embycursor.execute(query, (parentid, mediatype,))
|
self.embycursor.execute(query, (parentid, mediatype,))
|
||||||
items = embycursor.fetchall()
|
return self.embycursor.fetchall()
|
||||||
|
|
||||||
return items
|
|
||||||
|
|
||||||
def getItemId_byParentId(self, parentid, mediatype):
|
def getItemId_byParentId(self, parentid, mediatype):
|
||||||
|
|
||||||
embycursor = self.embycursor
|
|
||||||
|
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
"SELECT emby_id, kodi_id",
|
"SELECT emby_id, kodi_id",
|
||||||
|
@ -294,39 +271,32 @@ class Embydb_Functions():
|
||||||
"WHERE parent_id = ?",
|
"WHERE parent_id = ?",
|
||||||
"AND media_type = ?"
|
"AND media_type = ?"
|
||||||
))
|
))
|
||||||
embycursor.execute(query, (parentid, mediatype,))
|
self.embycursor.execute(query, (parentid, mediatype,))
|
||||||
items = embycursor.fetchall()
|
return self.embycursor.fetchall()
|
||||||
|
|
||||||
return items
|
|
||||||
|
|
||||||
def getChecksum(self, mediatype):
|
def getChecksum(self, mediatype):
|
||||||
|
|
||||||
embycursor = self.embycursor
|
|
||||||
|
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
"SELECT emby_id, checksum",
|
"SELECT emby_id, checksum",
|
||||||
"FROM emby",
|
"FROM emby",
|
||||||
"WHERE emby_type = ?"
|
"WHERE emby_type = ?"
|
||||||
))
|
))
|
||||||
embycursor.execute(query, (mediatype,))
|
self.embycursor.execute(query, (mediatype,))
|
||||||
items = embycursor.fetchall()
|
return self.embycursor.fetchall()
|
||||||
|
|
||||||
return items
|
|
||||||
|
|
||||||
def getMediaType_byId(self, embyid):
|
def getMediaType_byId(self, embyid):
|
||||||
|
|
||||||
embycursor = self.embycursor
|
|
||||||
|
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
"SELECT emby_type",
|
"SELECT emby_type",
|
||||||
"FROM emby",
|
"FROM emby",
|
||||||
"WHERE emby_id = ?"
|
"WHERE emby_id = ?"
|
||||||
))
|
))
|
||||||
embycursor.execute(query, (embyid,))
|
self.embycursor.execute(query, (embyid,))
|
||||||
try:
|
try:
|
||||||
itemtype = embycursor.fetchone()[0]
|
itemtype = self.embycursor.fetchone()[0]
|
||||||
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
itemtype = None
|
itemtype = None
|
||||||
|
|
||||||
|
|
|
@ -328,12 +328,12 @@ def doMainListing():
|
||||||
if not path:
|
if not path:
|
||||||
path = utils.window('Emby.nodes.%s.content' % i)
|
path = utils.window('Emby.nodes.%s.content' % i)
|
||||||
label = utils.window('Emby.nodes.%s.title' % i)
|
label = utils.window('Emby.nodes.%s.title' % i)
|
||||||
type = utils.window('Emby.nodes.%s.type' % i)
|
node_type = utils.window('Emby.nodes.%s.type' % i)
|
||||||
#because we do not use seperate entrypoints for each content type, we need to figure out which items to show in each listing.
|
#because we do not use seperate entrypoints for each content type, we need to figure out which items to show in each listing.
|
||||||
#for now we just only show picture nodes in the picture library video nodes in the video library and all nodes in any other window
|
#for now we just only show picture nodes in the picture library video nodes in the video library and all nodes in any other window
|
||||||
if path and xbmc.getCondVisibility("Window.IsActive(Pictures)") and type == "photos":
|
if path and xbmc.getCondVisibility("Window.IsActive(Pictures)") and node_type == "photos":
|
||||||
addDirectoryItem(label, path)
|
addDirectoryItem(label, path)
|
||||||
elif path and xbmc.getCondVisibility("Window.IsActive(VideoLibrary)") and type != "photos":
|
elif path and xbmc.getCondVisibility("Window.IsActive(VideoLibrary)") and node_type != "photos":
|
||||||
addDirectoryItem(label, path)
|
addDirectoryItem(label, path)
|
||||||
elif path and not xbmc.getCondVisibility("Window.IsActive(VideoLibrary) | Window.IsActive(Pictures) | Window.IsActive(MusicLibrary)"):
|
elif path and not xbmc.getCondVisibility("Window.IsActive(VideoLibrary) | Window.IsActive(Pictures) | Window.IsActive(MusicLibrary)"):
|
||||||
addDirectoryItem(label, path)
|
addDirectoryItem(label, path)
|
||||||
|
@ -431,7 +431,7 @@ def deleteItem():
|
||||||
doUtils = downloadutils.DownloadUtils()
|
doUtils = downloadutils.DownloadUtils()
|
||||||
url = "{server}/emby/Items/%s?format=json" % embyid
|
url = "{server}/emby/Items/%s?format=json" % embyid
|
||||||
utils.logMsg("EMBY delete", "Deleting request: %s" % embyid, 0)
|
utils.logMsg("EMBY delete", "Deleting request: %s" % embyid, 0)
|
||||||
doUtils.downloadUrl(url, type="DELETE")
|
doUtils.downloadUrl(url, action_type="DELETE")
|
||||||
|
|
||||||
##### ADD ADDITIONAL USERS #####
|
##### ADD ADDITIONAL USERS #####
|
||||||
def addUser():
|
def addUser():
|
||||||
|
@ -486,7 +486,7 @@ def addUser():
|
||||||
selected = additionalUsername[resp]
|
selected = additionalUsername[resp]
|
||||||
selected_userId = additionalUserlist[selected]
|
selected_userId = additionalUserlist[selected]
|
||||||
url = "{server}/emby/Sessions/%s/Users/%s" % (sessionId, selected_userId)
|
url = "{server}/emby/Sessions/%s/Users/%s" % (sessionId, selected_userId)
|
||||||
doUtils.downloadUrl(url, postBody={}, type="DELETE")
|
doUtils.downloadUrl(url, postBody={}, action_type="DELETE")
|
||||||
dialog.notification(
|
dialog.notification(
|
||||||
heading="Success!",
|
heading="Success!",
|
||||||
message="%s removed from viewing session" % selected,
|
message="%s removed from viewing session" % selected,
|
||||||
|
@ -519,7 +519,7 @@ def addUser():
|
||||||
selected = users[resp]
|
selected = users[resp]
|
||||||
selected_userId = userlist[selected]
|
selected_userId = userlist[selected]
|
||||||
url = "{server}/emby/Sessions/%s/Users/%s" % (sessionId, selected_userId)
|
url = "{server}/emby/Sessions/%s/Users/%s" % (sessionId, selected_userId)
|
||||||
doUtils.downloadUrl(url, postBody={}, type="POST")
|
doUtils.downloadUrl(url, postBody={}, action_type="POST")
|
||||||
dialog.notification(
|
dialog.notification(
|
||||||
heading="Success!",
|
heading="Success!",
|
||||||
message="%s added to viewing session" % selected,
|
message="%s added to viewing session" % selected,
|
||||||
|
@ -759,22 +759,22 @@ def GetSubFolders(nodeindex):
|
||||||
title = utils.window('Emby.nodes.%s%s.title' %(nodeindex,node))
|
title = utils.window('Emby.nodes.%s%s.title' %(nodeindex,node))
|
||||||
if title:
|
if title:
|
||||||
path = utils.window('Emby.nodes.%s%s.content' %(nodeindex,node))
|
path = utils.window('Emby.nodes.%s%s.content' %(nodeindex,node))
|
||||||
type = utils.window('Emby.nodes.%s%s.type' %(nodeindex,node))
|
|
||||||
addDirectoryItem(title, path)
|
addDirectoryItem(title, path)
|
||||||
xbmcplugin.endOfDirectory(int(sys.argv[1]))
|
xbmcplugin.endOfDirectory(int(sys.argv[1]))
|
||||||
|
|
||||||
##### BROWSE EMBY NODES DIRECTLY #####
|
##### BROWSE EMBY NODES DIRECTLY #####
|
||||||
def BrowseContent(viewname, type="", folderid=""):
|
def BrowseContent(viewname, browse_type="", folderid=""):
|
||||||
|
|
||||||
emby = embyserver.Read_EmbyServer()
|
emby = embyserver.Read_EmbyServer()
|
||||||
art = artwork.Artwork()
|
art = artwork.Artwork()
|
||||||
doUtils = downloadutils.DownloadUtils()
|
doUtils = downloadutils.DownloadUtils()
|
||||||
|
|
||||||
#folderid used as filter ?
|
#folderid used as filter ?
|
||||||
if folderid in ["recent","recentepisodes","inprogress","inprogressepisodes","unwatched","nextepisodes","sets","genres","random","recommended"]:
|
if folderid in ["recent","recentepisodes","inprogress","inprogressepisodes","unwatched","nextepisodes","sets","genres","random","recommended"]:
|
||||||
filter = folderid
|
filter_type = folderid
|
||||||
folderid = ""
|
folderid = ""
|
||||||
else:
|
else:
|
||||||
filter = ""
|
filter_type = ""
|
||||||
|
|
||||||
xbmcplugin.setPluginCategory(int(sys.argv[1]), viewname)
|
xbmcplugin.setPluginCategory(int(sys.argv[1]), viewname)
|
||||||
#get views for root level
|
#get views for root level
|
||||||
|
@ -783,33 +783,35 @@ def BrowseContent(viewname, type="", folderid=""):
|
||||||
for view in views:
|
for view in views:
|
||||||
if view.get("name") == viewname.decode('utf-8'):
|
if view.get("name") == viewname.decode('utf-8'):
|
||||||
folderid = view.get("id")
|
folderid = view.get("id")
|
||||||
|
break
|
||||||
|
|
||||||
utils.logMsg("BrowseContent","viewname: %s - type: %s - folderid: %s - filter: %s" %(viewname.decode('utf-8'), type.decode('utf-8'), folderid.decode('utf-8'), filter.decode('utf-8')))
|
if viewname is not None:
|
||||||
|
utils.logMsg("BrowseContent","viewname: %s - type: %s - folderid: %s - filter: %s" %(viewname.decode('utf-8'), browse_type.decode('utf-8'), folderid.decode('utf-8'), filter_type.decode('utf-8')))
|
||||||
#set the correct params for the content type
|
#set the correct params for the content type
|
||||||
#only proceed if we have a folderid
|
#only proceed if we have a folderid
|
||||||
if folderid:
|
if folderid:
|
||||||
if type.lower() == "homevideos":
|
if browse_type.lower() == "homevideos":
|
||||||
xbmcplugin.setContent(int(sys.argv[1]), 'episodes')
|
xbmcplugin.setContent(int(sys.argv[1]), 'episodes')
|
||||||
itemtype = "Video,Folder,PhotoAlbum"
|
itemtype = "Video,Folder,PhotoAlbum"
|
||||||
elif type.lower() == "photos":
|
elif browse_type.lower() == "photos":
|
||||||
xbmcplugin.setContent(int(sys.argv[1]), 'files')
|
xbmcplugin.setContent(int(sys.argv[1]), 'files')
|
||||||
itemtype = "Photo,PhotoAlbum,Folder"
|
itemtype = "Photo,PhotoAlbum,Folder"
|
||||||
else:
|
else:
|
||||||
itemtype = ""
|
itemtype = ""
|
||||||
|
|
||||||
#get the actual listing
|
#get the actual listing
|
||||||
if type == "recordings":
|
if browse_type == "recordings":
|
||||||
listing = emby.getTvRecordings(folderid)
|
listing = emby.getTvRecordings(folderid)
|
||||||
elif type == "tvchannels":
|
elif browse_type == "tvchannels":
|
||||||
listing = emby.getTvChannels()
|
listing = emby.getTvChannels()
|
||||||
elif filter == "recent":
|
elif filter_type == "recent":
|
||||||
listing = emby.getFilteredSection(folderid, itemtype=itemtype.split(",")[0], sortby="DateCreated", recursive=True, limit=25, sortorder="Descending")
|
listing = emby.getFilteredSection(folderid, itemtype=itemtype.split(",")[0], sortby="DateCreated", recursive=True, limit=25, sortorder="Descending")
|
||||||
elif filter == "random":
|
elif filter_type == "random":
|
||||||
listing = emby.getFilteredSection(folderid, itemtype=itemtype.split(",")[0], sortby="Random", recursive=True, limit=150, sortorder="Descending")
|
listing = emby.getFilteredSection(folderid, itemtype=itemtype.split(",")[0], sortby="Random", recursive=True, limit=150, sortorder="Descending")
|
||||||
elif filter == "recommended":
|
elif filter_type == "recommended":
|
||||||
listing = emby.getFilteredSection(folderid, itemtype=itemtype.split(",")[0], sortby="SortName", recursive=True, limit=25, sortorder="Ascending", filter="IsFavorite")
|
listing = emby.getFilteredSection(folderid, itemtype=itemtype.split(",")[0], sortby="SortName", recursive=True, limit=25, sortorder="Ascending", filter_type="IsFavorite")
|
||||||
elif filter == "sets":
|
elif filter_type == "sets":
|
||||||
listing = emby.getFilteredSection(folderid, itemtype=itemtype.split(",")[1], sortby="SortName", recursive=True, limit=25, sortorder="Ascending", filter="IsFavorite")
|
listing = emby.getFilteredSection(folderid, itemtype=itemtype.split(",")[1], sortby="SortName", recursive=True, limit=25, sortorder="Ascending", filter_type="IsFavorite")
|
||||||
else:
|
else:
|
||||||
listing = emby.getFilteredSection(folderid, itemtype=itemtype, recursive=False)
|
listing = emby.getFilteredSection(folderid, itemtype=itemtype, recursive=False)
|
||||||
|
|
||||||
|
@ -819,14 +821,14 @@ def BrowseContent(viewname, type="", folderid=""):
|
||||||
li = createListItemFromEmbyItem(item,art,doUtils)
|
li = createListItemFromEmbyItem(item,art,doUtils)
|
||||||
if item.get("IsFolder") == True:
|
if item.get("IsFolder") == True:
|
||||||
#for folders we add an additional browse request, passing the folderId
|
#for folders we add an additional browse request, passing the folderId
|
||||||
path = "%s?id=%s&mode=browsecontent&type=%s&folderid=%s" % (sys.argv[0].decode('utf-8'), viewname.decode('utf-8'), type.decode('utf-8'), item.get("Id").decode('utf-8'))
|
path = "%s?id=%s&mode=browsecontent&type=%s&folderid=%s" % (sys.argv[0].decode('utf-8'), viewname.decode('utf-8'), browse_type.decode('utf-8'), item.get("Id").decode('utf-8'))
|
||||||
xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=path, listitem=li, isFolder=True)
|
xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=path, listitem=li, isFolder=True)
|
||||||
else:
|
else:
|
||||||
#playable item, set plugin path and mediastreams
|
#playable item, set plugin path and mediastreams
|
||||||
xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=li.getProperty("path"), listitem=li)
|
xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=li.getProperty("path"), listitem=li)
|
||||||
|
|
||||||
|
|
||||||
if filter == "recent":
|
if filter_type == "recent":
|
||||||
xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_DATE)
|
xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_DATE)
|
||||||
else:
|
else:
|
||||||
xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_VIDEO_TITLE)
|
xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_VIDEO_TITLE)
|
||||||
|
|
|
@ -309,10 +309,9 @@ class Movies(Items):
|
||||||
count = 0
|
count = 0
|
||||||
for boxset in items:
|
for boxset in items:
|
||||||
|
|
||||||
title = boxset['Name']
|
|
||||||
if pdialog:
|
if pdialog:
|
||||||
percentage = int((float(count) / float(total))*100)
|
percentage = int((float(count) / float(total))*100)
|
||||||
pdialog.update(percentage, message=title)
|
pdialog.update(percentage, message=boxset['Name'])
|
||||||
count += 1
|
count += 1
|
||||||
self.add_updateBoxset(boxset)
|
self.add_updateBoxset(boxset)
|
||||||
|
|
||||||
|
@ -333,7 +332,6 @@ class Movies(Items):
|
||||||
# Process single movie
|
# Process single movie
|
||||||
kodicursor = self.kodicursor
|
kodicursor = self.kodicursor
|
||||||
emby_db = self.emby_db
|
emby_db = self.emby_db
|
||||||
kodi_db = self.kodi_db
|
|
||||||
artwork = self.artwork
|
artwork = self.artwork
|
||||||
API = PlexAPI.API(item)
|
API = PlexAPI.API(item)
|
||||||
|
|
||||||
|
@ -517,23 +515,23 @@ class Movies(Items):
|
||||||
kodi_db.addCountries(movieid, countries, "movie")
|
kodi_db.addCountries(movieid, countries, "movie")
|
||||||
# Process cast
|
# Process cast
|
||||||
people = API.getPeopleList()
|
people = API.getPeopleList()
|
||||||
kodi_db.addPeople(movieid, people, "movie")
|
self.kodi_db.addPeople(movieid, people, "movie")
|
||||||
# Process genres
|
# Process genres
|
||||||
kodi_db.addGenres(movieid, genres, "movie")
|
self.kodi_db.addGenres(movieid, genres, "movie")
|
||||||
# Process artwork
|
# Process artwork
|
||||||
allartworks = API.getAllArtwork()
|
allartworks = API.getAllArtwork()
|
||||||
artwork.addArtwork(allartworks, movieid, "movie", kodicursor)
|
artwork.addArtwork(allartworks, movieid, "movie", kodicursor)
|
||||||
# Process stream details
|
# Process stream details
|
||||||
streams = API.getMediaStreams()
|
streams = API.getMediaStreams()
|
||||||
kodi_db.addStreams(fileid, streams, runtime)
|
self.kodi_db.addStreams(fileid, streams, runtime)
|
||||||
# Process studios
|
# Process studios
|
||||||
kodi_db.addStudios(movieid, studios, "movie")
|
self.kodi_db.addStudios(movieid, studios, "movie")
|
||||||
# Process tags: view, Plex collection tags
|
# Process tags: view, Plex collection tags
|
||||||
tags = [viewtag]
|
tags = [viewtag]
|
||||||
tags.extend(collections)
|
tags.extend(collections)
|
||||||
if userdata['Favorite']:
|
if userdata['Favorite']:
|
||||||
tags.append("Favorite movies")
|
tags.append("Favorite movies")
|
||||||
kodi_db.addTags(movieid, tags, "movie")
|
self.kodi_db.addTags(movieid, tags, "movie")
|
||||||
# Process playstates
|
# Process playstates
|
||||||
kodi_db.addPlaystate(fileid, resume, runtime, playcount, dateplayed)
|
kodi_db.addPlaystate(fileid, resume, runtime, playcount, dateplayed)
|
||||||
|
|
||||||
|
@ -603,7 +601,6 @@ class MusicVideos(Items):
|
||||||
# Process single music video
|
# Process single music video
|
||||||
kodicursor = self.kodicursor
|
kodicursor = self.kodicursor
|
||||||
emby_db = self.emby_db
|
emby_db = self.emby_db
|
||||||
kodi_db = self.kodi_db
|
|
||||||
artwork = self.artwork
|
artwork = self.artwork
|
||||||
API = api.API(item)
|
API = api.API(item)
|
||||||
|
|
||||||
|
@ -794,32 +791,31 @@ class MusicVideos(Items):
|
||||||
artist['Type'] = "Artist"
|
artist['Type'] = "Artist"
|
||||||
people.extend(artists)
|
people.extend(artists)
|
||||||
people = artwork.getPeopleArtwork(people)
|
people = artwork.getPeopleArtwork(people)
|
||||||
kodi_db.addPeople(mvideoid, people, "musicvideo")
|
self.kodi_db.addPeople(mvideoid, people, "musicvideo")
|
||||||
# Process genres
|
# Process genres
|
||||||
kodi_db.addGenres(mvideoid, genres, "musicvideo")
|
self.kodi_db.addGenres(mvideoid, genres, "musicvideo")
|
||||||
# Process artwork
|
# Process artwork
|
||||||
artwork.addArtwork(artwork.getAllArtwork(item), mvideoid, "musicvideo", kodicursor)
|
artwork.addArtwork(artwork.getAllArtwork(item), mvideoid, "musicvideo", kodicursor)
|
||||||
# Process stream details
|
# Process stream details
|
||||||
streams = API.getMediaStreams()
|
streams = API.getMediaStreams()
|
||||||
kodi_db.addStreams(fileid, streams, runtime)
|
self.kodi_db.addStreams(fileid, streams, runtime)
|
||||||
# Process studios
|
# Process studios
|
||||||
kodi_db.addStudios(mvideoid, studios, "musicvideo")
|
self.kodi_db.addStudios(mvideoid, studios, "musicvideo")
|
||||||
# Process tags: view, emby tags
|
# Process tags: view, emby tags
|
||||||
tags = [viewtag]
|
tags = [viewtag]
|
||||||
tags.extend(item['Tags'])
|
tags.extend(item['Tags'])
|
||||||
if userdata['Favorite']:
|
if userdata['Favorite']:
|
||||||
tags.append("Favorite musicvideos")
|
tags.append("Favorite musicvideos")
|
||||||
kodi_db.addTags(mvideoid, tags, "musicvideo")
|
self.kodi_db.addTags(mvideoid, tags, "musicvideo")
|
||||||
# Process playstates
|
# Process playstates
|
||||||
resume = API.adjustResume(userdata['Resume'])
|
resume = API.adjustResume(userdata['Resume'])
|
||||||
total = round(float(runtime), 6)
|
total = round(float(runtime), 6)
|
||||||
kodi_db.addPlaystate(fileid, resume, total, playcount, dateplayed)
|
self.kodi_db.addPlaystate(fileid, resume, total, playcount, dateplayed)
|
||||||
|
|
||||||
def updateUserdata(self, item):
|
def updateUserdata(self, item):
|
||||||
# This updates: Favorite, LastPlayedDate, Playcount, PlaybackPositionTicks
|
# This updates: Favorite, LastPlayedDate, Playcount, PlaybackPositionTicks
|
||||||
# Poster with progress bar
|
# Poster with progress bar
|
||||||
emby_db = self.emby_db
|
emby_db = self.emby_db
|
||||||
kodi_db = self.kodi_db
|
|
||||||
API = api.API(item)
|
API = api.API(item)
|
||||||
|
|
||||||
# Get emby information
|
# Get emby information
|
||||||
|
@ -841,9 +837,9 @@ class MusicVideos(Items):
|
||||||
|
|
||||||
# Process favorite tags
|
# Process favorite tags
|
||||||
if userdata['Favorite']:
|
if userdata['Favorite']:
|
||||||
kodi_db.addTag(mvideoid, "Favorite musicvideos", "musicvideo")
|
self.kodi_db.addTag(mvideoid, "Favorite musicvideos", "musicvideo")
|
||||||
else:
|
else:
|
||||||
kodi_db.removeTag(mvideoid, "Favorite musicvideos", "musicvideo")
|
self.kodi_db.removeTag(mvideoid, "Favorite musicvideos", "musicvideo")
|
||||||
|
|
||||||
# Process playstates
|
# Process playstates
|
||||||
playcount = userdata['PlayCount']
|
playcount = userdata['PlayCount']
|
||||||
|
@ -851,7 +847,7 @@ class MusicVideos(Items):
|
||||||
resume = API.adjustResume(userdata['Resume'])
|
resume = API.adjustResume(userdata['Resume'])
|
||||||
total = round(float(runtime), 6)
|
total = round(float(runtime), 6)
|
||||||
|
|
||||||
kodi_db.addPlaystate(fileid, resume, total, playcount, dateplayed)
|
self.kodi_db.addPlaystate(fileid, resume, total, playcount, dateplayed)
|
||||||
emby_db.updateReference(itemid, checksum)
|
emby_db.updateReference(itemid, checksum)
|
||||||
|
|
||||||
def remove(self, itemid):
|
def remove(self, itemid):
|
||||||
|
@ -878,8 +874,7 @@ class MusicVideos(Items):
|
||||||
"AND media_type = 'musicvideo'"
|
"AND media_type = 'musicvideo'"
|
||||||
))
|
))
|
||||||
kodicursor.execute(query, (mvideoid,))
|
kodicursor.execute(query, (mvideoid,))
|
||||||
rows = kodicursor.fetchall()
|
for row in kodicursor.fetchall():
|
||||||
for row in rows:
|
|
||||||
|
|
||||||
url = row[0]
|
url = row[0]
|
||||||
imagetype = row[1]
|
imagetype = row[1]
|
||||||
|
@ -959,7 +954,6 @@ class TVShows(Items):
|
||||||
# Process single tvshow
|
# Process single tvshow
|
||||||
kodicursor = self.kodicursor
|
kodicursor = self.kodicursor
|
||||||
emby_db = self.emby_db
|
emby_db = self.emby_db
|
||||||
kodi_db = self.kodi_db
|
|
||||||
artwork = self.artwork
|
artwork = self.artwork
|
||||||
API = PlexAPI.API(item)
|
API = PlexAPI.API(item)
|
||||||
|
|
||||||
|
@ -1079,7 +1073,7 @@ class TVShows(Items):
|
||||||
kodicursor.execute(query, (toplevelpath, "tvshows", "metadata.local", 1, toppathid))
|
kodicursor.execute(query, (toplevelpath, "tvshows", "metadata.local", 1, toppathid))
|
||||||
|
|
||||||
# Add path
|
# Add path
|
||||||
pathid = kodi_db.addPath(path)
|
pathid = self.kodi_db.addPath(path)
|
||||||
|
|
||||||
# Create the tvshow entry
|
# Create the tvshow entry
|
||||||
query = (
|
query = (
|
||||||
|
@ -1112,18 +1106,18 @@ class TVShows(Items):
|
||||||
|
|
||||||
# Process cast
|
# Process cast
|
||||||
people = API.getPeopleList()
|
people = API.getPeopleList()
|
||||||
kodi_db.addPeople(showid, people, "tvshow")
|
self.kodi_db.addPeople(showid, people, "tvshow")
|
||||||
# Process genres
|
# Process genres
|
||||||
kodi_db.addGenres(showid, genres, "tvshow")
|
self.kodi_db.addGenres(showid, genres, "tvshow")
|
||||||
# Process artwork
|
# Process artwork
|
||||||
allartworks = API.getAllArtwork()
|
allartworks = API.getAllArtwork()
|
||||||
artwork.addArtwork(allartworks, showid, "tvshow", kodicursor)
|
artwork.addArtwork(allartworks, showid, "tvshow", kodicursor)
|
||||||
# Process studios
|
# Process studios
|
||||||
kodi_db.addStudios(showid, studios, "tvshow")
|
self.kodi_db.addStudios(showid, studios, "tvshow")
|
||||||
# Process tags: view, PMS collection tags
|
# Process tags: view, PMS collection tags
|
||||||
tags = [viewtag]
|
tags = [viewtag]
|
||||||
tags.extend(collections)
|
tags.extend(collections)
|
||||||
kodi_db.addTags(showid, tags, "tvshow")
|
self.kodi_db.addTags(showid, tags, "tvshow")
|
||||||
|
|
||||||
if force_episodes:
|
if force_episodes:
|
||||||
# We needed to recreate the show entry. Re-add episodes now.
|
# We needed to recreate the show entry. Re-add episodes now.
|
||||||
|
@ -1154,7 +1148,6 @@ class TVShows(Items):
|
||||||
return
|
return
|
||||||
kodicursor = self.kodicursor
|
kodicursor = self.kodicursor
|
||||||
emby_db = self.emby_db
|
emby_db = self.emby_db
|
||||||
kodi_db = self.kodi_db
|
|
||||||
artwork = self.artwork
|
artwork = self.artwork
|
||||||
seasonnum = API.getIndex()
|
seasonnum = API.getIndex()
|
||||||
# Get parent tv show Plex id
|
# Get parent tv show Plex id
|
||||||
|
@ -1210,10 +1203,8 @@ class TVShows(Items):
|
||||||
viewtag and viewid are irrelevant!
|
viewtag and viewid are irrelevant!
|
||||||
"""
|
"""
|
||||||
# Process single episode
|
# Process single episode
|
||||||
kodiversion = self.kodiversion
|
|
||||||
kodicursor = self.kodicursor
|
kodicursor = self.kodicursor
|
||||||
emby_db = self.emby_db
|
emby_db = self.emby_db
|
||||||
kodi_db = self.kodi_db
|
|
||||||
artwork = self.artwork
|
artwork = self.artwork
|
||||||
API = PlexAPI.API(item)
|
API = PlexAPI.API(item)
|
||||||
|
|
||||||
|
@ -1310,7 +1301,7 @@ class TVShows(Items):
|
||||||
# self.logMsg("Skipping: %s. Unable to add series: %s." % (itemid, seriesId), -1)
|
# self.logMsg("Skipping: %s. Unable to add series: %s." % (itemid, seriesId), -1)
|
||||||
self.logMsg("Parent tvshow now found, skip item", 2)
|
self.logMsg("Parent tvshow now found, skip item", 2)
|
||||||
return False
|
return False
|
||||||
seasonid = kodi_db.addSeason(showid, season)
|
seasonid = self.kodi_db.addSeason(showid, season)
|
||||||
|
|
||||||
# GET THE FILE AND PATH #####
|
# GET THE FILE AND PATH #####
|
||||||
doIndirect = not self.directpath
|
doIndirect = not self.directpath
|
||||||
|
@ -1368,7 +1359,7 @@ class TVShows(Items):
|
||||||
self.logMsg("UPDATE episode itemid: %s" % (itemid), 1)
|
self.logMsg("UPDATE episode itemid: %s" % (itemid), 1)
|
||||||
|
|
||||||
# Update the movie entry
|
# Update the movie entry
|
||||||
if kodiversion in (16, 17):
|
if self.kodiversion in (16, 17):
|
||||||
# Kodi Jarvis, Krypton
|
# Kodi Jarvis, Krypton
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
|
@ -1400,10 +1391,9 @@ class TVShows(Items):
|
||||||
|
|
||||||
##### OR ADD THE EPISODE #####
|
##### OR ADD THE EPISODE #####
|
||||||
else:
|
else:
|
||||||
self.logMsg("ADD episode itemid: %s" % (itemid), 1)
|
self.logMsg("ADD episode itemid: %s - Title: %s" % (itemid, title), 1)
|
||||||
|
|
||||||
# Create the episode entry
|
# Create the episode entry
|
||||||
if kodiversion in (16, 17):
|
if self.kodiversion in (16, 17):
|
||||||
# Kodi Jarvis, Krypton
|
# Kodi Jarvis, Krypton
|
||||||
query = (
|
query = (
|
||||||
'''
|
'''
|
||||||
|
@ -1454,7 +1444,7 @@ class TVShows(Items):
|
||||||
kodicursor.execute(query, (pathid, filename, dateadded, fileid))
|
kodicursor.execute(query, (pathid, filename, dateadded, fileid))
|
||||||
# Process cast
|
# Process cast
|
||||||
people = API.getPeopleList()
|
people = API.getPeopleList()
|
||||||
kodi_db.addPeople(episodeid, people, "episode")
|
self.kodi_db.addPeople(episodeid, people, "episode")
|
||||||
# Process artwork
|
# Process artwork
|
||||||
# Wide "screenshot" of particular episode
|
# Wide "screenshot" of particular episode
|
||||||
poster = item.attrib.get('thumb')
|
poster = item.attrib.get('thumb')
|
||||||
|
@ -1473,13 +1463,13 @@ class TVShows(Items):
|
||||||
|
|
||||||
# Process stream details
|
# Process stream details
|
||||||
streams = API.getMediaStreams()
|
streams = API.getMediaStreams()
|
||||||
kodi_db.addStreams(fileid, streams, runtime)
|
self.kodi_db.addStreams(fileid, streams, runtime)
|
||||||
# Process playstates
|
# Process playstates
|
||||||
kodi_db.addPlaystate(fileid, resume, runtime, playcount, dateplayed)
|
self.kodi_db.addPlaystate(fileid, resume, runtime, playcount, dateplayed)
|
||||||
if not self.directpath and resume:
|
if not self.directpath and resume:
|
||||||
# Create additional entry for widgets. This is only required for plugin/episode.
|
# Create additional entry for widgets. This is only required for plugin/episode.
|
||||||
temppathid = kodi_db.getPath("plugin://plugin.video.plexkodiconnect.tvshows/")
|
temppathid = self.kodi_db.getPath("plugin://plugin.video.plexkodiconnect.tvshows/")
|
||||||
tempfileid = kodi_db.addFile(filename, temppathid)
|
tempfileid = self.kodi_db.addFile(filename, temppathid)
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
"UPDATE files",
|
"UPDATE files",
|
||||||
|
@ -1487,7 +1477,7 @@ class TVShows(Items):
|
||||||
"WHERE idFile = ?"
|
"WHERE idFile = ?"
|
||||||
))
|
))
|
||||||
kodicursor.execute(query, (temppathid, filename, dateadded, tempfileid))
|
kodicursor.execute(query, (temppathid, filename, dateadded, tempfileid))
|
||||||
kodi_db.addPlaystate(tempfileid, resume, runtime, playcount, dateplayed)
|
self.kodi_db.addPlaystate(tempfileid, resume, runtime, playcount, dateplayed)
|
||||||
self.kodiconn.commit()
|
self.kodiconn.commit()
|
||||||
self.embyconn.commit()
|
self.embyconn.commit()
|
||||||
|
|
||||||
|
@ -1600,27 +1590,23 @@ class TVShows(Items):
|
||||||
def removeShow(self, kodiid):
|
def removeShow(self, kodiid):
|
||||||
|
|
||||||
kodicursor = self.kodicursor
|
kodicursor = self.kodicursor
|
||||||
artwork = self.artwork
|
self.artwork.deleteArtwork(kodiid, "tvshow", kodicursor)
|
||||||
|
|
||||||
artwork.deleteArtwork(kodiid, "tvshow", kodicursor)
|
|
||||||
kodicursor.execute("DELETE FROM tvshow WHERE idShow = ?", (kodiid,))
|
kodicursor.execute("DELETE FROM tvshow WHERE idShow = ?", (kodiid,))
|
||||||
self.logMsg("Removed tvshow: %s." % kodiid, 2)
|
self.logMsg("Removed tvshow: %s." % kodiid, 2)
|
||||||
|
|
||||||
def removeSeason(self, kodiid):
|
def removeSeason(self, kodiid):
|
||||||
|
|
||||||
kodicursor = self.kodicursor
|
kodicursor = self.kodicursor
|
||||||
artwork = self.artwork
|
|
||||||
|
|
||||||
artwork.deleteArtwork(kodiid, "season", kodicursor)
|
self.artwork.deleteArtwork(kodiid, "season", kodicursor)
|
||||||
kodicursor.execute("DELETE FROM seasons WHERE idSeason = ?", (kodiid,))
|
kodicursor.execute("DELETE FROM seasons WHERE idSeason = ?", (kodiid,))
|
||||||
self.logMsg("Removed season: %s." % kodiid, 2)
|
self.logMsg("Removed season: %s." % kodiid, 2)
|
||||||
|
|
||||||
def removeEpisode(self, kodiid, fileid):
|
def removeEpisode(self, kodiid, fileid):
|
||||||
|
|
||||||
kodicursor = self.kodicursor
|
kodicursor = self.kodicursor
|
||||||
artwork = self.artwork
|
|
||||||
|
|
||||||
artwork.deleteArtwork(kodiid, "episode", kodicursor)
|
self.artwork.deleteArtwork(kodiid, "episode", kodicursor)
|
||||||
kodicursor.execute("DELETE FROM episode WHERE idEpisode = ?", (kodiid,))
|
kodicursor.execute("DELETE FROM episode WHERE idEpisode = ?", (kodiid,))
|
||||||
kodicursor.execute("DELETE FROM files WHERE idFile = ?", (fileid,))
|
kodicursor.execute("DELETE FROM files WHERE idFile = ?", (fileid,))
|
||||||
self.logMsg("Removed episode: %s." % kodiid, 2)
|
self.logMsg("Removed episode: %s." % kodiid, 2)
|
||||||
|
@ -1656,10 +1642,9 @@ class Music(Items):
|
||||||
count = 0
|
count = 0
|
||||||
for artist in items:
|
for artist in items:
|
||||||
|
|
||||||
title = artist['Name']
|
|
||||||
if pdialog:
|
if pdialog:
|
||||||
percentage = int((float(count) / float(total))*100)
|
percentage = int((float(count) / float(total))*100)
|
||||||
pdialog.update(percentage, message=title)
|
pdialog.update(percentage, message=artist['Name'])
|
||||||
count += 1
|
count += 1
|
||||||
self.add_updateArtist(artist)
|
self.add_updateArtist(artist)
|
||||||
# Add albums
|
# Add albums
|
||||||
|
@ -1672,10 +1657,9 @@ class Music(Items):
|
||||||
count = 0
|
count = 0
|
||||||
for album in items:
|
for album in items:
|
||||||
|
|
||||||
title = album['Name']
|
|
||||||
if pdialog:
|
if pdialog:
|
||||||
percentage = int((float(count) / float(total))*100)
|
percentage = int((float(count) / float(total))*100)
|
||||||
pdialog.update(percentage, message=title)
|
pdialog.update(percentage, message=album['Name'])
|
||||||
count += 1
|
count += 1
|
||||||
self.add_updateAlbum(album)
|
self.add_updateAlbum(album)
|
||||||
# Add songs
|
# Add songs
|
||||||
|
@ -1688,14 +1672,13 @@ class Music(Items):
|
||||||
count = 0
|
count = 0
|
||||||
for song in items:
|
for song in items:
|
||||||
|
|
||||||
title = song['Name']
|
|
||||||
if pdialog:
|
if pdialog:
|
||||||
percentage = int((float(count) / float(total))*100)
|
percentage = int((float(count) / float(total))*100)
|
||||||
pdialog.update(percentage, message=title)
|
pdialog.update(percentage, message=song['Name'])
|
||||||
count += 1
|
count += 1
|
||||||
self.add_updateSong(song)
|
self.add_updateSong(song)
|
||||||
if not pdialog and self.contentmsg:
|
if not pdialog and self.contentmsg:
|
||||||
self.contentPop(title, self.newmusic_time)
|
self.contentPop(song['Name'], self.newmusic_time)
|
||||||
|
|
||||||
def add_updateArtist(self, item, viewtag=None, viewid=None, artisttype="MusicArtist"):
|
def add_updateArtist(self, item, viewtag=None, viewid=None, artisttype="MusicArtist"):
|
||||||
try:
|
try:
|
||||||
|
@ -1715,7 +1698,6 @@ class Music(Items):
|
||||||
artisttype="MusicArtist"):
|
artisttype="MusicArtist"):
|
||||||
kodicursor = self.kodicursor
|
kodicursor = self.kodicursor
|
||||||
emby_db = self.emby_db
|
emby_db = self.emby_db
|
||||||
kodi_db = self.kodi_db
|
|
||||||
artwork = self.artwork
|
artwork = self.artwork
|
||||||
API = PlexAPI.API(item)
|
API = PlexAPI.API(item)
|
||||||
|
|
||||||
|
@ -1764,7 +1746,7 @@ class Music(Items):
|
||||||
# multiple times.
|
# multiple times.
|
||||||
# Kodi doesn't allow that. In case that happens we just merge the
|
# Kodi doesn't allow that. In case that happens we just merge the
|
||||||
# artist entries.
|
# artist entries.
|
||||||
artistid = kodi_db.addArtist(name, musicBrainzId)
|
artistid = self.kodi_db.addArtist(name, musicBrainzId)
|
||||||
# Create the reference in emby table
|
# Create the reference in emby table
|
||||||
emby_db.addReference(
|
emby_db.addReference(
|
||||||
itemid, artistid, artisttype, "artist", checksum=checksum)
|
itemid, artistid, artisttype, "artist", checksum=checksum)
|
||||||
|
@ -1811,10 +1793,8 @@ class Music(Items):
|
||||||
return
|
return
|
||||||
|
|
||||||
def run_add_updateAlbum(self, item, viewtag=None, viewid=None):
|
def run_add_updateAlbum(self, item, viewtag=None, viewid=None):
|
||||||
kodiversion = self.kodiversion
|
|
||||||
kodicursor = self.kodicursor
|
kodicursor = self.kodicursor
|
||||||
emby_db = self.emby_db
|
emby_db = self.emby_db
|
||||||
kodi_db = self.kodi_db
|
|
||||||
artwork = self.artwork
|
artwork = self.artwork
|
||||||
API = PlexAPI.API(item)
|
API = PlexAPI.API(item)
|
||||||
|
|
||||||
|
@ -1875,13 +1855,13 @@ class Music(Items):
|
||||||
# multiple times.
|
# multiple times.
|
||||||
# Kodi doesn't allow that. In case that happens we just merge the
|
# Kodi doesn't allow that. In case that happens we just merge the
|
||||||
# artist entries.
|
# artist entries.
|
||||||
albumid = kodi_db.addAlbum(name, musicBrainzId)
|
albumid = self.kodi_db.addAlbum(name, musicBrainzId)
|
||||||
# Create the reference in emby table
|
# Create the reference in emby table
|
||||||
emby_db.addReference(
|
emby_db.addReference(
|
||||||
itemid, albumid, "MusicAlbum", "album", checksum=checksum)
|
itemid, albumid, "MusicAlbum", "album", checksum=checksum)
|
||||||
|
|
||||||
# Process the album info
|
# Process the album info
|
||||||
if kodiversion == 17:
|
if self.kodiversion == 17:
|
||||||
# Kodi Krypton
|
# Kodi Krypton
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
|
@ -1894,7 +1874,7 @@ class Music(Items):
|
||||||
kodicursor.execute(query, (artistname, year, genre, bio, thumb,
|
kodicursor.execute(query, (artistname, year, genre, bio, thumb,
|
||||||
rating, lastScraped, "album", studio,
|
rating, lastScraped, "album", studio,
|
||||||
albumid))
|
albumid))
|
||||||
elif kodiversion == 16:
|
elif self.kodiversion == 16:
|
||||||
# Kodi Jarvis
|
# Kodi Jarvis
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
|
@ -1907,7 +1887,7 @@ class Music(Items):
|
||||||
kodicursor.execute(query, (artistname, year, genre, bio, thumb,
|
kodicursor.execute(query, (artistname, year, genre, bio, thumb,
|
||||||
rating, lastScraped, "album", studio,
|
rating, lastScraped, "album", studio,
|
||||||
albumid))
|
albumid))
|
||||||
elif kodiversion == 15:
|
elif self.kodiversion == 15:
|
||||||
# Kodi Isengard
|
# Kodi Isengard
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
|
@ -1998,7 +1978,7 @@ class Music(Items):
|
||||||
# Update emby reference with parentid
|
# Update emby reference with parentid
|
||||||
emby_db.updateParentId(artistId, albumid)
|
emby_db.updateParentId(artistId, albumid)
|
||||||
# Add genres
|
# Add genres
|
||||||
kodi_db.addMusicGenres(albumid, genres, "album")
|
self.kodi_db.addMusicGenres(albumid, genres, "album")
|
||||||
# Update artwork
|
# Update artwork
|
||||||
artwork.addArtwork(artworks, albumid, "album", kodicursor)
|
artwork.addArtwork(artworks, albumid, "album", kodicursor)
|
||||||
self.embyconn.commit()
|
self.embyconn.commit()
|
||||||
|
@ -2020,11 +2000,9 @@ class Music(Items):
|
||||||
|
|
||||||
def run_add_updateSong(self, item, viewtag=None, viewid=None):
|
def run_add_updateSong(self, item, viewtag=None, viewid=None):
|
||||||
# Process single song
|
# Process single song
|
||||||
kodiversion = self.kodiversion
|
|
||||||
kodicursor = self.kodicursor
|
kodicursor = self.kodicursor
|
||||||
emby = self.emby
|
emby = self.emby
|
||||||
emby_db = self.emby_db
|
emby_db = self.emby_db
|
||||||
kodi_db = self.kodi_db
|
|
||||||
artwork = self.artwork
|
artwork = self.artwork
|
||||||
API = PlexAPI.API(item)
|
API = PlexAPI.API(item)
|
||||||
|
|
||||||
|
@ -2136,7 +2114,7 @@ class Music(Items):
|
||||||
self.logMsg("ADD song itemid: %s - Title: %s" % (itemid, title), 1)
|
self.logMsg("ADD song itemid: %s - Title: %s" % (itemid, title), 1)
|
||||||
|
|
||||||
# Add path
|
# Add path
|
||||||
pathid = kodi_db.addPath(path, strHash="123")
|
pathid = self.kodi_db.addPath(path, strHash="123")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Get the album
|
# Get the album
|
||||||
|
@ -2148,7 +2126,7 @@ class Music(Items):
|
||||||
album_name = item.get('parentTitle')
|
album_name = item.get('parentTitle')
|
||||||
if album_name:
|
if album_name:
|
||||||
self.logMsg("Creating virtual music album for song: %s." % itemid, 1)
|
self.logMsg("Creating virtual music album for song: %s." % itemid, 1)
|
||||||
albumid = kodi_db.addAlbum(album_name, API.getProvider('MusicBrainzAlbum'))
|
albumid = self.kodi_db.addAlbum(album_name, API.getProvider('MusicBrainzAlbum'))
|
||||||
emby_db.addReference("%salbum%s" % (itemid, albumid), albumid, "MusicAlbum_", "album")
|
emby_db.addReference("%salbum%s" % (itemid, albumid), albumid, "MusicAlbum_", "album")
|
||||||
else:
|
else:
|
||||||
# No album Id associated to the song.
|
# No album Id associated to the song.
|
||||||
|
@ -2173,7 +2151,7 @@ class Music(Items):
|
||||||
self.logMsg("Failed to add album. Creating singles.", 1)
|
self.logMsg("Failed to add album. Creating singles.", 1)
|
||||||
kodicursor.execute("select coalesce(max(idAlbum),0) from album")
|
kodicursor.execute("select coalesce(max(idAlbum),0) from album")
|
||||||
albumid = kodicursor.fetchone()[0] + 1
|
albumid = kodicursor.fetchone()[0] + 1
|
||||||
if kodiversion == 16:
|
if self.kodiversion == 16:
|
||||||
# Kodi Jarvis
|
# Kodi Jarvis
|
||||||
query = (
|
query = (
|
||||||
'''
|
'''
|
||||||
|
@ -2183,7 +2161,7 @@ class Music(Items):
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
kodicursor.execute(query, (albumid, genre, year, "single"))
|
kodicursor.execute(query, (albumid, genre, year, "single"))
|
||||||
elif kodiversion == 15:
|
elif self.kodiversion == 15:
|
||||||
# Kodi Isengard
|
# Kodi Isengard
|
||||||
query = (
|
query = (
|
||||||
'''
|
'''
|
||||||
|
@ -2316,11 +2294,11 @@ class Music(Items):
|
||||||
result = kodicursor.fetchone()
|
result = kodicursor.fetchone()
|
||||||
if result and result[0] != album_artists:
|
if result and result[0] != album_artists:
|
||||||
# Field is empty
|
# Field is empty
|
||||||
if kodiversion in (16, 17):
|
if self.kodiversion in (16, 17):
|
||||||
# Kodi Jarvis, Krypton
|
# Kodi Jarvis, Krypton
|
||||||
query = "UPDATE album SET strArtists = ? WHERE idAlbum = ?"
|
query = "UPDATE album SET strArtists = ? WHERE idAlbum = ?"
|
||||||
kodicursor.execute(query, (album_artists, albumid))
|
kodicursor.execute(query, (album_artists, albumid))
|
||||||
elif kodiversion == 15:
|
elif self.kodiversion == 15:
|
||||||
# Kodi Isengard
|
# Kodi Isengard
|
||||||
query = "UPDATE album SET strArtists = ? WHERE idAlbum = ?"
|
query = "UPDATE album SET strArtists = ? WHERE idAlbum = ?"
|
||||||
kodicursor.execute(query, (album_artists, albumid))
|
kodicursor.execute(query, (album_artists, albumid))
|
||||||
|
@ -2330,7 +2308,7 @@ class Music(Items):
|
||||||
kodicursor.execute(query, (album_artists, albumid))
|
kodicursor.execute(query, (album_artists, albumid))
|
||||||
|
|
||||||
# Add genres
|
# Add genres
|
||||||
kodi_db.addMusicGenres(songid, genres, "song")
|
self.kodi_db.addMusicGenres(songid, genres, "song")
|
||||||
|
|
||||||
# Update artwork
|
# Update artwork
|
||||||
allart = API.getAllArtwork(parentInfo=True)
|
allart = API.getAllArtwork(parentInfo=True)
|
||||||
|
@ -2372,10 +2350,9 @@ class Music(Items):
|
||||||
self.removeSong(kodiid)
|
self.removeSong(kodiid)
|
||||||
# This should only address single song scenario, where server doesn't actually
|
# This should only address single song scenario, where server doesn't actually
|
||||||
# create an album for the song.
|
# create an album for the song.
|
||||||
customitems = emby_db.getItem_byWildId(itemid)
|
|
||||||
emby_db.removeWildItem(itemid)
|
emby_db.removeWildItem(itemid)
|
||||||
|
|
||||||
for item in customitems:
|
for item in emby_db.getItem_byWildId(itemid):
|
||||||
|
|
||||||
item_kid = item[0]
|
item_kid = item[0]
|
||||||
item_mediatype = item[1]
|
item_mediatype = item[1]
|
||||||
|
@ -2431,23 +2408,16 @@ class Music(Items):
|
||||||
def removeSong(self, kodiid):
|
def removeSong(self, kodiid):
|
||||||
|
|
||||||
kodicursor = self.kodicursor
|
kodicursor = self.kodicursor
|
||||||
artwork = self.artwork
|
|
||||||
|
|
||||||
artwork.deleteArtwork(kodiid, "song", kodicursor)
|
self.artwork.deleteArtwork(kodiid, "song", self.kodicursor)
|
||||||
kodicursor.execute("DELETE FROM song WHERE idSong = ?", (kodiid,))
|
self.kodicursor.execute("DELETE FROM song WHERE idSong = ?", (kodiid,))
|
||||||
|
|
||||||
def removeAlbum(self, kodiid):
|
def removeAlbum(self, kodiid):
|
||||||
|
|
||||||
kodicursor = self.kodicursor
|
self.artwork.deleteArtwork(kodiid, "album", self.kodicursor)
|
||||||
artwork = self.artwork
|
self.kodicursor.execute("DELETE FROM album WHERE idAlbum = ?", (kodiid,))
|
||||||
|
|
||||||
artwork.deleteArtwork(kodiid, "album", kodicursor)
|
|
||||||
kodicursor.execute("DELETE FROM album WHERE idAlbum = ?", (kodiid,))
|
|
||||||
|
|
||||||
def removeArtist(self, kodiid):
|
def removeArtist(self, kodiid):
|
||||||
|
|
||||||
kodicursor = self.kodicursor
|
self.artwork.deleteArtwork(kodiid, "artist", self.kodicursor)
|
||||||
artwork = self.artwork
|
self.kodicursor.execute("DELETE FROM artist WHERE idArtist = ?", (kodiid,))
|
||||||
|
|
||||||
artwork.deleteArtwork(kodiid, "artist", kodicursor)
|
|
||||||
kodicursor.execute("DELETE FROM artist WHERE idArtist = ?", (kodiid,))
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -82,13 +82,13 @@ class KodiMonitor(xbmc.Monitor):
|
||||||
item = data.get('item')
|
item = data.get('item')
|
||||||
try:
|
try:
|
||||||
kodiid = item['id']
|
kodiid = item['id']
|
||||||
type = item['type']
|
item_type = item['type']
|
||||||
except (KeyError, TypeError):
|
except (KeyError, TypeError):
|
||||||
self.logMsg("Item is invalid for playstate update.", 1)
|
self.logMsg("Item is invalid for playstate update.", 1)
|
||||||
else:
|
else:
|
||||||
# Send notification to the server.
|
# Send notification to the server.
|
||||||
with embydb.GetEmbyDB() as emby_db:
|
with embydb.GetEmbyDB() as emby_db:
|
||||||
emby_dbitem = emby_db.getItem_byKodiId(kodiid, type)
|
emby_dbitem = emby_db.getItem_byKodiId(kodiid, item_type)
|
||||||
try:
|
try:
|
||||||
itemid = emby_dbitem[0]
|
itemid = emby_dbitem[0]
|
||||||
except TypeError:
|
except TypeError:
|
||||||
|
@ -137,7 +137,7 @@ class KodiMonitor(xbmc.Monitor):
|
||||||
|
|
||||||
url = "{server}/emby/Items/%s?format=json" % itemid
|
url = "{server}/emby/Items/%s?format=json" % itemid
|
||||||
self.logMsg("Deleting request: %s" % itemid)
|
self.logMsg("Deleting request: %s" % itemid)
|
||||||
doUtils.downloadUrl(url, type="DELETE")
|
doUtils.downloadUrl(url, action_type="DELETE")
|
||||||
finally:
|
finally:
|
||||||
embycursor.close()'''
|
embycursor.close()'''
|
||||||
|
|
||||||
|
|
|
@ -193,6 +193,7 @@ def getSongTags(file):
|
||||||
if pic.type == 3 and pic.data:
|
if pic.type == 3 and pic.data:
|
||||||
#the file has an embedded cover
|
#the file has an embedded cover
|
||||||
hasEmbeddedCover = True
|
hasEmbeddedCover = True
|
||||||
|
break
|
||||||
if audio.get("rating"):
|
if audio.get("rating"):
|
||||||
rating = float(audio.get("rating")[0])
|
rating = float(audio.get("rating")[0])
|
||||||
#flac rating is 0-100 and needs to be converted to 0-5 range
|
#flac rating is 0-100 and needs to be converted to 0-5 range
|
||||||
|
|
|
@ -44,7 +44,6 @@ class PlaybackUtils():
|
||||||
|
|
||||||
def play(self, itemid, dbid=None):
|
def play(self, itemid, dbid=None):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
window = utils.window
|
window = utils.window
|
||||||
settings = utils.settings
|
settings = utils.settings
|
||||||
|
|
||||||
|
@ -56,7 +55,7 @@ class PlaybackUtils():
|
||||||
listitem = xbmcgui.ListItem()
|
listitem = xbmcgui.ListItem()
|
||||||
playutils = putils.PlayUtils(item[0])
|
playutils = putils.PlayUtils(item[0])
|
||||||
|
|
||||||
log("Play called.", 1)
|
self.logMsg("Play called.", 1)
|
||||||
playurl = playutils.getPlayUrl()
|
playurl = playutils.getPlayUrl()
|
||||||
if not playurl:
|
if not playurl:
|
||||||
return xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, listitem)
|
return xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, listitem)
|
||||||
|
@ -101,9 +100,9 @@ class PlaybackUtils():
|
||||||
introsPlaylist = False
|
introsPlaylist = False
|
||||||
dummyPlaylist = False
|
dummyPlaylist = False
|
||||||
|
|
||||||
log("Playlist start position: %s" % startPos, 1)
|
self.logMsg("Playlist start position: %s" % startPos, 2)
|
||||||
log("Playlist plugin position: %s" % self.currentPosition, 1)
|
self.logMsg("Playlist plugin position: %s" % currentPosition, 2)
|
||||||
log("Playlist size: %s" % sizePlaylist, 1)
|
self.logMsg("Playlist size: %s" % sizePlaylist, 2)
|
||||||
|
|
||||||
############### RESUME POINT ################
|
############### RESUME POINT ################
|
||||||
|
|
||||||
|
@ -114,11 +113,11 @@ class PlaybackUtils():
|
||||||
if not propertiesPlayback:
|
if not propertiesPlayback:
|
||||||
|
|
||||||
window('emby_playbackProps', value="true")
|
window('emby_playbackProps', value="true")
|
||||||
log("Setting up properties in playlist.", 1)
|
self.logMsg("Setting up properties in playlist.", 1)
|
||||||
|
|
||||||
if (not homeScreen and not seektime and
|
if (not homeScreen and not seektime and
|
||||||
window('emby_customPlaylist') != "true"):
|
window('emby_customPlaylist') != "true"):
|
||||||
log("Adding dummy file to playlist.", 2)
|
self.logMsg("Adding dummy file to playlist.", 2)
|
||||||
dummyPlaylist = True
|
dummyPlaylist = True
|
||||||
playlist.add(playurl, listitem, index=startPos)
|
playlist.add(playurl, listitem, index=startPos)
|
||||||
# Remove the original item from playlist
|
# Remove the original item from playlist
|
||||||
|
@ -181,13 +180,13 @@ class PlaybackUtils():
|
||||||
if dummyPlaylist:
|
if dummyPlaylist:
|
||||||
# Added a dummy file to the playlist,
|
# Added a dummy file to the playlist,
|
||||||
# because the first item is going to fail automatically.
|
# because the first item is going to fail automatically.
|
||||||
log("Processed as a playlist. First item is skipped.", 1)
|
self.logMsg("Processed as a playlist. First item is skipped.", 1)
|
||||||
return xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, listitem)
|
return xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, listitem)
|
||||||
|
|
||||||
|
|
||||||
# We just skipped adding properties. Reset flag for next time.
|
# We just skipped adding properties. Reset flag for next time.
|
||||||
elif propertiesPlayback:
|
elif propertiesPlayback:
|
||||||
log("Resetting properties playback flag.", 2)
|
self.logMsg("Resetting properties playback flag.", 2)
|
||||||
window('emby_playbackProps', clear=True)
|
window('emby_playbackProps', clear=True)
|
||||||
|
|
||||||
#self.pl.verifyPlaylist()
|
#self.pl.verifyPlaylist()
|
||||||
|
@ -206,18 +205,18 @@ class PlaybackUtils():
|
||||||
############### PLAYBACK ################
|
############### PLAYBACK ################
|
||||||
|
|
||||||
if homeScreen and seektime and window('emby_customPlaylist') != "true":
|
if homeScreen and seektime and window('emby_customPlaylist') != "true":
|
||||||
log("Play as a widget item.", 1)
|
self.logMsg("Play as a widget item.", 1)
|
||||||
API.CreateListItemFromPlexItem(listitem)
|
API.CreateListItemFromPlexItem(listitem)
|
||||||
xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem)
|
xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem)
|
||||||
|
|
||||||
elif ((introsPlaylist and window('emby_customPlaylist') == "true") or
|
elif ((introsPlaylist and window('emby_customPlaylist') == "true") or
|
||||||
(homeScreen and not sizePlaylist)):
|
(homeScreen and not sizePlaylist)):
|
||||||
# Playlist was created just now, play it.
|
# Playlist was created just now, play it.
|
||||||
log("Play playlist.", 1)
|
self.logMsg("Play playlist.", 1)
|
||||||
xbmc.Player().play(playlist, startpos=startPos)
|
xbmc.Player().play(playlist, startpos=startPos)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
log("Play as a regular item.", 1)
|
self.logMsg("Play as a regular item.", 1)
|
||||||
xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem)
|
xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem)
|
||||||
|
|
||||||
def AddTrailers(self, xml):
|
def AddTrailers(self, xml):
|
||||||
|
|
|
@ -51,15 +51,13 @@ class Player(xbmc.Player):
|
||||||
"""
|
"""
|
||||||
Window values need to have been set in Kodimonitor.py
|
Window values need to have been set in Kodimonitor.py
|
||||||
"""
|
"""
|
||||||
log = self.logMsg
|
|
||||||
window = utils.window
|
window = utils.window
|
||||||
# Will be called when xbmc starts playing a file
|
# Will be called when xbmc starts playing a file
|
||||||
xbmcplayer = self.xbmcplayer
|
|
||||||
self.stopAll()
|
self.stopAll()
|
||||||
|
|
||||||
# Get current file (in utf-8!)
|
# Get current file (in utf-8!)
|
||||||
try:
|
try:
|
||||||
currentFile = xbmcplayer.getPlayingFile()
|
currentFile = self.xbmcplayer.getPlayingFile()
|
||||||
xbmc.sleep(300)
|
xbmc.sleep(300)
|
||||||
except:
|
except:
|
||||||
currentFile = ""
|
currentFile = ""
|
||||||
|
@ -67,11 +65,11 @@ class Player(xbmc.Player):
|
||||||
while not currentFile:
|
while not currentFile:
|
||||||
xbmc.sleep(100)
|
xbmc.sleep(100)
|
||||||
try:
|
try:
|
||||||
currentFile = xbmcplayer.getPlayingFile()
|
currentFile = self.xbmcplayer.getPlayingFile()
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
if count == 20:
|
if count == 20:
|
||||||
log("Cancelling playback report...", 1)
|
self.logMsg("Cancelling playback report...", 1)
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
count += 1
|
count += 1
|
||||||
|
@ -220,6 +218,8 @@ class Player(xbmc.Player):
|
||||||
except ValueError:
|
except ValueError:
|
||||||
runtime = xbmcplayer.getTotalTime()
|
runtime = xbmcplayer.getTotalTime()
|
||||||
log("Runtime is missing, Kodi runtime: %s" % runtime, 1)
|
log("Runtime is missing, Kodi runtime: %s" % runtime, 1)
|
||||||
|
runtime = self.xbmcplayer.getTotalTime()
|
||||||
|
self.logMsg("Runtime is missing, Kodi runtime: %s" % runtime, 1)
|
||||||
|
|
||||||
playQueueVersion = window('playQueueVersion')
|
playQueueVersion = window('playQueueVersion')
|
||||||
playQueueID = window('playQueueID')
|
playQueueID = window('playQueueID')
|
||||||
|
@ -263,7 +263,7 @@ class Player(xbmc.Player):
|
||||||
if not self.doNotify:
|
if not self.doNotify:
|
||||||
return
|
return
|
||||||
|
|
||||||
log = self.logMsg
|
self.logMsg("reportPlayback Called", 2)
|
||||||
|
|
||||||
log("reportPlayback Called", 2)
|
log("reportPlayback Called", 2)
|
||||||
|
|
||||||
|
@ -382,7 +382,7 @@ class Player(xbmc.Player):
|
||||||
|
|
||||||
if mapping: # Set in PlaybackUtils.py
|
if mapping: # Set in PlaybackUtils.py
|
||||||
|
|
||||||
log("Mapping for external subtitles index: %s" % mapping, 2)
|
self.logMsg("Mapping for external subtitles index: %s" % mapping, 2)
|
||||||
externalIndex = json.loads(mapping)
|
externalIndex = json.loads(mapping)
|
||||||
|
|
||||||
if externalIndex.get(str(indexSubs)):
|
if externalIndex.get(str(indexSubs)):
|
||||||
|
@ -404,7 +404,7 @@ class Player(xbmc.Player):
|
||||||
# postdata = json.dumps(postdata)
|
# postdata = json.dumps(postdata)
|
||||||
# self.ws.sendProgressUpdate(postdata)
|
# self.ws.sendProgressUpdate(postdata)
|
||||||
self.doUtils(
|
self.doUtils(
|
||||||
"{server}/:/timeline?" + urlencode(postdata), type="GET")
|
"{server}/:/timeline?" + urlencode(postdata), action_type="GET")
|
||||||
|
|
||||||
def onPlayBackPaused(self):
|
def onPlayBackPaused(self):
|
||||||
|
|
||||||
|
@ -440,7 +440,6 @@ class Player(xbmc.Player):
|
||||||
def onPlayBackStopped(self):
|
def onPlayBackStopped(self):
|
||||||
# Will be called when user stops xbmc playing a file
|
# Will be called when user stops xbmc playing a file
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
window = utils.window
|
window = utils.window
|
||||||
log("ONPLAYBACK_STOPPED", 1)
|
log("ONPLAYBACK_STOPPED", 1)
|
||||||
|
|
||||||
|
@ -459,31 +458,28 @@ class Player(xbmc.Player):
|
||||||
|
|
||||||
def stopAll(self):
|
def stopAll(self):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
lang = utils.language
|
lang = utils.language
|
||||||
settings = utils.settings
|
settings = utils.settings
|
||||||
|
|
||||||
doUtils = self.doUtils
|
|
||||||
|
|
||||||
if not self.played_info:
|
if not self.played_info:
|
||||||
return
|
return
|
||||||
|
|
||||||
log("Played_information: %s" % self.played_info, 1)
|
self.logMsg("Played_information: %s" % self.played_info, 1)
|
||||||
# Process each items
|
# Process each items
|
||||||
for item in self.played_info:
|
for item in self.played_info:
|
||||||
|
|
||||||
data = self.played_info.get(item)
|
data = self.played_info.get(item)
|
||||||
if data:
|
if data:
|
||||||
|
|
||||||
log("Item path: %s" % item, 2)
|
self.logMsg("Item path: %s" % item, 2)
|
||||||
log("Item data: %s" % data, 2)
|
self.logMsg("Item data: %s" % data, 2)
|
||||||
|
|
||||||
runtime = data['runtime']
|
runtime = data['runtime']
|
||||||
currentPosition = data['currentPosition']
|
currentPosition = data['currentPosition']
|
||||||
itemid = data['item_id']
|
itemid = data['item_id']
|
||||||
refresh_id = data['refresh_id']
|
refresh_id = data['refresh_id']
|
||||||
currentFile = data['currentfile']
|
currentFile = data['currentfile']
|
||||||
type = data['Type']
|
media_type = data['Type']
|
||||||
playMethod = data['playmethod']
|
playMethod = data['playmethod']
|
||||||
|
|
||||||
# Prevent manually mark as watched in Kodi monitor
|
# Prevent manually mark as watched in Kodi monitor
|
||||||
|
@ -497,15 +493,15 @@ class Player(xbmc.Player):
|
||||||
percentComplete = 0
|
percentComplete = 0
|
||||||
|
|
||||||
markPlayedAt = float(settings('markPlayed')) / 100
|
markPlayedAt = float(settings('markPlayed')) / 100
|
||||||
log("Percent complete: %s Mark played at: %s"
|
self.logMsg("Percent complete: %s Mark played at: %s"
|
||||||
% (percentComplete, markPlayedAt), 1)
|
% (percentComplete, markPlayedAt), 1)
|
||||||
|
|
||||||
# Send the delete action to the server.
|
# Send the delete action to the server.
|
||||||
offerDelete = False
|
offerDelete = False
|
||||||
|
|
||||||
if type == "Episode" and settings('deleteTV') == "true":
|
if media_type == "Episode" and settings('deleteTV') == "true":
|
||||||
offerDelete = True
|
offerDelete = True
|
||||||
elif type == "Movie" and settings('deleteMovies') == "true":
|
elif media_type == "Movie" and settings('deleteMovies') == "true":
|
||||||
offerDelete = True
|
offerDelete = True
|
||||||
|
|
||||||
if settings('offerDelete') != "true":
|
if settings('offerDelete') != "true":
|
||||||
|
@ -520,7 +516,7 @@ class Player(xbmc.Player):
|
||||||
lang(33015),
|
lang(33015),
|
||||||
autoclose=120000)
|
autoclose=120000)
|
||||||
if not resp:
|
if not resp:
|
||||||
log("User skipped deletion.", 1)
|
self.logMsg("User skipped deletion.", 1)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
url = "{server}/emby/Items/%s?format=json" % itemid
|
url = "{server}/emby/Items/%s?format=json" % itemid
|
||||||
|
@ -567,4 +563,4 @@ class Player(xbmc.Player):
|
||||||
'duration': int(duration)
|
'duration': int(duration)
|
||||||
}
|
}
|
||||||
url = url + urlencode(args)
|
url = url + urlencode(args)
|
||||||
self.doUtils(url, type="GET")
|
self.doUtils(url, action_type="GET")
|
||||||
|
|
|
@ -27,7 +27,6 @@ class Playlist():
|
||||||
self.emby = embyserver.Read_EmbyServer()
|
self.emby = embyserver.Read_EmbyServer()
|
||||||
|
|
||||||
def playAll(self, itemids, startat):
|
def playAll(self, itemids, startat):
|
||||||
log = self.logMsg
|
|
||||||
window = utils.window
|
window = utils.window
|
||||||
|
|
||||||
embyconn = utils.kodiSQL('emby')
|
embyconn = utils.kodiSQL('emby')
|
||||||
|
@ -38,8 +37,8 @@ class Playlist():
|
||||||
playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
|
playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
|
||||||
playlist.clear()
|
playlist.clear()
|
||||||
|
|
||||||
log("---*** PLAY ALL ***---", 1)
|
self.logMsg("---*** PLAY ALL ***---", 1)
|
||||||
log("Items: %s and start at: %s" % (itemids, startat), 1)
|
self.logMsg("Items: %s and start at: %s" % (itemids, startat), 1)
|
||||||
|
|
||||||
started = False
|
started = False
|
||||||
window('emby_customplaylist', value="true")
|
window('emby_customplaylist', value="true")
|
||||||
|
@ -76,14 +75,12 @@ class Playlist():
|
||||||
|
|
||||||
def modifyPlaylist(self, itemids):
|
def modifyPlaylist(self, itemids):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
|
|
||||||
embyconn = utils.kodiSQL('emby')
|
embyconn = utils.kodiSQL('emby')
|
||||||
embycursor = embyconn.cursor()
|
embycursor = embyconn.cursor()
|
||||||
emby_db = embydb.Embydb_Functions(embycursor)
|
emby_db = embydb.Embydb_Functions(embycursor)
|
||||||
|
|
||||||
log("---*** ADD TO PLAYLIST ***---", 1)
|
self.logMsg("---*** ADD TO PLAYLIST ***---", 1)
|
||||||
log("Items: %s" % itemids, 1)
|
self.logMsg("Items: %s" % itemids, 1)
|
||||||
|
|
||||||
# player = xbmc.Player()
|
# player = xbmc.Player()
|
||||||
playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
|
playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
|
||||||
|
@ -101,7 +98,7 @@ class Playlist():
|
||||||
# Add to playlist
|
# Add to playlist
|
||||||
self.addtoPlaylist(dbid, mediatype)
|
self.addtoPlaylist(dbid, mediatype)
|
||||||
|
|
||||||
log("Adding %s to playlist." % itemid, 1)
|
self.logMsg("Adding %s to playlist." % itemid, 1)
|
||||||
|
|
||||||
self.verifyPlaylist()
|
self.verifyPlaylist()
|
||||||
embycursor.close()
|
embycursor.close()
|
||||||
|
@ -124,8 +121,7 @@ class Playlist():
|
||||||
else:
|
else:
|
||||||
pl['params']['item'] = {'file': url}
|
pl['params']['item'] = {'file': url}
|
||||||
|
|
||||||
result = xbmc.executeJSONRPC(json.dumps(pl))
|
self.logMsg(xbmc.executeJSONRPC(json.dumps(pl)), 2)
|
||||||
self.logMsg(result, 2)
|
|
||||||
|
|
||||||
def addtoPlaylist_xbmc(self, playlist, item):
|
def addtoPlaylist_xbmc(self, playlist, item):
|
||||||
path = "plugin://plugin.video.plexkodiconnect.movies/"
|
path = "plugin://plugin.video.plexkodiconnect.movies/"
|
||||||
|
@ -160,8 +156,7 @@ class Playlist():
|
||||||
else:
|
else:
|
||||||
pl['params']['item'] = {'file': url}
|
pl['params']['item'] = {'file': url}
|
||||||
|
|
||||||
result = xbmc.executeJSONRPC(json.dumps(pl))
|
self.logMsg(xbmc.executeJSONRPC(json.dumps(pl)), 2)
|
||||||
self.logMsg(result, 2)
|
|
||||||
|
|
||||||
def verifyPlaylist(self):
|
def verifyPlaylist(self):
|
||||||
|
|
||||||
|
@ -176,8 +171,7 @@ class Playlist():
|
||||||
'properties': ['title', 'file']
|
'properties': ['title', 'file']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result = xbmc.executeJSONRPC(json.dumps(pl))
|
self.logMsg(xbmc.executeJSONRPC(json.dumps(pl)), 2)
|
||||||
self.logMsg(result, 2)
|
|
||||||
|
|
||||||
def removefromPlaylist(self, position):
|
def removefromPlaylist(self, position):
|
||||||
|
|
||||||
|
@ -192,5 +186,4 @@ class Playlist():
|
||||||
'position': position
|
'position': position
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result = xbmc.executeJSONRPC(json.dumps(pl))
|
self.logMsg(xbmc.executeJSONRPC(json.dumps(pl)), 2)
|
||||||
self.logMsg(result, 2)
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ class PlayUtils():
|
||||||
utils.window('emby_%s.playmethod' % playurl, "DirectStream")
|
utils.window('emby_%s.playmethod' % playurl, "DirectStream")
|
||||||
|
|
||||||
elif self.isTranscoding():
|
elif self.isTranscoding():
|
||||||
log("File is transcoding.", 1)
|
self.logMsg("File is transcoding.", 1)
|
||||||
quality = {
|
quality = {
|
||||||
'maxVideoBitrate': self.getBitrate(),
|
'maxVideoBitrate': self.getBitrate(),
|
||||||
'videoResolution': self.getResolution(),
|
'videoResolution': self.getResolution(),
|
||||||
|
@ -73,16 +73,14 @@ class PlayUtils():
|
||||||
|
|
||||||
def httpPlay(self):
|
def httpPlay(self):
|
||||||
# Audio, Video, Photo
|
# Audio, Video, Photo
|
||||||
item = self.item
|
|
||||||
server = self.server
|
|
||||||
|
|
||||||
itemid = item['Id']
|
itemid = self.item['Id']
|
||||||
mediatype = item['MediaType']
|
mediatype = self.item['MediaType']
|
||||||
|
|
||||||
if mediatype == "Audio":
|
if mediatype == "Audio":
|
||||||
playurl = "%s/emby/Audio/%s/stream" % (server, itemid)
|
playurl = "%s/emby/Audio/%s/stream" % (self.server, itemid)
|
||||||
else:
|
else:
|
||||||
playurl = "%s/emby/Videos/%s/stream?static=true" % (server, itemid)
|
playurl = "%s/emby/Videos/%s/stream?static=true" % (self.server, itemid)
|
||||||
|
|
||||||
return playurl
|
return playurl
|
||||||
|
|
||||||
|
@ -117,20 +115,16 @@ class PlayUtils():
|
||||||
|
|
||||||
def directPlay(self):
|
def directPlay(self):
|
||||||
|
|
||||||
item = self.item
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
playurl = item['MediaSources'][0]['Path']
|
playurl = self.item['MediaSources'][0]['Path']
|
||||||
except (IndexError, KeyError):
|
except (IndexError, KeyError):
|
||||||
playurl = item['Path']
|
playurl = self.item['Path']
|
||||||
|
|
||||||
if item.get('VideoType'):
|
if self.item.get('VideoType'):
|
||||||
# Specific format modification
|
# Specific format modification
|
||||||
type = item['VideoType']
|
if self.item['VideoType'] == "Dvd":
|
||||||
|
|
||||||
if type == "Dvd":
|
|
||||||
playurl = "%s/VIDEO_TS/VIDEO_TS.IFO" % playurl
|
playurl = "%s/VIDEO_TS/VIDEO_TS.IFO" % playurl
|
||||||
elif type == "BluRay":
|
elif self.item['VideoType'] == "BluRay":
|
||||||
playurl = "%s/BDMV/index.bdmv" % playurl
|
playurl = "%s/BDMV/index.bdmv" % playurl
|
||||||
|
|
||||||
# Assign network protocol
|
# Assign network protocol
|
||||||
|
@ -146,26 +140,24 @@ class PlayUtils():
|
||||||
|
|
||||||
def fileExists(self):
|
def fileExists(self):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
|
|
||||||
if 'Path' not in self.item:
|
if 'Path' not in self.item:
|
||||||
# File has no path defined in server
|
# File has no path defined in server
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Convert path to direct play
|
# Convert path to direct play
|
||||||
path = self.directPlay()
|
path = self.directPlay()
|
||||||
log("Verifying path: %s" % path, 1)
|
self.logMsg("Verifying path: %s" % path, 1)
|
||||||
|
|
||||||
if xbmcvfs.exists(path):
|
if xbmcvfs.exists(path):
|
||||||
log("Path exists.", 1)
|
self.logMsg("Path exists.", 1)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
elif ":" not in path:
|
elif ":" not in path:
|
||||||
log("Can't verify path, assumed linux. Still try to direct play.", 1)
|
self.logMsg("Can't verify path, assumed linux. Still try to direct play.", 1)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
else:
|
else:
|
||||||
log("Failed to find file.", 1)
|
self.logMsg("Failed to find file.", 1)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def h265enabled(self):
|
def h265enabled(self):
|
||||||
|
@ -197,6 +189,8 @@ class PlayUtils():
|
||||||
if utils.settings('playType') == "2":
|
if utils.settings('playType') == "2":
|
||||||
# User forcing to play via HTTP
|
# User forcing to play via HTTP
|
||||||
self.logMsg("User chose to transcode", 1)
|
self.logMsg("User chose to transcode", 1)
|
||||||
|
self.logMsg("Resolution is: %sP, transcode for resolution: %sP+"
|
||||||
|
canDirectStream = self.item['MediaSources'][0]['SupportsDirectStream']
|
||||||
return False
|
return False
|
||||||
if self.h265enabled():
|
if self.h265enabled():
|
||||||
return False
|
return False
|
||||||
|
@ -244,26 +238,19 @@ class PlayUtils():
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def isTranscoding(self):
|
def isTranscoding(self):
|
||||||
# I hope Plex transcodes everything
|
|
||||||
return True
|
|
||||||
item = self.item
|
|
||||||
|
|
||||||
canTranscode = item['MediaSources'][0]['SupportsTranscoding']
|
|
||||||
# Make sure the server supports it
|
# Make sure the server supports it
|
||||||
if not canTranscode:
|
if not self.item['MediaSources'][0]['SupportsTranscoding']:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def transcoding(self):
|
def transcoding(self):
|
||||||
|
|
||||||
item = self.item
|
if 'Path' in self.item and self.item['Path'].endswith('.strm'):
|
||||||
|
|
||||||
if 'Path' in item and item['Path'].endswith('.strm'):
|
|
||||||
# Allow strm loading when transcoding
|
# Allow strm loading when transcoding
|
||||||
playurl = self.directPlay()
|
playurl = self.directPlay()
|
||||||
else:
|
else:
|
||||||
itemid = item['Id']
|
itemid = self.item['Id']
|
||||||
deviceId = self.clientInfo.getDeviceId()
|
deviceId = self.clientInfo.getDeviceId()
|
||||||
playurl = (
|
playurl = (
|
||||||
"%s/emby/Videos/%s/master.m3u8?MediaSourceId=%s"
|
"%s/emby/Videos/%s/master.m3u8?MediaSourceId=%s"
|
||||||
|
|
|
@ -31,8 +31,7 @@ class Read_EmbyServer():
|
||||||
# This will return the full item
|
# This will return the full item
|
||||||
item = {}
|
item = {}
|
||||||
|
|
||||||
url = "{server}/emby/Users/{UserId}/Items/%s?format=json" % itemid
|
result = self.doUtils("{server}/emby/Users/{UserId}/Items/%s?format=json" % itemid)
|
||||||
result = self.doUtils(url)
|
|
||||||
if result:
|
if result:
|
||||||
item = result
|
item = result
|
||||||
|
|
||||||
|
@ -45,13 +44,12 @@ class Read_EmbyServer():
|
||||||
itemlists = self.split_list(itemlist, 50)
|
itemlists = self.split_list(itemlist, 50)
|
||||||
for itemlist in itemlists:
|
for itemlist in itemlists:
|
||||||
# Will return basic information
|
# Will return basic information
|
||||||
url = "{server}/emby/Users/{UserId}/Items?&format=json"
|
|
||||||
params = {
|
params = {
|
||||||
|
|
||||||
'Ids': ",".join(itemlist),
|
'Ids': ",".join(itemlist),
|
||||||
'Fields': "Etag"
|
'Fields': "Etag"
|
||||||
}
|
}
|
||||||
result = self.doUtils(url, parameters=params)
|
result = self.doUtils("{server}/emby/Users/{UserId}/Items?&format=json", parameters=params)
|
||||||
if result:
|
if result:
|
||||||
items.extend(result['Items'])
|
items.extend(result['Items'])
|
||||||
|
|
||||||
|
@ -64,7 +62,6 @@ class Read_EmbyServer():
|
||||||
itemlists = self.split_list(itemlist, 50)
|
itemlists = self.split_list(itemlist, 50)
|
||||||
for itemlist in itemlists:
|
for itemlist in itemlists:
|
||||||
|
|
||||||
url = "{server}/emby/Users/{UserId}/Items?format=json"
|
|
||||||
params = {
|
params = {
|
||||||
|
|
||||||
"Ids": ",".join(itemlist),
|
"Ids": ",".join(itemlist),
|
||||||
|
@ -75,10 +72,10 @@ class Read_EmbyServer():
|
||||||
"Metascore,AirTime,DateCreated,MediaStreams,People,Overview,"
|
"Metascore,AirTime,DateCreated,MediaStreams,People,Overview,"
|
||||||
"CriticRating,CriticRatingSummary,Etag,ShortOverview,ProductionLocations,"
|
"CriticRating,CriticRatingSummary,Etag,ShortOverview,ProductionLocations,"
|
||||||
"Tags,ProviderIds,ParentId,RemoteTrailers,SpecialEpisodeNumbers,"
|
"Tags,ProviderIds,ParentId,RemoteTrailers,SpecialEpisodeNumbers,"
|
||||||
"MediaSources"
|
"MediaSources,VoteCount"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
result = self.doUtils(url, parameters=params)
|
result = self.doUtils("{server}/emby/Users/{UserId}/Items?format=json", parameters=params)
|
||||||
if result:
|
if result:
|
||||||
items.extend(result['Items'])
|
items.extend(result['Items'])
|
||||||
|
|
||||||
|
@ -87,13 +84,10 @@ class Read_EmbyServer():
|
||||||
def getView_embyId(self, itemid):
|
def getView_embyId(self, itemid):
|
||||||
# Returns ancestors using embyId
|
# Returns ancestors using embyId
|
||||||
viewId = None
|
viewId = None
|
||||||
url = "{server}/emby/Items/%s/Ancestors?UserId={UserId}&format=json" % itemid
|
|
||||||
result = self.doUtils(url)
|
|
||||||
|
|
||||||
for view in result:
|
for view in self.doUtils("{server}/emby/Items/%s/Ancestors?UserId={UserId}&format=json" % itemid):
|
||||||
|
|
||||||
viewtype = view['Type']
|
if view['Type'] == "CollectionFolder":
|
||||||
if viewtype == "CollectionFolder":
|
|
||||||
# Found view
|
# Found view
|
||||||
viewId = view['Id']
|
viewId = view['Id']
|
||||||
|
|
||||||
|
@ -120,8 +114,6 @@ class Read_EmbyServer():
|
||||||
return [viewName, viewId, mediatype]
|
return [viewName, viewId, mediatype]
|
||||||
|
|
||||||
def getFilteredSection(self, parentid, itemtype=None, sortby="SortName", recursive=True, limit=None, sortorder="Ascending", filter=""):
|
def getFilteredSection(self, parentid, itemtype=None, sortby="SortName", recursive=True, limit=None, sortorder="Ascending", filter=""):
|
||||||
doUtils = self.doUtils
|
|
||||||
url = "{server}/emby/Users/{UserId}/Items?format=json"
|
|
||||||
params = {
|
params = {
|
||||||
|
|
||||||
'ParentId': parentid,
|
'ParentId': parentid,
|
||||||
|
@ -140,11 +132,9 @@ class Read_EmbyServer():
|
||||||
"CriticRating,CriticRatingSummary,Etag,ShortOverview,ProductionLocations,"
|
"CriticRating,CriticRatingSummary,Etag,ShortOverview,ProductionLocations,"
|
||||||
"Tags,ProviderIds,ParentId,RemoteTrailers,SpecialEpisodeNumbers")
|
"Tags,ProviderIds,ParentId,RemoteTrailers,SpecialEpisodeNumbers")
|
||||||
}
|
}
|
||||||
return doUtils(url, parameters=params)
|
return self.doUtils("{server}/emby/Users/{UserId}/Items?format=json", parameters=params)
|
||||||
|
|
||||||
def getTvChannels(self):
|
def getTvChannels(self):
|
||||||
doUtils = self.doUtils
|
|
||||||
url = "{server}/emby/LiveTv/Channels/?userid={UserId}&format=json"
|
|
||||||
params = {
|
params = {
|
||||||
|
|
||||||
'EnableImages': True,
|
'EnableImages': True,
|
||||||
|
@ -154,11 +144,9 @@ class Read_EmbyServer():
|
||||||
"CriticRating,CriticRatingSummary,Etag,ShortOverview,ProductionLocations,"
|
"CriticRating,CriticRatingSummary,Etag,ShortOverview,ProductionLocations,"
|
||||||
"Tags,ProviderIds,ParentId,RemoteTrailers,SpecialEpisodeNumbers")
|
"Tags,ProviderIds,ParentId,RemoteTrailers,SpecialEpisodeNumbers")
|
||||||
}
|
}
|
||||||
return doUtils(url, parameters=params)
|
return self.doUtils("{server}/emby/LiveTv/Channels/?userid={UserId}&format=json", parameters=params)
|
||||||
|
|
||||||
def getTvRecordings(self, groupid):
|
def getTvRecordings(self, groupid):
|
||||||
doUtils = self.doUtils
|
|
||||||
url = "{server}/emby/LiveTv/Recordings/?userid={UserId}&format=json"
|
|
||||||
if groupid == "root": groupid = ""
|
if groupid == "root": groupid = ""
|
||||||
params = {
|
params = {
|
||||||
|
|
||||||
|
@ -170,13 +158,10 @@ class Read_EmbyServer():
|
||||||
"CriticRating,CriticRatingSummary,Etag,ShortOverview,ProductionLocations,"
|
"CriticRating,CriticRatingSummary,Etag,ShortOverview,ProductionLocations,"
|
||||||
"Tags,ProviderIds,ParentId,RemoteTrailers,SpecialEpisodeNumbers")
|
"Tags,ProviderIds,ParentId,RemoteTrailers,SpecialEpisodeNumbers")
|
||||||
}
|
}
|
||||||
return doUtils(url, parameters=params)
|
return self.doUtils("{server}/emby/LiveTv/Recordings/?userid={UserId}&format=json", parameters=params)
|
||||||
|
|
||||||
def getSection(self, parentid, itemtype=None, sortby="SortName", basic=False, dialog=None):
|
def getSection(self, parentid, itemtype=None, sortby="SortName", basic=False, dialog=None):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
|
|
||||||
doUtils = self.doUtils
|
|
||||||
items = {
|
items = {
|
||||||
|
|
||||||
'Items': [],
|
'Items': [],
|
||||||
|
@ -195,13 +180,13 @@ class Read_EmbyServer():
|
||||||
'Recursive': True,
|
'Recursive': True,
|
||||||
'Limit': 1
|
'Limit': 1
|
||||||
}
|
}
|
||||||
result = doUtils(url, parameters=params)
|
result = self.doUtils(url, parameters=params)
|
||||||
try:
|
try:
|
||||||
total = result['TotalRecordCount']
|
total = result['TotalRecordCount']
|
||||||
items['TotalRecordCount'] = total
|
items['TotalRecordCount'] = total
|
||||||
|
|
||||||
except TypeError: # Failed to retrieve
|
except TypeError: # Failed to retrieve
|
||||||
log("%s:%s Failed to retrieve the server response." % (url, params), 2)
|
self.logMsg("%s:%s Failed to retrieve the server response." % (url, params), 2)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
index = 0
|
index = 0
|
||||||
|
@ -234,36 +219,36 @@ class Read_EmbyServer():
|
||||||
"Metascore,AirTime,DateCreated,MediaStreams,People,Overview,"
|
"Metascore,AirTime,DateCreated,MediaStreams,People,Overview,"
|
||||||
"CriticRating,CriticRatingSummary,Etag,ShortOverview,ProductionLocations,"
|
"CriticRating,CriticRatingSummary,Etag,ShortOverview,ProductionLocations,"
|
||||||
"Tags,ProviderIds,ParentId,RemoteTrailers,SpecialEpisodeNumbers,"
|
"Tags,ProviderIds,ParentId,RemoteTrailers,SpecialEpisodeNumbers,"
|
||||||
"MediaSources"
|
"MediaSources,VoteCount"
|
||||||
)
|
)
|
||||||
result = doUtils(url, parameters=params)
|
result = self.doUtils(url, parameters=params)
|
||||||
try:
|
try:
|
||||||
items['Items'].extend(result['Items'])
|
items['Items'].extend(result['Items'])
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# Something happened to the connection
|
# Something happened to the connection
|
||||||
if not throttled:
|
if not throttled:
|
||||||
throttled = True
|
throttled = True
|
||||||
log("Throttle activated.", 1)
|
self.logMsg("Throttle activated.", 1)
|
||||||
|
|
||||||
if jump == highestjump:
|
if jump == highestjump:
|
||||||
# We already tried with the highestjump, but it failed. Reset value.
|
# We already tried with the highestjump, but it failed. Reset value.
|
||||||
log("Reset highest value.", 1)
|
self.logMsg("Reset highest value.", 1)
|
||||||
highestjump = 0
|
highestjump = 0
|
||||||
|
|
||||||
# Lower the number by half
|
# Lower the number by half
|
||||||
if highestjump:
|
if highestjump:
|
||||||
throttled = False
|
throttled = False
|
||||||
jump = highestjump
|
jump = highestjump
|
||||||
log("Throttle deactivated.", 1)
|
self.logMsg("Throttle deactivated.", 1)
|
||||||
else:
|
else:
|
||||||
jump = int(jump/4)
|
jump = int(jump/4)
|
||||||
log("Set jump limit to recover: %s" % jump, 2)
|
self.logMsg("Set jump limit to recover: %s" % jump, 2)
|
||||||
|
|
||||||
retry = 0
|
retry = 0
|
||||||
while utils.window('emby_online') != "true":
|
while utils.window('emby_online') != "true":
|
||||||
# Wait server to come back online
|
# Wait server to come back online
|
||||||
if retry == 5:
|
if retry == 5:
|
||||||
log("Unable to reconnect to server. Abort process.", 1)
|
self.logMsg("Unable to reconnect to server. Abort process.", 1)
|
||||||
return items
|
return items
|
||||||
|
|
||||||
retry += 1
|
retry += 1
|
||||||
|
@ -291,12 +276,11 @@ class Read_EmbyServer():
|
||||||
increment = 10
|
increment = 10
|
||||||
|
|
||||||
jump += increment
|
jump += increment
|
||||||
log("Increase jump limit to: %s" % jump, 1)
|
self.logMsg("Increase jump limit to: %s" % jump, 1)
|
||||||
return items
|
return items
|
||||||
|
|
||||||
def getViews(self, mediatype="", root=False, sortedlist=False):
|
def getViews(self, mediatype="", root=False, sortedlist=False):
|
||||||
# Build a list of user views
|
# Build a list of user views
|
||||||
doUtils = self.doUtils
|
|
||||||
views = []
|
views = []
|
||||||
mediatype = mediatype.lower()
|
mediatype = mediatype.lower()
|
||||||
|
|
||||||
|
@ -305,7 +289,7 @@ class Read_EmbyServer():
|
||||||
else: # Views ungrouped
|
else: # Views ungrouped
|
||||||
url = "{server}/emby/Users/{UserId}/Items?Sortby=SortName&format=json"
|
url = "{server}/emby/Users/{UserId}/Items?Sortby=SortName&format=json"
|
||||||
|
|
||||||
result = doUtils(url)
|
result = self.doUtils(url)
|
||||||
try:
|
try:
|
||||||
items = result['Items']
|
items = result['Items']
|
||||||
except TypeError:
|
except TypeError:
|
||||||
|
@ -313,11 +297,8 @@ class Read_EmbyServer():
|
||||||
else:
|
else:
|
||||||
for item in items:
|
for item in items:
|
||||||
|
|
||||||
name = item['Name']
|
item['Name'] = item['Name']
|
||||||
itemId = item['Id']
|
if item['Type'] == "Channel":
|
||||||
viewtype = item['Type']
|
|
||||||
|
|
||||||
if viewtype == "Channel":
|
|
||||||
# Filter view types
|
# Filter view types
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -328,20 +309,20 @@ class Read_EmbyServer():
|
||||||
# Assumed missing is mixed then.
|
# Assumed missing is mixed then.
|
||||||
'''if itemtype is None:
|
'''if itemtype is None:
|
||||||
url = "{server}/emby/Library/MediaFolders?format=json"
|
url = "{server}/emby/Library/MediaFolders?format=json"
|
||||||
result = doUtils(url)
|
result = self.doUtils(url)
|
||||||
|
|
||||||
for folder in result['Items']:
|
for folder in result['Items']:
|
||||||
if itemId == folder['Id']:
|
if item['Id'] == folder['Id']:
|
||||||
itemtype = folder.get('CollectionType', "mixed")'''
|
itemtype = folder.get('CollectionType', "mixed")'''
|
||||||
|
|
||||||
if name not in ('Collections', 'Trailers'):
|
if item['Name'] not in ('Collections', 'Trailers'):
|
||||||
|
|
||||||
if sortedlist:
|
if sortedlist:
|
||||||
views.append({
|
views.append({
|
||||||
|
|
||||||
'name': name,
|
'name': item['Name'],
|
||||||
'type': itemtype,
|
'type': itemtype,
|
||||||
'id': itemId
|
'id': item['Id']
|
||||||
})
|
})
|
||||||
|
|
||||||
elif (itemtype == mediatype or
|
elif (itemtype == mediatype or
|
||||||
|
@ -349,9 +330,9 @@ class Read_EmbyServer():
|
||||||
|
|
||||||
views.append({
|
views.append({
|
||||||
|
|
||||||
'name': name,
|
'name': item['Name'],
|
||||||
'type': itemtype,
|
'type': itemtype,
|
||||||
'id': itemId
|
'id': item['Id']
|
||||||
})
|
})
|
||||||
|
|
||||||
return views
|
return views
|
||||||
|
@ -359,8 +340,6 @@ class Read_EmbyServer():
|
||||||
def verifyView(self, parentid, itemid):
|
def verifyView(self, parentid, itemid):
|
||||||
|
|
||||||
belongs = False
|
belongs = False
|
||||||
|
|
||||||
url = "{server}/emby/Users/{UserId}/Items?format=json"
|
|
||||||
params = {
|
params = {
|
||||||
|
|
||||||
'ParentId': parentid,
|
'ParentId': parentid,
|
||||||
|
@ -370,7 +349,7 @@ class Read_EmbyServer():
|
||||||
'Recursive': True,
|
'Recursive': True,
|
||||||
'Ids': itemid
|
'Ids': itemid
|
||||||
}
|
}
|
||||||
result = self.doUtils(url, parameters=params)
|
result = self.doUtils("{server}/emby/Users/{UserId}/Items?format=json", parameters=params)
|
||||||
try:
|
try:
|
||||||
total = result['TotalRecordCount']
|
total = result['TotalRecordCount']
|
||||||
except TypeError:
|
except TypeError:
|
||||||
|
@ -383,40 +362,23 @@ class Read_EmbyServer():
|
||||||
return belongs
|
return belongs
|
||||||
|
|
||||||
def getMovies(self, parentId, basic=False, dialog=None):
|
def getMovies(self, parentId, basic=False, dialog=None):
|
||||||
|
return self.getSection(parentId, "Movie", basic=basic, dialog=dialog)
|
||||||
items = self.getSection(parentId, "Movie", basic=basic, dialog=dialog)
|
|
||||||
|
|
||||||
return items
|
|
||||||
|
|
||||||
def getBoxset(self, dialog=None):
|
def getBoxset(self, dialog=None):
|
||||||
|
return self.getSection(None, "BoxSet", dialog=dialog)
|
||||||
items = self.getSection(None, "BoxSet", dialog=dialog)
|
|
||||||
|
|
||||||
return items
|
|
||||||
|
|
||||||
def getMovies_byBoxset(self, boxsetid):
|
def getMovies_byBoxset(self, boxsetid):
|
||||||
|
return self.getSection(boxsetid, "Movie")
|
||||||
items = self.getSection(boxsetid, "Movie")
|
|
||||||
|
|
||||||
return items
|
|
||||||
|
|
||||||
def getMusicVideos(self, parentId, basic=False, dialog=None):
|
def getMusicVideos(self, parentId, basic=False, dialog=None):
|
||||||
|
return self.getSection(parentId, "MusicVideo", basic=basic, dialog=dialog)
|
||||||
items = self.getSection(parentId, "MusicVideo", basic=basic, dialog=dialog)
|
|
||||||
|
|
||||||
return items
|
|
||||||
|
|
||||||
def getHomeVideos(self, parentId):
|
def getHomeVideos(self, parentId):
|
||||||
|
|
||||||
items = self.getSection(parentId, "Video")
|
return self.getSection(parentId, "Video")
|
||||||
|
|
||||||
return items
|
|
||||||
|
|
||||||
def getShows(self, parentId, basic=False, dialog=None):
|
def getShows(self, parentId, basic=False, dialog=None):
|
||||||
|
return self.getSection(parentId, "Series", basic=basic, dialog=dialog)
|
||||||
items = self.getSection(parentId, "Series", basic=basic, dialog=dialog)
|
|
||||||
|
|
||||||
return items
|
|
||||||
|
|
||||||
def getSeasons(self, showId):
|
def getSeasons(self, showId):
|
||||||
|
|
||||||
|
@ -426,13 +388,12 @@ class Read_EmbyServer():
|
||||||
'TotalRecordCount': 0
|
'TotalRecordCount': 0
|
||||||
}
|
}
|
||||||
|
|
||||||
url = "{server}/emby/Shows/%s/Seasons?UserId={UserId}&format=json" % showId
|
|
||||||
params = {
|
params = {
|
||||||
|
|
||||||
'IsVirtualUnaired': False,
|
'IsVirtualUnaired': False,
|
||||||
'Fields': "Etag"
|
'Fields': "Etag"
|
||||||
}
|
}
|
||||||
result = self.doUtils(url, parameters=params)
|
result = self.doUtils("{server}/emby/Shows/%s/Seasons?UserId={UserId}&format=json" % showId, parameters=params)
|
||||||
if result:
|
if result:
|
||||||
items = result
|
items = result
|
||||||
|
|
||||||
|
@ -440,25 +401,19 @@ class Read_EmbyServer():
|
||||||
|
|
||||||
def getEpisodes(self, parentId, basic=False, dialog=None):
|
def getEpisodes(self, parentId, basic=False, dialog=None):
|
||||||
|
|
||||||
items = self.getSection(parentId, "Episode", basic=basic, dialog=dialog)
|
return self.getSection(parentId, "Episode", basic=basic, dialog=dialog)
|
||||||
|
|
||||||
return items
|
|
||||||
|
|
||||||
def getEpisodesbyShow(self, showId):
|
def getEpisodesbyShow(self, showId):
|
||||||
|
|
||||||
items = self.getSection(showId, "Episode")
|
return self.getSection(showId, "Episode")
|
||||||
|
|
||||||
return items
|
|
||||||
|
|
||||||
def getEpisodesbySeason(self, seasonId):
|
def getEpisodesbySeason(self, seasonId):
|
||||||
|
|
||||||
items = self.getSection(seasonId, "Episode")
|
return self.getSection(seasonId, "Episode")
|
||||||
|
|
||||||
return items
|
|
||||||
|
|
||||||
def getArtists(self, dialog=None):
|
def getArtists(self, dialog=None):
|
||||||
|
|
||||||
doUtils = self.doUtils
|
|
||||||
items = {
|
items = {
|
||||||
|
|
||||||
'Items': [],
|
'Items': [],
|
||||||
|
@ -472,7 +427,7 @@ class Read_EmbyServer():
|
||||||
'Recursive': True,
|
'Recursive': True,
|
||||||
'Limit': 1
|
'Limit': 1
|
||||||
}
|
}
|
||||||
result = doUtils(url, parameters=params)
|
result = self.doUtils(url, parameters=params)
|
||||||
try:
|
try:
|
||||||
total = result['TotalRecordCount']
|
total = result['TotalRecordCount']
|
||||||
items['TotalRecordCount'] = total
|
items['TotalRecordCount'] = total
|
||||||
|
@ -502,7 +457,7 @@ class Read_EmbyServer():
|
||||||
"AirTime,DateCreated,MediaStreams,People,ProviderIds,Overview"
|
"AirTime,DateCreated,MediaStreams,People,ProviderIds,Overview"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
result = doUtils(url, parameters=params)
|
result = self.doUtils(url, parameters=params)
|
||||||
items['Items'].extend(result['Items'])
|
items['Items'].extend(result['Items'])
|
||||||
|
|
||||||
index += jump
|
index += jump
|
||||||
|
@ -512,28 +467,17 @@ class Read_EmbyServer():
|
||||||
return items
|
return items
|
||||||
|
|
||||||
def getAlbums(self, basic=False, dialog=None):
|
def getAlbums(self, basic=False, dialog=None):
|
||||||
|
return self.getSection(None, "MusicAlbum", sortby="DateCreated", basic=basic, dialog=dialog)
|
||||||
items = self.getSection(None, "MusicAlbum", sortby="DateCreated", basic=basic, dialog=dialog)
|
|
||||||
|
|
||||||
return items
|
|
||||||
|
|
||||||
def getAlbumsbyArtist(self, artistId):
|
def getAlbumsbyArtist(self, artistId):
|
||||||
|
return self.getSection(artistId, "MusicAlbum", sortby="DateCreated")
|
||||||
items = self.getSection(artistId, "MusicAlbum", sortby="DateCreated")
|
|
||||||
|
|
||||||
return items
|
|
||||||
|
|
||||||
def getSongs(self, basic=False, dialog=None):
|
def getSongs(self, basic=False, dialog=None):
|
||||||
|
return self.getSection(None, "Audio", basic=basic, dialog=dialog)
|
||||||
items = self.getSection(None, "Audio", basic=basic, dialog=dialog)
|
|
||||||
|
|
||||||
return items
|
|
||||||
|
|
||||||
def getSongsbyAlbum(self, albumId):
|
def getSongsbyAlbum(self, albumId):
|
||||||
|
return self.getSection(albumId, "Audio")
|
||||||
|
|
||||||
items = self.getSection(albumId, "Audio")
|
|
||||||
|
|
||||||
return items
|
|
||||||
|
|
||||||
def getAdditionalParts(self, itemId):
|
def getAdditionalParts(self, itemId):
|
||||||
|
|
||||||
|
@ -543,8 +487,7 @@ class Read_EmbyServer():
|
||||||
'TotalRecordCount': 0
|
'TotalRecordCount': 0
|
||||||
}
|
}
|
||||||
|
|
||||||
url = "{server}/emby/Videos/%s/AdditionalParts?UserId={UserId}&format=json" % itemId
|
result = self.doUtils("{server}/emby/Videos/%s/AdditionalParts?UserId={UserId}&format=json" % itemId)
|
||||||
result = self.doUtils(url)
|
|
||||||
if result:
|
if result:
|
||||||
items = result
|
items = result
|
||||||
|
|
||||||
|
@ -566,25 +509,21 @@ class Read_EmbyServer():
|
||||||
|
|
||||||
def updateUserRating(self, itemid, like=None, favourite=None, deletelike=False):
|
def updateUserRating(self, itemid, like=None, favourite=None, deletelike=False):
|
||||||
# Updates the user rating to Emby
|
# Updates the user rating to Emby
|
||||||
doUtils = self.doUtils
|
|
||||||
|
|
||||||
if favourite:
|
if favourite:
|
||||||
url = "{server}/emby/Users/{UserId}/FavoriteItems/%s?format=json" % itemid
|
self.doUtils("{server}/emby/Users/{UserId}/FavoriteItems/%s?format=json" % itemid, action_type="POST")
|
||||||
doUtils(url, type="POST")
|
|
||||||
elif favourite == False:
|
elif favourite == False:
|
||||||
url = "{server}/emby/Users/{UserId}/FavoriteItems/%s?format=json" % itemid
|
self.doUtils("{server}/emby/Users/{UserId}/FavoriteItems/%s?format=json" % itemid, action_type="DELETE")
|
||||||
doUtils(url, type="DELETE")
|
|
||||||
|
|
||||||
if not deletelike and like:
|
if not deletelike and like:
|
||||||
url = "{server}/emby/Users/{UserId}/Items/%s/Rating?Likes=true&format=json" % itemid
|
self.doUtils("{server}/emby/Users/{UserId}/Items/%s/Rating?Likes=true&format=json" % itemid, action_type="POST")
|
||||||
doUtils(url, type="POST")
|
elif not deletelike and like is False:
|
||||||
elif not deletelike and like == False:
|
self.doUtils("{server}/emby/Users/{UserId}/Items/%s/Rating?Likes=false&format=json" % itemid, action_type="POST")
|
||||||
url = "{server}/emby/Users/{UserId}/Items/%s/Rating?Likes=false&format=json" % itemid
|
|
||||||
doUtil(url, type="POST")
|
|
||||||
elif deletelike:
|
elif deletelike:
|
||||||
url = "{server}/emby/Users/{UserId}/Items/%s/Rating?format=json" % itemid
|
self.doUtils("{server}/emby/Users/{UserId}/Items/%s/Rating?format=json" % itemid, action_type="DELETE")
|
||||||
doUtils(url, type="DELETE")
|
else:
|
||||||
|
self.logMsg("Error processing user rating.", 1)
|
||||||
|
|
||||||
self.logMsg("Update user rating to emby for itemid: %s "
|
self.logMsg("Update user rating to emby for itemid: %s "
|
||||||
"| like: %s | favourite: %s | deletelike: %s"
|
"| like: %s | favourite: %s | deletelike: %s"
|
||||||
% (itemid, like, favourite, deletelike), 1)
|
% (itemid, like, favourite, deletelike), 1)
|
||||||
|
|
|
@ -299,7 +299,7 @@ def window(property, value=None, clear=False, windowid=10000):
|
||||||
Property needs to be string; value may be string or unicode
|
Property needs to be string; value may be string or unicode
|
||||||
"""
|
"""
|
||||||
WINDOW = xbmcgui.Window(windowid)
|
WINDOW = xbmcgui.Window(windowid)
|
||||||
|
|
||||||
#setproperty accepts both string and unicode but utf-8 strings are adviced by kodi devs because some unicode can give issues
|
#setproperty accepts both string and unicode but utf-8 strings are adviced by kodi devs because some unicode can give issues
|
||||||
'''if isinstance(property, unicode):
|
'''if isinstance(property, unicode):
|
||||||
property = property.encode("utf-8")
|
property = property.encode("utf-8")
|
||||||
|
@ -334,23 +334,22 @@ def language(stringid):
|
||||||
string = addon.getLocalizedString(stringid) #returns unicode object
|
string = addon.getLocalizedString(stringid) #returns unicode object
|
||||||
return string
|
return string
|
||||||
|
|
||||||
def kodiSQL(type="video"):
|
def kodiSQL(media_type="video"):
|
||||||
|
|
||||||
if type == "emby":
|
if media_type == "emby":
|
||||||
dbPath = xbmc.translatePath("special://database/emby.db").decode('utf-8')
|
dbPath = xbmc.translatePath("special://database/emby.db").decode('utf-8')
|
||||||
elif type == "music":
|
elif media_type == "music":
|
||||||
dbPath = getKodiMusicDBPath()
|
dbPath = getKodiMusicDBPath()
|
||||||
elif type == "texture":
|
elif media_type == "texture":
|
||||||
dbPath = xbmc.translatePath("special://database/Textures13.db").decode('utf-8')
|
dbPath = xbmc.translatePath("special://database/Textures13.db").decode('utf-8')
|
||||||
else:
|
else:
|
||||||
dbPath = getKodiVideoDBPath()
|
dbPath = getKodiVideoDBPath()
|
||||||
|
|
||||||
connection = sqlite3.connect(dbPath)
|
connection = sqlite3.connect(dbPath)
|
||||||
return connection
|
return connection
|
||||||
|
|
||||||
def getKodiVideoDBPath():
|
def getKodiVideoDBPath():
|
||||||
|
|
||||||
kodibuild = xbmc.getInfoLabel('System.BuildVersion')[:2]
|
|
||||||
dbVersion = {
|
dbVersion = {
|
||||||
|
|
||||||
"13": 78, # Gotham
|
"13": 78, # Gotham
|
||||||
|
@ -358,16 +357,16 @@ def getKodiVideoDBPath():
|
||||||
"15": 93, # Isengard
|
"15": 93, # Isengard
|
||||||
"16": 99, # Jarvis
|
"16": 99, # Jarvis
|
||||||
"17":104 # Krypton
|
"17":104 # Krypton
|
||||||
|
"17": 104 # Krypton
|
||||||
}
|
}
|
||||||
|
|
||||||
dbPath = xbmc.translatePath(
|
dbPath = xbmc.translatePath(
|
||||||
"special://database/MyVideos%s.db"
|
"special://database/MyVideos%s.db"
|
||||||
% dbVersion.get(kodibuild, "")).decode('utf-8')
|
% dbVersion.get(xbmc.getInfoLabel('System.BuildVersion')[:2], "")).decode('utf-8')
|
||||||
return dbPath
|
return dbPath
|
||||||
|
|
||||||
def getKodiMusicDBPath():
|
def getKodiMusicDBPath():
|
||||||
|
|
||||||
kodibuild = xbmc.getInfoLabel('System.BuildVersion')[:2]
|
|
||||||
dbVersion = {
|
dbVersion = {
|
||||||
|
|
||||||
"13": 46, # Gotham
|
"13": 46, # Gotham
|
||||||
|
@ -379,7 +378,7 @@ def getKodiMusicDBPath():
|
||||||
|
|
||||||
dbPath = xbmc.translatePath(
|
dbPath = xbmc.translatePath(
|
||||||
"special://database/MyMusic%s.db"
|
"special://database/MyMusic%s.db"
|
||||||
% dbVersion.get(kodibuild, "")).decode('utf-8')
|
% dbVersion.get(xbmc.getInfoLabel('System.BuildVersion')[:2], "")).decode('utf-8')
|
||||||
return dbPath
|
return dbPath
|
||||||
|
|
||||||
def getScreensaver():
|
def getScreensaver():
|
||||||
|
@ -394,11 +393,7 @@ def getScreensaver():
|
||||||
'setting': "screensaver.mode"
|
'setting': "screensaver.mode"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result = xbmc.executeJSONRPC(json.dumps(query))
|
return json.loads(xbmc.executeJSONRPC(json.dumps(query)))['result']['value']
|
||||||
result = json.loads(result)
|
|
||||||
screensaver = result['result']['value']
|
|
||||||
|
|
||||||
return screensaver
|
|
||||||
|
|
||||||
def setScreensaver(value):
|
def setScreensaver(value):
|
||||||
# Toggle the screensaver
|
# Toggle the screensaver
|
||||||
|
@ -413,15 +408,13 @@ def setScreensaver(value):
|
||||||
'value': value
|
'value': value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result = xbmc.executeJSONRPC(json.dumps(query))
|
logMsg("PLEX", "Toggling screensaver: %s %s" % (value, xbmc.executeJSONRPC(json.dumps(query))), 1)
|
||||||
logMsg("PLEX", "Toggling screensaver: %s %s" % (value, result), 1)
|
|
||||||
|
|
||||||
def reset():
|
def reset():
|
||||||
|
|
||||||
dialog = xbmcgui.Dialog()
|
dialog = xbmcgui.Dialog()
|
||||||
|
|
||||||
resp = dialog.yesno("Warning", "Are you sure you want to reset your local Kodi database?")
|
if dialog.yesno("Warning", "Are you sure you want to reset your local Kodi database?") == 0:
|
||||||
if resp == 0:
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# first stop any db sync
|
# first stop any db sync
|
||||||
|
@ -483,7 +476,7 @@ def reset():
|
||||||
cursor.close()
|
cursor.close()
|
||||||
|
|
||||||
# Offer to wipe cached thumbnails
|
# Offer to wipe cached thumbnails
|
||||||
resp = dialog.yesno("Warning", "Removed all cached artwork?")
|
resp = dialog.yesno("Warning", "Remove all cached artwork?")
|
||||||
if resp:
|
if resp:
|
||||||
logMsg("EMBY", "Resetting all cached artwork.", 0)
|
logMsg("EMBY", "Resetting all cached artwork.", 0)
|
||||||
# Remove all existing textures first
|
# Remove all existing textures first
|
||||||
|
@ -497,7 +490,7 @@ def reset():
|
||||||
xbmcvfs.delete(os.path.join(path+dir.decode('utf-8'),file.decode('utf-8')))
|
xbmcvfs.delete(os.path.join(path+dir.decode('utf-8'),file.decode('utf-8')))
|
||||||
else:
|
else:
|
||||||
xbmcvfs.delete(os.path.join(path.encode('utf-8')+dir,file))
|
xbmcvfs.delete(os.path.join(path.encode('utf-8')+dir,file))
|
||||||
|
|
||||||
# remove all existing data from texture DB
|
# remove all existing data from texture DB
|
||||||
connection = kodiSQL('texture')
|
connection = kodiSQL('texture')
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
|
@ -509,8 +502,8 @@ def reset():
|
||||||
cursor.execute("DELETE FROM " + tableName)
|
cursor.execute("DELETE FROM " + tableName)
|
||||||
connection.commit()
|
connection.commit()
|
||||||
cursor.close()
|
cursor.close()
|
||||||
|
|
||||||
# reset the install run flag
|
# reset the install run flag
|
||||||
settings('SyncInstallRunDone', value="false")
|
settings('SyncInstallRunDone', value="false")
|
||||||
|
|
||||||
# Remove emby info
|
# Remove emby info
|
||||||
|
@ -532,7 +525,7 @@ def profiling(sortby="cumulative"):
|
||||||
# Will print results to Kodi log
|
# Will print results to Kodi log
|
||||||
def decorator(func):
|
def decorator(func):
|
||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
|
|
||||||
pr = cProfile.Profile()
|
pr = cProfile.Profile()
|
||||||
|
|
||||||
pr.enable()
|
pr.enable()
|
||||||
|
@ -576,7 +569,7 @@ def normalize_nodes(text):
|
||||||
# with dots at the end
|
# with dots at the end
|
||||||
text = text.rstrip('.')
|
text = text.rstrip('.')
|
||||||
text = unicodedata.normalize('NFKD', unicode(text, 'utf-8')).encode('ascii', 'ignore')
|
text = unicodedata.normalize('NFKD', unicode(text, 'utf-8')).encode('ascii', 'ignore')
|
||||||
|
|
||||||
return text
|
return text
|
||||||
|
|
||||||
def normalize_string(text):
|
def normalize_string(text):
|
||||||
|
@ -717,7 +710,7 @@ def sourcesXML():
|
||||||
root = etree.Element('sources')
|
root = etree.Element('sources')
|
||||||
else:
|
else:
|
||||||
root = xmlparse.getroot()
|
root = xmlparse.getroot()
|
||||||
|
|
||||||
|
|
||||||
video = root.find('video')
|
video = root.find('video')
|
||||||
if video is None:
|
if video is None:
|
||||||
|
@ -729,7 +722,7 @@ def sourcesXML():
|
||||||
for source in root.findall('.//path'):
|
for source in root.findall('.//path'):
|
||||||
if source.text == "smb://":
|
if source.text == "smb://":
|
||||||
count -= 1
|
count -= 1
|
||||||
|
|
||||||
if count == 0:
|
if count == 0:
|
||||||
# sources already set
|
# sources already set
|
||||||
break
|
break
|
||||||
|
@ -775,9 +768,7 @@ def passwordsXML():
|
||||||
|
|
||||||
elif option == 1:
|
elif option == 1:
|
||||||
# User selected remove
|
# User selected remove
|
||||||
iterator = root.getiterator('passwords')
|
for paths in root.getiterator('passwords'):
|
||||||
|
|
||||||
for paths in iterator:
|
|
||||||
for path in paths:
|
for path in paths:
|
||||||
if path.find('.//from').text == "smb://%s/" % credentials:
|
if path.find('.//from').text == "smb://%s/" % credentials:
|
||||||
paths.remove(path)
|
paths.remove(path)
|
||||||
|
@ -788,7 +779,7 @@ def passwordsXML():
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
logMsg("EMBY", "Failed to find saved server: %s in passwords.xml" % credentials, 1)
|
logMsg("EMBY", "Failed to find saved server: %s in passwords.xml" % credentials, 1)
|
||||||
|
|
||||||
settings('networkCreds', value="")
|
settings('networkCreds', value="")
|
||||||
xbmcgui.Dialog().notification(
|
xbmcgui.Dialog().notification(
|
||||||
heading='PlexKodiConnect',
|
heading='PlexKodiConnect',
|
||||||
|
@ -842,7 +833,7 @@ def passwordsXML():
|
||||||
# Force Kodi to see the credentials without restarting
|
# Force Kodi to see the credentials without restarting
|
||||||
xbmcvfs.exists(topath)
|
xbmcvfs.exists(topath)
|
||||||
|
|
||||||
# Add credentials
|
# Add credentials
|
||||||
settings('networkCreds', value="%s" % server)
|
settings('networkCreds', value="%s" % server)
|
||||||
logMsg("PLEX", "Added server: %s to passwords.xml" % server, 1)
|
logMsg("PLEX", "Added server: %s to passwords.xml" % server, 1)
|
||||||
# Prettify and write to file
|
# Prettify and write to file
|
||||||
|
@ -850,7 +841,7 @@ def passwordsXML():
|
||||||
indent(root)
|
indent(root)
|
||||||
except: pass
|
except: pass
|
||||||
etree.ElementTree(root).write(xmlpath)
|
etree.ElementTree(root).write(xmlpath)
|
||||||
|
|
||||||
# dialog.notification(
|
# dialog.notification(
|
||||||
# heading="PlexKodiConnect",
|
# heading="PlexKodiConnect",
|
||||||
# message="Added to passwords.xml",
|
# message="Added to passwords.xml",
|
||||||
|
@ -881,7 +872,7 @@ def playlistXSP(mediatype, tagname, viewid, viewtype="", delete=False):
|
||||||
if delete:
|
if delete:
|
||||||
xbmcvfs.delete(xsppath.encode('utf-8'))
|
xbmcvfs.delete(xsppath.encode('utf-8'))
|
||||||
logMsg("PLEX", "Successfully removed playlist: %s." % tagname, 1)
|
logMsg("PLEX", "Successfully removed playlist: %s." % tagname, 1)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# Using write process since there's no guarantee the xml declaration works with etree
|
# Using write process since there's no guarantee the xml declaration works with etree
|
||||||
|
@ -949,4 +940,4 @@ def try_decode(text, encoding="utf-8"):
|
||||||
try:
|
try:
|
||||||
return text.decode(encoding,"ignore")
|
return text.decode(encoding,"ignore")
|
||||||
except:
|
except:
|
||||||
return text
|
return text
|
||||||
|
|
|
@ -54,7 +54,6 @@ class VideoNodes(object):
|
||||||
mediatype = mediatypes[mediatype]
|
mediatype = mediatypes[mediatype]
|
||||||
|
|
||||||
window = utils.window
|
window = utils.window
|
||||||
kodiversion = self.kodiversion
|
|
||||||
|
|
||||||
if viewtype == "mixed":
|
if viewtype == "mixed":
|
||||||
dirname = "%s-%s" % (viewid, mediatype)
|
dirname = "%s-%s" % (viewid, mediatype)
|
||||||
|
@ -231,7 +230,7 @@ class VideoNodes(object):
|
||||||
# Custom query
|
# Custom query
|
||||||
path = ("plugin://plugin.video.plexkodiconnect/?id=%s&mode=recentepisodes&type=%s&tagname=%s&limit=%s"
|
path = ("plugin://plugin.video.plexkodiconnect/?id=%s&mode=recentepisodes&type=%s&tagname=%s&limit=%s"
|
||||||
% (viewid, mediatype, tagname, limit))
|
% (viewid, mediatype, tagname, limit))
|
||||||
elif kodiversion == 14 and nodetype == "inprogressepisodes":
|
elif self.kodiversion == 14 and nodetype == "inprogressepisodes":
|
||||||
# Custom query
|
# Custom query
|
||||||
path = "plugin://plugin.video.plexkodiconnect/?id=%s&mode=inprogressepisodes&limit=%s" % (tagname, limit)
|
path = "plugin://plugin.video.plexkodiconnect/?id=%s&mode=inprogressepisodes&limit=%s" % (tagname, limit)
|
||||||
elif nodetype == 'ondeck':
|
elif nodetype == 'ondeck':
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue