Interrupt sleep if Kodi exits. Use Monitor's Player()

This commit is contained in:
croneter 2018-11-20 16:58:25 +01:00
parent fff791e3d1
commit 6fe0e23f53
22 changed files with 70 additions and 83 deletions

View file

@ -32,6 +32,8 @@ class App(object):
self.command_pipeline_queue = Queue.Queue()
# Websocket_client queue to communicate with librarysync
self.websocket_queue = Queue.Queue()
# xbmc.Monitor() instance from kodimonitor.py
self.monitor = None
def load_settings(self):
# Number of items to fetch and display in widgets

View file

@ -4,7 +4,6 @@ from __future__ import absolute_import, division, unicode_literals
from logging import getLogger
from urllib import quote_plus, unquote
import requests
import xbmc
from .kodi_db import KodiVideoDB, KodiMusicDB, KodiTextureDB
from . import app, backgroundthread, utils
@ -59,7 +58,7 @@ class ImageCachingThread(backgroundthread.KillableThread):
# Abort was requested while waiting. We should exit
LOG.info("---===### Stopped ImageCachingThread ###===---")
return
xbmc.sleep(1000)
app.APP.monitor.waitForAbort(1)
cache_url(url)
LOG.info("---===### Stopped ImageCachingThread ###===---")
@ -95,7 +94,7 @@ def cache_url(url):
'over-loaded. Sleep %s seconds before trying '
'again to download %s',
2**sleeptime, double_urldecode(url))
xbmc.sleep((2**sleeptime) * 1000)
app.APP.monitor.waitForAbort((2**sleeptime))
sleeptime += 1
continue
except Exception as err:

View file

@ -7,7 +7,7 @@ import Queue
import heapq
import xbmc
from . import utils
from . import utils, app
from Queue import Empty
LOG = getLogger('PLEX.' + __name__)
@ -253,7 +253,7 @@ class NonstoppingBackgroundWorker(BackgroundWorker):
self._queue.task_done()
self._task = None
except Queue.Empty:
xbmc.sleep(50)
app.APP.monitor.waitForAbort(0.05)
def working(self):
return self._working

View file

@ -63,7 +63,7 @@ class ContextMenu(object):
if self._selected_option in (OPTIONS['Delete'],
OPTIONS['Refresh']):
LOG.info("refreshing container")
xbmc.sleep(500)
app.APP.monitor.waitForAbort(0.5)
xbmc.executebuiltin('Container.Refresh')
@staticmethod

View file

@ -9,7 +9,7 @@ from logging import getLogger
from sys import argv
from urllib import urlencode
import xbmcplugin
from xbmc import sleep, executebuiltin
from xbmc import sleep
from xbmcgui import ListItem
from . import utils

View file

@ -13,7 +13,7 @@ from xbmcgui import Window
from .plex_db import PlexDB
from . import kodi_db
from .downloadutils import DownloadUtils as DU
from . import utils, timing, plex_functions as PF, playback, initialsetup
from . import utils, timing, plex_functions as PF, playback
from . import json_rpc as js, playqueue as PQ, playlist_func as PL
from . import backgroundthread, app, variables as v
@ -133,11 +133,11 @@ class KodiMonitor(xbmc.Monitor):
utils.window('plex_online', value="sleep")
elif method == "System.OnWake":
# Allow network to wake up
xbmc.sleep(10000)
self.waitForAbort(10)
utils.window('plex_online', value="false")
elif method == "GUI.OnScreensaverDeactivated":
if utils.settings('dbSyncScreensaver') == "true":
xbmc.sleep(5000)
self.waitForAbort(5)
utils.plex_command('RUN_LIB_SCAN', 'full')
elif method == "System.OnQuit":
LOG.info('Kodi OnQuit detected - shutting down')
@ -267,7 +267,7 @@ class KodiMonitor(xbmc.Monitor):
# start as Kodi updates this info very late!! Might get previous
# element otherwise
self._already_slept = True
xbmc.sleep(1000)
self.waitForAbort(1)
try:
json_item = js.get_item(playerid)
except KeyError:
@ -422,7 +422,7 @@ class SpecialMonitor(backgroundthread.KillableThread):
pass
# TODO: start polling PMS for playlist changes
# Optionally: poll PMS continuously with custom intervall
xbmc.sleep(200)
app.APP.monitor.waitForAbort(0.2)
LOG.info("#====---- Special Monitor Stopped ----====#")
@ -525,7 +525,7 @@ def _clean_file_table():
This function tries for at most 5 seconds to clean the file table.
"""
LOG.debug('Start cleaning Kodi files table')
xbmc.sleep(2000)
app.APP.monitor.waitForAbort(2)
with kodi_db.KodiVideoDB() as kodidb_1:
with kodi_db.KodiVideoDB() as kodidb_2:
for file_id in kodidb_1.obsolete_file_ids():

View file

@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, unicode_literals
from logging import getLogger
import xbmc
from . import common
from ..plex_api import API
@ -62,7 +61,7 @@ class FanartThread(backgroundthread.KillableThread):
if self.isSuspended():
if self.isCanceled():
return
xbmc.sleep(1000)
app.APP.monitor.waitForAbort(1)
LOG.info('FanartThread finished')
self.callback(finished)

View file

@ -2,7 +2,6 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, unicode_literals
from logging import getLogger
import xbmc
from .get_metadata import GetMetadataTask, reset_collections
from .process_metadata import InitNewSection, UpdateLastSync, ProcessMetadata
@ -120,7 +119,7 @@ class FullSync(common.libsync_mixin):
continue
LOG.debug('Waiting for download threads to finish')
while self.threader.threader.working():
xbmc.sleep(100)
app.APP.monitor.waitForAbort(0.1)
LOG.debug('Waiting for processing thread to finish section')
self.queue.join()
reset_collections()

View file

@ -3,9 +3,7 @@
from __future__ import absolute_import, division, unicode_literals
from logging import getLogger
import xbmc
from .. import plex_functions as PF, utils, timing, variables as v
from .. import plex_functions as PF, utils, timing, variables as v, app
LOG = getLogger('PLEX.sync.time')
@ -88,7 +86,7 @@ def sync_pms_time():
# Toggle watched state
PF.scrobble(plex_id, 'watched')
# Let the PMS process this first!
xbmc.sleep(1000)
app.APP.monitor.waitForAbort(1)
# Get updated metadata
xml = PF.GetPlexMetadata(plex_id)
# Toggle watched state back

View file

@ -6,7 +6,6 @@ Used to kick off Kodi playback
from __future__ import absolute_import, division, unicode_literals
from logging import getLogger
from threading import Thread
from xbmc import Player, sleep
from .plex_api import API
from .plex_db import PlexDB
@ -209,7 +208,7 @@ def _playback_init(plex_id, plex_type, playqueue, pos):
# Sleep a bit to let setResolvedUrl do its thing - bit ugly
sleep_timer = 0
while not app.PLAYSTATE.pkc_caused_stop_done:
sleep(50)
app.APP.monitor.waitForAbort(0.05)
sleep_timer += 1
if sleep_timer > 100:
break
@ -505,7 +504,7 @@ def process_indirect(key, offset, resolve=True):
result.listitem = listitem
pickler.pickle_me(result)
else:
thread = Thread(target=Player().play,
thread = Thread(target=app.APP.monitor.xmbcplayer.play,
args={'item': utils.try_encode(playurl),
'listitem': listitem})
thread.setDaemon(True)
@ -547,12 +546,11 @@ def threaded_playback(kodi_playlist, startpos, offset):
"""
Seek immediately after kicking off playback is not reliable.
"""
player = Player()
player.play(kodi_playlist, None, False, startpos)
app.APP.monitor.xmbcplayer.play(kodi_playlist, None, False, startpos)
if offset and offset != '0':
i = 0
while not player.isPlaying():
sleep(100)
while not app.APP.monitor.xmbcplayer.isPlaying():
app.APP.monitor.waitForAbort(0.1)
i += 1
if i > 100:
LOG.error('Could not seek to %s', offset)

View file

@ -9,8 +9,7 @@ from ..watchdog import events
from ..watchdog.observers import Observer
from ..watchdog.utils.bricks import OrderedSetQueue
from .. import path_ops
from .. import variables as v
from .. import path_ops, variables as v, app
###############################################################################
LOG = getLogger('PLEX.playlists.common')
@ -171,7 +170,7 @@ class PlaylistObserver(Observer):
try:
new_event, new_watch = event_queue.get(block=False)
except Queue.Empty:
time.sleep(0.2)
app.APP.monitor.waitForAbort(0.2)
else:
event_queue.task_done()
start = time.time()

View file

@ -87,7 +87,7 @@ def init_playqueue_from_plex_children(plex_id, transient_token=None):
PL.add_item_to_playlist(playqueue, i, plex_id=api.plex_id())
playqueue.plex_transient_token = transient_token
LOG.debug('Firing up Kodi player')
xbmc.Player().play(playqueue.kodi_pl, None, False, 0)
app.APP.xbmcplayer.play(playqueue.kodi_pl, None, False, 0)
return playqueue
@ -197,7 +197,7 @@ class PlayqueueMonitor(backgroundthread.KillableThread):
while self.isSuspended():
if self.isCanceled():
break
xbmc.sleep(1000)
app.APP.monitor.waitForAbort(1)
with app.APP.lock_playqueues:
for playqueue in PLAYQUEUES:
kodi_pl = js.playlist_get_items(playqueue.playlistid)
@ -211,5 +211,5 @@ class PlayqueueMonitor(backgroundthread.KillableThread):
# compare old and new playqueue
self._compare_playqueues(playqueue, kodi_pl)
playqueue.old_kodi_pl = list(kodi_pl)
xbmc.sleep(200)
app.APP.monitor.waitForAbort(0.2)
LOG.info("----===## PlayqueueMonitor stopped ##===----")

View file

@ -9,7 +9,7 @@ from threading import Thread
from Queue import Empty
from socket import SHUT_RDWR
from urllib import urlencode
from xbmc import sleep, executebuiltin, Player
from xbmc import executebuiltin
from .plexbmchelper import listener, plexgdm, subscribers, httppersist
from .plex_api import API
@ -76,8 +76,6 @@ class PlexCompanion(backgroundthread.KillableThread):
self.client = plexgdm.plexgdm()
self.client.clientDetails()
LOG.debug("Registration string is:\n%s", self.client.getClientDetails())
# kodi player instance
self.player = Player()
self.httpd = False
self.subscription_manager = None
super(PlexCompanion, self).__init__()
@ -177,14 +175,14 @@ class PlexCompanion(backgroundthread.KillableThread):
if 'audioStreamID' in data:
index = playqueue.items[pos].kodi_stream_index(
data['audioStreamID'], 'audio')
self.player.setAudioStream(index)
app.APP.monitor.xbmcplayer.setAudioStream(index)
elif 'subtitleStreamID' in data:
if data['subtitleStreamID'] == '0':
self.player.showSubtitles(False)
app.APP.monitor.xbmcplayer.showSubtitles(False)
else:
index = playqueue.items[pos].kodi_stream_index(
data['subtitleStreamID'], 'subtitle')
self.player.setSubtitleStream(index)
app.APP.monitor.xbmcplayer.setSubtitleStream(index)
else:
LOG.error('Unknown setStreams command: %s', data)
@ -269,7 +267,7 @@ class PlexCompanion(backgroundthread.KillableThread):
# Start up instances
request_mgr = httppersist.RequestMgr()
subscription_manager = subscribers.SubscriptionMgr(request_mgr,
self.player)
app.APP.monitor.xbmcplayer)
self.subscription_manager = subscription_manager
if utils.settings('plexCompanion') == 'true':
@ -288,7 +286,7 @@ class PlexCompanion(backgroundthread.KillableThread):
LOG.error("Unable to start PlexCompanion. Traceback:")
import traceback
LOG.error(traceback.print_exc())
sleep(3000)
app.APP.monitor.waitForAbort(3)
if start_count == 3:
LOG.error("Error: Unable to start web helper.")
httpd = False
@ -308,7 +306,7 @@ class PlexCompanion(backgroundthread.KillableThread):
while self.isSuspended():
if self.isCanceled():
break
sleep(1000)
app.APP.monitor.waitForAbort(1)
try:
message_count += 1
if httpd:
@ -347,6 +345,6 @@ class PlexCompanion(backgroundthread.KillableThread):
app.APP.companion_queue.task_done()
# Don't sleep
continue
sleep(50)
app.APP.monitor.waitForAbort(0.05)
subscription_manager.signal_stop()
client.stop_all()

View file

@ -8,10 +8,9 @@ from urlparse import urlparse, parse_qsl
from copy import deepcopy
from time import time
from threading import Thread
from xbmc import sleep
from .downloadutils import DownloadUtils as DU
from . import backgroundthread, utils, plex_tv, variables as v
from . import backgroundthread, utils, plex_tv, variables as v, app
###############################################################################
LOG = getLogger('PLEX.plex_functions')
@ -388,7 +387,7 @@ def _pms_list_from_plex_tv(token):
thread.start()
threads.append(thread)
else:
sleep(50)
app.APP.monitor.waitForAbort(0.05)
# wait for requests being answered
for thread in threads:
thread.join()
@ -616,7 +615,7 @@ class DownloadGen(object):
self._download_chunk(
start=self.current + (self.cache_factor - 1) * CONTAINERSIZE)
return child
sleep(100)
app.APP.monitor.waitForAbort(0.1)
if not len(self.pending_counter) and not len(self.xml):
raise StopIteration
LOG.debug('Waiting for download to finish')

View file

@ -4,7 +4,6 @@ from __future__ import absolute_import, division, unicode_literals
from logging import getLogger
import time
import threading
import xbmc
from .downloadutils import DownloadUtils as DU
from . import utils, app
@ -181,12 +180,12 @@ class PinLogin(object):
try:
token = xml.find('auth_token').text
except AttributeError:
time.sleep(self.POLL_INTERVAL)
app.APP.monitor.waitForAbort(self.POLL_INTERVAL)
continue
if token:
self.token = token
break
time.sleep(self.POLL_INTERVAL)
app.APP.monitor.waitForAbort(self.POLL_INTERVAL)
if self._callback:
self._callback(self.token, self.xml)
if self.token:
@ -256,7 +255,7 @@ def _sign_in_with_pin():
LOG.debug('Pin login aborted')
pinlogin.abort()
return
xbmc.sleep(100)
app.APP.monitor.waitForAbort(0.1)
if not pinlogin.expired:
if pinlogin.xml:
pin_login_window.setLinking()

View file

@ -15,12 +15,11 @@ from .. import companion
from .. import json_rpc as js
from .. import clientinfo
from .. import variables as v
from .. import app
###############################################################################
LOG = getLogger('PLEX.listener')
PLAYER = xbmc.Player()
MONITOR = xbmc.Monitor()
# Hack we need in order to keep track of the open connections from Plex Web
CLIENT_DICT = {}
@ -130,20 +129,20 @@ class MyHandler(BaseHTTPRequestHandler):
# Only reply if there is indeed something playing
# Otherwise, all clients seem to keep connection open
if params.get('wait') == '1':
MONITOR.waitForAbort(0.95)
app.APP.monitor.waitForAbort(0.95)
if self.client_address[0] not in CLIENT_DICT:
CLIENT_DICT[self.client_address[0]] = []
tracker = CLIENT_DICT[self.client_address[0]]
tracker.append(self.client_address[1])
while (not PLAYER.isPlaying() and
not MONITOR.abortRequested() and
while (not app.APP.monitor.xbmcplayer.isPlaying() and
not app.APP.monitor.abortRequested() and
sub_mgr.stop_sent_to_web and not
(len(tracker) >= 4 and
tracker[0] == self.client_address[1])):
# Keep at most 3 connections open, then drop the first one
# Doesn't need to be thread-save
# Silly stuff really
MONITOR.waitForAbort(1)
app.APP.monitor.waitForAbort(1)
# Let PKC know that we're releasing this connection
tracker.pop(0)
msg = sub_mgr.msg(js.get_players()).format(

View file

@ -28,11 +28,9 @@ import logging
import socket
import threading
import time
from xbmc import sleep
from ..downloadutils import DownloadUtils as DU
from .. import utils, app
from .. import variables as v
from .. import utils, app, variables as v
###############################################################################
@ -172,7 +170,7 @@ class plexgdm:
log.debug("Sending registration data HTTP/1.0 200 OK")
self.client_registered = True
sleep(500)
app.APP.monitor.waitForAbort(0.5)
log.info("Client Update loop stopped")
# When we are finished, then send a final goodbye message to
# deregister cleanly.
@ -286,7 +284,7 @@ class plexgdm:
if discovery_count > self.discovery_interval:
self.discover()
discovery_count = 0
sleep(500)
app.APP.monitor.waitForAbort(0.5)
def start_discovery(self, daemon=False):
if not self._discovery_is_running:

View file

@ -79,7 +79,6 @@ class Service():
utils.window('plex_kodiProfile',
value=utils.try_decode(xbmc.translatePath("special://profile")))
self.monitor = xbmc.Monitor()
# Load/Reset PKC entirely - important for user/Kodi profile switch
# Clear video nodes properties
from .library_sync import videonodes
@ -100,7 +99,7 @@ class Service():
i = 0
while app.SYNC.db_scan:
i += 1
xbmc.sleep(50)
app.APP.monitor.waitForAbort(0.05)
if i > 100:
LOG.error('Could not stop library sync, aborting log-out')
# Failed to reset PMS and plex.tv connects. Try to restart Kodi
@ -238,6 +237,7 @@ class Service():
# if profile switch happens more than once.
app.init()
# Some plumbing
app.APP.monitor = kodimonitor.KodiMonitor()
artwork.IMAGE_CACHING_SUSPENDS = [
app.SYNC.suspend_library_thread,
app.SYNC.stop_sync,
@ -325,7 +325,7 @@ class Service():
if utils.window('plex_online') == "true":
# Plex server is online
if app.CONN.pms_status == 'Stop':
xbmc.sleep(500)
app.APP.monitor.waitForAbort(0.05)
continue
elif app.CONN.pms_status == '401':
# Unauthorized access, revoke token
@ -352,7 +352,7 @@ class Service():
sound=False)
# Start monitoring kodi events
if not self.kodimonitor_running:
self.kodimonitor_running = kodimonitor.KodiMonitor()
self.kodimonitor_running = True
self.specialmonitor.start()
# Start the Websocket Client
if not self.ws_running:
@ -429,7 +429,7 @@ class Service():
# Hence resume threads
app.SYNC.suspend_library_thread = False
if self.monitor.waitForAbort(0.05):
if app.APP.monitor.waitForAbort(0.05):
# Abort was requested while waiting. We should exit
break
# Tell all threads to terminate (e.g. several lib sync threads)

View file

@ -231,7 +231,7 @@ class Sync(backgroundthread.KillableThread):
# Abort was requested while waiting. We should exit
LOG.info("###===--- Sync Thread Stopped ---===###")
return
xbmc.sleep(1000)
app.APP.monitor.waitForAbort(1)
if not install_sync_done:
# Very FIRST sync ever upon installation or reset of Kodi DB
@ -257,7 +257,7 @@ class Sync(backgroundthread.KillableThread):
self.start_image_cache_thread()
else:
LOG.error('Initial start-up full sync unsuccessful')
xbmc.sleep(1000)
app.APP.monitor.waitForAbort(1)
self.force_dialog = False
xbmc.executebuiltin('InhibitIdleShutdown(false)')
@ -279,7 +279,7 @@ class Sync(backgroundthread.KillableThread):
self.start_image_cache_thread()
else:
LOG.info('Startup sync has not yet been successful')
xbmc.sleep(1000)
app.APP.monitor.waitForAbort(1)
# Currently no db scan, so we could start a new scan
elif app.SYNC.db_scan is False:
@ -320,9 +320,9 @@ class Sync(backgroundthread.KillableThread):
library_sync.store_websocket_message(message)
queue.task_done()
# Sleep just a bit
xbmc.sleep(10)
app.APP.monitor.waitForAbort(0.01)
continue
xbmc.sleep(100)
app.APP.monitor.waitForAbort(0.1)
# Shut down playlist monitoring
if playlist_monitor:
playlist_monitor.stop()

View file

@ -43,12 +43,11 @@ import uuid
import hashlib
import base64
import threading
import time
import logging
import traceback
import sys
from . import utils
from . import utils, app
###############################################################################
@ -821,7 +820,7 @@ class WebSocketApp(object):
def _send_ping(self, interval):
while True:
for _ in range(interval):
time.sleep(1)
app.APP.monitor.waitForAbort(1)
if not self.keep_running:
return
self.sock.ping()

View file

@ -3,7 +3,6 @@
from logging import getLogger
from json import loads
from ssl import CERT_NONE
from xbmc import sleep
from . import backgroundthread, websocket, utils, companion, app, variables as v
@ -60,7 +59,7 @@ class WebSocket(backgroundthread.KillableThread):
LOG.info("##===---- %s Stopped ----===##",
self.__class__.__name__)
return
sleep(1000)
app.APP.monitor.waitForAbort(1)
try:
self.process(*self.receive(self.ws))
except websocket.WebSocketTimeoutException:
@ -86,12 +85,12 @@ class WebSocket(backgroundthread.KillableThread):
LOG.info('%s: Repeated IOError detected. Stopping now',
self.__class__.__name__)
break
sleep(1000)
app.APP.monitor.waitForAbort(1)
except websocket.WebSocketTimeoutException:
LOG.info("%s: Timeout while connecting, trying again",
self.__class__.__name__)
self.ws = None
sleep(1000)
app.APP.monitor.waitForAbort(1)
except websocket.WebSocketException as e:
LOG.info('%s: WebSocketException: %s',
self.__class__.__name__, e)
@ -103,7 +102,7 @@ class WebSocket(backgroundthread.KillableThread):
'Stopping now', self.__class__.__name__)
break
self.ws = None
sleep(1000)
app.APP.monitor.waitForAbort(1)
except Exception as e:
LOG.error('%s: Unknown exception encountered when '
'connecting: %s', self.__class__.__name__, e)
@ -111,7 +110,7 @@ class WebSocket(backgroundthread.KillableThread):
LOG.error("%s: Traceback:\n%s",
self.__class__.__name__, traceback.format_exc())
self.ws = None
sleep(1000)
app.APP.monitor.waitForAbort(1)
else:
counter = 0
except Exception as e:

View file

@ -7,6 +7,8 @@ import time
import threading
import traceback
from .. import app
MONITOR = None
@ -918,7 +920,7 @@ class PropertyTimer():
def _wait(self):
while not xbmc.abortRequested and time.time() < self._endTime:
xbmc.sleep(100)
app.APP.monitor.waitForAbort(0.1)
if xbmc.abortRequested:
return
if self._endTime == 0: