mirror of
https://github.com/jellyfin/jellyfin-kodi.git
synced 2025-01-24 08:56:10 +00:00
Rework full sync into a context
This commit is contained in:
parent
f9db3c6134
commit
7e7cf1489d
4 changed files with 161 additions and 109 deletions
|
@ -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
|
|
||||||
|
|
||||||
#################################################################################################
|
#################################################################################################
|
||||||
|
|
||||||
|
|
|
@ -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 ]")
|
||||||
|
|
|
@ -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,44 +64,43 @@ class FullSync(object):
|
||||||
self.screensaver = get_screensaver()
|
self.screensaver = get_screensaver()
|
||||||
set_screensaver(value="")
|
set_screensaver(value="")
|
||||||
|
|
||||||
if not self.running:
|
self.running = True
|
||||||
|
window('emby_sync.bool', True)
|
||||||
|
|
||||||
self.running = True
|
return self
|
||||||
self.library = library
|
|
||||||
self.direct_path = settings('useDirectPaths') == "1"
|
|
||||||
self.update_library = update
|
|
||||||
self.server = Emby()
|
|
||||||
self.sync = get_sync()
|
|
||||||
|
|
||||||
if library_id:
|
|
||||||
libraries = library_id.split(',')
|
|
||||||
|
|
||||||
for selected in libraries:
|
def libraries(self, library_id=None, update=False):
|
||||||
|
|
||||||
if selected not in [x.replace('Mixed:', "") for x in self.sync['Libraries']]:
|
''' Map the syncing process and start the sync. Ensure only one sync is running.
|
||||||
library = self.get_libraries(selected)
|
'''
|
||||||
|
self.direct_path = settings('useDirectPaths') == "1"
|
||||||
|
self.update_library = update
|
||||||
|
self.sync = get_sync()
|
||||||
|
|
||||||
if library:
|
if library_id:
|
||||||
|
libraries = library_id.split(',')
|
||||||
|
|
||||||
self.sync['Libraries'].append("Mixed:%s" % selected if library[1] == 'mixed' else selected)
|
for selected in libraries:
|
||||||
|
|
||||||
if library[1] in ('mixed', 'movies'):
|
if selected not in [x.replace('Mixed:', "") for x in self.sync['Libraries']]:
|
||||||
self.sync['Libraries'].append('Boxsets:%s' % selected)
|
library = self.get_libraries(selected)
|
||||||
else:
|
|
||||||
self.sync['Libraries'].append(selected)
|
|
||||||
else:
|
|
||||||
self.mapping()
|
|
||||||
|
|
||||||
xmls.sources()
|
if library:
|
||||||
|
|
||||||
if not xmls.advanced_settings() and self.sync['Libraries']:
|
self.sync['Libraries'].append("Mixed:%s" % selected if library[1] == 'mixed' else selected)
|
||||||
self.start()
|
|
||||||
else:
|
if library[1] in ('mixed', 'movies'):
|
||||||
self.running = False
|
self.sync['Libraries'].append('Boxsets:%s' % selected)
|
||||||
|
else:
|
||||||
|
self.sync['Libraries'].append(selected)
|
||||||
else:
|
else:
|
||||||
dialog("ok", heading="{emby}", line1=_(33197))
|
self.mapping()
|
||||||
|
|
||||||
raise Exception("Sync is already running.")
|
xmls.sources()
|
||||||
|
|
||||||
|
if not xmls.advanced_settings() and self.sync['Libraries']:
|
||||||
|
self.start()
|
||||||
|
|
||||||
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 ]")
|
||||||
|
|
|
@ -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()
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue