diff --git a/addon.xml b/addon.xml
index 2acd340..24cac10 100644
--- a/addon.xml
+++ b/addon.xml
@@ -1,7 +1,7 @@
@@ -15,10 +15,10 @@
all
en
GNU GENERAL PUBLIC LICENSE. Version 2, June 1991
-
-
-
-
-
+ https://emby.media/community/index.php?/forum/99-kodi/
+ https://emby.media/community/index.php?/forum/99-kodi/
+ https://github.com/faush01/plugin.video.embycon
+ Emby Connector Addon for Kodi
+ A basic addon to allow you to view and play back your Emby Movie and TV Show collection.
diff --git a/resources/language/English/strings.xml b/resources/language/English/strings.xml
index 645936c..6624f61 100644
--- a/resources/language/English/strings.xml
+++ b/resources/language/English/strings.xml
@@ -37,7 +37,7 @@
This item is not playable
Error
EmbyCon service is not running
- Please restart XBMC
+ Please restart Kodi
Skin does not support setting views
Select item action (Requires Restart)
diff --git a/resources/lib/clientinfo.py b/resources/lib/clientinfo.py
index e7ea48b..ee3f37c 100644
--- a/resources/lib/clientinfo.py
+++ b/resources/lib/clientinfo.py
@@ -1,3 +1,5 @@
+# Gnu General Public License - see LICENSE.TXT
+
from uuid import uuid4 as uuid4
import xbmcaddon
import xbmc
diff --git a/resources/lib/datamanager.py b/resources/lib/datamanager.py
index 55e5af3..c3ec3e7 100644
--- a/resources/lib/datamanager.py
+++ b/resources/lib/datamanager.py
@@ -1,3 +1,5 @@
+# Gnu General Public License - see LICENSE.TXT
+
import hashlib
import os
import threading
diff --git a/resources/lib/downloadutils.py b/resources/lib/downloadutils.py
index ac0432e..9e25084 100644
--- a/resources/lib/downloadutils.py
+++ b/resources/lib/downloadutils.py
@@ -1,3 +1,5 @@
+# Gnu General Public License - see LICENSE.TXT
+
import xbmc
import xbmcgui
import xbmcaddon
diff --git a/resources/lib/functions.py b/resources/lib/functions.py
index cb2f79e..74d1d09 100644
--- a/resources/lib/functions.py
+++ b/resources/lib/functions.py
@@ -1,23 +1,4 @@
-'''
- @license : Gnu General Public License - see LICENSE.TXT
-
- This is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 2 of the License, or
- (at your option) any later version.
-
- This is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with software. If not, see .
-
- Thanks to Hippojay for the PleXBMC plugin this is derived from
- This software is derived form the XBMB3C addon
-
-'''
+# Gnu General Public License - see LICENSE.TXT
import urllib
import re
@@ -38,13 +19,14 @@ import xbmcaddon
import xbmc
from downloadutils import DownloadUtils
-from utils import PlayUtils
+from utils import PlayUtils, getDetailsString
from clientinfo import ClientInformation
from datamanager import DataManager
from views import DefaultViews, loadSkinDefaults
from server_detect import checkServer
from resume_dialog import ResumeDialog
from simple_logging import SimpleLogging
+from menu_functions import displaySections, showMovieAlphaList, showGenreList
__settings__ = xbmcaddon.Addon(id='plugin.video.embycon')
__addon__ = xbmcaddon.Addon(id='plugin.video.embycon')
@@ -164,8 +146,6 @@ def mainEntryPoint():
# displaySections(pluginhandle)
if mode == "GET_CONTENT":
getContent(param_url, pluginhandle)
- elif mode == "PLAY":
- PLAY(param_url, pluginhandle)
else:
displaySections()
@@ -203,112 +183,6 @@ def mainEntryPoint():
f.close()
log.info("===== EmbyCon FINISHED =====")
-
-def getCollections(detailsString):
- log.info("== ENTER: getCollections ==")
-
- server = __settings__.getSetting('ipaddress') + ":" + __settings__.getSetting('port')
-
- userid = downloadUtils.getUserId()
-
- if(userid == None or len(userid) == 0):
- return []
-
- try:
- jsonData = downloadUtils.downloadUrl(server + "/emby/Users/" + userid + "/Items/Root?format=json")
- except Exception, msg:
- error = "Get connect : " + str(msg)
- log.error(error)
- return []
-
- log.debug("jsonData : " + jsonData)
- result = json.loads(jsonData)
-
- parentid = result.get("Id")
- log.info("parentid : " + parentid)
-
- htmlpath = ("http://%s/emby/Users/" % server)
- jsonData = downloadUtils.downloadUrl(htmlpath + userid + "/items?ParentId=" + parentid + "&Sortby=SortName&format=json")
- log.debug("jsonData : " + jsonData)
- collections=[]
-
- result = []
- try:
- result = json.loads(jsonData)
- result = result.get("Items")
- except Exception as error:
- log.error("Error parsing user collection: " + str(error))
-
- for item in result:
- item_name = (item.get("Name")).encode('utf-8')
-
- collections.append({
- 'title': item_name,
- 'address': server,
- 'thumbnail': downloadUtils.getArtwork(item,"Primary"),
- 'path': ('/emby/Users/' + userid +
- '/items?ParentId=' + item.get("Id") +
- '&IsVirtualUnaired=false&IsMissing=False&Fields=' + detailsString +
- '&CollapseBoxSetItems=true&ImageTypeLimit=1&format=json')})
-
- log.info("Title: " + item_name)
-
- # Add standard nodes
- item_data = {}
- item_data['address'] = server
- item_data['title'] = "All Movies"
- item_data['path'] = '/emby/Users/' + userid + '/Items?Fields=' + detailsString + '&Recursive=true&IncludeItemTypes=Movie&CollapseBoxSetItems=true&ImageTypeLimit=1&format=json'
- collections.append(item_data)
-
- item_data = {}
- item_data['address'] = server
- item_data['title'] = "BoxSets"
- item_data['path'] = '/emby/Users/' + userid + '/Items?Recursive=true&Fields=' + detailsString + '&IncludeItemTypes=BoxSet&ImageTypeLimit=1&format=json'
- collections.append(item_data)
-
- item_data = {}
- item_data['address'] = server
- item_data['title'] = "All TV"
- item_data['path'] = '/emby/Users/' + userid + '/Items?Fields=' + detailsString + '&Recursive=true&IncludeItemTypes=Series&ImageTypeLimit=1&format=json'
- collections.append(item_data)
-
- item_data = {}
- item_data['address'] = server
- item_data['title'] = "Recently Added Movies"
- item_data['path'] = '/emby/Users/' + userid + '/Items?Limit=' + '20' + '&Recursive=true&SortBy=DateCreated&Fields=' + detailsString + '&SortOrder=Descending&Filters=IsUnplayed,IsNotFolder&IncludeItemTypes=Movie&ImageTypeLimit=1&format=json'
- collections.append(item_data)
-
- item_data = {}
- item_data['address'] = server
- item_data['title'] = "Recently Added Episodes"
- item_data['path'] = '/emby/Users/' + userid + '/Items?Limit=' + '20' + '&Recursive=true&SortBy=DateCreated&Fields=' + detailsString + '&SortOrder=Descending&Filters=IsUnplayed,IsNotFolder&IsVirtualUnaired=false&IsMissing=False&IncludeItemTypes=Episode&ImageTypeLimit=1&format=json'
- collections.append(item_data)
-
- item_data = {}
- item_data['address'] = server
- item_data['title'] = "In Progress Movies"
- item_data['path'] = '/emby/Users/' + userid + '/Items?Limit=' + '20' + '&Recursive=true&Fields=' + detailsString + '&Filters=IsResumable&IncludeItemTypes=Movie&ImageTypeLimit=1&format=json'
- collections.append(item_data)
-
- item_data = {}
- item_data['address'] = server
- item_data['title'] = "In Progress Episodes"
- item_data['path'] = '/emby/Users/' + userid + '/Items?Limit=' + '20' + '&Recursive=true&Fields=' + detailsString + '&Filters=IsResumable&IncludeItemTypes=Episode&ImageTypeLimit=1&format=json'
- collections.append(item_data)
-
- item_data = {}
- item_data['address'] = server
- item_data['title'] = "Next Episodes"
- item_data['path'] = '/emby/Shows/NextUp/?Userid=' + userid + '&Limit=' + '20' + '&Recursive=true&Fields=' + detailsString + '&Filters=IsUnplayed,IsNotFolder&IsVirtualUnaired=false&IsMissing=False&IncludeItemTypes=Episode&ImageTypeLimit=1&format=json'
- collections.append(item_data)
-
- item_data = {}
- item_data['address'] = server
- item_data['title'] = "Upcoming TV"
- item_data['path'] = '/emby/Users/' + userid + '/Items?Recursive=true&SortBy=PremiereDate&Fields=' + detailsString + '&SortOrder=Ascending&Filters=IsUnplayed&IsVirtualUnaired=true&IsNotFolder&IncludeItemTypes=Episode&ImageTypeLimit=1&format=json'
- collections.append(item_data)
-
- return collections
def markWatched(item_id):
log.info("Mark Item Watched : " + item_id)
@@ -549,210 +423,6 @@ def addContextMenu(details, extraData, folder):
commands.append(("Emby: Delete", "XBMC.RunScript(" + scriptToRun + ", " + argsToPass + ")"))
return(commands)
-
-def getDetailsString():
- detailsString = "EpisodeCount,SeasonCount,Path,Genres,Studios,CumulativeRunTimeTicks,MediaStreams,Overview"
- #detailsString = "EpisodeCount,SeasonCount,Path,Genres,CumulativeRunTimeTicks"
- return detailsString
-
-
-def showGenreList():
- log.info("== ENTER: showGenreList() ==")
-
- server = __settings__.getSetting('ipaddress') + ":" + __settings__.getSetting('port')
- userid = downloadUtils.getUserId()
- detailsString = getDetailsString()
-
- try:
- jsonData = downloadUtils.downloadUrl(server + "/emby/Genres?SortBy=SortName&SortOrder=Ascending&IncludeTypes=Movie&Recursive=true&UserId=" + userid + "&format=json")
- log.info("GENRE_LIST_DATA : " + jsonData)
- except Exception, msg:
- error = "Get connect : " + str(msg)
- log.error(error)
-
- result = json.loads(jsonData)
- result = result.get("Items")
-
- collections = []
-
- for genre in result:
- item_data = {}
- item_data['address'] = server
- item_data['title'] = genre.get("Name")
- item_data['thumbnail'] = downloadUtils.getArtwork(genre, "Thumb")
- item_data['path'] = '/emby/Users/' + userid + '/Items?Fields=' + detailsString + '&Recursive=true&GenreIds=' + genre.get("Id") + '&IncludeItemTypes=Movie&CollapseBoxSetItems=true&ImageTypeLimit=1&format=json'
- collections.append(item_data)
-
- for collection in collections:
- url = sys.argv[0] + "?url=" + urllib.quote('http://%s%s' % (collection['address'], collection['path'])) + "&mode=GET_CONTENT"
- log.info("addMenuDirectoryItem: " + collection.get('title', 'Unknown') + " " + str(url))
- addMenuDirectoryItem(collection.get('title', 'Unknown'), url, thumbnail=collection.get("thumbnail"))
-
- xbmcplugin.endOfDirectory(int(sys.argv[1]))
-
-
-def showMovieAlphaList():
- log.info("== ENTER: showMovieAlphaList() ==")
-
- server = __settings__.getSetting('ipaddress') + ":" + __settings__.getSetting('port')
- userid = downloadUtils.getUserId()
- detailsString = getDetailsString()
-
- collections = []
-
- item_data = {}
- item_data['address'] = server
- item_data['title'] = "#"
- item_data['path'] = '/emby/Users/' + userid + '/Items?Fields=' + detailsString + '&Recursive=true&NameLessThan=A&IncludeItemTypes=Movie&CollapseBoxSetItems=true&ImageTypeLimit=1&format=json'
- collections.append(item_data)
-
- alphaList = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "Y", "Z"]
-
- for alphaName in alphaList:
- item_data = {}
- item_data['address'] = server
- item_data['title'] = alphaName
- item_data['path'] = '/emby/Users/' + userid + '/Items?Fields=' + detailsString + '&Recursive=true&NameStartsWith=' + alphaName + '&IncludeItemTypes=Movie&CollapseBoxSetItems=true&ImageTypeLimit=1&format=json'
- collections.append(item_data)
-
- for collection in collections:
- url = sys.argv[0] + "?url=" + urllib.quote('http://%s%s' % (collection['address'], collection['path'])) + "&mode=GET_CONTENT"
- log.info("addMenuDirectoryItem: " + collection.get('title', 'Unknown') + " " + str(url))
- addMenuDirectoryItem(collection.get('title', 'Unknown'), url)
-
- xbmcplugin.endOfDirectory(int(sys.argv[1]))
-
-def displaySections():
- log.info("== ENTER: displaySections() ==")
- xbmcplugin.setContent(int(sys.argv[1]), 'files')
-
- # Add collections
- detailsString = getDetailsString()
- collections = getCollections(detailsString)
- for collection in collections:
- url = sys.argv[0] + "?url=" + urllib.quote('http://%s%s' % (collection['address'], collection['path'])) + "&mode=GET_CONTENT"
- log.info("addMenuDirectoryItem: " + collection.get('title', 'Unknown') + " " + str(url))
- addMenuDirectoryItem(collection.get('title', 'Unknown'), url, thumbnail=collection.get("thumbnail"))
-
- addMenuDirectoryItem("Movies (Genre)", "plugin://plugin.video.embycon/?mode=MOVIE_GENRA")
- addMenuDirectoryItem("Movies (A-Z)", "plugin://plugin.video.embycon/?mode=MOVIE_ALPHA")
- addMenuDirectoryItem("Change User", "plugin://plugin.video.embycon/?mode=CHANGE_USER")
- addMenuDirectoryItem("Show Settings", "plugin://plugin.video.embycon/?mode=SHOW_SETTINGS")
- addMenuDirectoryItem("Set Default Views", "plugin://plugin.video.embycon/?mode=SET_DEFAULT_VIEWS")
-
- xbmcplugin.endOfDirectory(int(sys.argv[1]))
-
-def addMenuDirectoryItem(label, path, folder=True, thumbnail=None):
- li = xbmcgui.ListItem(label, path=path, thumbnailImage=thumbnail)
- li.setThumbnailImage(thumbnail)
- #li.setThumbnailImage("special://home/addons/plugin.video.emby/icon.png")
- #li.setArt({"fanart":"special://home/addons/plugin.video.emby/fanart.jpg"})
- #li.setArt({"landscape":"special://home/addons/plugin.video.emby/fanart.jpg"})
- xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=path, listitem=li, isFolder=folder)
-
-def remove_html_tags( data ):
- p = re.compile(r'<.*?>')
- return p.sub('', data)
-
-def PLAY( url, handle ):
- log.info("== ENTER: PLAY ==")
-
- #playData = json.loads(url)
-
- url=urllib.unquote(url)
-
- urlParts = url.split(',;')
- log.info("PLAY ACTION URL PARTS : " + str(urlParts))
- server = urlParts[0]
- id = urlParts[1]
- autoResume = 0
-
- if(len(urlParts) > 2):
- autoResume = int(urlParts[2])
- log.info("PLAY ACTION URL AUTO RESUME : " + str(autoResume))
-
- ip,port = server.split(':')
- userid = downloadUtils.getUserId()
- seekTime = 0
- resume = 0
-
- id = urlParts[1]
- jsonData = downloadUtils.downloadUrl("http://" + server + "/emby/Users/" + userid + "/Items/" + id + "?format=json", suppress=False, popup=1 )
- result = json.loads(jsonData)
-
- if(autoResume != 0):
- if(autoResume == -1):
- resume_result = 1
- else:
- resume_result = 0
- seekTime = (autoResume / 1000) / 10000
- else:
- userData = result.get("UserData")
- resume_result = 0
-
- if userData.get("PlaybackPositionTicks") != 0:
- reasonableTicks = int(userData.get("PlaybackPositionTicks")) / 1000
- seekTime = reasonableTicks / 10000
- displayTime = str(timedelta(seconds=seekTime))
-
- resumeDialog = ResumeDialog("ResumeDialog.xml", __cwd__, "default", "720p")
- resumeDialog.setResumeTime("Resume from " + displayTime)
- resumeDialog.doModal()
- resume_result = resumeDialog.getResumeAction()
- del resumeDialog
-
- log.info("Resume Dialog Result: " + str(resume_result))
-
- if resume_result == -1:
- return
-
- #playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO)
- #playlist.clear()
-
- playurl = PlayUtils().getPlayUrl(server, id, result)
- log.info("Play URL: " + playurl)
- thumbPath = downloadUtils.getArtwork(result, "Primary")
- listItem = xbmcgui.ListItem(path=playurl, iconImage=thumbPath, thumbnailImage=thumbPath)
-
- setListItemProps(server, id, listItem, result)
-
- # Can not play virtual items
- if (result.get("LocationType") == "Virtual"):
- xbmcgui.Dialog().ok(__language__(30128), __language__(30129))
- return
-
- # set the current playing item id
- WINDOW = xbmcgui.Window(10000)
- WINDOW.setProperty("item_id", id)
-
- #playlist.add(playurl, listItem)
-
- #xbmc.Player().play(playlist)
-
- #xbmc.Player().play(playurl, listItem)
-
- xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, listItem)
-
- #Set a loop to wait for positive confirmation of playback
- count = 0
- while not xbmc.Player().isPlaying():
- log.info( "Not playing yet...sleep for 1 sec")
- count = count + 1
- if count >= 10:
- return
- else:
- time.sleep(1)
-
- if resume_result == 0:
- jumpBackSec = int(__settings__.getSetting("resumeJumpBack"))
- seekToTime = seekTime - jumpBackSec
- while xbmc.Player().getTime() < (seekToTime - 5):
- xbmc.Player().pause
- xbmc.sleep(100)
- xbmc.Player().seekTime(seekToTime)
- xbmc.sleep(100)
- xbmc.Player().play()
- return
def setListItemProps(server, id, listItem, result):
@@ -781,29 +451,31 @@ def setListItemProps(server, id, listItem, result):
listItem.setInfo( "Video", infoLabels=details )
return
-
-def get_params( paramstring ):
+
+
+def get_params(paramstring):
log.debug("Parameter string: " + paramstring)
- param={}
+ param = {}
if len(paramstring) >= 2:
- params=paramstring
+ params = paramstring
- if params[0] == "?":
- cleanedparams=params[1:]
- else:
- cleanedparams=params
+ if params[0] == "?":
+ cleanedparams = params[1:]
+ else:
+ cleanedparams = params
- if (params[len(params)-1]=='/'):
- params=params[0:len(params)-2]
+ if (params[len(params) - 1] == '/'):
+ params = params[0:len(params) - 2]
+
+ pairsofparams = cleanedparams.split('&')
+ for i in range(len(pairsofparams)):
+ splitparams = {}
+ splitparams = pairsofparams[i].split('=')
+ if (len(splitparams)) == 2:
+ param[splitparams[0]] = splitparams[1]
+ elif (len(splitparams)) == 3:
+ param[splitparams[0]] = splitparams[1] + "=" + splitparams[2]
- pairsofparams=cleanedparams.split('&')
- for i in range(len(pairsofparams)):
- splitparams={}
- splitparams=pairsofparams[i].split('=')
- if (len(splitparams))==2:
- param[splitparams[0]]=splitparams[1]
- elif (len(splitparams))==3:
- param[splitparams[0]]=splitparams[1]+"="+splitparams[2]
log.debug("EmbyCon -> Detected parameters: " + str(param))
return param
@@ -856,9 +528,6 @@ def getContent(url, pluginhandle):
return
-def loadJasonData(jsonData):
- return json.loads(jsonData)
-
def processDirectory(url, results, progress, pluginhandle):
cast = ['None']
log.info("== ENTER: processDirectory ==")
@@ -1139,140 +808,15 @@ def processDirectory(url, results, progress, pluginhandle):
return dirItems, viewType
def getServerFromURL( url ):
- '''
- Simply split the URL up and get the server portion, sans port
- @ input: url, woth or without protocol
- @ return: the URL server
- '''
if url[0:4] == "http":
return url.split('/')[2]
else:
return url.split('/')[0]
-def getLinkURL( url, pathData, server ):
- '''
- Investigate the passed URL and determine what is required to
- turn it into a usable URL
- @ input: url, XML data and PM server address
- @ return: Usable http URL
- '''
- log.info("== ENTER: getLinkURL ==")
- path = pathData.get('key','')
- log.info("Path is: " + path)
-
- if path == '':
- log.error("Empty Path")
- return
-
- #If key starts with http, then return it
- if path[0:4] == "http":
- log.info("Detected http link")
- return path
-
- #If key starts with a / then prefix with server address
- elif path[0] == '/':
- log.info("Detected base path link")
- return 'http://%s%s' % ( server, path )
-
- elif path[0:5] == "rtmp:":
- log.info("Detected link")
- return path
-
- #Any thing else is assumed to be a relative path and is built on existing url
- else:
- log.info("Detected relative link")
- return "%s/%s" % ( url, path )
-
- return url
-
def setArt(list, name, path):
list.setProperty(name, path)
list.setArt({name:path})
return list
-
-def getXbmcVersion():
- version = 0.0
- jsonData = xbmc.executeJSONRPC('{ "jsonrpc": "2.0", "method": "Application.GetProperties", "params": {"properties": ["version", "name"]}, "id": 1 }')
-
- result = json.loads(jsonData)
-
- try:
- result = result.get("result")
- versionData = result.get("version")
- version = float(str(versionData.get("major")) + "." + str(versionData.get("minor")))
- log.info("Version : " + str(version) + " - " + str(versionData))
- except:
- version = 0.0
- log.error("Version Error : RAW Version Data : " + str(result))
-
- return version
-
-def getCastList(pluginName, handle, params):
-
- log.info("EmbyCon Returning Cast List")
-
- port = __settings__.getSetting('port')
- host = __settings__.getSetting('ipaddress')
- server = host + ":" + port
- userid = downloadUtils.getUserId()
- seekTime = 0
- resume = 0
-
- # get the cast list for an item
- jsonData = downloadUtils.downloadUrl("http://" + server + "/emby/Users/" + userid + "/Items/" + params.get("id") + "?format=json", suppress=False, popup=1 )
- log.debug("CastList(Items) jsonData: " + jsonData)
- result = json.loads(jsonData)
-
- people = result.get("People")
-
- if(people == None):
- return
-
- listItems = []
-
- for person in people:
-
- displayName = person.get("Name")
- if(person.get("Role") != None):
- displayName = displayName + " (" + person.get("Role") + ")"
-
- tag = person.get("PrimaryImageTag")
- id = person.get("Id")
-
- baseName = person.get("Name")
- #urllib.quote(baseName)
- baseName = baseName.replace(" ", "+")
- baseName = baseName.replace("&", "_")
- baseName = baseName.replace("?", "_")
- baseName = baseName.replace("=", "_")
-
- if(tag != None):
- thumbPath = downloadUtils.imageUrl(id, "Primary", 0, 400, 400, tag)
- item = xbmcgui.ListItem(label=displayName, iconImage=thumbPath, thumbnailImage=thumbPath)
- else:
- item = xbmcgui.ListItem(label=displayName)
-
- actionUrl = "plugin://plugin.video.embycon?mode=PERSON_DETAILS&name=" + baseName
-
- item.setProperty('IsPlayable', 'false')
- item.setProperty('IsFolder', 'false')
-
- commands = []
- detailsString = getDetailsString()
- url = "http://" + host + ":" + port + "/emby/Users/" + userid + "/Items/?Recursive=True&Person=PERSON_NAME&Fields=" + detailsString + "&format=json"
- url = urllib.quote(url)
- url = url.replace("PERSON_NAME", baseName)
- pluginCastLink = "XBMC.Container.Update(plugin://plugin.video.embycon?mode=GET_CONTENT&url=" + url + ")"
- commands.append(( "Show Other Library Items", pluginCastLink))
- item.addContextMenuItems( commands, True )
-
- itemTupple = (actionUrl, item, False)
- listItems.append(itemTupple)
-
-
- #listItems.sort()
- xbmcplugin.addDirectoryItems(handle, listItems)
- xbmcplugin.endOfDirectory(handle, cacheToDisc=False)
def showSetViews():
log.info("showSetViews Called")
diff --git a/resources/lib/menu_functions.py b/resources/lib/menu_functions.py
new file mode 100644
index 0000000..b239a13
--- /dev/null
+++ b/resources/lib/menu_functions.py
@@ -0,0 +1,228 @@
+# Gnu General Public License - see LICENSE.TXT
+
+import sys
+import json as json
+import urllib
+
+import xbmcplugin
+import xbmcgui
+import xbmcaddon
+import xbmc
+
+from downloadutils import DownloadUtils
+from utils import getDetailsString
+from simple_logging import SimpleLogging
+
+log = SimpleLogging("EmbyCon." + __name__)
+downloadUtils = DownloadUtils()
+
+__settings__ = xbmcaddon.Addon(id='plugin.video.embycon')
+
+def showGenreList():
+ log.info("== ENTER: showGenreList() ==")
+
+ server = __settings__.getSetting('ipaddress') + ":" + __settings__.getSetting('port')
+ userid = downloadUtils.getUserId()
+ detailsString = getDetailsString()
+
+ try:
+ jsonData = downloadUtils.downloadUrl(server + "/emby/Genres?SortBy=SortName&SortOrder=Ascending&IncludeTypes=Movie&Recursive=true&UserId=" + userid + "&format=json")
+ log.info("GENRE_LIST_DATA : " + jsonData)
+ except Exception, msg:
+ error = "Get connect : " + str(msg)
+ log.error(error)
+
+ result = json.loads(jsonData)
+ result = result.get("Items")
+
+ collections = []
+
+ for genre in result:
+ item_data = {}
+ item_data['address'] = server
+ item_data['title'] = genre.get("Name")
+ item_data['thumbnail'] = downloadUtils.getArtwork(genre, "Thumb")
+ item_data['path'] = '/emby/Users/' + userid + '/Items?Fields=' + detailsString + '&Recursive=true&GenreIds=' + genre.get("Id") + '&IncludeItemTypes=Movie&CollapseBoxSetItems=true&ImageTypeLimit=1&format=json'
+ collections.append(item_data)
+
+ for collection in collections:
+ url = sys.argv[0] + "?url=" + urllib.quote('http://%s%s' % (collection['address'], collection['path'])) + "&mode=GET_CONTENT"
+ log.info("addMenuDirectoryItem: " + collection.get('title', 'Unknown') + " " + str(url))
+ addMenuDirectoryItem(collection.get('title', 'Unknown'), url, thumbnail=collection.get("thumbnail"))
+
+ xbmcplugin.endOfDirectory(int(sys.argv[1]))
+
+
+def showMovieAlphaList():
+ log.info("== ENTER: showMovieAlphaList() ==")
+
+ server = __settings__.getSetting('ipaddress') + ":" + __settings__.getSetting('port')
+ userid = downloadUtils.getUserId()
+ detailsString = getDetailsString()
+
+ collections = []
+
+ item_data = {}
+ item_data['address'] = server
+ item_data['title'] = "#"
+ item_data['path'] = '/emby/Users/' + userid + '/Items?Fields=' + detailsString + '&Recursive=true&NameLessThan=A&IncludeItemTypes=Movie&CollapseBoxSetItems=true&ImageTypeLimit=1&format=json'
+ collections.append(item_data)
+
+ alphaList = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "Y", "Z"]
+
+ for alphaName in alphaList:
+ item_data = {}
+ item_data['address'] = server
+ item_data['title'] = alphaName
+ item_data['path'] = '/emby/Users/' + userid + '/Items?Fields=' + detailsString + '&Recursive=true&NameStartsWith=' + alphaName + '&IncludeItemTypes=Movie&CollapseBoxSetItems=true&ImageTypeLimit=1&format=json'
+ collections.append(item_data)
+
+ for collection in collections:
+ url = sys.argv[0] + "?url=" + urllib.quote('http://%s%s' % (collection['address'], collection['path'])) + "&mode=GET_CONTENT"
+ log.info("addMenuDirectoryItem: " + collection.get('title', 'Unknown') + " " + str(url))
+ addMenuDirectoryItem(collection.get('title', 'Unknown'), url)
+
+ xbmcplugin.endOfDirectory(int(sys.argv[1]))
+
+def displaySections():
+ log.info("== ENTER: displaySections() ==")
+ xbmcplugin.setContent(int(sys.argv[1]), 'files')
+
+ # Add collections
+ detailsString = getDetailsString()
+ collections = getCollections(detailsString)
+ for collection in collections:
+ url = sys.argv[0] + "?url=" + urllib.quote('http://%s%s' % (collection['address'], collection['path'])) + "&mode=GET_CONTENT"
+ log.info("addMenuDirectoryItem: " + collection.get('title', 'Unknown') + " " + str(url))
+ addMenuDirectoryItem(collection.get('title', 'Unknown'), url, thumbnail=collection.get("thumbnail"))
+
+ addMenuDirectoryItem("Movies (Genre)", "plugin://plugin.video.embycon/?mode=MOVIE_GENRA")
+ addMenuDirectoryItem("Movies (A-Z)", "plugin://plugin.video.embycon/?mode=MOVIE_ALPHA")
+ addMenuDirectoryItem("Change User", "plugin://plugin.video.embycon/?mode=CHANGE_USER")
+ addMenuDirectoryItem("Show Settings", "plugin://plugin.video.embycon/?mode=SHOW_SETTINGS")
+ addMenuDirectoryItem("Set Default Views", "plugin://plugin.video.embycon/?mode=SET_DEFAULT_VIEWS")
+
+ xbmcplugin.endOfDirectory(int(sys.argv[1]))
+
+def addMenuDirectoryItem(label, path, folder=True, thumbnail=None):
+ li = xbmcgui.ListItem(label, path=path, thumbnailImage=thumbnail)
+ li.setThumbnailImage(thumbnail)
+ #li.setThumbnailImage("special://home/addons/plugin.video.emby/icon.png")
+ #li.setArt({"fanart":"special://home/addons/plugin.video.emby/fanart.jpg"})
+ #li.setArt({"landscape":"special://home/addons/plugin.video.emby/fanart.jpg"})
+ xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=path, listitem=li, isFolder=folder)
+
+def getCollections(detailsString):
+ log.info("== ENTER: getCollections ==")
+
+ server = __settings__.getSetting('ipaddress') + ":" + __settings__.getSetting('port')
+
+ userid = downloadUtils.getUserId()
+ if(userid == None or len(userid) == 0):
+ return []
+
+ try:
+ jsonData = downloadUtils.downloadUrl(server + "/emby/Users/" + userid + "/Items/Root?format=json")
+ except Exception, msg:
+ error = "Get connect : " + str(msg)
+ log.error(error)
+ return []
+
+ log.debug("jsonData : " + jsonData)
+ result = json.loads(jsonData)
+
+ parentid = result.get("Id")
+ log.info("parentid : " + parentid)
+
+ htmlpath = ("http://%s/emby/Users/" % server)
+ jsonData = downloadUtils.downloadUrl(
+ htmlpath + userid + "/items?ParentId=" + parentid + "&Sortby=SortName&format=json")
+ log.debug("jsonData : " + jsonData)
+ collections=[]
+
+ result = []
+ try:
+ result = json.loads(jsonData)
+ result = result.get("Items")
+ except Exception as error:
+ log.error("Error parsing user collection: " + str(error))
+
+ for item in result:
+ item_name = (item.get("Name")).encode('utf-8')
+
+ collections.append({
+ 'title': item_name,
+ 'address': server,
+ 'thumbnail': downloadUtils.getArtwork(item, "Primary"),
+ 'path': ('/emby/Users/' + userid +
+ '/items?ParentId=' + item.get("Id") +
+ '&IsVirtualUnaired=false&IsMissing=False&Fields=' + detailsString +
+ '&CollapseBoxSetItems=true&ImageTypeLimit=1&format=json')})
+
+ log.info("Title: " + item_name)
+
+ # Add standard nodes
+ item_data = {}
+ item_data['address'] = server
+ item_data['title'] = "All Movies"
+ item_data[
+ 'path'] = '/emby/Users/' + userid + '/Items?Fields=' + detailsString + '&Recursive=true&IncludeItemTypes=Movie&CollapseBoxSetItems=true&ImageTypeLimit=1&format=json'
+ collections.append(item_data)
+
+ item_data = {}
+ item_data['address'] = server
+ item_data['title'] = "BoxSets"
+ item_data[
+ 'path'] = '/emby/Users/' + userid + '/Items?Recursive=true&Fields=' + detailsString + '&IncludeItemTypes=BoxSet&ImageTypeLimit=1&format=json'
+ collections.append(item_data)
+
+ item_data = {}
+ item_data['address'] = server
+ item_data['title'] = "All TV"
+ item_data[
+ 'path'] = '/emby/Users/' + userid + '/Items?Fields=' + detailsString + '&Recursive=true&IncludeItemTypes=Series&ImageTypeLimit=1&format=json'
+ collections.append(item_data)
+
+ item_data = {}
+ item_data['address'] = server
+ item_data['title'] = "Recently Added Movies"
+ item_data[
+ 'path'] = '/emby/Users/' + userid + '/Items?Limit=' + '20' + '&Recursive=true&SortBy=DateCreated&Fields=' + detailsString + '&SortOrder=Descending&Filters=IsUnplayed,IsNotFolder&IncludeItemTypes=Movie&ImageTypeLimit=1&format=json'
+ collections.append(item_data)
+
+ item_data = {}
+ item_data['address'] = server
+ item_data['title'] = "Recently Added Episodes"
+ item_data[
+ 'path'] = '/emby/Users/' + userid + '/Items?Limit=' + '20' + '&Recursive=true&SortBy=DateCreated&Fields=' + detailsString + '&SortOrder=Descending&Filters=IsUnplayed,IsNotFolder&IsVirtualUnaired=false&IsMissing=False&IncludeItemTypes=Episode&ImageTypeLimit=1&format=json'
+ collections.append(item_data)
+
+ item_data = {}
+ item_data['address'] = server
+ item_data['title'] = "In Progress Movies"
+ item_data[
+ 'path'] = '/emby/Users/' + userid + '/Items?Limit=' + '20' + '&Recursive=true&Fields=' + detailsString + '&Filters=IsResumable&IncludeItemTypes=Movie&ImageTypeLimit=1&format=json'
+ collections.append(item_data)
+
+ item_data = {}
+ item_data['address'] = server
+ item_data['title'] = "In Progress Episodes"
+ item_data[
+ 'path'] = '/emby/Users/' + userid + '/Items?Limit=' + '20' + '&Recursive=true&Fields=' + detailsString + '&Filters=IsResumable&IncludeItemTypes=Episode&ImageTypeLimit=1&format=json'
+ collections.append(item_data)
+
+ item_data = {}
+ item_data['address'] = server
+ item_data['title'] = "Next Episodes"
+ item_data[
+ 'path'] = '/emby/Shows/NextUp/?Userid=' + userid + '&Limit=' + '20' + '&Recursive=true&Fields=' + detailsString + '&Filters=IsUnplayed,IsNotFolder&IsVirtualUnaired=false&IsMissing=False&IncludeItemTypes=Episode&ImageTypeLimit=1&format=json'
+ collections.append(item_data)
+
+ item_data = {}
+ item_data['address'] = server
+ item_data['title'] = "Upcoming TV"
+ item_data[
+ 'path'] = '/emby/Users/' + userid + '/Items?Recursive=true&SortBy=PremiereDate&Fields=' + detailsString + '&SortOrder=Ascending&Filters=IsUnplayed&IsVirtualUnaired=true&IsNotFolder&IncludeItemTypes=Episode&ImageTypeLimit=1&format=json'
+ collections.append(item_data)
+
+ return collections
\ No newline at end of file
diff --git a/resources/lib/resume_dialog.py b/resources/lib/resume_dialog.py
index 5acde41..ac9e558 100644
--- a/resources/lib/resume_dialog.py
+++ b/resources/lib/resume_dialog.py
@@ -1,3 +1,4 @@
+# Gnu General Public License - see LICENSE.TXT
import os
import sys
diff --git a/resources/lib/server_detect.py b/resources/lib/server_detect.py
index 8ba5c4d..561ce5e 100644
--- a/resources/lib/server_detect.py
+++ b/resources/lib/server_detect.py
@@ -1,4 +1,4 @@
-
+# Gnu General Public License - see LICENSE.TXT
import socket
import json as json
diff --git a/resources/lib/simple_logging.py b/resources/lib/simple_logging.py
index d93b2e9..ddf6a8a 100644
--- a/resources/lib/simple_logging.py
+++ b/resources/lib/simple_logging.py
@@ -1,3 +1,4 @@
+# Gnu General Public License - see LICENSE.TXT
import xbmc
import xbmcaddon
diff --git a/resources/lib/utils.py b/resources/lib/utils.py
index a04c4f3..d20ddba 100644
--- a/resources/lib/utils.py
+++ b/resources/lib/utils.py
@@ -1,6 +1,4 @@
-#################################################################################################
-# utils class
-#################################################################################################
+# Gnu General Public License - see LICENSE.TXT
import xbmc
import xbmcgui
@@ -68,3 +66,26 @@ class PlayUtils():
log.info("Playback URL: " + playurl)
return playurl.encode('utf-8')
+
+def getKodiVersion():
+ version = 0.0
+ jsonData = xbmc.executeJSONRPC(
+ '{ "jsonrpc": "2.0", "method": "Application.GetProperties", "params": {"properties": ["version", "name"]}, "id": 1 }')
+
+ result = json.loads(jsonData)
+
+ try:
+ result = result.get("result")
+ versionData = result.get("version")
+ version = float(str(versionData.get("major")) + "." + str(versionData.get("minor")))
+ log.info("Version : " + str(version) + " - " + str(versionData))
+ except:
+ version = 0.0
+ log.error("Version Error : RAW Version Data : " + str(result))
+
+ return version
+
+def getDetailsString():
+ detailsString = "EpisodeCount,SeasonCount,Path,Genres,Studios,CumulativeRunTimeTicks,MediaStreams,Overview"
+ #detailsString = "EpisodeCount,SeasonCount,Path,Genres,CumulativeRunTimeTicks"
+ return detailsString
diff --git a/resources/lib/views.py b/resources/lib/views.py
index e4e0a22..b0c6cf9 100644
--- a/resources/lib/views.py
+++ b/resources/lib/views.py
@@ -1,3 +1,4 @@
+# Gnu General Public License - see LICENSE.TXT
import os
import xml.etree.ElementTree as etree
diff --git a/resources/lib/websocketclient.py b/resources/lib/websocketclient.py
index dad44d0..74ba7d6 100644
--- a/resources/lib/websocketclient.py
+++ b/resources/lib/websocketclient.py
@@ -1,6 +1,4 @@
-#################################################################################################
-# WebSocket Client thread
-#################################################################################################
+# Gnu General Public License - see LICENSE.TXT
import xbmc
import xbmcgui
diff --git a/resources/settings.xml b/resources/settings.xml
index a7a0cc8..c6d2a64 100644
--- a/resources/settings.xml
+++ b/resources/settings.xml
@@ -11,7 +11,7 @@
-
+