Merge pull request #861 from croneter/fix-crash

Another attempt to keep Kodi from crashing on playback startup
This commit is contained in:
croneter 2019-05-30 14:32:37 +02:00 committed by GitHub
commit ab47b63bc5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 37 additions and 28 deletions

View file

@ -4,8 +4,8 @@
<import addon="xbmc.python" version="2.1.0"/> <import addon="xbmc.python" version="2.1.0"/>
<import addon="script.module.requests" version="2.9.1" /> <import addon="script.module.requests" version="2.9.1" />
<import addon="script.module.defusedxml" version="0.5.0"/> <import addon="script.module.defusedxml" version="0.5.0"/>
<import addon="plugin.video.plexkodiconnect.movies" version="2.1.0" /> <import addon="plugin.video.plexkodiconnect.movies" version="2.1.1" />
<import addon="plugin.video.plexkodiconnect.tvshows" version="2.1.0" /> <import addon="plugin.video.plexkodiconnect.tvshows" version="2.1.1" />
</requires> </requires>
<extension point="xbmc.python.pluginsource" library="default.py"> <extension point="xbmc.python.pluginsource" library="default.py">
<provides>video audio image</provides> <provides>video audio image</provides>

View file

@ -157,17 +157,11 @@ class Main():
# Handle -1 received, not waiting for main thread # Handle -1 received, not waiting for main thread
return return
# Wait for the result from the main PKC thread # Wait for the result from the main PKC thread
result = transfer.wait_for_transfer() result = transfer.wait_for_transfer(source='main')
if result is None: if result is True:
LOG.error('Error encountered, aborting')
utils.dialog('notification',
heading='{plex}',
message=utils.lang(30128),
icon='{error}',
time=3000)
xbmcplugin.setResolvedUrl(HANDLE, False, xbmcgui.ListItem())
elif result is True:
xbmcplugin.setResolvedUrl(HANDLE, False, xbmcgui.ListItem()) xbmcplugin.setResolvedUrl(HANDLE, False, xbmcgui.ListItem())
# Tell main thread that we're done
transfer.send(True, target='main')
else: else:
# Received a xbmcgui.ListItem() # Received a xbmcgui.ListItem()
xbmcplugin.setResolvedUrl(HANDLE, True, result) xbmcplugin.setResolvedUrl(HANDLE, True, result)

View file

@ -177,10 +177,10 @@ def _playback_init(plex_id, plex_type, playqueue, pos):
plex_type in v.PLEX_VIDEOTYPES and plex_type in v.PLEX_VIDEOTYPES and
playqueue.kodi_pl.size() > 1): playqueue.kodi_pl.size() > 1):
LOG.debug('Detected widget playback for videos') LOG.debug('Detected widget playback for videos')
# Need to clear playlist because playqueue.kodi_pl.size() could return # playqueue.kodi_pl.size() could return more than one - since playback
# more than one - since playback was initiated from the audio queue! # was initiated from the audio queue!
playqueue.clear() pass
if playqueue.kodi_pl.size() > 1: elif playqueue.kodi_pl.size() > 1:
# Special case - we already got a filled Kodi playqueue # Special case - we already got a filled Kodi playqueue
try: try:
_init_existing_kodi_playlist(playqueue, pos) _init_existing_kodi_playlist(playqueue, pos)
@ -199,8 +199,7 @@ def _playback_init(plex_id, plex_type, playqueue, pos):
return return
# "Usual" case - consider trailers and parts and build both Kodi and Plex # "Usual" case - consider trailers and parts and build both Kodi and Plex
# playqueues # playqueues
# Pass dummy PKC video with 0 length so Kodi immediately stops playback # Release default.py
# and we can build our own playqueue.
_ensure_resolve() _ensure_resolve()
api = API(xml[0]) api = API(xml[0])
trailers = False trailers = False
@ -270,9 +269,14 @@ def _ensure_resolve(abort=False):
if RESOLVE: if RESOLVE:
# Releases the other Python thread without a ListItem # Releases the other Python thread without a ListItem
transfer.send(True) transfer.send(True)
# Shows PKC error message # Wait for default.py to have completed xbmcplugin.setResolvedUrl()
# transfer.send(None) transfer.wait_for_transfer(source='default')
if abort: if abort:
utils.dialog('notification',
heading='{plex}',
message=utils.lang(30128),
icon='{error}',
time=3000)
# Reset some playback variables # Reset some playback variables
app.PLAYSTATE.context_menu_play = False app.PLAYSTATE.context_menu_play = False
app.PLAYSTATE.force_transcode = False app.PLAYSTATE.force_transcode = False
@ -403,8 +407,7 @@ def _conclude_playback(playqueue, pos):
playurl = item.file playurl = item.file
if not playurl: if not playurl:
LOG.info('Did not get a playurl, aborting playback silently') LOG.info('Did not get a playurl, aborting playback silently')
app.PLAYSTATE.resume_playback = False _ensure_resolve(abort=True)
transfer.send(True)
return return
listitem.setPath(utils.try_encode(playurl)) listitem.setPath(utils.try_encode(playurl))
if item.playmethod == 'DirectStream': if item.playmethod == 'DirectStream':

