moved videonodes code to seperate class
This commit is contained in:
parent
e76bf71591
commit
d4e44122ba
4 changed files with 326 additions and 309 deletions
|
@ -273,7 +273,6 @@ def getNextUpEpisodes(tagname,limit):
|
||||||
xbmcplugin.setContent(int(sys.argv[1]), 'episodes')
|
xbmcplugin.setContent(int(sys.argv[1]), 'episodes')
|
||||||
# First we get a list of all the in-progress TV shows - filtered by tag
|
# First we get a list of all the in-progress TV shows - filtered by tag
|
||||||
json_query_string = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetTVShows", "params": { "sort": { "order": "descending", "method": "lastplayed" }, "filter": {"and": [{"operator":"true", "field":"inprogress", "value":""}, {"operator": "contains", "field": "tag", "value": "%s"}]}, "properties": [ "title", "studio", "mpaa", "file", "art" ] }, "id": "libTvShows"}' %tagname)
|
json_query_string = xbmc.executeJSONRPC('{"jsonrpc": "2.0", "method": "VideoLibrary.GetTVShows", "params": { "sort": { "order": "descending", "method": "lastplayed" }, "filter": {"and": [{"operator":"true", "field":"inprogress", "value":""}, {"operator": "contains", "field": "tag", "value": "%s"}]}, "properties": [ "title", "studio", "mpaa", "file", "art" ] }, "id": "libTvShows"}' %tagname)
|
||||||
print json_query_string
|
|
||||||
|
|
||||||
json_result = json.loads(json_query_string)
|
json_result = json.loads(json_query_string)
|
||||||
# If we found any, find the oldest unwatched show for each one.
|
# If we found any, find the oldest unwatched show for each one.
|
||||||
|
|
|
@ -22,6 +22,7 @@ from DownloadUtils import DownloadUtils
|
||||||
from ReadEmbyDB import ReadEmbyDB
|
from ReadEmbyDB import ReadEmbyDB
|
||||||
from ReadKodiDB import ReadKodiDB
|
from ReadKodiDB import ReadKodiDB
|
||||||
from WriteKodiDB import WriteKodiDB
|
from WriteKodiDB import WriteKodiDB
|
||||||
|
from VideoNodes import VideoNodes
|
||||||
|
|
||||||
addondir = xbmc.translatePath(xbmcaddon.Addon(id='plugin.video.emby').getAddonInfo('profile'))
|
addondir = xbmc.translatePath(xbmcaddon.Addon(id='plugin.video.emby').getAddonInfo('profile'))
|
||||||
dataPath = os.path.join(addondir,"library")
|
dataPath = os.path.join(addondir,"library")
|
||||||
|
@ -64,7 +65,7 @@ class LibrarySync():
|
||||||
connection.commit()
|
connection.commit()
|
||||||
|
|
||||||
### BUILD VIDEO NODES LISTING ###
|
### BUILD VIDEO NODES LISTING ###
|
||||||
utils.buildVideoNodesListing()
|
VideoNodes().buildVideoNodesListing()
|
||||||
|
|
||||||
# sync movies
|
# sync movies
|
||||||
self.MoviesFullSync(connection,cursor,pDialog)
|
self.MoviesFullSync(connection,cursor,pDialog)
|
||||||
|
|
|
@ -15,10 +15,7 @@ import inspect
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import string
|
import string
|
||||||
import unicodedata
|
import unicodedata
|
||||||
from xml.etree.ElementTree import Element, SubElement, Comment, tostring
|
|
||||||
from xml.etree import ElementTree
|
|
||||||
from xml.dom import minidom
|
|
||||||
import xml.etree.cElementTree as ET
|
|
||||||
|
|
||||||
from API import API
|
from API import API
|
||||||
from PlayUtils import PlayUtils
|
from PlayUtils import PlayUtils
|
||||||
|
@ -210,306 +207,3 @@ def reset():
|
||||||
dialog = xbmcgui.Dialog()
|
dialog = xbmcgui.Dialog()
|
||||||
dialog.ok('Emby Reset', 'Database reset has completed, Kodi will now restart to apply the changes.')
|
dialog.ok('Emby Reset', 'Database reset has completed, Kodi will now restart to apply the changes.')
|
||||||
xbmc.executebuiltin("RestartApp")
|
xbmc.executebuiltin("RestartApp")
|
||||||
|
|
||||||
|
|
||||||
def buildVideoNodeForView(tagname, type, windowPropId):
|
|
||||||
#this method will build a video node for a particular Emby view (= tag in kodi)
|
|
||||||
#we set some window props here to for easy future reference and to be used in skins (for easy access only)
|
|
||||||
|
|
||||||
WINDOW = xbmcgui.Window(10000)
|
|
||||||
libraryPath = xbmc.translatePath("special://profile/library/video/Emby - %s/" %tagname)
|
|
||||||
|
|
||||||
#create tag node - index
|
|
||||||
xbmcvfs.mkdir(libraryPath)
|
|
||||||
nodefile = os.path.join(libraryPath, "index.xml")
|
|
||||||
root = Element("node", {"order":"0"})
|
|
||||||
SubElement(root, "label").text = "Emby - " + tagname
|
|
||||||
SubElement(root, "icon").text = "special://home/addons/plugin.video.emby/icon.png"
|
|
||||||
try:
|
|
||||||
ET.ElementTree(root).write(nodefile, xml_declaration=True)
|
|
||||||
except:
|
|
||||||
ET.ElementTree(root).write(nodefile)
|
|
||||||
|
|
||||||
#create tag node - all items
|
|
||||||
nodefile = os.path.join(libraryPath, tagname + "_all.xml")
|
|
||||||
root = Element("node", {"order":"1", "type":"filter"})
|
|
||||||
SubElement(root, "label").text = tagname
|
|
||||||
SubElement(root, "match").text = "all"
|
|
||||||
SubElement(root, "content").text = type
|
|
||||||
SubElement(root, "icon").text = "special://home/addons/plugin.video.emby/icon.png"
|
|
||||||
SubElement(root, "order", {"direction":"ascending"}).text = "sorttitle"
|
|
||||||
Rule = SubElement(root, "rule", {"field":"tag","operator":"is"})
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.title" %str(windowPropId),tagname)
|
|
||||||
path = "library://video/Emby - %s/%s_all.xml"%(tagname,tagname)
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.path" %str(windowPropId),"ActivateWindow(Video,%s,return)"%path)
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.content" %str(windowPropId),path)
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.type" %str(windowPropId),type)
|
|
||||||
SubElement(Rule, "value").text = tagname
|
|
||||||
try:
|
|
||||||
ET.ElementTree(root).write(nodefile, xml_declaration=True)
|
|
||||||
except:
|
|
||||||
ET.ElementTree(root).write(nodefile)
|
|
||||||
|
|
||||||
#create tag node - recent items
|
|
||||||
nodefile = os.path.join(libraryPath, tagname + "_recent.xml")
|
|
||||||
root = Element("node", {"order":"2", "type":"filter"})
|
|
||||||
if type == "tvshows":
|
|
||||||
label = tagname + " - " + language(30170)
|
|
||||||
else:
|
|
||||||
label = tagname + " - " + language(30174)
|
|
||||||
SubElement(root, "label").text = label
|
|
||||||
SubElement(root, "match").text = "all"
|
|
||||||
SubElement(root, "content").text = type
|
|
||||||
SubElement(root, "icon").text = "special://home/addons/plugin.video.emby/icon.png"
|
|
||||||
Rule = SubElement(root, "rule", {"field":"tag","operator":"is"})
|
|
||||||
SubElement(Rule, "value").text = tagname
|
|
||||||
SubElement(root, "order", {"direction":"descending"}).text = "dateadded"
|
|
||||||
#set limit to 25 --> currently hardcoded --> TODO: add a setting for this ?
|
|
||||||
SubElement(root, "limit").text = "25"
|
|
||||||
#exclude watched items --> currently hardcoded --> TODO: add a setting for this ?
|
|
||||||
Rule2 = SubElement(root, "rule", {"field":"playcount","operator":"is"})
|
|
||||||
SubElement(Rule2, "value").text = "0"
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.recent.title" %str(windowPropId),label)
|
|
||||||
path = "library://video/Emby - %s/%s_recent.xml"%(tagname,tagname)
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.recent.path" %str(windowPropId),"ActivateWindow(Video,%s,return)"%path)
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.recent.content" %str(windowPropId),path)
|
|
||||||
try:
|
|
||||||
ET.ElementTree(root).write(nodefile, xml_declaration=True)
|
|
||||||
except:
|
|
||||||
ET.ElementTree(root).write(nodefile)
|
|
||||||
|
|
||||||
#create tag node - inprogress items
|
|
||||||
nodefile = os.path.join(libraryPath, tagname + "_progress.xml")
|
|
||||||
root = Element("node", {"order":"3", "type":"filter"})
|
|
||||||
if type == "tvshows":
|
|
||||||
label = tagname + " - " + language(30171)
|
|
||||||
else:
|
|
||||||
label = tagname + " - " + language(30177)
|
|
||||||
SubElement(root, "label").text = label
|
|
||||||
SubElement(root, "match").text = "all"
|
|
||||||
SubElement(root, "content").text = type
|
|
||||||
SubElement(root, "icon").text = "special://home/addons/plugin.video.emby/icon.png"
|
|
||||||
Rule = SubElement(root, "rule", {"field":"tag","operator":"is"})
|
|
||||||
SubElement(Rule, "value").text = tagname
|
|
||||||
#set limit to 25 --> currently hardcoded --> TODO: add a setting for this ?
|
|
||||||
SubElement(root, "limit").text = "25"
|
|
||||||
Rule2 = SubElement(root, "rule", {"field":"inprogress","operator":"true"})
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.inprogress.title" %str(windowPropId),label)
|
|
||||||
path = "library://video/Emby - %s/%s_progress.xml"%(tagname,tagname)
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.inprogress.path" %str(windowPropId),"ActivateWindow(Video,%s,return)"%path)
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.inprogress.content" %str(windowPropId),path)
|
|
||||||
try:
|
|
||||||
ET.ElementTree(root).write(nodefile, xml_declaration=True)
|
|
||||||
except:
|
|
||||||
ET.ElementTree(root).write(nodefile)
|
|
||||||
|
|
||||||
#create tag node - add unwatched movies node for movies
|
|
||||||
if type == "movies":
|
|
||||||
nodefile = os.path.join(libraryPath, tagname + "_unwatched.xml")
|
|
||||||
root = Element("node", {"order":"4", "type":"filter"})
|
|
||||||
label = tagname + " - " + language(30189)
|
|
||||||
SubElement(root, "label").text = label
|
|
||||||
SubElement(root, "match").text = "all"
|
|
||||||
SubElement(root, "content").text = "movies"
|
|
||||||
SubElement(root, "icon").text = "special://home/addons/plugin.video.emby/icon.png"
|
|
||||||
Rule = SubElement(root, "rule", {"field":"tag","operator":"is"})
|
|
||||||
SubElement(Rule, "value").text = tagname
|
|
||||||
Rule = SubElement(root, "rule", {"field":"playcount","operator":"is"})
|
|
||||||
SubElement(Rule, "value").text = "0"
|
|
||||||
SubElement(root, "order", {"direction":"ascending"}).text = "sorttitle"
|
|
||||||
#set limit to 25 --> currently hardcoded --> TODO: add a setting for this ?
|
|
||||||
SubElement(root, "limit").text = "25"
|
|
||||||
#exclude watched items --> currently hardcoded --> TODO: add a setting for this ?
|
|
||||||
Rule2 = SubElement(root, "rule", {"field":"playcount","operator":"is"})
|
|
||||||
SubElement(Rule2, "value").text = "0"
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.unwatched.title" %str(windowPropId),label)
|
|
||||||
path = "library://video/Emby - %s/%s_unwatched.xml"%(tagname,tagname)
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.unwatched.path" %str(windowPropId),"ActivateWindow(Video,%s,return)"%path)
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.unwatched.content" %str(windowPropId),path)
|
|
||||||
try:
|
|
||||||
ET.ElementTree(root).write(nodefile, xml_declaration=True)
|
|
||||||
except:
|
|
||||||
ET.ElementTree(root).write(nodefile)
|
|
||||||
|
|
||||||
|
|
||||||
#add some additional nodes for episodes
|
|
||||||
if type == "tvshows":
|
|
||||||
#create tag node - recent episodes
|
|
||||||
nodefile = os.path.join(libraryPath, tagname + "_recent_episodes.xml")
|
|
||||||
root = Element("node", {"order":"3", "type":"filter"})
|
|
||||||
label = tagname + " - " + language(30175)
|
|
||||||
SubElement(root, "label").text = label
|
|
||||||
SubElement(root, "match").text = "all"
|
|
||||||
SubElement(root, "content").text = "episodes"
|
|
||||||
SubElement(root, "icon").text = "special://home/addons/plugin.video.emby/icon.png"
|
|
||||||
Rule = SubElement(root, "rule", {"field":"tag","operator":"is"})
|
|
||||||
SubElement(Rule, "value").text = tagname
|
|
||||||
SubElement(root, "order", {"direction":"descending"}).text = "dateadded"
|
|
||||||
#set limit to 25 --> currently hardcoded --> TODO: add a setting for this ?
|
|
||||||
SubElement(root, "limit").text = "25"
|
|
||||||
#exclude watched items --> currently hardcoded --> TODO: add a setting for this ?
|
|
||||||
Rule2 = SubElement(root, "rule", {"field":"playcount","operator":"is"})
|
|
||||||
SubElement(Rule2, "value").text = "0"
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.recentepisodes.title" %str(windowPropId),label)
|
|
||||||
path = "library://video/Emby - %s/%s_recent_episodes.xml"%(tagname,tagname)
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.recentepisodes.path" %str(windowPropId),"ActivateWindow(Video,%s,return)"%path)
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.recentepisodes.content" %str(windowPropId),path)
|
|
||||||
try:
|
|
||||||
ET.ElementTree(root).write(nodefile, xml_declaration=True)
|
|
||||||
except:
|
|
||||||
ET.ElementTree(root).write(nodefile)
|
|
||||||
|
|
||||||
#create tag node - inprogress items
|
|
||||||
nodefile = os.path.join(libraryPath, tagname + "_progress_episodes.xml")
|
|
||||||
root = Element("node", {"order":"4", "type":"filter"})
|
|
||||||
label = tagname + " - " + language(30178)
|
|
||||||
SubElement(root, "label").text = label
|
|
||||||
SubElement(root, "match").text = "all"
|
|
||||||
SubElement(root, "content").text = "episodes"
|
|
||||||
SubElement(root, "icon").text = "special://home/addons/plugin.video.emby/icon.png"
|
|
||||||
Rule = SubElement(root, "rule", {"field":"tag","operator":"is"})
|
|
||||||
SubElement(Rule, "value").text = tagname
|
|
||||||
#set limit to 25 --> currently hardcoded --> TODO: add a setting for this ?
|
|
||||||
SubElement(root, "limit").text = "25"
|
|
||||||
Rule2 = SubElement(root, "rule", {"field":"inprogress","operator":"true"})
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.inprogressepisodes.title" %str(windowPropId),label)
|
|
||||||
path = "library://video/Emby - %s/%s_progress_episodes.xml"%(tagname,tagname)
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.inprogressepisodes.path" %str(windowPropId),"ActivateWindow(Video,%s,return)"%path)
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.inprogressepisodes.content" %str(windowPropId),path)
|
|
||||||
try:
|
|
||||||
ET.ElementTree(root).write(nodefile, xml_declaration=True)
|
|
||||||
except:
|
|
||||||
ET.ElementTree(root).write(nodefile)
|
|
||||||
|
|
||||||
#create tag node - nextup items
|
|
||||||
nodefile = os.path.join(libraryPath, tagname + "_nextup_episodes.xml")
|
|
||||||
root = Element("node", {"order":"4", "type":"folder"})
|
|
||||||
label = tagname + " - " + language(30179)
|
|
||||||
SubElement(root, "label").text = label
|
|
||||||
SubElement(root, "content").text = "episodes"
|
|
||||||
path = "plugin://plugin.video.emby/?id=%s&mode=nextup&limit=25" %tagname
|
|
||||||
SubElement(root, "path").text = path
|
|
||||||
SubElement(root, "icon").text = "special://home/addons/plugin.video.emby/icon.png"
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.nextepisodes.title" %str(windowPropId),label)
|
|
||||||
path = "library://video/Emby - %s/%s_nextup_episodes.xml"%(tagname,tagname)
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.nextepisodes.path" %str(windowPropId),"ActivateWindow(Video,%s,return)"%path)
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.nextepisodes.content" %str(windowPropId),path)
|
|
||||||
try:
|
|
||||||
ET.ElementTree(root).write(nodefile, xml_declaration=True)
|
|
||||||
except:
|
|
||||||
ET.ElementTree(root).write(nodefile)
|
|
||||||
|
|
||||||
def buildVideoNodesListing():
|
|
||||||
|
|
||||||
import shutil
|
|
||||||
from ReadEmbyDB import ReadEmbyDB
|
|
||||||
WINDOW = xbmcgui.Window(10000)
|
|
||||||
|
|
||||||
try:
|
|
||||||
|
|
||||||
# the library path doesn't exist on all systems
|
|
||||||
if not xbmcvfs.exists("special://profile/library/"):
|
|
||||||
xbmcvfs.mkdir("special://profile/library")
|
|
||||||
if not xbmcvfs.exists("special://profile/library/video/"):
|
|
||||||
#we need to copy over the default items
|
|
||||||
import shutil
|
|
||||||
shutil.copytree(xbmc.translatePath("special://xbmc/system/library/video"), xbmc.translatePath("special://profile/library/video"))
|
|
||||||
|
|
||||||
#always cleanup existing Emby video nodes first because we don't want old stuff to stay in there
|
|
||||||
path = "special://profile/library/video/"
|
|
||||||
if xbmcvfs.exists(path):
|
|
||||||
allDirs, allFiles = xbmcvfs.listdir(path)
|
|
||||||
for dir in allDirs:
|
|
||||||
if dir.startswith("Emby "):
|
|
||||||
shutil.rmtree(xbmc.translatePath("special://profile/library/video/" + dir))
|
|
||||||
for file in allFiles:
|
|
||||||
if file.startswith("emby"):
|
|
||||||
xbmcvfs.delete(path + file)
|
|
||||||
|
|
||||||
#we build up a listing and set window props for all nodes we created
|
|
||||||
#the window props will be used by the main entry point to quickly build up the listing and can be used in skins (like titan) too for quick reference
|
|
||||||
#comment marcelveldt: please leave the window props as-is because I will be referencing them in titan skin...
|
|
||||||
totalNodesCount = 0
|
|
||||||
|
|
||||||
#build the listing for all views
|
|
||||||
views_movies = ReadEmbyDB().getCollections("movies")
|
|
||||||
if views_movies:
|
|
||||||
for view in views_movies:
|
|
||||||
buildVideoNodeForView(view.get('title'), "movies", totalNodesCount)
|
|
||||||
totalNodesCount +=1
|
|
||||||
|
|
||||||
views_shows = ReadEmbyDB().getCollections("tvshows")
|
|
||||||
if views_shows:
|
|
||||||
for view in views_shows:
|
|
||||||
buildVideoNodeForView(view.get('title'), "tvshows", totalNodesCount)
|
|
||||||
totalNodesCount +=1
|
|
||||||
|
|
||||||
#create tag node for emby channels
|
|
||||||
nodefile = os.path.join(xbmc.translatePath("special://profile/library/video"), "emby_channels.xml")
|
|
||||||
root = Element("node", {"order":"1", "type":"folder"})
|
|
||||||
label = "Emby - " + language(30173)
|
|
||||||
SubElement(root, "label").text = label
|
|
||||||
SubElement(root, "content").text = "movies"
|
|
||||||
SubElement(root, "path").text = "plugin://plugin.video.emby/?id=0&mode=channels"
|
|
||||||
SubElement(root, "icon").text = "special://home/addons/plugin.video.emby/icon.png"
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.title" %str(totalNodesCount),label)
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.type" %str(totalNodesCount),"channels")
|
|
||||||
path = "library://video/emby_channels.xml"
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.path" %str(totalNodesCount),"ActivateWindow(Video,%s,return)"%path)
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.content" %str(totalNodesCount),path)
|
|
||||||
totalNodesCount +=1
|
|
||||||
try:
|
|
||||||
ET.ElementTree(root).write(nodefile, xml_declaration=True)
|
|
||||||
except:
|
|
||||||
ET.ElementTree(root).write(nodefile)
|
|
||||||
|
|
||||||
#create tag node - favorite shows
|
|
||||||
nodefile = os.path.join(xbmc.translatePath("special://profile/library/video"),"emby_favorite_shows.xml")
|
|
||||||
root = Element("node", {"order":"1", "type":"filter"})
|
|
||||||
label = "Emby - " + language(30181)
|
|
||||||
SubElement(root, "label").text = label
|
|
||||||
SubElement(root, "match").text = "all"
|
|
||||||
SubElement(root, "content").text = "tvshows"
|
|
||||||
SubElement(root, "icon").text = "special://home/addons/plugin.video.emby/icon.png"
|
|
||||||
SubElement(root, "order", {"direction":"ascending"}).text = "sorttitle"
|
|
||||||
Rule = SubElement(root, "rule", {"field":"tag","operator":"is"})
|
|
||||||
SubElement(Rule, "value").text = "Favorite tvshows" #do not localize the tagname itself
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.title" %str(totalNodesCount),label)
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.type" %str(totalNodesCount),"favourites")
|
|
||||||
path = "library://video/emby_favorite_shows.xml"
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.path" %str(totalNodesCount),"ActivateWindow(Video,%s,return)"%path)
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.content" %str(totalNodesCount),path)
|
|
||||||
totalNodesCount +=1
|
|
||||||
try:
|
|
||||||
ET.ElementTree(root).write(nodefile, xml_declaration=True)
|
|
||||||
except:
|
|
||||||
ET.ElementTree(root).write(nodefile)
|
|
||||||
|
|
||||||
#create tag node - favorite movies
|
|
||||||
nodefile = os.path.join(xbmc.translatePath("special://profile/library/video"),"emby_favorite_movies.xml")
|
|
||||||
root = Element("node", {"order":"1", "type":"filter"})
|
|
||||||
label = "Emby - " + language(30180)
|
|
||||||
SubElement(root, "label").text = label
|
|
||||||
SubElement(root, "match").text = "all"
|
|
||||||
SubElement(root, "content").text = "movies"
|
|
||||||
SubElement(root, "icon").text = "special://home/addons/plugin.video.emby/icon.png"
|
|
||||||
SubElement(root, "order", {"direction":"ascending"}).text = "sorttitle"
|
|
||||||
Rule = SubElement(root, "rule", {"field":"tag","operator":"is"})
|
|
||||||
SubElement(Rule, "value").text = "Favorite movies" #do not localize the tagname itself
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.title" %str(totalNodesCount),label)
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.type" %str(totalNodesCount),"favourites")
|
|
||||||
path = "library://video/emby_favorite_movies.xml"
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.path" %str(totalNodesCount),"ActivateWindow(Video,%s,return)"%path)
|
|
||||||
WINDOW.setProperty("Emby.nodes.%s.content" %str(totalNodesCount),path)
|
|
||||||
totalNodesCount +=1
|
|
||||||
try:
|
|
||||||
ET.ElementTree(root).write(nodefile, xml_declaration=True)
|
|
||||||
except:
|
|
||||||
ET.ElementTree(root).write(nodefile)
|
|
||||||
|
|
||||||
WINDOW.setProperty("Emby.nodes.total", str(totalNodesCount))
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logMsg("Emby addon","Error while creating videonodes listings, restart required ?")
|
|
||||||
print e
|
|
||||||
|
|
323
resources/lib/VideoNodes.py
Normal file
323
resources/lib/VideoNodes.py
Normal file
|
@ -0,0 +1,323 @@
|
||||||
|
#################################################################################################
|
||||||
|
# VideoNodes - utils to create video nodes listings in kodi for the emby addon
|
||||||
|
#################################################################################################
|
||||||
|
|
||||||
|
|
||||||
|
import xbmc
|
||||||
|
import xbmcgui
|
||||||
|
import xbmcaddon
|
||||||
|
import xbmcvfs
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
from xml.etree.ElementTree import Element, SubElement, Comment, tostring
|
||||||
|
from xml.etree import ElementTree
|
||||||
|
from xml.dom import minidom
|
||||||
|
import xml.etree.cElementTree as ET
|
||||||
|
|
||||||
|
import Utils as utils
|
||||||
|
|
||||||
|
from ReadEmbyDB import ReadEmbyDB
|
||||||
|
WINDOW = xbmcgui.Window(10000)
|
||||||
|
|
||||||
|
addonSettings = xbmcaddon.Addon(id='plugin.video.emby')
|
||||||
|
language = addonSettings.getLocalizedString
|
||||||
|
|
||||||
|
class VideoNodes():
|
||||||
|
|
||||||
|
|
||||||
|
def buildVideoNodeForView(self, tagname, type, windowPropId):
|
||||||
|
#this method will build a video node for a particular Emby view (= tag in kodi)
|
||||||
|
#we set some window props here to for easy future reference and to be used in skins (for easy access only)
|
||||||
|
|
||||||
|
libraryPath = xbmc.translatePath("special://profile/library/video/Emby - %s/" %tagname)
|
||||||
|
|
||||||
|
#create tag node - index
|
||||||
|
xbmcvfs.mkdir(libraryPath)
|
||||||
|
nodefile = os.path.join(libraryPath, "index.xml")
|
||||||
|
root = Element("node", {"order":"0"})
|
||||||
|
SubElement(root, "label").text = "Emby - " + tagname
|
||||||
|
SubElement(root, "icon").text = "special://home/addons/plugin.video.emby/icon.png"
|
||||||
|
try:
|
||||||
|
ET.ElementTree(root).write(nodefile, xml_declaration=True)
|
||||||
|
except:
|
||||||
|
ET.ElementTree(root).write(nodefile)
|
||||||
|
|
||||||
|
#create tag node - all items
|
||||||
|
nodefile = os.path.join(libraryPath, tagname + "_all.xml")
|
||||||
|
root = Element("node", {"order":"1", "type":"filter"})
|
||||||
|
SubElement(root, "label").text = tagname
|
||||||
|
SubElement(root, "match").text = "all"
|
||||||
|
SubElement(root, "content").text = type
|
||||||
|
SubElement(root, "icon").text = "special://home/addons/plugin.video.emby/icon.png"
|
||||||
|
SubElement(root, "order", {"direction":"ascending"}).text = "sorttitle"
|
||||||
|
Rule = SubElement(root, "rule", {"field":"tag","operator":"is"})
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.title" %str(windowPropId),tagname)
|
||||||
|
path = "library://video/Emby - %s/%s_all.xml"%(tagname,tagname)
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.path" %str(windowPropId),"ActivateWindow(Video,%s,return)"%path)
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.content" %str(windowPropId),path)
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.type" %str(windowPropId),type)
|
||||||
|
SubElement(Rule, "value").text = tagname
|
||||||
|
try:
|
||||||
|
ET.ElementTree(root).write(nodefile, xml_declaration=True)
|
||||||
|
except:
|
||||||
|
ET.ElementTree(root).write(nodefile)
|
||||||
|
|
||||||
|
#create tag node - recent items
|
||||||
|
nodefile = os.path.join(libraryPath, tagname + "_recent.xml")
|
||||||
|
root = Element("node", {"order":"2", "type":"filter"})
|
||||||
|
if type == "tvshows":
|
||||||
|
label = tagname + " - " + language(30170)
|
||||||
|
else:
|
||||||
|
label = tagname + " - " + language(30174)
|
||||||
|
SubElement(root, "label").text = label
|
||||||
|
SubElement(root, "match").text = "all"
|
||||||
|
SubElement(root, "content").text = type
|
||||||
|
SubElement(root, "icon").text = "special://home/addons/plugin.video.emby/icon.png"
|
||||||
|
Rule = SubElement(root, "rule", {"field":"tag","operator":"is"})
|
||||||
|
SubElement(Rule, "value").text = tagname
|
||||||
|
SubElement(root, "order", {"direction":"descending"}).text = "dateadded"
|
||||||
|
#set limit to 25 --> currently hardcoded --> TODO: add a setting for this ?
|
||||||
|
SubElement(root, "limit").text = "25"
|
||||||
|
#exclude watched items --> currently hardcoded --> TODO: add a setting for this ?
|
||||||
|
Rule2 = SubElement(root, "rule", {"field":"playcount","operator":"is"})
|
||||||
|
SubElement(Rule2, "value").text = "0"
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.recent.title" %str(windowPropId),label)
|
||||||
|
path = "library://video/Emby - %s/%s_recent.xml"%(tagname,tagname)
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.recent.path" %str(windowPropId),"ActivateWindow(Video,%s,return)"%path)
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.recent.content" %str(windowPropId),path)
|
||||||
|
try:
|
||||||
|
ET.ElementTree(root).write(nodefile, xml_declaration=True)
|
||||||
|
except:
|
||||||
|
ET.ElementTree(root).write(nodefile)
|
||||||
|
|
||||||
|
#create tag node - inprogress items
|
||||||
|
nodefile = os.path.join(libraryPath, tagname + "_progress.xml")
|
||||||
|
root = Element("node", {"order":"3", "type":"filter"})
|
||||||
|
if type == "tvshows":
|
||||||
|
label = tagname + " - " + language(30171)
|
||||||
|
else:
|
||||||
|
label = tagname + " - " + language(30177)
|
||||||
|
SubElement(root, "label").text = label
|
||||||
|
SubElement(root, "match").text = "all"
|
||||||
|
SubElement(root, "content").text = type
|
||||||
|
SubElement(root, "icon").text = "special://home/addons/plugin.video.emby/icon.png"
|
||||||
|
Rule = SubElement(root, "rule", {"field":"tag","operator":"is"})
|
||||||
|
SubElement(Rule, "value").text = tagname
|
||||||
|
#set limit to 25 --> currently hardcoded --> TODO: add a setting for this ?
|
||||||
|
SubElement(root, "limit").text = "25"
|
||||||
|
Rule2 = SubElement(root, "rule", {"field":"inprogress","operator":"true"})
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.inprogress.title" %str(windowPropId),label)
|
||||||
|
path = "library://video/Emby - %s/%s_progress.xml"%(tagname,tagname)
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.inprogress.path" %str(windowPropId),"ActivateWindow(Video,%s,return)"%path)
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.inprogress.content" %str(windowPropId),path)
|
||||||
|
try:
|
||||||
|
ET.ElementTree(root).write(nodefile, xml_declaration=True)
|
||||||
|
except:
|
||||||
|
ET.ElementTree(root).write(nodefile)
|
||||||
|
|
||||||
|
#create tag node - add unwatched movies node for movies
|
||||||
|
if type == "movies":
|
||||||
|
nodefile = os.path.join(libraryPath, tagname + "_unwatched.xml")
|
||||||
|
root = Element("node", {"order":"4", "type":"filter"})
|
||||||
|
label = tagname + " - " + language(30189)
|
||||||
|
SubElement(root, "label").text = label
|
||||||
|
SubElement(root, "match").text = "all"
|
||||||
|
SubElement(root, "content").text = "movies"
|
||||||
|
SubElement(root, "icon").text = "special://home/addons/plugin.video.emby/icon.png"
|
||||||
|
Rule = SubElement(root, "rule", {"field":"tag","operator":"is"})
|
||||||
|
SubElement(Rule, "value").text = tagname
|
||||||
|
Rule = SubElement(root, "rule", {"field":"playcount","operator":"is"})
|
||||||
|
SubElement(Rule, "value").text = "0"
|
||||||
|
SubElement(root, "order", {"direction":"ascending"}).text = "sorttitle"
|
||||||
|
#set limit to 25 --> currently hardcoded --> TODO: add a setting for this ?
|
||||||
|
SubElement(root, "limit").text = "25"
|
||||||
|
#exclude watched items --> currently hardcoded --> TODO: add a setting for this ?
|
||||||
|
Rule2 = SubElement(root, "rule", {"field":"playcount","operator":"is"})
|
||||||
|
SubElement(Rule2, "value").text = "0"
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.unwatched.title" %str(windowPropId),label)
|
||||||
|
path = "library://video/Emby - %s/%s_unwatched.xml"%(tagname,tagname)
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.unwatched.path" %str(windowPropId),"ActivateWindow(Video,%s,return)"%path)
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.unwatched.content" %str(windowPropId),path)
|
||||||
|
try:
|
||||||
|
ET.ElementTree(root).write(nodefile, xml_declaration=True)
|
||||||
|
except:
|
||||||
|
ET.ElementTree(root).write(nodefile)
|
||||||
|
|
||||||
|
|
||||||
|
#add some additional nodes for episodes
|
||||||
|
if type == "tvshows":
|
||||||
|
#create tag node - recent episodes
|
||||||
|
nodefile = os.path.join(libraryPath, tagname + "_recent_episodes.xml")
|
||||||
|
root = Element("node", {"order":"3", "type":"filter"})
|
||||||
|
label = tagname + " - " + language(30175)
|
||||||
|
SubElement(root, "label").text = label
|
||||||
|
SubElement(root, "match").text = "all"
|
||||||
|
SubElement(root, "content").text = "episodes"
|
||||||
|
SubElement(root, "icon").text = "special://home/addons/plugin.video.emby/icon.png"
|
||||||
|
Rule = SubElement(root, "rule", {"field":"tag","operator":"is"})
|
||||||
|
SubElement(Rule, "value").text = tagname
|
||||||
|
SubElement(root, "order", {"direction":"descending"}).text = "dateadded"
|
||||||
|
#set limit to 25 --> currently hardcoded --> TODO: add a setting for this ?
|
||||||
|
SubElement(root, "limit").text = "25"
|
||||||
|
#exclude watched items --> currently hardcoded --> TODO: add a setting for this ?
|
||||||
|
Rule2 = SubElement(root, "rule", {"field":"playcount","operator":"is"})
|
||||||
|
SubElement(Rule2, "value").text = "0"
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.recentepisodes.title" %str(windowPropId),label)
|
||||||
|
path = "library://video/Emby - %s/%s_recent_episodes.xml"%(tagname,tagname)
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.recentepisodes.path" %str(windowPropId),"ActivateWindow(Video,%s,return)"%path)
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.recentepisodes.content" %str(windowPropId),path)
|
||||||
|
try:
|
||||||
|
ET.ElementTree(root).write(nodefile, xml_declaration=True)
|
||||||
|
except:
|
||||||
|
ET.ElementTree(root).write(nodefile)
|
||||||
|
|
||||||
|
#create tag node - inprogress items
|
||||||
|
nodefile = os.path.join(libraryPath, tagname + "_progress_episodes.xml")
|
||||||
|
root = Element("node", {"order":"4", "type":"filter"})
|
||||||
|
label = tagname + " - " + language(30178)
|
||||||
|
SubElement(root, "label").text = label
|
||||||
|
SubElement(root, "match").text = "all"
|
||||||
|
SubElement(root, "content").text = "episodes"
|
||||||
|
SubElement(root, "icon").text = "special://home/addons/plugin.video.emby/icon.png"
|
||||||
|
Rule = SubElement(root, "rule", {"field":"tag","operator":"is"})
|
||||||
|
SubElement(Rule, "value").text = tagname
|
||||||
|
#set limit to 25 --> currently hardcoded --> TODO: add a setting for this ?
|
||||||
|
SubElement(root, "limit").text = "25"
|
||||||
|
Rule2 = SubElement(root, "rule", {"field":"inprogress","operator":"true"})
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.inprogressepisodes.title" %str(windowPropId),label)
|
||||||
|
path = "library://video/Emby - %s/%s_progress_episodes.xml"%(tagname,tagname)
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.inprogressepisodes.path" %str(windowPropId),"ActivateWindow(Video,%s,return)"%path)
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.inprogressepisodes.content" %str(windowPropId),path)
|
||||||
|
try:
|
||||||
|
ET.ElementTree(root).write(nodefile, xml_declaration=True)
|
||||||
|
except:
|
||||||
|
ET.ElementTree(root).write(nodefile)
|
||||||
|
|
||||||
|
#create tag node - nextup items
|
||||||
|
nodefile = os.path.join(libraryPath, tagname + "_nextup_episodes.xml")
|
||||||
|
root = Element("node", {"order":"4", "type":"folder"})
|
||||||
|
label = tagname + " - " + language(30179)
|
||||||
|
SubElement(root, "label").text = label
|
||||||
|
SubElement(root, "content").text = "episodes"
|
||||||
|
path = "plugin://plugin.video.emby/?id=%s&mode=nextup&limit=25" %tagname
|
||||||
|
SubElement(root, "path").text = path
|
||||||
|
SubElement(root, "icon").text = "special://home/addons/plugin.video.emby/icon.png"
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.nextepisodes.title" %str(windowPropId),label)
|
||||||
|
path = "library://video/Emby - %s/%s_nextup_episodes.xml"%(tagname,tagname)
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.nextepisodes.path" %str(windowPropId),"ActivateWindow(Video,%s,return)"%path)
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.nextepisodes.content" %str(windowPropId),path)
|
||||||
|
try:
|
||||||
|
ET.ElementTree(root).write(nodefile, xml_declaration=True)
|
||||||
|
except:
|
||||||
|
ET.ElementTree(root).write(nodefile)
|
||||||
|
|
||||||
|
def buildVideoNodesListing(self):
|
||||||
|
|
||||||
|
try:
|
||||||
|
|
||||||
|
# the library path doesn't exist on all systems
|
||||||
|
if not xbmcvfs.exists("special://profile/library/"):
|
||||||
|
xbmcvfs.mkdir("special://profile/library")
|
||||||
|
if not xbmcvfs.exists("special://profile/library/video/"):
|
||||||
|
#we need to copy over the default items
|
||||||
|
shutil.copytree(xbmc.translatePath("special://xbmc/system/library/video"), xbmc.translatePath("special://profile/library/video"))
|
||||||
|
|
||||||
|
#always cleanup existing Emby video nodes first because we don't want old stuff to stay in there
|
||||||
|
path = "special://profile/library/video/"
|
||||||
|
if xbmcvfs.exists(path):
|
||||||
|
allDirs, allFiles = xbmcvfs.listdir(path)
|
||||||
|
for dir in allDirs:
|
||||||
|
if dir.startswith("Emby "):
|
||||||
|
shutil.rmtree(xbmc.translatePath("special://profile/library/video/" + dir))
|
||||||
|
for file in allFiles:
|
||||||
|
if file.startswith("emby"):
|
||||||
|
xbmcvfs.delete(path + file)
|
||||||
|
|
||||||
|
#we build up a listing and set window props for all nodes we created
|
||||||
|
#the window props will be used by the main entry point to quickly build up the listing and can be used in skins (like titan) too for quick reference
|
||||||
|
#comment marcelveldt: please leave the window props as-is because I will be referencing them in titan skin...
|
||||||
|
totalNodesCount = 0
|
||||||
|
|
||||||
|
#build the listing for all views
|
||||||
|
views_movies = ReadEmbyDB().getCollections("movies")
|
||||||
|
if views_movies:
|
||||||
|
for view in views_movies:
|
||||||
|
self.buildVideoNodeForView(view.get('title'), "movies", totalNodesCount)
|
||||||
|
totalNodesCount +=1
|
||||||
|
|
||||||
|
views_shows = ReadEmbyDB().getCollections("tvshows")
|
||||||
|
if views_shows:
|
||||||
|
for view in views_shows:
|
||||||
|
self.buildVideoNodeForView(view.get('title'), "tvshows", totalNodesCount)
|
||||||
|
totalNodesCount +=1
|
||||||
|
|
||||||
|
#create tag node for emby channels
|
||||||
|
nodefile = os.path.join(xbmc.translatePath("special://profile/library/video"), "emby_channels.xml")
|
||||||
|
root = Element("node", {"order":"1", "type":"folder"})
|
||||||
|
label = "Emby - " + language(30173)
|
||||||
|
SubElement(root, "label").text = label
|
||||||
|
SubElement(root, "content").text = "movies"
|
||||||
|
SubElement(root, "path").text = "plugin://plugin.video.emby/?id=0&mode=channels"
|
||||||
|
SubElement(root, "icon").text = "special://home/addons/plugin.video.emby/icon.png"
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.title" %str(totalNodesCount),label)
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.type" %str(totalNodesCount),"channels")
|
||||||
|
path = "library://video/emby_channels.xml"
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.path" %str(totalNodesCount),"ActivateWindow(Video,%s,return)"%path)
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.content" %str(totalNodesCount),path)
|
||||||
|
totalNodesCount +=1
|
||||||
|
try:
|
||||||
|
ET.ElementTree(root).write(nodefile, xml_declaration=True)
|
||||||
|
except:
|
||||||
|
ET.ElementTree(root).write(nodefile)
|
||||||
|
|
||||||
|
#create tag node - favorite shows
|
||||||
|
nodefile = os.path.join(xbmc.translatePath("special://profile/library/video"),"emby_favorite_shows.xml")
|
||||||
|
root = Element("node", {"order":"1", "type":"filter"})
|
||||||
|
label = "Emby - " + language(30181)
|
||||||
|
SubElement(root, "label").text = label
|
||||||
|
SubElement(root, "match").text = "all"
|
||||||
|
SubElement(root, "content").text = "tvshows"
|
||||||
|
SubElement(root, "icon").text = "special://home/addons/plugin.video.emby/icon.png"
|
||||||
|
SubElement(root, "order", {"direction":"ascending"}).text = "sorttitle"
|
||||||
|
Rule = SubElement(root, "rule", {"field":"tag","operator":"is"})
|
||||||
|
SubElement(Rule, "value").text = "Favorite tvshows" #do not localize the tagname itself
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.title" %str(totalNodesCount),label)
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.type" %str(totalNodesCount),"favourites")
|
||||||
|
path = "library://video/emby_favorite_shows.xml"
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.path" %str(totalNodesCount),"ActivateWindow(Video,%s,return)"%path)
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.content" %str(totalNodesCount),path)
|
||||||
|
totalNodesCount +=1
|
||||||
|
try:
|
||||||
|
ET.ElementTree(root).write(nodefile, xml_declaration=True)
|
||||||
|
except:
|
||||||
|
ET.ElementTree(root).write(nodefile)
|
||||||
|
|
||||||
|
#create tag node - favorite movies
|
||||||
|
nodefile = os.path.join(xbmc.translatePath("special://profile/library/video"),"emby_favorite_movies.xml")
|
||||||
|
root = Element("node", {"order":"1", "type":"filter"})
|
||||||
|
label = "Emby - " + language(30180)
|
||||||
|
SubElement(root, "label").text = label
|
||||||
|
SubElement(root, "match").text = "all"
|
||||||
|
SubElement(root, "content").text = "movies"
|
||||||
|
SubElement(root, "icon").text = "special://home/addons/plugin.video.emby/icon.png"
|
||||||
|
SubElement(root, "order", {"direction":"ascending"}).text = "sorttitle"
|
||||||
|
Rule = SubElement(root, "rule", {"field":"tag","operator":"is"})
|
||||||
|
SubElement(Rule, "value").text = "Favorite movies" #do not localize the tagname itself
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.title" %str(totalNodesCount),label)
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.type" %str(totalNodesCount),"favourites")
|
||||||
|
path = "library://video/emby_favorite_movies.xml"
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.path" %str(totalNodesCount),"ActivateWindow(Video,%s,return)"%path)
|
||||||
|
WINDOW.setProperty("Emby.nodes.%s.content" %str(totalNodesCount),path)
|
||||||
|
totalNodesCount +=1
|
||||||
|
try:
|
||||||
|
ET.ElementTree(root).write(nodefile, xml_declaration=True)
|
||||||
|
except:
|
||||||
|
ET.ElementTree(root).write(nodefile)
|
||||||
|
|
||||||
|
WINDOW.setProperty("Emby.nodes.total", str(totalNodesCount))
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
utils.logMsg("Emby addon","Error while creating videonodes listings, restart required ?")
|
||||||
|
print e
|
||||||
|
|
Loading…
Reference in a new issue