Merge branch 'translations' into l10n_translations

This commit is contained in:
tomkat83 2017-03-09 13:04:43 +01:00
commit 1d424cf547
11 changed files with 476 additions and 316 deletions

View file

@ -1,14 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="plugin.video.plexkodiconnect"
name="PlexKodiConnect"
version="1.6.4"
provider-name="croneter">
<addon id="plugin.video.plexkodiconnect" name="PlexKodiConnect" version="1.6.5" provider-name="croneter">
<requires>
<import addon="xbmc.python" version="2.1.0"/>
<import addon="script.module.requests" version="2.3.0" />
</requires>
<extension point="xbmc.python.pluginsource"
library="default.py">
<extension point="xbmc.python.pluginsource" library="default.py">
<provides>video audio image</provides>
</extension>
<extension point="xbmc.service" library="service.py" start="login">
@ -21,6 +17,13 @@
</item>
</extension>
<extension point="xbmc.addon.metadata">
<platform>all</platform>
<language></language>
<license>GNU GENERAL PUBLIC LICENSE. Version 2, June 1991</license>
<forum>https://forums.plex.tv</forum>
<website>https://github.com/croneter/PlexKodiConnect</website>
<email></email>
<source>https://github.com/croneter/PlexKodiConnect</source>
<summary lang="en">Native Integration of Plex into Kodi</summary>
<summary lang="en_gb">Native Integration of Plex into Kodi</summary>
<summary lang="en_us">Native Integration of Plex into Kodi</summary>
@ -37,11 +40,5 @@
<description lang="es">Connect Kodi to your Plex Media Server. This plugin assumes that you manage all your videos with Plex (and none with Kodi). You might lose data already stored in the Kodi video and music databases (as this plugin directly changes them). Use at your own risk!</description>
<description lang="dk">Tilslut Kodi til din Plex Media Server. Dette plugin forudsætter, at du administrere alle dine videoer med Plex (og ikke med Kodi). Du kan miste data som allerede er gemt i Kodi video og musik-databaser (dette plugin ændrer direkte i dem). Brug på eget ansvar!</description>
<description lang="nl">Verbind Kodi met je Plex Media Server. Deze plugin gaat ervan uit dat je al je video's met Plex (en niet met Kodi) beheerd. Je kunt gegevens reeds opgeslagen in de databases voor video en muziek van Kodi (deze plugin wijzigt deze gegevens direct) verliezen. Gebruik op eigen risico!</description>
<platform>all</platform>
<license>GPL v2.0</license>
<forum>https://forums.plex.tv</forum>
<website>https://github.com/croneter/PlexKodiConnect</website>
<email></email>
<source>https://github.com/croneter/PlexKodiConnect</source>
</extension>
</addon>
</addon>

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,6 +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="39702">Browse by folder</string>
<string id="39701">Alexa aktivieren</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:
@ -114,8 +117,7 @@ def Plex_Node(url, viewOffset, playdirectly=False, node=True):
return
if viewOffset != '0':
try:
viewOffset = int(v.PLEX_TO_KODI_TIMEFACTOR *
float(viewOffset))
viewOffset = int(v.PLEX_TO_KODI_TIMEFACTOR * float(viewOffset))
except:
pass
else:
@ -194,6 +196,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 +216,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 +237,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 +643,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 +810,179 @@ 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_CLIP:
params = {
'mode': "Plex_Node",
'id': xml_element.attrib.get('key'),
'viewOffset': xml_element.attrib.get('viewOffset', '0'),
'plex_type': xml_element.attrib.get('type')
}
else:
params = {
'filename': api.getKey(),
'id': api.getRatingKey(),
'dbid': listitem.getProperty('dbid') or '',
'mode': "play"
}
url = "plugin://%s?%s" % (v.ADDON_ID, urlencode(params))
xbmcplugin.addDirectoryItem(handle=HANDLE,
url=url,
listitem=listitem)
def enterPMS():
"""
Opens dialogs for the user the plug in the PMS details

View file

@ -260,7 +260,6 @@ def init_Plex_playlist(playlist, plex_id=None, kodi_item=None):
except KeyError:
log.error('Could not init Plex playlist')
return
item.ID = xml[-1].attrib['%sItemID' % playlist.kind]
playlist.items.append(item)
log.debug('Initialized the playlist on the Plex side: %s' % playlist)

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

View file

@ -96,7 +96,7 @@
<setting id="offerDelete" type="bool" label="30114" default="false" visible="false"/>
<setting id="deleteTV" type="bool" label="30115" visible="eq(-1,true)" default="false" subsetting="true" />
<setting id="deleteMovies" type="bool" label="30116" visible="eq(-2,true)" default="false" subsetting="true" />
<setting id="resumeJumpBack" type="slider" label="30521" default="10" range="0,1,120" option="int" />
<setting id="resumeJumpBack" type="slider" label="30521" default="10" range="0,1,120" option="int" visible="false"/>
<setting type="sep" />
<setting id="playType" type="enum" label="30002" values="Direct Play (default)|Direct Stream|Force Transcode" default="0" />
<setting id="transcoderVideoQualities" type="enum" label="30160" values="420x420, 320kbps|576x320, 720kbps|720x480, 1.5Mbps|1024x768, 2Mbps|1280x720, 3Mbps|1280x720, 4Mbps|1920x1080, 8Mbps|1920x1080, 10Mbps|1920x1080, 12Mbps|1920x1080, 20Mbps|1920x1080, 40Mbps" default="10" /><!-- Video Quality if Transcoding necessary -->