View file

@ -29,6 +29,8 @@ class PlaybackTask(backgroundthread.Task):
# E.g. other add-ons scanning for Extras folder # E.g. other add-ons scanning for Extras folder
LOG.debug('Detected 3rd party add-on call - ignoring') LOG.debug('Detected 3rd party add-on call - ignoring')
transfer.send(True) transfer.send(True)
# Wait for default.py to have completed xbmcplugin.setResolvedUrl()
transfer.wait_for_transfer(source='default')
return return
params = dict(utils.parse_qsl(params)) params = dict(utils.parse_qsl(params))
mode = params.get('mode') mode = params.get('mode')

View file

@ -14,7 +14,8 @@ import xbmcgui
LOG = getLogger('PLEX.transfer') LOG = getLogger('PLEX.transfer')
MONITOR = xbmc.Monitor() MONITOR = xbmc.Monitor()
WINDOW = xbmcgui.Window(10000) WINDOW = xbmcgui.Window(10000)
WINDOW_RESULT = 'plexkodiconnect.result'.encode('utf-8') WINDOW_UPSTREAM = 'plexkodiconnect.result.upstream'.encode('utf-8')
WINDOW_DOWNSTREAM = 'plexkodiconnect.result.downstream'.encode('utf-8')
WINDOW_COMMAND = 'plexkodiconnect.command'.encode('utf-8') WINDOW_COMMAND = 'plexkodiconnect.command'.encode('utf-8')
@ -90,7 +91,7 @@ def de_serialize(answ):
raise NotImplementedError('Not implemented: %s' % answ) raise NotImplementedError('Not implemented: %s' % answ)
def send(pkc_listitem): def send(pkc_listitem, target='default'):
""" """
Pickles the obj to the window variable. Use to transfer Python Pickles the obj to the window variable. Use to transfer Python
objects between different PKC python instances (e.g. if default.py is objects between different PKC python instances (e.g. if default.py is
@ -98,18 +99,27 @@ def send(pkc_listitem):
obj can be pretty much any Python object. However, classes and obj can be pretty much any Python object. However, classes and
functions won't work. See the Pickle documentation functions won't work. See the Pickle documentation
Set target='default' if you send data TO another Python default.py
instance, 'main' if your default.py needs to send to the main thread
""" """
window = WINDOW_DOWNSTREAM if target == 'default' else WINDOW_UPSTREAM
LOG.debug('Sending: %s', pkc_listitem) LOG.debug('Sending: %s', pkc_listitem)
kodi_window(WINDOW_RESULT, kodi_window(window,
value=json.dumps(serialize(pkc_listitem))) value=json.dumps(serialize(pkc_listitem)))
def wait_for_transfer(): def wait_for_transfer(source='main'):
"""
Set source='default' if you wait for data FROM another Python default.py
instance, 'main' if your default.py needs to wait for the main thread
"""
window = WINDOW_DOWNSTREAM if source == 'main' else WINDOW_UPSTREAM
result = '' result = ''
while not result: while not result:
result = kodi_window(WINDOW_RESULT) result = kodi_window(window)
if result: if result:
kodi_window(WINDOW_RESULT, clear=True) kodi_window(window, clear=True)
LOG.debug('Received') LOG.debug('Received')
result = json.loads(result) result = json.loads(result)
return de_serialize(result) return de_serialize(result)