Merge branch 'master' into translations

This commit is contained in:
tomkat83 2017-03-08 19:11:16 +01:00
commit d57d55d070
10 changed files with 463 additions and 300 deletions

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="plugin.video.plexkodiconnect"
name="PlexKodiConnect"
version="1.6.4"
version="1.6.5"
provider-name="croneter">
<requires>
<import addon="xbmc.python" version="2.1.0"/>

View file

@ -1,3 +1,9 @@
version 1.6.5 (beta only)
- Plex Channels!
- Browse video nodes by folder/path
- Update Danish translation
- Code optimization
version 1.6.4 (beta only)
- Amazon Alexa support! Be mindful to check the Alexa forum thread first; there are still many issues completely unrelated to PKC
- Enable skipping for Plex Companion

View file

@ -36,13 +36,14 @@ from utils import window, pickl_window, reset, passwordsXML, language as lang,\
dialog
from pickler import unpickle_me
from PKC_listitem import convert_PKC_to_listitem
import variables as v
###############################################################################
import loghandler
loghandler.config()
log = logging.getLogger("PLEX.default")
log = logging.getLogger('PLEX.default')
###############################################################################
@ -50,144 +51,160 @@ HANDLE = int(argv[1])
class Main():
# MAIN ENTRY POINT
# @utils.profiling()
def __init__(self):
log.debug("Full sys.argv received: %s" % argv)
log.debug('Full sys.argv received: %s' % argv)
# Parse parameters
params = dict(parse_qsl(argv[2][1:]))
try:
mode = params['mode']
itemid = params.get('id', '')
except:
mode = ""
itemid = ''
mode = params.get('mode', '')
itemid = params.get('id', '')
if mode == 'play':
# Put the request into the "queue"
while window('plex_play_new_item'):
sleep(50)
window('plex_play_new_item',
value='%s%s' % (mode, argv[2]))
# Wait for the result
while not pickl_window('plex_result'):
sleep(50)
result = unpickle_me()
if result is None:
log.error('Error encountered, aborting')
dialog('notification',
heading='{plex}',
message=lang(30128),
icon='{error}',
time=3000)
setResolvedUrl(HANDLE, False, ListItem())
elif result.listitem:
listitem = convert_PKC_to_listitem(result.listitem)
setResolvedUrl(HANDLE, True, listitem)
return
self.play()
modes = {
'reset': reset,
'resetauth': entrypoint.resetAuth,
'passwords': passwordsXML,
'getsubfolders': entrypoint.GetSubFolders,
'nextup': entrypoint.getNextUpEpisodes,
'inprogressepisodes': entrypoint.getInProgressEpisodes,
'recentepisodes': entrypoint.getRecentEpisodes,
'refreshplaylist': entrypoint.refreshPlaylist,
'switchuser': entrypoint.switchPlexUser,
'deviceid': entrypoint.resetDeviceId,
'browseplex': entrypoint.BrowsePlexContent,
'ondeck': entrypoint.getOnDeck,
'chooseServer': entrypoint.chooseServer,
'watchlater': entrypoint.watchlater,
'enterPMS': entrypoint.enterPMS,
'togglePlexTV': entrypoint.togglePlexTV,
'Plex_Node': entrypoint.Plex_Node
}
elif mode == 'ondeck':
entrypoint.getOnDeck(itemid,
params.get('type'),
params.get('tagname'),
int(params.get('limit')))
if "/extrafanart" in argv[0]:
plexpath = argv[2][1:]
plexid = params.get('id')
entrypoint.getExtraFanArt(plexid, plexpath)
entrypoint.getVideoFiles(plexid, plexpath)
return
elif mode == 'recentepisodes':
entrypoint.getRecentEpisodes(itemid,
params.get('type'),
params.get('tagname'),
int(params.get('limit')))
if mode == 'fanart':
elif mode == 'nextup':
entrypoint.getNextUpEpisodes(params['tagname'],
int(params['limit']))
elif mode == 'inprogressepisodes':
entrypoint.getInProgressEpisodes(params['tagname'],
int(params['limit']))
elif mode == 'Plex_Node':
entrypoint.Plex_Node(itemid, params.get('viewOffset'))
elif mode == 'browseplex':
entrypoint.browse_plex(key=params.get('key'),
plex_section_id=params.get('id'))
elif mode == 'getsubfolders':
entrypoint.GetSubFolders(itemid)
elif mode == 'watchlater':
entrypoint.watchlater()
elif mode == 'channels':
entrypoint.channels()
elif mode == 'settings':
executebuiltin('Addon.OpenSettings(%s)' % v.ADDON_ID)
elif mode == 'enterPMS':
entrypoint.enterPMS()
elif mode == 'reset':
reset()
elif mode == 'togglePlexTV':
entrypoint.togglePlexTV()
elif mode == 'resetauth':
entrypoint.resetAuth()
elif mode == 'passwords':
passwordsXML()
elif mode == 'switchuser':
entrypoint.switchPlexUser()
elif mode in ('manualsync', 'repair'):
if window('plex_online') != 'true':
# Server is not online, do not run the sync
dialog('ok',
heading=lang(29999),
message=lang(39205))
log.error('Not connected to a PMS.')
else:
if mode == 'repair':
window('plex_runLibScan', value='repair')
log.info('Requesting repair lib sync')
elif mode == 'manualsync':
log.info('Requesting full library scan')
window('plex_runLibScan', value='full')
elif mode == 'texturecache':
window('plex_runLibScan', value='del_textures')
elif mode == 'chooseServer':
entrypoint.chooseServer()
elif mode == 'refreshplaylist':
log.info('Requesting playlist/nodes refresh')
window('plex_runLibScan', value='views')
elif mode == 'deviceid':
self.deviceid()
elif mode == 'fanart':
log.info('User requested fanarttv refresh')
window('plex_runLibScan', value='fanart')
elif '/extrafanart' in argv[0]:
plexpath = argv[2][1:]
plexid = itemid
entrypoint.getExtraFanArt(plexid, plexpath)
entrypoint.getVideoFiles(plexid, plexpath)
# Called by e.g. 3rd party plugin video extras
if ("/Extras" in argv[0] or "/VideoFiles" in argv[0] or
"/Extras" in argv[2]):
plexId = params.get('id', None)
elif ('/Extras' in argv[0] or '/VideoFiles' in argv[0] or
'/Extras' in argv[2]):
plexId = itemid or None
entrypoint.getVideoFiles(plexId, params)
if modes.get(mode):
# Simple functions
if mode == "play":
dbid = params.get('dbid')
# modes[mode](itemid, dbid)
modes[mode](itemid, dbid)
elif mode in ("nextup", "inprogressepisodes"):
limit = int(params['limit'])
modes[mode](params['tagname'], limit)
elif mode in ("channels","getsubfolders"):
modes[mode](itemid)
elif mode == "browsecontent":
modes[mode](itemid, params.get('type'), params.get('folderid'))
elif mode == 'browseplex':
modes[mode](
itemid,
params.get('type'),
params.get('folderid'))
elif mode in ('ondeck', 'recentepisodes'):
modes[mode](
itemid,
params.get('type'),
params.get('tagname'),
int(params.get('limit')))
elif mode == "channelsfolder":
folderid = params['folderid']
modes[mode](itemid, folderid)
elif mode == "companion":
modes[mode](itemid, params=argv[2])
elif mode == 'Plex_Node':
modes[mode](params.get('id'),
params.get('viewOffset'))
else:
modes[mode]()
else:
# Other functions
if mode == "settings":
executebuiltin('Addon.OpenSettings(plugin.video.plexkodiconnect)')
elif mode in ("manualsync", "repair"):
if window('plex_online') != "true":
# Server is not online, do not run the sync
dialog('ok',
heading=lang(29999),
message=lang(39205))
log.error("Not connected to a PMS.")
else:
if mode == 'repair':
window('plex_runLibScan', value="repair")
log.info("Requesting repair lib sync")
elif mode == 'manualsync':
log.info("Requesting full library scan")
window('plex_runLibScan', value="full")
elif mode == "texturecache":
window('plex_runLibScan', value='del_textures')
else:
entrypoint.doMainListing()
entrypoint.doMainListing()
if __name__ == "__main__":
log.info('plugin.video.plexkodiconnect started')
def play(self):
# Put the request into the 'queue'
while window('plex_play_new_item'):
sleep(50)
window('plex_play_new_item',
value='%s%s' % ('play', argv[2]))
# Wait for the result
while not pickl_window('plex_result'):
sleep(50)
result = unpickle_me()
if result is None:
log.error('Error encountered, aborting')
dialog('notification',
heading='{plex}',
message=lang(30128),
icon='{error}',
time=3000)
setResolvedUrl(HANDLE, False, ListItem())
elif result.listitem:
listitem = convert_PKC_to_listitem(result.listitem)
setResolvedUrl(HANDLE, True, listitem)
def deviceid(self):
deviceId_old = window('plex_client_Id')
from clientinfo import getDeviceId
try:
deviceId = getDeviceId(reset=True)
except Exception as e:
log.error('Failed to generate a new device Id: %s' % e)
dialog('ok', lang(29999), lang(33032))
else:
log.info('Successfully removed old device ID: %s New deviceId:'
'%s' % (deviceId_old, deviceId))
# 'Kodi will now restart to apply the changes'
dialog('ok', lang(29999), lang(33033))
executebuiltin('RestartApp')
if __name__ == '__main__':
log.info('%s started' % v.ADDON_ID)
Main()
log.info('plugin.video.plexkodiconnect stopped')
log.info('%s stopped' % v.ADDON_ID)

