Rewire PKC startup and authentication mechanism

This commit is contained in:
croneter 2018-11-25 17:03:19 +01:00
parent 6d450b2be9
commit 6dc436da91
18 changed files with 243 additions and 232 deletions

View file

@ -101,17 +101,12 @@ class Main():
entrypoint.switch_plex_user()
elif mode in ('manualsync', 'repair'):
if pickler.pickl_window('plex_online') != 'true':
# Server is not online, do not run the sync
utils.messageDialog(utils.lang(29999), utils.lang(39205))
log.error('Not connected to a PMS.')
else:
if mode == 'repair':
log.info('Requesting repair lib sync')
utils.plex_command('repair-scan')
elif mode == 'manualsync':
log.info('Requesting full library scan')
utils.plex_command('full-scan')
if mode == 'repair':
log.info('Requesting repair lib sync')
utils.plex_command('repair-scan')
elif mode == 'manualsync':
log.info('Requesting full library scan')
utils.plex_command('full-scan')
elif mode == 'texturecache':
log.info('Requesting texture caching of all textures')

View file

@ -619,7 +619,7 @@ msgid "Invalid username or password"
msgstr ""
msgctxt "#33010"
msgid "Your Plex token is no longer valid. Logging-out of plex.tv"
msgid "User is unauthorized for server {0}"
msgstr ""
msgctxt "#33011"

View file

@ -30,6 +30,9 @@ class Account(object):
def load(self):
LOG.debug('Loading account settings')
# User name we used to sign in to plex.tv
self.plex_login = utils.settings('plexLogin') or None
self.plex_login_id = utils.settings('plexid') or None
# plex.tv username
self.plex_username = utils.settings('username') or None
# Plex ID of that user (e.g. for plex.tv) as a STRING
@ -62,13 +65,17 @@ class Account(object):
LOG.debug('User is restricted Home user: %s', self.restricted_user)
def log_out(self):
LOG.debug('Logging-out user')
LOG.debug('Logging-out user %s', self.plex_username)
self.plex_username = None
self.plex_user_id = None
self.pms_token = None
self.avatar = None
self.restricted_user = None
self.authenticated = False
try:
self._session.close()
except AttributeError:
pass
self._session = None
utils.settings('username', value='')
@ -91,6 +98,12 @@ class Account(object):
self.avatar = None
self.restricted_user = None
self.authenticated = False
self.plex_login = None
self.plex_login_id = None
try:
self._session.close()
except AttributeError:
pass
self._session = None
utils.settings('username', value='')
@ -99,6 +112,8 @@ class Account(object):
utils.settings('plexToken', value='')
utils.settings('accessToken', value='')
utils.settings('plexAvatar', value='')
utils.settings('plexLogin', value='')
utils.settings('plexid', value='')
utils.window('plex_restricteduser', clear=True)
utils.window('plex_token', clear=True)

View file

@ -17,7 +17,10 @@ class App(object):
return
# Quit PKC?
self.stop_pkc = False
# Shall we completely suspend PKC and our threads?
self.suspend = False
# Shall we only suspend threads?
self._suspend_threads = False
# Need to lock all methods and functions messing with Plex Companion subscribers
self.lock_subscriber = RLock()
# Need to lock everything messing with Kodi/PKC playqueues
@ -43,3 +46,11 @@ class App(object):
# Hack to force Kodi widget for "in progress" to show up if it was empty
# before
self.force_reload_skin = utils.settings('forceReloadSkinOnPlaybackStop') == 'true'
@property
def suspend_threads(self):
return self._suspend_threads or self.suspend
@suspend_threads.setter
def suspend_threads(self, value):
self._suspend_threads = value

View file

@ -16,12 +16,6 @@ class Connection(object):
return
# TODO: Delete
self.pms_server = None
# Plex Media Server Status - along with window('plex_serverStatus')
# Values:
# 'Stop': set if e.g.
# '401': Token has been revoked - PKC yet to delete tokens
# 'Auth':
self.pms_status = False
# Token passed along, e.g. if playback initiated by Plex Companion. Might be
# another user playing something! Token identifies user
self.plex_transient_token = None
@ -61,6 +55,7 @@ class Connection(object):
else:
self.server = 'http://%s:%s' % (self.host, self.port)
utils.window('pms_server', value=self.server)
self.online = False
LOG.debug('Set server %s (%s) to %s',
self.server_name, self.machine_identifier, self.server)

View file

@ -12,9 +12,6 @@ class Sync(object):
return
# Do we need to run a special library scan?
self.run_lib_scan = None
# Usually triggered by another Python instance - will have to be set (by
# polling window) through e.g. librarysync thread
self.suspend_library_thread = False
# Set if user decided to cancel sync
self.stop_sync = False
# Set during media playback if PKC should not do any syncs. Will NOT

View file

@ -160,15 +160,18 @@ class Task(object):
return not self.finished and not self._canceled
def FunctionAsTask(Task):
def __init__(self, function, *args, **kwargs):
self.function = function
class FunctionAsTask(Task):
def __init__(self, function, callback, *args, **kwargs):
self._function = function
self._callback = callback
self._args = args
self._kwargs = kwargs
super(FunctionAsTask, self).__init__()
def run(self):
self.function(*self._args, **self._kwargs)
result = self._function(*self._args, **self._kwargs)
if self._callback:
self._callback(result)
class MutablePriorityQueue(Queue.PriorityQueue):

View file

@ -28,9 +28,11 @@ class DownloadUtils():
_shared_state = {}
# How many failed attempts before declaring PMS dead?
connectionAttempts = 1
connection_attempts = 1
count_error = 0
# How many 401 returns before declaring unauthorized?
unauthorizedAttempts = 2
unauthorized_attempts = 2
count_unauthorized = 0
# How long should we wait for an answer from the
timeout = 30.0
@ -69,11 +71,9 @@ class DownloadUtils():
self.setSSL()
# Counters to declare PMS dead or unauthorized
# Use window variables because start of movies will be called with a
# new plugin instance - it's impossible to share data otherwise
if reset is True:
utils.window('countUnauthorized', value='0')
utils.window('countError', value='0')
self.count_error = 0
self.count_unauthorized = 0
# Retry connections to the server
self.s.mount("http://", requests.adapters.HTTPAdapter(max_retries=1))
@ -210,9 +210,9 @@ class DownloadUtils():
else:
# We COULD contact the PMS, hence it ain't dead
if authenticate is True:
utils.window('countError', value='0')
self.count_error = 0
if r.status_code != 401:
utils.window('countUnauthorized', value='0')
self.count_unauthorized = 0
if r.status_code == 204:
# No body in the response
@ -230,22 +230,16 @@ class DownloadUtils():
LOG.info(r.text)
if '401 Unauthorized' in r.text:
# Truly unauthorized
utils.window(
'countUnauthorized',
value=str(int(utils.window('countUnauthorized')) + 1))
if (int(utils.window('countUnauthorized')) >=
self.unauthorizedAttempts):
self.count_unauthorized += 1
if self.count_unauthorized >= self.unauthorized_attempts:
LOG.warn('We seem to be truly unauthorized for PMS'
' %s ', url)
if app.CONN.pms_status not in ('401', 'Auth'):
# Tell others token has been revoked.
LOG.debug('Setting PMS server status to '
'unauthorized')
app.CONN.pms_status = '401'
utils.dialog('notification',
utils.lang(29999),
utils.lang(30017),
icon='{error}')
# Unauthorized access, user no longer has access
app.ACCOUNT.log_out()
utils.dialog('notification',
utils.lang(29999),
utils.lang(30017),
icon='{error}')
else:
# there might be other 401 where e.g. PMS under strain
LOG.info('PMS might only be under strain')
@ -284,7 +278,7 @@ class DownloadUtils():
elif r.status_code == 403:
# E.g. deleting a PMS item
LOG.warn('PMS sent 403: Forbidden error for url %s', url)
return None
return
else:
r.encoding = 'utf-8'
LOG.warn('Unknown answer from PMS %s with status code %s. ',
@ -294,14 +288,9 @@ class DownloadUtils():
# And now deal with the consequences of the exceptions
if authenticate is True:
# Make the addon aware of status
try:
utils.window('countError',
value=str(int(utils.window('countError')) + 1))
if int(utils.window('countError')) >= self.connectionAttempts:
LOG.warn('Failed to connect to %s too many times. '
'Declare PMS dead', url)
utils.window('plex_online', value="false")
except ValueError:
# 'countError' not yet set
pass
return None
self.count_error += 1
if self.count_error >= self.connection_attempts:
LOG.warn('Failed to connect to %s too many times. '
'Declare PMS dead', url)
app.CONN.online = False
return

View file

@ -54,8 +54,8 @@ class InitialSetup(object):
# Get Plex credentials from settings file, if they exist
plexdict = PF.GetPlexLoginFromSettings()
self.plex_login = plexdict['plexLogin']
self.plex_login_id = plexdict['plexid']
self.plex_token = plexdict['plexToken']
self.plexid = plexdict['plexid']
# Token for the PMS, not plex.tv
self.pms_token = utils.settings('accessToken')
if self.plex_token:
@ -66,7 +66,7 @@ class InitialSetup(object):
Writes Plex username, token to plex.tv and Plex id to PKC settings
"""
utils.settings('username', value=self.plex_login or '')
utils.settings('userid', value=self.plexid or '')
utils.settings('userid', value=self.plex_login_id or '')
utils.settings('plexToken', value=self.plex_token or '')
def enter_new_pms_address(self):
@ -117,14 +117,11 @@ class InitialSetup(object):
Returns True if successful, or False if not
"""
try:
user = plex_tv.sign_in_with_pin()
except:
utils.ERROR()
user = plex_tv.sign_in_with_pin()
if user:
self.plex_login = user.username
self.plex_token = user.authToken
self.plexid = user.id
self.plex_login_id = user.id
return True
return False
@ -600,7 +597,7 @@ class InitialSetup(object):
goto_settings = utils.yesno_dialog(utils.lang(29999),
utils.lang(39017))
if goto_settings:
state.PMS_STATUS = 'Stop'
app.APP.suspend = True
executebuiltin(
'Addon.OpenSettings(plugin.video.plexkodiconnect)')
elif reboot is True:

View file

@ -54,6 +54,8 @@ class KodiMonitor(xbmc.Monitor):
Monitor the PKC settings for changes made by the user
"""
LOG.debug('PKC settings change detected')
# Assume that the user changed something so we can try to reconnect
app.APP.suspend = False
def onNotification(self, sender, method, data):
"""
@ -129,11 +131,10 @@ class KodiMonitor(xbmc.Monitor):
elif method == "System.OnSleep":
# Connection is going to sleep
LOG.info("Marking the server as offline. SystemOnSleep activated.")
utils.window('plex_online', value="sleep")
elif method == "System.OnWake":
# Allow network to wake up
self.waitForAbort(10)
utils.window('plex_online', value="false")
app.CONN.online = False
elif method == "GUI.OnScreensaverDeactivated":
if utils.settings('dbSyncScreensaver') == "true":
self.waitForAbort(5)
@ -511,7 +512,7 @@ def _record_playstate(status, ended):
xbmc.getCondVisibility('Window.IsVisible(Home.xml)')):
LOG.debug('Refreshing skin to update widgets')
xbmc.executebuiltin('ReloadSkin()')
task = backgroundthread.FunctionAsTask(_clean_file_table)
task = backgroundthread.FunctionAsTask(function=_clean_file_table)
backgroundthread.BGThreader.addTasksToFront(task)

View file

@ -9,7 +9,7 @@ from .. import app
class libsync_mixin(object):
def isCanceled(self):
return (self._canceled or app.APP.stop_pkc or app.SYNC.stop_sync or
app.SYNC.suspend_library_thread or app.SYNC.suspend_sync)
app.APP.suspend_threads or app.SYNC.suspend_sync)
def update_kodi_library(video=True, music=True):

View file

@ -18,7 +18,7 @@ PREFER_KODI_COLLECTION_ART = utils.settings('PreferKodiCollectionArt') == 'false
def suspends():
return (app.SYNC.suspend_library_thread or
return (app.APP.suspend_threads or
app.SYNC.stop_sync or
app.SYNC.db_scan or
app.SYNC.suspend_sync)

View file

@ -22,7 +22,7 @@ PLAYSTATE_SESSIONS = {}
def interrupt_processing():
return app.APP.stop_pkc or app.SYNC.suspend_library_thread or app.SYNC.stop_sync
return app.APP.stop_pkc or app.APP.suspend_threads or app.SYNC.stop_sync
def multi_delete(input_list, delete_list):

View file

@ -101,7 +101,7 @@ class PlayqueueMonitor(backgroundthread.KillableThread):
"""
Returns True if the thread is suspended
"""
return self._suspended or app.CONN.pms_status
return self._suspended or app.APP.suspend_threads
def _compare_playqueues(self, playqueue, new):
"""

View file

@ -84,7 +84,7 @@ class PlexCompanion(backgroundthread.KillableThread):
"""
Returns True if the thread is suspended
"""
return self._suspended or app.CONN.pms_status
return self._suspended or app.APP.suspend
def _process_alexa(self, data):
xml = PF.GetPlexMetadata(data['key'])

View file

@ -17,6 +17,7 @@ from . import playqueue
from . import variables as v
from . import app
from . import loghandler
from . import backgroundthread
from .windows import userselect
###############################################################################
@ -25,11 +26,11 @@ LOG = logging.getLogger("PLEX.service")
###############################################################################
WINDOW_PROPERTIES = (
"plex_online", "plex_command_processed", "plex_shouldStop", "plex_dbScan",
"plex_command_processed", "plex_shouldStop", "plex_dbScan",
"plex_customplayqueue", "plex_playbackProps",
"pms_token", "plex_token", "pms_server", "plex_machineIdentifier",
"plex_servername", "plex_authenticated", "PlexUserImage", "useDirectPaths",
"countError", "countUnauthorized", "plex_restricteduser",
"plex_restricteduser",
"plex_allows_mediaDeletion", "plex_command", "plex_result",
"plex_force_transcode_pix"
)
@ -40,13 +41,6 @@ class Service():
sync = None
plexcompanion = None
ws_running = False
alexa_running = False
sync_running = False
plexcompanion_running = False
kodimonitor_running = False
playback_starter_running = False
def __init__(self):
# Initial logging
LOG.info("======== START %s ========", v.ADDON_NAME)
@ -87,15 +81,71 @@ class Service():
# Init time-offset between Kodi and Plex
timing.KODI_PLEX_TIME_OFFSET = float(utils.settings('kodiplextimeoffset') or 0.0)
def isCanceled(self):
return xbmc.abortRequested
self.startup_completed = False
self.server_has_been_online = True
self.welcome_msg = True
self.connection_check_counter = 0
# Flags for other threads
self.connection_check_running = False
self.auth_running = False
def on_connection_check(self, result):
"""
Call this method after PF.check_connection()
"""
try:
if result is False:
# Server is offline or cannot be reached
# Alert the user and suppress future warning
if app.CONN.online:
# PMS was online before
app.CONN.online = False
app.APP.suspend_threads = True
LOG.warn("Plex Media Server went offline")
if utils.settings('show_pms_offline') == 'true':
utils.dialog('notification',
utils.lang(33001),
"%s %s" % (utils.lang(29999),
utils.lang(33002)),
icon='{plex}',
sound=False)
self.connection_check_counter += 1
# Periodically check if the IP changed every 15 seconds
if self.connection_check_counter > 150:
self.connection_check_counter = 0
server = self.setup.pick_pms()
if server:
self.setup.write_pms_to_settings(server)
app.CONN.load()
else:
# Server is online
self.connection_check_counter = 0
if not app.CONN.online:
# Server was offline before
if (self.welcome_msg is False and
utils.settings('show_pms_offline') == 'true'):
# Alert the user that server is online
utils.dialog('notification',
utils.lang(29999),
utils.lang(33003),
icon='{plex}',
time=5000,
sound=False)
LOG.info("Server is online and ready")
if app.ACCOUNT.authenticated:
# Server got offline when we were authenticated.
# Hence resume threads
app.APP.suspend_threads = False
app.CONN.online = True
finally:
self.connection_check_running = False
def log_out(self):
"""
Ensures that lib sync threads are suspended; signs out user
"""
LOG.info('Log-out requested')
app.SYNC.suspend_library_thread = True
app.APP.suspend_threads = True
i = 0
while app.SYNC.db_scan:
i += 1
@ -105,7 +155,7 @@ class Service():
# Failed to reset PMS and plex.tv connects. Try to restart Kodi
utils.messageDialog(utils.lang(29999), utils.lang(39208))
# Resuming threads, just in case
app.SYNC.suspend_library_thread = False
app.APP.suspend_threads = False
return False
LOG.info('Successfully stopped library sync')
app.ACCOUNT.log_out()
@ -132,6 +182,9 @@ class Service():
# Wipe Kodi and Plex database as well as playlists and video nodes
utils.wipe_database()
app.CONN.load()
app.ACCOUNT.set_unauthenticated()
self.server_has_been_online = False
self.welcome_msg = False
LOG.info("Choosing new PMS complete")
return True
@ -142,16 +195,19 @@ class Service():
utils.delete_playlists()
# Remove video nodes
utils.delete_nodes()
app.ACCOUNT.set_unauthenticated()
return True
def toggle_plex_tv(self):
if utils.settings('plexToken'):
LOG.info('Reseting plex.tv credentials in settings')
if app.ACCOUNT.plex_token:
LOG.info('Resetting plex.tv credentials in settings')
self.log_out()
app.ACCOUNT.clear()
return True
else:
LOG.info('Login to plex.tv')
return self.setup.plex_tv_sign_in()
if self.setup.plex_tv_sign_in():
self.setup.write_credentials_to_settings()
app.ACCOUNT.load()
def authenticate(self):
"""
@ -160,9 +216,30 @@ class Service():
Returns True if successful, False if not. 'aborted' if user chose to
abort
"""
if self._do_auth():
if self.welcome_msg is True:
# Reset authentication warnings
self.welcome_msg = False
utils.dialog('notification',
utils.lang(29999),
"%s %s" % (utils.lang(33000),
app.ACCOUNT.plex_username),
icon='{plex}',
time=2000,
sound=False)
app.APP.suspend_threads = False
self.auth_running = False
def enter_new_pms_address(self):
if self.setup.enter_new_pms_address():
app.CONN.load()
app.ACCOUNT.set_unauthenticated()
self.server_has_been_online = False
self.welcome_msg = False
def _do_auth(self):
LOG.info('Authenticating user')
if app.ACCOUNT.plex_username and not app.ACCOUNT.force_login:
# Found a user in the settings, try to authenticate
if app.ACCOUNT.plex_username and not app.ACCOUNT.force_login: # Found a user in the settings, try to authenticate
LOG.info('Trying to authenticate with old settings')
res = PF.check_connection(app.CONN.server,
token=app.ACCOUNT.pms_token,
@ -171,8 +248,9 @@ class Service():
LOG.error('Something went wrong while checking connection')
return False
elif res == 401:
LOG.error('User token no longer valid. Sign user out')
app.ACCOUNT.clear()
LOG.error('User %s no longer has access - signing user out',
app.ACCOUNT.plex_username)
self.log_out()
return False
elif res >= 400:
LOG.error('Answer from PMS is not as expected')
@ -188,7 +266,7 @@ class Service():
user, _ = userselect.start()
if not user:
LOG.info('No user received')
app.CONN.pms_status = 'Stop'
app.APP.suspend = True
return False
username = user.title
user_id = user.id
@ -206,10 +284,12 @@ class Service():
return False
elif res == 401:
if app.ACCOUNT.plex_token:
LOG.error('Token no longer valid')
# "Your Plex token is no longer valid. Logging-out of plex.tv"
utils.messageDialog(utils.lang(29999), utils.lang(33010))
app.ACCOUNT.clear()
LOG.error('User %s does not have access to PMS %s on %s',
username, app.CONN.server_name, app.CONN.server)
# "User is unauthorized for server {0}"
utils.messageDialog(utils.lang(29999),
utils.lang(33010).format(app.CONN.server_name))
self.log_out()
return False
else:
# "Failed to authenticate. Did you login to plex.tv?"
@ -219,6 +299,7 @@ class Service():
app.ACCOUNT.load()
continue
else:
app.APP.suspend = True
return False
elif res >= 400:
LOG.error('Answer from PMS is not as expected')
@ -235,12 +316,12 @@ class Service():
def ServiceEntryPoint(self):
# Important: Threads depending on abortRequest will not trigger
# if profile switch happens more than once.
app.init()
# Some plumbing
app.init()
app.APP.monitor = kodimonitor.KodiMonitor()
app.APP.player = xbmc.Player()
artwork.IMAGE_CACHING_SUSPENDS = [
app.SYNC.suspend_library_thread,
app.APP.suspend_threads,
app.SYNC.stop_sync,
app.SYNC.db_scan
]
@ -262,11 +343,9 @@ class Service():
self.playback_starter = playback_starter.PlaybackStarter()
self.playqueue = playqueue.PlayqueueMonitor()
server_online = True
welcome_msg = True
counter = 0
while not self.isCanceled():
# Main PKC program loop
while not xbmc.abortRequested:
# Check for Kodi profile change
if utils.window('plex_kodiProfile') != v.KODI_PROFILE:
# Profile change happened, terminate this thread and others
LOG.info("Kodi profile was: %s and changed to: %s. "
@ -274,6 +353,7 @@ class Service():
v.KODI_PROFILE, utils.window('plex_kodiProfile'))
break
# Check for PKC commands from other Python instances
plex_command = utils.window('plex_command')
if plex_command:
# Commands/user interaction received from other PKC Python
@ -291,24 +371,21 @@ class Service():
'dummy?mode=context_menu&%s'
% plex_command.replace('CONTEXT_menu?', ''))
elif plex_command == 'choose_pms_server':
if self.choose_pms_server():
utils.window('plex_online', clear=True)
app.ACCOUNT.set_unauthenticated()
server_online = False
welcome_msg = False
task = backgroundthread.FunctionAsTask(
self.choose_pms_server, None)
backgroundthread.BGThreader.addTasksToFront([task])
elif plex_command == 'switch_plex_user':
if self.switch_plex_user():
app.ACCOUNT.set_unauthenticated()
task = backgroundthread.FunctionAsTask(
self.switch_plex_user, None)
backgroundthread.BGThreader.addTasksToFront([task])
elif plex_command == 'enter_new_pms_address':
if self.setup.enter_new_pms_address():
if self.log_out():
utils.window('plex_online', clear=True)
app.ACCOUNT.set_unauthenticated()
server_online = False
welcome_msg = False
task = backgroundthread.FunctionAsTask(
self.enter_new_pms_address, None)
backgroundthread.BGThreader.addTasksToFront([task])
elif plex_command == 'toggle_plex_tv_sign_in':
if self.toggle_plex_tv():
app.ACCOUNT.set_unauthenticated()
task = backgroundthread.FunctionAsTask(
self.toggle_plex_tv, None)
backgroundthread.BGThreader.addTasksToFront([task])
elif plex_command == 'repair-scan':
app.SYNC.run_lib_scan = 'repair'
elif plex_command == 'full-scan':
@ -319,120 +396,51 @@ class Service():
app.SYNC.run_lib_scan = 'textures'
continue
if app.APP.suspend:
app.APP.monitor.waitForAbort(0.1)
continue
# Before proceeding, need to make sure:
# 1. Server is online
# 2. User is set
# 3. User has access to the server
if utils.window('plex_online') == "true":
# Plex server is online
if app.CONN.pms_status == 'Stop':
app.APP.monitor.waitForAbort(0.05)
continue
elif app.CONN.pms_status == '401':
# Unauthorized access, revoke token
LOG.info('401 received - revoking token')
app.ACCOUNT.clear()
app.CONN.pms_status = 'Auth'
utils.window('plex_serverStatus', value='Auth')
continue
if not app.ACCOUNT.authenticated:
LOG.info('Not yet authenticated')
# Do authentication
if not self.authenticate():
continue
# Start up events
if welcome_msg is True:
# Reset authentication warnings
welcome_msg = False
utils.dialog('notification',
utils.lang(29999),
"%s %s" % (utils.lang(33000),
app.ACCOUNT.plex_username),
icon='{plex}',
time=2000,
sound=False)
# Start monitoring kodi events
if not self.kodimonitor_running:
self.kodimonitor_running = True
self.specialmonitor.start()
# Start the Websocket Client
if not self.ws_running:
self.ws_running = True
self.ws.start()
# Start the Alexa thread
if (not self.alexa_running and
utils.settings('enable_alexa') == 'true'):
self.alexa_running = True
self.alexa.start()
# Start the syncing thread
if not self.sync_running:
self.sync_running = True
self.sync.start()
# Start the Plex Companion thread
if not self.plexcompanion_running:
self.plexcompanion_running = True
self.plexcompanion.start()
if not self.playback_starter_running:
self.playback_starter_running = True
self.playback_starter.start()
self.playqueue.start()
else:
# Wait until Plex server is online
# or Kodi is shut down.
if not app.CONN.online:
# Not online
server = app.CONN.server
if not server:
# No server info set in add-on settings
pass
elif PF.check_connection(server, verifySSL=True) is False:
# Server is offline or cannot be reached
# Alert the user and suppress future warning
if server_online:
server_online = False
utils.window('plex_online', value="false")
# Suspend threads
app.SYNC.suspend_library_thread = True
LOG.warn("Plex Media Server went offline")
if utils.settings('show_pms_offline') == 'true':
utils.dialog('notification',
utils.lang(33001),
"%s %s" % (utils.lang(29999),
utils.lang(33002)),
icon='{plex}',
sound=False)
counter += 1
# Periodically check if the IP changed, e.g. per minute
if counter > 20:
counter = 0
setup = initialsetup.InitialSetup()
tmp = setup.pick_pms()
if tmp:
setup.write_pms_to_settings(tmp)
app.CONN.load()
else:
# Server is online
counter = 0
if not server_online:
# Server was offline when Kodi started.
server_online = True
# Alert the user that server is online.
if (welcome_msg is False and
utils.settings('show_pms_offline') == 'true'):
utils.dialog('notification',
utils.lang(29999),
utils.lang(33003),
icon='{plex}',
time=5000,
sound=False)
LOG.info("Server %s is online and ready.", server)
utils.window('plex_online', value="true")
if app.ACCOUNT.authenticated:
# Server got offline when we were authenticated.
# Hence resume threads
app.SYNC.suspend_library_thread = False
elif not self.connection_check_running:
self.connection_check_running = True
task = backgroundthread.FunctionAsTask(
PF.check_connection,
self.on_connection_check,
server,
verifySSL=True)
backgroundthread.BGThreader.addTasksToFront([task])
continue
elif not app.ACCOUNT.authenticated:
# Plex server is online, but we're not yet authenticated
if not self.auth_running:
self.auth_running = True
task = backgroundthread.FunctionAsTask(
self.authenticate, None)
backgroundthread.BGThreader.addTasksToFront([task])
continue
elif not self.startup_completed:
self.startup_completed = True
self.specialmonitor.start()
self.ws.start()
self.sync.start()
self.plexcompanion.start()
self.playback_starter.start()
self.playqueue.start()
if utils.settings('enable_alexa') == 'true':
self.alexa.start()
if app.APP.monitor.waitForAbort(0.05):
# Abort was requested while waiting. We should exit
break
app.APP.monitor.waitForAbort(0.1)
# EXITING PKC
# Tell all threads to terminate (e.g. several lib sync threads)
app.APP.stop_pkc = True
utils.window('plex_service_started', clear=True)

View file

@ -41,7 +41,7 @@ class Sync(backgroundthread.KillableThread):
super(Sync, self).__init__()
def isSuspended(self):
return self._suspended or app.SYNC.suspend_library_thread
return self._suspended or app.APP.suspend_threads
def show_kodi_note(self, message, icon="plex", force=False):
"""

View file

@ -137,7 +137,7 @@ class PMS_Websocket(WebSocket):
Returns True if the thread is suspended
"""
return (self._suspended or
app.SYNC.suspend_library_thread or
app.APP.suspend_threads or
app.SYNC.background_sync_disabled)
def getUri(self):