From bcc46e4ea16cbda1d562b46034f75f0c83671d66 Mon Sep 17 00:00:00 2001 From: tomkat83 Date: Sun, 6 Nov 2016 12:15:41 +0100 Subject: [PATCH] New contextmenu: force playback from PMS - Visible if using direct paths - You will be able to correctly play videos with several parts, media streams or versions - Fixes #78 --- resources/language/English/strings.xml | 1 + resources/language/German/strings.xml | 1 + resources/lib/PlexFunctions.py | 79 +++++++++++++------------- resources/lib/context_entry.py | 45 ++++++++++----- resources/lib/librarysync.py | 2 +- resources/lib/playbackutils.py | 5 +- 6 files changed, 78 insertions(+), 55 deletions(-) diff --git a/resources/language/English/strings.xml b/resources/language/English/strings.xml index bd909e25..9208715e 100644 --- a/resources/language/English/strings.xml +++ b/resources/language/English/strings.xml @@ -269,6 +269,7 @@ Force transcode Enable Plex context menu in Kodi Could not delete the Plex item. Is item deletion enabled on the Plex Media Server? + Start playback via PMS Verify Host SSL Certificate (more secure) diff --git a/resources/language/German/strings.xml b/resources/language/German/strings.xml index 6a907f3f..1d569543 100644 --- a/resources/language/German/strings.xml +++ b/resources/language/German/strings.xml @@ -299,6 +299,7 @@ Transkodieren erzwingen Plex Kontextmenu in Kodi aktivieren Konnte das Element nicht löschen. Ist diese Option auf dem Plex Medien Server aktiviert? + Wiedergabe via PMS starten Kodi wird jetzt neu gestartet um die Änderungen anzuwenden. diff --git a/resources/lib/PlexFunctions.py b/resources/lib/PlexFunctions.py index 7a3b3c46..70776f38 100644 --- a/resources/lib/PlexFunctions.py +++ b/resources/lib/PlexFunctions.py @@ -17,8 +17,49 @@ addonName = 'PlexKodiConnect' ############################################################################### +# Multiply Plex time by this factor to receive Kodi time PLEX_TO_KODI_TIMEFACTOR = 1.0 / 1000.0 +# Possible output of Kodi's ListItem.DBTYPE for all video items +KODI_VIDEOTYPES = ( + 'video', + 'movie', + 'set', + 'tvshow', + 'season', + 'episode', + 'musicvideo' +) + +# Possible output of Kodi's ListItem.DBTYPE for all audio items +KODI_AUDIOTYPES = ( + 'music', + 'song', + 'album', + 'artist' +) + +ITEMTYPE_FROM_PLEXTYPE = { + 'movie': 'Movies', + 'season': 'TVShows', + 'episode': 'TVShows', + 'show': 'TVShows', + 'artist': 'Music', + 'album': 'Music', + 'track': 'Music', + 'song': 'Music' +} + +KODITYPE_FROM_PLEXTYPE = { + 'movie': 'movie', + 'episode': 'episode', + 'track': 'song', + 'artist': 'artist', + 'album': 'album', + 'XXXXXX': 'musicvideo', + 'XXXXXXX': 'genre' +} + def ConvertPlexToKodiTime(plexTime): """ @@ -29,44 +70,6 @@ def ConvertPlexToKodiTime(plexTime): return int(float(plexTime) * PLEX_TO_KODI_TIMEFACTOR) -def GetItemClassFromType(itemType): - classes = { - 'movie': 'Movies', - 'season': 'TVShows', - 'episode': 'TVShows', - 'show': 'TVShows', - 'artist': 'Music', - 'album': 'Music', - 'track': 'Music', - 'song': 'Music' - } - return classes[itemType] - - -def GetItemClassFromNumber(itemType): - classes = { - 1: 'Movies', - 4: 'TVShows', - } - return classes[itemType] - - -def GetKodiTypeFromPlex(plexItemType): - """ - As used in playlist.item here: http://kodi.wiki/view/JSON-RPC_API - """ - classes = { - 'movie': 'movie', - 'episode': 'episode', - 'track': 'song', - 'artist': 'artist', - 'album': 'album', - 'XXXXXX': 'musicvideo', - 'XXXXXXX': 'genre' - } - return classes[plexItemType.lower()] - - def GetPlexKeyNumber(plexKey): """ Deconstructs e.g. '/library/metadata/xxxx' to the tuple diff --git a/resources/lib/context_entry.py b/resources/lib/context_entry.py index d6d1e78e..d4f6ac81 100644 --- a/resources/lib/context_entry.py +++ b/resources/lib/context_entry.py @@ -7,8 +7,7 @@ import logging import xbmc import xbmcaddon -import PlexAPI -from PlexFunctions import GetPlexMetadata, delete_item_from_pms +import PlexFunctions as PF import embydb_functions as embydb from utils import window, settings, dialog, language as lang, kodiSQL from dialogs import context @@ -25,7 +24,8 @@ OPTIONS = { # 'AddFav': lang(30405), # 'RemoveFav': lang(30406), # 'RateSong': lang(30407), - 'Transcode': lang(30412) + 'Transcode': lang(30412), + 'PMS_Play': lang(30415) # Use PMS to start playback } ############################################################################### @@ -46,9 +46,6 @@ class ContextMenu(object): if not self.item_id: return - self.item = GetPlexMetadata(self.item_id) - self.api = PlexAPI.API(self.item) - if self._select_menu(): self._action_menu() @@ -61,7 +58,6 @@ class ContextMenu(object): @classmethod def _get_item_type(cls): item_type = xbmc.getInfoLabel('ListItem.DBTYPE').decode('utf-8') - if not item_type: if xbmc.getCondVisibility('Container.Content(albums)'): item_type = "album" @@ -73,7 +69,6 @@ class ContextMenu(object): item_type = "picture" else: log.info("item_type is unknown") - return item_type @classmethod @@ -92,6 +87,11 @@ class ContextMenu(object): # Display select dialog options = [] + # if user uses direct paths, give option to initiate playback via PMS + if (window('useDirectPaths') == 'true' and + self.item_type in PF.KODI_VIDEOTYPES): + options.append(OPTIONS['PMS_Play']) + # if self.item_type in ("movie", "episode", "song"): # options.append(OPTIONS['Transcode']) @@ -116,10 +116,11 @@ class ContextMenu(object): # Addon settings options.append(OPTIONS['Addon']) - addon = xbmcaddon.Addon('plugin.video.plexkodiconnect') - context_menu = context.ContextMenu("script-emby-context.xml", - addon.getAddonInfo('path'), - "default", "1080i") + context_menu = context.ContextMenu( + "script-emby-context.xml", + xbmcaddon.Addon( + 'plugin.video.plexkodiconnect').getAddonInfo('path'), + "default", "1080i") context_menu.set_options(options) context_menu.doModal() @@ -135,6 +136,9 @@ class ContextMenu(object): if selected == OPTIONS['Transcode']: pass + elif selected == OPTIONS['PMS_Play']: + self._PMS_play() + elif selected == OPTIONS['Refresh']: self.emby.refreshItem(self.item_id) @@ -192,5 +196,20 @@ class ContextMenu(object): if delete: log.info("Deleting Plex item with id %s", self.item_id) - if delete_item_from_pms(self.item_id) is False: + if PF.delete_item_from_pms(self.item_id) is False: dialog(type_="ok", heading="{plex}", line1=lang(30414)) + + def _PMS_play(self): + """ + For using direct paths: Initiates playback using the PMS + """ + params = { + 'filename': '/library/metadata/%s' % self.item_id, + 'id': self.item_id, + 'dbid': self.kodi_id, + 'mode': "play" + } + from urllib import urlencode + handle = ("plugin://plugin.video.plexkodiconnect.movies?%s" + % urlencode(params)) + xbmc.executebuiltin('RunPlugin(%s)' % handle) diff --git a/resources/lib/librarysync.py b/resources/lib/librarysync.py index b4f211c3..3bc4168e 100644 --- a/resources/lib/librarysync.py +++ b/resources/lib/librarysync.py @@ -1623,7 +1623,7 @@ class LibrarySync(Thread): # Now tell Kodi where we are for item in items: itemFkt = getattr(itemtypes, - PF.GetItemClassFromType(item['kodi_type'])) + PF.ITEMTYPE_FROM_PLEXTYPE[item['kodi_type']]) with itemFkt() as Fkt: Fkt.updatePlaystate(item) diff --git a/resources/lib/playbackutils.py b/resources/lib/playbackutils.py index 6f832ef5..620ef303 100644 --- a/resources/lib/playbackutils.py +++ b/resources/lib/playbackutils.py @@ -3,7 +3,6 @@ ############################################################################### import logging -import json import sys from urllib import urlencode @@ -123,7 +122,7 @@ class PlaybackUtils(): self.pl.insertintoPlaylist( self.currentPosition+1, dbid, - PF.GetKodiTypeFromPlex(API.getType())) + PF.KODITYPE_FROM_PLEXTYPE[API.getType()]) self.currentPosition += 1 ############### -- CHECK FOR INTROS ################ @@ -143,7 +142,7 @@ class PlaybackUtils(): log.info("Adding main item to playlist.") self.pl.addtoPlaylist( dbid, - PF.GetKodiTypeFromPlex(API.getType())) + PF.KODITYPE_FROM_PLEXTYPE[API.getType()]) # Ensure that additional parts are played after the main item self.currentPosition += 1