View file

@ -515,5 +515,5 @@
<string id="39603">Nulstil alle indstillinger for PlexKodiConnect Addon? (dette er normalt ikke anbefalet og unødvendigt!)</string>
<string id="39700">Amazon Alexa (Voice Recognition)</string>
<string id="39701">Activate Alexa</string>
<string id="39701">Alexa aktivieren</string>
</strings>

View file

@ -516,4 +516,5 @@
<string id="39700">Amazon Alexa (Voice Recognition)</string>
<string id="39701">Activate Alexa</string>
</strings>
<string id="39702">Browse by folder</string>
</strings>

View file

@ -106,7 +106,10 @@ def Plex_Node(url, viewOffset, playdirectly=False, node=True):
log.info('Plex_Node called with url: %s, viewOffset: %s'
% (url, viewOffset))
# Plex redirect, e.g. watch later. Need to get actual URLs
xml = downloadutils.DownloadUtils().downloadUrl(url)
if url.startswith('http'):
xml = downloadutils.DownloadUtils().downloadUrl(url)
else:
xml = downloadutils.DownloadUtils().downloadUrl('{server}%s' % url)
try:
xml[0].attrib
except:
@ -194,6 +197,9 @@ def doMainListing():
# Plex Watch later
addDirectoryItem(lang(39211),
"plugin://plugin.video.plexkodiconnect/?mode=watchlater")
# Plex Channels
addDirectoryItem(lang(30173),
"plugin://plugin.video.plexkodiconnect/?mode=channels")
# Plex user switch
addDirectoryItem(lang(39200) + window('plex_username'),
"plugin://plugin.video.plexkodiconnect/"
@ -211,23 +217,6 @@ def doMainListing():
xbmcplugin.endOfDirectory(HANDLE)
##### Generate a new deviceId
def resetDeviceId():
deviceId_old = window('plex_client_Id')
from clientinfo import getDeviceId
try:
deviceId = getDeviceId(reset=True)
except Exception as e:
log.error("Failed to generate a new device Id: %s" % e)
dialog('ok', lang(29999), lang(33032))
else:
log.info("Successfully removed old deviceId: %s New deviceId: %s"
% (deviceId_old, deviceId))
# "Kodi will now restart to apply the changes"
dialog('ok', lang(29999), lang(33033))
executebuiltin('RestartApp')
def switchPlexUser():
"""
Signs out currently logged in user (if applicable). Triggers sign-in of a
@ -249,12 +238,6 @@ def switchPlexUser():
__LogIn()
##### REFRESH EMBY PLAYLISTS #####
def refreshPlaylist():
log.info('Requesting playlist/nodes refresh')
window('plex_runLibScan', value="views")
#### SHOW SUBFOLDERS FOR NODE #####
def GetSubFolders(nodeindex):
nodetypes = ["",".recent",".recentepisodes",".inprogress",".inprogressepisodes",".unwatched",".nextepisodes",".sets",".genres",".random",".recommended"]
@ -661,83 +644,6 @@ def RunLibScan(mode):
window('plex_runLibScan', value='full')
def BrowsePlexContent(viewid, mediatype="", folderid=""):
"""
Browse Plex Photos:
viewid: PMS name of the library
mediatype: mediatype, 'photos'
nodetype: e.g. 'ondeck' (TBD!!)
"""
log.debug("BrowsePlexContent called with viewid: %s, mediatype: "
"%s, folderid: %s" % (viewid, mediatype, folderid))
if not folderid:
# Top-level navigation, so get the content of this section
# Get all sections
xml = GetPlexSectionResults(
viewid,
containerSize=int(settings('limitindex')))
try:
xml.attrib
except AttributeError:
log.error("Error download section %s" % viewid)
return xbmcplugin.endOfDirectory(HANDLE, False)
else:
# folderid was passed so we can directly access the folder
xml = downloadutils.DownloadUtils().downloadUrl(
"{server}%s" % folderid)
try:
xml.attrib
except AttributeError:
log.error("Error downloading %s" % folderid)
return xbmcplugin.endOfDirectory(HANDLE, False)
# Set the folder's name
xbmcplugin.setPluginCategory(HANDLE,
xml.attrib.get('librarySectionTitle'))
# set the correct params for the content type
if mediatype == "photos":
xbmcplugin.setContent(HANDLE, 'photos')
# process the listing
for item in xml:
api = API(item)
if item.tag == 'Directory':
li = ListItem(item.attrib.get('title', 'Missing title'))
# for folders we add an additional browse request, passing the
# folderId
li.setProperty('IsFolder', 'true')
li.setProperty('IsPlayable', 'false')
path = "%s?id=%s&mode=browseplex&type=%s&folderid=%s" \
% (ARGV_0, viewid, mediatype, api.getKey())
api.set_listitem_artwork(li)
xbmcplugin.addDirectoryItem(handle=HANDLE,
url=path,
listitem=li,
isFolder=True)
else:
li = api.CreateListItemFromPlexItem()
api.set_listitem_artwork(li)
xbmcplugin.addDirectoryItem(
handle=HANDLE,
url=li.getProperty("path"),
listitem=li)
xbmcplugin.addSortMethod(HANDLE,
xbmcplugin.SORT_METHOD_VIDEO_TITLE)
xbmcplugin.addSortMethod(HANDLE,
xbmcplugin.SORT_METHOD_DATE)
xbmcplugin.addSortMethod(HANDLE,
xbmcplugin.SORT_METHOD_VIDEO_RATING)
xbmcplugin.addSortMethod(HANDLE,
xbmcplugin.SORT_METHOD_VIDEO_RUNTIME)
xbmcplugin.endOfDirectory(
handle=HANDLE,
cacheToDisc=settings('enableTextureCache') == 'true')
def getOnDeck(viewid, mediatype, tagname, limit):
"""
Retrieves Plex On Deck items, currently only for TV shows
@ -905,28 +811,175 @@ def watchlater():
log.info('Displaying watch later plex.tv items')
xbmcplugin.setContent(HANDLE, 'movies')
url = "plugin://plugin.video.plexkodiconnect/"
params = {
'mode': "Plex_Node",
}
for item in xml:
api = API(item)
listitem = api.CreateListItemFromPlexItem()
api.AddStreamInfo(listitem)
api.set_listitem_artwork(listitem)
params['id'] = item.attrib.get('key')
params['viewOffset'] = item.attrib.get('viewOffset', '0')
params['plex_type'] = item.attrib.get('type')
xbmcplugin.addDirectoryItem(
handle=HANDLE,
url="%s?%s" % (url, urlencode(params)),
listitem=listitem)
__build_item(item)
xbmcplugin.endOfDirectory(
handle=HANDLE,
cacheToDisc=settings('enableTextureCache') == 'true')
def channels():
"""
Listing for Plex Channels
"""
if window('plex_restricteduser') == 'true':
log.error('No Plex Channels - restricted user')
return xbmcplugin.endOfDirectory(HANDLE, False)
xml = downloadutils.DownloadUtils().downloadUrl('{server}/channels/all')
try:
xml[0].attrib
except (ValueError, AttributeError, IndexError):
log.error('Could not download Plex Channels')
return xbmcplugin.endOfDirectory(HANDLE, False)
log.info('Displaying Plex Channels')
xbmcplugin.setContent(HANDLE, 'files')
for method in v.SORT_METHODS_DIRECTORY:
xbmcplugin.addSortMethod(HANDLE, getattr(xbmcplugin, method))
for item in xml:
__build_folder(item)
xbmcplugin.endOfDirectory(
handle=HANDLE,
cacheToDisc=settings('enableTextureCache') == 'true')
def browse_plex(key=None, plex_section_id=None):
"""
Lists the content of a Plex folder, e.g. channels. Either pass in key (to
be used directly for PMS url {server}<key>) or the plex_section_id
"""
if key:
xml = downloadutils.DownloadUtils().downloadUrl('{server}%s' % key)
else:
xml = GetPlexSectionResults(
plex_section_id,
containerSize=int(settings('limitindex')))
try:
xml[0].attrib
except (ValueError, AttributeError, IndexError):
log.error('Could not browse to %s' % key)
return xbmcplugin.endOfDirectory(HANDLE, False)
photos = False
movies = False
clips = False
tvshows = False
episodes = False
songs = False
artists = False
albums = False
musicvideos = False
for item in xml:
typus = item.attrib.get('type')
if item.tag == 'Directory':
__build_folder(item, plex_section_id=plex_section_id)
else:
__build_item(item)
if typus == v.PLEX_TYPE_PHOTO:
photos = True
elif typus == v.PLEX_TYPE_MOVIE:
movies = True
elif typus == v.PLEX_TYPE_CLIP:
clips = True
elif typus in (v.PLEX_TYPE_SHOW, v.PLEX_TYPE_SEASON):
tvshows = True
elif typus == v.PLEX_TYPE_EPISODE:
episodes = True
elif typus == v.PLEX_TYPE_SONG:
songs = True
elif typus == v.PLEX_TYPE_ARTIST:
artists = True
elif typus == v.PLEX_TYPE_ALBUM:
albums = True
elif typus == v.PLEX_TYPE_MUSICVIDEO:
musicvideos = True
# Set the correct content type
if movies is True:
xbmcplugin.setContent(HANDLE, 'movies')
sort_methods = v.SORT_METHODS_MOVIES
elif clips is True:
xbmcplugin.setContent(HANDLE, 'movies')
sort_methods = v.SORT_METHODS_CLIPS
elif photos is True:
xbmcplugin.setContent(HANDLE, 'files')
sort_methods = v.SORT_METHODS_PHOTOS
elif tvshows is True:
xbmcplugin.setContent(HANDLE, 'tvshows')
sort_methods = v.SORT_METHOD_TVSHOWS
elif episodes is True:
xbmcplugin.setContent(HANDLE, 'episodes')
sort_methods = v.SORT_METHODS_EPISODES
elif songs is True:
xbmcplugin.setContent(HANDLE, 'songs')
sort_methods = v.SORT_METHODS_SONGS
elif artists is True:
xbmcplugin.setContent(HANDLE, 'artists')
sort_methods = v.SORT_METHODS_ARTISTS
elif albums is True:
xbmcplugin.setContent(HANDLE, 'albums')
sort_methods = v.SORT_METHODS_ALBUMS
elif musicvideos is True:
xbmcplugin.setContent(HANDLE, 'musicvideos')
sort_methods = v.SORT_METHODS_MOVIES
else:
xbmcplugin.setContent(HANDLE, 'files')
sort_methods = v.SORT_METHODS_DIRECTORY
for method in sort_methods:
xbmcplugin.addSortMethod(HANDLE, getattr(xbmcplugin, method))
# Set the Kodi title for this view
title = xml.attrib.get('librarySectionTitle', xml.attrib.get('title1'))
xbmcplugin.setPluginCategory(HANDLE, title)
xbmcplugin.endOfDirectory(
handle=HANDLE,
cacheToDisc=settings('enableTextureCache') == 'true')
def __build_folder(xml_element, plex_section_id=None):
url = "plugin://%s/" % v.ADDON_ID
key = xml_element.attrib.get('fastKey', xml_element.attrib.get('key'))
if not key.startswith('/'):
key = '/library/sections/%s/%s' % (plex_section_id, key)
params = {
'mode': "browseplex",
'key': key,
'id': plex_section_id
}
listitem = ListItem(xml_element.attrib.get('title'))
listitem.setArt({'thumb': xml_element.attrib.get('thumb'),
'poster': xml_element.attrib.get('art')})
xbmcplugin.addDirectoryItem(handle=HANDLE,
url="%s?%s" % (url, urlencode(params)),
isFolder=True,
listitem=listitem)
def __build_item(xml_element):
api = API(xml_element)
listitem = api.CreateListItemFromPlexItem()
api.AddStreamInfo(listitem)
api.set_listitem_artwork(listitem)
if api.getType() != v.PLEX_TYPE_PHOTO:
url = "plugin://%s/" % v.ADDON_ID
params = {
'mode': "Plex_Node",
'id': xml_element.attrib.get('key'),
'viewOffset': xml_element.attrib.get('viewOffset', '0'),
'plex_type': xml_element.attrib.get('type')
}
url = '%s?%s' % (url, urlencode(params))
else:
url = listitem.getProperty('path')
xbmcplugin.addDirectoryItem(handle=HANDLE,
url=url,
listitem=listitem)
def enterPMS():
"""
Opens dialogs for the user the plug in the PMS details

View file

@ -53,6 +53,8 @@ class Playqueue(Thread):
else:
# Currently, only video or audio playqueues available
playqueue.kodi_pl = PlayList(PLAYLIST_VIDEO)
# Overwrite 'picture' with 'photo'
playqueue.type = v.KODI_TYPE_PHOTO
self.playqueues.append(playqueue)
# sort the list by their playlistid, just in case
self.playqueues = sorted(

View file

@ -70,19 +70,6 @@ class PlayUtils():
log.info("The playurl is: %s" % playurl)
return playurl
def httpPlay(self):
# Audio, Video, Photo
itemid = self.item['Id']
mediatype = self.item['MediaType']
if mediatype == "Audio":
playurl = "%s/emby/Audio/%s/stream" % (self.server, itemid)
else:
playurl = "%s/emby/Videos/%s/stream?static=true" % (self.server, itemid)
return playurl
def isDirectPlay(self):
"""
Returns the path/playurl if we can direct play, None otherwise

View file

@ -113,6 +113,7 @@ PLEX_TYPE_AUDIO = 'music'
PLEX_TYPE_SONG = 'track'
PLEX_TYPE_ALBUM = 'album'
PLEX_TYPE_ARTIST = 'artist'
PLEX_TYPE_MUSICVIDEO = 'musicvideo'
PLEX_TYPE_PHOTO = 'photo'
@ -131,6 +132,7 @@ KODI_TYPE_AUDIO = 'audio'
KODI_TYPE_SONG = 'song'
KODI_TYPE_ALBUM = 'album'
KODI_TYPE_ARTIST = 'artist'
KODI_TYPE_MUSICVIDEO = 'musicvideo'
KODI_TYPE_PHOTO = 'photo'
@ -195,7 +197,8 @@ KODI_PLAYLIST_TYPE_FROM_PLEX_TYPE = {
PLEX_TYPE_ARTIST: KODI_TYPE_AUDIO,
PLEX_TYPE_ALBUM: KODI_TYPE_AUDIO,
PLEX_TYPE_SONG: KODI_TYPE_AUDIO,
PLEX_TYPE_AUDIO: KODI_TYPE_AUDIO
PLEX_TYPE_AUDIO: KODI_TYPE_AUDIO,
PLEX_TYPE_PHOTO: KODI_TYPE_PHOTO
}
@ -266,3 +269,88 @@ ALEXA_TO_COMPANION = {
'queryContainerKey': 'containerKey',
'queryToken': 'token',
}
# Kodi sort methods for xbmcplugin.addSortMethod()
SORT_METHODS_DIRECTORY = (
'SORT_METHOD_UNSORTED', # sorted as returned from Plex
'SORT_METHOD_LABEL',
)
SORT_METHODS_PHOTOS = (
'SORT_METHOD_UNSORTED',
'SORT_METHOD_LABEL',
'SORT_METHOD_DATE',
'SORT_METHOD_DATEADDED',
)
SORT_METHODS_CLIPS = (
'SORT_METHOD_UNSORTED',
'SORT_METHOD_TITLE',
'SORT_METHOD_DURATION',
)
SORT_METHODS_MOVIES = (
'SORT_METHOD_UNSORTED',
'SORT_METHOD_TITLE',
'SORT_METHOD_DURATION',
'SORT_METHOD_VIDEO_RATING',
'SORT_METHOD_VIDEO_USER_RATING',
'SORT_METHOD_MPAA_RATING',
'SORT_METHOD_COUNTRY',
'SORT_METHOD_STUDIO',
'SORT_METHOD_GENRE',
)
SORT_METHOD_TVSHOWS = (
'SORT_METHOD_UNSORTED',
'SORT_METHOD_TITLE',
'SORT_METHOD_VIDEO_RATING',
'SORT_METHOD_VIDEO_USER_RATING',
'SORT_METHOD_MPAA_RATING',
'SORT_METHOD_COUNTRY',
'SORT_METHOD_GENRE',
)
SORT_METHODS_EPISODES = (
'SORT_METHOD_UNSORTED',
'SORT_METHOD_TITLE',
'SORT_METHOD_EPISODE',
'SORT_METHOD_DURATION',
'SORT_METHOD_VIDEO_RATING',
'SORT_METHOD_VIDEO_USER_RATING',
'SORT_METHOD_MPAA_RATING',
'SORT_METHOD_FILE',
'SORT_METHOD_FULLPATH',
)
SORT_METHODS_SONGS = (
'SORT_METHOD_UNSORTED',
'SORT_METHOD_TITLE',
'SORT_METHOD_TRACKNUM',
'SORT_METHOD_DURATION',
'SORT_METHOD_ARTIST',
'SORT_METHOD_ARTIST_AND_YEAR',
'SORT_METHOD_ALBUM',
'SORT_METHOD_SONG_RATING',
'SORT_METHOD_SONG_USER_RATING'
)
SORT_METHODS_ARTISTS = (
'SORT_METHOD_UNSORTED',
'SORT_METHOD_TITLE',
'SORT_METHOD_TRACKNUM',
'SORT_METHOD_DURATION',
'SORT_METHOD_ARTIST',
'SORT_METHOD_ARTIST_AND_YEAR',
'SORT_METHOD_ALBUM',
)
SORT_METHODS_ALBUMS = (
'SORT_METHOD_UNSORTED',
'SORT_METHOD_TITLE',
'SORT_METHOD_TRACKNUM',
'SORT_METHOD_DURATION',
'SORT_METHOD_ARTIST',
'SORT_METHOD_ARTIST_AND_YEAR',
'SORT_METHOD_ALBUM',
)

View file

@ -102,7 +102,7 @@ class VideoNodes(object):
return
if mediatype == "photos":
path = "plugin://plugin.video.plexkodiconnect/?id=%s&mode=getsubfolders" % indexnumber
path = "plugin://plugin.video.plexkodiconnect?mode=browseplex&key=/library/sections/%s&id=%s" % (viewid, viewid)
window('Plex.nodes.%s.index' % indexnumber, value=path)
@ -131,58 +131,64 @@ class VideoNodes(object):
'9': "genres",
'10': "random",
'11': "recommended",
'12': "ondeck"
'12': "ondeck",
'13': 'browsefiles'
}
mediatypes = {
# label according to nodetype per mediatype
'movies':
'movies':
{
'1': tagname,
'2': 30174,
# '4': 30177,
# '6': 30189,
'8': 39501,
'9': 135,
'10': 30227,
'11': 30230,
'12': 39500,
'1': tagname,
'2': 30174,
# '4': 30177,
# '6': 30189,
'8': 39501,
'9': 135,
'10': 30227,
'11': 30230,
'12': 39500,
'13': 39702
},
'tvshows':
'tvshows':
{
'1': tagname,
# '2': 30170,
'3': 30174,
# '4': 30171,
# '5': 30178,
# '7': 30179,
'9': 135,
'10': 30227,
# '11': 30230,
'12': 39500,
},
'homevideos':
{
'1': tagname,
'2': 30251,
'11': 30253
},
'photos':
{
'1': tagname,
'2': 30252,
'8': 30255,
'11': 30254
'1': tagname,
# '2': 30170,
'3': 30174,
# '4': 30171,
# '5': 30178,
# '7': 30179,
'9': 135,
'10': 30227,
# '11': 30230,
'12': 39500,
'13': 39702
},
'musicvideos':
'homevideos':
{
'1': tagname,
'2': 30256,
'4': 30257,
'6': 30258
'1': tagname,
'2': 30251,
'11': 30253,
'13': 39702
},
'photos':
{
'1': tagname,
'2': 30252,
'8': 30255,
'11': 30254,
'13': 39702
},
'musicvideos':
{
'1': tagname,
'2': 30256,
'4': 30257,
'6': 30258,
'13': 39702
}
}
@ -200,6 +206,7 @@ class VideoNodes(object):
'10': '8', # "random",
'11': '5', # "recommended",
'12': '1', # "ondeck"
'13': '9' # browse by folder
}
nodes = mediatypes[mediatype]
@ -244,6 +251,8 @@ class VideoNodes(object):
elif mediatype =="movies":
# Reset nodetype; we got the label
nodetype = 'inprogress'
elif nodetype == 'browsefiles':
path = 'plugin://plugin.video.plexkodiconnect?mode=browseplex&key=/library/sections/%s/folder' % viewid
else:
path = "library://video/Plex-%s/%s_%s.xml" % (dirname, viewid, nodetype)
@ -285,7 +294,7 @@ class VideoNodes(object):
continue
# Create the root
if (nodetype in ("nextepisodes", "ondeck", 'recentepisodes') or mediatype == "homevideos"):
if (nodetype in ("nextepisodes", "ondeck", 'recentepisodes', 'browsefiles') or mediatype == "homevideos"):
# Folder type with plugin path
root = self.commonRoot(order=sortorder[node], label=label, tagname=tagname, roottype=2)
etree.SubElement(root, 'path').text = path