Enable context menu playback

This commit is contained in:
croneter 2018-02-03 12:45:48 +01:00
parent a6a8c18711
commit bd85bb445e
6 changed files with 94 additions and 120 deletions

View file

@ -1,19 +1,20 @@
# -*- coding: utf-8 -*-
###############################################################################
import logging
from logging import getLogger
import xbmc
import xbmcaddon
from xbmc import getInfoLabel, sleep, executebuiltin, getCondVisibility
from xbmcaddon import Addon
import plexdb_functions as plexdb
from utils import window, settings, dialog, language as lang, kodiSQL
from utils import window, settings, dialog, language as lang
from dialogs import context
from PlexFunctions import delete_item_from_pms
import variables as v
import state
###############################################################################
LOG = logging.getLogger("PLEX." + __name__)
LOG = getLogger("PLEX." + __name__)
OPTIONS = {
'Refresh': lang(30410),
@ -30,69 +31,74 @@ OPTIONS = {
class ContextMenu(object):
"""
Class initiated if user opens "Plex options" on a PLEX item using the Kodi
context menu
"""
_selected_option = None
def __init__(self):
self.kodi_id = xbmc.getInfoLabel('ListItem.DBID').decode('utf-8')
self.item_type = self._get_item_type()
self.item_id = self._get_item_id(self.kodi_id, self.item_type)
LOG.info("Found item_id: %s item_type: %s",
self.item_id, self.item_type)
if not self.item_id:
"""
Simply instantiate with ContextMenu() - no need to call any methods
"""
self.kodi_id = getInfoLabel('ListItem.DBID').decode('utf-8')
self.kodi_type = self._get_kodi_type()
self.plex_id = self._get_plex_id(self.kodi_id, self.kodi_type)
if self.kodi_type:
self.plex_type = v.PLEX_TYPE_FROM_KODI_TYPE[self.kodi_type]
else:
self.plex_type = None
LOG.debug("Found plex_id: %s plex_type: %s",
self.plex_id, self.plex_type)
if not self.plex_id:
return
if self._select_menu():
self._action_menu()
if self._selected_option in (OPTIONS['Delete'],
OPTIONS['Refresh']):
LOG.info("refreshing container")
xbmc.sleep(500)
xbmc.executebuiltin('Container.Refresh')
sleep(500)
executebuiltin('Container.Refresh')
@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"
elif xbmc.getCondVisibility('Container.Content(artists)'):
item_type = "artist"
elif xbmc.getCondVisibility('Container.Content(songs)'):
item_type = "song"
elif xbmc.getCondVisibility('Container.Content(pictures)'):
item_type = "picture"
@staticmethod
def _get_kodi_type():
kodi_type = getInfoLabel('ListItem.DBTYPE').decode('utf-8')
if not kodi_type:
if getCondVisibility('Container.Content(albums)'):
kodi_type = v.KODI_TYPE_ALBUM
elif getCondVisibility('Container.Content(artists)'):
kodi_type = v.KODI_TYPE_ARTIST
elif getCondVisibility('Container.Content(songs)'):
kodi_type = v.KODI_TYPE_SONG
elif getCondVisibility('Container.Content(pictures)'):
kodi_type = v.KODI_TYPE_PHOTO
else:
LOG.info("item_type is unknown")
return item_type
LOG.info("kodi_type is unknown")
kodi_type = None
return kodi_type
@classmethod
def _get_item_id(cls, kodi_id, item_type):
item_id = xbmc.getInfoLabel('ListItem.Property(plexid)')
if not item_id and kodi_id and item_type:
@staticmethod
def _get_plex_id(kodi_id, kodi_type):
plex_id = getInfoLabel('ListItem.Property(plexid)') or None
if not plex_id and kodi_id and kodi_type:
with plexdb.Get_Plex_DB() as plexcursor:
item = plexcursor.getItem_byKodiId(kodi_id, item_type)
item = plexcursor.getItem_byKodiId(kodi_id, kodi_type)
try:
item_id = item[0]
plex_id = item[0]
except TypeError:
LOG.error('Could not get the Plex id for context menu')
return item_id
LOG.info('Could not get the Plex id for context menu')
return plex_id
def _select_menu(self):
# Display select dialog
"""
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 v.KODI_VIDEOTYPES):
if state.DIRECT_PATHS and self.kodi_type in v.KODI_VIDEOTYPES:
options.append(OPTIONS['PMS_Play'])
if self.item_type in v.KODI_VIDEOTYPES:
if self.kodi_type in v.KODI_VIDEOTYPES:
options.append(OPTIONS['Transcode'])
# userdata = self.api.getUserData()
# if userdata['Favorite']:
# # Remove from emby favourites
@ -100,11 +106,9 @@ class ContextMenu(object):
# else:
# # Add to emby favourites
# options.append(OPTIONS['AddFav'])
# if self.item_type == "song":
# if self.kodi_type == "song":
# # Set custom song rating
# options.append(OPTIONS['RateSong'])
# Refresh item
# options.append(OPTIONS['Refresh'])
# Delete item, only if the Plex Home main user is logged in
@ -113,103 +117,65 @@ class ContextMenu(object):
options.append(OPTIONS['Delete'])
# Addon settings
options.append(OPTIONS['Addon'])
context_menu = context.ContextMenu(
"script-emby-context.xml",
xbmcaddon.Addon(
'plugin.video.plexkodiconnect').getAddonInfo('path'),
"default", "1080i")
Addon('plugin.video.plexkodiconnect').getAddonInfo('path'),
"default",
"1080i")
context_menu.set_options(options)
context_menu.doModal()
if context_menu.is_selected():
self._selected_option = context_menu.get_selected()
return self._selected_option
def _action_menu(self):
"""
Do whatever the user selected to do
"""
selected = self._selected_option
if selected == OPTIONS['Transcode']:
window('plex_forcetranscode', value='true')
state.FORCE_TRANSCODE = True
self._PMS_play()
elif selected == OPTIONS['PMS_Play']:
self._PMS_play()
# elif selected == OPTIONS['Refresh']:
# self.emby.refreshItem(self.item_id)
# elif selected == OPTIONS['AddFav']:
# self.emby.updateUserRating(self.item_id, favourite=True)
# elif selected == OPTIONS['RemoveFav']:
# self.emby.updateUserRating(self.item_id, favourite=False)
# elif selected == OPTIONS['RateSong']:
# self._rate_song()
elif selected == OPTIONS['Addon']:
xbmc.executebuiltin('Addon.OpenSettings(plugin.video.plexkodiconnect)')
executebuiltin('Addon.OpenSettings(plugin.video.plexkodiconnect)')
elif selected == OPTIONS['Delete']:
self._delete_item()
def _rate_song(self):
conn = kodiSQL('music')
cursor = conn.cursor()
query = "SELECT rating FROM song WHERE idSong = ?"
cursor.execute(query, (self.kodi_id,))
try:
value = cursor.fetchone()[0]
current_value = int(round(float(value), 0))
except TypeError:
pass
else:
new_value = dialog("numeric", 0, lang(30411), str(current_value))
if new_value > -1:
new_value = int(new_value)
if new_value > 5:
new_value = 5
if settings('enableUpdateSongRating') == "true":
musicutils.updateRatingToFile(new_value, self.api.get_file_path())
query = "UPDATE song SET rating = ? WHERE idSong = ?"
cursor.execute(query, (new_value, self.kodi_id,))
conn.commit()
finally:
cursor.close()
def _delete_item(self):
"""
Delete item on PMS
"""
delete = True
if settings('skipContextMenu') != "true":
if not dialog("yesno", heading=lang(29999), line1=lang(33041)):
LOG.info("User skipped deletion for: %s", self.item_id)
if not dialog("yesno", heading="{plex}", line1=lang(33041)):
LOG.info("User skipped deletion for: %s", self.plex_id)
delete = False
if delete:
LOG.info("Deleting Plex item with id %s", self.item_id)
if delete_item_from_pms(self.item_id) is False:
LOG.info("Deleting Plex item with id %s", self.plex_id)
if delete_item_from_pms(self.plex_id) is False:
dialog("ok", heading="{plex}", line1=lang(30414))
def _PMS_play(self):
"""
For using direct paths: Initiates playback using the PMS
"""
window('plex_contextplay', value='true')
state.CONTEXT_MENU_PLAY = True
params = {
'filename': '/library/metadata/%s' % self.item_id,
'id': self.item_id,
'dbid': self.kodi_id,
'mode': "play"
'mode': 'play',
'plex_id': self.plex_id,
'plex_type': self.plex_type
}
from urllib import urlencode
handle = ("plugin://plugin.video.plexkodiconnect/movies?%s"
% urlencode(params))
xbmc.executebuiltin('RunPlugin(%s)' % handle)
executebuiltin('RunPlugin(%s)' % handle)

View file

@ -17,7 +17,7 @@ from playutils import PlayUtils
from PKC_listitem import PKC_ListItem
from pickler import pickle_me, Playback_Successful
import json_rpc as js
from utils import window, settings, dialog, language as lang, tryEncode
from utils import settings, dialog, language as lang, tryEncode
from plexbmchelper.subscribers import LOCKER
import variables as v
import state
@ -120,8 +120,6 @@ def playback_init(plex_id, plex_type, playqueue):
Playback setup if Kodi starts playing an item for the first time.
"""
LOG.info('Initializing PKC playback')
contextmenu_play = window('plex_contextplay') == 'true'
window('plex_contextplay', clear=True)
xml = GetPlexMetadata(plex_id)
try:
xml[0].attrib
@ -158,6 +156,9 @@ def playback_init(plex_id, plex_type, playqueue):
# Sleep a bit to let setResolvedUrl do its thing - bit ugly
sleep(200)
_process_stack(playqueue, stack)
# Reset some playback variables
state.CONTEXT_MENU_PLAY = False
state.FORCE_TRANSCODE = False
# New thread to release this one sooner (e.g. harddisk spinning up)
thread = Thread(target=Player().play,
args=(playqueue.kodi_pl, ))
@ -176,7 +177,10 @@ def _prep_playlist_stack(xml):
stack = []
for item in xml:
api = API(item)
if api.getType() != v.PLEX_TYPE_CLIP:
if (state.CONTEXT_MENU_PLAY is False or
api.getType() != v.PLEX_TYPE_CLIP):
# If user chose to play via PMS or force transcode, do not
# use the item path stored in the Kodi DB
with plexdb.Get_Plex_DB() as plex_db:
plex_dbitem = plex_db.getItem_byId(api.getRatingKey())
kodi_id = plex_dbitem[0] if plex_dbitem else None
@ -243,6 +247,7 @@ def _process_stack(playqueue, stack, fill_queue=False):
playlist_item.offset = item['offset']
playlist_item.part = item['part']
playlist_item.id = item['id']
playlist_item.force_transcode = state.FORCE_TRANSCODE
playlist_item.init_done = True
pos += 1
if fill_queue:
@ -356,7 +361,8 @@ def process_indirect(key, offset, resolve=True):
pickle_me(result)
else:
thread = Thread(target=Player().play,
args={'item': tryEncode(playurl), 'listitem': listitem})
args={'item': tryEncode(playurl),
'listitem': listitem})
thread.setDaemon(True)
LOG.info('Done initializing PKC playback, starting Kodi player')
thread.start()

View file

@ -5,7 +5,6 @@ from logging import getLogger
from xbmc import Player
from utils import window
from downloadutils import DownloadUtils as DU
from plexbmchelper.subscribers import LOCKER
import variables as v
@ -26,10 +25,6 @@ def playback_cleanup():
# We might have saved a transient token from a user flinging media via
# Companion (if we could not use the playqueue to store the token)
state.PLEX_TRANSIENT_TOKEN = None
for item in ('plex_customplaylist',
'plex_customplaylist.seektime',
'plex_forcetranscode'):
window(item, clear=True)
for playerid in state.ACTIVE_PLAYERS:
status = state.PLAYER_STATES[playerid]
# Remember the last played item later

View file

@ -197,6 +197,7 @@ class Playlist_Item(object):
playcount = None [int] how many times the item has already been played
offset = None [int] the item's view offset UPON START in Plex time
part = 0 [int] part number if Plex video consists of mult. parts
force_transcode [bool] defaults to False
init_done = False Set to True only if run through playback init
"""
def __init__(self):
@ -215,6 +216,7 @@ class Playlist_Item(object):
self.offset = None
# If Plex video consists of several parts; part number
self.part = 0
self.force_transcode = False
self.init_done = False
def __repr__(self):

View file

@ -87,7 +87,8 @@ class PlayUtils():
- codec is in h265
- 10bit video codec
- HEVC codec
- window variable 'plex_forcetranscode' set to 'true'
- playqueue_item force_transcode is set to True
- state variable FORCE_TRANSCODE set to True
(excepting trailers etc.)
- video bitrate above specified settings bitrate
if the corresponding file settings are set to 'true'
@ -97,7 +98,7 @@ class PlayUtils():
return False
videoCodec = self.api.getVideoCodec()
LOG.info("videoCodec: %s" % videoCodec)
if window('plex_forcetranscode') == 'true':
if self.item.force_transcode is True:
LOG.info('User chose to force-transcode')
return True
codec = videoCodec['videocodec']

View file

@ -143,6 +143,10 @@ RESUMABLE = False
# Set by SpecialMonitor - did user choose to resume playback or start from the
# beginning?
RESUME_PLAYBACK = False
# Was the playback initiated by the user using the Kodi context menu?
CONTEXT_MENU_PLAY = False
# Set by context menu - shall we force-transcode the next playing item?
FORCE_TRANSCODE = False
# Kodi webserver details
WEBSERVER_PORT = 8080