mirror of
https://github.com/jellyfin/jellyfin-kodi.git
synced 2024-12-25 02:06:09 +00:00
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:
parent
00ee891952
commit
11f771ade2
9 changed files with 54 additions and 28 deletions
|
@ -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 ""
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 ]")
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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'):
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
Loading…
Reference in a new issue