Remember sync position for manual triggers

Allow to resume sync on restart for manual user triggers (update, repair). Automatically refresh boxsets if movie library is selected.

use waitForAbort and emby_should_stop prop to terminate threads
This commit is contained in:
angelblue05 2018-09-22 02:52:14 -05:00
parent 00ee891952
commit 11f771ade2
9 changed files with 54 additions and 28 deletions

View file

@ -845,3 +845,7 @@ msgstr ""
msgctxt "#33172"
msgid "You have {number} updates pending. This may take a little while before seeing new content. It might be faster to update your libraries via launching the Emby add-on > update libraries. Proceed anyway?"
msgstr ""
msgctxt "#33173"
msgid "Forget about the previous sync?"
msgstr ""

View file

@ -262,7 +262,7 @@ class GetItemWorker(threading.Thread):
self.queue.task_done()
if xbmc.Monitor().abortRequested():
if window('emby_should_stop.bool'):
break
class TheVoid(object):
@ -282,10 +282,12 @@ class TheVoid(object):
event(method, data)
self.method = method
self.data = data
self.monitor = xbmc.Monitor()
def get(self):
while True:
response = window('emby_%s.json' % self.data['VoidName'])
if response != "":
@ -295,7 +297,7 @@ class TheVoid(object):
return response
if window('emby_should_stop.bool'):
if window('emby_should_stop.bool') or self.monitor.waitForAbort(0.2):
LOG.info("Abandon mission! A black hole just swallowed [ %s ]", self.data['VoidName'])
break
@ -306,7 +308,7 @@ def get_objects(src, filename):
'''
temp = xbmc.translatePath('special://temp/emby').decode('utf-8')
restart = not xbmcvfs.exists(os.path.join(temp, "objects") + '/')
path = os.path.join(temp, filename).decode('utf-8')
path = os.path.join(temp, filename).encode('utf-8')
if not xbmcvfs.exists(path):
delete_folder()

View file

@ -46,7 +46,7 @@ class HTTP(object):
return
try:
LOG.warn("Closing session %s", id(self.session))
LOG.warn("--<[ session/%s ]", id(self.session))
self.session.close()
except Exception as error:
LOG.warn("The requests session could not be terminated: %s", error)

View file

@ -7,6 +7,8 @@ import logging
import threading
import time
import xbmc
from ..resources import websocket
##################################################################################################
@ -46,6 +48,7 @@ class WSClient(threading.Thread):
def run(self):
monitor = xbmc.Monitor()
token = self.client['config/auth.token']
device_id = self.client['config/app.device_id']
server = self.client['config/auth.server']
@ -63,8 +66,8 @@ class WSClient(threading.Thread):
self.wsc.run_forever(ping_interval=10)
if not self.stop:
time.sleep(5)
if not self.stop and monitor.waitForAbort(5):
break
LOG.info("---<[ websocket ]")

View file

@ -42,6 +42,8 @@ class Service(xbmc.Monitor):
def __init__(self):
window('emby_should_stop', clear=True)
self.settings['addon_version'] = client.get_version()
self.settings['profile'] = xbmc.translatePath('special://profile')
self.settings['mode'] = settings('useDirectPaths')
@ -194,7 +196,7 @@ class Service(xbmc.Monitor):
data = json.loads(data)
LOG.debug("[ %s: %s ] %s", sender, method, json.dumps(data, indent=4))
LOG.info("[ %s: %s ] %s", sender, method, json.dumps(data, indent=4))
if method == 'ServerOnline':
if data['ServerId'] is None:
@ -410,7 +412,7 @@ class Service(xbmc.Monitor):
"emby_currUser", "emby_dbScan",
"emby_initialScan",
"emby_play", "emby_online", "emby.connected", "emby_should_stop", "emby.resume",
"emby_play", "emby_online", "emby.connected", "emby.resume",
"emby.external", "emby.external_check", "emby_deviceId", "emby_db_check", "emby_pathverified"
]
for prop in properties:

View file

@ -40,19 +40,24 @@ class FullSync(object):
libraries = library_id.split(',')
for selected in libraries:
if selected not in [x.replace('Mixed:', "") for x in self.sync['Libraries']]:
library = self.get_libraries(selected)
if library and library[1] == 'mixed':
selected = "Mixed:%s" % selected
if library:
self.sync['Libraries'].append(selected)
self.sync['Libraries'].append("Mixed:%s" % selected if library[1] == 'mixed' else selected)
if library[1] in ('mixed', 'movies'):
self.sync['Libraries'].append('Boxsets:%s' % selected)
else:
self.sync['Libraries'].append(selected)
else:
self.mapping()
xmls.sources()
if not xmls.advanced_settings():
if not xmls.advanced_settings() and self.sync['Libraries']:
self.start()
def get_libraries(self, library_id=None):
@ -71,10 +76,14 @@ class FullSync(object):
if self.sync['Libraries']:
if not dialog("yesno", heading="{emby}", line1=_(33102)):
dialog("ok", heading="{emby}", line1=_(33122))
raise LibraryException("ProgressStopped")
if not dialog("yesno", heading="{emby}", line1=_(33173)):
dialog("ok", heading="{emby}", line1=_(33122))
raise LibraryException("ProgressStopped")
else:
self.sync['Libraries'] = []
self.sync['RestorePoint'] = {}
else:
LOG.info("generate full sync")
libraries = []
@ -89,7 +98,7 @@ class FullSync(object):
if [x['Media'] for x in libraries if x['Media'] in ('movies', 'mixed')]:
self.sync['Libraries'].append("Boxsets:")
save_sync(self.sync)
save_sync(self.sync)
def select_libraries(self, libraries):
@ -168,7 +177,7 @@ class FullSync(object):
if library_id.endswith('Refresh'):
self.refresh_boxsets()
else:
self.boxsets()
self.boxsets(library_id.split('Boxsets:')[1] if len(library_id) > len('Boxsets:') else None)
return
@ -197,8 +206,8 @@ class FullSync(object):
dialog("ok", heading="{emby}", line1=_(33119))
LOG.error("full sync exited unexpectedly")
save_sync(self.sync)
else:
save_sync(self.sync)
raise
@ -306,7 +315,7 @@ class FullSync(object):
obj.song(song)
@progress(_(33018))
def boxsets(self, dialog):
def boxsets(self, library_id=None, dialog=None):
''' Process all boxsets.
'''
@ -314,7 +323,7 @@ class FullSync(object):
with Database('emby') as embydb:
obj = Movies(self.server, embydb, videodb, self.direct_path)
for items in server.get_items(None, "BoxSet", False, self.sync['RestorePoint'].get('params')):
for items in server.get_items(library_id, "BoxSet", False, self.sync['RestorePoint'].get('params')):
self.sync['RestorePoint'] = items['RestorePoint']
start_index = items['RestorePoint']['params']['StartIndex']
@ -336,4 +345,4 @@ class FullSync(object):
obj = Movies(self.server, embydb, videodb, self.direct_path)
obj.boxsets_reset()
self.boxsets()
self.boxsets(None)

View file

@ -160,7 +160,7 @@ def should_stop():
''' Checkpoint during the sync process.
'''
if xbmc.Monitor().abortRequested():
if xbmc.Monitor().waitForAbort(0.00001):
return True
if window('emby_should_stop.bool'):

View file

@ -15,7 +15,7 @@ from database import Database, emby_db, get_sync, save_sync
from full_sync import FullSync
from views import Views
from downloader import GetItemWorker
from helper import _, stop, settings, dialog, event, progress, LibraryException
from helper import _, stop, settings, window, dialog, event, progress, LibraryException
from emby import Emby
##################################################################################################
@ -210,7 +210,13 @@ class Library(threading.Thread):
else:
raise LibraryException('CompanionMissing')
if get_sync()['Libraries']:
FullSync(self)
Views().get_nodes()
if settings('SyncInstallRunDone.bool'):
if fast_sync and not self.fast_sync():
dialog("ok", heading="{emby}", line1=_(33128))
@ -537,7 +543,7 @@ class UpdatedWorker(threading.Thread):
except Exception as error:
LOG.exception(error)
if xbmc.Monitor().abortRequested():
if window('emby_should_stop.bool'):
break
class UserDataWorker(threading.Thread):
@ -580,7 +586,7 @@ class UserDataWorker(threading.Thread):
except Exception as error:
LOG.exception(error)
if xbmc.Monitor().abortRequested():
if window('emby_should_stop.bool'):
break
class SortWorker(threading.Thread):
@ -624,7 +630,7 @@ class SortWorker(threading.Thread):
self.queue.task_done()
if xbmc.Monitor().abortRequested():
if window('emby_should_stop.bool'):
break
class RemovedWorker(threading.Thread):
@ -667,7 +673,7 @@ class RemovedWorker(threading.Thread):
except Exception as error:
LOG.exception(error)
if xbmc.Monitor().abortRequested():
if window('emby_should_stop.bool'):
break
class NotifyWorker(threading.Thread):

View file

@ -414,7 +414,7 @@ class Views(object):
rule = etree.SubElement(xml, 'rule', {'field': "tag", 'operator': "is"})
etree.SubElement(rule, 'value').text = view['Tag']
getattr(self, 'node_' + node)(xml)
getattr(self, 'node_' + node)(xml) # get node function based on node type
indent(xml)
write_xml(etree.tostring(xml, 'UTF-8'), file)