Merge pull request #917 from croneter/fix-skin
Ensure correct Kodi Container.Type is set for PKC widgets
This commit is contained in:
commit
53139a7e45
9 changed files with 216 additions and 135 deletions
|
@ -52,6 +52,9 @@ class Main():
|
||||||
synched=params.get('synched') != 'false',
|
synched=params.get('synched') != 'false',
|
||||||
prompt=params.get('prompt'))
|
prompt=params.get('prompt'))
|
||||||
|
|
||||||
|
elif mode == 'show_section':
|
||||||
|
entrypoint.show_section(params.get('section_index'))
|
||||||
|
|
||||||
elif mode == 'watchlater':
|
elif mode == 'watchlater':
|
||||||
entrypoint.watchlater()
|
entrypoint.watchlater()
|
||||||
|
|
||||||
|
|
|
@ -20,11 +20,13 @@ from . import plex_functions as PF
|
||||||
from . import variables as v
|
from . import variables as v
|
||||||
# Be careful - your using app in another Python instance!
|
# Be careful - your using app in another Python instance!
|
||||||
from . import app, widgets
|
from . import app, widgets
|
||||||
|
from .library_sync.nodes import NODE_TYPES
|
||||||
|
|
||||||
|
|
||||||
LOG = getLogger('PLEX.entrypoint')
|
LOG = getLogger('PLEX.entrypoint')
|
||||||
|
|
||||||
|
|
||||||
def guess_content_type():
|
def guess_video_or_audio():
|
||||||
"""
|
"""
|
||||||
Returns either 'video', 'audio' or 'image', based how the user navigated to
|
Returns either 'video', 'audio' or 'image', based how the user navigated to
|
||||||
the current view.
|
the current view.
|
||||||
|
@ -102,9 +104,9 @@ def show_main_menu(content_type=None):
|
||||||
"""
|
"""
|
||||||
Shows the main PKC menu listing with all libraries, Channel, settings, etc.
|
Shows the main PKC menu listing with all libraries, Channel, settings, etc.
|
||||||
"""
|
"""
|
||||||
content_type = content_type or guess_content_type()
|
content_type = content_type or guess_video_or_audio()
|
||||||
LOG.debug('Do main listing for content_type: %s', content_type)
|
LOG.debug('Do main listing for %s', content_type)
|
||||||
xbmcplugin.setContent(int(sys.argv[1]), 'files')
|
xbmcplugin.setContent(int(sys.argv[1]), v.CONTENT_TYPE_FILE)
|
||||||
# Get nodes from the window props
|
# Get nodes from the window props
|
||||||
totalnodes = int(utils.window('Plex.nodes.total') or 0)
|
totalnodes = int(utils.window('Plex.nodes.total') or 0)
|
||||||
for i in range(totalnodes):
|
for i in range(totalnodes):
|
||||||
|
@ -133,14 +135,6 @@ def show_main_menu(content_type=None):
|
||||||
# Should only be called if the user selects widgets
|
# Should only be called if the user selects widgets
|
||||||
LOG.info('Detected user selecting widgets')
|
LOG.info('Detected user selecting widgets')
|
||||||
directory_item(label, path)
|
directory_item(label, path)
|
||||||
if not path.startswith('library://'):
|
|
||||||
# Already using add-on paths (e.g. section not synched)
|
|
||||||
continue
|
|
||||||
# Add ANOTHER menu item that uses add-on paths instead of direct
|
|
||||||
# paths in order to let the user navigate into all submenus
|
|
||||||
addon_index = utils.window('Plex.nodes.%s.addon_index' % i)
|
|
||||||
# Append "(More...)" to the label
|
|
||||||
directory_item('%s (%s)' % (label, utils.lang(22082)), addon_index)
|
|
||||||
# Playlists
|
# Playlists
|
||||||
if content_type != 'image':
|
if content_type != 'image':
|
||||||
path = 'plugin://%s?mode=playlists' % v.ADDON_ID
|
path = 'plugin://%s?mode=playlists' % v.ADDON_ID
|
||||||
|
@ -169,32 +163,64 @@ def show_main_menu(content_type=None):
|
||||||
xbmcplugin.endOfDirectory(int(sys.argv[1]))
|
xbmcplugin.endOfDirectory(int(sys.argv[1]))
|
||||||
|
|
||||||
|
|
||||||
def show_listing(xml, plex_type=None, section_id=None, synched=True, key=None,
|
def show_section(section_index):
|
||||||
content_type=None):
|
"""
|
||||||
|
Displays menu for an entire Plex section. We're using add-on paths instead
|
||||||
|
of Kodi video library xmls to be able to use type="filter" library xmls
|
||||||
|
and thus set the "content"
|
||||||
|
|
||||||
|
Only used for synched Plex sections - otherwise, PMS xml for the section
|
||||||
|
is used directly
|
||||||
|
"""
|
||||||
|
LOG.debug('Do section listing for section index %s', section_index)
|
||||||
|
xbmcplugin.setContent(int(sys.argv[1]), v.CONTENT_TYPE_FILE)
|
||||||
|
# Get nodes from the window props
|
||||||
|
node = 'Plex.nodes.%s' % section_index
|
||||||
|
content = utils.window('%s.type' % node)
|
||||||
|
plex_type = v.PLEX_TYPE_MOVIE if content == v.CONTENT_TYPE_MOVIE \
|
||||||
|
else v.PLEX_TYPE_SHOW
|
||||||
|
for node_type, _, _, _, _ in NODE_TYPES[plex_type]:
|
||||||
|
label = utils.window('%s.%s.title' % (node, node_type))
|
||||||
|
path = utils.window('%s.%s.index' % (node, node_type))
|
||||||
|
directory_item(label, path)
|
||||||
|
xbmcplugin.endOfDirectory(int(sys.argv[1]))
|
||||||
|
|
||||||
|
|
||||||
|
def show_listing(xml, plex_type=None, section_id=None, synched=True, key=None):
|
||||||
"""
|
"""
|
||||||
Pass synched=False if the items have not been synched to the Kodi DB
|
Pass synched=False if the items have not been synched to the Kodi DB
|
||||||
|
|
||||||
|
Kodi content type will be set using the very first item returned by the PMS
|
||||||
"""
|
"""
|
||||||
content_type = content_type or guess_content_type()
|
|
||||||
LOG.debug('show_listing: content_type %s, section_id %s, synched %s, '
|
|
||||||
'key %s, plex_type %s', content_type, section_id, synched, key,
|
|
||||||
plex_type)
|
|
||||||
try:
|
try:
|
||||||
xml[0]
|
xml[0]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
LOG.info('xml received from the PMS is empty: %s', xml.attrib)
|
LOG.info('xml received from the PMS is empty: %s, %s',
|
||||||
xbmcplugin.endOfDirectory(handle=int(sys.argv[1]))
|
xml.tag, xml.attrib)
|
||||||
|
xbmcplugin.endOfDirectory(int(sys.argv[1]))
|
||||||
return
|
return
|
||||||
if content_type == 'video':
|
api = API(xml[0])
|
||||||
xbmcplugin.setContent(int(sys.argv[1]), 'videos')
|
# Determine content type for Kodi's Container.content
|
||||||
elif content_type == 'audio':
|
if key == '/hubs/home/continueWatching':
|
||||||
xbmcplugin.setContent(int(sys.argv[1]), 'artists')
|
# Mix of movies and episodes
|
||||||
elif plex_type in (v.PLEX_TYPE_PLAYLIST, v.PLEX_TYPE_CHANNEL):
|
plex_type = v.PLEX_TYPE_VIDEO
|
||||||
xbmcplugin.setContent(int(sys.argv[1]), 'videos')
|
elif key == '/hubs/home/recentlyAdded?type=2':
|
||||||
elif plex_type:
|
# "Recently Added TV", potentially a mix of Seasons and Episodes
|
||||||
xbmcplugin.setContent(int(sys.argv[1]),
|
plex_type = v.PLEX_TYPE_VIDEO
|
||||||
v.MEDIATYPE_FROM_PLEX_TYPE[plex_type])
|
elif api.plex_type is None and api.fast_key and '?collection=' in api.fast_key:
|
||||||
|
# Collections/Kodi sets
|
||||||
|
plex_type = v.PLEX_TYPE_SET
|
||||||
|
elif api.plex_type is None and plex_type:
|
||||||
|
# e.g. browse by folder - folders will be listed first
|
||||||
|
# Retain plex_type
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
xbmcplugin.setContent(int(sys.argv[1]), 'files')
|
plex_type = api.plex_type
|
||||||
|
content_type = v.CONTENT_FROM_PLEX_TYPE[plex_type]
|
||||||
|
LOG.debug('show_listing: section_id %s, synched %s, key %s, plex_type %s, '
|
||||||
|
'content type %s',
|
||||||
|
section_id, synched, key, plex_type, content_type)
|
||||||
|
xbmcplugin.setContent(int(sys.argv[1]), content_type)
|
||||||
# Initialization
|
# Initialization
|
||||||
widgets.PLEX_TYPE = plex_type
|
widgets.PLEX_TYPE = plex_type
|
||||||
widgets.SYNCHED = synched
|
widgets.SYNCHED = synched
|
||||||
|
@ -204,11 +230,15 @@ def show_listing(xml, plex_type=None, section_id=None, synched=True, key=None,
|
||||||
if plex_type == v.PLEX_TYPE_SHOW and key and 'recentlyAdded' in key:
|
if plex_type == v.PLEX_TYPE_SHOW and key and 'recentlyAdded' in key:
|
||||||
widgets.APPEND_SHOW_TITLE = utils.settings('RecentTvAppendShow') == 'true'
|
widgets.APPEND_SHOW_TITLE = utils.settings('RecentTvAppendShow') == 'true'
|
||||||
widgets.APPEND_SXXEXX = utils.settings('RecentTvAppendSeason') == 'true'
|
widgets.APPEND_SXXEXX = utils.settings('RecentTvAppendSeason') == 'true'
|
||||||
if content_type and xml[0].tag == 'Playlist':
|
if api.tag == 'Playlist':
|
||||||
# Certain views mix playlist types audio and video
|
# Only show video playlists if navigation started for videos
|
||||||
for entry in reversed(xml):
|
# and vice-versa for audio playlists
|
||||||
if entry.get('playlistType') != content_type:
|
content = guess_video_or_audio()
|
||||||
xml.remove(entry)
|
if content:
|
||||||
|
for entry in reversed(xml):
|
||||||
|
tmp_api = API(entry)
|
||||||
|
if tmp_api.playlist_type() != content:
|
||||||
|
xml.remove(entry)
|
||||||
if xml.get('librarySectionID'):
|
if xml.get('librarySectionID'):
|
||||||
widgets.SECTION_ID = utils.cast(int, xml.get('librarySectionID'))
|
widgets.SECTION_ID = utils.cast(int, xml.get('librarySectionID'))
|
||||||
elif section_id:
|
elif section_id:
|
||||||
|
@ -355,15 +385,14 @@ def playlists(content_type):
|
||||||
Lists all Plex playlists of the media type plex_playlist_type
|
Lists all Plex playlists of the media type plex_playlist_type
|
||||||
content_type: 'audio', 'video'
|
content_type: 'audio', 'video'
|
||||||
"""
|
"""
|
||||||
content_type = content_type or guess_content_type()
|
LOG.debug('Listing Plex playlists for content type %s', content_type)
|
||||||
LOG.debug('Listing Plex %s playlists', content_type)
|
|
||||||
if not _wait_for_auth():
|
if not _wait_for_auth():
|
||||||
return xbmcplugin.endOfDirectory(int(sys.argv[1]), False)
|
return xbmcplugin.endOfDirectory(int(sys.argv[1]), False)
|
||||||
app.init(entrypoint=True)
|
app.init(entrypoint=True)
|
||||||
from .playlists.pms import all_playlists
|
from .playlists.pms import all_playlists
|
||||||
xml = all_playlists()
|
xml = all_playlists()
|
||||||
if xml is None:
|
if xml is None:
|
||||||
return
|
return xbmcplugin.endOfDirectory(handle=int(sys.argv[1]))
|
||||||
if content_type is not None:
|
if content_type is not None:
|
||||||
# This will be skipped if user selects a widget
|
# This will be skipped if user selects a widget
|
||||||
# Buggy xml.remove(child) requires reversed()
|
# Buggy xml.remove(child) requires reversed()
|
||||||
|
@ -371,7 +400,7 @@ def playlists(content_type):
|
||||||
api = API(entry)
|
api = API(entry)
|
||||||
if not api.playlist_type() == content_type:
|
if not api.playlist_type() == content_type:
|
||||||
xml.remove(entry)
|
xml.remove(entry)
|
||||||
show_listing(xml, content_type=content_type)
|
show_listing(xml)
|
||||||
|
|
||||||
|
|
||||||
def hub(content_type):
|
def hub(content_type):
|
||||||
|
@ -380,7 +409,7 @@ def hub(content_type):
|
||||||
content_type:
|
content_type:
|
||||||
audio, video, image
|
audio, video, image
|
||||||
"""
|
"""
|
||||||
content_type = content_type or guess_content_type()
|
content_type = content_type or guess_video_or_audio()
|
||||||
LOG.debug('Showing Plex Hub entries for %s', content_type)
|
LOG.debug('Showing Plex Hub entries for %s', content_type)
|
||||||
if not _wait_for_auth():
|
if not _wait_for_auth():
|
||||||
return xbmcplugin.endOfDirectory(int(sys.argv[1]), False)
|
return xbmcplugin.endOfDirectory(int(sys.argv[1]), False)
|
||||||
|
@ -410,7 +439,7 @@ def hub(content_type):
|
||||||
append = True
|
append = True
|
||||||
if not append:
|
if not append:
|
||||||
xml.remove(entry)
|
xml.remove(entry)
|
||||||
show_listing(xml, content_type=content_type)
|
show_listing(xml)
|
||||||
|
|
||||||
|
|
||||||
def watchlater():
|
def watchlater():
|
||||||
|
@ -447,7 +476,8 @@ def browse_plex(key=None, plex_type=None, section_id=None, synched=True,
|
||||||
LOG.debug('Browsing to key %s, section %s, plex_type: %s, synched: %s, '
|
LOG.debug('Browsing to key %s, section %s, plex_type: %s, synched: %s, '
|
||||||
'prompt "%s"', key, section_id, plex_type, synched, prompt)
|
'prompt "%s"', key, section_id, plex_type, synched, prompt)
|
||||||
if not _wait_for_auth():
|
if not _wait_for_auth():
|
||||||
return xbmcplugin.endOfDirectory(int(sys.argv[1]), False)
|
xbmcplugin.endOfDirectory(int(sys.argv[1]), False)
|
||||||
|
return
|
||||||
app.init(entrypoint=True)
|
app.init(entrypoint=True)
|
||||||
if prompt:
|
if prompt:
|
||||||
prompt = utils.dialog('input', prompt)
|
prompt = utils.dialog('input', prompt)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, unicode_literals
|
from __future__ import absolute_import, division, unicode_literals
|
||||||
import urllib
|
import urllib
|
||||||
|
import copy
|
||||||
|
|
||||||
from ..utils import etree
|
from ..utils import etree
|
||||||
from .. import variables as v, utils
|
from .. import variables as v, utils
|
||||||
|
@ -23,10 +24,9 @@ NODE_TYPES = {
|
||||||
{
|
{
|
||||||
'mode': 'browseplex',
|
'mode': 'browseplex',
|
||||||
'key': '/library/sections/{self.section_id}/onDeck',
|
'key': '/library/sections/{self.section_id}/onDeck',
|
||||||
'plex_type': '{self.section_type}',
|
|
||||||
'section_id': '{self.section_id}'
|
'section_id': '{self.section_id}'
|
||||||
},
|
},
|
||||||
'movies',
|
v.CONTENT_TYPE_MOVIE,
|
||||||
True),
|
True),
|
||||||
('pkc_ondeck',
|
('pkc_ondeck',
|
||||||
utils.lang(39502), # "PKC On Deck (faster)"
|
utils.lang(39502), # "PKC On Deck (faster)"
|
||||||
|
@ -38,20 +38,18 @@ NODE_TYPES = {
|
||||||
{
|
{
|
||||||
'mode': 'browseplex',
|
'mode': 'browseplex',
|
||||||
'key': '/library/sections/{self.section_id}/recentlyAdded',
|
'key': '/library/sections/{self.section_id}/recentlyAdded',
|
||||||
'plex_type': '{self.section_type}',
|
|
||||||
'section_id': '{self.section_id}'
|
'section_id': '{self.section_id}'
|
||||||
},
|
},
|
||||||
'movies',
|
v.CONTENT_TYPE_MOVIE,
|
||||||
False),
|
False),
|
||||||
('all',
|
('all',
|
||||||
'{self.name}', # We're using this section's name
|
'{self.name}', # We're using this section's name
|
||||||
{
|
{
|
||||||
'mode': 'browseplex',
|
'mode': 'browseplex',
|
||||||
'key': '/library/sections/{self.section_id}/all',
|
'key': '/library/sections/{self.section_id}/all',
|
||||||
'plex_type': '{self.section_type}',
|
|
||||||
'section_id': '{self.section_id}'
|
'section_id': '{self.section_id}'
|
||||||
},
|
},
|
||||||
'movies',
|
v.CONTENT_TYPE_MOVIE,
|
||||||
False),
|
False),
|
||||||
('recommended',
|
('recommended',
|
||||||
utils.lang(30230), # "Recommended"
|
utils.lang(30230), # "Recommended"
|
||||||
|
@ -59,30 +57,27 @@ NODE_TYPES = {
|
||||||
'mode': 'browseplex',
|
'mode': 'browseplex',
|
||||||
'key': ('/library/sections/{self.section_id}&%s'
|
'key': ('/library/sections/{self.section_id}&%s'
|
||||||
% urllib.urlencode({'sort': 'rating:desc'})),
|
% urllib.urlencode({'sort': 'rating:desc'})),
|
||||||
'plex_type': '{self.section_type}',
|
|
||||||
'section_id': '{self.section_id}'
|
'section_id': '{self.section_id}'
|
||||||
},
|
},
|
||||||
'movies',
|
v.CONTENT_TYPE_MOVIE,
|
||||||
False),
|
False),
|
||||||
('genres',
|
('genres',
|
||||||
utils.lang(135), # "Genres"
|
utils.lang(135), # "Genres"
|
||||||
{
|
{
|
||||||
'mode': 'browseplex',
|
'mode': 'browseplex',
|
||||||
'key': '/library/sections/{self.section_id}/genre',
|
'key': '/library/sections/{self.section_id}/genre',
|
||||||
'plex_type': '{self.section_type}',
|
|
||||||
'section_id': '{self.section_id}'
|
'section_id': '{self.section_id}'
|
||||||
},
|
},
|
||||||
'movies',
|
v.CONTENT_TYPE_MOVIE,
|
||||||
False),
|
False),
|
||||||
('sets',
|
('sets',
|
||||||
utils.lang(39501), # "Collections"
|
utils.lang(39501), # "Collections"
|
||||||
{
|
{
|
||||||
'mode': 'browseplex',
|
'mode': 'browseplex',
|
||||||
'key': '/library/sections/{self.section_id}/collection',
|
'key': '/library/sections/{self.section_id}/collection',
|
||||||
'plex_type': '{self.section_type}',
|
|
||||||
'section_id': '{self.section_id}'
|
'section_id': '{self.section_id}'
|
||||||
},
|
},
|
||||||
'movies',
|
v.CONTENT_TYPE_MOVIE,
|
||||||
False),
|
False),
|
||||||
('random',
|
('random',
|
||||||
utils.lang(30227), # "Random"
|
utils.lang(30227), # "Random"
|
||||||
|
@ -90,20 +85,18 @@ NODE_TYPES = {
|
||||||
'mode': 'browseplex',
|
'mode': 'browseplex',
|
||||||
'key': ('/library/sections/{self.section_id}&%s'
|
'key': ('/library/sections/{self.section_id}&%s'
|
||||||
% urllib.urlencode({'sort': 'random'})),
|
% urllib.urlencode({'sort': 'random'})),
|
||||||
'plex_type': '{self.section_type}',
|
|
||||||
'section_id': '{self.section_id}'
|
'section_id': '{self.section_id}'
|
||||||
},
|
},
|
||||||
'movies',
|
v.CONTENT_TYPE_MOVIE,
|
||||||
False),
|
False),
|
||||||
('lastplayed',
|
('lastplayed',
|
||||||
utils.lang(568), # "Last played"
|
utils.lang(568), # "Last played"
|
||||||
{
|
{
|
||||||
'mode': 'browseplex',
|
'mode': 'browseplex',
|
||||||
'key': '/library/sections/{self.section_id}/recentlyViewed',
|
'key': '/library/sections/{self.section_id}/recentlyViewed',
|
||||||
'plex_type': '{self.section_type}',
|
|
||||||
'section_id': '{self.section_id}'
|
'section_id': '{self.section_id}'
|
||||||
},
|
},
|
||||||
'movies',
|
v.CONTENT_TYPE_MOVIE,
|
||||||
False),
|
False),
|
||||||
('browse',
|
('browse',
|
||||||
utils.lang(39702), # "Browse by folder"
|
utils.lang(39702), # "Browse by folder"
|
||||||
|
@ -111,19 +104,20 @@ NODE_TYPES = {
|
||||||
'mode': 'browseplex',
|
'mode': 'browseplex',
|
||||||
'key': '/library/sections/{self.section_id}/folder',
|
'key': '/library/sections/{self.section_id}/folder',
|
||||||
'plex_type': '{self.section_type}',
|
'plex_type': '{self.section_type}',
|
||||||
'section_id': '{self.section_id}'
|
'section_id': '{self.section_id}',
|
||||||
|
'folder': True
|
||||||
},
|
},
|
||||||
'movies',
|
v.CONTENT_TYPE_MOVIE,
|
||||||
True),
|
True),
|
||||||
('more',
|
('more',
|
||||||
utils.lang(22082), # "More..."
|
utils.lang(22082), # "More..."
|
||||||
{
|
{
|
||||||
'mode': 'browseplex',
|
'mode': 'browseplex',
|
||||||
'key': '/library/sections/{self.section_id}',
|
'key': '/library/sections/{self.section_id}',
|
||||||
'plex_type': '{self.section_type}',
|
'section_id': '{self.section_id}',
|
||||||
'section_id': '{self.section_id}'
|
'folder': True
|
||||||
},
|
},
|
||||||
'movies',
|
v.CONTENT_TYPE_FILE,
|
||||||
True),
|
True),
|
||||||
),
|
),
|
||||||
###########################################################
|
###########################################################
|
||||||
|
@ -133,30 +127,27 @@ NODE_TYPES = {
|
||||||
{
|
{
|
||||||
'mode': 'browseplex',
|
'mode': 'browseplex',
|
||||||
'key': '/library/sections/{self.section_id}/onDeck',
|
'key': '/library/sections/{self.section_id}/onDeck',
|
||||||
'plex_type': '{self.section_type}',
|
|
||||||
'section_id': '{self.section_id}'
|
'section_id': '{self.section_id}'
|
||||||
},
|
},
|
||||||
'episodes',
|
v.CONTENT_TYPE_EPISODE,
|
||||||
True),
|
True),
|
||||||
('recent',
|
('recent',
|
||||||
utils.lang(30174), # "Recently Added"
|
utils.lang(30174), # "Recently Added"
|
||||||
{
|
{
|
||||||
'mode': 'browseplex',
|
'mode': 'browseplex',
|
||||||
'key': '/library/sections/{self.section_id}/recentlyAdded',
|
'key': '/library/sections/{self.section_id}/recentlyAdded',
|
||||||
'plex_type': '{self.section_type}',
|
|
||||||
'section_id': '{self.section_id}'
|
'section_id': '{self.section_id}'
|
||||||
},
|
},
|
||||||
'episodes',
|
v.CONTENT_TYPE_EPISODE,
|
||||||
False),
|
False),
|
||||||
('all',
|
('all',
|
||||||
'{self.name}', # We're using this section's name
|
'{self.name}', # We're using this section's name
|
||||||
{
|
{
|
||||||
'mode': 'browseplex',
|
'mode': 'browseplex',
|
||||||
'key': '/library/sections/{self.section_id}/all',
|
'key': '/library/sections/{self.section_id}/all',
|
||||||
'plex_type': '{self.section_type}',
|
|
||||||
'section_id': '{self.section_id}'
|
'section_id': '{self.section_id}'
|
||||||
},
|
},
|
||||||
'tvshows',
|
v.CONTENT_TYPE_SHOW,
|
||||||
False),
|
False),
|
||||||
('recommended',
|
('recommended',
|
||||||
utils.lang(30230), # "Recommended"
|
utils.lang(30230), # "Recommended"
|
||||||
|
@ -164,30 +155,27 @@ NODE_TYPES = {
|
||||||
'mode': 'browseplex',
|
'mode': 'browseplex',
|
||||||
'key': ('/library/sections/{self.section_id}&%s'
|
'key': ('/library/sections/{self.section_id}&%s'
|
||||||
% urllib.urlencode({'sort': 'rating:desc'})),
|
% urllib.urlencode({'sort': 'rating:desc'})),
|
||||||
'plex_type': '{self.section_type}',
|
|
||||||
'section_id': '{self.section_id}'
|
'section_id': '{self.section_id}'
|
||||||
},
|
},
|
||||||
'tvshows',
|
v.CONTENT_TYPE_SHOW,
|
||||||
False),
|
False),
|
||||||
('genres',
|
('genres',
|
||||||
utils.lang(135), # "Genres"
|
utils.lang(135), # "Genres"
|
||||||
{
|
{
|
||||||
'mode': 'browseplex',
|
'mode': 'browseplex',
|
||||||
'key': '/library/sections/{self.section_id}/genre',
|
'key': '/library/sections/{self.section_id}/genre',
|
||||||
'plex_type': '{self.section_type}',
|
|
||||||
'section_id': '{self.section_id}'
|
'section_id': '{self.section_id}'
|
||||||
},
|
},
|
||||||
'tvshows',
|
v.CONTENT_TYPE_SHOW,
|
||||||
False),
|
False),
|
||||||
('sets',
|
('sets',
|
||||||
utils.lang(39501), # "Collections"
|
utils.lang(39501), # "Collections"
|
||||||
{
|
{
|
||||||
'mode': 'browseplex',
|
'mode': 'browseplex',
|
||||||
'key': '/library/sections/{self.section_id}/collection',
|
'key': '/library/sections/{self.section_id}/collection',
|
||||||
'plex_type': '{self.section_type}',
|
|
||||||
'section_id': '{self.section_id}'
|
'section_id': '{self.section_id}'
|
||||||
},
|
},
|
||||||
'tvshows',
|
v.CONTENT_TYPE_SHOW,
|
||||||
True), # There are no sets/collections for shows with Kodi
|
True), # There are no sets/collections for shows with Kodi
|
||||||
('random',
|
('random',
|
||||||
utils.lang(30227), # "Random"
|
utils.lang(30227), # "Random"
|
||||||
|
@ -195,10 +183,9 @@ NODE_TYPES = {
|
||||||
'mode': 'browseplex',
|
'mode': 'browseplex',
|
||||||
'key': ('/library/sections/{self.section_id}&%s'
|
'key': ('/library/sections/{self.section_id}&%s'
|
||||||
% urllib.urlencode({'sort': 'random'})),
|
% urllib.urlencode({'sort': 'random'})),
|
||||||
'plex_type': '{self.section_type}',
|
|
||||||
'section_id': '{self.section_id}'
|
'section_id': '{self.section_id}'
|
||||||
},
|
},
|
||||||
'tvshows',
|
v.CONTENT_TYPE_SHOW,
|
||||||
False),
|
False),
|
||||||
('lastplayed',
|
('lastplayed',
|
||||||
utils.lang(568), # "Last played"
|
utils.lang(568), # "Last played"
|
||||||
|
@ -206,30 +193,29 @@ NODE_TYPES = {
|
||||||
'mode': 'browseplex',
|
'mode': 'browseplex',
|
||||||
'key': ('/library/sections/{self.section_id}/recentlyViewed&%s'
|
'key': ('/library/sections/{self.section_id}/recentlyViewed&%s'
|
||||||
% urllib.urlencode({'type': v.PLEX_TYPE_NUMBER_FROM_PLEX_TYPE[v.PLEX_TYPE_EPISODE]})),
|
% urllib.urlencode({'type': v.PLEX_TYPE_NUMBER_FROM_PLEX_TYPE[v.PLEX_TYPE_EPISODE]})),
|
||||||
'plex_type': '{self.section_type}',
|
|
||||||
'section_id': '{self.section_id}'
|
'section_id': '{self.section_id}'
|
||||||
},
|
},
|
||||||
'episodes',
|
v.CONTENT_TYPE_EPISODE,
|
||||||
False),
|
False),
|
||||||
('browse',
|
('browse',
|
||||||
utils.lang(39702), # "Browse by folder"
|
utils.lang(39702), # "Browse by folder"
|
||||||
{
|
{
|
||||||
'mode': 'browseplex',
|
'mode': 'browseplex',
|
||||||
'key': '/library/sections/{self.section_id}/folder',
|
'key': '/library/sections/{self.section_id}/folder',
|
||||||
'plex_type': '{self.section_type}',
|
'section_id': '{self.section_id}',
|
||||||
'section_id': '{self.section_id}'
|
'folder': True
|
||||||
},
|
},
|
||||||
'episodes',
|
v.CONTENT_TYPE_EPISODE,
|
||||||
True),
|
True),
|
||||||
('more',
|
('more',
|
||||||
utils.lang(22082), # "More..."
|
utils.lang(22082), # "More..."
|
||||||
{
|
{
|
||||||
'mode': 'browseplex',
|
'mode': 'browseplex',
|
||||||
'key': '/library/sections/{self.section_id}',
|
'key': '/library/sections/{self.section_id}',
|
||||||
'plex_type': '{self.section_type}',
|
'section_id': '{self.section_id}',
|
||||||
'section_id': '{self.section_id}'
|
'folder': True
|
||||||
},
|
},
|
||||||
'episodes',
|
v.CONTENT_TYPE_FILE,
|
||||||
True),
|
True),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
@ -239,9 +225,19 @@ def node_pms(section, node_name, args):
|
||||||
"""
|
"""
|
||||||
Nodes where the logic resides with the PMS - we're NOT building an
|
Nodes where the logic resides with the PMS - we're NOT building an
|
||||||
xml that filters and sorts, but point to PKC add-on path
|
xml that filters and sorts, but point to PKC add-on path
|
||||||
|
|
||||||
|
Be sure to set args['folder'] = True if the listing is a folder and does
|
||||||
|
not contain playable elements like movies, episodes or tracks
|
||||||
"""
|
"""
|
||||||
xml = etree.Element('node', attrib={'order': unicode(section.order),
|
if 'folder' in args:
|
||||||
'type': 'folder'})
|
args = copy.deepcopy(args)
|
||||||
|
args.pop('folder')
|
||||||
|
folder = True
|
||||||
|
else:
|
||||||
|
folder = False
|
||||||
|
xml = etree.Element('node',
|
||||||
|
attrib={'order': unicode(section.order),
|
||||||
|
'type': 'folder' if folder else 'filter'})
|
||||||
etree.SubElement(xml, 'label').text = node_name
|
etree.SubElement(xml, 'label').text = node_name
|
||||||
etree.SubElement(xml, 'icon').text = ICON_PATH
|
etree.SubElement(xml, 'icon').text = ICON_PATH
|
||||||
etree.SubElement(xml, 'content').text = section.content
|
etree.SubElement(xml, 'content').text = section.content
|
||||||
|
|
|
@ -132,7 +132,7 @@ class Section(object):
|
||||||
@section_type.setter
|
@section_type.setter
|
||||||
def section_type(self, value):
|
def section_type(self, value):
|
||||||
self._section_type = value
|
self._section_type = value
|
||||||
self.content = v.MEDIATYPE_FROM_PLEX_TYPE[value]
|
self.content = v.CONTENT_FROM_PLEX_TYPE[value]
|
||||||
# Default values whether we sync or not based on the Plex type
|
# Default values whether we sync or not based on the Plex type
|
||||||
if value == v.PLEX_TYPE_PHOTO:
|
if value == v.PLEX_TYPE_PHOTO:
|
||||||
self.sync_to_kodi = False
|
self.sync_to_kodi = False
|
||||||
|
@ -239,25 +239,24 @@ class Section(object):
|
||||||
raise RuntimeError('Index not initialized')
|
raise RuntimeError('Index not initialized')
|
||||||
# Main list entry for this section - which will show the different
|
# Main list entry for this section - which will show the different
|
||||||
# nodes as "submenus" once the user navigates into this section
|
# nodes as "submenus" once the user navigates into this section
|
||||||
args = {
|
|
||||||
'mode': 'browseplex',
|
|
||||||
'key': '/library/sections/%s' % self.section_id,
|
|
||||||
'plex_type': self.section_type,
|
|
||||||
'section_id': unicode(self.section_id)
|
|
||||||
}
|
|
||||||
if not self.sync_to_kodi:
|
|
||||||
args['synched'] = 'false'
|
|
||||||
addon_index = self.addon_path(args)
|
|
||||||
if self.sync_to_kodi and self.section_type in v.PLEX_VIDEOTYPES:
|
if self.sync_to_kodi and self.section_type in v.PLEX_VIDEOTYPES:
|
||||||
path = 'library://video/Plex-{0}/{0}_all.xml'
|
args = {
|
||||||
path = path.format(self.section_id)
|
'mode': 'show_section',
|
||||||
index = 'library://video/Plex-%s' % self.section_id
|
'section_index': self.index
|
||||||
|
}
|
||||||
|
path = utils.extend_url('plugin://%s' % v.ADDON_ID, args)
|
||||||
else:
|
else:
|
||||||
# No xmls to link to - let's show the listings on the fly
|
args = {
|
||||||
index = addon_index
|
'mode': 'browseplex',
|
||||||
args['key'] = '/library/sections/%s/all' % self.section_id
|
'key': '/library/sections/%s/all' % self.section_id,
|
||||||
|
'section_id': unicode(self.section_id)
|
||||||
|
}
|
||||||
|
if not self.sync_to_kodi:
|
||||||
|
args['synched'] = 'false'
|
||||||
|
# No library xmls to speed things up
|
||||||
|
# Immediately show the PMS options for this section
|
||||||
path = self.addon_path(args)
|
path = self.addon_path(args)
|
||||||
# .index will list all possible nodes for this library
|
index = path
|
||||||
utils.window('%s.index' % self.node, value=index)
|
utils.window('%s.index' % self.node, value=index)
|
||||||
utils.window('%s.title' % self.node, value=self.name)
|
utils.window('%s.title' % self.node, value=self.name)
|
||||||
utils.window('%s.type' % self.node, value=self.content)
|
utils.window('%s.type' % self.node, value=self.content)
|
||||||
|
@ -274,8 +273,6 @@ class Section(object):
|
||||||
utils.window('%s.path' % self.node,
|
utils.window('%s.path' % self.node,
|
||||||
value='ActivateWindow(pictures,%s,return)' % path)
|
value='ActivateWindow(pictures,%s,return)' % path)
|
||||||
utils.window('%s.id' % self.node, value=str(self.section_id))
|
utils.window('%s.id' % self.node, value=str(self.section_id))
|
||||||
# To let the user navigate into this node when selecting widgets
|
|
||||||
utils.window('%s.addon_index' % self.node, value=addon_index)
|
|
||||||
if not self.sync_to_kodi:
|
if not self.sync_to_kodi:
|
||||||
self.remove_files_from_kodi()
|
self.remove_files_from_kodi()
|
||||||
return
|
return
|
||||||
|
@ -312,18 +309,22 @@ class Section(object):
|
||||||
def _build_node(self, node_type, node_name, args, content, pms_node):
|
def _build_node(self, node_type, node_name, args, content, pms_node):
|
||||||
self.content = content
|
self.content = content
|
||||||
node_name = node_name.format(self=self)
|
node_name = node_name.format(self=self)
|
||||||
xml_name = '%s_%s.xml' % (self.section_id, node_type)
|
if pms_node:
|
||||||
path = path_ops.path.join(self.path, xml_name)
|
# Do NOT write a Kodi video library xml - can't use type="filter"
|
||||||
if not path_ops.exists(path):
|
# to point back to plugin://plugin.video.plexkodiconnect
|
||||||
if pms_node:
|
xml = nodes.node_pms(self, node_name, args)
|
||||||
# Even the xml will point back to the PKC add-on
|
args.pop('folder', None)
|
||||||
xml = nodes.node_pms(self, node_name, args)
|
path = self.addon_path(args)
|
||||||
else:
|
else:
|
||||||
|
# Write a Kodi video library xml
|
||||||
|
xml_name = '%s_%s.xml' % (self.section_id, node_type)
|
||||||
|
path = path_ops.path.join(self.path, xml_name)
|
||||||
|
if not path_ops.exists(path):
|
||||||
# Let's use Kodi's logic to sort/filter the Kodi library
|
# Let's use Kodi's logic to sort/filter the Kodi library
|
||||||
xml = getattr(nodes, 'node_%s' % node_type)(self, node_name)
|
xml = getattr(nodes, 'node_%s' % node_type)(self, node_name)
|
||||||
self._write_xml(xml, xml_name)
|
self._write_xml(xml, xml_name)
|
||||||
|
path = 'library://video/Plex-%s/%s' % (self.section_id, xml_name)
|
||||||
self.order += 1
|
self.order += 1
|
||||||
path = 'library://video/Plex-%s/%s' % (self.section_id, xml_name)
|
|
||||||
self._window_node(path, node_name, node_type, pms_node)
|
self._window_node(path, node_name, node_type, pms_node)
|
||||||
|
|
||||||
def _write_xml(self, xml, xml_name):
|
def _write_xml(self, xml, xml_name):
|
||||||
|
@ -337,7 +338,7 @@ class Section(object):
|
||||||
LOG.debug('Creating smart playlist for section %s: %s',
|
LOG.debug('Creating smart playlist for section %s: %s',
|
||||||
self.name, self.playlist_path)
|
self.name, self.playlist_path)
|
||||||
xml = etree.Element('smartplaylist',
|
xml = etree.Element('smartplaylist',
|
||||||
attrib={'type': v.MEDIATYPE_FROM_PLEX_TYPE[self.section_type]})
|
attrib={'type': v.CONTENT_FROM_PLEX_TYPE[self.section_type]})
|
||||||
etree.SubElement(xml, 'name').text = self.name
|
etree.SubElement(xml, 'name').text = self.name
|
||||||
etree.SubElement(xml, 'match').text = 'all'
|
etree.SubElement(xml, 'match').text = 'all'
|
||||||
rule = etree.SubElement(xml, 'rule', attrib={'field': 'tag',
|
rule = etree.SubElement(xml, 'rule', attrib={'field': 'tag',
|
||||||
|
@ -647,7 +648,6 @@ def _clear_window_vars(index):
|
||||||
utils.window('%s.content' % node, clear=True)
|
utils.window('%s.content' % node, clear=True)
|
||||||
utils.window('%s.path' % node, clear=True)
|
utils.window('%s.path' % node, clear=True)
|
||||||
utils.window('%s.id' % node, clear=True)
|
utils.window('%s.id' % node, clear=True)
|
||||||
utils.window('%s.addon_index' % node, clear=True)
|
|
||||||
# Just clear everything here, ignore the plex_type
|
# Just clear everything here, ignore the plex_type
|
||||||
for typus in (x[0] for y in nodes.NODE_TYPES.values() for x in y):
|
for typus in (x[0] for y in nodes.NODE_TYPES.values() for x in y):
|
||||||
for kind in WINDOW_ARGS:
|
for kind in WINDOW_ARGS:
|
||||||
|
|
|
@ -51,4 +51,10 @@ def check_migration():
|
||||||
plexdb.cursor.execute('DROP INDEX IF EXISTS ix_playlists_3')
|
plexdb.cursor.execute('DROP INDEX IF EXISTS ix_playlists_3')
|
||||||
# Index will be automatically recreated on next PKC startup
|
# Index will be automatically recreated on next PKC startup
|
||||||
|
|
||||||
|
if not utils.compare_version(last_migration, '2.8.9'):
|
||||||
|
LOG.info('Migrating to version 2.8.8')
|
||||||
|
from .library_sync import sections
|
||||||
|
sections.clear_window_vars()
|
||||||
|
sections.delete_videonode_files()
|
||||||
|
|
||||||
utils.settings('last_migrated_PKC_version', value=v.ADDON_VERSION)
|
utils.settings('last_migrated_PKC_version', value=v.ADDON_VERSION)
|
||||||
|
|
|
@ -71,6 +71,13 @@ class Base(object):
|
||||||
"""
|
"""
|
||||||
return cast(int, self.xml.get('ratingKey'))
|
return cast(int, self.xml.get('ratingKey'))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def fast_key(self):
|
||||||
|
"""
|
||||||
|
Returns the 'fastKey' as unicode or None
|
||||||
|
"""
|
||||||
|
return self.xml.get('fastKey')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def plex_type(self):
|
def plex_type(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -91,9 +91,10 @@ class File(object):
|
||||||
key = '/library/sections/%s/%s' % (section_id, key)
|
key = '/library/sections/%s/%s' % (section_id, key)
|
||||||
params = {
|
params = {
|
||||||
'mode': 'browseplex',
|
'mode': 'browseplex',
|
||||||
'key': key,
|
'key': key
|
||||||
'plex_type': plex_type or self.plex_type
|
|
||||||
}
|
}
|
||||||
|
if plex_type or self.plex_type:
|
||||||
|
params['plex_type'] = plex_type or self.plex_type
|
||||||
if not synched:
|
if not synched:
|
||||||
# No item to be found in the Kodi DB
|
# No item to be found in the Kodi DB
|
||||||
params['synched'] = 'false'
|
params['synched'] = 'false'
|
||||||
|
|
|
@ -165,6 +165,7 @@ PLEX_TYPE_VIDEO = 'video'
|
||||||
PLEX_TYPE_MOVIE = 'movie'
|
PLEX_TYPE_MOVIE = 'movie'
|
||||||
PLEX_TYPE_CLIP = 'clip' # e.g. trailers
|
PLEX_TYPE_CLIP = 'clip' # e.g. trailers
|
||||||
PLEX_TYPE_SET = 'collection' # sets/collections
|
PLEX_TYPE_SET = 'collection' # sets/collections
|
||||||
|
PLEX_TYPE_GENRE = 'genre'
|
||||||
PLEX_TYPE_MIXED = 'mixed'
|
PLEX_TYPE_MIXED = 'mixed'
|
||||||
|
|
||||||
PLEX_TYPE_EPISODE = 'episode'
|
PLEX_TYPE_EPISODE = 'episode'
|
||||||
|
@ -201,7 +202,7 @@ KODI_PLAYLIST_TYPE_FROM_PLEX_PLAYLIST_TYPE = {
|
||||||
KODI_TYPE_VIDEO = 'video'
|
KODI_TYPE_VIDEO = 'video'
|
||||||
KODI_TYPE_MOVIE = 'movie'
|
KODI_TYPE_MOVIE = 'movie'
|
||||||
KODI_TYPE_SET = 'set' # for movie sets of several movies
|
KODI_TYPE_SET = 'set' # for movie sets of several movies
|
||||||
KODI_TYPE_CLIP = 'clip' # e.g. trailers
|
KODI_TYPE_CLIP = 'video' # e.g. trailers
|
||||||
|
|
||||||
KODI_TYPE_EPISODE = 'episode'
|
KODI_TYPE_EPISODE = 'episode'
|
||||||
KODI_TYPE_SEASON = 'season'
|
KODI_TYPE_SEASON = 'season'
|
||||||
|
@ -216,6 +217,24 @@ KODI_TYPE_MUSICVIDEO = 'musicvideo'
|
||||||
KODI_TYPE_PHOTO = 'photo'
|
KODI_TYPE_PHOTO = 'photo'
|
||||||
|
|
||||||
KODI_TYPE_PLAYLIST = 'playlist'
|
KODI_TYPE_PLAYLIST = 'playlist'
|
||||||
|
KODI_TYPE_GENRE = 'genre'
|
||||||
|
|
||||||
|
# Kodi content types, primarily used for xbmcplugin.setContent()
|
||||||
|
CONTENT_TYPE_MOVIE = 'movies'
|
||||||
|
CONTENT_TYPE_SHOW = 'tvshows'
|
||||||
|
CONTENT_TYPE_SEASON = 'seasons'
|
||||||
|
CONTENT_TYPE_EPISODE = 'episodes'
|
||||||
|
CONTENT_TYPE_ARTIST = 'artists'
|
||||||
|
CONTENT_TYPE_ALBUM = 'albums'
|
||||||
|
CONTENT_TYPE_SONG = 'songs'
|
||||||
|
CONTENT_TYPE_CLIP = 'movies'
|
||||||
|
CONTENT_TYPE_SET = 'sets'
|
||||||
|
CONTENT_TYPE_PHOTO = 'photos'
|
||||||
|
CONTENT_TYPE_GENRE = 'genres'
|
||||||
|
CONTENT_TYPE_VIDEO = 'videos'
|
||||||
|
CONTENT_TYPE_PLAYLIST = 'playlists'
|
||||||
|
CONTENT_TYPE_FILE = 'files'
|
||||||
|
|
||||||
|
|
||||||
KODI_VIDEOTYPES = (
|
KODI_VIDEOTYPES = (
|
||||||
KODI_TYPE_VIDEO,
|
KODI_TYPE_VIDEO,
|
||||||
|
@ -306,7 +325,6 @@ PLEX_TYPE_FROM_KODI_TYPE = {
|
||||||
KODI_TYPE_EPISODE: PLEX_TYPE_EPISODE,
|
KODI_TYPE_EPISODE: PLEX_TYPE_EPISODE,
|
||||||
KODI_TYPE_SEASON: PLEX_TYPE_SEASON,
|
KODI_TYPE_SEASON: PLEX_TYPE_SEASON,
|
||||||
KODI_TYPE_SHOW: PLEX_TYPE_SHOW,
|
KODI_TYPE_SHOW: PLEX_TYPE_SHOW,
|
||||||
KODI_TYPE_CLIP: PLEX_TYPE_CLIP,
|
|
||||||
KODI_TYPE_ARTIST: PLEX_TYPE_ARTIST,
|
KODI_TYPE_ARTIST: PLEX_TYPE_ARTIST,
|
||||||
KODI_TYPE_ALBUM: PLEX_TYPE_ALBUM,
|
KODI_TYPE_ALBUM: PLEX_TYPE_ALBUM,
|
||||||
KODI_TYPE_SONG: PLEX_TYPE_SONG,
|
KODI_TYPE_SONG: PLEX_TYPE_SONG,
|
||||||
|
@ -418,24 +436,29 @@ PLEX_TYPE_NUMBER_FROM_PLEX_TYPE = {
|
||||||
PLEX_TYPE_ALBUM: 9,
|
PLEX_TYPE_ALBUM: 9,
|
||||||
PLEX_TYPE_SONG: 10,
|
PLEX_TYPE_SONG: 10,
|
||||||
PLEX_TYPE_CLIP: 12,
|
PLEX_TYPE_CLIP: 12,
|
||||||
'playlist': 15,
|
PLEX_TYPE_PLAYLIST: 15,
|
||||||
PLEX_TYPE_SET: 18
|
PLEX_TYPE_SET: 18
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# To be used with e.g. Kodi Widgets
|
# To be used with e.g. Kodi Widgets
|
||||||
MEDIATYPE_FROM_PLEX_TYPE = {
|
CONTENT_FROM_PLEX_TYPE = {
|
||||||
PLEX_TYPE_MOVIE: 'movies',
|
PLEX_TYPE_MOVIE: CONTENT_TYPE_MOVIE,
|
||||||
PLEX_TYPE_SHOW: 'tvshows',
|
PLEX_TYPE_SHOW: CONTENT_TYPE_SHOW,
|
||||||
PLEX_TYPE_SEASON: 'tvshows',
|
PLEX_TYPE_SEASON: CONTENT_TYPE_SEASON,
|
||||||
PLEX_TYPE_EPISODE: 'episodes',
|
PLEX_TYPE_EPISODE: CONTENT_TYPE_EPISODE,
|
||||||
PLEX_TYPE_ARTIST: 'artists',
|
PLEX_TYPE_ARTIST: CONTENT_TYPE_ARTIST,
|
||||||
PLEX_TYPE_ALBUM: 'albumbs',
|
PLEX_TYPE_ALBUM: CONTENT_TYPE_ALBUM,
|
||||||
PLEX_TYPE_SONG: 'songs',
|
PLEX_TYPE_SONG: CONTENT_TYPE_SONG,
|
||||||
PLEX_TYPE_CLIP: 'videos',
|
PLEX_TYPE_CLIP: CONTENT_TYPE_CLIP,
|
||||||
PLEX_TYPE_SET: 'movies',
|
PLEX_TYPE_SET: CONTENT_TYPE_SET,
|
||||||
PLEX_TYPE_PHOTO: 'photos',
|
PLEX_TYPE_PHOTO: CONTENT_TYPE_PHOTO,
|
||||||
'mixed': 'tvshows',
|
PLEX_TYPE_GENRE: CONTENT_TYPE_GENRE,
|
||||||
|
PLEX_TYPE_VIDEO: CONTENT_TYPE_VIDEO,
|
||||||
|
PLEX_TYPE_PLAYLIST: CONTENT_TYPE_PLAYLIST,
|
||||||
|
PLEX_TYPE_CHANNEL: CONTENT_TYPE_FILE,
|
||||||
|
'mixed': CONTENT_TYPE_SHOW,
|
||||||
|
None: CONTENT_TYPE_FILE
|
||||||
}
|
}
|
||||||
|
|
||||||
KODI_TO_PLEX_ARTWORK = {
|
KODI_TO_PLEX_ARTWORK = {
|
||||||
|
|
|
@ -80,6 +80,21 @@ def generate_item(api):
|
||||||
def _generate_folder(api):
|
def _generate_folder(api):
|
||||||
'''Generates "folder"/"directory" items that user can further navigate'''
|
'''Generates "folder"/"directory" items that user can further navigate'''
|
||||||
art = api.artwork()
|
art = api.artwork()
|
||||||
|
typus = ''
|
||||||
|
if api.plex_type == v.PLEX_TYPE_GENRE:
|
||||||
|
# Unfortunately, 'genre' is not yet supported by Kodi
|
||||||
|
# typus = v.KODI_TYPE_GENRE
|
||||||
|
pass
|
||||||
|
elif api.plex_type == v.PLEX_TYPE_SHOW:
|
||||||
|
typus = v.KODI_TYPE_SHOW
|
||||||
|
elif api.plex_type == v.PLEX_TYPE_SEASON:
|
||||||
|
typus = v.KODI_TYPE_SEASON
|
||||||
|
elif api.plex_type == v.PLEX_TYPE_ARTIST:
|
||||||
|
typus = v.KODI_TYPE_ARTIST
|
||||||
|
elif api.plex_type == v.PLEX_TYPE_ALBUM:
|
||||||
|
typus = v.KODI_TYPE_ALBUM
|
||||||
|
elif api.fast_key and '?collection=' in api.fast_key:
|
||||||
|
typus = v.KODI_TYPE_SET
|
||||||
return {
|
return {
|
||||||
'title': api.title(),
|
'title': api.title(),
|
||||||
'label': api.title(),
|
'label': api.title(),
|
||||||
|
@ -94,7 +109,7 @@ def _generate_folder(api):
|
||||||
'fanart': art['fanart'] if 'fanart' in art else
|
'fanart': art['fanart'] if 'fanart' in art else
|
||||||
'special://home/addons/%s/fanart.jpg' % v.ADDON_ID},
|
'special://home/addons/%s/fanart.jpg' % v.ADDON_ID},
|
||||||
'isFolder': True,
|
'isFolder': True,
|
||||||
'type': '',
|
'type': typus,
|
||||||
'IsPlayable': 'false',
|
'IsPlayable': 'false',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue