Trailers up. BUT: first trailer is repeated indefinitely

This commit is contained in:
tomkat83 2016-01-03 13:36:00 +01:00
parent e1eab21f7f
commit 7f9dfca2d6
6 changed files with 255 additions and 221 deletions

View file

@ -1258,44 +1258,20 @@ class PlexAPI():
self.logMsg("Error retrieving metadata for %s" % url, 1) self.logMsg("Error retrieving metadata for %s" % url, 1)
return xml return xml
def GetPlexPlaylist(self, key):
"""
Returns raw API metadata XML dump.
Can be called with either Plex key '/library/metadata/xxxx'metadata
OR with the digits 'xxxx' only.
"""
xml = ''
key = str(key)
url = "{server}/playQueues"
if '/library/metadata/' in key:
# Cut of the slash!
item = key[1:]
else:
item = "library/metadata/" + key
arguments = {
'checkFiles': 1, # No idea
'includeExtras': 1, # Trailers and Extras => Extras
'includeRelated': 1, # Similar movies => Video -> Related
'includeRelatedCount': 5,
'includeOnDeck': 1,
'includeChapters': 1,
'includePopularLeaves': 1,
'includeConcerts': 1
}
url = url + '?' + urlencode(arguments)
headerOptions = {'Accept': 'application/xml'}
xml = self.doUtils.downloadUrl(url, headerOptions=headerOptions)
if not xml:
self.logMsg("Error retrieving metadata for %s" % url, 1)
return xml
class API(): class API():
"""
API(item)
Processes a Plex media server's XML response
item: xml.etree.ElementTree element
"""
def __init__(self, item): def __init__(self, item):
self.item = item self.item = item
# which child in the XML response shall we look at?
self.child = 0
self.clientinfo = clientinfo.ClientInfo() self.clientinfo = clientinfo.ClientInfo()
self.addonName = self.clientinfo.getAddonName() self.addonName = self.clientinfo.getAddonName()
self.clientId = self.clientinfo.getDeviceId() self.clientId = self.clientinfo.getDeviceId()
@ -1304,10 +1280,16 @@ class API():
self.token = utils.window('emby_accessToken%s' % self.userId) self.token = utils.window('emby_accessToken%s' % self.userId)
def logMsg(self, msg, lvl=1): def logMsg(self, msg, lvl=1):
className = self.__class__.__name__ className = self.__class__.__name__
utils.logMsg("%s %s" % (self.addonName, className), msg, lvl) utils.logMsg("%s %s" % (self.addonName, className), msg, lvl)
def setChildNumber(self, number=0):
"""
Which child in the XML response shall we look at and work with?
"""
self.child = number
self.logMsg("Set child number to %s" % number, 1)
def convert_date(self, stamp): def convert_date(self, stamp):
""" """
convert_date(stamp) converts a Unix time stamp (seconds passed since convert_date(stamp) converts a Unix time stamp (seconds passed since
@ -1334,29 +1316,27 @@ class API():
return localdate return localdate
def getType(self): def getType(self):
"""
Returns the type of media, e.g. 'movie'
"""
item = self.item item = self.item
# Include a letter to prohibit saving as an int! item = item[self.child].attrib
# xml
try:
item = item[0].attrib
# json
except KeyError:
pass
itemtype = item['type'] itemtype = item['type']
return itemtype return itemtype
def getChecksum(self): def getChecksum(self):
""" """
Can be used on both XML and JSON
Returns a string, not int! Returns a string, not int!
""" """
item = self.item item = self.item
# Include a letter to prohibit saving as an int! # XML
# xml
try: try:
item = item[0].attrib item = item[self.child].attrib
# json # JSON
except KeyError: except KeyError:
pass pass
# Include a letter to prohibit saving as an int!
checksum = "K%s%s%s%s%s" % ( checksum = "K%s%s%s%s%s" % (
self.getKey(), self.getKey(),
item['updatedAt'], item['updatedAt'],
@ -1368,14 +1348,15 @@ class API():
def getKey(self): def getKey(self):
""" """
Can be used on both XML and JSON
Returns the Plex unique movie id as a str, not int Returns the Plex unique movie id as a str, not int
""" """
item = self.item item = self.item
key_regex = re.compile(r'/(\d+)$') key_regex = re.compile(r'/(\d+)$')
# xml # XML
try: try:
item = item[0].attrib item = item[self.child].attrib
# json # JSON
except KeyError: except KeyError:
pass pass
key = item['key'] key = item['key']
@ -1383,21 +1364,30 @@ class API():
return str(key) return str(key)
def getDateCreated(self): def getDateCreated(self):
"""
Returns the date when this library item was created
Input:
index child number as int; normally =0
"""
item = self.item item = self.item
# xml item = item[self.child].attrib
try:
item = item[0].attrib
# json
except KeyError:
pass
try:
dateadded = item['addedAt'] dateadded = item['addedAt']
dateadded = self.convert_date(dateadded) dateadded = self.convert_date(dateadded)
except KeyError:
dateadded = None
return dateadded return dateadded
def getUserData(self): def getUserData(self):
"""
Returns a dict with None if a value is missing
{
'Favorite': favorite, # False, because n/a in Plex
'PlayCount': playcount,
'Played': played, # True/False
'LastPlayedDate': lastPlayedDate,
'Resume': resume, # Resume time in seconds
'Rating': rating
}
"""
item = self.item item = self.item
# Default # Default
favorite = False favorite = False
@ -1407,12 +1397,7 @@ class API():
resume = 0 resume = 0
rating = 0 rating = 0
# xml item = item[self.child].attrib
try:
item = item[0].attrib
# json
except KeyError:
pass
try: try:
playcount = int(item['viewCount']) playcount = int(item['viewCount'])
except KeyError: except KeyError:
@ -1443,9 +1428,7 @@ class API():
def getPeople(self): def getPeople(self):
""" """
Input is Plex' XMl Returns a dict of lists of people found.
Returns a dictionary of lists of people found in item.
{ {
'Director': list, 'Director': list,
'Writer': list, 'Writer': list,
@ -1458,7 +1441,7 @@ class API():
writer = [] writer = []
cast = [] cast = []
producer = [] producer = []
for child in item[0]: for child in item[self.child]:
if child.tag == 'Director': if child.tag == 'Director':
director.append(child.attrib['tag']) director.append(child.attrib['tag'])
elif child.tag == 'Writer': elif child.tag == 'Writer':
@ -1481,8 +1464,8 @@ class API():
'Name': xxx, 'Name': xxx,
'Type': xxx, 'Type': xxx,
'Id': xxx 'Id': xxx
'imageurl': url to picture 'imageurl': url to picture, None otherwise
('Role': xxx for cast/actors only) ('Role': xxx for cast/actors only, None if not found)
} }
""" """
item = self.item item = self.item
@ -1494,7 +1477,7 @@ class API():
'Role': 'Actor', 'Role': 'Actor',
'Producer': 'Producer' 'Producer': 'Producer'
} }
for child in item[0]: for child in item[self.child]:
if child.tag in people_of_interest.keys(): if child.tag in people_of_interest.keys():
name = child.attrib['tag'] name = child.attrib['tag']
name_id = child.attrib['id'] name_id = child.attrib['id']
@ -1522,31 +1505,24 @@ class API():
def getGenres(self): def getGenres(self):
""" """
returns a list of genres found in item. (Not a string!!) Returns a list of genres found. (Not a string)
""" """
item = self.item item = self.item
genre = [] genre = []
for child in item[0]: for child in item[self.child]:
if child.tag == 'Genre': if child.tag == 'Genre':
genre.append(child.attrib['tag']) genre.append(child.attrib['tag'])
return genre return genre
def getProvider(self, providername): def getProvider(self, providername):
""" """
provider = getProvider(self, item, providername)
providername: imdb, tvdb, musicBrainzArtist, musicBrainzAlbum, providername: imdb, tvdb, musicBrainzArtist, musicBrainzAlbum,
musicBrainzTrackId musicBrainzTrackId
Return IMDB: "tt1234567" Return IMDB: "tt1234567". Returns None if not found
""" """
item = self.item item = self.item
# xml item = item[self.child].attrib
try:
item = item[0].attrib
# json
except KeyError:
pass
imdb_regex = re.compile(r'''( imdb_regex = re.compile(r'''(
imdb:// # imdb tag, which will be followed be tt1234567 imdb:// # imdb tag, which will be followed be tt1234567
(tt\d{7}) # actual IMDB ID, e.g. tt1234567 (tt\d{7}) # actual IMDB ID, e.g. tt1234567
@ -1570,13 +1546,16 @@ class API():
return provider return provider
def getTitle(self): def getTitle(self):
"""
Returns an item's name/title or "Missing Title Name"
Output:
title, sorttitle
sorttitle = title, if no sorttitle is found
"""
item = self.item item = self.item
# xml item = item[self.child].attrib
try:
item = item[0].attrib
# json
except KeyError:
pass
try: try:
title = item['title'] title = item['title']
except: except:
@ -1588,13 +1567,11 @@ class API():
return title, sorttitle return title, sorttitle
def getPlot(self): def getPlot(self):
"""
Returns the plot or None.
"""
item = self.item item = self.item
# xml item = item[self.child].attrib
try:
item = item[0].attrib
# json
except KeyError:
pass
try: try:
plot = item['summary'] plot = item['summary']
except: except:
@ -1602,13 +1579,11 @@ class API():
return plot return plot
def getTagline(self): def getTagline(self):
"""
Returns a shorter tagline or None
"""
item = self.item item = self.item
# xml item = item[self.child].attrib
try:
item = item[0].attrib
# json
except KeyError:
pass
try: try:
tagline = item['tagline'] tagline = item['tagline']
except KeyError: except KeyError:
@ -1616,13 +1591,11 @@ class API():
return tagline return tagline
def getAudienceRating(self): def getAudienceRating(self):
"""
Returns the audience rating or None
"""
item = self.item item = self.item
# xml item = item[self.child].attrib
try:
item = item[0].attrib
# json
except KeyError:
pass
try: try:
rating = item['audienceRating'] rating = item['audienceRating']
except: except:
@ -1630,13 +1603,11 @@ class API():
return rating return rating
def getYear(self): def getYear(self):
"""
Returns the production(?) year ("year") or None
"""
item = self.item item = self.item
# xml item = item[self.child].attrib
try:
item = item[0].attrib
# json
except KeyError:
pass
try: try:
year = item['year'] year = item['year']
except: except:
@ -1645,20 +1616,21 @@ class API():
def getRuntime(self): def getRuntime(self):
""" """
Resume point of time and runtime/totaltime. Rounded to 6th decimal. Resume point of time and runtime/totaltime in seconds, rounded to 6th
decimal.
Time from Plex server is measured in milliseconds. Time from Plex server is measured in milliseconds.
Kodi: on the Plex side and in seconds on the Kodi side. Kodi: seconds
Output:
resume, runtime as floats. 0.0 if not found
""" """
item = self.item item = self.item
time_factor = 1.0 / 1000.0 # millisecond -> seconds time_factor = 1.0 / 1000.0 # millisecond -> seconds
# xml item = item[self.child].attrib
try: try:
item = item[0].attrib
# json
except KeyError:
pass
runtime = float(item['duration']) runtime = float(item['duration'])
except KeyError:
runtime = 0.0
try: try:
resume = float(item['viewOffset']) resume = float(item['viewOffset'])
except KeyError: except KeyError:
@ -1670,14 +1642,12 @@ class API():
return resume, runtime return resume, runtime
def getMpaa(self): def getMpaa(self):
"""
Get the content rating or None
"""
# Convert more complex cases # Convert more complex cases
item = self.item item = self.item
# xml item = item[self.child].attrib
try:
item = item[0].attrib
# json
except KeyError:
pass
try: try:
mpaa = item['contentRating'] mpaa = item['contentRating']
except KeyError: except KeyError:
@ -1693,18 +1663,17 @@ class API():
""" """
item = self.item item = self.item
country = [] country = []
for child in item[0]: for child in item[self.child]:
if child.tag == 'Country': if child.tag == 'Country':
country.append(child.attrib['tag']) country.append(child.attrib['tag'])
return country return country
def getPremiereDate(self): def getPremiereDate(self):
"""
Returns the "originallyAvailableAt" or None
"""
item = self.item item = self.item
try: item = item[self.child].attrib
item = item[0].attrib
# json
except KeyError:
pass
try: try:
premiere = item['originallyAvailableAt'] premiere = item['originallyAvailableAt']
except: except:
@ -1712,14 +1681,12 @@ class API():
return premiere return premiere
def getStudios(self): def getStudios(self):
"""
Returns a list with a single entry for the studio, or an empty list
"""
item = self.item item = self.item
studio = [] studio = []
# xml item = item[self.child].attrib
try:
item = item[0].attrib
# json
except KeyError:
pass
try: try:
studio.append(self.getStudio(item['studio'])) studio.append(self.getStudio(item['studio']))
except KeyError: except KeyError:
@ -1727,7 +1694,9 @@ class API():
return studio return studio
def getStudio(self, studioName): def getStudio(self, studioName):
# Convert studio for Kodi to properly detect them """
Convert studio for Kodi to properly detect them
"""
studios = { studios = {
'abc (us)': "ABC", 'abc (us)': "ABC",
'fox (us)': "FOX", 'fox (us)': "FOX",
@ -1739,24 +1708,24 @@ class API():
def joinList(self, listobject): def joinList(self, listobject):
""" """
Smart-joins the list into a single string using a " / " separator. Smart-joins the listobject into a single string using a " / "
separator.
If the list is empty, smart_join returns an empty string. If the list is empty, smart_join returns an empty string.
""" """
string = " / ".join(listobject) string = " / ".join(listobject)
return string return string
def getFilePath(self): def getFilePath(self):
"""
returns the path to the Plex object, e.g. "/library/metadata/221803"
"""
item = self.item item = self.item
try: item = item[self.child].attrib
item = item[0].attrib
# json
except KeyError:
pass
try: try:
filepath = item['key'] filepath = item['key']
except KeyError: except KeyError:
filepath = "" filepath = ""
# Plex: do we need this?
else: else:
if "\\\\" in filepath: if "\\\\" in filepath:
# append smb protocol # append smb protocol
@ -1778,26 +1747,53 @@ class API():
return filepath return filepath
def addPlexCredentialsToUrl(self, url, arguments={}): def addPlexCredentialsToUrl(self, url, arguments={}):
"""
Takes an URL and optional arguments (also to be URL-encoded); returns
an extended URL with e.g. the Plex token included.
"""
token = {'X-Plex-Token': self.token} token = {'X-Plex-Token': self.token}
xargs = PlexAPI().getXArgsDeviceInfo(options=token) xargs = PlexAPI().getXArgsDeviceInfo(options=token)
xargs.update(arguments) xargs.update(arguments)
url = "%s?%s" % (url, urlencode(xargs)) url = "%s?%s" % (url, urlencode(xargs))
return url return url
def getBitrate(self):
"""
Returns the bitrate as an int or None
"""
item = self.item
try:
bitrate = item[self.child][0].attrib['bitrate']
bitrate = int(bitrate)
except KeyError:
bitrate = None
return bitrate
def getMediaStreams(self): def getMediaStreams(self):
"""
Returns the media streams
Output: each track contains a dictionaries
{
'video': videotrack-list, 'videocodec', 'height', 'width',
'aspectratio', video3DFormat'
'audio': audiotrack-list, 'audiocodec', 'channels',
'audiolanguage'
'subtitle': list of subtitle languages (or "Unknown")
}
"""
item = self.item item = self.item
videotracks = [] videotracks = []
audiotracks = [] audiotracks = []
subtitlelanguages = [] subtitlelanguages = []
aspectratio = None aspectratio = None
try: try:
aspectratio = item[0][0].attrib['aspectRatio'] aspectratio = item[self.child][0].attrib['aspectRatio']
except KeyError: except KeyError:
pass pass
# Loop over parts:
# TODO: what if several Media tags exist?!? # TODO: what if several Media tags exist?!?
# Loop over parts # Loop over parts
for child in item[0][0]: for child in item[self.child][0]:
container = child.attrib['container'].lower() container = child.attrib['container'].lower()
# Loop over Streams # Loop over Streams
for grandchild in child: for grandchild in child:
@ -1855,7 +1851,20 @@ class API():
return media return media
def getAllArtwork(self, parentInfo=False): def getAllArtwork(self, parentInfo=False):
"""
Gets the URLs to the Plex artwork, or empty string if not found.
Output:
{
'Primary': Plex key: "thumb". Only 1 pix
'Art':,
'Banner':,
'Logo':,
'Thumb':,
'Disc':,
'Backdrop': [] Plex key: "art". Only 1 pix
}
"""
server = self.server server = self.server
item = self.item item = self.item
@ -1870,7 +1879,6 @@ class API():
customquery += "&EnableImageEnhancers=false" customquery += "&EnableImageEnhancers=false"
allartworks = { allartworks = {
'Primary': "", 'Primary': "",
'Art': "", 'Art': "",
'Banner': "", 'Banner': "",
@ -1879,10 +1887,9 @@ class API():
'Disc': "", 'Disc': "",
'Backdrop': [] 'Backdrop': []
} }
# Process backdrops # Process backdrops
# Get background artwork URL # Get background artwork URL
item = item[0].attrib item = item[self.child].attrib
try: try:
background = item['art'] background = item['art']
background = "%s%s" % (server, background) background = "%s%s" % (server, background)
@ -1953,13 +1960,15 @@ class API():
def getTranscodeVideoPath(self, action, quality={}, subtitle={}, audioboost=None, partIndex=None, options={}): def getTranscodeVideoPath(self, action, quality={}, subtitle={}, audioboost=None, partIndex=None, options={}):
""" """
Transcode Video support Transcode Video support; returns the URL to get a media started
Input: Input:
action 'Transcode' OR any other string action 'Transcode' OR any other string
quality: {'videoResolution': 'resolution', quality: {
'videoResolution': 'resolution',
'videoQuality': 'quality', 'videoQuality': 'quality',
'maxVideoBitrate': 'bitrate'} 'maxVideoBitrate': 'bitrate'
}
subtitle {'selected', 'dontBurnIn', 'size'} subtitle {'selected', 'dontBurnIn', 'size'}
audioboost Guess this takes an int as str audioboost Guess this takes an int as str
partIndex No idea partIndex No idea
@ -2029,7 +2038,6 @@ class API():
return transcodePath + urlencode(args) + '&' + urlencode(xargs) return transcodePath + urlencode(args) + '&' + urlencode(xargs)
def adjustResume(self, resume_seconds): def adjustResume(self, resume_seconds):
resume = 0 resume = 0
if resume_seconds: if resume_seconds:
resume = round(float(resume_seconds), 6) resume = round(float(resume_seconds), 6)
@ -2037,35 +2045,21 @@ class API():
if resume > jumpback: if resume > jumpback:
# To avoid negative bookmark # To avoid negative bookmark
resume = resume - jumpback resume = resume - jumpback
return resume return resume
def returnParts(self):
"""
TODO
"""
item = self.item
PartCount = 0
# Run through parts
for child in item[0][0]:
if child.tag == 'Part':
PartCount += PartCount
def externalSubs(self, playurl): def externalSubs(self, playurl):
externalsubs = [] externalsubs = []
mapping = {} mapping = {}
item = self.item item = self.item
itemid = self.getKey() itemid = self.getKey()
try: try:
mediastreams = item[0][0][0] mediastreams = item[self.child][0][0]
except (TypeError, KeyError, IndexError): except (TypeError, KeyError, IndexError):
return return
kodiindex = 0 kodiindex = 0
for stream in mediastreams: for stream in mediastreams:
# index = stream['Index'] # index = stream['Index']
index = stream.attrib['id'] index = stream.attrib['id']
# Since Emby returns all possible tracks together, have to pull only external subtitles. # Since Emby returns all possible tracks together, have to pull only external subtitles.
@ -2087,3 +2081,34 @@ class API():
utils.window('emby_%s.indexMapping' % playurl, value=mapping) utils.window('emby_%s.indexMapping' % playurl, value=mapping)
return externalsubs return externalsubs
def GetPlexPlaylist(self):
"""
Returns raw API metadata XML dump for a playlist with e.g. trailers.
"""
item = self.item
key = self.getKey()
uuid = item.attrib['librarySectionUUID']
mediatype = item[self.child].tag.lower()
trailerNumber = utils.settings('trailerNumber')
if not trailerNumber:
trailerNumber = '3'
url = "{server}/playQueues"
args = {
'type': mediatype,
'uri': 'library://' + uuid +
'/item/%2Flibrary%2Fmetadata%2F' + key,
'includeChapters': '1',
'extrasPrefixCount': trailerNumber,
'shuffle': '0',
'repeat': '0'
}
url = url + '?' + urlencode(args)
xml = downloadutils.DownloadUtils().downloadUrl(
url,
type="POST",
headerOptions={'Accept': 'application/xml'}
)
if not xml:
self.logMsg("Error retrieving metadata for %s" % url, 1)
return xml

View file

@ -190,7 +190,6 @@ class DownloadUtils():
header = plx.getXArgsDeviceInfo(options=options, JSON=True) header = plx.getXArgsDeviceInfo(options=options, JSON=True)
else: else:
header = plx.getXArgsDeviceInfo(options=options, JSON=True) header = plx.getXArgsDeviceInfo(options=options, JSON=True)
self.logMsg("Header: %s" % header, 2)
return header return header
def downloadUrl(self, url, postBody=None, type="GET", parameters=None, authenticate=True, headerOptions={}): def downloadUrl(self, url, postBody=None, type="GET", parameters=None, authenticate=True, headerOptions={}):

View file

@ -278,6 +278,10 @@ class Movies(Items):
# If the item doesn't exist, we'll add it to the database # If the item doesn't exist, we'll add it to the database
update_item = True update_item = True
itemid = API.getKey() itemid = API.getKey()
# Cannot parse XML, abort
if not itemid:
self.logMsg("Cannot parse XML data for movie", -1)
return
emby_dbitem = emby_db.getItem_byId(itemid) emby_dbitem = emby_db.getItem_byId(itemid)
try: try:
movieid = emby_dbitem[0] movieid = emby_dbitem[0]

View file

@ -479,7 +479,7 @@ class LibrarySync(threading.Thread):
all_kodimoviesId = dict(emby_db.getChecksum('Movie')) all_kodimoviesId = dict(emby_db.getChecksum('Movie'))
except ValueError: except ValueError:
all_kodimoviesId = {} all_kodimoviesId = {}
all_plexmoviesIds = [] all_plexmoviesIds = {}
##### PROCESS MOVIES ##### ##### PROCESS MOVIES #####
for view in views: for view in views:
@ -510,7 +510,7 @@ class LibrarySync(threading.Thread):
plex_checksum = API.getChecksum() plex_checksum = API.getChecksum()
itemid = API.getKey() itemid = API.getKey()
kodi_checksum = all_kodimoviesId.get(itemid) kodi_checksum = all_kodimoviesId.get(itemid)
all_plexmoviesIds.append(plex_checksum) all_plexmoviesIds[itemid] = plex_checksum
if kodi_checksum != plex_checksum: if kodi_checksum != plex_checksum:
# 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)
@ -520,7 +520,7 @@ class LibrarySync(threading.Thread):
API = PlexAPI.API(plexmovie) API = PlexAPI.API(plexmovie)
itemid = API.getKey() itemid = API.getKey()
plex_checksum = API.getChecksum() plex_checksum = API.getChecksum()
all_plexmoviesIds.append(plex_checksum) all_plexmoviesIds[itemid] = plex_checksum
updatelist.append(itemid) updatelist.append(itemid)
total = len(updatelist) total = len(updatelist)
@ -532,23 +532,28 @@ class LibrarySync(threading.Thread):
# Process individual movies # Process individual movies
if self.shouldStop(): if self.shouldStop():
return False return False
# Download Metadata
plexmovie = plx.GetPlexMetadata(itemid) plexmovie = plx.GetPlexMetadata(itemid)
# Check whether metadata is valid
title = plexmovie[0].attrib['title'] title = plexmovie[0].attrib['title']
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
# Download individual metadata # Download individual metadata
self.logMsg("Start parsing metadata for movie: %s" % title, 0)
movies.add_update(plexmovie, viewName, viewId) movies.add_update(plexmovie, viewName, viewId)
else: else:
self.logMsg("Movies finished.", 2) self.logMsg("Movies finished.", 2)
##### PROCESS DELETES ##### ##### PROCESS DELETES #####
self.logMsg("all_plexmoviesIds: %s" % all_plexmoviesIds, 0)
self.logMsg("all_kodimoviesId: %s" % all_kodimoviesId, 0)
if compare: if compare:
# Manual sync, process deletes # Manual sync, process deletes
for kodimovie, checksum in all_kodimoviesId.items(): for kodimovie in all_kodimoviesId:
if checksum not in all_plexmoviesIds: if kodimovie not in all_plexmoviesIds:
movies.remove(kodimovie) movies.remove(kodimovie)
else: else:
self.logMsg("Movies compare finished.", 1) self.logMsg("Movies compare finished.", 1)

View file

@ -110,37 +110,41 @@ class PlaybackUtils():
############### -- CHECK FOR INTROS ################ ############### -- CHECK FOR INTROS ################
# PLEX: todo. Seems like Plex returns a playlist WITH trailers # PLEX: todo. Seems like Plex returns a playlist WITH trailers
# if utils.settings('enableCinema') == "true" and not seektime: if utils.settings('enableCinema') == "true" and not seektime:
if False:
# 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 # Download XML playlist associated with the picked movie
intros = doUtils.downloadUrl(url) self.item = API.GetPlexPlaylist()
item = self.item
if intros['TotalRecordCount'] != 0: # And overwrite instances with new item
self.API = PlexAPI.API(item)
API = self.API
playutils = putils.PlayUtils(item)
playListSize = int(self.item.attrib['size'])
if playListSize > 1:
getTrailers = True getTrailers = True
if utils.settings('askCinema') == "true": if utils.settings('askCinema') == "true":
resp = xbmcgui.Dialog().yesno("Emby Cinema Mode", "Play trailers?") resp = xbmcgui.Dialog().yesno("Emby Cinema Mode", "Play trailers?")
if not resp: if not resp:
# User selected to not play trailers # User selected to not play trailers
getTrailers = False getTrailers = False
self.logMsg("Skip trailers.", 1) self.logMsg("Skip trailers.", 1)
if getTrailers: if getTrailers:
for intro in intros['Items']: for i in range(0, playListSize):
# The server randomly returns intros, process them. # The server randomly returns intros, process them
# Set the child in XML Plex response to a trailer
API.setChildNumber(i)
introListItem = xbmcgui.ListItem() introListItem = xbmcgui.ListItem()
introPlayurl = putils.PlayUtils(intro).getPlayUrl() introPlayurl = playutils.getPlayUrl()
self.logMsg("Adding Intro: %s" % introPlayurl, 1) self.logMsg("Adding Trailer: %s" % introPlayurl, 1)
# Set listitem and properties for intros # Set listitem and properties for intros
pbutils = PlaybackUtils(intro) self.setProperties(introPlayurl, introListItem)
pbutils.setProperties(introPlayurl, introListItem)
self.pl.insertintoPlaylist(currentPosition, url=introPlayurl) self.pl.insertintoPlaylist(currentPosition, url=introPlayurl)
introsPlaylist = True introsPlaylist = True
currentPosition += 1 currentPosition += 1
self.logMsg("Successfally added trailer number %s" % i, 1)
# Set "working point" to the movie (last one in playlist)
API.setChildNumber(playListSize - 1)
############### -- ADD MAIN ITEM ONLY FOR HOMESCREEN ############### ############### -- ADD MAIN ITEM ONLY FOR HOMESCREEN ###############
@ -224,7 +228,7 @@ class PlaybackUtils():
# itemid = item['Id'] # itemid = item['Id']
itemid = self.API.getKey() itemid = self.API.getKey()
# itemtype = item['Type'] # itemtype = item['Type']
itemtype = item[0].attrib['type'] itemtype = self.API.getType()
resume, runtime = self.API.getRuntime() resume, runtime = self.API.getRuntime()
embyitem = "emby_%s" % playurl embyitem = "emby_%s" % playurl

View file

@ -28,7 +28,7 @@ class PlayUtils():
self.server = utils.window('emby_server%s' % self.userid) self.server = utils.window('emby_server%s' % self.userid)
self.machineIdentifier = utils.window('plex_machineIdentifier') self.machineIdentifier = utils.window('plex_machineIdentifier')
self.plx = PlexAPI.API(item) self.API = PlexAPI.API(item)
def logMsg(self, msg, lvl=1): def logMsg(self, msg, lvl=1):
@ -58,7 +58,7 @@ class PlayUtils():
if self.isDirectStream(): if self.isDirectStream():
self.logMsg("File is direct streaming.", 1) self.logMsg("File is direct streaming.", 1)
playurl = self.plx.getTranscodeVideoPath('direct') playurl = self.API.getTranscodeVideoPath('direct')
# Set playmethod property # Set playmethod property
utils.window('emby_%s.playmethod' % playurl, value="DirectStream") utils.window('emby_%s.playmethod' % playurl, value="DirectStream")
@ -68,7 +68,7 @@ class PlayUtils():
quality = { quality = {
'bitrate': self.getBitrate() 'bitrate': self.getBitrate()
} }
playurl = self.plx.getTranscodeVideoPath( playurl = self.API.getTranscodeVideoPath(
'Transcode', quality=quality 'Transcode', quality=quality
) )
# Set playmethod property # Set playmethod property
@ -225,11 +225,10 @@ class PlayUtils():
def directStream(self): def directStream(self):
item = self.item
server = self.server server = self.server
itemid = self.plx.getKey() itemid = self.API.getKey()
type = item[0].tag type = self.API.getType()
# if 'Path' in item and item['Path'].endswith('.strm'): # if 'Path' in item and item['Path'].endswith('.strm'):
# # Allow strm loading when direct streaming # # Allow strm loading when direct streaming
@ -239,24 +238,22 @@ class PlayUtils():
else: else:
playurl = "%s/emby/Videos/%s/stream?static=true" % (server, itemid) playurl = "%s/emby/Videos/%s/stream?static=true" % (server, itemid)
playurl = "{server}/player/playback/playMedia?key=%2Flibrary%2Fmetadata%2F%s&offset=0&X-Plex-Client-Identifier={clientId}&machineIdentifier={SERVER ID}&address={SERVER IP}&port={SERVER PORT}&protocol=http&path=http%3A%2F%2F{SERVER IP}%3A{SERVER PORT}%2Flibrary%2Fmetadata%2F{MEDIA ID}" % (itemid) playurl = "{server}/player/playback/playMedia?key=%2Flibrary%2Fmetadata%2F%s&offset=0&X-Plex-Client-Identifier={clientId}&machineIdentifier={SERVER ID}&address={SERVER IP}&port={SERVER PORT}&protocol=http&path=http%3A%2F%2F{SERVER IP}%3A{SERVER PORT}%2Flibrary%2Fmetadata%2F{MEDIA ID}" % (itemid)
playurl = self.plx.replaceURLtags() playurl = self.API.replaceURLtags()
return playurl return playurl
def isNetworkSufficient(self): def isNetworkSufficient(self):
settings = self.getBitrate()*1000 settings = self.getBitrate()
try: sourceBitrate = self.API.getBitrate()
sourceBitrate = int(self.item[0][0].attrib['bitrate']) if not sourceBitrate:
except (KeyError, TypeError): self.logMsg("Bitrate value is missing.", 0)
self.logMsg("Bitrate value is missing.", 1) return True
else:
self.logMsg("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
return True return True
def isTranscoding(self): def isTranscoding(self):