mirror of
https://github.com/jellyfin/jellyfin-kodi.git
synced 2024-12-26 02:36:10 +00:00
Simplify view selection, fix loop
Add new Emby.wnodes props, prevent duplicates, fix
This commit is contained in:
parent
0740dd024b
commit
4670cb426a
5 changed files with 124 additions and 35 deletions
|
@ -123,6 +123,7 @@ def listing():
|
||||||
'''
|
'''
|
||||||
total = int(window('Emby.nodes.total') or 0)
|
total = int(window('Emby.nodes.total') or 0)
|
||||||
sync = get_sync()
|
sync = get_sync()
|
||||||
|
whitelist = [x.replace('Mixed:', "") for x in sync['Whitelist']]
|
||||||
servers = get_credentials()['Servers'][1:]
|
servers = get_credentials()['Servers'][1:]
|
||||||
|
|
||||||
for i in range(total):
|
for i in range(total):
|
||||||
|
@ -139,11 +140,10 @@ def listing():
|
||||||
view_id = window('%s.id' % window_prop)
|
view_id = window('%s.id' % window_prop)
|
||||||
context = []
|
context = []
|
||||||
|
|
||||||
if view_id and node in ('movies', 'tvshows', 'musicvideos', 'music') and view_id not in sync['Whitelist']:
|
if view_id and node in ('movies', 'tvshows', 'musicvideos', 'music') and view_id not in whitelist:
|
||||||
|
|
||||||
context.append((_(33123), "RunPlugin(plugin://plugin.video.emby?mode=synclib&id=%s)" % view_id))
|
context.append((_(33123), "RunPlugin(plugin://plugin.video.emby?mode=synclib&id=%s)" % view_id))
|
||||||
|
|
||||||
if view_id and node in ('movies', 'tvshows', 'musicvideos', 'music') and view_id in sync['Whitelist']:
|
if view_id and node in ('movies', 'tvshows', 'musicvideos', 'music') and view_id in whitelist:
|
||||||
|
|
||||||
context.append((_(33136), "RunPlugin(plugin://plugin.video.emby?mode=synclib&id=%s)" % view_id))
|
context.append((_(33136), "RunPlugin(plugin://plugin.video.emby?mode=synclib&id=%s)" % view_id))
|
||||||
context.append((_(33132), "RunPlugin(plugin://plugin.video.emby?mode=repairlib&id=%s)" % view_id))
|
context.append((_(33132), "RunPlugin(plugin://plugin.video.emby?mode=repairlib&id=%s)" % view_id))
|
||||||
|
|
|
@ -139,7 +139,7 @@ class Service(xbmc.Monitor):
|
||||||
url = "https://sheets.googleapis.com/v4/spreadsheets/1cKWQCVL0lVONulO2KyGzBilzhGvsyuSjFvrqe8g6nJw/values/A2:B?key=AIzaSyAP-1mcBglk9zIofJlqGpvKXkff3GRMhdI"
|
url = "https://sheets.googleapis.com/v4/spreadsheets/1cKWQCVL0lVONulO2KyGzBilzhGvsyuSjFvrqe8g6nJw/values/A2:B?key=AIzaSyAP-1mcBglk9zIofJlqGpvKXkff3GRMhdI"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
versions = {k.lower(): v for k, v in dict(requests.get(url, verify=False).json()['values']).items()}
|
versions = {k.lower(): v for k, v in dict(requests.get(url).json()['values']).items()}
|
||||||
build = find(versions, kodi.lower())
|
build = find(versions, kodi.lower())
|
||||||
|
|
||||||
if not build:
|
if not build:
|
||||||
|
@ -284,11 +284,7 @@ class Service(xbmc.Monitor):
|
||||||
if not data.get('Id'):
|
if not data.get('Id'):
|
||||||
return
|
return
|
||||||
|
|
||||||
libraries = data['Id'].split(',')
|
self.library_thread.add_library(data['Id'])
|
||||||
|
|
||||||
for lib in libraries:
|
|
||||||
self.library_thread.add_library(lib)
|
|
||||||
|
|
||||||
xbmc.executebuiltin("Container.Refresh")
|
xbmc.executebuiltin("Container.Refresh")
|
||||||
|
|
||||||
elif method == 'RepairLibrary':
|
elif method == 'RepairLibrary':
|
||||||
|
@ -299,8 +295,8 @@ class Service(xbmc.Monitor):
|
||||||
|
|
||||||
for lib in libraries:
|
for lib in libraries:
|
||||||
self.library_thread.remove_library(lib)
|
self.library_thread.remove_library(lib)
|
||||||
self.library_thread.add_library(lib)
|
|
||||||
|
|
||||||
|
self.library_thread.add_library(data['Id'])
|
||||||
xbmc.executebuiltin("Container.Refresh")
|
xbmc.executebuiltin("Container.Refresh")
|
||||||
|
|
||||||
elif method == 'RemoveLibrary':
|
elif method == 'RemoveLibrary':
|
||||||
|
@ -398,7 +394,7 @@ class Service(xbmc.Monitor):
|
||||||
"emby_state", "emby_serverStatus",
|
"emby_state", "emby_serverStatus",
|
||||||
"emby_syncRunning", "emby_dbCheck",
|
"emby_syncRunning", "emby_dbCheck",
|
||||||
"emby_currUser", "emby_dbScan",
|
"emby_currUser", "emby_dbScan",
|
||||||
"emby_initialScan", "emby_playbackProps",
|
"emby_initialScan",
|
||||||
|
|
||||||
"emby_play", "emby_online", "emby.connected", "emby_should_stop", "emby.resume",
|
"emby_play", "emby_online", "emby.connected", "emby_should_stop", "emby.resume",
|
||||||
"emby.external", "emby.external_check"
|
"emby.external", "emby.external_check"
|
||||||
|
|
|
@ -12,7 +12,7 @@ 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
|
from database import Database, get_sync, save_sync, emby_db
|
||||||
from objects import Movies, TVShows, MusicVideos, Music
|
from objects import Movies, TVShows, MusicVideos, Music
|
||||||
from helper import _, settings, progress, dialog, LibraryException
|
from helper import _, settings, progress, dialog, LibraryException
|
||||||
from emby import Emby
|
from emby import Emby
|
||||||
|
@ -37,7 +37,16 @@ class FullSync(object):
|
||||||
self.sync = get_sync()
|
self.sync = get_sync()
|
||||||
|
|
||||||
if library_id:
|
if library_id:
|
||||||
self.sync['Libraries'].append(library_id)
|
libraries = library_id.split(',')
|
||||||
|
|
||||||
|
for selected in libraries:
|
||||||
|
if selected not in [x.replace('Mixed:', "") for x in self.sync['Whitelist']]:
|
||||||
|
library = self.get_libraries(selected)
|
||||||
|
|
||||||
|
if library[1] == 'mixed':
|
||||||
|
selected = "Mixed:%s" % selected
|
||||||
|
|
||||||
|
self.sync['Libraries'].append(selected)
|
||||||
else:
|
else:
|
||||||
self.mapping()
|
self.mapping()
|
||||||
|
|
||||||
|
@ -45,6 +54,14 @@ class FullSync(object):
|
||||||
if not xmls.advanced_settings():
|
if not xmls.advanced_settings():
|
||||||
self.start()
|
self.start()
|
||||||
|
|
||||||
|
def get_libraries(self, library_id=None):
|
||||||
|
|
||||||
|
with Database('emby') as embydb:
|
||||||
|
if library_id is None:
|
||||||
|
return emby_db.EmbyDatabase(embydb.cursor).get_views()
|
||||||
|
else:
|
||||||
|
return emby_db.EmbyDatabase(embydb.cursor).get_view(library_id)
|
||||||
|
|
||||||
def mapping(self):
|
def mapping(self):
|
||||||
|
|
||||||
''' Load the mapping of the full sync.
|
''' Load the mapping of the full sync.
|
||||||
|
@ -61,13 +78,10 @@ class FullSync(object):
|
||||||
LOG.info("generate full sync")
|
LOG.info("generate full sync")
|
||||||
libraries = []
|
libraries = []
|
||||||
|
|
||||||
for library in self.server['api'].get_media_folders()['Items']:
|
for library in self.get_libraries():
|
||||||
library['Media'] = library.get('OriginalCollectionType', library.get('CollectionType', "mixed"))
|
|
||||||
|
|
||||||
if library['Type'] in ('Channel', 'PlaylistsFolder') or library['Media'] not in ('movies', 'tvshows', 'musicvideos', 'music', 'mixed'):
|
if library[2] in ('movies', 'tvshows', 'musicvideos', 'music', 'mixed'):
|
||||||
continue
|
libraries.append({'Id': library[0], 'Name': library[1], 'Media': library[2]})
|
||||||
|
|
||||||
libraries.append(library)
|
|
||||||
|
|
||||||
libraries = self.select_libraries(libraries)
|
libraries = self.select_libraries(libraries)
|
||||||
|
|
||||||
|
|
|
@ -219,15 +219,18 @@ class Library(threading.Thread):
|
||||||
FullSync(self)
|
FullSync(self)
|
||||||
Views().get_nodes()
|
Views().get_nodes()
|
||||||
|
|
||||||
self.started = True
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except LibraryException as error:
|
except LibraryException as error:
|
||||||
LOG.error(error.status)
|
LOG.error(error.status)
|
||||||
|
|
||||||
if error.status in 'SyncLibraryLater':
|
if error.status in 'SyncLibraryLater':
|
||||||
|
|
||||||
dialog("ok", heading="{emby}", line1=_(33129))
|
dialog("ok", heading="{emby}", line1=_(33129))
|
||||||
settings('SyncInstallRunDone.bool', True)
|
settings('SyncInstallRunDone.bool', True)
|
||||||
|
sync = get_sync()
|
||||||
|
sync['Libraries'] = []
|
||||||
|
save_sync(sync)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -307,6 +310,7 @@ class Library(threading.Thread):
|
||||||
'AddLibrarySelection': 'SyncLibrary'
|
'AddLibrarySelection': 'SyncLibrary'
|
||||||
}
|
}
|
||||||
sync = get_sync()
|
sync = get_sync()
|
||||||
|
whitelist = [x.replace('Mixed:', "") for x in sync['Whitelist']]
|
||||||
libraries = []
|
libraries = []
|
||||||
|
|
||||||
with Database('emby') as embydb:
|
with Database('emby') as embydb:
|
||||||
|
@ -318,7 +322,7 @@ class Library(threading.Thread):
|
||||||
name = db.get_view_name(library.replace('Mixed:', ""))
|
name = db.get_view_name(library.replace('Mixed:', ""))
|
||||||
libraries.append({'Id': library, 'Name': name})
|
libraries.append({'Id': library, 'Name': name})
|
||||||
else:
|
else:
|
||||||
available = [x for x in sync['SortedViews'] if x not in [y.replace('Mixed:', "") for y in sync['Whitelist']]]
|
available = [x for x in sync['SortedViews'] if x not in whitelist]
|
||||||
|
|
||||||
for library in available:
|
for library in available:
|
||||||
name, media = db.get_view(library)
|
name, media = db.get_view(library)
|
||||||
|
@ -372,6 +376,21 @@ class Library(threading.Thread):
|
||||||
if items:
|
if items:
|
||||||
with self.music_database_lock if media == 'music' else self.database_lock:
|
with self.music_database_lock if media == 'music' else self.database_lock:
|
||||||
with Database(media) as kodidb:
|
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])
|
||||||
|
|
||||||
|
obj = MEDIA['Series'](self.server, embydb, kodidb, self.direct_path)['Remove']
|
||||||
|
|
||||||
|
for item in tvshows:
|
||||||
|
obj(item[0])
|
||||||
|
else:
|
||||||
obj = MEDIA[items[0][1]](self.server, embydb, kodidb, self.direct_path)['Remove']
|
obj = MEDIA[items[0][1]](self.server, embydb, kodidb, self.direct_path)['Remove']
|
||||||
|
|
||||||
for item in items:
|
for item in items:
|
||||||
|
|
|
@ -619,36 +619,53 @@ class Views(object):
|
||||||
Setup the window properties that reflect the emby server views and more.
|
Setup the window properties that reflect the emby server views and more.
|
||||||
'''
|
'''
|
||||||
self.window_clear()
|
self.window_clear()
|
||||||
|
self.window_clear('Emby.wnodes')
|
||||||
|
|
||||||
with Database('emby') as embydb:
|
with Database('emby') as embydb:
|
||||||
libraries = emby_db.EmbyDatabase(embydb.cursor).get_views()
|
libraries = emby_db.EmbyDatabase(embydb.cursor).get_views()
|
||||||
|
|
||||||
libraries = self.order_media_folders(libraries or [])
|
libraries = self.order_media_folders(libraries or [])
|
||||||
index = 0
|
index = 0
|
||||||
|
windex = 0
|
||||||
|
|
||||||
for library in (libraries or []):
|
for library in (libraries or []):
|
||||||
view = {'Id': library[0], 'Name': library[1], 'Tag': library[1], 'Media': library[2]}
|
view = {'Id': library[0], 'Name': library[1], 'Tag': library[1], 'Media': library[2]}
|
||||||
|
|
||||||
if library[0] in self.sync['Whitelist']: # Synced libraries
|
if library[0] in [x.replace('Mixed:', "") for x in self.sync['Whitelist']]: # Synced libraries
|
||||||
|
|
||||||
if view['Media'] in ('movies', 'tvshows', 'musicvideos', 'mixed'):
|
if view['Media'] in ('movies', 'tvshows', 'musicvideos', 'mixed'):
|
||||||
for node in NODES[view['Media']]:
|
|
||||||
|
|
||||||
if view['Media'] == 'mixed':
|
if view['Media'] == 'mixed':
|
||||||
for media in ('movies', 'tvshows'):
|
for media in ('movies', 'tvshows'):
|
||||||
|
|
||||||
|
for node in NODES[media]:
|
||||||
|
|
||||||
temp_view = dict(view)
|
temp_view = dict(view)
|
||||||
temp_view['Media'] = media
|
temp_view['Media'] = media
|
||||||
temp_view['Name'] = "%s (%s)" % (view['Name'], _(media))
|
temp_view['Name'] = "%s (%s)" % (view['Name'], _(media))
|
||||||
self.window_node(index, temp_view, *node)
|
self.window_node(index, temp_view, *node)
|
||||||
|
self.window_wnode(windex, view, *node)
|
||||||
else: # Add one to compensate for the duplicate.
|
else: # Add one to compensate for the duplicate.
|
||||||
index += 1
|
index += 1
|
||||||
|
windex += 1
|
||||||
else:
|
else:
|
||||||
|
for node in NODES[view['Media']]:
|
||||||
|
|
||||||
self.window_node(index, view, *node)
|
self.window_node(index, view, *node)
|
||||||
|
|
||||||
|
if view['Media'] in ('movies', 'tvshows'):
|
||||||
|
self.window_wnode(windex, view, *node)
|
||||||
|
|
||||||
|
if view['Media'] in ('movies', 'tvshows'):
|
||||||
|
windex += 1
|
||||||
|
|
||||||
elif view['Media'] == 'music':
|
elif view['Media'] == 'music':
|
||||||
self.window_node(index, view, 'music')
|
self.window_node(index, view, 'music')
|
||||||
else: # Dynamic entry
|
else: # Dynamic entry
|
||||||
|
if view['Media'] in ('homevideos', 'books', 'audiobooks'):
|
||||||
|
self.window_wnode(windex, view, 'browse')
|
||||||
|
windex += 1
|
||||||
|
|
||||||
self.window_node(index, view, 'browse')
|
self.window_node(index, view, 'browse')
|
||||||
|
|
||||||
index += 1
|
index += 1
|
||||||
|
@ -661,6 +678,8 @@ class Views(object):
|
||||||
index += 1
|
index += 1
|
||||||
|
|
||||||
window('Emby.nodes.total', str(index))
|
window('Emby.nodes.total', str(index))
|
||||||
|
LOG.info(windex)
|
||||||
|
window('Emby.wnodes.total', str(windex))
|
||||||
|
|
||||||
def window_node(self, index, view, node=None, node_label=None):
|
def window_node(self, index, view, node=None, node_label=None):
|
||||||
|
|
||||||
|
@ -688,16 +707,16 @@ class Views(object):
|
||||||
|
|
||||||
window_prop = "Emby.nodes.%s" % index
|
window_prop = "Emby.nodes.%s" % index
|
||||||
window('%s.index' % window_prop, path.replace('all.xml', "")) # dir
|
window('%s.index' % window_prop, path.replace('all.xml', "")) # dir
|
||||||
window('%s.title' % window_prop, view['Name'])
|
window('%s.title' % window_prop, view['Name'].encode('utf-8'))
|
||||||
window('%s.content' % window_prop, path)
|
window('%s.content' % window_prop, path)
|
||||||
|
|
||||||
elif node == 'browse':
|
elif node == 'browse':
|
||||||
|
|
||||||
window_prop = "Emby.nodes.%s" % index
|
window_prop = "Emby.nodes.%s" % index
|
||||||
window('%s.title' % window_prop, view['Name'])
|
window('%s.title' % window_prop, view['Name'].encode('utf-8'))
|
||||||
else:
|
else:
|
||||||
window_prop = "Emby.nodes.%s.%s" % (index, node)
|
window_prop = "Emby.nodes.%s.%s" % (index, node)
|
||||||
window('%s.title' % window_prop, str(node_label) or view['Name'])
|
window('%s.title' % window_prop, str(node_label) or view['Name'].encode('utf-8'))
|
||||||
window('%s.content' % window_prop, path)
|
window('%s.content' % window_prop, path)
|
||||||
|
|
||||||
window('%s.id' % window_prop, view['Id'])
|
window('%s.id' % window_prop, view['Id'])
|
||||||
|
@ -722,6 +741,47 @@ class Views(object):
|
||||||
window('%s.content' % window_prop, path)
|
window('%s.content' % window_prop, path)
|
||||||
window('%s.type' % window_prop, item_type)
|
window('%s.type' % window_prop, item_type)
|
||||||
|
|
||||||
|
def window_wnode(self, index, view, node=None, node_label=None):
|
||||||
|
|
||||||
|
''' Similar to window_node, but does not contain music, musicvideos.
|
||||||
|
Contains books, audiobooks.
|
||||||
|
'''
|
||||||
|
if view['Media'] in ('homevideos', 'photos'):
|
||||||
|
path = self.window_browse(view, None if node in ('all', 'browse') else node)
|
||||||
|
else:
|
||||||
|
path = self.window_path(view, node)
|
||||||
|
|
||||||
|
if node in ('browse', 'homevideos', 'photos'):
|
||||||
|
window_path = path
|
||||||
|
else:
|
||||||
|
window_path = "ActivateWindow(Videos,%s,return)" % path
|
||||||
|
|
||||||
|
if node == 'all':
|
||||||
|
|
||||||
|
window_prop = "Emby.wnodes.%s" % index
|
||||||
|
window('%s.index' % window_prop, path.replace('all.xml', "")) # dir
|
||||||
|
window('%s.title' % window_prop, view['Name'].encode('utf-8'))
|
||||||
|
window('%s.content' % window_prop, path)
|
||||||
|
|
||||||
|
elif node == 'browse':
|
||||||
|
|
||||||
|
window_prop = "Emby.wnodes.%s" % index
|
||||||
|
window('%s.title' % window_prop, view['Name'].encode('utf-8'))
|
||||||
|
window('%s.content' % window_prop, path)
|
||||||
|
else:
|
||||||
|
window_prop = "Emby.wnodes.%s.%s" % (index, node)
|
||||||
|
window('%s.title' % window_prop, str(node_label) or view['Name'].encode('utf-8'))
|
||||||
|
window('%s.content' % window_prop, path)
|
||||||
|
|
||||||
|
window('%s.id' % window_prop, view['Id'])
|
||||||
|
window('%s.path' % window_prop, window_path)
|
||||||
|
window('%s.type' % window_prop, view['Media'])
|
||||||
|
|
||||||
|
if self.server['connected']:
|
||||||
|
|
||||||
|
artwork = api.API(None, self.server['auth/server-address']).get_artwork(view['Id'], 'Primary')
|
||||||
|
window('%s.artwork' % window_prop, artwork)
|
||||||
|
|
||||||
def window_path(self, view, node):
|
def window_path(self, view, node):
|
||||||
return "library://video/emby%s%s/%s.xml" % (view['Media'], view['Id'], node)
|
return "library://video/emby%s%s/%s.xml" % (view['Media'], view['Id'], node)
|
||||||
|
|
||||||
|
@ -752,11 +812,11 @@ class Views(object):
|
||||||
|
|
||||||
return "%s?%s" % ("plugin://plugin.video.emby", urllib.urlencode(params))
|
return "%s?%s" % ("plugin://plugin.video.emby", urllib.urlencode(params))
|
||||||
|
|
||||||
def window_clear(self):
|
def window_clear(self, name=None):
|
||||||
|
|
||||||
''' Clearing window prop setup for Views.
|
''' Clearing window prop setup for Views.
|
||||||
'''
|
'''
|
||||||
total = int(window('Emby.nodes.total') or 0)
|
total = int(window((name or 'Emby.nodes') + '.total') or 0)
|
||||||
props = [
|
props = [
|
||||||
|
|
||||||
"index","id","path","title","content","type"
|
"index","id","path","title","content","type"
|
||||||
|
|
Loading…
Reference in a new issue