Rework full sync into a context

This commit is contained in:
angelblue05 2019-01-25 09:30:30 -06:00
parent f9db3c6134
commit 7e7cf1489d
4 changed files with 161 additions and 109 deletions

View file

@ -21,7 +21,6 @@ from database import reset, get_sync, Database, emby_db, get_credentials
from objects import Objects, Actions from objects import Objects, Actions
from downloader import TheVoid from downloader import TheVoid
from helper import _, event, settings, window, dialog, api, JSONRPC from helper import _, event, settings, window, dialog, api, JSONRPC
from emby import Emby
################################################################################################# #################################################################################################

View file

@ -361,7 +361,9 @@ class Service(xbmc.Monitor):
libraries = data['Id'].split(',') libraries = data['Id'].split(',')
for lib in libraries: for lib in libraries:
self.library_thread.remove_library(lib)
if not self.library_thread.remove_library(lib):
return
self.library_thread.add_library(data['Id']) self.library_thread.add_library(data['Id'])
xbmc.executebuiltin("Container.Refresh") xbmc.executebuiltin("Container.Refresh")
@ -370,7 +372,9 @@ class Service(xbmc.Monitor):
libraries = data['Id'].split(',') libraries = data['Id'].split(',')
for lib in libraries: for lib in libraries:
self.library_thread.remove_library(lib)
if not self.library_thread.remove_library(lib):
return
xbmc.executebuiltin("Container.Refresh") xbmc.executebuiltin("Container.Refresh")
@ -473,8 +477,6 @@ class Service(xbmc.Monitor):
''' Reload objects which depends on the patch module. ''' Reload objects which depends on the patch module.
This allows to see the changes in code without restarting the python interpreter. This allows to see the changes in code without restarting the python interpreter.
''' '''
import full_sync
reload_modules = ['objects.movies', 'objects.musicvideos', 'objects.tvshows', reload_modules = ['objects.movies', 'objects.musicvideos', 'objects.tvshows',
'objects.music', 'objects.obj', 'objects.actions', 'objects.kodi.kodi', 'objects.music', 'objects.obj', 'objects.actions', 'objects.kodi.kodi',
'objects.kodi.movies', 'objects.kodi.musicvideos', 'objects.kodi.tvshows', 'objects.kodi.movies', 'objects.kodi.musicvideos', 'objects.kodi.tvshows',
@ -487,7 +489,6 @@ class Service(xbmc.Monitor):
reload(objects.kodi) reload(objects.kodi)
reload(objects) reload(objects)
reload(library) reload(library)
reload(full_sync)
reload(monitor) reload(monitor)
LOG.warn("---[ objects reloaded ]") LOG.warn("---[ objects reloaded ]")

View file

@ -13,10 +13,9 @@ import xbmcvfs
import downloader as server import downloader as server
import helper.xmls as xmls import helper.xmls as xmls
from database import Database, get_sync, save_sync, emby_db from database import Database, get_sync, save_sync, emby_db
from objects import Movies, TVShows, MusicVideos, Music
from helper import _, settings, window, progress, dialog, LibraryException from helper import _, settings, window, progress, dialog, LibraryException
from helper.utils import get_screensaver, set_screensaver from helper.utils import get_screensaver, set_screensaver
from emby import Emby from views import Views
################################################################################################## ##################################################################################################
@ -27,18 +26,37 @@ LOG = logging.getLogger("EMBY."+__name__)
class FullSync(object): class FullSync(object):
''' This should be called like a context.
i.e. with FullSync('emby') as sync:
sync.libraries()
'''
# Borg - multiple instances, shared state # Borg - multiple instances, shared state
_shared_state = {} _shared_state = {}
sync = None sync = None
running = False running = False
screensaver = None screensaver = None
def __init__(self, library, library_id=None, update=False):
''' Map the syncing process and start the sync. Ensure only one sync is running. def __init__(self, library, server):
''' You can call all big syncing methods here.
Initial, update, repair, remove.
''' '''
self.__dict__ = self._shared_state self.__dict__ = self._shared_state
window('emby_sync.bool', True)
if self.running:
dialog("ok", heading="{emby}", line1=_(33197))
raise Exception("Sync is already running.")
self.library = library
self.server = server
def __enter__(self):
''' Do everything we need before the sync
'''
LOG.info("-->[ fullsync ]")
if not settings('dbSyncScreensaver.bool'): if not settings('dbSyncScreensaver.bool'):
@ -46,13 +64,18 @@ class FullSync(object):
self.screensaver = get_screensaver() self.screensaver = get_screensaver()
set_screensaver(value="") set_screensaver(value="")
if not self.running:
self.running = True self.running = True
self.library = library window('emby_sync.bool', True)
return self
def libraries(self, library_id=None, update=False):
''' Map the syncing process and start the sync. Ensure only one sync is running.
'''
self.direct_path = settings('useDirectPaths') == "1" self.direct_path = settings('useDirectPaths') == "1"
self.update_library = update self.update_library = update
self.server = Emby()
self.sync = get_sync() self.sync = get_sync()
if library_id: if library_id:
@ -78,12 +101,6 @@ class FullSync(object):
if not xmls.advanced_settings() and self.sync['Libraries']: if not xmls.advanced_settings() and self.sync['Libraries']:
self.start() self.start()
else:
self.running = False
else:
dialog("ok", heading="{emby}", line1=_(33197))
raise Exception("Sync is already running.")
def get_libraries(self, library_id=None): def get_libraries(self, library_id=None):
@ -162,6 +179,7 @@ class FullSync(object):
return [libraries[x - 1] for x in selection] return [libraries[x - 1] for x in selection]
def start(self): def start(self):
''' Main sync process. ''' Main sync process.
@ -239,24 +257,13 @@ class FullSync(object):
raise raise
def __exit__(self, exc_type, exc_val, exc_tb):
''' Exiting sync
'''
self.running = False
window('emby_sync', clear=True)
if not settings('dbSyncScreensaver.bool'):
xbmc.executebuiltin('InhibitIdleShutdown(false)')
set_screensaver(value=self.screensaver)
@progress() @progress()
def movies(self, library, dialog): def movies(self, library, dialog):
''' Process movies from a single library. ''' Process movies from a single library.
''' '''
Movies = self.library.media['Movies']
with self.library.database_lock: with self.library.database_lock:
with Database() as videodb: with Database() as videodb:
with Database('emby') as embydb: with Database('emby') as embydb:
@ -296,6 +303,8 @@ class FullSync(object):
''' Process tvshows and episodes from a single library. ''' Process tvshows and episodes from a single library.
''' '''
TVShows = self.library.media['TVShows']
with self.library.database_lock: with self.library.database_lock:
with Database() as videodb: with Database() as videodb:
with Database('emby') as embydb: with Database('emby') as embydb:
@ -344,6 +353,8 @@ class FullSync(object):
''' Process musicvideos from a single library. ''' Process musicvideos from a single library.
''' '''
MusicVideos = self.library.media['MusicVideos']
with self.library.database_lock: with self.library.database_lock:
with Database() as videodb: with Database() as videodb:
with Database('emby') as embydb: with Database('emby') as embydb:
@ -382,6 +393,8 @@ class FullSync(object):
''' Process artists, album, songs from a single library. ''' Process artists, album, songs from a single library.
''' '''
Music = self.library.media['Music']
with self.library.music_database_lock: with self.library.music_database_lock:
with Database('music') as musicdb: with Database('music') as musicdb:
with Database('emby') as embydb: with Database('emby') as embydb:
@ -442,6 +455,8 @@ class FullSync(object):
''' Process all boxsets. ''' Process all boxsets.
''' '''
Movies = self.library.media['Movies']
with self.library.database_lock: with self.library.database_lock:
with Database() as videodb: with Database() as videodb:
with Database('emby') as embydb: with Database('emby') as embydb:
@ -463,6 +478,8 @@ class FullSync(object):
''' Delete all exisitng boxsets and re-add. ''' Delete all exisitng boxsets and re-add.
''' '''
Movies = self.library.media['Movies']
with self.library.database_lock: with self.library.database_lock:
with Database() as videodb: with Database() as videodb:
with Database('emby') as embydb: with Database('emby') as embydb:
@ -471,3 +488,81 @@ class FullSync(object):
obj.boxsets_reset() obj.boxsets_reset()
self.boxsets(None) self.boxsets(None)
@progress(_(33144))
def remove_library(self, library_id, dialog):
''' Remove library by their id from the Kodi database.
'''
MEDIA = self.library.MEDIA
direct_path = self.library.direct_path
with Database('emby') as embydb:
db = emby_db.EmbyDatabase(embydb.cursor)
library = db.get_view(library_id.replace('Mixed:', ""))
items = db.get_item_by_media_folder(library_id.replace('Mixed:', ""))
media = 'music' if library[1] == 'music' else 'video'
if media == 'music':
settings('MusicRescan.bool', False)
if items:
count = 0
with self.library.music_database_lock if media == 'music' else self.library.database_lock:
with Database(media) as kodidb:
if library[1] == 'mixed':
movies = [x for x in items if x[1] == 'Movie']
tvshows = [x for x in items if x[1] == 'Series']
obj = MEDIA['Movie'](self.server, embydb, kodidb, direct_path)['Remove']
for item in movies:
obj(item[0])
dialog.update(int((float(count) / float(len(items))*100)), heading="%s: %s" % (_('addon_name'), library[0]))
count += 1
obj = MEDIA['Series'](self.server, embydb, kodidb, direct_path)['Remove']
for item in tvshows:
obj(item[0])
dialog.update(int((float(count) / float(len(items))*100)), heading="%s: %s" % (_('addon_name'), library[0]))
count += 1
else:
obj = MEDIA[items[0][1]](self.server, embydb, kodidb, direct_path)['Remove']
for item in items:
obj(item[0])
dialog.update(int((float(count) / float(len(items))*100)), heading="%s: %s" % (_('addon_name'), library[0]))
count += 1
self.sync = get_sync()
if library_id in self.sync['Whitelist']:
self.sync['Whitelist'].remove(library_id)
elif 'Mixed:%s' % library_id in self.sync['Whitelist']:
self.sync['Whitelist'].remove('Mixed:%s' % library_id)
save_sync(self.sync)
def __exit__(self, exc_type, exc_val, exc_tb):
''' Exiting sync
'''
self.running = False
window('emby_sync', clear=True)
if not settings('dbSyncScreensaver.bool') and self.screensaver is not None:
xbmc.executebuiltin('InhibitIdleShutdown(false)')
set_screensaver(value=self.screensaver)
LOG.info("--<[ fullsync ]")

View file

@ -55,11 +55,14 @@ class Library(threading.Thread):
def __init__(self, monitor): def __init__(self, monitor):
self.media = {'Movies': Movies, 'TVShows': TVShows, 'MusicVideos': MusicVideos, 'Music': Music}
self.MEDIA = MEDIA
self.direct_path = settings('useDirectPaths') == "1" self.direct_path = settings('useDirectPaths') == "1"
self.progress_display = int(settings('syncProgress') or 50) self.progress_display = int(settings('syncProgress') or 50)
self.monitor = monitor self.monitor = monitor
self.player = monitor.monitor.player self.player = monitor.monitor.player
self.server = Emby() self.server = Emby().get_client()
self.updated_queue = Queue.Queue() self.updated_queue = Queue.Queue()
self.userdata_queue = Queue.Queue() self.userdata_queue = Queue.Queue()
self.removed_queue = Queue.Queue() self.removed_queue = Queue.Queue()
@ -326,14 +329,18 @@ class Library(threading.Thread):
if get_sync()['Libraries']: if get_sync()['Libraries']:
try: try:
FullSync(self) with FullSync(self, self.server) as sync:
sync.libraries()
Views().get_nodes() Views().get_nodes()
except Exception as error: except Exception as error:
LOG.error(error) LOG.error(error)
elif not settings('SyncInstallRunDone.bool'): elif not settings('SyncInstallRunDone.bool'):
FullSync(self) with FullSync(self, self.server) as sync:
sync.libraries()
Views().get_nodes() Views().get_nodes()
return True return True
@ -513,7 +520,8 @@ class Library(threading.Thread):
def add_library(self, library_id, update=False): def add_library(self, library_id, update=False):
try: try:
FullSync(self, library_id, update=update) with FullSync(self, server=self.server) as sync:
sync.libraries(library_id, update)
except Exception as error: except Exception as error:
LOG.exception(error) LOG.exception(error)
@ -523,69 +531,18 @@ class Library(threading.Thread):
return True return True
@progress(_(33144)) def remove_library(self, library_id):
def remove_library(self, library_id, dialog):
window('emby_sync.bool', True)
try: try:
with Database('emby') as embydb: with FullSync(self, self.server) as sync:
sync.remove_library(library_id)
db = emby_db.EmbyDatabase(embydb.cursor)
library = db.get_view(library_id.replace('Mixed:', ""))
items = db.get_item_by_media_folder(library_id.replace('Mixed:', ""))
media = 'music' if library[1] == 'music' else 'video'
if media == 'music':
settings('MusicRescan.bool', False)
if items:
count = 0
with self.music_database_lock if media == 'music' else self.database_lock:
with Database(media) as kodidb:
if library[1] == 'mixed':
movies = [x for x in items if x[1] == 'Movie']
tvshows = [x for x in items if x[1] == 'Series']
obj = MEDIA['Movie'](self.server, embydb, kodidb, self.direct_path)['Remove']
for item in movies:
obj(item[0])
dialog.update(int((float(count) / float(len(items))*100)), heading="%s: %s" % (_('addon_name'), library[0]))
count += 1
obj = MEDIA['Series'](self.server, embydb, kodidb, self.direct_path)['Remove']
for item in tvshows:
obj(item[0])
dialog.update(int((float(count) / float(len(items))*100)), heading="%s: %s" % (_('addon_name'), library[0]))
count += 1
else:
obj = MEDIA[items[0][1]](self.server, embydb, kodidb, self.direct_path)['Remove']
for item in items:
obj(item[0])
dialog.update(int((float(count) / float(len(items))*100)), heading="%s: %s" % (_('addon_name'), library[0]))
count += 1
sync = get_sync()
if library_id in sync['Whitelist']:
sync['Whitelist'].remove(library_id)
elif 'Mixed:%s' % library_id in sync['Whitelist']:
sync['Whitelist'].remove('Mixed:%s' % library_id)
save_sync(sync)
Views().remove_library(library_id) Views().remove_library(library_id)
except Exception as error: except Exception as error:
LOG.exception(error) LOG.exception(error)
window('emby_sync', clear=True)
return False return False
window('emby_sync', clear=True)
Views().get_views() Views().get_views()
Views().get_nodes() Views().get_nodes()