mirror of
https://github.com/jellyfin/jellyfin-kodi.git
synced 2025-01-24 08:56:10 +00:00
Update views.py
This commit is contained in:
parent
82c31e0672
commit
5b6a53f58b
5 changed files with 75 additions and 134 deletions
|
@ -14,7 +14,8 @@ import xbmcgui
|
||||||
import xbmcplugin
|
import xbmcplugin
|
||||||
import xbmcvfs
|
import xbmcvfs
|
||||||
|
|
||||||
from utils import window, should_stop, settings, language, deletePlaylists, deleteNodes
|
from views import Playlist, VideoNodes
|
||||||
|
from utils import window, should_stop, settings, language
|
||||||
|
|
||||||
#################################################################################################
|
#################################################################################################
|
||||||
|
|
||||||
|
@ -157,10 +158,10 @@ def db_reset():
|
||||||
xbmc.sleep(1000)
|
xbmc.sleep(1000)
|
||||||
|
|
||||||
# Clean up the playlists
|
# Clean up the playlists
|
||||||
deletePlaylists()
|
Playlist().delete_playlists()
|
||||||
|
|
||||||
# Clean up the video nodes
|
# Clean up the video nodes
|
||||||
deleteNodes()
|
VideoNodes().deleteNodes()
|
||||||
|
|
||||||
# Wipe the kodi databases
|
# Wipe the kodi databases
|
||||||
log.warn("Resetting the Kodi video database.")
|
log.warn("Resetting the Kodi video database.")
|
||||||
|
|
|
@ -27,6 +27,7 @@ import playlist
|
||||||
import playbackutils as pbutils
|
import playbackutils as pbutils
|
||||||
import playutils
|
import playutils
|
||||||
import api
|
import api
|
||||||
|
from views import Playlist, VideoNodes
|
||||||
from utils import window, settings, dialog, language as lang
|
from utils import window, settings, dialog, language as lang
|
||||||
from database import DatabaseConn
|
from database import DatabaseConn
|
||||||
from contextlib import closing
|
from contextlib import closing
|
||||||
|
@ -548,9 +549,9 @@ def refreshPlaylist():
|
||||||
dialog = xbmcgui.Dialog()
|
dialog = xbmcgui.Dialog()
|
||||||
try:
|
try:
|
||||||
# First remove playlists
|
# First remove playlists
|
||||||
utils.deletePlaylists()
|
Playlist().delete_playlists()
|
||||||
# Remove video nodes
|
# Remove video nodes
|
||||||
utils.deleteNodes()
|
VideoNodes().deleteNodes()
|
||||||
# Refresh views
|
# Refresh views
|
||||||
lib.refreshViews()
|
lib.refreshViews()
|
||||||
dialog.notification(
|
dialog.notification(
|
||||||
|
|
|
@ -508,13 +508,9 @@ class LibrarySync(threading.Thread):
|
||||||
|
|
||||||
# do a view update if needed
|
# do a view update if needed
|
||||||
if self.refresh_views:
|
if self.refresh_views:
|
||||||
with DatabaseConn('emby') as conn_emby, DatabaseConn('video') as conn_video:
|
self.refreshViews()
|
||||||
with closing(conn_emby.cursor()) as cursor_emby, closing(conn_video.cursor()) as cursor_video:
|
self.refresh_views = False
|
||||||
# Received userconfig update
|
self.forceLibraryUpdate = True
|
||||||
self.refresh_views = False
|
|
||||||
self.maintainViews(cursor_emby, cursor_video)
|
|
||||||
self.forceLibraryUpdate = True
|
|
||||||
update_embydb = True
|
|
||||||
|
|
||||||
# do a lib update if any items in list
|
# do a lib update if any items in list
|
||||||
totalUpdates = len(self.addedItems) + len(self.updateItems) + len(self.userdataItems) + len(self.removeItems)
|
totalUpdates = len(self.addedItems) + len(self.updateItems) + len(self.userdataItems) + len(self.removeItems)
|
||||||
|
|
|
@ -150,26 +150,6 @@ def convertDate(date):
|
||||||
|
|
||||||
return date
|
return date
|
||||||
|
|
||||||
def normalize_nodes(text):
|
|
||||||
# For video nodes
|
|
||||||
text = text.replace(":", "")
|
|
||||||
text = text.replace("/", "-")
|
|
||||||
text = text.replace("\\", "-")
|
|
||||||
text = text.replace("<", "")
|
|
||||||
text = text.replace(">", "")
|
|
||||||
text = text.replace("*", "")
|
|
||||||
text = text.replace("?", "")
|
|
||||||
text = text.replace('|', "")
|
|
||||||
text = text.replace('(', "")
|
|
||||||
text = text.replace(')', "")
|
|
||||||
text = text.strip()
|
|
||||||
# Remove dots from the last character as windows can not have directories
|
|
||||||
# with dots at the end
|
|
||||||
text = text.rstrip('.')
|
|
||||||
text = unicodedata.normalize('NFKD', unicode(text, 'utf-8')).encode('ascii', 'ignore')
|
|
||||||
|
|
||||||
return text
|
|
||||||
|
|
||||||
def normalize_string(text):
|
def normalize_string(text):
|
||||||
# For theme media, do not modify unless
|
# For theme media, do not modify unless
|
||||||
# modified in TV Tunes
|
# modified in TV Tunes
|
||||||
|
@ -366,88 +346,3 @@ def passwordsXML():
|
||||||
icon="special://home/addons/plugin.video.emby/icon.png",
|
icon="special://home/addons/plugin.video.emby/icon.png",
|
||||||
time=1000,
|
time=1000,
|
||||||
sound=False)
|
sound=False)
|
||||||
|
|
||||||
def playlistXSP(mediatype, tagname, viewid, viewtype="", delete=False):
|
|
||||||
# Tagname is in unicode - actions: add or delete
|
|
||||||
tagname = tagname.encode('utf-8')
|
|
||||||
|
|
||||||
path = xbmc.translatePath("special://profile/playlists/video/").decode('utf-8')
|
|
||||||
if viewtype == "mixed":
|
|
||||||
plname = "%s - %s" % (tagname, mediatype)
|
|
||||||
xsppath = "%sEmby %s - %s.xsp" % (path, viewid, mediatype)
|
|
||||||
else:
|
|
||||||
plname = tagname
|
|
||||||
xsppath = "%sEmby %s.xsp" % (path, viewid)
|
|
||||||
|
|
||||||
# Create the playlist directory
|
|
||||||
if not xbmcvfs.exists(path):
|
|
||||||
log.info("Creating directory: %s" % path)
|
|
||||||
xbmcvfs.mkdirs(path)
|
|
||||||
|
|
||||||
# Only add the playlist if it doesn't already exists
|
|
||||||
if xbmcvfs.exists(xsppath):
|
|
||||||
|
|
||||||
if delete:
|
|
||||||
xbmcvfs.delete(xsppath)
|
|
||||||
log.info("Successfully removed playlist: %s." % tagname)
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
# Using write process since there's no guarantee the xml declaration works with etree
|
|
||||||
itemtypes = {
|
|
||||||
'homevideos': "movies"
|
|
||||||
}
|
|
||||||
log.info("Writing playlist file to: %s" % xsppath)
|
|
||||||
try:
|
|
||||||
f = xbmcvfs.File(xsppath, 'w')
|
|
||||||
except:
|
|
||||||
log.info("Failed to create playlist: %s" % xsppath)
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
f.write(
|
|
||||||
'<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>\n'
|
|
||||||
'<smartplaylist type="%s">\n\t'
|
|
||||||
'<name>Emby %s</name>\n\t'
|
|
||||||
'<match>all</match>\n\t'
|
|
||||||
'<rule field="tag" operator="is">\n\t\t'
|
|
||||||
'<value>%s</value>\n\t'
|
|
||||||
'</rule>'
|
|
||||||
'</smartplaylist>'
|
|
||||||
% (itemtypes.get(mediatype, mediatype), plname, tagname))
|
|
||||||
f.close()
|
|
||||||
log.info("Successfully added playlist: %s" % tagname)
|
|
||||||
|
|
||||||
def deletePlaylists():
|
|
||||||
|
|
||||||
# Clean up the playlists
|
|
||||||
path = xbmc.translatePath("special://profile/playlists/video/").decode('utf-8')
|
|
||||||
dirs, files = xbmcvfs.listdir(path)
|
|
||||||
for file in files:
|
|
||||||
if file.decode('utf-8').startswith('Emby'):
|
|
||||||
xbmcvfs.delete("%s%s" % (path, file))
|
|
||||||
|
|
||||||
def deleteNodes():
|
|
||||||
|
|
||||||
# Clean up video nodes
|
|
||||||
import shutil
|
|
||||||
path = xbmc.translatePath("special://profile/library/video/emby/").decode('utf-8')
|
|
||||||
if (xbmcvfs.exists(path)):
|
|
||||||
try:
|
|
||||||
shutil.rmtree(path)
|
|
||||||
except:
|
|
||||||
log.warn("Failed to delete directory: %s" % path)
|
|
||||||
# Old cleanup code kept for cleanup of old style nodes
|
|
||||||
path = xbmc.translatePath("special://profile/library/video/").decode('utf-8')
|
|
||||||
dirs, files = xbmcvfs.listdir(path)
|
|
||||||
for dir in dirs:
|
|
||||||
if dir.decode('utf-8').startswith('Emby'):
|
|
||||||
try:
|
|
||||||
shutil.rmtree("%s%s" % (path, dir.decode('utf-8')))
|
|
||||||
except:
|
|
||||||
log.warn("Failed to delete directory: %s" % dir.decode('utf-8'))
|
|
||||||
for file in files:
|
|
||||||
if file.decode('utf-8').startswith('emby'):
|
|
||||||
try:
|
|
||||||
xbmcvfs.delete("%s%s" % (path, file.decode('utf-8')))
|
|
||||||
except:
|
|
||||||
log.warn("Failed to delete file: %s" % file.decode('utf-8'))
|
|
|
@ -13,7 +13,7 @@ import xbmcvfs
|
||||||
|
|
||||||
import read_embyserver as embyserver
|
import read_embyserver as embyserver
|
||||||
import embydb_functions as embydb
|
import embydb_functions as embydb
|
||||||
from utils import window, language as lang, normalize_nodes, indent as xml_indent
|
from utils import window, language as lang, indent as xml_indent
|
||||||
|
|
||||||
#################################################################################################
|
#################################################################################################
|
||||||
|
|
||||||
|
@ -33,7 +33,6 @@ class Views(object):
|
||||||
grouped_views = list()
|
grouped_views = list()
|
||||||
|
|
||||||
media_types = {
|
media_types = {
|
||||||
|
|
||||||
'movies': "Movie",
|
'movies': "Movie",
|
||||||
'tvshows': "Series",
|
'tvshows': "Series",
|
||||||
'musicvideos': "MusicVideo",
|
'musicvideos': "MusicVideo",
|
||||||
|
@ -79,7 +78,7 @@ class Views(object):
|
||||||
|
|
||||||
self.nodes = list() # Prevent duplicate for nodes of the same type
|
self.nodes = list() # Prevent duplicate for nodes of the same type
|
||||||
self.playlists = list() # Prevent duplicate for playlists of the same type
|
self.playlists = list() # Prevent duplicate for playlists of the same type
|
||||||
# Get media folders from the ordered
|
# Get media folders to include mixed views as well
|
||||||
for folder in self.emby.getViews(media_type, root=True):
|
for folder in self.emby.getViews(media_type, root=True):
|
||||||
|
|
||||||
view_id = folder['id']
|
view_id = folder['id']
|
||||||
|
@ -287,7 +286,15 @@ class Views(object):
|
||||||
self.playlist.process_playlist(media_type, view_id, view_name, view_type)
|
self.playlist.process_playlist(media_type, view_id, view_name, view_type)
|
||||||
self.playlists.append(view_name)
|
self.playlists.append(view_name)
|
||||||
# Create the video node
|
# Create the video node
|
||||||
self._create_node(media_type, view_id, view_name, view_type)
|
if view_name not in self.nodes and media_type not in ('musicvideos', 'music'):
|
||||||
|
index = self.sorted_views.index(view_name)
|
||||||
|
self.video_nodes.viewNode(index, view_name, media_type,view_type, view_id)
|
||||||
|
|
||||||
|
if view_type == "mixed": # Change the value
|
||||||
|
self.sorted_views[index] = "%ss" % view_name
|
||||||
|
|
||||||
|
self.nodes.append(view_name)
|
||||||
|
self.total_nodes += 1
|
||||||
|
|
||||||
def delete_playlist_node(self, media_type, view_id, view_name, view_type):
|
def delete_playlist_node(self, media_type, view_id, view_name, view_type):
|
||||||
|
|
||||||
|
@ -302,19 +309,8 @@ class Views(object):
|
||||||
if media_type != "musicvideos":
|
if media_type != "musicvideos":
|
||||||
self.video_nodes.viewNode(None, view_name, media_type, view_type, view_id, True)
|
self.video_nodes.viewNode(None, view_name, media_type, view_type, view_id, True)
|
||||||
|
|
||||||
def _create_node(self, media_type, view_id, view_name, view_type):
|
|
||||||
|
|
||||||
if view_name not in self.nodes and media_type not in ('musicvideos', 'music'):
|
|
||||||
index = self.sorted_views.index(view_name)
|
|
||||||
self.video_nodes.viewNode(index, view_name, media_type,view_type, view_id)
|
|
||||||
|
|
||||||
if view_type == "mixed": # Change the value
|
|
||||||
self.sorted_views[index] = "%ss" % view_name
|
|
||||||
|
|
||||||
self.nodes.append(view_name)
|
|
||||||
self.total_nodes += 1
|
|
||||||
|
|
||||||
def add_single_nodes(self):
|
def add_single_nodes(self):
|
||||||
|
|
||||||
singles = [
|
singles = [
|
||||||
("Favorite movies", "movies", "favourites"),
|
("Favorite movies", "movies", "favourites"),
|
||||||
("Favorite tvshows", "tvshows", "favourites"),
|
("Favorite tvshows", "tvshows", "favourites"),
|
||||||
|
@ -385,6 +381,14 @@ class Playlist(object):
|
||||||
xbmcvfs.delete(path)
|
xbmcvfs.delete(path)
|
||||||
log.info("successfully removed playlist: %s", path)
|
log.info("successfully removed playlist: %s", path)
|
||||||
|
|
||||||
|
def delete_playlists(self):
|
||||||
|
# Clean up the playlists
|
||||||
|
path = xbmc.translatePath("special://profile/playlists/video/").decode('utf-8')
|
||||||
|
dirs, files = xbmcvfs.listdir(path)
|
||||||
|
for file in files:
|
||||||
|
if file.decode('utf-8').startswith('Emby'):
|
||||||
|
self._delete_playlist(os.path.join(path, file))
|
||||||
|
|
||||||
|
|
||||||
class VideoNodes(object):
|
class VideoNodes(object):
|
||||||
|
|
||||||
|
@ -392,6 +396,26 @@ class VideoNodes(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def normalize_nodes(self, text):
|
||||||
|
# For video nodes
|
||||||
|
text = text.replace(":", "")
|
||||||
|
text = text.replace("/", "-")
|
||||||
|
text = text.replace("\\", "-")
|
||||||
|
text = text.replace("<", "")
|
||||||
|
text = text.replace(">", "")
|
||||||
|
text = text.replace("*", "")
|
||||||
|
text = text.replace("?", "")
|
||||||
|
text = text.replace('|', "")
|
||||||
|
text = text.replace('(', "")
|
||||||
|
text = text.replace(')', "")
|
||||||
|
text = text.strip()
|
||||||
|
# Remove dots from the last character as windows can not have directories
|
||||||
|
# with dots at the end
|
||||||
|
text = text.rstrip('.')
|
||||||
|
text = unicodedata.normalize('NFKD', unicode(text, 'utf-8')).encode('ascii', 'ignore')
|
||||||
|
|
||||||
|
return text
|
||||||
|
|
||||||
def commonRoot(self, order, label, tagname="", roottype=1):
|
def commonRoot(self, order, label, tagname="", roottype=1):
|
||||||
|
|
||||||
if roottype == 0:
|
if roottype == 0:
|
||||||
|
@ -693,7 +717,7 @@ class VideoNodes(object):
|
||||||
def singleNode(self, indexnumber, tagname, mediatype, itemtype):
|
def singleNode(self, indexnumber, tagname, mediatype, itemtype):
|
||||||
|
|
||||||
tagname = tagname.encode('utf-8')
|
tagname = tagname.encode('utf-8')
|
||||||
cleantagname = normalize_nodes(tagname)
|
cleantagname = self.normalize_nodes(tagname)
|
||||||
nodepath = xbmc.translatePath("special://profile/library/video/").decode('utf-8')
|
nodepath = xbmc.translatePath("special://profile/library/video/").decode('utf-8')
|
||||||
nodeXML = "%semby_%s.xml" % (nodepath, cleantagname)
|
nodeXML = "%semby_%s.xml" % (nodepath, cleantagname)
|
||||||
path = "library://video/emby_%s.xml" % cleantagname
|
path = "library://video/emby_%s.xml" % cleantagname
|
||||||
|
@ -742,6 +766,30 @@ class VideoNodes(object):
|
||||||
except: pass
|
except: pass
|
||||||
etree.ElementTree(root).write(nodeXML)
|
etree.ElementTree(root).write(nodeXML)
|
||||||
|
|
||||||
|
def deleteNodes(self):
|
||||||
|
# Clean up video nodes
|
||||||
|
path = xbmc.translatePath("special://profile/library/video/emby/").decode('utf-8')
|
||||||
|
if (xbmcvfs.exists(path)):
|
||||||
|
try:
|
||||||
|
shutil.rmtree(path)
|
||||||
|
except:
|
||||||
|
log.warn("Failed to delete directory: %s" % path)
|
||||||
|
# Old cleanup code kept for cleanup of old style nodes
|
||||||
|
path = xbmc.translatePath("special://profile/library/video/").decode('utf-8')
|
||||||
|
dirs, files = xbmcvfs.listdir(path)
|
||||||
|
for dir in dirs:
|
||||||
|
if dir.decode('utf-8').startswith('Emby'):
|
||||||
|
try:
|
||||||
|
shutil.rmtree("%s%s" % (path, dir.decode('utf-8')))
|
||||||
|
except:
|
||||||
|
log.warn("Failed to delete directory: %s" % dir.decode('utf-8'))
|
||||||
|
for file in files:
|
||||||
|
if file.decode('utf-8').startswith('emby'):
|
||||||
|
try:
|
||||||
|
xbmcvfs.delete("%s%s" % (path, file.decode('utf-8')))
|
||||||
|
except:
|
||||||
|
log.warn("Failed to delete file: %s" % file.decode('utf-8'))
|
||||||
|
|
||||||
def clearProperties(self):
|
def clearProperties(self):
|
||||||
|
|
||||||
log.info("Clearing nodes properties.")
|
log.info("Clearing nodes properties.")
|
||||||
|
|
Loading…
Reference in a new issue