Prep On Deck
This commit is contained in:
parent
a4673b0377
commit
037925a030
8 changed files with 192 additions and 71 deletions
|
@ -68,7 +68,8 @@ class Main:
|
||||||
'switchuser': entrypoint.switchPlexUser,
|
'switchuser': entrypoint.switchPlexUser,
|
||||||
'deviceid': entrypoint.resetDeviceId,
|
'deviceid': entrypoint.resetDeviceId,
|
||||||
'reConnect': entrypoint.reConnect,
|
'reConnect': entrypoint.reConnect,
|
||||||
'delete': entrypoint.deleteItem
|
'delete': entrypoint.deleteItem,
|
||||||
|
'browseplex': entrypoint.BrowsePlexContent
|
||||||
}
|
}
|
||||||
|
|
||||||
if "/extrafanart" in sys.argv[0]:
|
if "/extrafanart" in sys.argv[0]:
|
||||||
|
@ -98,6 +99,12 @@ class Main:
|
||||||
elif mode == "browsecontent":
|
elif mode == "browsecontent":
|
||||||
modes[mode]( itemid, params.get('type',[""])[0], params.get('folderid',[""])[0] )
|
modes[mode]( itemid, params.get('type',[""])[0], params.get('folderid',[""])[0] )
|
||||||
|
|
||||||
|
elif mode == 'browseplex':
|
||||||
|
modes[mode](
|
||||||
|
itemid,
|
||||||
|
params.get('type', [""])[0],
|
||||||
|
params.get('folderid', [""])[0])
|
||||||
|
|
||||||
elif mode == "channelsfolder":
|
elif mode == "channelsfolder":
|
||||||
folderid = params['folderid'][0]
|
folderid = params['folderid'][0]
|
||||||
modes[mode](itemid, folderid)
|
modes[mode](itemid, folderid)
|
||||||
|
|
|
@ -411,4 +411,8 @@
|
||||||
<string id="39407">Full library sync finished</string>
|
<string id="39407">Full library sync finished</string>
|
||||||
<string id="39408">Sync had to skip some items because they could not be processed. Kodi may be instable now!! Please post your Kodi logs to the Plex forum.</string>
|
<string id="39408">Sync had to skip some items because they could not be processed. Kodi may be instable now!! Please post your Kodi logs to the Plex forum.</string>
|
||||||
|
|
||||||
|
<!-- Plex videonodes.py -->
|
||||||
|
<string id="39500">On Deck</string>
|
||||||
|
|
||||||
|
|
||||||
</strings>
|
</strings>
|
||||||
|
|
|
@ -343,4 +343,7 @@
|
||||||
<string id="39407">Plex Bibliotheken aktualisiert</string>
|
<string id="39407">Plex Bibliotheken aktualisiert</string>
|
||||||
<string id="39408">Einige Plex Einträge mussten übersprungen werden, da sie nicht verarbeitet werden konnten. Kodi ist nun möglicherweise instabil!! Bitte teilen Sie Ihr Kodi log im Plex Forum.</string>
|
<string id="39408">Einige Plex Einträge mussten übersprungen werden, da sie nicht verarbeitet werden konnten. Kodi ist nun möglicherweise instabil!! Bitte teilen Sie Ihr Kodi log im Plex Forum.</string>
|
||||||
|
|
||||||
|
<!-- Plex videonodes.py -->
|
||||||
|
<string id="39500">Aktuell</string>
|
||||||
|
|
||||||
</strings>
|
</strings>
|
||||||
|
|
|
@ -2194,8 +2194,75 @@ class API():
|
||||||
mapping[kodiindex] = index
|
mapping[kodiindex] = index
|
||||||
externalsubs.append(url)
|
externalsubs.append(url)
|
||||||
kodiindex += 1
|
kodiindex += 1
|
||||||
|
|
||||||
mapping = json.dumps(mapping)
|
mapping = json.dumps(mapping)
|
||||||
utils.window('emby_%s.indexMapping' % playurl, value=mapping)
|
utils.window('emby_%s.indexMapping' % playurl, value=mapping)
|
||||||
|
|
||||||
return externalsubs
|
return externalsubs
|
||||||
|
|
||||||
|
def CreateListItemFromPlexItem(self, listItem=None):
|
||||||
|
"""
|
||||||
|
Call on a child level of PMS xml response (e.g. in a for loop)
|
||||||
|
|
||||||
|
listItem: existing xbmcgui.ListItem to work with
|
||||||
|
otherwise, a new one is created
|
||||||
|
|
||||||
|
Returns XBMC listitem for this PMS library item
|
||||||
|
"""
|
||||||
|
people = self.getPeople()
|
||||||
|
userdata = self.getUserData()
|
||||||
|
title, sorttitle = self.getTitle()
|
||||||
|
|
||||||
|
if listItem is None:
|
||||||
|
listItem = xbmcgui.ListItem()
|
||||||
|
|
||||||
|
metadata = {
|
||||||
|
'genre': self.joinList(self.getGenres()),
|
||||||
|
'year': self.getYear(),
|
||||||
|
'rating': self.getAudienceRating(),
|
||||||
|
'playcount': userdata['PlayCount'],
|
||||||
|
'cast': people['Cast'],
|
||||||
|
'director': self.joinList(people.get('Director')),
|
||||||
|
'plot': self.getPlot(),
|
||||||
|
'title': title,
|
||||||
|
'sorttitle': sorttitle,
|
||||||
|
'duration': userdata['Runtime'],
|
||||||
|
'studio': self.joinList(self.getStudios()),
|
||||||
|
'tagline': self.getTagline(),
|
||||||
|
'writer': self.joinList(people.get('Writer')),
|
||||||
|
'premiered': self.getPremiereDate(),
|
||||||
|
'dateadded': self.getDateCreated(),
|
||||||
|
'lastplayed': userdata['LastPlayedDate'],
|
||||||
|
'mpaa': self.getMpaa(),
|
||||||
|
'aired': self.getPremiereDate()
|
||||||
|
}
|
||||||
|
|
||||||
|
if "episode" in self.getType():
|
||||||
|
# Only for tv shows
|
||||||
|
key, show, season, episode = self.getEpisodeDetails()
|
||||||
|
metadata['episode'] = episode
|
||||||
|
metadata['season'] = season
|
||||||
|
metadata['tvshowtitle'] = show
|
||||||
|
|
||||||
|
listItem.setProperty('IsPlayable', 'true')
|
||||||
|
listItem.setProperty('IsFolder', 'false')
|
||||||
|
listItem.setProperty('embyid', self.getRatingKey())
|
||||||
|
listItem.setLabel(title)
|
||||||
|
listItem.setInfo('video', infoLabels=metadata)
|
||||||
|
return listItem
|
||||||
|
|
||||||
|
def AddStreamInfo(self, listItem):
|
||||||
|
"""
|
||||||
|
Add media stream information to xbmcgui.ListItem
|
||||||
|
"""
|
||||||
|
mediastreams = self.getMediaStreams()
|
||||||
|
videostreamFound = False
|
||||||
|
if mediastreams:
|
||||||
|
for key, value in mediastreams.iteritems():
|
||||||
|
if key == "video" and value:
|
||||||
|
videostreamFound = True
|
||||||
|
if value:
|
||||||
|
listItem.addStreamInfo(key, value)
|
||||||
|
if not videostreamFound:
|
||||||
|
# just set empty streamdetails to prevent errors in the logs
|
||||||
|
listItem.addStreamInfo(
|
||||||
|
"video", {'duration': self.getRuntime()[1]})
|
||||||
|
|
|
@ -307,7 +307,13 @@ def GetAllPlexLeaves(viewId, lastViewedAt=None, updatedAt=None,
|
||||||
url += '?' + '&'.join(args) + '&'
|
url += '?' + '&'.join(args) + '&'
|
||||||
else:
|
else:
|
||||||
url += '?'
|
url += '?'
|
||||||
|
return DownloadChunks(url, containerSize)
|
||||||
|
|
||||||
|
|
||||||
|
def GetPlexOnDeck(viewId, containerSize=None):
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
url = "{server}/library/sections/%s/onDeck?" % viewId
|
||||||
return DownloadChunks(url, containerSize)
|
return DownloadChunks(url, containerSize)
|
||||||
|
|
||||||
|
|
||||||
|
@ -329,13 +335,13 @@ def GetPlexCollections(mediatype):
|
||||||
"""
|
"""
|
||||||
collections = []
|
collections = []
|
||||||
url = "{server}/library/sections"
|
url = "{server}/library/sections"
|
||||||
jsondata = downloadutils.DownloadUtils().downloadUrl(url)
|
xml = downloadutils.DownloadUtils().downloadUrl(url)
|
||||||
try:
|
try:
|
||||||
result = jsondata['_children']
|
xml.attrib
|
||||||
except KeyError:
|
except AttributeError:
|
||||||
pass
|
logMsg(title, 'Could not download PMS sections for %s' % url, -1)
|
||||||
else:
|
return {}
|
||||||
for item in result:
|
for item in xml:
|
||||||
contentType = item['type']
|
contentType = item['type']
|
||||||
if contentType in mediatype:
|
if contentType in mediatype:
|
||||||
name = item['title']
|
name = item['title']
|
||||||
|
|
|
@ -23,6 +23,7 @@ import playutils
|
||||||
import playlist
|
import playlist
|
||||||
|
|
||||||
import PlexFunctions
|
import PlexFunctions
|
||||||
|
import PlexAPI
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
@ -670,13 +671,19 @@ def GetSubFolders(nodeindex):
|
||||||
|
|
||||||
##### BROWSE EMBY NODES DIRECTLY #####
|
##### BROWSE EMBY NODES DIRECTLY #####
|
||||||
def BrowseContent(viewname, type="", folderid=""):
|
def BrowseContent(viewname, type="", folderid=""):
|
||||||
|
"""
|
||||||
|
Plex:
|
||||||
|
viewname: PMS name of the library
|
||||||
|
type: PMS library section ID
|
||||||
|
folderid: e.g. 'ondeck'
|
||||||
|
"""
|
||||||
emby = embyserver.Read_EmbyServer()
|
emby = embyserver.Read_EmbyServer()
|
||||||
art = artwork.Artwork()
|
art = artwork.Artwork()
|
||||||
doUtils = downloadutils.DownloadUtils()
|
doUtils = downloadutils.DownloadUtils()
|
||||||
|
|
||||||
#folderid used as filter ?
|
#folderid used as filter ?
|
||||||
if folderid in ["recent","recentepisodes","inprogress","inprogressepisodes","unwatched","nextepisodes","sets","genres","random","recommended"]:
|
if folderid in ["recent","recentepisodes","inprogress","inprogressepisodes","unwatched","nextepisodes","sets","genres","random","recommended",
|
||||||
|
"ondeck"]:
|
||||||
filter = folderid
|
filter = folderid
|
||||||
folderid = ""
|
folderid = ""
|
||||||
else:
|
else:
|
||||||
|
@ -685,7 +692,7 @@ def BrowseContent(viewname, type="", folderid=""):
|
||||||
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 = PlexFunctions.GetPlexCollections()
|
||||||
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")
|
||||||
|
@ -1278,3 +1285,66 @@ def RunLibScan(mode):
|
||||||
line1=string(39205))
|
line1=string(39205))
|
||||||
else:
|
else:
|
||||||
utils.window('plex_runLibScan', value='full')
|
utils.window('plex_runLibScan', value='full')
|
||||||
|
|
||||||
|
|
||||||
|
def BrowsePlexContent(viewid, mediatype="", nodetype=""):
|
||||||
|
"""
|
||||||
|
Plex:
|
||||||
|
viewid: PMS name of the library
|
||||||
|
mediatype: mediatype, e.g. 'movies', 'tvshows', 'photos'
|
||||||
|
nodetype: e.g. 'ondeck'
|
||||||
|
"""
|
||||||
|
utils.logMsg(title, "BrowsePlexContent called with viewid: %s, mediatype: %s, nodetype: %s" % (viewid, mediatype, nodetype), 1)
|
||||||
|
|
||||||
|
if nodetype == 'ondeck':
|
||||||
|
xml = PlexFunctions.GetPlexOnDeck(
|
||||||
|
viewid,
|
||||||
|
containerSize=int(utils.settings('limitindex')))
|
||||||
|
if not xml:
|
||||||
|
utils.logMsg(title, "Cannot get view for section %s" % viewid, -1)
|
||||||
|
return
|
||||||
|
|
||||||
|
viewname = xml.attrib.get('librarySectionTitle')
|
||||||
|
xbmcplugin.setPluginCategory(int(sys.argv[1]), viewname)
|
||||||
|
|
||||||
|
# set the correct params for the content type
|
||||||
|
if mediatype.lower() == "homevideos, tvshows":
|
||||||
|
xbmcplugin.setContent(int(sys.argv[1]), 'episodes')
|
||||||
|
itemtype = "Video,Folder,PhotoAlbum"
|
||||||
|
elif mediatype.lower() == "photos":
|
||||||
|
xbmcplugin.setContent(int(sys.argv[1]), 'files')
|
||||||
|
itemtype = "Photo,PhotoAlbum,Folder"
|
||||||
|
else:
|
||||||
|
itemtype = ""
|
||||||
|
|
||||||
|
# process the listing
|
||||||
|
for item in xml:
|
||||||
|
API = PlexAPI.API(item)
|
||||||
|
li = API.CreateListItemFromPlexItem()
|
||||||
|
if item.tag == 'Directory':
|
||||||
|
# for folders we add an additional browse request, passing the
|
||||||
|
# folderId
|
||||||
|
li.setProperty('IsFolder', 'true')
|
||||||
|
li.setProperty('IsPlayable', 'false')
|
||||||
|
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'))
|
||||||
|
xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=path, listitem=li, isFolder=True)
|
||||||
|
else:
|
||||||
|
# playable item, set plugin path and mediastreams
|
||||||
|
path = "%s?id=%s&mode=play" % (sys.argv[0], API.getRatingKey())
|
||||||
|
li.setProperty("path", path)
|
||||||
|
API.AddStreamInfo(li)
|
||||||
|
pbutils.PlaybackUtils(item).setArtwork(li)
|
||||||
|
xbmcplugin.addDirectoryItem(
|
||||||
|
handle=int(sys.argv[1]),
|
||||||
|
url=li.getProperty("path"),
|
||||||
|
listitem=li)
|
||||||
|
|
||||||
|
if filter == "recent":
|
||||||
|
xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_DATE)
|
||||||
|
else:
|
||||||
|
xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_VIDEO_TITLE)
|
||||||
|
xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_DATE)
|
||||||
|
xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_VIDEO_RATING)
|
||||||
|
xbmcplugin.addSortMethod(int(sys.argv[1]), xbmcplugin.SORT_METHOD_VIDEO_RUNTIME)
|
||||||
|
|
||||||
|
xbmcplugin.endOfDirectory(handle=int(sys.argv[1]))
|
||||||
|
|
|
@ -70,7 +70,7 @@ class PlaybackUtils():
|
||||||
window('emby_%s.playmethod' % playurl, "Transcode")
|
window('emby_%s.playmethod' % playurl, "Transcode")
|
||||||
listitem.setPath(playurl)
|
listitem.setPath(playurl)
|
||||||
self.setArtwork(listitem)
|
self.setArtwork(listitem)
|
||||||
self.setListItem(listitem)
|
API.CreateListItemFromPlexItem(listitem)
|
||||||
self.setProperties(playurl, listitem)
|
self.setProperties(playurl, listitem)
|
||||||
return xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem)
|
return xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem)
|
||||||
|
|
||||||
|
@ -159,7 +159,7 @@ class PlaybackUtils():
|
||||||
self.setProperties(additionalPlayurl, additionalListItem)
|
self.setProperties(additionalPlayurl, additionalListItem)
|
||||||
self.setArtwork(additionalListItem)
|
self.setArtwork(additionalListItem)
|
||||||
# NEW to Plex
|
# NEW to Plex
|
||||||
self.setListItem(additionalListItem)
|
API.CreateListItemFromPlexItem(additionalListItem)
|
||||||
|
|
||||||
playlist.add(additionalPlayurl, additionalListItem, index=self.currentPosition)
|
playlist.add(additionalPlayurl, additionalListItem, index=self.currentPosition)
|
||||||
self.pl.verifyPlaylist()
|
self.pl.verifyPlaylist()
|
||||||
|
@ -194,7 +194,7 @@ class PlaybackUtils():
|
||||||
|
|
||||||
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)
|
log("Play as a widget item.", 1)
|
||||||
self.setListItem(listitem)
|
API.CreateListItemFromPlexItem(listitem)
|
||||||
xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem)
|
xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listitem)
|
||||||
|
|
||||||
elif ((introsPlaylist and window('emby_customPlaylist') == "true") or
|
elif ((introsPlaylist and window('emby_customPlaylist') == "true") or
|
||||||
|
@ -368,45 +368,3 @@ class PlaybackUtils():
|
||||||
listItem.setProperty(arttype, path)
|
listItem.setProperty(arttype, path)
|
||||||
else:
|
else:
|
||||||
listItem.setArt({arttype: path})
|
listItem.setArt({arttype: path})
|
||||||
|
|
||||||
def setListItem(self, listItem):
|
|
||||||
|
|
||||||
API = self.API
|
|
||||||
mediaType = API.getType()
|
|
||||||
people = API.getPeople()
|
|
||||||
|
|
||||||
userdata = API.getUserData()
|
|
||||||
title, sorttitle = API.getTitle()
|
|
||||||
|
|
||||||
metadata = {
|
|
||||||
'genre': API.joinList(API.getGenres()),
|
|
||||||
'year': API.getYear(),
|
|
||||||
'rating': API.getAudienceRating(),
|
|
||||||
'playcount': userdata['PlayCount'],
|
|
||||||
'cast': people['Cast'],
|
|
||||||
'director': API.joinList(people.get('Director')),
|
|
||||||
'plot': API.getPlot(),
|
|
||||||
'title': title,
|
|
||||||
'sorttitle': sorttitle,
|
|
||||||
'duration': userdata['Runtime'],
|
|
||||||
'studio': API.joinList(API.getStudios()),
|
|
||||||
'tagline': API.getTagline(),
|
|
||||||
'writer': API.joinList(people.get('Writer')),
|
|
||||||
'premiered': API.getPremiereDate(),
|
|
||||||
'dateadded': API.getDateCreated(),
|
|
||||||
'lastplayed': userdata['LastPlayedDate'],
|
|
||||||
'mpaa': API.getMpaa(),
|
|
||||||
'aired': API.getPremiereDate()
|
|
||||||
}
|
|
||||||
|
|
||||||
if "episode" in mediaType:
|
|
||||||
# Only for tv shows
|
|
||||||
key, show, season, episode = API.getEpisodeDetails()
|
|
||||||
metadata['episode'] = episode
|
|
||||||
metadata['season'] = season
|
|
||||||
metadata['tvshowtitle'] = show
|
|
||||||
|
|
||||||
listItem.setProperty('IsPlayable', 'true')
|
|
||||||
listItem.setProperty('IsFolder', 'false')
|
|
||||||
listItem.setLabel(metadata['title'])
|
|
||||||
listItem.setInfo('video', infoLabels=metadata)
|
|
||||||
|
|
|
@ -127,6 +127,7 @@ class VideoNodes(object):
|
||||||
'9': "genres",
|
'9': "genres",
|
||||||
'10': "random",
|
'10': "random",
|
||||||
'11': "recommended",
|
'11': "recommended",
|
||||||
|
'12': "ondeck"
|
||||||
}
|
}
|
||||||
mediatypes = {
|
mediatypes = {
|
||||||
# label according to nodetype per mediatype
|
# label according to nodetype per mediatype
|
||||||
|
@ -152,10 +153,11 @@ class VideoNodes(object):
|
||||||
'7': 30179,
|
'7': 30179,
|
||||||
'9': 135,
|
'9': 135,
|
||||||
'10': 30229,
|
'10': 30229,
|
||||||
'11': 30230
|
'11': 30230,
|
||||||
|
'12': 39500
|
||||||
},
|
},
|
||||||
|
|
||||||
'homevideoss':
|
'homevideos':
|
||||||
{
|
{
|
||||||
'1': tagname,
|
'1': tagname,
|
||||||
'2': 30251,
|
'2': 30251,
|
||||||
|
@ -211,6 +213,10 @@ class VideoNodes(object):
|
||||||
elif kodiversion == 14 and nodetype == "inprogressepisodes":
|
elif kodiversion == 14 and nodetype == "inprogressepisodes":
|
||||||
# Custom query
|
# Custom query
|
||||||
path = "plugin://plugin.video.plexkodiconnect/?id=%s&mode=inprogressepisodes&limit=50"% tagname
|
path = "plugin://plugin.video.plexkodiconnect/?id=%s&mode=inprogressepisodes&limit=50"% tagname
|
||||||
|
elif nodetype == 'ondeck':
|
||||||
|
# PLEX custom query
|
||||||
|
path = ("plugin://plugin.video.plexkodiconnect/?id=%s&mode=browseplex&type=%s&folderid=%s"
|
||||||
|
% (viewid, mediatype, nodetype))
|
||||||
else:
|
else:
|
||||||
path = "library://video/Plex-%s/%s_%s.xml" % (dirname, viewid, nodetype)
|
path = "library://video/Plex-%s/%s_%s.xml" % (dirname, viewid, nodetype)
|
||||||
|
|
||||||
|
@ -248,7 +254,7 @@ class VideoNodes(object):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Create the root
|
# Create the root
|
||||||
if (nodetype == "nextepisodes" or mediatype == "homevideos" or
|
if (nodetype in ("nextepisodes", "ondeck") or mediatype == "homevideos" or
|
||||||
(kodiversion == 14 and nodetype in ('recentepisodes', 'inprogressepisodes'))):
|
(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)
|
||||||
|
|
Loading…
Reference in a new issue