Finally support for Extras!
This commit is contained in:
parent
ce29f5a60e
commit
63f7d5615d
4 changed files with 99 additions and 9 deletions
|
@ -99,6 +99,9 @@ class Main():
|
||||||
elif mode == 'channels':
|
elif mode == 'channels':
|
||||||
entrypoint.channels()
|
entrypoint.channels()
|
||||||
|
|
||||||
|
elif mode == 'extras':
|
||||||
|
entrypoint.extras(plex_id=params.get('plex_id'))
|
||||||
|
|
||||||
elif mode == 'settings':
|
elif mode == 'settings':
|
||||||
executebuiltin('Addon.OpenSettings(%s)' % v.ADDON_ID)
|
executebuiltin('Addon.OpenSettings(%s)' % v.ADDON_ID)
|
||||||
|
|
||||||
|
|
|
@ -99,6 +99,35 @@ class API(object):
|
||||||
"""
|
"""
|
||||||
return self.item.get('ratingKey')
|
return self.item.get('ratingKey')
|
||||||
|
|
||||||
|
def path(self, force_first_media=True):
|
||||||
|
"""
|
||||||
|
Returns a "fully qualified path": add-on paths or direct paths
|
||||||
|
depending on the current settings. Will NOT valide the playurl
|
||||||
|
Returns unicode or None if something went wrong.
|
||||||
|
"""
|
||||||
|
filename = self.file_path(force_first_media=force_first_media)
|
||||||
|
if not state.DIRECT_PATHS or self.plex_type() == v.PLEX_TYPE_CLIP:
|
||||||
|
if filename and '/' in filename:
|
||||||
|
filename = filename.rsplit('/', 1)
|
||||||
|
elif filename:
|
||||||
|
filename = filename.rsplit('\\', 1)
|
||||||
|
try:
|
||||||
|
filename = filename[1]
|
||||||
|
except (TypeError, IndexError):
|
||||||
|
filename = None
|
||||||
|
# Set plugin path and media flags using real filename
|
||||||
|
path = ('plugin://%s/?plex_id=%s&plex_type=%s&mode=play&filename=%s'
|
||||||
|
% (v.ADDON_TYPE[self.plex_type()],
|
||||||
|
self.plex_id(),
|
||||||
|
self.plex_type(),
|
||||||
|
filename))
|
||||||
|
else:
|
||||||
|
# Direct paths is set the Kodi way
|
||||||
|
path = self.validate_playurl(filename,
|
||||||
|
self.plex_type(),
|
||||||
|
omit_check=True)
|
||||||
|
return path
|
||||||
|
|
||||||
def path_and_plex_id(self):
|
def path_and_plex_id(self):
|
||||||
"""
|
"""
|
||||||
Returns the Plex key such as '/library/metadata/246922' or None
|
Returns the Plex key such as '/library/metadata/246922' or None
|
||||||
|
@ -655,6 +684,16 @@ class API(object):
|
||||||
answ['bitDepth'] = None
|
answ['bitDepth'] = None
|
||||||
return answ
|
return answ
|
||||||
|
|
||||||
|
def extras(self):
|
||||||
|
"""
|
||||||
|
Returns a list of XML etree elements for each extra, e.g. a trailer.
|
||||||
|
"""
|
||||||
|
answ = []
|
||||||
|
for extras in self.item.iterfind('Extras'):
|
||||||
|
for extra in extras:
|
||||||
|
answ.append(extra)
|
||||||
|
return answ
|
||||||
|
|
||||||
def trailer_id(self):
|
def trailer_id(self):
|
||||||
"""
|
"""
|
||||||
Returns the ratingKey (plex_id) of the trailer or None
|
Returns the ratingKey (plex_id) of the trailer or None
|
||||||
|
|
|
@ -2,13 +2,16 @@
|
||||||
###############################################################################
|
###############################################################################
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
|
||||||
from xbmc import getInfoLabel, sleep, executebuiltin
|
|
||||||
from xbmcaddon import Addon
|
from xbmcaddon import Addon
|
||||||
|
import xbmc
|
||||||
|
import xbmcplugin
|
||||||
|
import xbmcgui
|
||||||
|
|
||||||
import plexdb_functions as plexdb
|
import plexdb_functions as plexdb
|
||||||
from utils import window, settings, dialog, language as lang
|
from utils import window, settings, dialog, language as lang
|
||||||
from dialogs import context
|
from dialogs import context
|
||||||
from PlexFunctions import delete_item_from_pms
|
import PlexFunctions as PF
|
||||||
|
from PlexAPI import API
|
||||||
import playqueue as PQ
|
import playqueue as PQ
|
||||||
import variables as v
|
import variables as v
|
||||||
import state
|
import state
|
||||||
|
@ -25,7 +28,8 @@ OPTIONS = {
|
||||||
# 'RemoveFav': lang(30406),
|
# 'RemoveFav': lang(30406),
|
||||||
# 'RateSong': lang(30407),
|
# 'RateSong': lang(30407),
|
||||||
'Transcode': lang(30412),
|
'Transcode': lang(30412),
|
||||||
'PMS_Play': lang(30415) # Use PMS to start playback
|
'PMS_Play': lang(30415), # Use PMS to start playback
|
||||||
|
'Extras': lang(30235)
|
||||||
}
|
}
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
@ -53,17 +57,24 @@ class ContextMenu(object):
|
||||||
self.plex_id, self.plex_type)
|
self.plex_id, self.plex_type)
|
||||||
if not self.plex_id:
|
if not self.plex_id:
|
||||||
return
|
return
|
||||||
|
xml = PF.GetPlexMetadata(self.plex_id)
|
||||||
|
try:
|
||||||
|
xml[0].attrib
|
||||||
|
except (TypeError, IndexError, KeyError):
|
||||||
|
self.api = None
|
||||||
|
else:
|
||||||
|
self.api = API(xml[0])
|
||||||
if self._select_menu():
|
if self._select_menu():
|
||||||
self._action_menu()
|
self._action_menu()
|
||||||
if self._selected_option in (OPTIONS['Delete'],
|
if self._selected_option in (OPTIONS['Delete'],
|
||||||
OPTIONS['Refresh']):
|
OPTIONS['Refresh']):
|
||||||
LOG.info("refreshing container")
|
LOG.info("refreshing container")
|
||||||
sleep(500)
|
xbmc.sleep(500)
|
||||||
executebuiltin('Container.Refresh')
|
xbmc.executebuiltin('Container.Refresh')
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_plex_id(kodi_id, kodi_type):
|
def _get_plex_id(kodi_id, kodi_type):
|
||||||
plex_id = getInfoLabel('ListItem.Property(plexid)') or None
|
plex_id = xbmc.getInfoLabel('ListItem.Property(plexid)') or None
|
||||||
if not plex_id and kodi_id and kodi_type:
|
if not plex_id and kodi_id and kodi_type:
|
||||||
with plexdb.Get_Plex_DB() as plexcursor:
|
with plexdb.Get_Plex_DB() as plexcursor:
|
||||||
item = plexcursor.getItem_byKodiId(kodi_id, kodi_type)
|
item = plexcursor.getItem_byKodiId(kodi_id, kodi_type)
|
||||||
|
@ -79,6 +90,8 @@ class ContextMenu(object):
|
||||||
"""
|
"""
|
||||||
options = []
|
options = []
|
||||||
# if user uses direct paths, give option to initiate playback via PMS
|
# if user uses direct paths, give option to initiate playback via PMS
|
||||||
|
if self.api and self.api.extras():
|
||||||
|
options.append(OPTIONS['Extras'])
|
||||||
if state.DIRECT_PATHS and self.kodi_type in v.KODI_VIDEOTYPES:
|
if state.DIRECT_PATHS and self.kodi_type in v.KODI_VIDEOTYPES:
|
||||||
options.append(OPTIONS['PMS_Play'])
|
options.append(OPTIONS['PMS_Play'])
|
||||||
if self.kodi_type in v.KODI_VIDEOTYPES:
|
if self.kodi_type in v.KODI_VIDEOTYPES:
|
||||||
|
@ -122,6 +135,8 @@ class ContextMenu(object):
|
||||||
self._PMS_play()
|
self._PMS_play()
|
||||||
elif selected == OPTIONS['PMS_Play']:
|
elif selected == OPTIONS['PMS_Play']:
|
||||||
self._PMS_play()
|
self._PMS_play()
|
||||||
|
elif selected == OPTIONS['Extras']:
|
||||||
|
self._extras()
|
||||||
# elif selected == OPTIONS['Refresh']:
|
# elif selected == OPTIONS['Refresh']:
|
||||||
# self.emby.refreshItem(self.item_id)
|
# self.emby.refreshItem(self.item_id)
|
||||||
# elif selected == OPTIONS['AddFav']:
|
# elif selected == OPTIONS['AddFav']:
|
||||||
|
@ -131,7 +146,8 @@ class ContextMenu(object):
|
||||||
# elif selected == OPTIONS['RateSong']:
|
# elif selected == OPTIONS['RateSong']:
|
||||||
# self._rate_song()
|
# self._rate_song()
|
||||||
elif selected == OPTIONS['Addon']:
|
elif selected == OPTIONS['Addon']:
|
||||||
executebuiltin('Addon.OpenSettings(plugin.video.plexkodiconnect)')
|
xbmc.executebuiltin(
|
||||||
|
'Addon.OpenSettings(plugin.video.plexkodiconnect)')
|
||||||
elif selected == OPTIONS['Delete']:
|
elif selected == OPTIONS['Delete']:
|
||||||
self._delete_item()
|
self._delete_item()
|
||||||
|
|
||||||
|
@ -146,7 +162,7 @@ class ContextMenu(object):
|
||||||
delete = False
|
delete = False
|
||||||
if delete:
|
if delete:
|
||||||
LOG.info("Deleting Plex item with id %s", self.plex_id)
|
LOG.info("Deleting Plex item with id %s", self.plex_id)
|
||||||
if delete_item_from_pms(self.plex_id) is False:
|
if PF.delete_item_from_pms(self.plex_id) is False:
|
||||||
dialog("ok", heading="{plex}", line1=lang(30414))
|
dialog("ok", heading="{plex}", line1=lang(30414))
|
||||||
|
|
||||||
def _PMS_play(self):
|
def _PMS_play(self):
|
||||||
|
@ -161,4 +177,16 @@ class ContextMenu(object):
|
||||||
% (v.ADDON_TYPE[self.plex_type],
|
% (v.ADDON_TYPE[self.plex_type],
|
||||||
self.plex_id,
|
self.plex_id,
|
||||||
self.plex_type))
|
self.plex_type))
|
||||||
executebuiltin('RunPlugin(%s)' % handle)
|
xbmc.executebuiltin('RunPlugin(%s)' % handle)
|
||||||
|
|
||||||
|
def _extras(self):
|
||||||
|
"""
|
||||||
|
Displays a list of elements for all the extras of the Plex element
|
||||||
|
"""
|
||||||
|
handle = ('plugin://plugin.video.plexkodiconnect?mode=extras&plex_id=%s'
|
||||||
|
% self.plex_id)
|
||||||
|
if xbmcgui.getCurrentWindowId() == 10025:
|
||||||
|
# Video Window
|
||||||
|
xbmc.executebuiltin('Container.Update(\"%s\")' % handle)
|
||||||
|
else:
|
||||||
|
xbmc.executebuiltin('ActivateWindow(videos, \"%s\")' % handle)
|
||||||
|
|
|
@ -841,6 +841,26 @@ def __build_item(xml_element):
|
||||||
listitem=listitem)
|
listitem=listitem)
|
||||||
|
|
||||||
|
|
||||||
|
def extras(plex_id):
|
||||||
|
"""
|
||||||
|
Lists all extras for plex_id
|
||||||
|
"""
|
||||||
|
xbmcplugin.setContent(HANDLE, 'movies')
|
||||||
|
xml = GetPlexMetadata(plex_id)
|
||||||
|
try:
|
||||||
|
xml[0].attrib
|
||||||
|
except (TypeError, IndexError, KeyError):
|
||||||
|
xbmcplugin.endOfDirectory(HANDLE)
|
||||||
|
return
|
||||||
|
for item in API(xml[0]).extras():
|
||||||
|
api = API(item)
|
||||||
|
listitem = api.create_listitem()
|
||||||
|
xbmcplugin.addDirectoryItem(handle=HANDLE,
|
||||||
|
url=api.path(),
|
||||||
|
listitem=listitem)
|
||||||
|
xbmcplugin.endOfDirectory(HANDLE)
|
||||||
|
|
||||||
|
|
||||||
def enterPMS():
|
def enterPMS():
|
||||||
"""
|
"""
|
||||||
Opens dialogs for the user the plug in the PMS details
|
Opens dialogs for the user the plug in the PMS details
|
||||||
|
|
Loading…
Reference in a new issue