commit
bec455e8f7
24 changed files with 12471 additions and 12835 deletions
|
@ -143,7 +143,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(
|
||||||
|
@ -152,8 +152,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")
|
|
@ -323,7 +323,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>
|
||||||
|
|
|
@ -116,17 +116,16 @@ class API():
|
||||||
}
|
}
|
||||||
|
|
||||||
def getMediaStreams(self):
|
def getMediaStreams(self):
|
||||||
item = self.item
|
|
||||||
videotracks = []
|
videotracks = []
|
||||||
audiotracks = []
|
audiotracks = []
|
||||||
subtitlelanguages = []
|
subtitlelanguages = []
|
||||||
|
|
||||||
try:
|
try:
|
||||||
media_streams = item['MediaSources'][0]['MediaStreams']
|
media_streams = self.item['MediaSources'][0]['MediaStreams']
|
||||||
|
|
||||||
except KeyError:
|
except KeyError:
|
||||||
if not item.get("MediaStreams"): return None
|
if not self.item.get("MediaStreams"): return None
|
||||||
media_streams = item['MediaStreams']
|
media_streams = self.item['MediaStreams']
|
||||||
|
|
||||||
for media_stream in media_streams:
|
for media_stream in media_streams:
|
||||||
# Sort through Video, Audio, Subtitle
|
# Sort through Video, Audio, Subtitle
|
||||||
|
@ -141,12 +140,12 @@ class API():
|
||||||
'codec': codec,
|
'codec': codec,
|
||||||
'height': media_stream.get('Height'),
|
'height': media_stream.get('Height'),
|
||||||
'width': media_stream.get('Width'),
|
'width': media_stream.get('Width'),
|
||||||
'video3DFormat': item.get('Video3DFormat'),
|
'video3DFormat': self.item.get('Video3DFormat'),
|
||||||
'aspect': 1.85
|
'aspect': 1.85
|
||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
container = item['MediaSources'][0]['Container'].lower()
|
container = self.item['MediaSources'][0]['Container'].lower()
|
||||||
except:
|
except:
|
||||||
container = ""
|
container = ""
|
||||||
|
|
||||||
|
@ -161,9 +160,9 @@ class API():
|
||||||
track['codec'] = "avc1"
|
track['codec'] = "avc1"
|
||||||
|
|
||||||
# Aspect ratio
|
# Aspect ratio
|
||||||
if item.get('AspectRatio'):
|
if self.item.get('AspectRatio'):
|
||||||
# Metadata AR
|
# Metadata AR
|
||||||
aspect = item['AspectRatio']
|
aspect = self.item['AspectRatio']
|
||||||
else: # File AR
|
else: # File AR
|
||||||
aspect = media_stream.get('AspectRatio', "0")
|
aspect = media_stream.get('AspectRatio', "0")
|
||||||
|
|
||||||
|
@ -180,8 +179,8 @@ class API():
|
||||||
else:
|
else:
|
||||||
track['aspect'] = 1.85
|
track['aspect'] = 1.85
|
||||||
|
|
||||||
if item.get("RunTimeTicks"):
|
if self.item.get("RunTimeTicks"):
|
||||||
track['duration'] = item.get("RunTimeTicks") / 10000000.0
|
track['duration'] = self.item.get("RunTimeTicks") / 10000000.0
|
||||||
|
|
||||||
videotracks.append(track)
|
videotracks.append(track)
|
||||||
|
|
||||||
|
@ -211,12 +210,11 @@ class API():
|
||||||
}
|
}
|
||||||
|
|
||||||
def getRuntime(self):
|
def getRuntime(self):
|
||||||
item = self.item
|
|
||||||
try:
|
try:
|
||||||
runtime = item['RunTimeTicks'] / 10000000.0
|
runtime = self.item['RunTimeTicks'] / 10000000.0
|
||||||
|
|
||||||
except KeyError:
|
except KeyError:
|
||||||
runtime = item.get('CumulativeRunTimeTicks', 0) / 10000000.0
|
runtime = self.item.get('CumulativeRunTimeTicks', 0) / 10000000.0
|
||||||
|
|
||||||
return runtime
|
return runtime
|
||||||
|
|
||||||
|
@ -234,15 +232,14 @@ class API():
|
||||||
|
|
||||||
def getStudios(self):
|
def getStudios(self):
|
||||||
# Process Studios
|
# Process Studios
|
||||||
item = self.item
|
|
||||||
studios = []
|
studios = []
|
||||||
|
|
||||||
try:
|
try:
|
||||||
studio = item['SeriesStudio']
|
studio = self.item['SeriesStudio']
|
||||||
studios.append(self.verifyStudio(studio))
|
studios.append(self.verifyStudio(studio))
|
||||||
|
|
||||||
except KeyError:
|
except KeyError:
|
||||||
studioList = item['Studios']
|
studioList = self.item['Studios']
|
||||||
for studio in studioList:
|
for studio in studioList:
|
||||||
|
|
||||||
name = studio['Name']
|
name = studio['Name']
|
||||||
|
@ -265,12 +262,11 @@ class API():
|
||||||
|
|
||||||
def getChecksum(self):
|
def getChecksum(self):
|
||||||
# Use the etags checksum and userdata
|
# Use the etags checksum and userdata
|
||||||
item = self.item
|
userdata = self.item['UserData']
|
||||||
userdata = item['UserData']
|
|
||||||
|
|
||||||
checksum = "%s%s%s%s%s%s%s" % (
|
checksum = "%s%s%s%s%s%s%s" % (
|
||||||
|
|
||||||
item['Etag'],
|
self.item['Etag'],
|
||||||
userdata['Played'],
|
userdata['Played'],
|
||||||
userdata['IsFavorite'],
|
userdata['IsFavorite'],
|
||||||
userdata.get('Likes',''),
|
userdata.get('Likes',''),
|
||||||
|
@ -282,9 +278,8 @@ class API():
|
||||||
return checksum
|
return checksum
|
||||||
|
|
||||||
def getGenres(self):
|
def getGenres(self):
|
||||||
item = self.item
|
|
||||||
all_genres = ""
|
all_genres = ""
|
||||||
genres = item.get('Genres', item.get('SeriesGenres'))
|
genres = self.item.get('Genres', self.item.get('SeriesGenres'))
|
||||||
|
|
||||||
if genres:
|
if genres:
|
||||||
all_genres = " / ".join(genres)
|
all_genres = " / ".join(genres)
|
||||||
|
@ -362,9 +357,8 @@ class API():
|
||||||
|
|
||||||
def getFilePath(self):
|
def getFilePath(self):
|
||||||
|
|
||||||
item = self.item
|
|
||||||
try:
|
try:
|
||||||
filepath = item['Path']
|
filepath = self.item['Path']
|
||||||
|
|
||||||
except KeyError:
|
except KeyError:
|
||||||
filepath = ""
|
filepath = ""
|
||||||
|
@ -375,8 +369,8 @@ class API():
|
||||||
filepath = filepath.replace("\\\\", "smb://")
|
filepath = filepath.replace("\\\\", "smb://")
|
||||||
filepath = filepath.replace("\\", "/")
|
filepath = filepath.replace("\\", "/")
|
||||||
|
|
||||||
if item.get('VideoType'):
|
if self.item.get('VideoType'):
|
||||||
videotype = item['VideoType']
|
videotype = self.item['VideoType']
|
||||||
# Specific format modification
|
# Specific format modification
|
||||||
if 'Dvd'in videotype:
|
if 'Dvd'in videotype:
|
||||||
filepath = "%s/VIDEO_TS/VIDEO_TS.IFO" % filepath
|
filepath = "%s/VIDEO_TS/VIDEO_TS.IFO" % filepath
|
||||||
|
@ -388,4 +382,3 @@ class API():
|
||||||
filepath = filepath.replace("/", "\\")
|
filepath = filepath.replace("/", "\\")
|
||||||
|
|
||||||
return filepath
|
return filepath
|
||||||
|
|
|
@ -35,7 +35,7 @@ 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:
|
||||||
|
@ -509,8 +509,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',[])
|
||||||
|
@ -541,7 +539,7 @@ class Artwork():
|
||||||
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
|
||||||
|
@ -552,7 +550,7 @@ class Artwork():
|
||||||
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
|
||||||
|
@ -570,7 +568,7 @@ class Artwork():
|
||||||
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
|
||||||
|
@ -586,7 +584,7 @@ class Artwork():
|
||||||
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
|
||||||
|
|
||||||
|
@ -600,7 +598,7 @@ class Artwork():
|
||||||
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
|
|
@ -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,7 +73,7 @@ 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()
|
||||||
|
@ -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
|
||||||
|
@ -125,10 +122,9 @@ class ConnectUtils():
|
||||||
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
|
||||||
|
@ -213,25 +209,25 @@ 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()
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
|
@ -97,7 +97,7 @@ class DownloadUtils():
|
||||||
self.logMsg("Capabilities URL: %s" % url, 2)
|
self.logMsg("Capabilities URL: %s" % url, 2)
|
||||||
self.logMsg("Postdata: %s" % data, 2)
|
self.logMsg("Postdata: %s" % data, 2)
|
||||||
|
|
||||||
self.downloadUrl(url, postBody=data, type="POST")
|
self.downloadUrl(url, postBody=data, action_type="POST")
|
||||||
self.logMsg("Posted capabilities to %s" % self.server, 2)
|
self.logMsg("Posted capabilities to %s" % self.server, 2)
|
||||||
|
|
||||||
# Attempt at getting sessionId
|
# Attempt at getting sessionId
|
||||||
|
@ -140,13 +140,11 @@ class DownloadUtils():
|
||||||
"{server}/emby/Sessions/%s/Users/%s?format=json"
|
"{server}/emby/Sessions/%s/Users/%s?format=json"
|
||||||
% (sessionId, userId)
|
% (sessionId, userId)
|
||||||
)
|
)
|
||||||
self.downloadUrl(url, postBody={}, type="POST")
|
self.downloadUrl(url, postBody={}, action_type="POST")
|
||||||
|
|
||||||
|
|
||||||
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
|
||||||
|
@ -160,7 +158,7 @@ class DownloadUtils():
|
||||||
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.s = requests.Session()
|
self.s = requests.Session()
|
||||||
|
@ -170,7 +168,7 @@ class DownloadUtils():
|
||||||
self.s.mount("http://", requests.adapters.HTTPAdapter(max_retries=1))
|
self.s.mount("http://", requests.adapters.HTTPAdapter(max_retries=1))
|
||||||
self.s.mount("https://", requests.adapters.HTTPAdapter(max_retries=1))
|
self.s.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:
|
||||||
|
@ -180,12 +178,10 @@ class DownloadUtils():
|
||||||
|
|
||||||
def getHeader(self, authenticate=True):
|
def getHeader(self, authenticate=True):
|
||||||
|
|
||||||
clientInfo = self.clientInfo
|
deviceName = self.clientInfo.getDeviceName()
|
||||||
|
|
||||||
deviceName = clientInfo.getDeviceName()
|
|
||||||
deviceName = utils.normalize_string(deviceName.encode('utf-8'))
|
deviceName = utils.normalize_string(deviceName.encode('utf-8'))
|
||||||
deviceId = clientInfo.getDeviceId()
|
deviceId = self.clientInfo.getDeviceId()
|
||||||
version = clientInfo.getVersion()
|
version = self.clientInfo.getVersion()
|
||||||
|
|
||||||
if not authenticate:
|
if not authenticate:
|
||||||
# If user is not authenticated
|
# If user is not authenticated
|
||||||
|
@ -220,11 +216,10 @@ class DownloadUtils():
|
||||||
|
|
||||||
return header
|
return header
|
||||||
|
|
||||||
def downloadUrl(self, url, postBody=None, type="GET", parameters=None, authenticate=True):
|
def downloadUrl(self, url, postBody=None, action_type="GET", parameters=None, authenticate=True):
|
||||||
|
|
||||||
self.logMsg("=== ENTER downloadUrl ===", 2)
|
self.logMsg("=== ENTER downloadUrl ===", 2)
|
||||||
|
|
||||||
timeout = self.timeout
|
|
||||||
default_link = ""
|
default_link = ""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -238,12 +233,12 @@ class DownloadUtils():
|
||||||
url = url.replace("{UserId}", self.userId)
|
url = url.replace("{UserId}", self.userId)
|
||||||
|
|
||||||
# Prepare request
|
# Prepare request
|
||||||
if type == "GET":
|
if action_type == "GET":
|
||||||
r = s.get(url, json=postBody, params=parameters, timeout=timeout)
|
r = s.get(url, json=postBody, params=parameters, timeout=self.timeout)
|
||||||
elif type == "POST":
|
elif action_type == "POST":
|
||||||
r = s.post(url, json=postBody, timeout=timeout)
|
r = s.post(url, json=postBody, timeout=self.timeout)
|
||||||
elif type == "DELETE":
|
elif action_type == "DELETE":
|
||||||
r = s.delete(url, json=postBody, timeout=timeout)
|
r = s.delete(url, json=postBody, timeout=self.timeout)
|
||||||
|
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
# request session does not exists
|
# request session does not exists
|
||||||
|
@ -266,26 +261,26 @@ class DownloadUtils():
|
||||||
url = url.replace("{UserId}", self.userId)
|
url = url.replace("{UserId}", self.userId)
|
||||||
|
|
||||||
# Prepare request
|
# Prepare request
|
||||||
if type == "GET":
|
if action_type == "GET":
|
||||||
r = requests.get(url,
|
r = requests.get(url,
|
||||||
json=postBody,
|
json=postBody,
|
||||||
params=parameters,
|
params=parameters,
|
||||||
headers=header,
|
headers=header,
|
||||||
timeout=timeout,
|
timeout=self.timeout,
|
||||||
verify=verifyssl)
|
verify=verifyssl)
|
||||||
|
|
||||||
elif type == "POST":
|
elif action_type == "POST":
|
||||||
r = requests.post(url,
|
r = requests.post(url,
|
||||||
json=postBody,
|
json=postBody,
|
||||||
headers=header,
|
headers=header,
|
||||||
timeout=timeout,
|
timeout=self.timeout,
|
||||||
verify=verifyssl)
|
verify=verifyssl)
|
||||||
|
|
||||||
elif type == "DELETE":
|
elif action_type == "DELETE":
|
||||||
r = requests.delete(url,
|
r = requests.delete(url,
|
||||||
json=postBody,
|
json=postBody,
|
||||||
headers=header,
|
headers=header,
|
||||||
timeout=timeout,
|
timeout=self.timeout,
|
||||||
verify=verifyssl)
|
verify=verifyssl)
|
||||||
|
|
||||||
# If user is not authenticated
|
# If user is not authenticated
|
||||||
|
@ -303,19 +298,19 @@ class DownloadUtils():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Prepare request
|
# Prepare request
|
||||||
if type == "GET":
|
if action_type == "GET":
|
||||||
r = requests.get(url,
|
r = requests.get(url,
|
||||||
json=postBody,
|
json=postBody,
|
||||||
params=parameters,
|
params=parameters,
|
||||||
headers=header,
|
headers=header,
|
||||||
timeout=timeout,
|
timeout=self.timeout,
|
||||||
verify=verifyssl)
|
verify=verifyssl)
|
||||||
|
|
||||||
elif type == "POST":
|
elif action_type == "POST":
|
||||||
r = requests.post(url,
|
r = requests.post(url,
|
||||||
json=postBody,
|
json=postBody,
|
||||||
headers=header,
|
headers=header,
|
||||||
timeout=timeout,
|
timeout=self.timeout,
|
||||||
verify=verifyssl)
|
verify=verifyssl)
|
||||||
|
|
||||||
##### THE RESPONSE #####
|
##### THE RESPONSE #####
|
||||||
|
|
|
@ -25,7 +25,6 @@ class Embydb_Functions():
|
||||||
|
|
||||||
def getViews(self):
|
def getViews(self):
|
||||||
|
|
||||||
embycursor = self.embycursor
|
|
||||||
views = []
|
views = []
|
||||||
|
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
@ -33,8 +32,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])
|
||||||
|
|
||||||
|
@ -42,7 +41,6 @@ class Embydb_Functions():
|
||||||
|
|
||||||
def getView_byId(self, viewid):
|
def getView_byId(self, viewid):
|
||||||
|
|
||||||
embycursor = self.embycursor
|
|
||||||
|
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
|
@ -50,14 +48,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((
|
||||||
|
@ -66,8 +63,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({
|
||||||
|
|
||||||
|
@ -79,17 +76,15 @@ 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
|
||||||
|
@ -129,8 +124,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",
|
||||||
|
@ -138,45 +131,35 @@ 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 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",
|
||||||
|
@ -184,15 +167,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",
|
||||||
|
@ -200,15 +179,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",
|
||||||
|
@ -216,39 +191,31 @@ 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
|
||||||
|
|
|
@ -67,12 +67,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)
|
||||||
|
@ -166,7 +166,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():
|
||||||
|
@ -221,7 +221,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,
|
||||||
|
@ -254,7 +254,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,
|
||||||
|
@ -483,12 +483,11 @@ 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()
|
||||||
|
@ -496,46 +495,47 @@ def BrowseContent(viewname, type="", folderid=""):
|
||||||
|
|
||||||
#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
|
||||||
if not folderid:
|
if not folderid:
|
||||||
views = emby.getViews(type)
|
views = emby.getViews(browse_type)
|
||||||
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
|
||||||
|
|
||||||
if viewname is not None:
|
if viewname is not None:
|
||||||
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')))
|
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)
|
||||||
|
|
||||||
|
@ -545,14 +545,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)
|
||||||
|
|
|
@ -176,8 +176,8 @@ class InitialSetup():
|
||||||
sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_LOOP, 1)
|
sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_LOOP, 1)
|
||||||
sock.setsockopt(socket.IPPROTO_IP, socket.SO_REUSEADDR, 1)
|
sock.setsockopt(socket.IPPROTO_IP, socket.SO_REUSEADDR, 1)
|
||||||
|
|
||||||
self.logMsg("MultiGroup : %s" % str(MULTI_GROUP), 2);
|
self.logMsg("MultiGroup : %s" % str(MULTI_GROUP), 2)
|
||||||
self.logMsg("Sending UDP Data: %s" % MESSAGE, 2);
|
self.logMsg("Sending UDP Data: %s" % MESSAGE, 2)
|
||||||
sock.sendto(MESSAGE, MULTI_GROUP)
|
sock.sendto(MESSAGE, MULTI_GROUP)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -249,10 +249,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)
|
||||||
|
|
||||||
|
@ -261,7 +260,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 = api.API(item)
|
API = api.API(item)
|
||||||
|
|
||||||
|
@ -423,9 +421,9 @@ class Movies(Items):
|
||||||
self.logMsg("ADD movie itemid: %s - Title: %s" % (itemid, title), 1)
|
self.logMsg("ADD movie itemid: %s - Title: %s" % (itemid, title), 1)
|
||||||
|
|
||||||
# Add path
|
# Add path
|
||||||
pathid = kodi_db.addPath(path)
|
pathid = self.kodi_db.addPath(path)
|
||||||
# Add the file
|
# Add the file
|
||||||
fileid = kodi_db.addFile(filename, pathid)
|
fileid = self.kodi_db.addFile(filename, pathid)
|
||||||
|
|
||||||
# Create the movie entry
|
# Create the movie entry
|
||||||
query = (
|
query = (
|
||||||
|
@ -463,35 +461,34 @@ class Movies(Items):
|
||||||
kodicursor.execute(query, (pathid, filename, dateadded, fileid))
|
kodicursor.execute(query, (pathid, filename, dateadded, fileid))
|
||||||
|
|
||||||
# Process countries
|
# Process countries
|
||||||
kodi_db.addCountries(movieid, item['ProductionLocations'], "movie")
|
self.kodi_db.addCountries(movieid, item['ProductionLocations'], "movie")
|
||||||
# Process cast
|
# Process cast
|
||||||
people = artwork.getPeopleArtwork(item['People'])
|
people = artwork.getPeopleArtwork(item['People'])
|
||||||
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
|
||||||
artwork.addArtwork(artwork.getAllArtwork(item), movieid, "movie", kodicursor)
|
artwork.addArtwork(artwork.getAllArtwork(item), 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, 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 movies")
|
tags.append("Favorite movies")
|
||||||
kodi_db.addTags(movieid, tags, "movie")
|
self.kodi_db.addTags(movieid, tags, "movie")
|
||||||
# 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 add_updateBoxset(self, boxset):
|
def add_updateBoxset(self, boxset):
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
boxsetid = boxset['Id']
|
boxsetid = boxset['Id']
|
||||||
|
@ -502,7 +499,7 @@ class Movies(Items):
|
||||||
setid = emby_dbitem[0]
|
setid = emby_dbitem[0]
|
||||||
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
setid = kodi_db.createBoxset(title)
|
setid = self.kodi_db.createBoxset(title)
|
||||||
|
|
||||||
# Process artwork
|
# Process artwork
|
||||||
artwork.addArtwork(artwork.getAllArtwork(boxset), setid, "set", self.kodicursor)
|
artwork.addArtwork(artwork.getAllArtwork(boxset), setid, "set", self.kodicursor)
|
||||||
|
@ -521,8 +518,7 @@ class Movies(Items):
|
||||||
process.append(current_movie)
|
process.append(current_movie)
|
||||||
|
|
||||||
# New list to compare
|
# New list to compare
|
||||||
boxsetMovies = emby.getMovies_byBoxset(boxsetid)
|
for movie in emby.getMovies_byBoxset(boxsetid)['Items']:
|
||||||
for movie in boxsetMovies['Items']:
|
|
||||||
|
|
||||||
itemid = movie['Id']
|
itemid = movie['Id']
|
||||||
|
|
||||||
|
@ -536,7 +532,7 @@ class Movies(Items):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self.logMsg("New addition to boxset %s: %s" % (title, movie['Name']), 1)
|
self.logMsg("New addition to boxset %s: %s" % (title, movie['Name']), 1)
|
||||||
kodi_db.assignBoxset(setid, movieid)
|
self.kodi_db.assignBoxset(setid, movieid)
|
||||||
# Update emby reference
|
# Update emby reference
|
||||||
emby_db.updateParentId(itemid, setid)
|
emby_db.updateParentId(itemid, setid)
|
||||||
else:
|
else:
|
||||||
|
@ -547,7 +543,7 @@ class Movies(Items):
|
||||||
for movie in process:
|
for movie in process:
|
||||||
movieid = current[movie]
|
movieid = current[movie]
|
||||||
self.logMsg("Remove from boxset %s: %s" % (title, movieid))
|
self.logMsg("Remove from boxset %s: %s" % (title, movieid))
|
||||||
kodi_db.removefromBoxset(movieid)
|
self.kodi_db.removefromBoxset(movieid)
|
||||||
# Update emby reference
|
# Update emby reference
|
||||||
emby_db.updateParentId(movie, None)
|
emby_db.updateParentId(movie, None)
|
||||||
|
|
||||||
|
@ -558,7 +554,6 @@ class Movies(Items):
|
||||||
# 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
|
||||||
|
@ -580,9 +575,9 @@ class Movies(Items):
|
||||||
|
|
||||||
# Process favorite tags
|
# Process favorite tags
|
||||||
if userdata['Favorite']:
|
if userdata['Favorite']:
|
||||||
kodi_db.addTag(movieid, "Favorite movies", "movie")
|
self.kodi_db.addTag(movieid, "Favorite movies", "movie")
|
||||||
else:
|
else:
|
||||||
kodi_db.removeTag(movieid, "Favorite movies", "movie")
|
self.kodi_db.removeTag(movieid, "Favorite movies", "movie")
|
||||||
|
|
||||||
# Process playstates
|
# Process playstates
|
||||||
playcount = userdata['PlayCount']
|
playcount = userdata['PlayCount']
|
||||||
|
@ -592,7 +587,7 @@ class Movies(Items):
|
||||||
|
|
||||||
self.logMsg("%s New resume point: %s" % (itemid, resume))
|
self.logMsg("%s New resume point: %s" % (itemid, resume))
|
||||||
|
|
||||||
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):
|
||||||
|
@ -660,7 +655,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)
|
||||||
|
|
||||||
|
@ -851,32 +845,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
|
||||||
|
@ -898,9 +891,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']
|
||||||
|
@ -908,7 +901,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):
|
||||||
|
@ -935,8 +928,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]
|
||||||
|
@ -1009,7 +1001,6 @@ class TVShows(Items):
|
||||||
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 = api.API(item)
|
API = api.API(item)
|
||||||
|
|
||||||
|
@ -1131,7 +1122,7 @@ class TVShows(Items):
|
||||||
self.logMsg("ADD tvshow itemid: %s - Title: %s" % (itemid, title), 1)
|
self.logMsg("ADD tvshow itemid: %s - Title: %s" % (itemid, title), 1)
|
||||||
|
|
||||||
# Add top path
|
# Add top path
|
||||||
toppathid = kodi_db.addPath(toplevelpath)
|
toppathid = self.kodi_db.addPath(toplevelpath)
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
"UPDATE path",
|
"UPDATE path",
|
||||||
|
@ -1141,7 +1132,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 = (
|
||||||
|
@ -1174,26 +1165,26 @@ class TVShows(Items):
|
||||||
|
|
||||||
# Process cast
|
# Process cast
|
||||||
people = artwork.getPeopleArtwork(item['People'])
|
people = artwork.getPeopleArtwork(item['People'])
|
||||||
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
|
||||||
artwork.addArtwork(artwork.getAllArtwork(item), showid, "tvshow", kodicursor)
|
artwork.addArtwork(artwork.getAllArtwork(item), showid, "tvshow", kodicursor)
|
||||||
# Process studios
|
# Process studios
|
||||||
kodi_db.addStudios(showid, studios, "tvshow")
|
self.kodi_db.addStudios(showid, studios, "tvshow")
|
||||||
# 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 tvshows")
|
tags.append("Favorite tvshows")
|
||||||
kodi_db.addTags(showid, tags, "tvshow")
|
self.kodi_db.addTags(showid, tags, "tvshow")
|
||||||
# Process seasons
|
# Process seasons
|
||||||
all_seasons = emby.getSeasons(itemid)
|
all_seasons = emby.getSeasons(itemid)
|
||||||
for season in all_seasons['Items']:
|
for season in all_seasons['Items']:
|
||||||
self.add_updateSeason(season, showid=showid)
|
self.add_updateSeason(season, showid=showid)
|
||||||
else:
|
else:
|
||||||
# Finally, refresh the all season entry
|
# Finally, refresh the all season entry
|
||||||
seasonid = kodi_db.addSeason(showid, -1)
|
seasonid = self.kodi_db.addSeason(showid, -1)
|
||||||
# Process artwork
|
# Process artwork
|
||||||
artwork.addArtwork(artwork.getAllArtwork(item), seasonid, "season", kodicursor)
|
artwork.addArtwork(artwork.getAllArtwork(item), seasonid, "season", kodicursor)
|
||||||
|
|
||||||
|
@ -1207,11 +1198,9 @@ class TVShows(Items):
|
||||||
|
|
||||||
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 = item.get('IndexNumber', 1)
|
seasonnum = item.get('IndexNumber', 1)
|
||||||
itemid = item['Id']
|
|
||||||
|
|
||||||
if showid is None:
|
if showid is None:
|
||||||
try:
|
try:
|
||||||
|
@ -1225,21 +1214,19 @@ class TVShows(Items):
|
||||||
self.add_update(show)
|
self.add_update(show)
|
||||||
return
|
return
|
||||||
|
|
||||||
seasonid = kodi_db.addSeason(showid, seasonnum)
|
seasonid = self.kodi_db.addSeason(showid, seasonnum)
|
||||||
|
|
||||||
if item['LocationType'] != "Virtual":
|
if item['LocationType'] != "Virtual":
|
||||||
# Create the reference in emby table
|
# Create the reference in emby table
|
||||||
emby_db.addReference(itemid, seasonid, "Season", "season", parentid=showid)
|
emby_db.addReference(item['Id'], seasonid, "Season", "season", parentid=showid)
|
||||||
|
|
||||||
# Process artwork
|
# Process artwork
|
||||||
artwork.addArtwork(artwork.getAllArtwork(item), seasonid, "season", kodicursor)
|
artwork.addArtwork(artwork.getAllArtwork(item), seasonid, "season", kodicursor)
|
||||||
|
|
||||||
def add_updateEpisode(self, item):
|
def add_updateEpisode(self, item):
|
||||||
# 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 = api.API(item)
|
API = api.API(item)
|
||||||
|
|
||||||
|
@ -1336,7 +1323,7 @@ class TVShows(Items):
|
||||||
self.logMsg("Skipping: %s. Unable to add series: %s." % (itemid, seriesId))
|
self.logMsg("Skipping: %s. Unable to add series: %s." % (itemid, seriesId))
|
||||||
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 #####
|
||||||
|
@ -1384,7 +1371,7 @@ class TVShows(Items):
|
||||||
self.logMsg("UPDATE episode itemid: %s - Title: %s" % (itemid, title), 1)
|
self.logMsg("UPDATE episode itemid: %s - Title: %s" % (itemid, title), 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((
|
||||||
|
|
||||||
|
@ -1418,12 +1405,12 @@ class TVShows(Items):
|
||||||
self.logMsg("ADD episode itemid: %s - Title: %s" % (itemid, title), 1)
|
self.logMsg("ADD episode itemid: %s - Title: %s" % (itemid, title), 1)
|
||||||
|
|
||||||
# Add path
|
# Add path
|
||||||
pathid = kodi_db.addPath(path)
|
pathid = self.kodi_db.addPath(path)
|
||||||
# Add the file
|
# Add the file
|
||||||
fileid = kodi_db.addFile(filename, pathid)
|
fileid = self.kodi_db.addFile(filename, pathid)
|
||||||
|
|
||||||
# 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 = (
|
||||||
'''
|
'''
|
||||||
|
@ -1475,21 +1462,21 @@ class TVShows(Items):
|
||||||
|
|
||||||
# Process cast
|
# Process cast
|
||||||
people = artwork.getPeopleArtwork(item['People'])
|
people = artwork.getPeopleArtwork(item['People'])
|
||||||
kodi_db.addPeople(episodeid, people, "episode")
|
self.kodi_db.addPeople(episodeid, people, "episode")
|
||||||
# Process artwork
|
# Process artwork
|
||||||
artworks = artwork.getAllArtwork(item)
|
artworks = artwork.getAllArtwork(item)
|
||||||
artwork.addOrUpdateArt(artworks['Primary'], episodeid, "episode", "thumb", kodicursor)
|
artwork.addOrUpdateArt(artworks['Primary'], episodeid, "episode", "thumb", 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 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)
|
||||||
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.emby.tvshows/")
|
temppathid = self.kodi_db.getPath("plugin://plugin.video.emby.tvshows/")
|
||||||
tempfileid = kodi_db.addFile(filename, temppathid)
|
tempfileid = self.kodi_db.addFile(filename, temppathid)
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
"UPDATE files",
|
"UPDATE files",
|
||||||
|
@ -1497,13 +1484,12 @@ 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, total, playcount, dateplayed)
|
self.kodi_db.addPlaystate(tempfileid, 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
|
||||||
|
@ -1528,12 +1514,11 @@ class TVShows(Items):
|
||||||
# Process favorite tags
|
# Process favorite tags
|
||||||
if mediatype == "tvshow":
|
if mediatype == "tvshow":
|
||||||
if userdata['Favorite']:
|
if userdata['Favorite']:
|
||||||
kodi_db.addTag(kodiid, "Favorite tvshows", "tvshow")
|
self.kodi_db.addTag(kodiid, "Favorite tvshows", "tvshow")
|
||||||
else:
|
else:
|
||||||
kodi_db.removeTag(kodiid, "Favorite tvshows", "tvshow")
|
self.kodi_db.removeTag(kodiid, "Favorite tvshows", "tvshow")
|
||||||
|
elif mediatype == "episode":
|
||||||
# Process playstates
|
# Process playstates
|
||||||
if mediatype == "episode":
|
|
||||||
playcount = userdata['PlayCount']
|
playcount = userdata['PlayCount']
|
||||||
dateplayed = userdata['LastPlayedDate']
|
dateplayed = userdata['LastPlayedDate']
|
||||||
resume = API.adjustResume(userdata['Resume'])
|
resume = API.adjustResume(userdata['Resume'])
|
||||||
|
@ -1541,17 +1526,17 @@ class TVShows(Items):
|
||||||
|
|
||||||
self.logMsg("%s New resume point: %s" % (itemid, resume))
|
self.logMsg("%s New resume point: %s" % (itemid, resume))
|
||||||
|
|
||||||
kodi_db.addPlaystate(fileid, resume, total, playcount, dateplayed)
|
self.kodi_db.addPlaystate(fileid, resume, total, playcount, dateplayed)
|
||||||
if not self.directpath and not resume:
|
if not self.directpath and not resume:
|
||||||
# Make sure there's no other bookmarks created by widget.
|
# Make sure there's no other bookmarks created by widget.
|
||||||
filename = kodi_db.getFile(fileid)
|
filename = self.kodi_db.getFile(fileid)
|
||||||
kodi_db.removeFile("plugin://plugin.video.emby.tvshows/", filename)
|
self.kodi_db.removeFile("plugin://plugin.video.emby.tvshows/", filename)
|
||||||
|
|
||||||
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.
|
||||||
filename = kodi_db.getFile(fileid)
|
filename = self.kodi_db.getFile(fileid)
|
||||||
temppathid = kodi_db.getPath("plugin://plugin.video.emby.tvshows/")
|
temppathid = self.kodi_db.getPath("plugin://plugin.video.emby.tvshows/")
|
||||||
tempfileid = kodi_db.addFile(filename, temppathid)
|
tempfileid = self.kodi_db.addFile(filename, temppathid)
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
"UPDATE files",
|
"UPDATE files",
|
||||||
|
@ -1559,7 +1544,7 @@ class TVShows(Items):
|
||||||
"WHERE idFile = ?"
|
"WHERE idFile = ?"
|
||||||
))
|
))
|
||||||
self.kodicursor.execute(query, (temppathid, filename, dateadded, tempfileid))
|
self.kodicursor.execute(query, (temppathid, filename, dateadded, tempfileid))
|
||||||
kodi_db.addPlaystate(tempfileid, resume, total, playcount, dateplayed)
|
self.kodi_db.addPlaystate(tempfileid, resume, total, playcount, dateplayed)
|
||||||
|
|
||||||
emby_db.updateReference(itemid, checksum)
|
emby_db.updateReference(itemid, checksum)
|
||||||
|
|
||||||
|
@ -1672,27 +1657,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)
|
||||||
|
@ -1717,10 +1698,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
|
||||||
|
@ -1733,10 +1713,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
|
||||||
|
@ -1749,21 +1728,18 @@ 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, artisttype="MusicArtist"):
|
def add_updateArtist(self, item, artisttype="MusicArtist"):
|
||||||
# Process a single artist
|
# Process a single artist
|
||||||
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 = api.API(item)
|
API = api.API(item)
|
||||||
|
|
||||||
|
@ -1810,7 +1786,7 @@ class Music(Items):
|
||||||
self.logMsg("ADD artist itemid: %s - Name: %s" % (itemid, name), 1)
|
self.logMsg("ADD artist itemid: %s - Name: %s" % (itemid, name), 1)
|
||||||
# safety checks: It looks like Emby supports the same artist multiple times.
|
# safety checks: It looks like Emby supports the same artist multiple times.
|
||||||
# Kodi doesn't allow that. In case that happens we just merge the artist entries.
|
# Kodi doesn't allow that. In case that happens we just merge the 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(itemid, artistid, artisttype, "artist", checksum=checksum)
|
emby_db.addReference(itemid, artistid, artisttype, "artist", checksum=checksum)
|
||||||
|
|
||||||
|
@ -1843,10 +1819,8 @@ class Music(Items):
|
||||||
def add_updateAlbum(self, item):
|
def add_updateAlbum(self, item):
|
||||||
# Process a single artist
|
# Process a single artist
|
||||||
emby = self.emby
|
emby = self.emby
|
||||||
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 = api.API(item)
|
API = api.API(item)
|
||||||
|
|
||||||
|
@ -1897,13 +1871,13 @@ class Music(Items):
|
||||||
self.logMsg("ADD album itemid: %s - Name: %s" % (itemid, name), 1)
|
self.logMsg("ADD album itemid: %s - Name: %s" % (itemid, name), 1)
|
||||||
# safety checks: It looks like Emby supports the same artist multiple times.
|
# safety checks: It looks like Emby supports the same artist multiple times.
|
||||||
# Kodi doesn't allow that. In case that happens we just merge the artist entries.
|
# Kodi doesn't allow that. In case that happens we just merge the 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(itemid, albumid, "MusicAlbum", "album", checksum=checksum)
|
emby_db.addReference(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((
|
||||||
|
|
||||||
|
@ -1914,7 +1888,7 @@ class Music(Items):
|
||||||
))
|
))
|
||||||
kodicursor.execute(query, (artistname, year, genre, bio, thumb, rating, lastScraped,
|
kodicursor.execute(query, (artistname, year, genre, bio, thumb, rating, lastScraped,
|
||||||
"album", albumid))
|
"album", albumid))
|
||||||
elif kodiversion == 16:
|
elif self.kodiversion == 16:
|
||||||
# Kodi Jarvis
|
# Kodi Jarvis
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
|
@ -1925,7 +1899,7 @@ class Music(Items):
|
||||||
))
|
))
|
||||||
kodicursor.execute(query, (artistname, year, genre, bio, thumb, rating, lastScraped,
|
kodicursor.execute(query, (artistname, year, genre, bio, thumb, rating, lastScraped,
|
||||||
"album", albumid))
|
"album", albumid))
|
||||||
elif kodiversion == 15:
|
elif self.kodiversion == 15:
|
||||||
# Kodi Isengard
|
# Kodi Isengard
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
|
@ -2006,17 +1980,15 @@ class Music(Items):
|
||||||
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)
|
||||||
|
|
||||||
def add_updateSong(self, item):
|
def add_updateSong(self, item):
|
||||||
# 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 = api.API(item)
|
API = api.API(item)
|
||||||
|
|
||||||
|
@ -2122,7 +2094,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)
|
pathid = self.kodi_db.addPath(path)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Get the album
|
# Get the album
|
||||||
|
@ -2133,7 +2105,7 @@ class Music(Items):
|
||||||
album_name = item.get('Album')
|
album_name = item.get('Album')
|
||||||
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.
|
||||||
|
@ -2155,7 +2127,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 = (
|
||||||
'''
|
'''
|
||||||
|
@ -2165,7 +2137,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 = (
|
||||||
'''
|
'''
|
||||||
|
@ -2289,11 +2261,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))
|
||||||
|
@ -2303,7 +2275,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 = artwork.getAllArtwork(item, parentInfo=True)
|
allart = artwork.getAllArtwork(item, parentInfo=True)
|
||||||
|
@ -2320,7 +2292,6 @@ class Music(Items):
|
||||||
# Poster with progress bar
|
# Poster with progress bar
|
||||||
kodicursor = self.kodicursor
|
kodicursor = self.kodicursor
|
||||||
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
|
||||||
|
@ -2391,10 +2362,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]
|
||||||
|
@ -2448,23 +2418,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,))
|
|
||||||
|
|
|
@ -33,20 +33,18 @@ class Kodidb_Functions():
|
||||||
|
|
||||||
def addPath(self, path):
|
def addPath(self, path):
|
||||||
|
|
||||||
cursor = self.cursor
|
|
||||||
|
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
"SELECT idPath",
|
"SELECT idPath",
|
||||||
"FROM path",
|
"FROM path",
|
||||||
"WHERE strPath = ?"
|
"WHERE strPath = ?"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (path,))
|
self.cursor.execute(query, (path,))
|
||||||
try:
|
try:
|
||||||
pathid = cursor.fetchone()[0]
|
pathid = self.cursor.fetchone()[0]
|
||||||
except TypeError:
|
except TypeError:
|
||||||
cursor.execute("select coalesce(max(idPath),0) from path")
|
self.cursor.execute("select coalesce(max(idPath),0) from path")
|
||||||
pathid = cursor.fetchone()[0] + 1
|
pathid = self.cursor.fetchone()[0] + 1
|
||||||
query = (
|
query = (
|
||||||
'''
|
'''
|
||||||
INSERT INTO path(
|
INSERT INTO path(
|
||||||
|
@ -55,23 +53,21 @@ class Kodidb_Functions():
|
||||||
VALUES (?, ?)
|
VALUES (?, ?)
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
cursor.execute(query, (pathid, path))
|
self.cursor.execute(query, (pathid, path))
|
||||||
|
|
||||||
return pathid
|
return pathid
|
||||||
|
|
||||||
def getPath(self, path):
|
def getPath(self, path):
|
||||||
|
|
||||||
cursor = self.cursor
|
|
||||||
|
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
"SELECT idPath",
|
"SELECT idPath",
|
||||||
"FROM path",
|
"FROM path",
|
||||||
"WHERE strPath = ?"
|
"WHERE strPath = ?"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (path,))
|
self.cursor.execute(query, (path,))
|
||||||
try:
|
try:
|
||||||
pathid = cursor.fetchone()[0]
|
pathid = self.cursor.fetchone()[0]
|
||||||
except TypeError:
|
except TypeError:
|
||||||
pathid = None
|
pathid = None
|
||||||
|
|
||||||
|
@ -79,8 +75,6 @@ class Kodidb_Functions():
|
||||||
|
|
||||||
def addFile(self, filename, pathid):
|
def addFile(self, filename, pathid):
|
||||||
|
|
||||||
cursor = self.cursor
|
|
||||||
|
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
"SELECT idFile",
|
"SELECT idFile",
|
||||||
|
@ -88,12 +82,12 @@ class Kodidb_Functions():
|
||||||
"WHERE strFilename = ?",
|
"WHERE strFilename = ?",
|
||||||
"AND idPath = ?"
|
"AND idPath = ?"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (filename, pathid,))
|
self.cursor.execute(query, (filename, pathid,))
|
||||||
try:
|
try:
|
||||||
fileid = cursor.fetchone()[0]
|
fileid = self.cursor.fetchone()[0]
|
||||||
except TypeError:
|
except TypeError:
|
||||||
cursor.execute("select coalesce(max(idFile),0) from files")
|
self.cursor.execute("select coalesce(max(idFile),0) from files")
|
||||||
fileid = cursor.fetchone()[0] + 1
|
fileid = self.cursor.fetchone()[0] + 1
|
||||||
query = (
|
query = (
|
||||||
'''
|
'''
|
||||||
INSERT INTO files(
|
INSERT INTO files(
|
||||||
|
@ -102,23 +96,21 @@ class Kodidb_Functions():
|
||||||
VALUES (?, ?)
|
VALUES (?, ?)
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
cursor.execute(query, (fileid, filename))
|
self.cursor.execute(query, (fileid, filename))
|
||||||
|
|
||||||
return fileid
|
return fileid
|
||||||
|
|
||||||
def getFile(self, fileid):
|
def getFile(self, fileid):
|
||||||
|
|
||||||
cursor = self.cursor
|
|
||||||
|
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
"SELECT strFilename",
|
"SELECT strFilename",
|
||||||
"FROM files",
|
"FROM files",
|
||||||
"WHERE idFile = ?"
|
"WHERE idFile = ?"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (fileid,))
|
self.cursor.execute(query, (fileid,))
|
||||||
try:
|
try:
|
||||||
filename = cursor.fetchone()[0]
|
filename = self.cursor.fetchone()[0]
|
||||||
except TypeError:
|
except TypeError:
|
||||||
filename = ""
|
filename = ""
|
||||||
|
|
||||||
|
@ -139,8 +131,6 @@ class Kodidb_Functions():
|
||||||
|
|
||||||
def addCountries(self, kodiid, countries, mediatype):
|
def addCountries(self, kodiid, countries, mediatype):
|
||||||
|
|
||||||
cursor = self.cursor
|
|
||||||
|
|
||||||
if self.kodiversion in (15, 16, 17):
|
if self.kodiversion in (15, 16, 17):
|
||||||
# Kodi Isengard, Jarvis, Krypton
|
# Kodi Isengard, Jarvis, Krypton
|
||||||
for country in countries:
|
for country in countries:
|
||||||
|
@ -151,18 +141,18 @@ class Kodidb_Functions():
|
||||||
"WHERE name = ?",
|
"WHERE name = ?",
|
||||||
"COLLATE NOCASE"
|
"COLLATE NOCASE"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (country,))
|
self.cursor.execute(query, (country,))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
country_id = cursor.fetchone()[0]
|
country_id = self.cursor.fetchone()[0]
|
||||||
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# Country entry does not exists
|
# Country entry does not exists
|
||||||
cursor.execute("select coalesce(max(country_id),0) from country")
|
self.cursor.execute("select coalesce(max(country_id),0) from country")
|
||||||
country_id = cursor.fetchone()[0] + 1
|
country_id = self.cursor.fetchone()[0] + 1
|
||||||
|
|
||||||
query = "INSERT INTO country(country_id, name) values(?, ?)"
|
query = "INSERT INTO country(country_id, name) values(?, ?)"
|
||||||
cursor.execute(query, (country_id, country))
|
self.cursor.execute(query, (country_id, country))
|
||||||
self.logMsg("Add country to media, processing: %s" % country, 2)
|
self.logMsg("Add country to media, processing: %s" % country, 2)
|
||||||
|
|
||||||
finally: # Assign country to content
|
finally: # Assign country to content
|
||||||
|
@ -174,7 +164,7 @@ class Kodidb_Functions():
|
||||||
VALUES (?, ?, ?)
|
VALUES (?, ?, ?)
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
cursor.execute(query, (country_id, kodiid, mediatype))
|
self.cursor.execute(query, (country_id, kodiid, mediatype))
|
||||||
else:
|
else:
|
||||||
# Kodi Helix
|
# Kodi Helix
|
||||||
for country in countries:
|
for country in countries:
|
||||||
|
@ -185,18 +175,18 @@ class Kodidb_Functions():
|
||||||
"WHERE strCountry = ?",
|
"WHERE strCountry = ?",
|
||||||
"COLLATE NOCASE"
|
"COLLATE NOCASE"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (country,))
|
self.cursor.execute(query, (country,))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
idCountry = cursor.fetchone()[0]
|
idCountry = self.cursor.fetchone()[0]
|
||||||
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# Country entry does not exists
|
# Country entry does not exists
|
||||||
cursor.execute("select coalesce(max(idCountry),0) from country")
|
self.cursor.execute("select coalesce(max(idCountry),0) from country")
|
||||||
idCountry = cursor.fetchone()[0] + 1
|
idCountry = self.cursor.fetchone()[0] + 1
|
||||||
|
|
||||||
query = "INSERT INTO country(idCountry, strCountry) values(?, ?)"
|
query = "INSERT INTO country(idCountry, strCountry) values(?, ?)"
|
||||||
cursor.execute(query, (idCountry, country))
|
self.cursor.execute(query, (idCountry, country))
|
||||||
self.logMsg("Add country to media, processing: %s" % country, 2)
|
self.logMsg("Add country to media, processing: %s" % country, 2)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
|
@ -210,23 +200,19 @@ class Kodidb_Functions():
|
||||||
VALUES (?, ?)
|
VALUES (?, ?)
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
cursor.execute(query, (idCountry, kodiid))
|
self.cursor.execute(query, (idCountry, kodiid))
|
||||||
|
|
||||||
def addPeople(self, kodiid, people, mediatype):
|
def addPeople(self, kodiid, people, mediatype):
|
||||||
|
|
||||||
cursor = self.cursor
|
|
||||||
artwork = self.artwork
|
|
||||||
kodiversion = self.kodiversion
|
|
||||||
|
|
||||||
castorder = 1
|
castorder = 1
|
||||||
for person in people:
|
for person in people:
|
||||||
|
|
||||||
name = person['Name']
|
name = person['Name']
|
||||||
type = person['Type']
|
person_type = person['Type']
|
||||||
thumb = person['imageurl']
|
thumb = person['imageurl']
|
||||||
|
|
||||||
# Kodi Isengard, Jarvis, Krypton
|
# Kodi Isengard, Jarvis, Krypton
|
||||||
if kodiversion in (15, 16, 17):
|
if self.kodiversion in (15, 16, 17):
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
"SELECT actor_id",
|
"SELECT actor_id",
|
||||||
|
@ -234,23 +220,23 @@ class Kodidb_Functions():
|
||||||
"WHERE name = ?",
|
"WHERE name = ?",
|
||||||
"COLLATE NOCASE"
|
"COLLATE NOCASE"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (name,))
|
self.cursor.execute(query, (name,))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
actorid = cursor.fetchone()[0]
|
actorid = self.cursor.fetchone()[0]
|
||||||
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# Cast entry does not exists
|
# Cast entry does not exists
|
||||||
cursor.execute("select coalesce(max(actor_id),0) from actor")
|
self.cursor.execute("select coalesce(max(actor_id),0) from actor")
|
||||||
actorid = cursor.fetchone()[0] + 1
|
actorid = self.cursor.fetchone()[0] + 1
|
||||||
|
|
||||||
query = "INSERT INTO actor(actor_id, name) values(?, ?)"
|
query = "INSERT INTO actor(actor_id, name) values(?, ?)"
|
||||||
cursor.execute(query, (actorid, name))
|
self.cursor.execute(query, (actorid, name))
|
||||||
self.logMsg("Add people to media, processing: %s" % name, 2)
|
self.logMsg("Add people to media, processing: %s" % name, 2)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
# Link person to content
|
# Link person to content
|
||||||
if "Actor" in type:
|
if "Actor" in person_type:
|
||||||
role = person.get('Role')
|
role = person.get('Role')
|
||||||
query = (
|
query = (
|
||||||
'''
|
'''
|
||||||
|
@ -260,10 +246,10 @@ class Kodidb_Functions():
|
||||||
VALUES (?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?)
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
cursor.execute(query, (actorid, kodiid, mediatype, role, castorder))
|
self.cursor.execute(query, (actorid, kodiid, mediatype, role, castorder))
|
||||||
castorder += 1
|
castorder += 1
|
||||||
|
|
||||||
elif "Director" in type:
|
elif "Director" in person_type:
|
||||||
query = (
|
query = (
|
||||||
'''
|
'''
|
||||||
INSERT OR REPLACE INTO director_link(
|
INSERT OR REPLACE INTO director_link(
|
||||||
|
@ -272,9 +258,9 @@ class Kodidb_Functions():
|
||||||
VALUES (?, ?, ?)
|
VALUES (?, ?, ?)
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
cursor.execute(query, (actorid, kodiid, mediatype))
|
self.cursor.execute(query, (actorid, kodiid, mediatype))
|
||||||
|
|
||||||
elif type in ("Writing", "Writer"):
|
elif person_type in ("Writing", "Writer"):
|
||||||
query = (
|
query = (
|
||||||
'''
|
'''
|
||||||
INSERT OR REPLACE INTO writer_link(
|
INSERT OR REPLACE INTO writer_link(
|
||||||
|
@ -283,9 +269,9 @@ class Kodidb_Functions():
|
||||||
VALUES (?, ?, ?)
|
VALUES (?, ?, ?)
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
cursor.execute(query, (actorid, kodiid, mediatype))
|
self.cursor.execute(query, (actorid, kodiid, mediatype))
|
||||||
|
|
||||||
elif "Artist" in type:
|
elif "Artist" in person_type:
|
||||||
query = (
|
query = (
|
||||||
'''
|
'''
|
||||||
INSERT OR REPLACE INTO actor_link(
|
INSERT OR REPLACE INTO actor_link(
|
||||||
|
@ -294,7 +280,7 @@ class Kodidb_Functions():
|
||||||
VALUES (?, ?, ?)
|
VALUES (?, ?, ?)
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
cursor.execute(query, (actorid, kodiid, mediatype))
|
self.cursor.execute(query, (actorid, kodiid, mediatype))
|
||||||
# Kodi Helix
|
# Kodi Helix
|
||||||
else:
|
else:
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
@ -304,23 +290,23 @@ class Kodidb_Functions():
|
||||||
"WHERE strActor = ?",
|
"WHERE strActor = ?",
|
||||||
"COLLATE NOCASE"
|
"COLLATE NOCASE"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (name,))
|
self.cursor.execute(query, (name,))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
actorid = cursor.fetchone()[0]
|
actorid = self.cursor.fetchone()[0]
|
||||||
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# Cast entry does not exists
|
# Cast entry does not exists
|
||||||
cursor.execute("select coalesce(max(idActor),0) from actors")
|
self.cursor.execute("select coalesce(max(idActor),0) from actors")
|
||||||
actorid = cursor.fetchone()[0] + 1
|
actorid = self.cursor.fetchone()[0] + 1
|
||||||
|
|
||||||
query = "INSERT INTO actors(idActor, strActor) values(?, ?)"
|
query = "INSERT INTO actors(idActor, strActor) values(?, ?)"
|
||||||
cursor.execute(query, (actorid, name))
|
self.cursor.execute(query, (actorid, name))
|
||||||
self.logMsg("Add people to media, processing: %s" % name, 2)
|
self.logMsg("Add people to media, processing: %s" % name, 2)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
# Link person to content
|
# Link person to content
|
||||||
if "Actor" in type:
|
if "Actor" in person_type:
|
||||||
role = person.get('Role')
|
role = person.get('Role')
|
||||||
|
|
||||||
if "movie" in mediatype:
|
if "movie" in mediatype:
|
||||||
|
@ -352,10 +338,10 @@ class Kodidb_Functions():
|
||||||
)
|
)
|
||||||
else: return # Item is invalid
|
else: return # Item is invalid
|
||||||
|
|
||||||
cursor.execute(query, (actorid, kodiid, role, castorder))
|
self.cursor.execute(query, (actorid, kodiid, role, castorder))
|
||||||
castorder += 1
|
castorder += 1
|
||||||
|
|
||||||
elif "Director" in type:
|
elif "Director" in person_type:
|
||||||
if "movie" in mediatype:
|
if "movie" in mediatype:
|
||||||
query = (
|
query = (
|
||||||
'''
|
'''
|
||||||
|
@ -395,9 +381,9 @@ class Kodidb_Functions():
|
||||||
)
|
)
|
||||||
else: return # Item is invalid
|
else: return # Item is invalid
|
||||||
|
|
||||||
cursor.execute(query, (actorid, kodiid))
|
self.cursor.execute(query, (actorid, kodiid))
|
||||||
|
|
||||||
elif type in ("Writing", "Writer"):
|
elif person_type in ("Writing", "Writer"):
|
||||||
if "movie" in mediatype:
|
if "movie" in mediatype:
|
||||||
query = (
|
query = (
|
||||||
'''
|
'''
|
||||||
|
@ -418,9 +404,9 @@ class Kodidb_Functions():
|
||||||
)
|
)
|
||||||
else: return # Item is invalid
|
else: return # Item is invalid
|
||||||
|
|
||||||
cursor.execute(query, (actorid, kodiid))
|
self.cursor.execute(query, (actorid, kodiid))
|
||||||
|
|
||||||
elif "Artist" in type:
|
elif "Artist" in person_type:
|
||||||
query = (
|
query = (
|
||||||
'''
|
'''
|
||||||
INSERT OR REPLACE INTO artistlinkmusicvideo(
|
INSERT OR REPLACE INTO artistlinkmusicvideo(
|
||||||
|
@ -429,20 +415,19 @@ class Kodidb_Functions():
|
||||||
VALUES (?, ?)
|
VALUES (?, ?)
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
cursor.execute(query, (actorid, kodiid))
|
self.cursor.execute(query, (actorid, kodiid))
|
||||||
|
|
||||||
# Add person image to art table
|
# Add person image to art table
|
||||||
if thumb:
|
if thumb:
|
||||||
arttype = type.lower()
|
arttype = person_type.lower()
|
||||||
|
|
||||||
if "writing" in arttype:
|
if "writing" in arttype:
|
||||||
arttype = "writer"
|
arttype = "writer"
|
||||||
|
|
||||||
artwork.addOrUpdateArt(thumb, actorid, arttype, "thumb", cursor)
|
self.artwork.addOrUpdateArt(thumb, actorid, arttype, "thumb", self.cursor)
|
||||||
|
|
||||||
def addGenres(self, kodiid, genres, mediatype):
|
def addGenres(self, kodiid, genres, mediatype):
|
||||||
|
|
||||||
cursor = self.cursor
|
|
||||||
|
|
||||||
# Kodi Isengard, Jarvis, Krypton
|
# Kodi Isengard, Jarvis, Krypton
|
||||||
if self.kodiversion in (15, 16, 17):
|
if self.kodiversion in (15, 16, 17):
|
||||||
|
@ -453,7 +438,7 @@ class Kodidb_Functions():
|
||||||
"WHERE media_id = ?",
|
"WHERE media_id = ?",
|
||||||
"AND media_type = ?"
|
"AND media_type = ?"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (kodiid, mediatype,))
|
self.cursor.execute(query, (kodiid, mediatype,))
|
||||||
|
|
||||||
# Add genres
|
# Add genres
|
||||||
for genre in genres:
|
for genre in genres:
|
||||||
|
@ -465,18 +450,18 @@ class Kodidb_Functions():
|
||||||
"WHERE name = ?",
|
"WHERE name = ?",
|
||||||
"COLLATE NOCASE"
|
"COLLATE NOCASE"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (genre,))
|
self.cursor.execute(query, (genre,))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
genre_id = cursor.fetchone()[0]
|
genre_id = self.cursor.fetchone()[0]
|
||||||
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# Create genre in database
|
# Create genre in database
|
||||||
cursor.execute("select coalesce(max(genre_id),0) from genre")
|
self.cursor.execute("select coalesce(max(genre_id),0) from genre")
|
||||||
genre_id = cursor.fetchone()[0] + 1
|
genre_id = self.cursor.fetchone()[0] + 1
|
||||||
|
|
||||||
query = "INSERT INTO genre(genre_id, name) values(?, ?)"
|
query = "INSERT INTO genre(genre_id, name) values(?, ?)"
|
||||||
cursor.execute(query, (genre_id, genre))
|
self.cursor.execute(query, (genre_id, genre))
|
||||||
self.logMsg("Add Genres to media, processing: %s" % genre, 2)
|
self.logMsg("Add Genres to media, processing: %s" % genre, 2)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
|
@ -489,16 +474,16 @@ class Kodidb_Functions():
|
||||||
VALUES (?, ?, ?)
|
VALUES (?, ?, ?)
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
cursor.execute(query, (genre_id, kodiid, mediatype))
|
self.cursor.execute(query, (genre_id, kodiid, mediatype))
|
||||||
else:
|
else:
|
||||||
# Kodi Helix
|
# Kodi Helix
|
||||||
# Delete current genres for clean slate
|
# Delete current genres for clean slate
|
||||||
if "movie" in mediatype:
|
if "movie" in mediatype:
|
||||||
cursor.execute("DELETE FROM genrelinkmovie WHERE idMovie = ?", (kodiid,))
|
self.cursor.execute("DELETE FROM genrelinkmovie WHERE idMovie = ?", (kodiid,))
|
||||||
elif "tvshow" in mediatype:
|
elif "tvshow" in mediatype:
|
||||||
cursor.execute("DELETE FROM genrelinktvshow WHERE idShow = ?", (kodiid,))
|
self.cursor.execute("DELETE FROM genrelinktvshow WHERE idShow = ?", (kodiid,))
|
||||||
elif "musicvideo" in mediatype:
|
elif "musicvideo" in mediatype:
|
||||||
cursor.execute("DELETE FROM genrelinkmusicvideo WHERE idMVideo = ?", (kodiid,))
|
self.cursor.execute("DELETE FROM genrelinkmusicvideo WHERE idMVideo = ?", (kodiid,))
|
||||||
|
|
||||||
# Add genres
|
# Add genres
|
||||||
for genre in genres:
|
for genre in genres:
|
||||||
|
@ -510,18 +495,18 @@ class Kodidb_Functions():
|
||||||
"WHERE strGenre = ?",
|
"WHERE strGenre = ?",
|
||||||
"COLLATE NOCASE"
|
"COLLATE NOCASE"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (genre,))
|
self.cursor.execute(query, (genre,))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
idGenre = cursor.fetchone()[0]
|
idGenre = self.cursor.fetchone()[0]
|
||||||
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# Create genre in database
|
# Create genre in database
|
||||||
cursor.execute("select coalesce(max(idGenre),0) from genre")
|
self.cursor.execute("select coalesce(max(idGenre),0) from genre")
|
||||||
idGenre = cursor.fetchone()[0] + 1
|
idGenre = self.cursor.fetchone()[0] + 1
|
||||||
|
|
||||||
query = "INSERT INTO genre(idGenre, strGenre) values(?, ?)"
|
query = "INSERT INTO genre(idGenre, strGenre) values(?, ?)"
|
||||||
cursor.execute(query, (idGenre, genre))
|
self.cursor.execute(query, (idGenre, genre))
|
||||||
self.logMsg("Add Genres to media, processing: %s" % genre, 2)
|
self.logMsg("Add Genres to media, processing: %s" % genre, 2)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
|
@ -555,16 +540,13 @@ class Kodidb_Functions():
|
||||||
)
|
)
|
||||||
else: return # Item is invalid
|
else: return # Item is invalid
|
||||||
|
|
||||||
cursor.execute(query, (idGenre, kodiid))
|
self.cursor.execute(query, (idGenre, kodiid))
|
||||||
|
|
||||||
def addStudios(self, kodiid, studios, mediatype):
|
def addStudios(self, kodiid, studios, mediatype):
|
||||||
|
|
||||||
cursor = self.cursor
|
|
||||||
kodiversion = self.kodiversion
|
|
||||||
|
|
||||||
for studio in studios:
|
for studio in studios:
|
||||||
|
|
||||||
if kodiversion in (15, 16, 17):
|
if self.kodiversion in (15, 16, 17):
|
||||||
# Kodi Isengard, Jarvis, Krypton
|
# Kodi Isengard, Jarvis, Krypton
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
|
@ -573,17 +555,17 @@ class Kodidb_Functions():
|
||||||
"WHERE name = ?",
|
"WHERE name = ?",
|
||||||
"COLLATE NOCASE"
|
"COLLATE NOCASE"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (studio,))
|
self.cursor.execute(query, (studio,))
|
||||||
try:
|
try:
|
||||||
studioid = cursor.fetchone()[0]
|
studioid = self.cursor.fetchone()[0]
|
||||||
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# Studio does not exists.
|
# Studio does not exists.
|
||||||
cursor.execute("select coalesce(max(studio_id),0) from studio")
|
self.cursor.execute("select coalesce(max(studio_id),0) from studio")
|
||||||
studioid = cursor.fetchone()[0] + 1
|
studioid = self.cursor.fetchone()[0] + 1
|
||||||
|
|
||||||
query = "INSERT INTO studio(studio_id, name) values(?, ?)"
|
query = "INSERT INTO studio(studio_id, name) values(?, ?)"
|
||||||
cursor.execute(query, (studioid, studio))
|
self.cursor.execute(query, (studioid, studio))
|
||||||
self.logMsg("Add Studios to media, processing: %s" % studio, 2)
|
self.logMsg("Add Studios to media, processing: %s" % studio, 2)
|
||||||
|
|
||||||
finally: # Assign studio to item
|
finally: # Assign studio to item
|
||||||
|
@ -594,7 +576,7 @@ class Kodidb_Functions():
|
||||||
|
|
||||||
VALUES (?, ?, ?)
|
VALUES (?, ?, ?)
|
||||||
''')
|
''')
|
||||||
cursor.execute(query, (studioid, kodiid, mediatype))
|
self.cursor.execute(query, (studioid, kodiid, mediatype))
|
||||||
else:
|
else:
|
||||||
# Kodi Helix
|
# Kodi Helix
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
@ -604,17 +586,17 @@ class Kodidb_Functions():
|
||||||
"WHERE strstudio = ?",
|
"WHERE strstudio = ?",
|
||||||
"COLLATE NOCASE"
|
"COLLATE NOCASE"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (studio,))
|
self.cursor.execute(query, (studio,))
|
||||||
try:
|
try:
|
||||||
studioid = cursor.fetchone()[0]
|
studioid = self.cursor.fetchone()[0]
|
||||||
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# Studio does not exists.
|
# Studio does not exists.
|
||||||
cursor.execute("select coalesce(max(idstudio),0) from studio")
|
self.cursor.execute("select coalesce(max(idstudio),0) from studio")
|
||||||
studioid = cursor.fetchone()[0] + 1
|
studioid = self.cursor.fetchone()[0] + 1
|
||||||
|
|
||||||
query = "INSERT INTO studio(idstudio, strstudio) values(?, ?)"
|
query = "INSERT INTO studio(idstudio, strstudio) values(?, ?)"
|
||||||
cursor.execute(query, (studioid, studio))
|
self.cursor.execute(query, (studioid, studio))
|
||||||
self.logMsg("Add Studios to media, processing: %s" % studio, 2)
|
self.logMsg("Add Studios to media, processing: %s" % studio, 2)
|
||||||
|
|
||||||
finally: # Assign studio to item
|
finally: # Assign studio to item
|
||||||
|
@ -642,14 +624,12 @@ class Kodidb_Functions():
|
||||||
INSERT OR REPLACE INTO studiolinkepisode(idstudio, idEpisode)
|
INSERT OR REPLACE INTO studiolinkepisode(idstudio, idEpisode)
|
||||||
VALUES (?, ?)
|
VALUES (?, ?)
|
||||||
''')
|
''')
|
||||||
cursor.execute(query, (studioid, kodiid))
|
self.cursor.execute(query, (studioid, kodiid))
|
||||||
|
|
||||||
def addStreams(self, fileid, streamdetails, runtime):
|
def addStreams(self, fileid, streamdetails, runtime):
|
||||||
|
|
||||||
cursor = self.cursor
|
|
||||||
|
|
||||||
# First remove any existing entries
|
# First remove any existing entries
|
||||||
cursor.execute("DELETE FROM streamdetails WHERE idFile = ?", (fileid,))
|
self.cursor.execute("DELETE FROM streamdetails WHERE idFile = ?", (fileid,))
|
||||||
if streamdetails:
|
if streamdetails:
|
||||||
# Video details
|
# Video details
|
||||||
for videotrack in streamdetails['video']:
|
for videotrack in streamdetails['video']:
|
||||||
|
@ -662,7 +642,7 @@ class Kodidb_Functions():
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
cursor.execute(query, (fileid, 0, videotrack['codec'],
|
self.cursor.execute(query, (fileid, 0, videotrack['codec'],
|
||||||
videotrack['aspect'], videotrack['width'], videotrack['height'],
|
videotrack['aspect'], videotrack['width'], videotrack['height'],
|
||||||
runtime ,videotrack['video3DFormat']))
|
runtime ,videotrack['video3DFormat']))
|
||||||
|
|
||||||
|
@ -676,7 +656,7 @@ class Kodidb_Functions():
|
||||||
VALUES (?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?)
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
cursor.execute(query, (fileid, 1, audiotrack['codec'],
|
self.cursor.execute(query, (fileid, 1, audiotrack['codec'],
|
||||||
audiotrack['channels'], audiotrack['language']))
|
audiotrack['channels'], audiotrack['language']))
|
||||||
|
|
||||||
# Subtitles details
|
# Subtitles details
|
||||||
|
@ -689,19 +669,17 @@ class Kodidb_Functions():
|
||||||
VALUES (?, ?, ?)
|
VALUES (?, ?, ?)
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
cursor.execute(query, (fileid, 2, subtitletrack))
|
self.cursor.execute(query, (fileid, 2, subtitletrack))
|
||||||
|
|
||||||
def addPlaystate(self, fileid, resume_seconds, total_seconds, playcount, dateplayed):
|
def addPlaystate(self, fileid, resume_seconds, total_seconds, playcount, dateplayed):
|
||||||
|
|
||||||
cursor = self.cursor
|
|
||||||
|
|
||||||
# Delete existing resume point
|
# Delete existing resume point
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
"DELETE FROM bookmark",
|
"DELETE FROM bookmark",
|
||||||
"WHERE idFile = ?"
|
"WHERE idFile = ?"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (fileid,))
|
self.cursor.execute(query, (fileid,))
|
||||||
|
|
||||||
# Set watched count
|
# Set watched count
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
@ -710,12 +688,12 @@ class Kodidb_Functions():
|
||||||
"SET playCount = ?, lastPlayed = ?",
|
"SET playCount = ?, lastPlayed = ?",
|
||||||
"WHERE idFile = ?"
|
"WHERE idFile = ?"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (playcount, dateplayed, fileid))
|
self.cursor.execute(query, (playcount, dateplayed, fileid))
|
||||||
|
|
||||||
# Set the resume bookmark
|
# Set the resume bookmark
|
||||||
if resume_seconds:
|
if resume_seconds:
|
||||||
cursor.execute("select coalesce(max(idBookmark),0) from bookmark")
|
self.cursor.execute("select coalesce(max(idBookmark),0) from bookmark")
|
||||||
bookmarkId = cursor.fetchone()[0] + 1
|
bookmarkId = self.cursor.fetchone()[0] + 1
|
||||||
query = (
|
query = (
|
||||||
'''
|
'''
|
||||||
INSERT INTO bookmark(
|
INSERT INTO bookmark(
|
||||||
|
@ -724,13 +702,11 @@ class Kodidb_Functions():
|
||||||
VALUES (?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?)
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
cursor.execute(query, (bookmarkId, fileid, resume_seconds, total_seconds,
|
self.cursor.execute(query, (bookmarkId, fileid, resume_seconds, total_seconds,
|
||||||
"DVDPlayer", 1))
|
"DVDPlayer", 1))
|
||||||
|
|
||||||
def addTags(self, kodiid, tags, mediatype):
|
def addTags(self, kodiid, tags, mediatype):
|
||||||
|
|
||||||
cursor = self.cursor
|
|
||||||
|
|
||||||
# First, delete any existing tags associated to the id
|
# First, delete any existing tags associated to the id
|
||||||
if self.kodiversion in (15, 16, 17):
|
if self.kodiversion in (15, 16, 17):
|
||||||
# Kodi Isengard, Jarvis, Krypton
|
# Kodi Isengard, Jarvis, Krypton
|
||||||
|
@ -740,7 +716,7 @@ class Kodidb_Functions():
|
||||||
"WHERE media_id = ?",
|
"WHERE media_id = ?",
|
||||||
"AND media_type = ?"
|
"AND media_type = ?"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (kodiid, mediatype))
|
self.cursor.execute(query, (kodiid, mediatype))
|
||||||
else:
|
else:
|
||||||
# Kodi Helix
|
# Kodi Helix
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
@ -749,7 +725,7 @@ class Kodidb_Functions():
|
||||||
"WHERE idMedia = ?",
|
"WHERE idMedia = ?",
|
||||||
"AND media_type = ?"
|
"AND media_type = ?"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (kodiid, mediatype))
|
self.cursor.execute(query, (kodiid, mediatype))
|
||||||
|
|
||||||
# Add tags
|
# Add tags
|
||||||
self.logMsg("Adding Tags: %s" % tags, 2)
|
self.logMsg("Adding Tags: %s" % tags, 2)
|
||||||
|
@ -758,8 +734,6 @@ class Kodidb_Functions():
|
||||||
|
|
||||||
def addTag(self, kodiid, tag, mediatype):
|
def addTag(self, kodiid, tag, mediatype):
|
||||||
|
|
||||||
cursor = self.cursor
|
|
||||||
|
|
||||||
if self.kodiversion in (15, 16, 17):
|
if self.kodiversion in (15, 16, 17):
|
||||||
# Kodi Isengard, Jarvis, Krypton
|
# Kodi Isengard, Jarvis, Krypton
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
@ -769,9 +743,9 @@ class Kodidb_Functions():
|
||||||
"WHERE name = ?",
|
"WHERE name = ?",
|
||||||
"COLLATE NOCASE"
|
"COLLATE NOCASE"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (tag,))
|
self.cursor.execute(query, (tag,))
|
||||||
try:
|
try:
|
||||||
tag_id = cursor.fetchone()[0]
|
tag_id = self.cursor.fetchone()[0]
|
||||||
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# Create the tag, because it does not exist
|
# Create the tag, because it does not exist
|
||||||
|
@ -788,7 +762,7 @@ class Kodidb_Functions():
|
||||||
VALUES (?, ?, ?)
|
VALUES (?, ?, ?)
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
cursor.execute(query, (tag_id, kodiid, mediatype))
|
self.cursor.execute(query, (tag_id, kodiid, mediatype))
|
||||||
else:
|
else:
|
||||||
# Kodi Helix
|
# Kodi Helix
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
@ -798,9 +772,9 @@ class Kodidb_Functions():
|
||||||
"WHERE strTag = ?",
|
"WHERE strTag = ?",
|
||||||
"COLLATE NOCASE"
|
"COLLATE NOCASE"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (tag,))
|
self.cursor.execute(query, (tag,))
|
||||||
try:
|
try:
|
||||||
tag_id = cursor.fetchone()[0]
|
tag_id = self.cursor.fetchone()[0]
|
||||||
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# Create the tag
|
# Create the tag
|
||||||
|
@ -817,12 +791,10 @@ class Kodidb_Functions():
|
||||||
VALUES (?, ?, ?)
|
VALUES (?, ?, ?)
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
cursor.execute(query, (tag_id, kodiid, mediatype))
|
self.cursor.execute(query, (tag_id, kodiid, mediatype))
|
||||||
|
|
||||||
def createTag(self, name):
|
def createTag(self, name):
|
||||||
|
|
||||||
cursor = self.cursor
|
|
||||||
|
|
||||||
# This will create and return the tag_id
|
# This will create and return the tag_id
|
||||||
if self.kodiversion in (15, 16, 17):
|
if self.kodiversion in (15, 16, 17):
|
||||||
# Kodi Isengard, Jarvis, Krypton
|
# Kodi Isengard, Jarvis, Krypton
|
||||||
|
@ -833,16 +805,16 @@ class Kodidb_Functions():
|
||||||
"WHERE name = ?",
|
"WHERE name = ?",
|
||||||
"COLLATE NOCASE"
|
"COLLATE NOCASE"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (name,))
|
self.cursor.execute(query, (name,))
|
||||||
try:
|
try:
|
||||||
tag_id = cursor.fetchone()[0]
|
tag_id = self.cursor.fetchone()[0]
|
||||||
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
cursor.execute("select coalesce(max(tag_id),0) from tag")
|
self.cursor.execute("select coalesce(max(tag_id),0) from tag")
|
||||||
tag_id = cursor.fetchone()[0] + 1
|
tag_id = self.cursor.fetchone()[0] + 1
|
||||||
|
|
||||||
query = "INSERT INTO tag(tag_id, name) values(?, ?)"
|
query = "INSERT INTO tag(tag_id, name) values(?, ?)"
|
||||||
cursor.execute(query, (tag_id, name))
|
self.cursor.execute(query, (tag_id, name))
|
||||||
self.logMsg("Create tag_id: %s name: %s" % (tag_id, name), 2)
|
self.logMsg("Create tag_id: %s name: %s" % (tag_id, name), 2)
|
||||||
else:
|
else:
|
||||||
# Kodi Helix
|
# Kodi Helix
|
||||||
|
@ -853,23 +825,22 @@ class Kodidb_Functions():
|
||||||
"WHERE strTag = ?",
|
"WHERE strTag = ?",
|
||||||
"COLLATE NOCASE"
|
"COLLATE NOCASE"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (name,))
|
self.cursor.execute(query, (name,))
|
||||||
try:
|
try:
|
||||||
tag_id = cursor.fetchone()[0]
|
tag_id = self.cursor.fetchone()[0]
|
||||||
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
cursor.execute("select coalesce(max(idTag),0) from tag")
|
self.cursor.execute("select coalesce(max(idTag),0) from tag")
|
||||||
tag_id = cursor.fetchone()[0] + 1
|
tag_id = self.cursor.fetchone()[0] + 1
|
||||||
|
|
||||||
query = "INSERT INTO tag(idTag, strTag) values(?, ?)"
|
query = "INSERT INTO tag(idTag, strTag) values(?, ?)"
|
||||||
cursor.execute(query, (tag_id, name))
|
self.cursor.execute(query, (tag_id, name))
|
||||||
self.logMsg("Create idTag: %s name: %s" % (tag_id, name), 2)
|
self.logMsg("Create idTag: %s name: %s" % (tag_id, name), 2)
|
||||||
|
|
||||||
return tag_id
|
return tag_id
|
||||||
|
|
||||||
def updateTag(self, oldtag, newtag, kodiid, mediatype):
|
def updateTag(self, oldtag, newtag, kodiid, mediatype):
|
||||||
|
|
||||||
cursor = self.cursor
|
|
||||||
self.logMsg("Updating: %s with %s for %s: %s" % (oldtag, newtag, mediatype, kodiid), 2)
|
self.logMsg("Updating: %s with %s for %s: %s" % (oldtag, newtag, mediatype, kodiid), 2)
|
||||||
|
|
||||||
if self.kodiversion in (15, 16, 17):
|
if self.kodiversion in (15, 16, 17):
|
||||||
|
@ -883,7 +854,7 @@ class Kodidb_Functions():
|
||||||
"AND media_type = ?",
|
"AND media_type = ?",
|
||||||
"AND tag_id = ?"
|
"AND tag_id = ?"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (newtag, kodiid, mediatype, oldtag,))
|
self.cursor.execute(query, (newtag, kodiid, mediatype, oldtag,))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# The new tag we are going to apply already exists for this item
|
# The new tag we are going to apply already exists for this item
|
||||||
# delete current tag instead
|
# delete current tag instead
|
||||||
|
@ -895,7 +866,7 @@ class Kodidb_Functions():
|
||||||
"AND media_type = ?",
|
"AND media_type = ?",
|
||||||
"AND tag_id = ?"
|
"AND tag_id = ?"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (kodiid, mediatype, oldtag,))
|
self.cursor.execute(query, (kodiid, mediatype, oldtag,))
|
||||||
else:
|
else:
|
||||||
# Kodi Helix
|
# Kodi Helix
|
||||||
try:
|
try:
|
||||||
|
@ -907,7 +878,7 @@ class Kodidb_Functions():
|
||||||
"AND media_type = ?",
|
"AND media_type = ?",
|
||||||
"AND idTag = ?"
|
"AND idTag = ?"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (newtag, kodiid, mediatype, oldtag,))
|
self.cursor.execute(query, (newtag, kodiid, mediatype, oldtag,))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# The new tag we are going to apply already exists for this item
|
# The new tag we are going to apply already exists for this item
|
||||||
# delete current tag instead
|
# delete current tag instead
|
||||||
|
@ -919,12 +890,10 @@ class Kodidb_Functions():
|
||||||
"AND media_type = ?",
|
"AND media_type = ?",
|
||||||
"AND idTag = ?"
|
"AND idTag = ?"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (kodiid, mediatype, oldtag,))
|
self.cursor.execute(query, (kodiid, mediatype, oldtag,))
|
||||||
|
|
||||||
def removeTag(self, kodiid, tagname, mediatype):
|
def removeTag(self, kodiid, tagname, mediatype):
|
||||||
|
|
||||||
cursor = self.cursor
|
|
||||||
|
|
||||||
if self.kodiversion in (15, 16, 17):
|
if self.kodiversion in (15, 16, 17):
|
||||||
# Kodi Isengard, Jarvis, Krypton
|
# Kodi Isengard, Jarvis, Krypton
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
@ -934,9 +903,9 @@ class Kodidb_Functions():
|
||||||
"WHERE name = ?",
|
"WHERE name = ?",
|
||||||
"COLLATE NOCASE"
|
"COLLATE NOCASE"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (tagname,))
|
self.cursor.execute(query, (tagname,))
|
||||||
try:
|
try:
|
||||||
tag_id = cursor.fetchone()[0]
|
tag_id = self.cursor.fetchone()[0]
|
||||||
except TypeError:
|
except TypeError:
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
|
@ -947,7 +916,7 @@ class Kodidb_Functions():
|
||||||
"AND media_type = ?",
|
"AND media_type = ?",
|
||||||
"AND tag_id = ?"
|
"AND tag_id = ?"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (kodiid, mediatype, tag_id,))
|
self.cursor.execute(query, (kodiid, mediatype, tag_id,))
|
||||||
else:
|
else:
|
||||||
# Kodi Helix
|
# Kodi Helix
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
@ -957,9 +926,9 @@ class Kodidb_Functions():
|
||||||
"WHERE strTag = ?",
|
"WHERE strTag = ?",
|
||||||
"COLLATE NOCASE"
|
"COLLATE NOCASE"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (tagname,))
|
self.cursor.execute(query, (tagname,))
|
||||||
try:
|
try:
|
||||||
tag_id = cursor.fetchone()[0]
|
tag_id = self.cursor.fetchone()[0]
|
||||||
except TypeError:
|
except TypeError:
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
|
@ -970,11 +939,10 @@ class Kodidb_Functions():
|
||||||
"AND media_type = ?",
|
"AND media_type = ?",
|
||||||
"AND idTag = ?"
|
"AND idTag = ?"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (kodiid, mediatype, tag_id,))
|
self.cursor.execute(query, (kodiid, mediatype, tag_id,))
|
||||||
|
|
||||||
def createBoxset(self, boxsetname):
|
def createBoxset(self, boxsetname):
|
||||||
|
|
||||||
cursor = self.cursor
|
|
||||||
self.logMsg("Adding boxset: %s" % boxsetname, 2)
|
self.logMsg("Adding boxset: %s" % boxsetname, 2)
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
|
@ -983,16 +951,16 @@ class Kodidb_Functions():
|
||||||
"WHERE strSet = ?",
|
"WHERE strSet = ?",
|
||||||
"COLLATE NOCASE"
|
"COLLATE NOCASE"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (boxsetname,))
|
self.cursor.execute(query, (boxsetname,))
|
||||||
try:
|
try:
|
||||||
setid = cursor.fetchone()[0]
|
setid = self.cursor.fetchone()[0]
|
||||||
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
cursor.execute("select coalesce(max(idSet),0) from sets")
|
self.cursor.execute("select coalesce(max(idSet),0) from sets")
|
||||||
setid = cursor.fetchone()[0] + 1
|
setid = self.cursor.fetchone()[0] + 1
|
||||||
|
|
||||||
query = "INSERT INTO sets(idSet, strSet) values(?, ?)"
|
query = "INSERT INTO sets(idSet, strSet) values(?, ?)"
|
||||||
cursor.execute(query, (setid, boxsetname))
|
self.cursor.execute(query, (setid, boxsetname))
|
||||||
|
|
||||||
return setid
|
return setid
|
||||||
|
|
||||||
|
@ -1018,8 +986,6 @@ class Kodidb_Functions():
|
||||||
|
|
||||||
def addSeason(self, showid, seasonnumber):
|
def addSeason(self, showid, seasonnumber):
|
||||||
|
|
||||||
cursor = self.cursor
|
|
||||||
|
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
"SELECT idSeason",
|
"SELECT idSeason",
|
||||||
|
@ -1027,30 +993,28 @@ class Kodidb_Functions():
|
||||||
"WHERE idShow = ?",
|
"WHERE idShow = ?",
|
||||||
"AND season = ?"
|
"AND season = ?"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (showid, seasonnumber,))
|
self.cursor.execute(query, (showid, seasonnumber,))
|
||||||
try:
|
try:
|
||||||
seasonid = cursor.fetchone()[0]
|
seasonid = self.cursor.fetchone()[0]
|
||||||
except TypeError:
|
except TypeError:
|
||||||
cursor.execute("select coalesce(max(idSeason),0) from seasons")
|
self.cursor.execute("select coalesce(max(idSeason),0) from seasons")
|
||||||
seasonid = cursor.fetchone()[0] + 1
|
seasonid = self.cursor.fetchone()[0] + 1
|
||||||
query = "INSERT INTO seasons(idSeason, idShow, season) values(?, ?, ?)"
|
query = "INSERT INTO seasons(idSeason, idShow, season) values(?, ?, ?)"
|
||||||
cursor.execute(query, (seasonid, showid, seasonnumber))
|
self.cursor.execute(query, (seasonid, showid, seasonnumber))
|
||||||
|
|
||||||
return seasonid
|
return seasonid
|
||||||
|
|
||||||
def addArtist(self, name, musicbrainz):
|
def addArtist(self, name, musicbrainz):
|
||||||
|
|
||||||
cursor = self.cursor
|
|
||||||
|
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
"SELECT idArtist, strArtist",
|
"SELECT idArtist, strArtist",
|
||||||
"FROM artist",
|
"FROM artist",
|
||||||
"WHERE strMusicBrainzArtistID = ?"
|
"WHERE strMusicBrainzArtistID = ?"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (musicbrainz,))
|
self.cursor.execute(query, (musicbrainz,))
|
||||||
try:
|
try:
|
||||||
result = cursor.fetchone()
|
result = self.cursor.fetchone()
|
||||||
artistid = result[0]
|
artistid = result[0]
|
||||||
artistname = result[1]
|
artistname = result[1]
|
||||||
|
|
||||||
|
@ -1063,12 +1027,12 @@ class Kodidb_Functions():
|
||||||
"WHERE strArtist = ?",
|
"WHERE strArtist = ?",
|
||||||
"COLLATE NOCASE"
|
"COLLATE NOCASE"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (name,))
|
self.cursor.execute(query, (name,))
|
||||||
try:
|
try:
|
||||||
artistid = cursor.fetchone()[0]
|
artistid = self.cursor.fetchone()[0]
|
||||||
except TypeError:
|
except TypeError:
|
||||||
cursor.execute("select coalesce(max(idArtist),0) from artist")
|
self.cursor.execute("select coalesce(max(idArtist),0) from artist")
|
||||||
artistid = cursor.fetchone()[0] + 1
|
artistid = self.cursor.fetchone()[0] + 1
|
||||||
query = (
|
query = (
|
||||||
'''
|
'''
|
||||||
INSERT INTO artist(idArtist, strArtist, strMusicBrainzArtistID)
|
INSERT INTO artist(idArtist, strArtist, strMusicBrainzArtistID)
|
||||||
|
@ -1076,33 +1040,30 @@ class Kodidb_Functions():
|
||||||
VALUES (?, ?, ?)
|
VALUES (?, ?, ?)
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
cursor.execute(query, (artistid, name, musicbrainz))
|
self.cursor.execute(query, (artistid, name, musicbrainz))
|
||||||
else:
|
else:
|
||||||
if artistname != name:
|
if artistname != name:
|
||||||
query = "UPDATE artist SET strArtist = ? WHERE idArtist = ?"
|
query = "UPDATE artist SET strArtist = ? WHERE idArtist = ?"
|
||||||
cursor.execute(query, (name, artistid,))
|
self.cursor.execute(query, (name, artistid,))
|
||||||
|
|
||||||
return artistid
|
return artistid
|
||||||
|
|
||||||
def addAlbum(self, name, musicbrainz):
|
def addAlbum(self, name, musicbrainz):
|
||||||
|
|
||||||
kodiversion = self.kodiversion
|
|
||||||
cursor = self.cursor
|
|
||||||
|
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
|
||||||
"SELECT idAlbum",
|
"SELECT idAlbum",
|
||||||
"FROM album",
|
"FROM album",
|
||||||
"WHERE strMusicBrainzAlbumID = ?"
|
"WHERE strMusicBrainzAlbumID = ?"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (musicbrainz,))
|
self.cursor.execute(query, (musicbrainz,))
|
||||||
try:
|
try:
|
||||||
albumid = cursor.fetchone()[0]
|
albumid = self.cursor.fetchone()[0]
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# Create the album
|
# Create the album
|
||||||
cursor.execute("select coalesce(max(idAlbum),0) from album")
|
self.cursor.execute("select coalesce(max(idAlbum),0) from album")
|
||||||
albumid = cursor.fetchone()[0] + 1
|
albumid = self.cursor.fetchone()[0] + 1
|
||||||
if kodiversion in (15, 16, 17):
|
if self.kodiversion in (15, 16, 17):
|
||||||
query = (
|
query = (
|
||||||
'''
|
'''
|
||||||
INSERT INTO album(idAlbum, strAlbum, strMusicBrainzAlbumID, strReleaseType)
|
INSERT INTO album(idAlbum, strAlbum, strMusicBrainzAlbumID, strReleaseType)
|
||||||
|
@ -1110,7 +1071,7 @@ class Kodidb_Functions():
|
||||||
VALUES (?, ?, ?, ?)
|
VALUES (?, ?, ?, ?)
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
cursor.execute(query, (albumid, name, musicbrainz, "album"))
|
self.cursor.execute(query, (albumid, name, musicbrainz, "album"))
|
||||||
else: # Helix
|
else: # Helix
|
||||||
query = (
|
query = (
|
||||||
'''
|
'''
|
||||||
|
@ -1119,14 +1080,12 @@ class Kodidb_Functions():
|
||||||
VALUES (?, ?, ?)
|
VALUES (?, ?, ?)
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
cursor.execute(query, (albumid, name, musicbrainz))
|
self.cursor.execute(query, (albumid, name, musicbrainz))
|
||||||
|
|
||||||
return albumid
|
return albumid
|
||||||
|
|
||||||
def addMusicGenres(self, kodiid, genres, mediatype):
|
def addMusicGenres(self, kodiid, genres, mediatype):
|
||||||
|
|
||||||
cursor = self.cursor
|
|
||||||
|
|
||||||
if mediatype == "album":
|
if mediatype == "album":
|
||||||
|
|
||||||
# Delete current genres for clean slate
|
# Delete current genres for clean slate
|
||||||
|
@ -1135,7 +1094,7 @@ class Kodidb_Functions():
|
||||||
"DELETE FROM album_genre",
|
"DELETE FROM album_genre",
|
||||||
"WHERE idAlbum = ?"
|
"WHERE idAlbum = ?"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (kodiid,))
|
self.cursor.execute(query, (kodiid,))
|
||||||
|
|
||||||
for genre in genres:
|
for genre in genres:
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
@ -1145,18 +1104,18 @@ class Kodidb_Functions():
|
||||||
"WHERE strGenre = ?",
|
"WHERE strGenre = ?",
|
||||||
"COLLATE NOCASE"
|
"COLLATE NOCASE"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (genre,))
|
self.cursor.execute(query, (genre,))
|
||||||
try:
|
try:
|
||||||
genreid = cursor.fetchone()[0]
|
genreid = self.cursor.fetchone()[0]
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# Create the genre
|
# Create the genre
|
||||||
cursor.execute("select coalesce(max(idGenre),0) from genre")
|
self.cursor.execute("select coalesce(max(idGenre),0) from genre")
|
||||||
genreid = cursor.fetchone()[0] + 1
|
genreid = self.cursor.fetchone()[0] + 1
|
||||||
query = "INSERT INTO genre(idGenre, strGenre) values(?, ?)"
|
query = "INSERT INTO genre(idGenre, strGenre) values(?, ?)"
|
||||||
cursor.execute(query, (genreid, genre))
|
self.cursor.execute(query, (genreid, genre))
|
||||||
|
|
||||||
query = "INSERT OR REPLACE INTO album_genre(idGenre, idAlbum) values(?, ?)"
|
query = "INSERT OR REPLACE INTO album_genre(idGenre, idAlbum) values(?, ?)"
|
||||||
cursor.execute(query, (genreid, kodiid))
|
self.cursor.execute(query, (genreid, kodiid))
|
||||||
|
|
||||||
elif mediatype == "song":
|
elif mediatype == "song":
|
||||||
|
|
||||||
|
@ -1166,7 +1125,7 @@ class Kodidb_Functions():
|
||||||
"DELETE FROM song_genre",
|
"DELETE FROM song_genre",
|
||||||
"WHERE idSong = ?"
|
"WHERE idSong = ?"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (kodiid,))
|
self.cursor.execute(query, (kodiid,))
|
||||||
|
|
||||||
for genre in genres:
|
for genre in genres:
|
||||||
query = ' '.join((
|
query = ' '.join((
|
||||||
|
@ -1176,15 +1135,15 @@ class Kodidb_Functions():
|
||||||
"WHERE strGenre = ?",
|
"WHERE strGenre = ?",
|
||||||
"COLLATE NOCASE"
|
"COLLATE NOCASE"
|
||||||
))
|
))
|
||||||
cursor.execute(query, (genre,))
|
self.cursor.execute(query, (genre,))
|
||||||
try:
|
try:
|
||||||
genreid = cursor.fetchone()[0]
|
genreid = self.cursor.fetchone()[0]
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# Create the genre
|
# Create the genre
|
||||||
cursor.execute("select coalesce(max(idGenre),0) from genre")
|
self.cursor.execute("select coalesce(max(idGenre),0) from genre")
|
||||||
genreid = cursor.fetchone()[0] + 1
|
genreid = self.cursor.fetchone()[0] + 1
|
||||||
query = "INSERT INTO genre(idGenre, strGenre) values(?, ?)"
|
query = "INSERT INTO genre(idGenre, strGenre) values(?, ?)"
|
||||||
cursor.execute(query, (genreid, genre))
|
self.cursor.execute(query, (genreid, genre))
|
||||||
|
|
||||||
query = "INSERT OR REPLACE INTO song_genre(idGenre, idSong) values(?, ?)"
|
query = "INSERT OR REPLACE INTO song_genre(idGenre, idSong) values(?, ?)"
|
||||||
cursor.execute(query, (genreid, kodiid))
|
self.cursor.execute(query, (genreid, kodiid))
|
|
@ -82,17 +82,17 @@ 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:
|
||||||
if ((utils.settings('useDirectPaths') == "1" and not type == "song") or
|
if ((utils.settings('useDirectPaths') == "1" and not item_type == "song") or
|
||||||
(type == "song" and utils.settings('enableMusic') == "true")):
|
(item_type == "song" and utils.settings('enableMusic') == "true")):
|
||||||
# Set up properties for player
|
# Set up properties for player
|
||||||
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)
|
||||||
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:
|
||||||
|
@ -114,7 +114,7 @@ class KodiMonitor(xbmc.Monitor):
|
||||||
listItem = xbmcgui.ListItem()
|
listItem = xbmcgui.ListItem()
|
||||||
playback = pbutils.PlaybackUtils(result)
|
playback = pbutils.PlaybackUtils(result)
|
||||||
|
|
||||||
if type == "song" and utils.settings('streamMusic') == "true":
|
if item_type == "song" and utils.settings('streamMusic') == "true":
|
||||||
utils.window('emby_%s.playmethod' % playurl,
|
utils.window('emby_%s.playmethod' % playurl,
|
||||||
value="DirectStream")
|
value="DirectStream")
|
||||||
else:
|
else:
|
||||||
|
@ -132,7 +132,7 @@ 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:
|
||||||
|
@ -140,7 +140,7 @@ class KodiMonitor(xbmc.Monitor):
|
||||||
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)
|
||||||
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:
|
||||||
|
@ -154,10 +154,10 @@ class KodiMonitor(xbmc.Monitor):
|
||||||
# notify the server
|
# notify the server
|
||||||
url = "{server}/emby/Users/{UserId}/PlayedItems/%s?format=json" % itemid
|
url = "{server}/emby/Users/{UserId}/PlayedItems/%s?format=json" % itemid
|
||||||
if playcount != 0:
|
if playcount != 0:
|
||||||
doUtils.downloadUrl(url, type="POST")
|
doUtils.downloadUrl(url, action_type="POST")
|
||||||
self.logMsg("Mark as watched for itemid: %s" % itemid, 1)
|
self.logMsg("Mark as watched for itemid: %s" % itemid, 1)
|
||||||
else:
|
else:
|
||||||
doUtils.downloadUrl(url, type="DELETE")
|
doUtils.downloadUrl(url, action_type="DELETE")
|
||||||
self.logMsg("Mark as unwatched for itemid: %s" % itemid, 1)
|
self.logMsg("Mark as unwatched for itemid: %s" % itemid, 1)
|
||||||
finally:
|
finally:
|
||||||
embycursor.close()
|
embycursor.close()
|
||||||
|
@ -195,7 +195,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()'''
|
||||||
|
|
||||||
|
|
|
@ -90,6 +90,7 @@ class LibrarySync(threading.Thread):
|
||||||
if plugin['Name'] == "Emby.Kodi Sync Queue":
|
if plugin['Name'] == "Emby.Kodi Sync Queue":
|
||||||
self.logMsg("Found server plugin.", 2)
|
self.logMsg("Found server plugin.", 2)
|
||||||
completed = self.fastSync()
|
completed = self.fastSync()
|
||||||
|
break
|
||||||
|
|
||||||
if not completed:
|
if not completed:
|
||||||
# Fast sync failed or server plugin is not found
|
# Fast sync failed or server plugin is not found
|
||||||
|
@ -102,20 +103,15 @@ class LibrarySync(threading.Thread):
|
||||||
|
|
||||||
def fastSync(self):
|
def fastSync(self):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
|
|
||||||
doUtils = self.doUtils
|
|
||||||
|
|
||||||
lastSync = utils.settings('LastIncrementalSync')
|
lastSync = utils.settings('LastIncrementalSync')
|
||||||
if not lastSync:
|
if not lastSync:
|
||||||
lastSync = "2010-01-01T00:00:00Z"
|
lastSync = "2010-01-01T00:00:00Z"
|
||||||
|
|
||||||
lastSyncTime = utils.convertdate(lastSync)
|
lastSyncTime = utils.convertdate(lastSync)
|
||||||
log("Last sync run: %s" % lastSyncTime, 1)
|
self.logMsg("Last sync run: %s" % lastSyncTime, 1)
|
||||||
|
|
||||||
# get server RetentionDateTime
|
# get server RetentionDateTime
|
||||||
url = "{server}/emby/Emby.Kodi.SyncQueue/GetServerDateTime?format=json"
|
result = self.doUtils("{server}/emby/Emby.Kodi.SyncQueue/GetServerDateTime?format=json")
|
||||||
result = doUtils(url)
|
|
||||||
retention_time = "2010-01-01T00:00:00Z"
|
retention_time = "2010-01-01T00:00:00Z"
|
||||||
if result and result.get('RetentionDateTime'):
|
if result and result.get('RetentionDateTime'):
|
||||||
retention_time = result['RetentionDateTime']
|
retention_time = result['RetentionDateTime']
|
||||||
|
@ -129,16 +125,15 @@ class LibrarySync(threading.Thread):
|
||||||
'''
|
'''
|
||||||
|
|
||||||
retention_time = utils.convertdate(retention_time)
|
retention_time = utils.convertdate(retention_time)
|
||||||
log("RetentionDateTime: %s" % retention_time, 1)
|
self.logMsg("RetentionDateTime: %s" % retention_time, 1)
|
||||||
|
|
||||||
# if last sync before retention time do a full sync
|
# if last sync before retention time do a full sync
|
||||||
if retention_time > lastSyncTime:
|
if retention_time > lastSyncTime:
|
||||||
log("Fast sync server retention insufficient, fall back to full sync", 1)
|
self.logMsg("Fast sync server retention insufficient, fall back to full sync", 1)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
url = "{server}/emby/Emby.Kodi.SyncQueue/{UserId}/GetItems?format=json"
|
|
||||||
params = {'LastUpdateDT': lastSync}
|
params = {'LastUpdateDT': lastSync}
|
||||||
result = doUtils(url, parameters=params)
|
result = self.doUtils("{server}/emby/Emby.Kodi.SyncQueue/{UserId}/GetItems?format=json", parameters=params)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
processlist = {
|
processlist = {
|
||||||
|
@ -150,11 +145,11 @@ class LibrarySync(threading.Thread):
|
||||||
}
|
}
|
||||||
|
|
||||||
except (KeyError, TypeError):
|
except (KeyError, TypeError):
|
||||||
log("Failed to retrieve latest updates using fast sync.", 1)
|
self.logMsg("Failed to retrieve latest updates using fast sync.", 1)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
else:
|
else:
|
||||||
log("Fast sync changes: %s" % result, 1)
|
self.logMsg("Fast sync changes: %s" % result, 1)
|
||||||
for action in processlist:
|
for action in processlist:
|
||||||
self.triage_items(action, processlist[action])
|
self.triage_items(action, processlist[action])
|
||||||
|
|
||||||
|
@ -162,26 +157,24 @@ class LibrarySync(threading.Thread):
|
||||||
|
|
||||||
def saveLastSync(self):
|
def saveLastSync(self):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
# Save last sync time
|
# Save last sync time
|
||||||
overlap = 2
|
overlap = 2
|
||||||
|
|
||||||
url = "{server}/emby/Emby.Kodi.SyncQueue/GetServerDateTime?format=json"
|
result = self.doUtils("{server}/emby/Emby.Kodi.SyncQueue/GetServerDateTime?format=json")
|
||||||
result = self.doUtils(url)
|
|
||||||
try: # datetime fails when used more than once, TypeError
|
try: # datetime fails when used more than once, TypeError
|
||||||
server_time = result['ServerDateTime']
|
server_time = result['ServerDateTime']
|
||||||
server_time = utils.convertdate(server_time)
|
server_time = utils.convertdate(server_time)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# If the server plugin is not installed or an error happened.
|
# If the server plugin is not installed or an error happened.
|
||||||
log("An exception occurred: %s" % e, 1)
|
self.logMsg("An exception occurred: %s" % e, 1)
|
||||||
time_now = datetime.utcnow()-timedelta(minutes=overlap)
|
time_now = datetime.utcnow()-timedelta(minutes=overlap)
|
||||||
lastSync = time_now.strftime('%Y-%m-%dT%H:%M:%SZ')
|
lastSync = time_now.strftime('%Y-%m-%dT%H:%M:%SZ')
|
||||||
log("New sync time: client time -%s min: %s" % (overlap, lastSync), 1)
|
self.logMsg("New sync time: client time -%s min: %s" % (overlap, lastSync), 1)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
lastSync = (server_time - timedelta(minutes=overlap)).strftime('%Y-%m-%dT%H:%M:%SZ')
|
lastSync = (server_time - timedelta(minutes=overlap)).strftime('%Y-%m-%dT%H:%M:%SZ')
|
||||||
log("New sync time: server time -%s min: %s" % (overlap, lastSync), 1)
|
self.logMsg("New sync time: server time -%s min: %s" % (overlap, lastSync), 1)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
utils.settings('LastIncrementalSync', value=lastSync)
|
utils.settings('LastIncrementalSync', value=lastSync)
|
||||||
|
@ -197,35 +190,32 @@ class LibrarySync(threading.Thread):
|
||||||
|
|
||||||
def dbCommit(self, connection):
|
def dbCommit(self, connection):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
window = utils.window
|
window = utils.window
|
||||||
# Central commit, verifies if Kodi database update is running
|
# Central commit, verifies if Kodi database update is running
|
||||||
kodidb_scan = window('emby_kodiScan') == "true"
|
kodidb_scan = window('emby_kodiScan') == "true"
|
||||||
|
|
||||||
while kodidb_scan:
|
while kodidb_scan:
|
||||||
|
|
||||||
log("Kodi scan is running. Waiting...", 1)
|
self.logMsg("Kodi scan is running. Waiting...", 1)
|
||||||
kodidb_scan = window('emby_kodiScan') == "true"
|
kodidb_scan = window('emby_kodiScan') == "true"
|
||||||
|
|
||||||
if self.shouldStop():
|
if self.shouldStop():
|
||||||
log("Commit unsuccessful. Sync terminated.", 1)
|
self.logMsg("Commit unsuccessful. Sync terminated.", 1)
|
||||||
break
|
break
|
||||||
|
|
||||||
if self.monitor.waitForAbort(1):
|
if self.monitor.waitForAbort(1):
|
||||||
# Abort was requested while waiting. We should exit
|
# Abort was requested while waiting. We should exit
|
||||||
log("Commit unsuccessful.", 1)
|
self.logMsg("Commit unsuccessful.", 1)
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
connection.commit()
|
connection.commit()
|
||||||
log("Commit successful.", 1)
|
self.logMsg("Commit successful.", 1)
|
||||||
|
|
||||||
def fullSync(self, manualrun=False, repair=False, forceddialog=False):
|
def fullSync(self, manualrun=False, repair=False, forceddialog=False):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
window = utils.window
|
window = utils.window
|
||||||
settings = utils.settings
|
settings = utils.settings
|
||||||
# Only run once when first setting up. Can be run manually.
|
# Only run once when first setting up. Can be run manually.
|
||||||
emby = self.emby
|
|
||||||
music_enabled = utils.settings('enableMusic') == "true"
|
music_enabled = utils.settings('enableMusic') == "true"
|
||||||
|
|
||||||
xbmc.executebuiltin('InhibitIdleShutdown(true)')
|
xbmc.executebuiltin('InhibitIdleShutdown(true)')
|
||||||
|
@ -294,7 +284,7 @@ class LibrarySync(threading.Thread):
|
||||||
self.dbCommit(kodiconn)
|
self.dbCommit(kodiconn)
|
||||||
embyconn.commit()
|
embyconn.commit()
|
||||||
elapsedTime = datetime.now() - startTime
|
elapsedTime = datetime.now() - startTime
|
||||||
log("SyncDatabase (finished %s in: %s)"
|
self.logMsg("SyncDatabase (finished %s in: %s)"
|
||||||
% (itemtype, str(elapsedTime).split('.')[0]), 1)
|
% (itemtype, str(elapsedTime).split('.')[0]), 1)
|
||||||
else:
|
else:
|
||||||
# Close the Kodi cursor
|
# Close the Kodi cursor
|
||||||
|
@ -322,7 +312,7 @@ class LibrarySync(threading.Thread):
|
||||||
musicconn.commit()
|
musicconn.commit()
|
||||||
embyconn.commit()
|
embyconn.commit()
|
||||||
elapsedTime = datetime.now() - startTime
|
elapsedTime = datetime.now() - startTime
|
||||||
log("SyncDatabase (finished music in: %s)"
|
self.logMsg("SyncDatabase (finished music in: %s)"
|
||||||
% (str(elapsedTime).split('.')[0]), 1)
|
% (str(elapsedTime).split('.')[0]), 1)
|
||||||
musiccursor.close()
|
musiccursor.close()
|
||||||
|
|
||||||
|
@ -369,19 +359,15 @@ class LibrarySync(threading.Thread):
|
||||||
|
|
||||||
def maintainViews(self, embycursor, kodicursor):
|
def maintainViews(self, embycursor, kodicursor):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
# Compare the views to emby
|
# Compare the views to emby
|
||||||
emby = self.emby
|
emby = self.emby
|
||||||
emby_db = embydb.Embydb_Functions(embycursor)
|
emby_db = embydb.Embydb_Functions(embycursor)
|
||||||
kodi_db = kodidb.Kodidb_Functions(kodicursor)
|
kodi_db = kodidb.Kodidb_Functions(kodicursor)
|
||||||
doUtils = self.doUtils
|
|
||||||
vnodes = self.vnodes
|
|
||||||
|
|
||||||
# Get views
|
# Get views
|
||||||
url = "{server}/emby/Users/{UserId}/Views?format=json"
|
result = self.doUtils("{server}/emby/Users/{UserId}/Views?format=json")
|
||||||
result = doUtils(url)
|
|
||||||
grouped_views = result['Items']
|
grouped_views = result['Items']
|
||||||
ordered_views = emby.getViews(sortedlist=True)
|
ordered_views = self.emby.getViews(sortedlist=True)
|
||||||
all_views = []
|
all_views = []
|
||||||
sorted_views = []
|
sorted_views = []
|
||||||
for view in ordered_views:
|
for view in ordered_views:
|
||||||
|
@ -392,10 +378,10 @@ class LibrarySync(threading.Thread):
|
||||||
if view['type'] == "mixed":
|
if view['type'] == "mixed":
|
||||||
sorted_views.append(view['name'])
|
sorted_views.append(view['name'])
|
||||||
sorted_views.append(view['name'])
|
sorted_views.append(view['name'])
|
||||||
log("Sorted views: %s" % sorted_views, 1)
|
self.logMsg("Sorted views: %s" % sorted_views, 1)
|
||||||
|
|
||||||
# total nodes for window properties
|
# total nodes for window properties
|
||||||
vnodes.clearProperties()
|
self.vnodes.clearProperties()
|
||||||
totalnodes = len(sorted_views) + 0
|
totalnodes = len(sorted_views) + 0
|
||||||
|
|
||||||
current_views = emby_db.getViews()
|
current_views = emby_db.getViews()
|
||||||
|
@ -409,13 +395,12 @@ class LibrarySync(threading.Thread):
|
||||||
'music': "Audio",
|
'music': "Audio",
|
||||||
'photos': "Photo"
|
'photos': "Photo"
|
||||||
}
|
}
|
||||||
mediatypes = ['movies', 'tvshows', 'musicvideos', 'homevideos', 'music', 'photos']
|
for mediatype in ['movies', 'tvshows', 'musicvideos', 'homevideos', 'music', 'photos']:
|
||||||
for mediatype in mediatypes:
|
|
||||||
|
|
||||||
nodes = [] # Prevent duplicate for nodes of the same type
|
nodes = [] # Prevent duplicate for nodes of the same type
|
||||||
playlists = [] # Prevent duplicate for playlists of the same type
|
playlists = [] # Prevent duplicate for playlists of the same type
|
||||||
# Get media folders from server
|
# Get media folders from server
|
||||||
folders = emby.getViews(mediatype, root=True)
|
folders = self.emby.getViews(mediatype, root=True)
|
||||||
for folder in folders:
|
for folder in folders:
|
||||||
|
|
||||||
folderid = folder['id']
|
folderid = folder['id']
|
||||||
|
@ -424,14 +409,13 @@ class LibrarySync(threading.Thread):
|
||||||
|
|
||||||
if foldername not in all_views:
|
if foldername not in all_views:
|
||||||
# Media folders are grouped into userview
|
# Media folders are grouped into userview
|
||||||
url = "{server}/emby/Users/{UserId}/Items?format=json"
|
|
||||||
params = {
|
params = {
|
||||||
'ParentId': folderid,
|
'ParentId': folderid,
|
||||||
'Recursive': True,
|
'Recursive': True,
|
||||||
'Limit': 1,
|
'Limit': 1,
|
||||||
'IncludeItemTypes': emby_mediatypes[mediatype]
|
'IncludeItemTypes': emby_mediatypes[mediatype]
|
||||||
} # Get one item from server using the folderid
|
} # Get one item from server using the folderid
|
||||||
result = doUtils(url, parameters=params)
|
result = self.doUtils("{server}/emby/Users/{UserId}/Items?format=json", parameters=params)
|
||||||
try:
|
try:
|
||||||
verifyitem = result['Items'][0]['Id']
|
verifyitem = result['Items'][0]['Id']
|
||||||
except (TypeError, IndexError):
|
except (TypeError, IndexError):
|
||||||
|
@ -444,16 +428,16 @@ class LibrarySync(threading.Thread):
|
||||||
if (grouped_view['Type'] == "UserView" and
|
if (grouped_view['Type'] == "UserView" and
|
||||||
grouped_view.get('CollectionType') == mediatype):
|
grouped_view.get('CollectionType') == mediatype):
|
||||||
# Take the userview, and validate the item belong to the view
|
# Take the userview, and validate the item belong to the view
|
||||||
if emby.verifyView(grouped_view['Id'], verifyitem):
|
if self.emby.verifyView(grouped_view['Id'], verifyitem):
|
||||||
# Take the name of the userview
|
# Take the name of the userview
|
||||||
log("Found corresponding view: %s %s"
|
self.logMsg("Found corresponding view: %s %s"
|
||||||
% (grouped_view['Name'], grouped_view['Id']), 1)
|
% (grouped_view['Name'], grouped_view['Id']), 1)
|
||||||
foldername = grouped_view['Name']
|
foldername = grouped_view['Name']
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
# Unable to find a match, add the name to our sorted_view list
|
# Unable to find a match, add the name to our sorted_view list
|
||||||
sorted_views.append(foldername)
|
sorted_views.append(foldername)
|
||||||
log("Couldn't find corresponding grouped view: %s" % sorted_views, 1)
|
self.logMsg("Couldn't find corresponding grouped view: %s" % sorted_views, 1)
|
||||||
|
|
||||||
# Failsafe
|
# Failsafe
|
||||||
try:
|
try:
|
||||||
|
@ -469,7 +453,7 @@ class LibrarySync(threading.Thread):
|
||||||
current_tagid = view[2]
|
current_tagid = view[2]
|
||||||
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
log("Creating viewid: %s in Emby database." % folderid, 1)
|
self.logMsg("Creating viewid: %s in Emby database." % folderid, 1)
|
||||||
tagid = kodi_db.createTag(foldername)
|
tagid = kodi_db.createTag(foldername)
|
||||||
# Create playlist for the video library
|
# Create playlist for the video library
|
||||||
if (foldername not in playlists and
|
if (foldername not in playlists and
|
||||||
|
@ -478,7 +462,7 @@ class LibrarySync(threading.Thread):
|
||||||
playlists.append(foldername)
|
playlists.append(foldername)
|
||||||
# Create the video node
|
# Create the video node
|
||||||
if foldername not in nodes and mediatype not in ("musicvideos", "music"):
|
if foldername not in nodes and mediatype not in ("musicvideos", "music"):
|
||||||
vnodes.viewNode(sorted_views.index(foldername), foldername, mediatype,
|
self.vnodes.viewNode(sorted_views.index(foldername), foldername, mediatype,
|
||||||
viewtype, folderid)
|
viewtype, folderid)
|
||||||
if viewtype == "mixed": # Change the value
|
if viewtype == "mixed": # Change the value
|
||||||
sorted_views[sorted_views.index(foldername)] = "%ss" % foldername
|
sorted_views[sorted_views.index(foldername)] = "%ss" % foldername
|
||||||
|
@ -488,7 +472,7 @@ class LibrarySync(threading.Thread):
|
||||||
emby_db.addView(folderid, foldername, viewtype, tagid)
|
emby_db.addView(folderid, foldername, viewtype, tagid)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
log(' '.join((
|
self.logMsg(' '.join((
|
||||||
|
|
||||||
"Found viewid: %s" % folderid,
|
"Found viewid: %s" % folderid,
|
||||||
"viewname: %s" % current_viewname,
|
"viewname: %s" % current_viewname,
|
||||||
|
@ -504,7 +488,7 @@ class LibrarySync(threading.Thread):
|
||||||
|
|
||||||
# View was modified, update with latest info
|
# View was modified, update with latest info
|
||||||
if current_viewname != foldername:
|
if current_viewname != foldername:
|
||||||
log("viewid: %s new viewname: %s" % (folderid, foldername), 1)
|
self.logMsg("viewid: %s new viewname: %s" % (folderid, foldername), 1)
|
||||||
tagid = kodi_db.createTag(foldername)
|
tagid = kodi_db.createTag(foldername)
|
||||||
|
|
||||||
# Update view with new info
|
# Update view with new info
|
||||||
|
@ -518,7 +502,7 @@ class LibrarySync(threading.Thread):
|
||||||
mediatype, current_viewname, folderid, current_viewtype, True)
|
mediatype, current_viewname, folderid, current_viewtype, True)
|
||||||
# Delete video node
|
# Delete video node
|
||||||
if mediatype != "musicvideos":
|
if mediatype != "musicvideos":
|
||||||
vnodes.viewNode(
|
self.vnodes.viewNode(
|
||||||
indexnumber=None,
|
indexnumber=None,
|
||||||
tagname=current_viewname,
|
tagname=current_viewname,
|
||||||
mediatype=mediatype,
|
mediatype=mediatype,
|
||||||
|
@ -532,7 +516,7 @@ class LibrarySync(threading.Thread):
|
||||||
playlists.append(foldername)
|
playlists.append(foldername)
|
||||||
# Add new video node
|
# Add new video node
|
||||||
if foldername not in nodes and mediatype != "musicvideos":
|
if foldername not in nodes and mediatype != "musicvideos":
|
||||||
vnodes.viewNode(sorted_views.index(foldername), foldername,
|
self.vnodes.viewNode(sorted_views.index(foldername), foldername,
|
||||||
mediatype, viewtype, folderid)
|
mediatype, viewtype, folderid)
|
||||||
if viewtype == "mixed": # Change the value
|
if viewtype == "mixed": # Change the value
|
||||||
sorted_views[sorted_views.index(foldername)] = "%ss" % foldername
|
sorted_views[sorted_views.index(foldername)] = "%ss" % foldername
|
||||||
|
@ -554,7 +538,7 @@ class LibrarySync(threading.Thread):
|
||||||
playlists.append(foldername)
|
playlists.append(foldername)
|
||||||
# Create the video node if not already exists
|
# Create the video node if not already exists
|
||||||
if foldername not in nodes and mediatype != "musicvideos":
|
if foldername not in nodes and mediatype != "musicvideos":
|
||||||
vnodes.viewNode(sorted_views.index(foldername), foldername,
|
self.vnodes.viewNode(sorted_views.index(foldername), foldername,
|
||||||
mediatype, viewtype, folderid)
|
mediatype, viewtype, folderid)
|
||||||
if viewtype == "mixed": # Change the value
|
if viewtype == "mixed": # Change the value
|
||||||
sorted_views[sorted_views.index(foldername)] = "%ss" % foldername
|
sorted_views[sorted_views.index(foldername)] = "%ss" % foldername
|
||||||
|
@ -562,32 +546,30 @@ class LibrarySync(threading.Thread):
|
||||||
totalnodes += 1
|
totalnodes += 1
|
||||||
else:
|
else:
|
||||||
# Add video nodes listings
|
# Add video nodes listings
|
||||||
vnodes.singleNode(totalnodes, "Favorite movies", "movies", "favourites")
|
self.vnodes.singleNode(totalnodes, "Favorite movies", "movies", "favourites")
|
||||||
totalnodes += 1
|
totalnodes += 1
|
||||||
vnodes.singleNode(totalnodes, "Favorite tvshows", "tvshows", "favourites")
|
self.vnodes.singleNode(totalnodes, "Favorite tvshows", "tvshows", "favourites")
|
||||||
totalnodes += 1
|
totalnodes += 1
|
||||||
vnodes.singleNode(totalnodes, "channels", "movies", "channels")
|
self.vnodes.singleNode(totalnodes, "channels", "movies", "channels")
|
||||||
totalnodes += 1
|
totalnodes += 1
|
||||||
# Save total
|
# Save total
|
||||||
utils.window('Emby.nodes.total', str(totalnodes))
|
utils.window('Emby.nodes.total', str(totalnodes))
|
||||||
|
|
||||||
# Remove any old referenced views
|
# Remove any old referenced views
|
||||||
log("Removing views: %s" % current_views, 1)
|
self.logMsg("Removing views: %s" % current_views, 1)
|
||||||
for view in current_views:
|
for view in current_views:
|
||||||
emby_db.removeView(view)
|
emby_db.removeView(view)
|
||||||
|
|
||||||
def movies(self, embycursor, kodicursor, pdialog):
|
def movies(self, embycursor, kodicursor, pdialog):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
lang = utils.language
|
lang = utils.language
|
||||||
# Get movies from emby
|
# Get movies from emby
|
||||||
emby = self.emby
|
|
||||||
emby_db = embydb.Embydb_Functions(embycursor)
|
emby_db = embydb.Embydb_Functions(embycursor)
|
||||||
movies = itemtypes.Movies(embycursor, kodicursor)
|
movies = itemtypes.Movies(embycursor, kodicursor)
|
||||||
|
|
||||||
views = emby_db.getView_byType('movies')
|
views = emby_db.getView_byType('movies')
|
||||||
views += emby_db.getView_byType('mixed')
|
views += emby_db.getView_byType('mixed')
|
||||||
log("Media folders: %s" % views, 1)
|
self.logMsg("Media folders: %s" % views, 1)
|
||||||
|
|
||||||
##### PROCESS MOVIES #####
|
##### PROCESS MOVIES #####
|
||||||
for view in views:
|
for view in views:
|
||||||
|
@ -596,21 +578,18 @@ class LibrarySync(threading.Thread):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Get items per view
|
# Get items per view
|
||||||
viewId = view['id']
|
|
||||||
viewName = view['name']
|
|
||||||
|
|
||||||
if pdialog:
|
if pdialog:
|
||||||
pdialog.update(
|
pdialog.update(
|
||||||
heading="Emby for Kodi",
|
heading="Emby for Kodi",
|
||||||
message="%s %s..." % (lang(33017), viewName))
|
message="%s %s..." % (lang(33017), view['name']))
|
||||||
|
|
||||||
# Initial or repair sync
|
# Initial or repair sync
|
||||||
all_embymovies = emby.getMovies(viewId, dialog=pdialog)
|
all_embymovies = self.emby.getMovies(view['id'], dialog=pdialog)
|
||||||
total = all_embymovies['TotalRecordCount']
|
total = all_embymovies['TotalRecordCount']
|
||||||
embymovies = all_embymovies['Items']
|
embymovies = all_embymovies['Items']
|
||||||
|
|
||||||
if pdialog:
|
if pdialog:
|
||||||
pdialog.update(heading="Processing %s / %s items" % (viewName, total))
|
pdialog.update(heading="Processing %s / %s items" % (view['name'], total))
|
||||||
|
|
||||||
count = 0
|
count = 0
|
||||||
for embymovie in embymovies:
|
for embymovie in embymovies:
|
||||||
|
@ -623,16 +602,16 @@ class LibrarySync(threading.Thread):
|
||||||
percentage = int((float(count) / float(total))*100)
|
percentage = int((float(count) / float(total))*100)
|
||||||
pdialog.update(percentage, message=title)
|
pdialog.update(percentage, message=title)
|
||||||
count += 1
|
count += 1
|
||||||
movies.add_update(embymovie, viewName, viewId)
|
movies.add_update(embymovie, view['name'], view['id'])
|
||||||
else:
|
else:
|
||||||
log("Movies finished.", 2)
|
self.logMsg("Movies finished.", 2)
|
||||||
|
|
||||||
|
|
||||||
##### PROCESS BOXSETS #####
|
##### PROCESS BOXSETS #####
|
||||||
if pdialog:
|
if pdialog:
|
||||||
pdialog.update(heading="Emby for Kodi", message=lang(33018))
|
pdialog.update(heading="Emby for Kodi", message=lang(33018))
|
||||||
|
|
||||||
boxsets = emby.getBoxset(dialog=pdialog)
|
boxsets = self.emby.getBoxset(dialog=pdialog)
|
||||||
total = boxsets['TotalRecordCount']
|
total = boxsets['TotalRecordCount']
|
||||||
embyboxsets = boxsets['Items']
|
embyboxsets = boxsets['Items']
|
||||||
|
|
||||||
|
@ -652,20 +631,18 @@ class LibrarySync(threading.Thread):
|
||||||
count += 1
|
count += 1
|
||||||
movies.add_updateBoxset(boxset)
|
movies.add_updateBoxset(boxset)
|
||||||
else:
|
else:
|
||||||
log("Boxsets finished.", 2)
|
self.logMsg("Boxsets finished.", 2)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def musicvideos(self, embycursor, kodicursor, pdialog):
|
def musicvideos(self, embycursor, kodicursor, pdialog):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
# Get musicvideos from emby
|
# Get musicvideos from emby
|
||||||
emby = self.emby
|
|
||||||
emby_db = embydb.Embydb_Functions(embycursor)
|
emby_db = embydb.Embydb_Functions(embycursor)
|
||||||
mvideos = itemtypes.MusicVideos(embycursor, kodicursor)
|
mvideos = itemtypes.MusicVideos(embycursor, kodicursor)
|
||||||
|
|
||||||
views = emby_db.getView_byType('musicvideos')
|
views = emby_db.getView_byType('musicvideos')
|
||||||
log("Media folders: %s" % views, 1)
|
self.logMsg("Media folders: %s" % views, 1)
|
||||||
|
|
||||||
for view in views:
|
for view in views:
|
||||||
|
|
||||||
|
@ -682,7 +659,7 @@ class LibrarySync(threading.Thread):
|
||||||
message="%s %s..." % (utils.language(33019), viewName))
|
message="%s %s..." % (utils.language(33019), viewName))
|
||||||
|
|
||||||
# Initial or repair sync
|
# Initial or repair sync
|
||||||
all_embymvideos = emby.getMusicVideos(viewId, dialog=pdialog)
|
all_embymvideos = self.emby.getMusicVideos(viewId, dialog=pdialog)
|
||||||
total = all_embymvideos['TotalRecordCount']
|
total = all_embymvideos['TotalRecordCount']
|
||||||
embymvideos = all_embymvideos['Items']
|
embymvideos = all_embymvideos['Items']
|
||||||
|
|
||||||
|
@ -702,21 +679,19 @@ class LibrarySync(threading.Thread):
|
||||||
count += 1
|
count += 1
|
||||||
mvideos.add_update(embymvideo, viewName, viewId)
|
mvideos.add_update(embymvideo, viewName, viewId)
|
||||||
else:
|
else:
|
||||||
log("MusicVideos finished.", 2)
|
self.logMsg("MusicVideos finished.", 2)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def tvshows(self, embycursor, kodicursor, pdialog):
|
def tvshows(self, embycursor, kodicursor, pdialog):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
# Get shows from emby
|
# Get shows from emby
|
||||||
emby = self.emby
|
|
||||||
emby_db = embydb.Embydb_Functions(embycursor)
|
emby_db = embydb.Embydb_Functions(embycursor)
|
||||||
tvshows = itemtypes.TVShows(embycursor, kodicursor)
|
tvshows = itemtypes.TVShows(embycursor, kodicursor)
|
||||||
|
|
||||||
views = emby_db.getView_byType('tvshows')
|
views = emby_db.getView_byType('tvshows')
|
||||||
views += emby_db.getView_byType('mixed')
|
views += emby_db.getView_byType('mixed')
|
||||||
log("Media folders: %s" % views, 1)
|
self.logMsg("Media folders: %s" % views, 1)
|
||||||
|
|
||||||
for view in views:
|
for view in views:
|
||||||
|
|
||||||
|
@ -724,20 +699,17 @@ class LibrarySync(threading.Thread):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Get items per view
|
# Get items per view
|
||||||
viewId = view['id']
|
|
||||||
viewName = view['name']
|
|
||||||
|
|
||||||
if pdialog:
|
if pdialog:
|
||||||
pdialog.update(
|
pdialog.update(
|
||||||
heading="Emby for Kodi",
|
heading="Emby for Kodi",
|
||||||
message="%s %s..." % (utils.language(33020), viewName))
|
message="%s %s..." % (utils.language(33020), view['name']))
|
||||||
|
|
||||||
all_embytvshows = emby.getShows(viewId, dialog=pdialog)
|
all_embytvshows = self.emby.getShows(view['id'], dialog=pdialog)
|
||||||
total = all_embytvshows['TotalRecordCount']
|
total = all_embytvshows['TotalRecordCount']
|
||||||
embytvshows = all_embytvshows['Items']
|
embytvshows = all_embytvshows['Items']
|
||||||
|
|
||||||
if pdialog:
|
if pdialog:
|
||||||
pdialog.update(heading="Processing %s / %s items" % (viewName, total))
|
pdialog.update(heading="Processing %s / %s items" % (view['name'], total))
|
||||||
|
|
||||||
count = 0
|
count = 0
|
||||||
for embytvshow in embytvshows:
|
for embytvshow in embytvshows:
|
||||||
|
@ -745,16 +717,15 @@ class LibrarySync(threading.Thread):
|
||||||
if self.shouldStop():
|
if self.shouldStop():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
itemid = embytvshow['Id']
|
|
||||||
title = embytvshow['Name']
|
title = embytvshow['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=title)
|
||||||
count += 1
|
count += 1
|
||||||
tvshows.add_update(embytvshow, viewName, viewId)
|
tvshows.add_update(embytvshow, view['name'], view['id'])
|
||||||
|
|
||||||
# Process episodes
|
# Process episodes
|
||||||
all_episodes = emby.getEpisodesbyShow(itemid)
|
all_episodes = self.emby.getEpisodesbyShow(embytvshow['Id'])
|
||||||
for episode in all_episodes['Items']:
|
for episode in all_episodes['Items']:
|
||||||
|
|
||||||
# Process individual show
|
# Process individual show
|
||||||
|
@ -766,24 +737,22 @@ class LibrarySync(threading.Thread):
|
||||||
pdialog.update(percentage, message="%s - %s" % (title, episodetitle))
|
pdialog.update(percentage, message="%s - %s" % (title, episodetitle))
|
||||||
tvshows.add_updateEpisode(episode)
|
tvshows.add_updateEpisode(episode)
|
||||||
else:
|
else:
|
||||||
log("TVShows finished.", 2)
|
self.logMsg("TVShows finished.", 2)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def music(self, embycursor, kodicursor, pdialog):
|
def music(self, embycursor, kodicursor, pdialog):
|
||||||
# Get music from emby
|
# Get music from emby
|
||||||
emby = self.emby
|
|
||||||
emby_db = embydb.Embydb_Functions(embycursor)
|
emby_db = embydb.Embydb_Functions(embycursor)
|
||||||
music = itemtypes.Music(embycursor, kodicursor)
|
music = itemtypes.Music(embycursor, kodicursor)
|
||||||
|
|
||||||
process = {
|
process = {
|
||||||
|
|
||||||
'artists': [emby.getArtists, music.add_updateArtist],
|
'artists': [self.emby.getArtists, music.add_updateArtist],
|
||||||
'albums': [emby.getAlbums, music.add_updateAlbum],
|
'albums': [self.emby.getAlbums, music.add_updateAlbum],
|
||||||
'songs': [emby.getSongs, music.add_updateSong]
|
'songs': [self.emby.getSongs, music.add_updateSong]
|
||||||
}
|
}
|
||||||
types = ['artists', 'albums', 'songs']
|
for itemtype in ['artists', 'albums', 'songs']:
|
||||||
for itemtype in types:
|
|
||||||
|
|
||||||
if pdialog:
|
if pdialog:
|
||||||
pdialog.update(
|
pdialog.update(
|
||||||
|
@ -802,11 +771,9 @@ class LibrarySync(threading.Thread):
|
||||||
# Process individual item
|
# Process individual item
|
||||||
if self.shouldStop():
|
if self.shouldStop():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
title = embyitem['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=embyitem['Name'])
|
||||||
count += 1
|
count += 1
|
||||||
|
|
||||||
process[itemtype][1](embyitem)
|
process[itemtype][1](embyitem)
|
||||||
|
@ -837,13 +804,10 @@ class LibrarySync(threading.Thread):
|
||||||
|
|
||||||
def incrementalSync(self):
|
def incrementalSync(self):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
|
|
||||||
embyconn = utils.kodiSQL('emby')
|
embyconn = utils.kodiSQL('emby')
|
||||||
embycursor = embyconn.cursor()
|
embycursor = embyconn.cursor()
|
||||||
kodiconn = utils.kodiSQL('video')
|
kodiconn = utils.kodiSQL('video')
|
||||||
kodicursor = kodiconn.cursor()
|
kodicursor = kodiconn.cursor()
|
||||||
emby = self.emby
|
|
||||||
emby_db = embydb.Embydb_Functions(embycursor)
|
emby_db = embydb.Embydb_Functions(embycursor)
|
||||||
pDialog = None
|
pDialog = None
|
||||||
update_embydb = False
|
update_embydb = False
|
||||||
|
@ -867,28 +831,27 @@ class LibrarySync(threading.Thread):
|
||||||
'userdata': self.userdataItems,
|
'userdata': self.userdataItems,
|
||||||
'remove': self.removeItems
|
'remove': self.removeItems
|
||||||
}
|
}
|
||||||
types = ['added', 'update', 'userdata', 'remove']
|
for process_type in ['added', 'update', 'userdata', 'remove']:
|
||||||
for type in types:
|
|
||||||
|
|
||||||
if process[type] and utils.window('emby_kodiScan') != "true":
|
if process[process_type] and utils.window('emby_kodiScan') != "true":
|
||||||
|
|
||||||
listItems = list(process[type])
|
listItems = list(process[process_type])
|
||||||
del process[type][:] # Reset class list
|
del process[process_type][:] # Reset class list
|
||||||
|
|
||||||
items_process = itemtypes.Items(embycursor, kodicursor)
|
items_process = itemtypes.Items(embycursor, kodicursor)
|
||||||
update = False
|
update = False
|
||||||
|
|
||||||
# Prepare items according to process type
|
# Prepare items according to process process_type
|
||||||
if type == "added":
|
if process_type == "added":
|
||||||
items = emby.sortby_mediatype(listItems)
|
items = self.emby.sortby_mediatype(listItems)
|
||||||
|
|
||||||
elif type in ("userdata", "remove"):
|
elif process_type in ("userdata", "remove"):
|
||||||
items = emby_db.sortby_mediaType(listItems, unsorted=False)
|
items = emby_db.sortby_mediaType(listItems, unsorted=False)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
items = emby_db.sortby_mediaType(listItems)
|
items = emby_db.sortby_mediaType(listItems)
|
||||||
if items.get('Unsorted'):
|
if items.get('Unsorted'):
|
||||||
sorted_items = emby.sortby_mediatype(items['Unsorted'])
|
sorted_items = self.emby.sortby_mediatype(items['Unsorted'])
|
||||||
doupdate = items_process.itemsbyId(sorted_items, "added", pDialog)
|
doupdate = items_process.itemsbyId(sorted_items, "added", pDialog)
|
||||||
if doupdate:
|
if doupdate:
|
||||||
embyupdate, kodiupdate_video = doupdate
|
embyupdate, kodiupdate_video = doupdate
|
||||||
|
@ -898,7 +861,7 @@ class LibrarySync(threading.Thread):
|
||||||
self.forceLibraryUpdate = True
|
self.forceLibraryUpdate = True
|
||||||
del items['Unsorted']
|
del items['Unsorted']
|
||||||
|
|
||||||
doupdate = items_process.itemsbyId(items, type, pDialog)
|
doupdate = items_process.itemsbyId(items, process_type, pDialog)
|
||||||
if doupdate:
|
if doupdate:
|
||||||
embyupdate, kodiupdate_video = doupdate
|
embyupdate, kodiupdate_video = doupdate
|
||||||
if embyupdate:
|
if embyupdate:
|
||||||
|
@ -908,7 +871,7 @@ class LibrarySync(threading.Thread):
|
||||||
|
|
||||||
if update_embydb:
|
if update_embydb:
|
||||||
update_embydb = False
|
update_embydb = False
|
||||||
log("Updating emby database.", 1)
|
self.logMsg("Updating emby database.", 1)
|
||||||
embyconn.commit()
|
embyconn.commit()
|
||||||
self.saveLastSync()
|
self.saveLastSync()
|
||||||
|
|
||||||
|
@ -917,7 +880,7 @@ class LibrarySync(threading.Thread):
|
||||||
self.forceLibraryUpdate = False
|
self.forceLibraryUpdate = False
|
||||||
self.dbCommit(kodiconn)
|
self.dbCommit(kodiconn)
|
||||||
|
|
||||||
log("Updating video library.", 1)
|
self.logMsg("Updating video library.", 1)
|
||||||
utils.window('emby_kodiScan', value="true")
|
utils.window('emby_kodiScan', value="true")
|
||||||
xbmc.executebuiltin('UpdateLibrary(video)')
|
xbmc.executebuiltin('UpdateLibrary(video)')
|
||||||
|
|
||||||
|
@ -959,23 +922,21 @@ class LibrarySync(threading.Thread):
|
||||||
|
|
||||||
def run_internal(self):
|
def run_internal(self):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
lang = utils.language
|
lang = utils.language
|
||||||
window = utils.window
|
window = utils.window
|
||||||
settings = utils.settings
|
settings = utils.settings
|
||||||
dialog = xbmcgui.Dialog()
|
dialog = xbmcgui.Dialog()
|
||||||
|
|
||||||
startupComplete = False
|
startupComplete = False
|
||||||
monitor = self.monitor
|
|
||||||
|
|
||||||
log("---===### Starting LibrarySync ###===---", 0)
|
self.logMsg("---===### Starting LibrarySync ###===---", 0)
|
||||||
|
|
||||||
while not monitor.abortRequested():
|
while not self.monitor.abortRequested():
|
||||||
|
|
||||||
# In the event the server goes offline
|
# In the event the server goes offline
|
||||||
while self.suspend_thread:
|
while self.suspend_thread:
|
||||||
# Set in service.py
|
# Set in service.py
|
||||||
if monitor.waitForAbort(5):
|
if self.monitor.waitForAbort(5):
|
||||||
# Abort was requested while waiting. We should exit
|
# Abort was requested while waiting. We should exit
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -986,12 +947,12 @@ class LibrarySync(threading.Thread):
|
||||||
uptoDate = self.compareDBVersion(currentVersion, minVersion)
|
uptoDate = self.compareDBVersion(currentVersion, minVersion)
|
||||||
|
|
||||||
if not uptoDate:
|
if not uptoDate:
|
||||||
log("Database version out of date: %s minimum version required: %s"
|
self.logMsg("Database version out of date: %s minimum version required: %s"
|
||||||
% (currentVersion, minVersion), 0)
|
% (currentVersion, minVersion), 0)
|
||||||
|
|
||||||
resp = dialog.yesno("Emby for Kodi", lang(33022))
|
resp = dialog.yesno("Emby for Kodi", lang(33022))
|
||||||
if not resp:
|
if not resp:
|
||||||
log("Database version is out of date! USER IGNORED!", 0)
|
self.logMsg("Database version is out of date! USER IGNORED!", 0)
|
||||||
dialog.ok("Emby for Kodi", lang(33023))
|
dialog.ok("Emby for Kodi", lang(33023))
|
||||||
else:
|
else:
|
||||||
utils.reset()
|
utils.reset()
|
||||||
|
@ -1006,7 +967,7 @@ class LibrarySync(threading.Thread):
|
||||||
videoDb = utils.getKodiVideoDBPath()
|
videoDb = utils.getKodiVideoDBPath()
|
||||||
if not xbmcvfs.exists(videoDb):
|
if not xbmcvfs.exists(videoDb):
|
||||||
# Database does not exists
|
# Database does not exists
|
||||||
log(
|
self.logMsg(
|
||||||
"The current Kodi version is incompatible "
|
"The current Kodi version is incompatible "
|
||||||
"with the Emby for Kodi add-on. Please visit "
|
"with the Emby for Kodi add-on. Please visit "
|
||||||
"https://github.com/MediaBrowser/Emby.Kodi/wiki "
|
"https://github.com/MediaBrowser/Emby.Kodi/wiki "
|
||||||
|
@ -1018,12 +979,12 @@ class LibrarySync(threading.Thread):
|
||||||
break
|
break
|
||||||
|
|
||||||
# Run start up sync
|
# Run start up sync
|
||||||
log("Database version: %s" % settings('dbCreatedWithVersion'), 0)
|
self.logMsg("Database version: %s" % settings('dbCreatedWithVersion'), 0)
|
||||||
log("SyncDatabase (started)", 1)
|
self.logMsg("SyncDatabase (started)", 1)
|
||||||
startTime = datetime.now()
|
startTime = datetime.now()
|
||||||
librarySync = self.startSync()
|
librarySync = self.startSync()
|
||||||
elapsedTime = datetime.now() - startTime
|
elapsedTime = datetime.now() - startTime
|
||||||
log("SyncDatabase (finished in: %s) %s"
|
self.logMsg("SyncDatabase (finished in: %s) %s"
|
||||||
% (str(elapsedTime).split('.')[0], librarySync), 1)
|
% (str(elapsedTime).split('.')[0], librarySync), 1)
|
||||||
# Only try the initial sync once per kodi session regardless
|
# Only try the initial sync once per kodi session regardless
|
||||||
# This will prevent an infinite loop in case something goes wrong.
|
# This will prevent an infinite loop in case something goes wrong.
|
||||||
|
@ -1038,20 +999,20 @@ class LibrarySync(threading.Thread):
|
||||||
# Set in kodimonitor.py
|
# Set in kodimonitor.py
|
||||||
window('emby_onWake', clear=True)
|
window('emby_onWake', clear=True)
|
||||||
if window('emby_syncRunning') != "true":
|
if window('emby_syncRunning') != "true":
|
||||||
log("SyncDatabase onWake (started)", 0)
|
self.logMsg("SyncDatabase onWake (started)", 0)
|
||||||
librarySync = self.startSync()
|
librarySync = self.startSync()
|
||||||
log("SyncDatabase onWake (finished) %s" % librarySync, 0)
|
self.logMsg("SyncDatabase onWake (finished) %s" % librarySync, 0)
|
||||||
|
|
||||||
if self.stop_thread:
|
if self.stop_thread:
|
||||||
# Set in service.py
|
# Set in service.py
|
||||||
log("Service terminated thread.", 2)
|
self.logMsg("Service terminated thread.", 2)
|
||||||
break
|
break
|
||||||
|
|
||||||
if monitor.waitForAbort(1):
|
if self.monitor.waitForAbort(1):
|
||||||
# Abort was requested while waiting. We should exit
|
# Abort was requested while waiting. We should exit
|
||||||
break
|
break
|
||||||
|
|
||||||
log("###===--- LibrarySync Stopped ---===###", 0)
|
self.logMsg("###===--- LibrarySync Stopped ---===###", 0)
|
||||||
|
|
||||||
def stopThread(self):
|
def stopThread(self):
|
||||||
self.stop_thread = True
|
self.stop_thread = True
|
||||||
|
@ -1080,16 +1041,14 @@ class ManualSync(LibrarySync):
|
||||||
|
|
||||||
def movies(self, embycursor, kodicursor, pdialog):
|
def movies(self, embycursor, kodicursor, pdialog):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
lang = utils.language
|
lang = utils.language
|
||||||
# Get movies from emby
|
# Get movies from emby
|
||||||
emby = self.emby
|
|
||||||
emby_db = embydb.Embydb_Functions(embycursor)
|
emby_db = embydb.Embydb_Functions(embycursor)
|
||||||
movies = itemtypes.Movies(embycursor, kodicursor)
|
movies = itemtypes.Movies(embycursor, kodicursor)
|
||||||
|
|
||||||
views = emby_db.getView_byType('movies')
|
views = emby_db.getView_byType('movies')
|
||||||
views += emby_db.getView_byType('mixed')
|
views += emby_db.getView_byType('mixed')
|
||||||
log("Media folders: %s" % views, 1)
|
self.logMsg("Media folders: %s" % views, 1)
|
||||||
|
|
||||||
# Pull the list of movies and boxsets in Kodi
|
# Pull the list of movies and boxsets in Kodi
|
||||||
try:
|
try:
|
||||||
|
@ -1121,7 +1080,7 @@ class ManualSync(LibrarySync):
|
||||||
heading="Emby for Kodi",
|
heading="Emby for Kodi",
|
||||||
message="%s %s..." % (lang(33026), viewName))
|
message="%s %s..." % (lang(33026), viewName))
|
||||||
|
|
||||||
all_embymovies = emby.getMovies(viewId, basic=True, dialog=pdialog)
|
all_embymovies = self.emby.getMovies(viewId, basic=True, dialog=pdialog)
|
||||||
for embymovie in all_embymovies['Items']:
|
for embymovie in all_embymovies['Items']:
|
||||||
|
|
||||||
if self.shouldStop():
|
if self.shouldStop():
|
||||||
|
@ -1136,8 +1095,8 @@ class ManualSync(LibrarySync):
|
||||||
# Only update if movie is not in Kodi or checksum is different
|
# Only update if movie is not in Kodi or checksum is different
|
||||||
updatelist.append(itemid)
|
updatelist.append(itemid)
|
||||||
|
|
||||||
log("Movies to update for %s: %s" % (viewName, updatelist), 1)
|
self.logMsg("Movies to update for %s: %s" % (viewName, updatelist), 1)
|
||||||
embymovies = emby.getFullItems(updatelist)
|
embymovies = self.emby.getFullItems(updatelist)
|
||||||
total = len(updatelist)
|
total = len(updatelist)
|
||||||
del updatelist[:]
|
del updatelist[:]
|
||||||
|
|
||||||
|
@ -1150,16 +1109,15 @@ class ManualSync(LibrarySync):
|
||||||
if self.shouldStop():
|
if self.shouldStop():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
title = embymovie['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=embymovie['Name'])
|
||||||
count += 1
|
count += 1
|
||||||
movies.add_update(embymovie, viewName, viewId)
|
movies.add_update(embymovie, viewName, viewId)
|
||||||
|
|
||||||
##### PROCESS BOXSETS #####
|
##### PROCESS BOXSETS #####
|
||||||
|
|
||||||
boxsets = emby.getBoxset(dialog=pdialog)
|
boxsets = self.emby.getBoxset(dialog=pdialog)
|
||||||
embyboxsets = []
|
embyboxsets = []
|
||||||
|
|
||||||
if pdialog:
|
if pdialog:
|
||||||
|
@ -1171,16 +1129,15 @@ class ManualSync(LibrarySync):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Boxset has no real userdata, so using etag to compare
|
# Boxset has no real userdata, so using etag to compare
|
||||||
checksum = boxset['Etag']
|
|
||||||
itemid = boxset['Id']
|
itemid = boxset['Id']
|
||||||
all_embyboxsetsIds.add(itemid)
|
all_embyboxsetsIds.add(itemid)
|
||||||
|
|
||||||
if all_kodisets.get(itemid) != checksum:
|
if all_kodisets.get(itemid) != boxset['Etag']:
|
||||||
# Only update if boxset is not in Kodi or checksum is different
|
# Only update if boxset is not in Kodi or boxset['Etag'] is different
|
||||||
updatelist.append(itemid)
|
updatelist.append(itemid)
|
||||||
embyboxsets.append(boxset)
|
embyboxsets.append(boxset)
|
||||||
|
|
||||||
log("Boxsets to update: %s" % updatelist, 1)
|
self.logMsg("Boxsets to update: %s" % updatelist, 1)
|
||||||
total = len(updatelist)
|
total = len(updatelist)
|
||||||
|
|
||||||
if pdialog:
|
if pdialog:
|
||||||
|
@ -1192,10 +1149,9 @@ class ManualSync(LibrarySync):
|
||||||
if self.shouldStop():
|
if self.shouldStop():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
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
|
||||||
movies.add_updateBoxset(boxset)
|
movies.add_updateBoxset(boxset)
|
||||||
|
|
||||||
|
@ -1205,26 +1161,24 @@ class ManualSync(LibrarySync):
|
||||||
if kodimovie not in all_embymoviesIds:
|
if kodimovie not in all_embymoviesIds:
|
||||||
movies.remove(kodimovie)
|
movies.remove(kodimovie)
|
||||||
else:
|
else:
|
||||||
log("Movies compare finished.", 1)
|
self.logMsg("Movies compare finished.", 1)
|
||||||
|
|
||||||
for boxset in all_kodisets:
|
for boxset in all_kodisets:
|
||||||
if boxset not in all_embyboxsetsIds:
|
if boxset not in all_embyboxsetsIds:
|
||||||
movies.remove(boxset)
|
movies.remove(boxset)
|
||||||
else:
|
else:
|
||||||
log("Boxsets compare finished.", 1)
|
self.logMsg("Boxsets compare finished.", 1)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def musicvideos(self, embycursor, kodicursor, pdialog):
|
def musicvideos(self, embycursor, kodicursor, pdialog):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
# Get musicvideos from emby
|
# Get musicvideos from emby
|
||||||
emby = self.emby
|
|
||||||
emby_db = embydb.Embydb_Functions(embycursor)
|
emby_db = embydb.Embydb_Functions(embycursor)
|
||||||
mvideos = itemtypes.MusicVideos(embycursor, kodicursor)
|
mvideos = itemtypes.MusicVideos(embycursor, kodicursor)
|
||||||
|
|
||||||
views = emby_db.getView_byType('musicvideos')
|
views = emby_db.getView_byType('musicvideos')
|
||||||
log("Media folders: %s" % views, 1)
|
self.logMsg("Media folders: %s" % views, 1)
|
||||||
|
|
||||||
# Pull the list of musicvideos in Kodi
|
# Pull the list of musicvideos in Kodi
|
||||||
try:
|
try:
|
||||||
|
@ -1249,7 +1203,7 @@ class ManualSync(LibrarySync):
|
||||||
heading="Emby for Kodi",
|
heading="Emby for Kodi",
|
||||||
message="%s %s..." % (utils.language(33028), viewName))
|
message="%s %s..." % (utils.language(33028), viewName))
|
||||||
|
|
||||||
all_embymvideos = emby.getMusicVideos(viewId, basic=True, dialog=pdialog)
|
all_embymvideos = self.emby.getMusicVideos(viewId, basic=True, dialog=pdialog)
|
||||||
for embymvideo in all_embymvideos['Items']:
|
for embymvideo in all_embymvideos['Items']:
|
||||||
|
|
||||||
if self.shouldStop():
|
if self.shouldStop():
|
||||||
|
@ -1264,8 +1218,8 @@ class ManualSync(LibrarySync):
|
||||||
# Only update if musicvideo is not in Kodi or checksum is different
|
# Only update if musicvideo is not in Kodi or checksum is different
|
||||||
updatelist.append(itemid)
|
updatelist.append(itemid)
|
||||||
|
|
||||||
log("MusicVideos to update for %s: %s" % (viewName, updatelist), 1)
|
self.logMsg("MusicVideos to update for %s: %s" % (viewName, updatelist), 1)
|
||||||
embymvideos = emby.getFullItems(updatelist)
|
embymvideos = self.emby.getFullItems(updatelist)
|
||||||
total = len(updatelist)
|
total = len(updatelist)
|
||||||
del updatelist[:]
|
del updatelist[:]
|
||||||
|
|
||||||
|
@ -1279,10 +1233,9 @@ class ManualSync(LibrarySync):
|
||||||
if self.shouldStop():
|
if self.shouldStop():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
title = embymvideo['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=embymvideo['Name'])
|
||||||
count += 1
|
count += 1
|
||||||
mvideos.add_update(embymvideo, viewName, viewId)
|
mvideos.add_update(embymvideo, viewName, viewId)
|
||||||
|
|
||||||
|
@ -1292,22 +1245,20 @@ class ManualSync(LibrarySync):
|
||||||
if kodimvideo not in all_embymvideosIds:
|
if kodimvideo not in all_embymvideosIds:
|
||||||
mvideos.remove(kodimvideo)
|
mvideos.remove(kodimvideo)
|
||||||
else:
|
else:
|
||||||
log("MusicVideos compare finished.", 1)
|
self.logMsg("MusicVideos compare finished.", 1)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def tvshows(self, embycursor, kodicursor, pdialog):
|
def tvshows(self, embycursor, kodicursor, pdialog):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
lang = utils.language
|
lang = utils.language
|
||||||
# Get shows from emby
|
# Get shows from emby
|
||||||
emby = self.emby
|
|
||||||
emby_db = embydb.Embydb_Functions(embycursor)
|
emby_db = embydb.Embydb_Functions(embycursor)
|
||||||
tvshows = itemtypes.TVShows(embycursor, kodicursor)
|
tvshows = itemtypes.TVShows(embycursor, kodicursor)
|
||||||
|
|
||||||
views = emby_db.getView_byType('tvshows')
|
views = emby_db.getView_byType('tvshows')
|
||||||
views += emby_db.getView_byType('mixed')
|
views += emby_db.getView_byType('mixed')
|
||||||
log("Media folders: %s" % views, 1)
|
self.logMsg("Media folders: %s" % views, 1)
|
||||||
|
|
||||||
# Pull the list of tvshows and episodes in Kodi
|
# Pull the list of tvshows and episodes in Kodi
|
||||||
try:
|
try:
|
||||||
|
@ -1339,7 +1290,7 @@ class ManualSync(LibrarySync):
|
||||||
heading="Emby for Kodi",
|
heading="Emby for Kodi",
|
||||||
message="%s %s..." % (lang(33029), viewName))
|
message="%s %s..." % (lang(33029), viewName))
|
||||||
|
|
||||||
all_embytvshows = emby.getShows(viewId, basic=True, dialog=pdialog)
|
all_embytvshows = self.emby.getShows(viewId, basic=True, dialog=pdialog)
|
||||||
for embytvshow in all_embytvshows['Items']:
|
for embytvshow in all_embytvshows['Items']:
|
||||||
|
|
||||||
if self.shouldStop():
|
if self.shouldStop():
|
||||||
|
@ -1354,8 +1305,8 @@ class ManualSync(LibrarySync):
|
||||||
# Only update if movie is not in Kodi or checksum is different
|
# Only update if movie is not in Kodi or checksum is different
|
||||||
updatelist.append(itemid)
|
updatelist.append(itemid)
|
||||||
|
|
||||||
log("TVShows to update for %s: %s" % (viewName, updatelist), 1)
|
self.logMsg("TVShows to update for %s: %s" % (viewName, updatelist), 1)
|
||||||
embytvshows = emby.getFullItems(updatelist)
|
embytvshows = self.emby.getFullItems(updatelist)
|
||||||
total = len(updatelist)
|
total = len(updatelist)
|
||||||
del updatelist[:]
|
del updatelist[:]
|
||||||
|
|
||||||
|
@ -1384,7 +1335,7 @@ class ManualSync(LibrarySync):
|
||||||
heading="Emby for Kodi",
|
heading="Emby for Kodi",
|
||||||
message="%s %s..." % (lang(33030), viewName))
|
message="%s %s..." % (lang(33030), viewName))
|
||||||
|
|
||||||
all_embyepisodes = emby.getEpisodes(viewId, basic=True, dialog=pdialog)
|
all_embyepisodes = self.emby.getEpisodes(viewId, basic=True, dialog=pdialog)
|
||||||
for embyepisode in all_embyepisodes['Items']:
|
for embyepisode in all_embyepisodes['Items']:
|
||||||
|
|
||||||
if self.shouldStop():
|
if self.shouldStop():
|
||||||
|
@ -1398,8 +1349,8 @@ class ManualSync(LibrarySync):
|
||||||
# Only update if movie is not in Kodi or checksum is different
|
# Only update if movie is not in Kodi or checksum is different
|
||||||
updatelist.append(itemid)
|
updatelist.append(itemid)
|
||||||
|
|
||||||
log("Episodes to update for %s: %s" % (viewName, updatelist), 1)
|
self.logMsg("Episodes to update for %s: %s" % (viewName, updatelist), 1)
|
||||||
embyepisodes = emby.getFullItems(updatelist)
|
embyepisodes = self.emby.getFullItems(updatelist)
|
||||||
total = len(updatelist)
|
total = len(updatelist)
|
||||||
del updatelist[:]
|
del updatelist[:]
|
||||||
|
|
||||||
|
@ -1410,11 +1361,9 @@ class ManualSync(LibrarySync):
|
||||||
if self.shouldStop():
|
if self.shouldStop():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
title = episode['SeriesName']
|
|
||||||
episodetitle = episode['Name']
|
|
||||||
if pdialog:
|
if pdialog:
|
||||||
percentage = int((float(count) / float(total))*100)
|
percentage = int((float(count) / float(total))*100)
|
||||||
pdialog.update(percentage, message="%s - %s" % (title, episodetitle))
|
pdialog.update(percentage, message="%s - %s" % (episode['SeriesName'], episode['Name']))
|
||||||
count += 1
|
count += 1
|
||||||
tvshows.add_updateEpisode(episode)
|
tvshows.add_updateEpisode(episode)
|
||||||
|
|
||||||
|
@ -1424,21 +1373,19 @@ class ManualSync(LibrarySync):
|
||||||
if koditvshow not in all_embytvshowsIds:
|
if koditvshow not in all_embytvshowsIds:
|
||||||
tvshows.remove(koditvshow)
|
tvshows.remove(koditvshow)
|
||||||
else:
|
else:
|
||||||
log("TVShows compare finished.", 1)
|
self.logMsg("TVShows compare finished.", 1)
|
||||||
|
|
||||||
for kodiepisode in all_kodiepisodes:
|
for kodiepisode in all_kodiepisodes:
|
||||||
if kodiepisode not in all_embyepisodesIds:
|
if kodiepisode not in all_embyepisodesIds:
|
||||||
tvshows.remove(kodiepisode)
|
tvshows.remove(kodiepisode)
|
||||||
else:
|
else:
|
||||||
log("Episodes compare finished.", 1)
|
self.logMsg("Episodes compare finished.", 1)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def music(self, embycursor, kodicursor, pdialog):
|
def music(self, embycursor, kodicursor, pdialog):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
# Get music from emby
|
# Get music from emby
|
||||||
emby = self.emby
|
|
||||||
emby_db = embydb.Embydb_Functions(embycursor)
|
emby_db = embydb.Embydb_Functions(embycursor)
|
||||||
music = itemtypes.Music(embycursor, kodicursor)
|
music = itemtypes.Music(embycursor, kodicursor)
|
||||||
|
|
||||||
|
@ -1465,35 +1412,30 @@ class ManualSync(LibrarySync):
|
||||||
|
|
||||||
process = {
|
process = {
|
||||||
|
|
||||||
'artists': [emby.getArtists, music.add_updateArtist],
|
'artists': [self.emby.getArtists, music.add_updateArtist],
|
||||||
'albums': [emby.getAlbums, music.add_updateAlbum],
|
'albums': [self.emby.getAlbums, music.add_updateAlbum],
|
||||||
'songs': [emby.getSongs, music.add_updateSong]
|
'songs': [self.emby.getSongs, music.add_updateSong]
|
||||||
}
|
}
|
||||||
types = ['artists', 'albums', 'songs']
|
for data_type in ['artists', 'albums', 'songs']:
|
||||||
for type in types:
|
|
||||||
|
|
||||||
if pdialog:
|
if pdialog:
|
||||||
pdialog.update(
|
pdialog.update(
|
||||||
heading="Emby for Kodi",
|
heading="Emby for Kodi",
|
||||||
message="%s %s..." % (utils.language(33031), type))
|
message="%s %s..." % (utils.language(33031), data_type))
|
||||||
|
if data_type != "artists":
|
||||||
if type != "artists":
|
all_embyitems = process[data_type][0](basic=True, dialog=pdialog)
|
||||||
all_embyitems = process[type][0](basic=True, dialog=pdialog)
|
|
||||||
else:
|
else:
|
||||||
all_embyitems = process[type][0](dialog=pdialog)
|
all_embyitems = process[data_type][0](dialog=pdialog)
|
||||||
for embyitem in all_embyitems['Items']:
|
for embyitem in all_embyitems['Items']:
|
||||||
|
|
||||||
if self.shouldStop():
|
if self.shouldStop():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
API = api.API(embyitem)
|
API = api.API(embyitem)
|
||||||
itemid = embyitem['Id']
|
itemid = embyitem['Id']
|
||||||
if type == "artists":
|
if data_type == "artists":
|
||||||
all_embyartistsIds.add(itemid)
|
all_embyartistsIds.add(itemid)
|
||||||
if all_kodiartists.get(itemid) != API.getChecksum():
|
if all_kodiartists.get(itemid) != API.getChecksum():
|
||||||
# Only update if artist is not in Kodi or checksum is different
|
# Only update if artist is not in Kodi or checksum is different
|
||||||
updatelist.append(itemid)
|
updatelist.append(itemid)
|
||||||
elif type == "albums":
|
elif data_type == "albums":
|
||||||
all_embyalbumsIds.add(itemid)
|
all_embyalbumsIds.add(itemid)
|
||||||
if all_kodialbums.get(itemid) != API.getChecksum():
|
if all_kodialbums.get(itemid) != API.getChecksum():
|
||||||
# Only update if album is not in Kodi or checksum is different
|
# Only update if album is not in Kodi or checksum is different
|
||||||
|
@ -1503,47 +1445,36 @@ class ManualSync(LibrarySync):
|
||||||
if all_kodisongs.get(itemid) != API.getChecksum():
|
if all_kodisongs.get(itemid) != API.getChecksum():
|
||||||
# Only update if songs is not in Kodi or checksum is different
|
# Only update if songs is not in Kodi or checksum is different
|
||||||
updatelist.append(itemid)
|
updatelist.append(itemid)
|
||||||
|
self.logMsg("%s to update: %s" % (data_type, updatelist), 1)
|
||||||
log("%s to update: %s" % (type, updatelist), 1)
|
embyitems = self.emby.getFullItems(updatelist)
|
||||||
embyitems = emby.getFullItems(updatelist)
|
|
||||||
total = len(updatelist)
|
total = len(updatelist)
|
||||||
del updatelist[:]
|
del updatelist[:]
|
||||||
|
|
||||||
if pdialog:
|
if pdialog:
|
||||||
pdialog.update(heading="Processing %s / %s items" % (type, total))
|
pdialog.update(heading="Processing %s / %s items" % (data_type, total))
|
||||||
|
|
||||||
count = 0
|
count = 0
|
||||||
for embyitem in embyitems:
|
for embyitem in embyitems:
|
||||||
# Process individual item
|
# Process individual item
|
||||||
if self.shouldStop():
|
if self.shouldStop():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
title = embyitem['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=embyitem['Name'])
|
||||||
count += 1
|
count += 1
|
||||||
|
process[data_type][1](embyitem)
|
||||||
process[type][1](embyitem)
|
|
||||||
|
|
||||||
##### PROCESS DELETES #####
|
##### PROCESS DELETES #####
|
||||||
|
|
||||||
for kodiartist in all_kodiartists:
|
for kodiartist in all_kodiartists:
|
||||||
if kodiartist not in all_embyartistsIds and all_kodiartists[kodiartist] is not None:
|
if kodiartist not in all_embyartistsIds and all_kodiartists[kodiartist] is not None:
|
||||||
music.remove(kodiartist)
|
music.remove(kodiartist)
|
||||||
else:
|
else:
|
||||||
log("Artist compare finished.", 1)
|
self.logMsg("Artist compare finished.", 1)
|
||||||
|
|
||||||
for kodialbum in all_kodialbums:
|
for kodialbum in all_kodialbums:
|
||||||
if kodialbum not in all_embyalbumsIds:
|
if kodialbum not in all_embyalbumsIds:
|
||||||
music.remove(kodialbum)
|
music.remove(kodialbum)
|
||||||
else:
|
else:
|
||||||
log("Albums compare finished.", 1)
|
self.logMsg("Albums compare finished.", 1)
|
||||||
|
|
||||||
for kodisong in all_kodisongs:
|
for kodisong in all_kodisongs:
|
||||||
if kodisong not in all_embysongsIds:
|
if kodisong not in all_embysongsIds:
|
||||||
music.remove(kodisong)
|
music.remove(kodisong)
|
||||||
else:
|
else:
|
||||||
log("Songs compare finished.", 1)
|
self.logMsg("Songs compare finished.", 1)
|
||||||
|
|
||||||
return True
|
return True
|
|
@ -195,6 +195,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
|
||||||
|
|
|
@ -48,17 +48,13 @@ 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
|
||||||
|
|
||||||
doUtils = self.doUtils
|
|
||||||
item = self.item
|
|
||||||
API = self.API
|
|
||||||
listitem = xbmcgui.ListItem()
|
listitem = xbmcgui.ListItem()
|
||||||
playutils = putils.PlayUtils(item)
|
playutils = putils.PlayUtils(self.item)
|
||||||
|
|
||||||
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)
|
||||||
|
@ -81,32 +77,32 @@ class PlaybackUtils():
|
||||||
introsPlaylist = False
|
introsPlaylist = False
|
||||||
dummyPlaylist = False
|
dummyPlaylist = False
|
||||||
|
|
||||||
log("Playlist start position: %s" % startPos, 2)
|
self.logMsg("Playlist start position: %s" % startPos, 2)
|
||||||
log("Playlist plugin position: %s" % currentPosition, 2)
|
self.logMsg("Playlist plugin position: %s" % currentPosition, 2)
|
||||||
log("Playlist size: %s" % sizePlaylist, 2)
|
self.logMsg("Playlist size: %s" % sizePlaylist, 2)
|
||||||
|
|
||||||
############### RESUME POINT ################
|
############### RESUME POINT ################
|
||||||
|
|
||||||
userdata = API.getUserData()
|
userdata = self.API.getUserData()
|
||||||
seektime = API.adjustResume(userdata['Resume'])
|
seektime = self.API.adjustResume(userdata['Resume'])
|
||||||
|
|
||||||
# We need to ensure we add the intro and additional parts only once.
|
# We need to ensure we add the intro and additional parts only once.
|
||||||
# Otherwise we get a loop.
|
# Otherwise we get a loop.
|
||||||
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
|
||||||
self.pl.removefromPlaylist(startPos+1)
|
self.pl.removefromPlaylist(startPos+1)
|
||||||
# Readd the original item to playlist - via jsonrpc so we have full metadata
|
# Readd the original item to playlist - via jsonrpc so we have full metadata
|
||||||
self.pl.insertintoPlaylist(currentPosition+1, dbid, item['Type'].lower())
|
self.pl.insertintoPlaylist(currentPosition+1, dbid, self.item['Type'].lower())
|
||||||
currentPosition += 1
|
currentPosition += 1
|
||||||
|
|
||||||
############### -- CHECK FOR INTROS ################
|
############### -- CHECK FOR INTROS ################
|
||||||
|
@ -114,7 +110,7 @@ class PlaybackUtils():
|
||||||
if settings('enableCinema') == "true" and not seektime:
|
if settings('enableCinema') == "true" and not seektime:
|
||||||
# if we have any play them when the movie/show is not being resumed
|
# if we have any play them when the movie/show is not being resumed
|
||||||
url = "{server}/emby/Users/{UserId}/Items/%s/Intros?format=json" % itemid
|
url = "{server}/emby/Users/{UserId}/Items/%s/Intros?format=json" % itemid
|
||||||
intros = doUtils(url)
|
intros = self.doUtils(url)
|
||||||
|
|
||||||
if intros['TotalRecordCount'] != 0:
|
if intros['TotalRecordCount'] != 0:
|
||||||
getTrailers = True
|
getTrailers = True
|
||||||
|
@ -124,14 +120,14 @@ class PlaybackUtils():
|
||||||
if not resp:
|
if not resp:
|
||||||
# User selected to not play trailers
|
# User selected to not play trailers
|
||||||
getTrailers = False
|
getTrailers = False
|
||||||
log("Skip trailers.", 1)
|
self.logMsg("Skip trailers.", 1)
|
||||||
|
|
||||||
if getTrailers:
|
if getTrailers:
|
||||||
for intro in intros['Items']:
|
for intro in intros['Items']:
|
||||||
# The server randomly returns intros, process them.
|
# The server randomly returns intros, process them.
|
||||||
introListItem = xbmcgui.ListItem()
|
introListItem = xbmcgui.ListItem()
|
||||||
introPlayurl = putils.PlayUtils(intro).getPlayUrl()
|
introPlayurl = putils.PlayUtils(intro).getPlayUrl()
|
||||||
log("Adding Intro: %s" % introPlayurl, 1)
|
self.logMsg("Adding Intro: %s" % introPlayurl, 1)
|
||||||
|
|
||||||
# Set listitem and properties for intros
|
# Set listitem and properties for intros
|
||||||
pbutils = PlaybackUtils(intro)
|
pbutils = PlaybackUtils(intro)
|
||||||
|
@ -147,24 +143,24 @@ class PlaybackUtils():
|
||||||
if homeScreen and not seektime and not sizePlaylist:
|
if homeScreen and not seektime and not sizePlaylist:
|
||||||
# Extend our current playlist with the actual item to play
|
# Extend our current playlist with the actual item to play
|
||||||
# only if there's no playlist first
|
# only if there's no playlist first
|
||||||
log("Adding main item to playlist.", 1)
|
self.logMsg("Adding main item to playlist.", 1)
|
||||||
self.pl.addtoPlaylist(dbid, item['Type'].lower())
|
self.pl.addtoPlaylist(dbid, self.item['Type'].lower())
|
||||||
|
|
||||||
# Ensure that additional parts are played after the main item
|
# Ensure that additional parts are played after the main item
|
||||||
currentPosition += 1
|
currentPosition += 1
|
||||||
|
|
||||||
############### -- CHECK FOR ADDITIONAL PARTS ################
|
############### -- CHECK FOR ADDITIONAL PARTS ################
|
||||||
|
|
||||||
if item.get('PartCount'):
|
if self.item.get('PartCount'):
|
||||||
# Only add to the playlist after intros have played
|
# Only add to the playlist after intros have played
|
||||||
partcount = item['PartCount']
|
partcount = self.item['PartCount']
|
||||||
url = "{server}/emby/Videos/%s/AdditionalParts?format=json" % itemid
|
url = "{server}/emby/Videos/%s/AdditionalParts?format=json" % itemid
|
||||||
parts = doUtils(url)
|
parts = self.doUtils(url)
|
||||||
for part in parts['Items']:
|
for part in parts['Items']:
|
||||||
|
|
||||||
additionalListItem = xbmcgui.ListItem()
|
additionalListItem = xbmcgui.ListItem()
|
||||||
additionalPlayurl = putils.PlayUtils(part).getPlayUrl()
|
additionalPlayurl = putils.PlayUtils(part).getPlayUrl()
|
||||||
log("Adding additional part: %s" % partcount, 1)
|
self.logMsg("Adding additional part: %s" % partcount, 1)
|
||||||
|
|
||||||
# Set listitem and properties for each additional parts
|
# Set listitem and properties for each additional parts
|
||||||
pbutils = PlaybackUtils(part)
|
pbutils = PlaybackUtils(part)
|
||||||
|
@ -178,13 +174,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()
|
||||||
|
@ -201,35 +197,34 @@ 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)
|
||||||
self.setListItem(listitem)
|
self.setListItem(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 setProperties(self, playurl, listitem):
|
def setProperties(self, playurl, listitem):
|
||||||
|
|
||||||
window = utils.window
|
window = utils.window
|
||||||
# Set all properties necessary for plugin path playback
|
# Set all properties necessary for plugin path playback
|
||||||
item = self.item
|
itemid = self.item['Id']
|
||||||
itemid = item['Id']
|
itemtype = self.item['Type']
|
||||||
itemtype = item['Type']
|
|
||||||
|
|
||||||
embyitem = "emby_%s" % playurl
|
embyitem = "emby_%s" % playurl
|
||||||
window('%s.runtime' % embyitem, value=str(item.get('RunTimeTicks')))
|
window('%s.runtime' % embyitem, value=str(self.item.get('RunTimeTicks')))
|
||||||
window('%s.type' % embyitem, value=itemtype)
|
window('%s.type' % embyitem, value=itemtype)
|
||||||
window('%s.itemid' % embyitem, value=itemid)
|
window('%s.itemid' % embyitem, value=itemid)
|
||||||
|
|
||||||
if itemtype == "Episode":
|
if itemtype == "Episode":
|
||||||
window('%s.refreshid' % embyitem, value=item.get('SeriesId'))
|
window('%s.refreshid' % embyitem, value=self.item.get('SeriesId'))
|
||||||
else:
|
else:
|
||||||
window('%s.refreshid' % embyitem, value=itemid)
|
window('%s.refreshid' % embyitem, value=itemid)
|
||||||
|
|
||||||
|
@ -248,10 +243,9 @@ class PlaybackUtils():
|
||||||
externalsubs = []
|
externalsubs = []
|
||||||
mapping = {}
|
mapping = {}
|
||||||
|
|
||||||
item = self.item
|
itemid = self.item['Id']
|
||||||
itemid = item['Id']
|
|
||||||
try:
|
try:
|
||||||
mediastreams = item['MediaSources'][0]['MediaStreams']
|
mediastreams = self.item['MediaSources'][0]['MediaStreams']
|
||||||
except (TypeError, KeyError, IndexError):
|
except (TypeError, KeyError, IndexError):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -280,10 +274,7 @@ class PlaybackUtils():
|
||||||
|
|
||||||
def setArtwork(self, listItem):
|
def setArtwork(self, listItem):
|
||||||
# Set up item and item info
|
# Set up item and item info
|
||||||
item = self.item
|
allartwork = self.artwork.getAllArtwork(self.item, parentInfo=True)
|
||||||
artwork = self.artwork
|
|
||||||
|
|
||||||
allartwork = artwork.getAllArtwork(item, parentInfo=True)
|
|
||||||
# Set artwork for listitem
|
# Set artwork for listitem
|
||||||
arttypes = {
|
arttypes = {
|
||||||
|
|
||||||
|
@ -320,33 +311,30 @@ class PlaybackUtils():
|
||||||
|
|
||||||
def setListItem(self, listItem):
|
def setListItem(self, listItem):
|
||||||
|
|
||||||
item = self.item
|
people = self.API.getPeople()
|
||||||
itemtype = item['Type']
|
studios = self.API.getStudios()
|
||||||
API = self.API
|
|
||||||
people = API.getPeople()
|
|
||||||
studios = API.getStudios()
|
|
||||||
|
|
||||||
metadata = {
|
metadata = {
|
||||||
|
|
||||||
'title': item.get('Name', "Missing name"),
|
'title': self.item.get('Name', "Missing name"),
|
||||||
'year': item.get('ProductionYear'),
|
'year': self.item.get('ProductionYear'),
|
||||||
'plot': API.getOverview(),
|
'plot': self.API.getOverview(),
|
||||||
'director': people.get('Director'),
|
'director': people.get('Director'),
|
||||||
'writer': people.get('Writer'),
|
'writer': people.get('Writer'),
|
||||||
'mpaa': API.getMpaa(),
|
'mpaa': self.API.getMpaa(),
|
||||||
'genre': " / ".join(item['Genres']),
|
'genre': " / ".join(self.item['Genres']),
|
||||||
'studio': " / ".join(studios),
|
'studio': " / ".join(studios),
|
||||||
'aired': API.getPremiereDate(),
|
'aired': self.API.getPremiereDate(),
|
||||||
'rating': item.get('CommunityRating'),
|
'rating': self.item.get('CommunityRating'),
|
||||||
'votes': item.get('VoteCount')
|
'votes': self.item.get('VoteCount')
|
||||||
}
|
}
|
||||||
|
|
||||||
if "Episode" in itemtype:
|
if "Episode" in self.item['Type']:
|
||||||
# Only for tv shows
|
# Only for tv shows
|
||||||
thumbId = item.get('SeriesId')
|
thumbId = self.item.get('SeriesId')
|
||||||
season = item.get('ParentIndexNumber', -1)
|
season = self.item.get('ParentIndexNumber', -1)
|
||||||
episode = item.get('IndexNumber', -1)
|
episode = self.item.get('IndexNumber', -1)
|
||||||
show = item.get('SeriesName', "")
|
show = self.item.get('SeriesName', "")
|
||||||
|
|
||||||
metadata['TVShowTitle'] = show
|
metadata['TVShowTitle'] = show
|
||||||
metadata['season'] = season
|
metadata['season'] = season
|
||||||
|
|
|
@ -49,15 +49,13 @@ class Player(xbmc.Player):
|
||||||
|
|
||||||
def onPlayBackStarted(self):
|
def onPlayBackStarted(self):
|
||||||
|
|
||||||
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
|
# Get current file
|
||||||
try:
|
try:
|
||||||
currentFile = xbmcplayer.getPlayingFile()
|
currentFile = self.xbmcplayer.getPlayingFile()
|
||||||
xbmc.sleep(300)
|
xbmc.sleep(300)
|
||||||
except:
|
except:
|
||||||
currentFile = ""
|
currentFile = ""
|
||||||
|
@ -65,11 +63,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: pass
|
except: pass
|
||||||
|
|
||||||
if count == 5: # try 5 times
|
if count == 5: # try 5 times
|
||||||
log("Cancelling playback report...", 1)
|
self.logMsg("Cancelling playback report...", 1)
|
||||||
break
|
break
|
||||||
else: count += 1
|
else: count += 1
|
||||||
|
|
||||||
|
@ -86,12 +84,12 @@ class Player(xbmc.Player):
|
||||||
xbmc.sleep(200)
|
xbmc.sleep(200)
|
||||||
itemId = window("emby_%s.itemid" % currentFile)
|
itemId = window("emby_%s.itemid" % currentFile)
|
||||||
if tryCount == 20: # try 20 times or about 10 seconds
|
if tryCount == 20: # try 20 times or about 10 seconds
|
||||||
log("Could not find itemId, cancelling playback report...", 1)
|
self.logMsg("Could not find itemId, cancelling playback report...", 1)
|
||||||
break
|
break
|
||||||
else: tryCount += 1
|
else: tryCount += 1
|
||||||
|
|
||||||
else:
|
else:
|
||||||
log("ONPLAYBACK_STARTED: %s itemid: %s" % (currentFile, itemId), 0)
|
self.logMsg("ONPLAYBACK_STARTED: %s itemid: %s" % (currentFile, itemId), 0)
|
||||||
|
|
||||||
# Only proceed if an itemId was found.
|
# Only proceed if an itemId was found.
|
||||||
embyitem = "emby_%s" % currentFile
|
embyitem = "emby_%s" % currentFile
|
||||||
|
@ -104,11 +102,11 @@ class Player(xbmc.Player):
|
||||||
customseek = window('emby_customPlaylist.seektime')
|
customseek = window('emby_customPlaylist.seektime')
|
||||||
if window('emby_customPlaylist') == "true" and customseek:
|
if window('emby_customPlaylist') == "true" and customseek:
|
||||||
# Start at, when using custom playlist (play to Kodi from webclient)
|
# Start at, when using custom playlist (play to Kodi from webclient)
|
||||||
log("Seeking to: %s" % customseek, 1)
|
self.logMsg("Seeking to: %s" % customseek, 1)
|
||||||
xbmcplayer.seekTime(int(customseek)/10000000.0)
|
self.xbmcplayer.seekTime(int(customseek)/10000000.0)
|
||||||
window('emby_customPlaylist.seektime', clear=True)
|
window('emby_customPlaylist.seektime', clear=True)
|
||||||
|
|
||||||
seekTime = xbmcplayer.getTime()
|
seekTime = self.xbmcplayer.getTime()
|
||||||
|
|
||||||
# Get playback volume
|
# Get playback volume
|
||||||
volume_query = {
|
volume_query = {
|
||||||
|
@ -191,7 +189,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)):
|
||||||
|
@ -209,15 +207,15 @@ class Player(xbmc.Player):
|
||||||
|
|
||||||
|
|
||||||
# Post playback to server
|
# Post playback to server
|
||||||
log("Sending POST play started: %s." % postdata, 2)
|
self.logMsg("Sending POST play started: %s." % postdata, 2)
|
||||||
self.doUtils(url, postBody=postdata, type="POST")
|
self.doUtils(url, postBody=postdata, action_type="POST")
|
||||||
|
|
||||||
# Ensure we do have a runtime
|
# Ensure we do have a runtime
|
||||||
try:
|
try:
|
||||||
runtime = int(runtime)
|
runtime = int(runtime)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
runtime = xbmcplayer.getTotalTime()
|
runtime = self.xbmcplayer.getTotalTime()
|
||||||
log("Runtime is missing, Kodi runtime: %s" % runtime, 1)
|
self.logMsg("Runtime is missing, Kodi runtime: %s" % runtime, 1)
|
||||||
|
|
||||||
# Save data map for updates and position calls
|
# Save data map for updates and position calls
|
||||||
data = {
|
data = {
|
||||||
|
@ -234,7 +232,7 @@ class Player(xbmc.Player):
|
||||||
}
|
}
|
||||||
|
|
||||||
self.played_info[currentFile] = data
|
self.played_info[currentFile] = data
|
||||||
log("ADDING_FILE: %s" % self.played_info, 1)
|
self.logMsg("ADDING_FILE: %s" % self.played_info, 1)
|
||||||
|
|
||||||
# log some playback stats
|
# log some playback stats
|
||||||
'''if(itemType != None):
|
'''if(itemType != None):
|
||||||
|
@ -253,10 +251,7 @@ class Player(xbmc.Player):
|
||||||
|
|
||||||
def reportPlayback(self):
|
def reportPlayback(self):
|
||||||
|
|
||||||
log = self.logMsg
|
self.logMsg("reportPlayback Called", 2)
|
||||||
|
|
||||||
log("reportPlayback Called", 2)
|
|
||||||
xbmcplayer = self.xbmcplayer
|
|
||||||
|
|
||||||
# Get current file
|
# Get current file
|
||||||
currentFile = self.currentFile
|
currentFile = self.currentFile
|
||||||
|
@ -354,7 +349,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)):
|
||||||
|
@ -374,7 +369,7 @@ class Player(xbmc.Player):
|
||||||
|
|
||||||
# Report progress via websocketclient
|
# Report progress via websocketclient
|
||||||
postdata = json.dumps(postdata)
|
postdata = json.dumps(postdata)
|
||||||
log("Report: %s" % postdata, 2)
|
self.logMsg("Report: %s" % postdata, 2)
|
||||||
self.ws.sendProgressUpdate(postdata)
|
self.ws.sendProgressUpdate(postdata)
|
||||||
|
|
||||||
def onPlayBackPaused(self):
|
def onPlayBackPaused(self):
|
||||||
|
@ -410,14 +405,13 @@ class Player(xbmc.Player):
|
||||||
|
|
||||||
def onPlayBackStopped(self):
|
def onPlayBackStopped(self):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
window = utils.window
|
window = utils.window
|
||||||
# Will be called when user stops xbmc playing a file
|
# Will be called when user stops xbmc playing a file
|
||||||
log("ONPLAYBACK_STOPPED", 2)
|
self.logMsg("ONPLAYBACK_STOPPED", 2)
|
||||||
window('emby_customPlaylist', clear=True)
|
window('emby_customPlaylist', clear=True)
|
||||||
window('emby_customPlaylist.seektime', clear=True)
|
window('emby_customPlaylist.seektime', clear=True)
|
||||||
window('emby_playbackProps', clear=True)
|
window('emby_playbackProps', clear=True)
|
||||||
log("Clear playlist properties.", 1)
|
self.logMsg("Clear playlist properties.", 1)
|
||||||
self.stopAll()
|
self.stopAll()
|
||||||
|
|
||||||
def onPlayBackEnded(self):
|
def onPlayBackEnded(self):
|
||||||
|
@ -428,31 +422,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
|
||||||
|
@ -466,15 +457,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":
|
||||||
|
@ -484,21 +475,21 @@ class Player(xbmc.Player):
|
||||||
if percentComplete >= markPlayedAt and offerDelete:
|
if percentComplete >= markPlayedAt and offerDelete:
|
||||||
resp = xbmcgui.Dialog().yesno(lang(30091), lang(33015), autoclose=120000)
|
resp = xbmcgui.Dialog().yesno(lang(30091), lang(33015), 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
|
||||||
log("Deleting request: %s" % itemid, 1)
|
self.logMsg("Deleting request: %s" % itemid, 1)
|
||||||
doUtils(url, type="DELETE")
|
self.doUtils(url, action_type="DELETE")
|
||||||
|
|
||||||
self.stopPlayback(data)
|
self.stopPlayback(data)
|
||||||
|
|
||||||
# Stop transcoding
|
# Stop transcoding
|
||||||
if playMethod == "Transcode":
|
if playMethod == "Transcode":
|
||||||
log("Transcoding for %s terminated." % itemid, 1)
|
self.logMsg("Transcoding for %s terminated." % itemid, 1)
|
||||||
deviceId = self.clientInfo.getDeviceId()
|
deviceId = self.clientInfo.getDeviceId()
|
||||||
url = "{server}/emby/Videos/ActiveEncodings?DeviceId=%s" % deviceId
|
url = "{server}/emby/Videos/ActiveEncodings?DeviceId=%s" % deviceId
|
||||||
doUtils(url, type="DELETE")
|
self.doUtils(url, action_type="DELETE")
|
||||||
|
|
||||||
self.played_info.clear()
|
self.played_info.clear()
|
||||||
|
|
||||||
|
@ -517,4 +508,4 @@ class Player(xbmc.Player):
|
||||||
'MediaSourceId': itemId,
|
'MediaSourceId': itemId,
|
||||||
'PositionTicks': positionTicks
|
'PositionTicks': positionTicks
|
||||||
}
|
}
|
||||||
self.doUtils(url, postBody=postdata, type="POST")
|
self.doUtils(url, postBody=postdata, action_type="POST")
|
|
@ -39,7 +39,6 @@ class Playlist():
|
||||||
|
|
||||||
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')
|
||||||
|
@ -50,8 +49,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")
|
||||||
|
@ -67,14 +66,14 @@ class Playlist():
|
||||||
mediatype = embydb_item[4]
|
mediatype = embydb_item[4]
|
||||||
except TypeError:
|
except TypeError:
|
||||||
# Item is not found in our database, add item manually
|
# Item is not found in our database, add item manually
|
||||||
log("Item was not found in the database, manually adding item.", 1)
|
self.logMsg("Item was not found in the database, manually adding item.", 1)
|
||||||
item = self.emby.getItem(itemid)
|
item = self.emby.getItem(itemid)
|
||||||
self.addtoPlaylist_xbmc(playlist, item)
|
self.addtoPlaylist_xbmc(playlist, item)
|
||||||
else:
|
else:
|
||||||
# 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)
|
||||||
|
|
||||||
if not started:
|
if not started:
|
||||||
started = True
|
started = True
|
||||||
|
@ -85,14 +84,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)
|
||||||
|
@ -110,7 +107,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()
|
||||||
|
@ -133,12 +130,10 @@ 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):
|
||||||
|
|
||||||
itemid = item['Id']
|
|
||||||
playurl = playutils.PlayUtils(item).getPlayUrl()
|
playurl = playutils.PlayUtils(item).getPlayUrl()
|
||||||
if not playurl:
|
if not playurl:
|
||||||
# Playurl failed
|
# Playurl failed
|
||||||
|
@ -169,8 +164,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):
|
||||||
|
|
||||||
|
@ -184,8 +178,7 @@ class Playlist():
|
||||||
'playlistid': 1
|
'playlistid': 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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):
|
||||||
|
|
||||||
|
@ -200,5 +193,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)
|
|
||||||
|
|
|
@ -33,28 +33,26 @@ class PlayUtils():
|
||||||
|
|
||||||
def getPlayUrl(self):
|
def getPlayUrl(self):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
window = utils.window
|
window = utils.window
|
||||||
|
|
||||||
item = self.item
|
|
||||||
playurl = None
|
playurl = None
|
||||||
|
|
||||||
if (item.get('Type') in ("Recording", "TvChannel") and
|
if (self.item.get('Type') in ("Recording", "TvChannel") and
|
||||||
item.get('MediaSources') and item['MediaSources'][0]['Protocol'] == "Http"):
|
self.item.get('MediaSources') and self.item['MediaSources'][0]['Protocol'] == "Http"):
|
||||||
# Play LiveTV or recordings
|
# Play LiveTV or recordings
|
||||||
log("File protocol is http (livetv).", 1)
|
self.logMsg("File protocol is http (livetv).", 1)
|
||||||
playurl = "%s/emby/Videos/%s/live.m3u8?static=true" % (self.server, item['Id'])
|
playurl = "%s/emby/Videos/%s/live.m3u8?static=true" % (self.server, self.item['Id'])
|
||||||
window('emby_%s.playmethod' % playurl, value="Transcode")
|
window('emby_%s.playmethod' % playurl, value="Transcode")
|
||||||
|
|
||||||
elif item.get('MediaSources') and item['MediaSources'][0]['Protocol'] == "Http":
|
elif self.item.get('MediaSources') and self.item['MediaSources'][0]['Protocol'] == "Http":
|
||||||
# Only play as http, used for channels, or online hosting of content
|
# Only play as http, used for channels, or online hosting of content
|
||||||
log("File protocol is http.", 1)
|
self.logMsg("File protocol is http.", 1)
|
||||||
playurl = self.httpPlay()
|
playurl = self.httpPlay()
|
||||||
window('emby_%s.playmethod' % playurl, value="DirectStream")
|
window('emby_%s.playmethod' % playurl, value="DirectStream")
|
||||||
|
|
||||||
elif self.isDirectPlay():
|
elif self.isDirectPlay():
|
||||||
|
|
||||||
log("File is direct playing.", 1)
|
self.logMsg("File is direct playing.", 1)
|
||||||
playurl = self.directPlay()
|
playurl = self.directPlay()
|
||||||
playurl = playurl.encode('utf-8')
|
playurl = playurl.encode('utf-8')
|
||||||
# Set playmethod property
|
# Set playmethod property
|
||||||
|
@ -62,14 +60,14 @@ class PlayUtils():
|
||||||
|
|
||||||
elif self.isDirectStream():
|
elif self.isDirectStream():
|
||||||
|
|
||||||
log("File is direct streaming.", 1)
|
self.logMsg("File is direct streaming.", 1)
|
||||||
playurl = self.directStream()
|
playurl = self.directStream()
|
||||||
# Set playmethod property
|
# Set playmethod property
|
||||||
window('emby_%s.playmethod' % playurl, value="DirectStream")
|
window('emby_%s.playmethod' % playurl, value="DirectStream")
|
||||||
|
|
||||||
elif self.isTranscoding():
|
elif self.isTranscoding():
|
||||||
|
|
||||||
log("File is transcoding.", 1)
|
self.logMsg("File is transcoding.", 1)
|
||||||
playurl = self.transcoding()
|
playurl = self.transcoding()
|
||||||
# Set playmethod property
|
# Set playmethod property
|
||||||
window('emby_%s.playmethod' % playurl, value="Transcode")
|
window('emby_%s.playmethod' % playurl, value="Transcode")
|
||||||
|
@ -78,35 +76,31 @@ 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
|
||||||
|
|
||||||
def isDirectPlay(self):
|
def isDirectPlay(self):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
lang = utils.language
|
lang = utils.language
|
||||||
settings = utils.settings
|
settings = utils.settings
|
||||||
dialog = xbmcgui.Dialog()
|
dialog = xbmcgui.Dialog()
|
||||||
|
|
||||||
item = self.item
|
|
||||||
|
|
||||||
# Requirement: Filesystem, Accessible path
|
# Requirement: Filesystem, Accessible path
|
||||||
if settings('playFromStream') == "true":
|
if settings('playFromStream') == "true":
|
||||||
# User forcing to play via HTTP
|
# User forcing to play via HTTP
|
||||||
log("Can't direct play, play from HTTP enabled.", 1)
|
self.logMsg("Can't direct play, play from HTTP enabled.", 1)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
videotrack = item['MediaSources'][0]['Name']
|
videotrack = self.item['MediaSources'][0]['Name']
|
||||||
transcodeH265 = settings('transcodeH265')
|
transcodeH265 = settings('transcodeH265')
|
||||||
|
|
||||||
if transcodeH265 in ("1", "2", "3") and ("HEVC" in videotrack or "H265" in videotrack):
|
if transcodeH265 in ("1", "2", "3") and ("HEVC" in videotrack or "H265" in videotrack):
|
||||||
|
@ -118,27 +112,27 @@ class PlayUtils():
|
||||||
'2': 720,
|
'2': 720,
|
||||||
'3': 1080
|
'3': 1080
|
||||||
}
|
}
|
||||||
log("Resolution is: %sP, transcode for resolution: %sP+"
|
self.logMsg("Resolution is: %sP, transcode for resolution: %sP+"
|
||||||
% (resolution, res[transcodeH265]), 1)
|
% (resolution, res[transcodeH265]), 1)
|
||||||
if res[transcodeH265] <= resolution:
|
if res[transcodeH265] <= resolution:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
canDirectPlay = item['MediaSources'][0]['SupportsDirectPlay']
|
canDirectPlay = self.item['MediaSources'][0]['SupportsDirectPlay']
|
||||||
# Make sure direct play is supported by the server
|
# Make sure direct play is supported by the server
|
||||||
if not canDirectPlay:
|
if not canDirectPlay:
|
||||||
log("Can't direct play, server doesn't allow/support it.", 1)
|
self.logMsg("Can't direct play, server doesn't allow/support it.", 1)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
location = item['LocationType']
|
location = self.item['LocationType']
|
||||||
if location == "FileSystem":
|
if location == "FileSystem":
|
||||||
# Verify the path
|
# Verify the path
|
||||||
if not self.fileExists():
|
if not self.fileExists():
|
||||||
log("Unable to direct play.")
|
self.logMsg("Unable to direct play.")
|
||||||
try:
|
try:
|
||||||
count = int(settings('failCount'))
|
count = int(settings('failCount'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
count = 0
|
count = 0
|
||||||
log("Direct play failed: %s times." % count, 1)
|
self.logMsg("Direct play failed: %s times." % count, 1)
|
||||||
|
|
||||||
if count < 2:
|
if count < 2:
|
||||||
# Let the user know that direct play failed
|
# Let the user know that direct play failed
|
||||||
|
@ -163,20 +157,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
|
||||||
|
@ -192,35 +182,30 @@ 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 isDirectStream(self):
|
def isDirectStream(self):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
|
|
||||||
item = self.item
|
videotrack = self.item['MediaSources'][0]['Name']
|
||||||
|
|
||||||
videotrack = item['MediaSources'][0]['Name']
|
|
||||||
transcodeH265 = utils.settings('transcodeH265')
|
transcodeH265 = utils.settings('transcodeH265')
|
||||||
|
|
||||||
if transcodeH265 in ("1", "2", "3") and ("HEVC" in videotrack or "H265" in videotrack):
|
if transcodeH265 in ("1", "2", "3") and ("HEVC" in videotrack or "H265" in videotrack):
|
||||||
|
@ -232,54 +217,47 @@ class PlayUtils():
|
||||||
'2': 720,
|
'2': 720,
|
||||||
'3': 1080
|
'3': 1080
|
||||||
}
|
}
|
||||||
log("Resolution is: %sP, transcode for resolution: %sP+"
|
self.logMsg("Resolution is: %sP, transcode for resolution: %sP+"
|
||||||
% (resolution, res[transcodeH265]), 1)
|
% (resolution, res[transcodeH265]), 1)
|
||||||
if res[transcodeH265] <= resolution:
|
if res[transcodeH265] <= resolution:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Requirement: BitRate, supported encoding
|
# Requirement: BitRate, supported encoding
|
||||||
canDirectStream = item['MediaSources'][0]['SupportsDirectStream']
|
canDirectStream = self.item['MediaSources'][0]['SupportsDirectStream']
|
||||||
# Make sure the server supports it
|
# Make sure the server supports it
|
||||||
if not canDirectStream:
|
if not canDirectStream:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Verify the bitrate
|
# Verify the bitrate
|
||||||
if not self.isNetworkSufficient():
|
if not self.isNetworkSufficient():
|
||||||
log("The network speed is insufficient to direct stream file.", 1)
|
self.logMsg("The network speed is insufficient to direct stream file.", 1)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def directStream(self):
|
def directStream(self):
|
||||||
|
|
||||||
item = self.item
|
if 'Path' in self.item and self.item['Path'].endswith('.strm'):
|
||||||
server = self.server
|
|
||||||
|
|
||||||
itemid = item['Id']
|
|
||||||
itemtype = item['Type']
|
|
||||||
|
|
||||||
if 'Path' in item and item['Path'].endswith('.strm'):
|
|
||||||
# Allow strm loading when direct streaming
|
# Allow strm loading when direct streaming
|
||||||
playurl = self.directPlay()
|
playurl = self.directPlay()
|
||||||
elif itemtype == "Audio":
|
elif self.item['Type'] == "Audio":
|
||||||
playurl = "%s/emby/Audio/%s/stream.mp3" % (server, itemid)
|
playurl = "%s/emby/Audio/%s/stream.mp3" % (self.server, self.item['Id'])
|
||||||
else:
|
else:
|
||||||
playurl = "%s/emby/Videos/%s/stream?static=true" % (server, itemid)
|
playurl = "%s/emby/Videos/%s/stream?static=true" % (self.server, self.item['Id'])
|
||||||
|
|
||||||
return playurl
|
return playurl
|
||||||
|
|
||||||
def isNetworkSufficient(self):
|
def isNetworkSufficient(self):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
|
|
||||||
settings = self.getBitrate()*1000
|
settings = self.getBitrate()*1000
|
||||||
|
|
||||||
try:
|
try:
|
||||||
sourceBitrate = int(self.item['MediaSources'][0]['Bitrate'])
|
sourceBitrate = int(self.item['MediaSources'][0]['Bitrate'])
|
||||||
except (KeyError, TypeError):
|
except (KeyError, TypeError):
|
||||||
log("Bitrate value is missing.", 1)
|
self.logMsg("Bitrate value is missing.", 1)
|
||||||
else:
|
else:
|
||||||
log("The add-on settings bitrate is: %s, the video bitrate required is: %s"
|
self.logMsg("The add-on settings bitrate is: %s, the video bitrate required is: %s"
|
||||||
% (settings, sourceBitrate), 1)
|
% (settings, sourceBitrate), 1)
|
||||||
if settings < sourceBitrate:
|
if settings < sourceBitrate:
|
||||||
return False
|
return False
|
||||||
|
@ -287,25 +265,19 @@ class PlayUtils():
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def isTranscoding(self):
|
def isTranscoding(self):
|
||||||
|
|
||||||
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"
|
||||||
|
@ -320,7 +292,6 @@ class PlayUtils():
|
||||||
def getBitrate(self):
|
def getBitrate(self):
|
||||||
|
|
||||||
# get the addon video quality
|
# get the addon video quality
|
||||||
videoQuality = utils.settings('videoBitrate')
|
|
||||||
bitrate = {
|
bitrate = {
|
||||||
|
|
||||||
'0': 664,
|
'0': 664,
|
||||||
|
@ -345,11 +316,10 @@ class PlayUtils():
|
||||||
}
|
}
|
||||||
|
|
||||||
# max bit rate supported by server (max signed 32bit integer)
|
# max bit rate supported by server (max signed 32bit integer)
|
||||||
return bitrate.get(videoQuality, 2147483)
|
return bitrate.get(utils.settings('videoBitrate'), 2147483)
|
||||||
|
|
||||||
def audioSubsPref(self, url, listitem):
|
def audioSubsPref(self, url, listitem):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
lang = utils.language
|
lang = utils.language
|
||||||
dialog = xbmcgui.Dialog()
|
dialog = xbmcgui.Dialog()
|
||||||
# For transcoding only
|
# For transcoding only
|
||||||
|
@ -364,9 +334,8 @@ class PlayUtils():
|
||||||
selectSubsIndex = ""
|
selectSubsIndex = ""
|
||||||
playurlprefs = "%s" % url
|
playurlprefs = "%s" % url
|
||||||
|
|
||||||
item = self.item
|
|
||||||
try:
|
try:
|
||||||
mediasources = item['MediaSources'][0]
|
mediasources = self.item['MediaSources'][0]
|
||||||
mediastreams = mediasources['MediaStreams']
|
mediastreams = mediasources['MediaStreams']
|
||||||
except (TypeError, KeyError, IndexError):
|
except (TypeError, KeyError, IndexError):
|
||||||
return
|
return
|
||||||
|
@ -374,9 +343,8 @@ class PlayUtils():
|
||||||
for stream in mediastreams:
|
for stream in mediastreams:
|
||||||
# Since Emby returns all possible tracks together, have to sort them.
|
# Since Emby returns all possible tracks together, have to sort them.
|
||||||
index = stream['Index']
|
index = stream['Index']
|
||||||
type = stream['Type']
|
|
||||||
|
|
||||||
if 'Audio' in type:
|
if 'Audio' in stream['Type']:
|
||||||
codec = stream['Codec']
|
codec = stream['Codec']
|
||||||
channelLayout = stream.get('ChannelLayout', "")
|
channelLayout = stream.get('ChannelLayout', "")
|
||||||
|
|
||||||
|
@ -389,7 +357,7 @@ class PlayUtils():
|
||||||
audioStreamsList[track] = index
|
audioStreamsList[track] = index
|
||||||
audioStreams.append(track)
|
audioStreams.append(track)
|
||||||
|
|
||||||
elif 'Subtitle' in type:
|
elif 'Subtitle' in stream['Type']:
|
||||||
try:
|
try:
|
||||||
track = "%s - %s" % (index, stream['Language'])
|
track = "%s - %s" % (index, stream['Language'])
|
||||||
except:
|
except:
|
||||||
|
@ -436,10 +404,10 @@ class PlayUtils():
|
||||||
# Load subtitles in the listitem if downloadable
|
# Load subtitles in the listitem if downloadable
|
||||||
if selectSubsIndex in downloadableStreams:
|
if selectSubsIndex in downloadableStreams:
|
||||||
|
|
||||||
itemid = item['Id']
|
itemid = self.item['Id']
|
||||||
url = [("%s/Videos/%s/%s/Subtitles/%s/Stream.srt"
|
url = [("%s/Videos/%s/%s/Subtitles/%s/Stream.srt"
|
||||||
% (self.server, itemid, itemid, selectSubsIndex))]
|
% (self.server, itemid, itemid, selectSubsIndex))]
|
||||||
log("Set up subtitles: %s %s" % (selectSubsIndex, url), 1)
|
self.logMsg("Set up subtitles: %s %s" % (selectSubsIndex, url), 1)
|
||||||
listitem.setSubtitles(url)
|
listitem.setSubtitles(url)
|
||||||
else:
|
else:
|
||||||
# Burn subtitles
|
# Burn subtitles
|
||||||
|
|
|
@ -42,8 +42,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}/metaman/Users/{UserId}/Items/%s?format=json" % itemid)
|
||||||
result = self.doUtils(url)
|
|
||||||
if result:
|
if result:
|
||||||
item = result
|
item = result
|
||||||
|
|
||||||
|
@ -56,13 +55,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'])
|
||||||
|
|
||||||
|
@ -75,7 +73,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),
|
||||||
|
@ -89,7 +86,7 @@ class Read_EmbyServer():
|
||||||
"MediaSources"
|
"MediaSources"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
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'])
|
||||||
|
|
||||||
|
@ -98,13 +95,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']
|
||||||
|
|
||||||
|
@ -131,8 +125,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,
|
||||||
|
@ -151,11 +143,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,
|
||||||
|
@ -165,11 +155,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 = {
|
||||||
|
|
||||||
|
@ -181,13 +169,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': [],
|
||||||
|
@ -206,13 +191,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
|
||||||
|
@ -247,34 +232,34 @@ class Read_EmbyServer():
|
||||||
"Tags,ProviderIds,ParentId,RemoteTrailers,SpecialEpisodeNumbers,"
|
"Tags,ProviderIds,ParentId,RemoteTrailers,SpecialEpisodeNumbers,"
|
||||||
"MediaSources"
|
"MediaSources"
|
||||||
)
|
)
|
||||||
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
|
||||||
|
@ -302,12 +287,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()
|
||||||
|
|
||||||
|
@ -316,7 +300,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:
|
||||||
|
@ -324,11 +308,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
|
||||||
|
|
||||||
|
@ -339,20 +320,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
|
||||||
|
@ -360,9 +341,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
|
||||||
|
@ -370,8 +351,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,
|
||||||
|
@ -381,7 +360,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:
|
||||||
|
@ -394,40 +373,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):
|
||||||
|
|
||||||
|
@ -437,13 +399,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
|
||||||
|
|
||||||
|
@ -451,25 +412,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': [],
|
||||||
|
@ -483,7 +438,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
|
||||||
|
@ -513,7 +468,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
|
||||||
|
@ -523,28 +478,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):
|
||||||
|
|
||||||
|
@ -554,8 +498,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
|
||||||
|
|
||||||
|
@ -577,24 +520,18 @@ 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")
|
|
||||||
|
|
||||||
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"
|
||||||
|
|
|
@ -81,7 +81,6 @@ class UserClient(threading.Thread):
|
||||||
|
|
||||||
def getUserId(self):
|
def getUserId(self):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
window = utils.window
|
window = utils.window
|
||||||
settings = utils.settings
|
settings = utils.settings
|
||||||
|
|
||||||
|
@ -94,17 +93,17 @@ class UserClient(threading.Thread):
|
||||||
if not s_userId:
|
if not s_userId:
|
||||||
# Save access token if it's missing from settings
|
# Save access token if it's missing from settings
|
||||||
settings('userId%s' % username, value=w_userId)
|
settings('userId%s' % username, value=w_userId)
|
||||||
log("Returning userId from WINDOW for username: %s UserId: %s"
|
self.logMsg("Returning userId from WINDOW for username: %s UserId: %s"
|
||||||
% (username, w_userId), 2)
|
% (username, w_userId), 2)
|
||||||
return w_userId
|
return w_userId
|
||||||
# Verify the settings
|
# Verify the settings
|
||||||
elif s_userId:
|
elif s_userId:
|
||||||
log("Returning userId from SETTINGS for username: %s userId: %s"
|
self.logMsg("Returning userId from SETTINGS for username: %s userId: %s"
|
||||||
% (username, s_userId), 2)
|
% (username, s_userId), 2)
|
||||||
return s_userId
|
return s_userId
|
||||||
# No userId found
|
# No userId found
|
||||||
else:
|
else:
|
||||||
log("No userId saved for username: %s." % username, 1)
|
self.logMsg("No userId saved for username: %s." % username, 1)
|
||||||
|
|
||||||
def getServer(self, prefix=True):
|
def getServer(self, prefix=True):
|
||||||
|
|
||||||
|
@ -142,7 +141,6 @@ class UserClient(threading.Thread):
|
||||||
|
|
||||||
def getToken(self):
|
def getToken(self):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
window = utils.window
|
window = utils.window
|
||||||
settings = utils.settings
|
settings = utils.settings
|
||||||
|
|
||||||
|
@ -156,17 +154,17 @@ class UserClient(threading.Thread):
|
||||||
if not s_token:
|
if not s_token:
|
||||||
# Save access token if it's missing from settings
|
# Save access token if it's missing from settings
|
||||||
settings('accessToken', value=w_token)
|
settings('accessToken', value=w_token)
|
||||||
log("Returning accessToken from WINDOW for username: %s accessToken: %s"
|
self.logMsg("Returning accessToken from WINDOW for username: %s accessToken: %s"
|
||||||
% (username, w_token), 2)
|
% (username, w_token), 2)
|
||||||
return w_token
|
return w_token
|
||||||
# Verify the settings
|
# Verify the settings
|
||||||
elif s_token:
|
elif s_token:
|
||||||
log("Returning accessToken from SETTINGS for username: %s accessToken: %s"
|
self.logMsg("Returning accessToken from SETTINGS for username: %s accessToken: %s"
|
||||||
% (username, s_token), 2)
|
% (username, s_token), 2)
|
||||||
window('emby_accessToken%s' % username, value=s_token)
|
window('emby_accessToken%s' % username, value=s_token)
|
||||||
return s_token
|
return s_token
|
||||||
else:
|
else:
|
||||||
log("No token found.", 1)
|
self.logMsg("No token found.", 1)
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
def getSSLverify(self):
|
def getSSLverify(self):
|
||||||
|
@ -198,46 +196,37 @@ class UserClient(threading.Thread):
|
||||||
def setUserPref(self):
|
def setUserPref(self):
|
||||||
|
|
||||||
doUtils = self.doUtils.downloadUrl
|
doUtils = self.doUtils.downloadUrl
|
||||||
art = artwork.Artwork()
|
|
||||||
|
|
||||||
url = "{server}/emby/Users/{UserId}?format=json"
|
result = doUtils("{server}/emby/Users/{UserId}?format=json")
|
||||||
result = doUtils(url)
|
|
||||||
self.userSettings = result
|
self.userSettings = result
|
||||||
# Set user image for skin display
|
# Set user image for skin display
|
||||||
if result.get('PrimaryImageTag'):
|
if result.get('PrimaryImageTag'):
|
||||||
utils.window('EmbyUserImage', value=art.getUserArtwork(result['Id'], 'Primary'))
|
utils.window('EmbyUserImage', value=artwork.Artwork().getUserArtwork(result['Id'], 'Primary'))
|
||||||
|
|
||||||
# Set resume point max
|
# Set resume point max
|
||||||
url = "{server}/emby/System/Configuration?format=json"
|
result = doUtils("{server}/emby/System/Configuration?format=json")
|
||||||
result = doUtils(url)
|
|
||||||
|
|
||||||
utils.settings('markPlayed', value=str(result['MaxResumePct']))
|
utils.settings('markPlayed', value=str(result['MaxResumePct']))
|
||||||
|
|
||||||
def getPublicUsers(self):
|
def getPublicUsers(self):
|
||||||
|
|
||||||
server = self.getServer()
|
|
||||||
|
|
||||||
# Get public Users
|
# Get public Users
|
||||||
url = "%s/emby/Users/Public?format=json" % server
|
result = self.doUtils.downloadUrl("%s/emby/Users/Public?format=json" % self.getServer(), authenticate=False)
|
||||||
result = self.doUtils.downloadUrl(url, authenticate=False)
|
|
||||||
|
|
||||||
if result != "":
|
if result != "":
|
||||||
return result
|
return result
|
||||||
else:
|
else:
|
||||||
# Server connection failed
|
# Server connection failed
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def hasAccess(self):
|
def hasAccess(self):
|
||||||
# hasAccess is verified in service.py
|
# hasAccess is verified in service.py
|
||||||
log = self.logMsg
|
|
||||||
window = utils.window
|
window = utils.window
|
||||||
|
|
||||||
url = "{server}/emby/Users?format=json"
|
result = self.doUtils.downloadUrl("{server}/emby/Users?format=json")
|
||||||
result = self.doUtils.downloadUrl(url)
|
|
||||||
|
|
||||||
if result == False:
|
if result == False:
|
||||||
# Access is restricted, set in downloadutils.py via exception
|
# Access is restricted, set in downloadutils.py via exception
|
||||||
log("Access is restricted.", 1)
|
self.logMsg("Access is restricted.", 1)
|
||||||
self.HasAccess = False
|
self.HasAccess = False
|
||||||
|
|
||||||
elif window('emby_online') != "true":
|
elif window('emby_online') != "true":
|
||||||
|
@ -245,7 +234,7 @@ class UserClient(threading.Thread):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
elif window('emby_serverStatus') == "restricted":
|
elif window('emby_serverStatus') == "restricted":
|
||||||
log("Access is granted.", 1)
|
self.logMsg("Access is granted.", 1)
|
||||||
self.HasAccess = True
|
self.HasAccess = True
|
||||||
window('emby_serverStatus', clear=True)
|
window('emby_serverStatus', clear=True)
|
||||||
xbmcgui.Dialog().notification("Emby for Kodi", utils.language(33007))
|
xbmcgui.Dialog().notification("Emby for Kodi", utils.language(33007))
|
||||||
|
@ -301,7 +290,6 @@ class UserClient(threading.Thread):
|
||||||
|
|
||||||
def authenticate(self):
|
def authenticate(self):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
lang = utils.language
|
lang = utils.language
|
||||||
window = utils.window
|
window = utils.window
|
||||||
settings = utils.settings
|
settings = utils.settings
|
||||||
|
@ -316,24 +304,24 @@ class UserClient(threading.Thread):
|
||||||
|
|
||||||
# If there's no settings.xml
|
# If there's no settings.xml
|
||||||
if not hasSettings:
|
if not hasSettings:
|
||||||
log("No settings.xml found.", 1)
|
self.logMsg("No settings.xml found.", 1)
|
||||||
self.auth = False
|
self.auth = False
|
||||||
return
|
return
|
||||||
# If no user information
|
# If no user information
|
||||||
elif not server or not username:
|
elif not server or not username:
|
||||||
log("Missing server information.", 1)
|
self.logMsg("Missing server information.", 1)
|
||||||
self.auth = False
|
self.auth = False
|
||||||
return
|
return
|
||||||
# If there's a token, load the user
|
# If there's a token, load the user
|
||||||
elif self.getToken():
|
elif self.getToken():
|
||||||
result = self.loadCurrUser()
|
result = self.loadCurrUser()
|
||||||
|
|
||||||
if result == False:
|
if result is False:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
log("Current user: %s" % self.currUser, 1)
|
self.logMsg("Current user: %s" % self.currUser, 1)
|
||||||
log("Current userId: %s" % self.currUserId, 1)
|
self.logMsg("Current userId: %s" % self.currUserId, 1)
|
||||||
log("Current accessToken: %s" % self.currToken, 2)
|
self.logMsg("Current accessToken: %s" % self.currToken, 2)
|
||||||
return
|
return
|
||||||
|
|
||||||
##### AUTHENTICATE USER #####
|
##### AUTHENTICATE USER #####
|
||||||
|
@ -353,7 +341,7 @@ class UserClient(threading.Thread):
|
||||||
option=xbmcgui.ALPHANUM_HIDE_INPUT)
|
option=xbmcgui.ALPHANUM_HIDE_INPUT)
|
||||||
# If password dialog is cancelled
|
# If password dialog is cancelled
|
||||||
if not password:
|
if not password:
|
||||||
log("No password entered.", 0)
|
self.logMsg("No password entered.", 0)
|
||||||
window('emby_serverStatus', value="Stop")
|
window('emby_serverStatus', value="Stop")
|
||||||
self.auth = False
|
self.auth = False
|
||||||
return
|
return
|
||||||
|
@ -367,40 +355,38 @@ class UserClient(threading.Thread):
|
||||||
sha1 = sha1.hexdigest()
|
sha1 = sha1.hexdigest()
|
||||||
|
|
||||||
# Authenticate username and password
|
# Authenticate username and password
|
||||||
url = "%s/emby/Users/AuthenticateByName?format=json" % server
|
|
||||||
data = {'username': username, 'password': sha1}
|
data = {'username': username, 'password': sha1}
|
||||||
log(data, 2)
|
self.logMsg(data, 2)
|
||||||
|
|
||||||
result = self.doUtils.downloadUrl(url, postBody=data, type="POST", authenticate=False)
|
result = self.doUtils.downloadUrl("%s/emby/Users/AuthenticateByName?format=json" % server, postBody=data, action_type="POST", authenticate=False)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
log("Auth response: %s" % result, 1)
|
self.logMsg("Auth response: %s" % result, 1)
|
||||||
accessToken = result['AccessToken']
|
accessToken = result['AccessToken']
|
||||||
|
|
||||||
except (KeyError, TypeError):
|
except (KeyError, TypeError):
|
||||||
log("Failed to retrieve the api key.", 1)
|
self.logMsg("Failed to retrieve the api key.", 1)
|
||||||
accessToken = None
|
accessToken = None
|
||||||
|
|
||||||
if accessToken is not None:
|
if accessToken is not None:
|
||||||
self.currUser = username
|
self.currUser = username
|
||||||
dialog.notification("Emby for Kodi",
|
dialog.notification("Emby for Kodi",
|
||||||
"%s %s!" % (lang(33000), self.currUser.decode('utf-8')))
|
"%s %s!" % (lang(33000), self.currUser.decode('utf-8')))
|
||||||
userId = result['User']['Id']
|
|
||||||
settings('accessToken', value=accessToken)
|
settings('accessToken', value=accessToken)
|
||||||
settings('userId%s' % username, value=userId)
|
settings('userId%s' % username, value=result['User']['Id'])
|
||||||
log("User Authenticated: %s" % accessToken, 1)
|
self.logMsg("User Authenticated: %s" % accessToken, 1)
|
||||||
self.loadCurrUser(authenticated=True)
|
self.loadCurrUser(authenticated=True)
|
||||||
window('emby_serverStatus', clear=True)
|
window('emby_serverStatus', clear=True)
|
||||||
self.retry = 0
|
self.retry = 0
|
||||||
else:
|
else:
|
||||||
log("User authentication failed.", 1)
|
self.logMsg("User authentication failed.", 1)
|
||||||
settings('accessToken', value="")
|
settings('accessToken', value="")
|
||||||
settings('userId%s' % username, value="")
|
settings('userId%s' % username, value="")
|
||||||
dialog.ok(lang(33001), lang(33009))
|
dialog.ok(lang(33001), lang(33009))
|
||||||
|
|
||||||
# Give two attempts at entering password
|
# Give two attempts at entering password
|
||||||
if self.retry == 2:
|
if self.retry == 2:
|
||||||
log("Too many retries. "
|
self.logMsg("Too many retries. "
|
||||||
"You can retry by resetting attempts in the addon settings.", 1)
|
"You can retry by resetting attempts in the addon settings.", 1)
|
||||||
window('emby_serverStatus', value="Stop")
|
window('emby_serverStatus', value="Stop")
|
||||||
dialog.ok(lang(33001), lang(33010))
|
dialog.ok(lang(33001), lang(33010))
|
||||||
|
@ -410,28 +396,23 @@ class UserClient(threading.Thread):
|
||||||
|
|
||||||
def resetClient(self):
|
def resetClient(self):
|
||||||
|
|
||||||
log = self.logMsg
|
self.logMsg("Reset UserClient authentication.", 1)
|
||||||
|
|
||||||
log("Reset UserClient authentication.", 1)
|
|
||||||
userId = self.getUserId()
|
|
||||||
|
|
||||||
if self.currToken is not None:
|
if self.currToken is not None:
|
||||||
# In case of 401, removed saved token
|
# In case of 401, removed saved token
|
||||||
utils.settings('accessToken', value="")
|
utils.settings('accessToken', value="")
|
||||||
utils.window('emby_accessToken%s' % userId, clear=True)
|
utils.window('emby_accessToken%s' % self.getUserId(), clear=True)
|
||||||
self.currToken = None
|
self.currToken = None
|
||||||
log("User token has been removed.", 1)
|
self.logMsg("User token has been removed.", 1)
|
||||||
|
|
||||||
self.auth = True
|
self.auth = True
|
||||||
self.currUser = None
|
self.currUser = None
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
window = utils.window
|
window = utils.window
|
||||||
|
|
||||||
monitor = xbmc.Monitor()
|
monitor = xbmc.Monitor()
|
||||||
log("----===## Starting UserClient ##===----", 0)
|
self.logMsg("----===## Starting UserClient ##===----", 0)
|
||||||
|
|
||||||
while not monitor.abortRequested():
|
while not monitor.abortRequested():
|
||||||
|
|
||||||
|
@ -466,8 +447,8 @@ class UserClient(threading.Thread):
|
||||||
# The status Stop is for when user cancelled password dialog.
|
# The status Stop is for when user cancelled password dialog.
|
||||||
if server and username and status != "Stop":
|
if server and username and status != "Stop":
|
||||||
# Only if there's information found to login
|
# Only if there's information found to login
|
||||||
log("Server found: %s" % server, 2)
|
self.logMsg("Server found: %s" % server, 2)
|
||||||
log("Username found: %s" % username, 2)
|
self.logMsg("Username found: %s" % username, 2)
|
||||||
self.auth = True
|
self.auth = True
|
||||||
|
|
||||||
|
|
||||||
|
@ -480,7 +461,7 @@ class UserClient(threading.Thread):
|
||||||
break
|
break
|
||||||
|
|
||||||
self.doUtils.stopSession()
|
self.doUtils.stopSession()
|
||||||
log("##===---- UserClient Stopped ----===##", 0)
|
self.logMsg("##===---- UserClient Stopped ----===##", 0)
|
||||||
|
|
||||||
def stopClient(self):
|
def stopClient(self):
|
||||||
# When emby for kodi terminates
|
# When emby for kodi terminates
|
||||||
|
|
|
@ -62,26 +62,23 @@ def window(property, value=None, clear=False, windowid=10000):
|
||||||
|
|
||||||
def settings(setting, value=None):
|
def settings(setting, value=None):
|
||||||
# Get or add addon setting
|
# Get or add addon setting
|
||||||
addon = xbmcaddon.Addon(id='plugin.video.emby')
|
|
||||||
|
|
||||||
if value is not None:
|
if value is not None:
|
||||||
addon.setSetting(setting, value)
|
xbmcaddon.Addon(id='plugin.video.metaman').setSetting(setting, value)
|
||||||
else:
|
else:
|
||||||
return addon.getSetting(setting) #returns unicode object
|
return xbmcaddon.Addon(id='plugin.video.metaman').getSetting(setting) #returns unicode object
|
||||||
|
|
||||||
def language(stringid):
|
def language(stringid):
|
||||||
# Central string retrieval
|
# Central string retrieval
|
||||||
addon = xbmcaddon.Addon(id='plugin.video.emby')
|
string = xbmcaddon.Addon(id='plugin.video.emby').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()
|
||||||
|
@ -91,7 +88,6 @@ def kodiSQL(type="video"):
|
||||||
|
|
||||||
def getKodiVideoDBPath():
|
def getKodiVideoDBPath():
|
||||||
|
|
||||||
kodibuild = xbmc.getInfoLabel('System.BuildVersion')[:2]
|
|
||||||
dbVersion = {
|
dbVersion = {
|
||||||
|
|
||||||
"13": 78, # Gotham
|
"13": 78, # Gotham
|
||||||
|
@ -102,12 +98,11 @@ def getKodiVideoDBPath():
|
||||||
|
|
||||||
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
|
||||||
|
@ -118,7 +113,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():
|
||||||
|
@ -133,11 +128,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
|
||||||
|
@ -152,15 +143,13 @@ def setScreensaver(value):
|
||||||
'value': value
|
'value': value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result = xbmc.executeJSONRPC(json.dumps(query))
|
logMsg("EMBY", "Toggling screensaver: %s %s" % (value, xbmc.executeJSONRPC(json.dumps(query))), 1)
|
||||||
logMsg("EMBY", "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
|
||||||
|
@ -222,7 +211,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
|
||||||
|
@ -418,9 +407,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)
|
||||||
|
|
|
@ -55,7 +55,6 @@ class VideoNodes(object):
|
||||||
def viewNode(self, indexnumber, tagname, mediatype, viewtype, viewid, delete=False):
|
def viewNode(self, indexnumber, tagname, mediatype, viewtype, viewid, delete=False):
|
||||||
|
|
||||||
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)
|
||||||
|
@ -203,10 +202,10 @@ class VideoNodes(object):
|
||||||
elif nodetype == "nextepisodes":
|
elif nodetype == "nextepisodes":
|
||||||
# Custom query
|
# Custom query
|
||||||
path = "plugin://plugin.video.emby/?id=%s&mode=nextup&limit=25" % tagname
|
path = "plugin://plugin.video.emby/?id=%s&mode=nextup&limit=25" % tagname
|
||||||
elif kodiversion == 14 and nodetype == "recentepisodes":
|
elif self.kodiversion == 14 and nodetype == "recentepisodes":
|
||||||
# Custom query
|
# Custom query
|
||||||
path = "plugin://plugin.video.emby/?id=%s&mode=recentepisodes&limit=25" % tagname
|
path = "plugin://plugin.video.emby/?id=%s&mode=recentepisodes&limit=25" % tagname
|
||||||
elif kodiversion == 14 and nodetype == "inprogressepisodes":
|
elif self.kodiversion == 14 and nodetype == "inprogressepisodes":
|
||||||
# Custom query
|
# Custom query
|
||||||
path = "plugin://plugin.video.emby/?id=%s&mode=inprogressepisodes&limit=25"% tagname
|
path = "plugin://plugin.video.emby/?id=%s&mode=inprogressepisodes&limit=25"% tagname
|
||||||
else:
|
else:
|
||||||
|
@ -247,7 +246,7 @@ class VideoNodes(object):
|
||||||
|
|
||||||
# Create the root
|
# Create the root
|
||||||
if (nodetype == "nextepisodes" or mediatype == "homevideos" or
|
if (nodetype == "nextepisodes" or mediatype == "homevideos" or
|
||||||
(kodiversion == 14 and nodetype in ('recentepisodes', 'inprogressepisodes'))):
|
(self.kodiversion == 14 and nodetype in ('recentepisodes', 'inprogressepisodes'))):
|
||||||
# Folder type with plugin path
|
# Folder type with plugin path
|
||||||
root = self.commonRoot(order=node, label=label, tagname=tagname, roottype=2)
|
root = self.commonRoot(order=node, label=label, tagname=tagname, roottype=2)
|
||||||
etree.SubElement(root, 'path').text = path
|
etree.SubElement(root, 'path').text = path
|
||||||
|
|
|
@ -455,7 +455,6 @@ class WebSocket(object):
|
||||||
self._handshake(hostname, port, resource, **options)
|
self._handshake(hostname, port, resource, **options)
|
||||||
|
|
||||||
def _handshake(self, host, port, resource, **options):
|
def _handshake(self, host, port, resource, **options):
|
||||||
sock = self.sock
|
|
||||||
headers = []
|
headers = []
|
||||||
headers.append("GET %s HTTP/1.1" % resource)
|
headers.append("GET %s HTTP/1.1" % resource)
|
||||||
headers.append("Upgrade: websocket")
|
headers.append("Upgrade: websocket")
|
||||||
|
|
|
@ -51,9 +51,7 @@ class WebSocket_Client(threading.Thread):
|
||||||
|
|
||||||
def sendProgressUpdate(self, data):
|
def sendProgressUpdate(self, data):
|
||||||
|
|
||||||
log = self.logMsg
|
self.logMsg("sendProgressUpdate", 2)
|
||||||
|
|
||||||
log("sendProgressUpdate", 2)
|
|
||||||
try:
|
try:
|
||||||
messageData = {
|
messageData = {
|
||||||
|
|
||||||
|
@ -62,14 +60,13 @@ class WebSocket_Client(threading.Thread):
|
||||||
}
|
}
|
||||||
messageString = json.dumps(messageData)
|
messageString = json.dumps(messageData)
|
||||||
self.client.send(messageString)
|
self.client.send(messageString)
|
||||||
log("Message data: %s" % messageString, 2)
|
self.logMsg("Message data: %s" % messageString, 2)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log("Exception: %s" % e, 1)
|
self.logMsg("Exception: %s" % e, 1)
|
||||||
|
|
||||||
def on_message(self, ws, message):
|
def on_message(self, ws, message):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
window = utils.window
|
window = utils.window
|
||||||
lang = utils.language
|
lang = utils.language
|
||||||
|
|
||||||
|
@ -79,7 +76,7 @@ class WebSocket_Client(threading.Thread):
|
||||||
|
|
||||||
if messageType not in ('SessionEnded'):
|
if messageType not in ('SessionEnded'):
|
||||||
# Mute certain events
|
# Mute certain events
|
||||||
log("Message: %s" % message, 1)
|
self.logMsg("Message: %s" % message, 1)
|
||||||
|
|
||||||
if messageType == "Play":
|
if messageType == "Play":
|
||||||
# A remote control play command has been sent from the server.
|
# A remote control play command has been sent from the server.
|
||||||
|
@ -129,10 +126,10 @@ class WebSocket_Client(threading.Thread):
|
||||||
seekto = data['SeekPositionTicks']
|
seekto = data['SeekPositionTicks']
|
||||||
seektime = seekto / 10000000.0
|
seektime = seekto / 10000000.0
|
||||||
action(seektime)
|
action(seektime)
|
||||||
log("Seek to %s." % seektime, 1)
|
self.logMsg("Seek to %s." % seektime, 1)
|
||||||
else:
|
else:
|
||||||
action()
|
action()
|
||||||
log("Command: %s completed." % command, 1)
|
self.logMsg("Command: %s completed." % command, 1)
|
||||||
|
|
||||||
window('emby_command', value="true")
|
window('emby_command', value="true")
|
||||||
|
|
||||||
|
@ -279,26 +276,21 @@ class WebSocket_Client(threading.Thread):
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
log = self.logMsg
|
|
||||||
window = utils.window
|
window = utils.window
|
||||||
monitor = self.monitor
|
|
||||||
|
|
||||||
loglevel = int(window('emby_logLevel'))
|
loglevel = int(window('emby_logLevel'))
|
||||||
# websocket.enableTrace(True)
|
# websocket.enableTrace(True)
|
||||||
|
|
||||||
userId = window('emby_currUser')
|
userId = window('emby_currUser')
|
||||||
server = window('emby_server%s' % userId)
|
server = window('emby_server%s' % userId)
|
||||||
token = window('emby_accessToken%s' % userId)
|
token = window('emby_accessToken%s' % userId)
|
||||||
deviceId = self.deviceId
|
|
||||||
|
|
||||||
# Get the appropriate prefix for the websocket
|
# Get the appropriate prefix for the websocket
|
||||||
if "https" in server:
|
if "https" in server:
|
||||||
server = server.replace('https', "wss")
|
server = server.replace('https', "wss")
|
||||||
else:
|
else:
|
||||||
server = server.replace('http', "ws")
|
server = server.replace('http', "ws")
|
||||||
|
|
||||||
websocket_url = "%s?api_key=%s&deviceId=%s" % (server, token, deviceId)
|
websocket_url = "%s?api_key=%s&deviceId=%s" % (server, token, self.deviceId)
|
||||||
log("websocket url: %s" % websocket_url, 1)
|
self.logMsg("websocket url: %s" % websocket_url, 1)
|
||||||
|
|
||||||
self.client = websocket.WebSocketApp(websocket_url,
|
self.client = websocket.WebSocketApp(websocket_url,
|
||||||
on_message=self.on_message,
|
on_message=self.on_message,
|
||||||
|
@ -306,19 +298,19 @@ class WebSocket_Client(threading.Thread):
|
||||||
on_close=self.on_close)
|
on_close=self.on_close)
|
||||||
|
|
||||||
self.client.on_open = self.on_open
|
self.client.on_open = self.on_open
|
||||||
log("----===## Starting WebSocketClient ##===----", 0)
|
self.logMsg("----===## Starting WebSocketClient ##===----", 0)
|
||||||
|
|
||||||
while not monitor.abortRequested():
|
while not self.monitor.abortRequested():
|
||||||
|
|
||||||
self.client.run_forever(ping_interval=10)
|
self.client.run_forever(ping_interval=10)
|
||||||
if self.stopWebsocket:
|
if self.stopWebsocket:
|
||||||
break
|
break
|
||||||
|
|
||||||
if monitor.waitForAbort(5):
|
if self.monitor.waitForAbort(5):
|
||||||
# Abort was requested, exit
|
# Abort was requested, exit
|
||||||
break
|
break
|
||||||
|
|
||||||
log("##===---- WebSocketClient Stopped ----===##", 0)
|
self.logMsg("##===---- WebSocketClient Stopped ----===##", 0)
|
||||||
|
|
||||||
def stopClient(self):
|
def stopClient(self):
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue