changes to comply with Kodi repo rules
This commit is contained in:
@@ -18,7 +18,7 @@
|
||||
<forum>https://emby.media/community/index.php?/topic/46651-embycon/</forum>
|
||||
<website>https://emby.media/community/index.php?/topic/46651-embycon/</website>
|
||||
<source>https://github.com/faush01/plugin.video.embycon</source>
|
||||
<summary lang="en">View and play your Emby media library.</summary>
|
||||
<description lang="en">An addon to allow you to view and playback your Emby (www.emby.media) Movie and TV Show collection.</description>
|
||||
<summary lang="en_GB">View and play your Emby media library.</summary>
|
||||
<description lang="en_GB">An addon to allow you to view and playback your Emby (www.emby.media) Movie and TV Show collection.</description>
|
||||
</extension>
|
||||
</addon>
|
||||
|
||||
13
default.py
13
default.py
@@ -2,21 +2,12 @@
|
||||
|
||||
from resources.lib.simple_logging import SimpleLogging
|
||||
from resources.lib.functions import mainEntryPoint
|
||||
from resources.lib.ga_client import GoogleAnalytics, log_error
|
||||
|
||||
log = SimpleLogging('default')
|
||||
|
||||
log.info("About to enter mainEntryPoint()")
|
||||
log.debug("About to enter mainEntryPoint()")
|
||||
|
||||
try:
|
||||
mainEntryPoint()
|
||||
except Exception as error:
|
||||
ga = GoogleAnalytics()
|
||||
err_strings = ga.formatException()
|
||||
ga.sendEventData("Exception", err_strings[0], err_strings[1])
|
||||
log.error(str(error))
|
||||
log.error(str(err_strings))
|
||||
raise
|
||||
mainEntryPoint()
|
||||
|
||||
# clear done and exit.
|
||||
# sys.modules.clear()
|
||||
|
||||
BIN
icon.png
BIN
icon.png
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 29 KiB |
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"skin.estuary" : {"None" : -1, "List" : 50, "Poster" : 51, "IconWall" : 52, "Shift" : 53, "InfoWall" : 54, "WideList" : 55, "Wall" : 500, "Banner" : 501, "FanArt" : 502},
|
||||
"skin.confluence" : {"None" : -1, "List" : 50, "Big list" : 51, "Thumbnail" : 500, "Poster" : 500, "Fanart" : 508, "Media info" : 504, "Media info 2" : 503, "Media info 3" : 515, "Wide" : 505},
|
||||
"skin.titan" : {"None" : -1, "List" : 50, "Big list" : 51, "Horizontal Panel" : 52, "Panel Details" : 53, "Panel" : 54, "Banner List" : 55, "Banner Plex" : 56, "Big Panel" : 57, "Large Poster" : 58, "Big Panel Details" : 59, "Landscape" : 501, "Landscape Single" : 502, "Logos" : 503, "Big List 2" : 504, "Landscape Details" : 505, "Extended List" : 506, "Fan Art" : 507, "Single Poster" : 508, "Panel Square" : 509, "Panel Square Details" : 510, "Thumbs" : 511, "Thumbs Details" : 512, "Poster Row" : 513, "Poster Shift" : 514, "Low LIst" : 515, "Slim List" : 516, "Cards" : 517, "Wide" : 518, "Big Panel Wall" : 519, "Panel Wall" : 520, "Panel Low" : 521, "Right List" : 522, "Netflix" : 523, "Showcase" : 524}
|
||||
}
|
||||
@@ -26,10 +26,6 @@ msgctxt "#30003"
|
||||
msgid "Verify HTTPS Certificate: "
|
||||
msgstr ""
|
||||
|
||||
msgctxt "#30004"
|
||||
msgid "Log Level: "
|
||||
msgstr ""
|
||||
|
||||
msgctxt "#30005"
|
||||
msgid "Username: "
|
||||
msgstr ""
|
||||
@@ -422,10 +418,6 @@ msgctxt "#30254"
|
||||
msgid "Show Settings"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "#30255"
|
||||
msgid "Set Default Views"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "#30256"
|
||||
msgid "Movies - All"
|
||||
msgstr ""
|
||||
@@ -550,6 +542,3 @@ msgctxt "#30286"
|
||||
msgid "Movies - Unwatched"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "#30287"
|
||||
msgid "Log Errors and Anonymous Metrics"
|
||||
msgstr ""
|
||||
|
||||
@@ -22,18 +22,18 @@ class ClientInformation():
|
||||
return client_id
|
||||
|
||||
emby_guid_path = xbmc.translatePath("special://temp/embycon_guid").decode('utf-8')
|
||||
log.info("emby_guid_path: " + emby_guid_path)
|
||||
log.debug("emby_guid_path: " + emby_guid_path)
|
||||
guid = xbmcvfs.File(emby_guid_path)
|
||||
client_id = guid.read()
|
||||
guid.close()
|
||||
|
||||
if not client_id:
|
||||
client_id = str("%012X" % uuid4())
|
||||
log.info("Generating a new guid: " + client_id)
|
||||
log.debug("Generating a new guid: " + client_id)
|
||||
guid = xbmcvfs.File(emby_guid_path, 'w')
|
||||
guid.write(client_id)
|
||||
guid.close()
|
||||
log.info("emby_guid_path (NEW): " + client_id)
|
||||
log.debug("emby_guid_path (NEW): " + client_id)
|
||||
|
||||
WINDOW.setProperty("client_id", client_id)
|
||||
return client_id
|
||||
|
||||
@@ -23,7 +23,7 @@ class DataManager():
|
||||
canRefreshNow = False
|
||||
|
||||
def __init__(self, *args):
|
||||
log.info("DataManager __init__")
|
||||
log.debug("DataManager __init__")
|
||||
|
||||
def getCacheValidatorFromData(self, result):
|
||||
key = 'Items'
|
||||
@@ -65,10 +65,10 @@ class DataManager():
|
||||
|
||||
if use_cache_system == False:
|
||||
# dont use cache system at all, just get the result and return
|
||||
log.info("GetContent - Not using cache system")
|
||||
log.debug("GetContent - Not using cache system")
|
||||
jsonData = DownloadUtils().downloadUrl(url, suppress=False, popup=1)
|
||||
result = self.loadJasonData(jsonData)
|
||||
log.info("Returning Loaded Result")
|
||||
log.debug("Returning Loaded Result")
|
||||
return result
|
||||
|
||||
# first get the url hash
|
||||
@@ -83,7 +83,7 @@ class DataManager():
|
||||
os.makedirs(os.path.join(__addondir__, "cache"))
|
||||
cacheDataPath = os.path.join(__addondir__, "cache", urlHash)
|
||||
|
||||
log.info("Cache_Data_Manager:" + cacheDataPath)
|
||||
log.debug("Cache_Data_Manager:" + cacheDataPath)
|
||||
|
||||
# are we forcing a reload
|
||||
WINDOW = HomeWindow()
|
||||
@@ -93,7 +93,7 @@ class DataManager():
|
||||
if os.path.exists(cacheDataPath) and not force_data_reload:
|
||||
# load data from cache if it is available and trigger a background
|
||||
# verification process to test cache validity
|
||||
log.info("Loading Cached File")
|
||||
log.debug("Loading Cached File")
|
||||
cachedfie = open(cacheDataPath, 'r')
|
||||
jsonData = cachedfie.read()
|
||||
cachedfie.close()
|
||||
@@ -107,18 +107,18 @@ class DataManager():
|
||||
actionThread.setCacheData(self)
|
||||
actionThread.start()
|
||||
|
||||
log.info("Returning Cached Result")
|
||||
log.debug("Returning Cached Result")
|
||||
return result
|
||||
else:
|
||||
# no cache data so load the url and save it
|
||||
jsonData = DownloadUtils().downloadUrl(url, suppress=False, popup=1)
|
||||
log.info("Loading URL and saving to cache")
|
||||
log.debug("Loading URL and saving to cache")
|
||||
cachedfie = open(cacheDataPath, 'w')
|
||||
cachedfie.write(jsonData)
|
||||
cachedfie.close()
|
||||
result = self.loadJasonData(jsonData)
|
||||
self.cacheManagerFinished = True
|
||||
log.info("Returning Loaded Result")
|
||||
log.debug("Returning Loaded Result")
|
||||
return result
|
||||
|
||||
|
||||
@@ -133,19 +133,19 @@ class CacheManagerThread(threading.Thread):
|
||||
|
||||
def run(self):
|
||||
|
||||
log.info("CacheManagerThread Started")
|
||||
log.debug("CacheManagerThread Started")
|
||||
|
||||
cacheValidatorString = self.dataManager.getCacheValidatorFromData(self.dataManager.cacheDataResult)
|
||||
log.info("Cache Validator String (" + cacheValidatorString + ")")
|
||||
log.debug("Cache Validator String (" + cacheValidatorString + ")")
|
||||
|
||||
jsonData = DownloadUtils().downloadUrl(self.dataManager.dataUrl, suppress=False, popup=1)
|
||||
loadedResult = self.dataManager.loadJasonData(jsonData)
|
||||
loadedValidatorString = self.dataManager.getCacheValidatorFromData(loadedResult)
|
||||
log.info("Loaded Validator String (" + loadedValidatorString + ")")
|
||||
log.debug("Loaded Validator String (" + loadedValidatorString + ")")
|
||||
|
||||
# if they dont match then save the data and trigger a content reload
|
||||
if (cacheValidatorString != loadedValidatorString):
|
||||
log.info("CacheManagerThread Saving new cache data and reloading container")
|
||||
log.debug("CacheManagerThread Saving new cache data and reloading container")
|
||||
cachedfie = open(self.dataManager.cacheDataPath, 'w')
|
||||
cachedfie.write(jsonData)
|
||||
cachedfie.close()
|
||||
@@ -157,7 +157,7 @@ class CacheManagerThread(threading.Thread):
|
||||
xbmc.sleep(100)
|
||||
loops = loops + 1
|
||||
|
||||
log.info("Sending container refresh (" + str(loops) + ")")
|
||||
log.debug("Sending container refresh (" + str(loops) + ")")
|
||||
xbmc.executebuiltin("Container.Refresh")
|
||||
|
||||
log.info("CacheManagerThread Exited")
|
||||
log.debug("CacheManagerThread Exited")
|
||||
|
||||
@@ -129,7 +129,7 @@ class DownloadUtils():
|
||||
userid = WINDOW.getProperty("userid")
|
||||
|
||||
if (userid != None and userid != ""):
|
||||
log.info("EmbyCon DownloadUtils -> Returning saved UserID : " + userid)
|
||||
log.debug("EmbyCon DownloadUtils -> Returning saved UserID : " + userid)
|
||||
return userid
|
||||
|
||||
settings = xbmcaddon.Addon('plugin.video.embycon')
|
||||
@@ -137,7 +137,7 @@ class DownloadUtils():
|
||||
|
||||
if not userName:
|
||||
return ""
|
||||
log.info("Looking for user name: " + userName)
|
||||
log.debug("Looking for user name: " + userName)
|
||||
|
||||
jsonData = None
|
||||
try:
|
||||
@@ -147,30 +147,30 @@ class DownloadUtils():
|
||||
log.error(error)
|
||||
return ""
|
||||
|
||||
log.info("GETUSER_JSONDATA_01:" + str(jsonData))
|
||||
log.debug("GETUSER_JSONDATA_01:" + str(jsonData))
|
||||
|
||||
result = []
|
||||
|
||||
try:
|
||||
result = json.loads(jsonData)
|
||||
except Exception, e:
|
||||
log.info("jsonload : " + str(e) + " (" + jsonData + ")")
|
||||
log.debug("jsonload : " + str(e) + " (" + jsonData + ")")
|
||||
return ""
|
||||
|
||||
if result is None:
|
||||
return ""
|
||||
|
||||
log.info("GETUSER_JSONDATA_02:" + str(result))
|
||||
log.debug("GETUSER_JSONDATA_02:" + str(result))
|
||||
|
||||
userid = ""
|
||||
secure = False
|
||||
for user in result:
|
||||
if (user.get("Name") == userName):
|
||||
userid = user.get("Id")
|
||||
log.info("Username Found:" + user.get("Name"))
|
||||
log.debug("Username Found:" + user.get("Name"))
|
||||
if (user.get("HasPassword") == True):
|
||||
secure = True
|
||||
log.info("Username Is Secure (HasPassword=True)")
|
||||
log.debug("Username Is Secure (HasPassword=True)")
|
||||
break
|
||||
|
||||
if (secure) or (not userid):
|
||||
@@ -184,7 +184,7 @@ class DownloadUtils():
|
||||
if userid == "":
|
||||
xbmcgui.Dialog().ok(self.addon_name, i18n('username_not_found'))
|
||||
|
||||
log.info("userid : " + userid)
|
||||
log.debug("userid : " + userid)
|
||||
|
||||
WINDOW.setProperty("userid", userid)
|
||||
|
||||
@@ -196,7 +196,7 @@ class DownloadUtils():
|
||||
|
||||
token = WINDOW.getProperty("AccessToken")
|
||||
if (token != None and token != ""):
|
||||
log.info("EmbyCon DownloadUtils -> Returning saved AccessToken : " + token)
|
||||
log.debug("EmbyCon DownloadUtils -> Returning saved AccessToken : " + token)
|
||||
return token
|
||||
|
||||
settings = xbmcaddon.Addon('plugin.video.embycon')
|
||||
@@ -233,12 +233,12 @@ class DownloadUtils():
|
||||
pass
|
||||
|
||||
if (accessToken != None):
|
||||
log.info("User Authenticated : " + accessToken)
|
||||
log.debug("User Authenticated : " + accessToken)
|
||||
WINDOW.setProperty("AccessToken", accessToken)
|
||||
WINDOW.setProperty("userid", userid)
|
||||
return accessToken
|
||||
else:
|
||||
log.info("User NOT Authenticated")
|
||||
log.debug("User NOT Authenticated")
|
||||
WINDOW.setProperty("AccessToken", "")
|
||||
WINDOW.setProperty("userid", "")
|
||||
return ""
|
||||
@@ -272,11 +272,11 @@ class DownloadUtils():
|
||||
if (authToken != ""):
|
||||
headers["X-MediaBrowser-Token"] = authToken
|
||||
|
||||
log.info("EmbyCon Authentication Header : " + str(headers))
|
||||
log.debug("EmbyCon Authentication Header : " + str(headers))
|
||||
return headers
|
||||
|
||||
def downloadUrl(self, url, suppress=False, postBody=None, method="GET", popup=0, authenticate=True):
|
||||
log.info("downloadUrl")
|
||||
log.debug("downloadUrl")
|
||||
settings = xbmcaddon.Addon(id='plugin.video.embycon')
|
||||
|
||||
log.debug(url)
|
||||
@@ -303,7 +303,7 @@ class DownloadUtils():
|
||||
server = url.split('/')[serversplit]
|
||||
urlPath = "/" + "/".join(url.split('/')[urlsplit:])
|
||||
|
||||
log.info("DOWNLOAD_URL = " + url)
|
||||
log.debug("DOWNLOAD_URL = " + url)
|
||||
log.debug("server = " + str(server))
|
||||
log.debug("urlPath = " + str(urlPath))
|
||||
|
||||
@@ -329,7 +329,7 @@ class DownloadUtils():
|
||||
conn = httplib.HTTPConnection(server, timeout=40)
|
||||
|
||||
head = self.getAuthHeader(authenticate)
|
||||
log.info("HEADERS : " + str(head))
|
||||
log.debug("HEADERS : " + str(head))
|
||||
|
||||
if (postBody != None):
|
||||
if isinstance(postBody, dict):
|
||||
@@ -339,9 +339,9 @@ class DownloadUtils():
|
||||
content_type = "application/x-www-form-urlencoded"
|
||||
|
||||
head["Content-Type"] = content_type
|
||||
log.info("Content-Type : " + content_type)
|
||||
log.debug("Content-Type : " + content_type)
|
||||
|
||||
log.info("POST DATA : " + postBody)
|
||||
log.debug("POST DATA : " + postBody)
|
||||
conn.request(method=method, url=urlPath, body=postBody, headers=head)
|
||||
else:
|
||||
conn.request(method=method, url=urlPath, headers=head)
|
||||
|
||||
@@ -19,7 +19,6 @@ from utils import getDetailsString, getArt
|
||||
from kodi_utils import HomeWindow
|
||||
from clientinfo import ClientInformation
|
||||
from datamanager import DataManager
|
||||
from views import DefaultViews, loadSkinDefaults
|
||||
from server_detect import checkServer
|
||||
from simple_logging import SimpleLogging
|
||||
from menu_functions import displaySections, showMovieAlphaList, showGenreList, showWidgets, showSearch
|
||||
@@ -40,7 +39,7 @@ dataManager = DataManager()
|
||||
|
||||
|
||||
def mainEntryPoint():
|
||||
log.info("===== EmbyCon START =====")
|
||||
log.debug("===== EmbyCon START =====")
|
||||
|
||||
settings = xbmcaddon.Addon(id='plugin.video.embycon')
|
||||
profile_code = settings.getSetting('profile') == "true"
|
||||
@@ -52,11 +51,11 @@ def mainEntryPoint():
|
||||
pr.enable()
|
||||
|
||||
ADDON_VERSION = ClientInformation().getVersion()
|
||||
log.info("Running Python: " + str(sys.version_info))
|
||||
log.info("Running EmbyCon: " + str(ADDON_VERSION))
|
||||
log.info("Kodi BuildVersion: " + xbmc.getInfoLabel("System.BuildVersion"))
|
||||
log.info("Kodi Version: " + str(kodi_version))
|
||||
log.info("Script argument data: " + str(sys.argv))
|
||||
log.debug("Running Python: " + str(sys.version_info))
|
||||
log.debug("Running EmbyCon: " + str(ADDON_VERSION))
|
||||
log.debug("Kodi BuildVersion: " + xbmc.getInfoLabel("System.BuildVersion"))
|
||||
log.debug("Kodi Version: " + str(kodi_version))
|
||||
log.debug("Script argument data: " + str(sys.argv))
|
||||
|
||||
try:
|
||||
params = get_params(sys.argv[2])
|
||||
@@ -66,7 +65,7 @@ def mainEntryPoint():
|
||||
if (len(params) == 0):
|
||||
home_window = HomeWindow()
|
||||
windowParams = home_window.getProperty("Params")
|
||||
log.info("windowParams : " + windowParams)
|
||||
log.debug("windowParams : " + windowParams)
|
||||
# home_window.clearProperty("Params")
|
||||
if (windowParams):
|
||||
try:
|
||||
@@ -74,7 +73,7 @@ def mainEntryPoint():
|
||||
except:
|
||||
params = {}
|
||||
|
||||
log.info("Script params = " + str(params))
|
||||
log.debug("Script params = " + str(params))
|
||||
|
||||
param_url = params.get('url', None)
|
||||
|
||||
@@ -115,14 +114,12 @@ def mainEntryPoint():
|
||||
__addon__.openSettings()
|
||||
WINDOW = xbmcgui.getCurrentWindowId()
|
||||
if WINDOW == 10000:
|
||||
log.info("Currently in home - refreshing to allow new settings to be taken")
|
||||
log.debug("Currently in home - refreshing to allow new settings to be taken")
|
||||
xbmc.executebuiltin("ActivateWindow(Home)")
|
||||
elif sys.argv[1] == "refresh":
|
||||
home_window = HomeWindow()
|
||||
home_window.setProperty("force_data_reload", "true")
|
||||
xbmc.executebuiltin("Container.Refresh")
|
||||
elif mode == "SET_DEFAULT_VIEWS":
|
||||
showSetViews()
|
||||
elif mode == "WIDGET_CONTENT":
|
||||
getWigetContent(int(sys.argv[1]), params)
|
||||
elif mode == "PARENT_CONTENT":
|
||||
@@ -164,8 +161,8 @@ def mainEntryPoint():
|
||||
|
||||
pluginhandle = int(sys.argv[1])
|
||||
|
||||
log.info("EmbyCon -> Mode: " + str(mode))
|
||||
log.info("EmbyCon -> URL: " + str(param_url))
|
||||
log.debug("EmbyCon -> Mode: " + str(mode))
|
||||
log.debug("EmbyCon -> URL: " + str(param_url))
|
||||
|
||||
# Run a function based on the mode variable that was passed in the URL
|
||||
# if ( mode == None or param_url == None or len(param_url) < 1 ):
|
||||
@@ -211,11 +208,11 @@ def mainEntryPoint():
|
||||
|
||||
f.close()
|
||||
|
||||
log.info("===== EmbyCon FINISHED =====")
|
||||
log.debug("===== EmbyCon FINISHED =====")
|
||||
|
||||
|
||||
def markWatched(item_id):
|
||||
log.info("Mark Item Watched : " + item_id)
|
||||
log.debug("Mark Item Watched : " + item_id)
|
||||
url = "{server}/emby/Users/{userid}/PlayedItems/" + item_id
|
||||
downloadUtils.downloadUrl(url, postBody="", method="POST")
|
||||
home_window = HomeWindow()
|
||||
@@ -224,7 +221,7 @@ def markWatched(item_id):
|
||||
|
||||
|
||||
def markUnwatched(item_id):
|
||||
log.info("Mark Item UnWatched : " + item_id)
|
||||
log.debug("Mark Item UnWatched : " + item_id)
|
||||
url = "{server}/emby/Users/{userid}/PlayedItems/" + item_id
|
||||
downloadUtils.downloadUrl(url, method="DELETE")
|
||||
home_window = HomeWindow()
|
||||
@@ -233,7 +230,7 @@ def markUnwatched(item_id):
|
||||
|
||||
|
||||
def markFavorite(item_id):
|
||||
log.info("Add item to favourites : " + item_id)
|
||||
log.debug("Add item to favourites : " + item_id)
|
||||
url = "{server}/emby/Users/{userid}/FavoriteItems/" + item_id
|
||||
downloadUtils.downloadUrl(url, postBody="", method="POST")
|
||||
home_window = HomeWindow()
|
||||
@@ -242,7 +239,7 @@ def markFavorite(item_id):
|
||||
|
||||
|
||||
def unmarkFavorite(item_id):
|
||||
log.info("Remove item from favourites : " + item_id)
|
||||
log.debug("Remove item from favourites : " + item_id)
|
||||
url = "{server}/emby/Users/{userid}/FavoriteItems/" + item_id
|
||||
downloadUtils.downloadUrl(url, method="DELETE")
|
||||
home_window = HomeWindow()
|
||||
@@ -253,7 +250,7 @@ def unmarkFavorite(item_id):
|
||||
def delete(item_id):
|
||||
return_value = xbmcgui.Dialog().yesno(i18n('confirm_file_delete'), i18n('file_delete_confirm'))
|
||||
if return_value:
|
||||
log.info('Deleting Item : ' + item_id)
|
||||
log.debug('Deleting Item : ' + item_id)
|
||||
url = '{server}/emby/Items/' + item_id
|
||||
progress = xbmcgui.DialogProgress()
|
||||
progress.create(i18n('deleting'), i18n('waiting_server_delete'))
|
||||
@@ -326,7 +323,7 @@ def addGUIItem(url, details, extraData, display_options, folder=True):
|
||||
details['title'] = listItemName
|
||||
|
||||
if kodi_version > 17:
|
||||
list_item = xbmcgui.ListItem(listItemName, iconImage=thumbPath, thumbnailImage=thumbPath, offscreen=True)
|
||||
list_item = xbmcgui.ListItem(listItemName, offscreen=True)
|
||||
else:
|
||||
list_item = xbmcgui.ListItem(listItemName, iconImage=thumbPath, thumbnailImage=thumbPath)
|
||||
|
||||
@@ -502,45 +499,29 @@ def get_params(paramstring):
|
||||
|
||||
|
||||
def setSort(pluginhandle, viewType):
|
||||
defaultData = loadSkinDefaults()
|
||||
|
||||
# set the default sort order
|
||||
defaultSortData = defaultData.get("sort", {})
|
||||
sortName = defaultSortData.get(viewType)
|
||||
log.info("SETTING_SORT : " + str(viewType) + " : " + str(sortName))
|
||||
if sortName == "title":
|
||||
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_VIDEO_SORT_TITLE_IGNORE_THE)
|
||||
elif sortName == "date":
|
||||
log.debug("SETTING_SORT for media type: " + str(viewType))
|
||||
if viewType == "BoxSets":
|
||||
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_VIDEO_YEAR)
|
||||
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_VIDEO_SORT_TITLE_IGNORE_THE)
|
||||
else:
|
||||
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_VIDEO_SORT_TITLE_IGNORE_THE)
|
||||
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_VIDEO_YEAR)
|
||||
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_GENRE)
|
||||
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_UNSORTED)
|
||||
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_NONE)
|
||||
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_VIDEO_RATING)
|
||||
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_LABEL)
|
||||
|
||||
|
||||
def setView(viewType):
|
||||
defaultData = loadSkinDefaults()
|
||||
|
||||
defaultViewData = defaultData.get("view", {})
|
||||
viewNum = defaultViewData.get(viewType)
|
||||
log.info("SETTING_VIEW : " + str(viewType) + " : " + str(viewNum))
|
||||
if viewNum is not None and viewNum != -1:
|
||||
xbmc.executebuiltin("Container.SetViewMode(%s)" % int(viewNum))
|
||||
|
||||
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_GENRE)
|
||||
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_UNSORTED)
|
||||
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_NONE)
|
||||
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_VIDEO_RATING)
|
||||
xbmcplugin.addSortMethod(pluginhandle, xbmcplugin.SORT_METHOD_LABEL)
|
||||
|
||||
def getContent(url, params):
|
||||
log.info("== ENTER: getContent ==")
|
||||
log.debug("== ENTER: getContent ==")
|
||||
|
||||
media_type = params.get("media_type", None)
|
||||
if not media_type:
|
||||
xbmcgui.Dialog().ok(i18n('error'), i18n('no_media_type'))
|
||||
|
||||
log.info("URL: " + str(url))
|
||||
log.info("MediaType: " + str(media_type))
|
||||
log.debug("URL: " + str(url))
|
||||
log.debug("MediaType: " + str(media_type))
|
||||
pluginhandle = int(sys.argv[1])
|
||||
|
||||
settings = xbmcaddon.Addon(id='plugin.video.embycon')
|
||||
@@ -562,7 +543,7 @@ def getContent(url, params):
|
||||
elif media_type == "season" or media_type == "episodes":
|
||||
viewType = "Episodes"
|
||||
xbmcplugin.setContent(pluginhandle, 'episodes')
|
||||
log.info("ViewType: " + viewType)
|
||||
log.debug("ViewType: " + viewType)
|
||||
|
||||
setSort(pluginhandle, viewType)
|
||||
|
||||
@@ -586,9 +567,6 @@ def getContent(url, params):
|
||||
return
|
||||
xbmcplugin.addDirectoryItems(pluginhandle, dirItems)
|
||||
|
||||
# set the view mode based on what the user wanted for this view type
|
||||
setView(viewType)
|
||||
|
||||
xbmcplugin.endOfDirectory(pluginhandle, cacheToDisc=False)
|
||||
|
||||
if (progress != None):
|
||||
@@ -599,7 +577,7 @@ def getContent(url, params):
|
||||
|
||||
|
||||
def processDirectory(results, progress, params):
|
||||
log.info("== ENTER: processDirectory ==")
|
||||
log.debug("== ENTER: processDirectory ==")
|
||||
|
||||
settings = xbmcaddon.Addon(id='plugin.video.embycon')
|
||||
server = downloadUtils.getServer()
|
||||
@@ -907,17 +885,8 @@ def processDirectory(results, progress, params):
|
||||
|
||||
return dirItems
|
||||
|
||||
|
||||
def showSetViews():
|
||||
log.info("showSetViews Called")
|
||||
|
||||
defaultViews = DefaultViews("DefaultViews.xml", __cwd__, "default", "720p")
|
||||
defaultViews.doModal()
|
||||
del defaultViews
|
||||
|
||||
|
||||
def getWigetContent(handle, params):
|
||||
log.info("getWigetContent Called" + str(params))
|
||||
log.debug("getWigetContent Called" + str(params))
|
||||
server = downloadUtils.getServer()
|
||||
|
||||
type = params.get("type")
|
||||
@@ -1076,7 +1045,7 @@ def getWigetContent(handle, params):
|
||||
|
||||
|
||||
def showContent(pluginName, handle, params):
|
||||
log.info("showContent Called: " + str(params))
|
||||
log.debug("showContent Called: " + str(params))
|
||||
|
||||
item_type = params.get("item_type")
|
||||
|
||||
@@ -1090,11 +1059,11 @@ def showContent(pluginName, handle, params):
|
||||
"&IsMissing=False"
|
||||
"&IncludeItemTypes=" + item_type)
|
||||
|
||||
log.info("showContent Content Url : " + str(contentUrl))
|
||||
log.debug("showContent Content Url : " + str(contentUrl))
|
||||
getContent(contentUrl, params)
|
||||
|
||||
def showParentContent(pluginName, handle, params):
|
||||
log.info("showParentContent Called: " + str(params))
|
||||
log.debug("showParentContent Called: " + str(params))
|
||||
|
||||
settings = xbmcaddon.Addon(id='plugin.video.embycon')
|
||||
|
||||
@@ -1109,7 +1078,7 @@ def showParentContent(pluginName, handle, params):
|
||||
"&Fields=" + detailsString +
|
||||
"&format=json")
|
||||
|
||||
log.info("showParentContent Content Url : " + str(contentUrl))
|
||||
log.debug("showParentContent Content Url : " + str(contentUrl))
|
||||
getContent(contentUrl, params)
|
||||
|
||||
def checkService():
|
||||
@@ -1125,8 +1094,8 @@ def checkService():
|
||||
sys.exit()
|
||||
xbmc.sleep(200)
|
||||
|
||||
log.info("EmbyCon Service Timestamp: " + timeStamp)
|
||||
log.info("EmbyCon Current Timestamp: " + str(int(time.time())))
|
||||
log.debug("EmbyCon Service Timestamp: " + timeStamp)
|
||||
log.debug("EmbyCon Current Timestamp: " + str(int(time.time())))
|
||||
|
||||
if ((int(timeStamp) + 240) < int(time.time())):
|
||||
log.error("EmbyCon Service Not Running, time stamp to old, exiting")
|
||||
@@ -1135,7 +1104,7 @@ def checkService():
|
||||
|
||||
|
||||
def search(handle, params):
|
||||
log.info('search Called: ' + str(params))
|
||||
log.debug('search Called: ' + str(params))
|
||||
item_type = params.get('item_type')
|
||||
if not item_type:
|
||||
return
|
||||
@@ -1164,7 +1133,7 @@ def search(handle, params):
|
||||
|
||||
|
||||
def searchResults(params):
|
||||
log.info('searchResults Called: ' + str(params))
|
||||
log.debug('searchResults Called: ' + str(params))
|
||||
|
||||
handle = int(sys.argv[1])
|
||||
query = params.get('query')
|
||||
@@ -1330,7 +1299,6 @@ def searchResults(params):
|
||||
list_items.append(item_tuple)
|
||||
|
||||
xbmcplugin.addDirectoryItems(handle, list_items)
|
||||
setView(view_type)
|
||||
xbmcplugin.endOfDirectory(handle, cacheToDisc=False)
|
||||
|
||||
if progress is not None:
|
||||
@@ -1339,16 +1307,16 @@ def searchResults(params):
|
||||
|
||||
|
||||
def PLAY(params, handle):
|
||||
log.info("== ENTER: PLAY ==")
|
||||
log.debug("== ENTER: PLAY ==")
|
||||
|
||||
log.info("PLAY ACTION PARAMS: " + str(params))
|
||||
log.debug("PLAY ACTION PARAMS: " + str(params))
|
||||
item_id = params.get("item_id")
|
||||
|
||||
auto_resume = int(params.get("auto_resume", "-1"))
|
||||
log.info("AUTO_RESUME: " + str(auto_resume))
|
||||
log.debug("AUTO_RESUME: " + str(auto_resume))
|
||||
|
||||
forceTranscode = params.get("force_transcode", None) is not None
|
||||
log.info("FORCE_TRANSCODE: " + str(forceTranscode))
|
||||
log.debug("FORCE_TRANSCODE: " + str(forceTranscode))
|
||||
|
||||
# set the current playing item id
|
||||
# set all the playback info, this will be picked up by the service
|
||||
|
||||
@@ -1,245 +0,0 @@
|
||||
import sys
|
||||
import os
|
||||
import traceback
|
||||
import hashlib
|
||||
import time
|
||||
import xbmcaddon
|
||||
import xbmc
|
||||
import urllib
|
||||
import httplib
|
||||
import ssl
|
||||
|
||||
from clientinfo import ClientInformation
|
||||
from simple_logging import SimpleLogging
|
||||
|
||||
log = SimpleLogging(__name__)
|
||||
|
||||
# for info on the metrics that can be sent to Google Analytics
|
||||
# https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#events
|
||||
|
||||
logEventHistory = {}
|
||||
|
||||
# wrap a function to catch, log and then re throw an exception
|
||||
def log_error(errors=(Exception, )):
|
||||
def decorator(func):
|
||||
def wrapper(*args, **kwargs):
|
||||
try:
|
||||
return func(*args, **kwargs)
|
||||
except errors as error:
|
||||
if not (hasattr(error, 'quiet') and error.quiet):
|
||||
ga = GoogleAnalytics()
|
||||
err_strings = ga.formatException()
|
||||
ga.sendEventData("Exception", err_strings[0], err_strings[1], True)
|
||||
log.error(error)
|
||||
log.error("log_error: %s \n args: %s \n kwargs: %s" % (func.__name__, args, kwargs))
|
||||
raise
|
||||
return wrapper
|
||||
return decorator
|
||||
|
||||
# main GA class
|
||||
class GoogleAnalytics:
|
||||
|
||||
testing = False
|
||||
enabled = True
|
||||
|
||||
def __init__(self):
|
||||
|
||||
settings = xbmcaddon.Addon('plugin.video.embycon')
|
||||
client_info = ClientInformation()
|
||||
self.version = client_info.getVersion()
|
||||
self.device_id = client_info.getDeviceId()
|
||||
|
||||
self.enabled = settings.getSetting("metricLogging") == "true"
|
||||
|
||||
# user agent string, used for OS and Kodi version identification
|
||||
kodi_ver = xbmc.getInfoLabel("System.BuildVersion")
|
||||
if not kodi_ver:
|
||||
kodi_ver = "na"
|
||||
kodi_ver = kodi_ver.strip()
|
||||
if kodi_ver.find(" ") > 0:
|
||||
kodi_ver = kodi_ver[0:kodi_ver.find(" ")]
|
||||
self.userAgent = "Kodi/" + kodi_ver + " (" + self.getUserAgentOS() + ")"
|
||||
|
||||
# Use set user name
|
||||
self.user_name = settings.getSetting('username') or 'None'
|
||||
|
||||
# use md5 for client and user for analytics
|
||||
self.device_id = hashlib.md5(self.device_id).hexdigest()
|
||||
self.user_name = hashlib.md5(self.user_name).hexdigest()
|
||||
|
||||
# resolution
|
||||
self.screen_mode = xbmc.getInfoLabel("System.ScreenMode")
|
||||
self.screen_height = xbmc.getInfoLabel("System.ScreenHeight")
|
||||
self.screen_width = xbmc.getInfoLabel("System.ScreenWidth")
|
||||
|
||||
self.lang = xbmc.getInfoLabel("System.Language")
|
||||
|
||||
def getUserAgentOS(self):
|
||||
|
||||
if xbmc.getCondVisibility('system.platform.osx'):
|
||||
return "Mac OS X"
|
||||
elif xbmc.getCondVisibility('system.platform.ios'):
|
||||
return "iOS"
|
||||
elif xbmc.getCondVisibility('system.platform.windows'):
|
||||
return "Windows NT"
|
||||
elif xbmc.getCondVisibility('system.platform.android'):
|
||||
return "Android"
|
||||
elif xbmc.getCondVisibility('system.platform.linux.raspberrypi'):
|
||||
return "Linux Rpi"
|
||||
elif xbmc.getCondVisibility('system.platform.linux'):
|
||||
return "Linux"
|
||||
else:
|
||||
return "Other"
|
||||
|
||||
def formatException(self):
|
||||
|
||||
stack = traceback.extract_stack()
|
||||
exc_type, exc_obj, exc_tb = sys.exc_info()
|
||||
tb = traceback.extract_tb(exc_tb)
|
||||
full_tb = stack[:-1] + tb
|
||||
#log.error(str(full_tb))
|
||||
|
||||
# get last stack frame
|
||||
latestStackFrame = None
|
||||
if len(tb) > 0:
|
||||
latestStackFrame = tb[-1]
|
||||
#log.error(str(tb))
|
||||
|
||||
fileStackTrace = ""
|
||||
try:
|
||||
# get files from stack
|
||||
stackFileList = []
|
||||
for frame in full_tb:
|
||||
#log.error(str(frame))
|
||||
frameFile = (os.path.split(frame[0])[1])[:-3]
|
||||
frameLine = frame[1]
|
||||
if len(stackFileList) == 0 or stackFileList[-1][0] != frameFile:
|
||||
stackFileList.append([frameFile, [str(frameLine)]])
|
||||
else:
|
||||
file = stackFileList[-1][0]
|
||||
lines = stackFileList[-1][1]
|
||||
lines.append(str(frameLine))
|
||||
stackFileList[-1] = [file, lines]
|
||||
#log.error(str(stackFileList))
|
||||
|
||||
for item in stackFileList:
|
||||
lines = ",".join(item[1])
|
||||
fileStackTrace += item[0] + "," + lines + ":"
|
||||
#log.error(str(fileStackTrace))
|
||||
except Exception as e:
|
||||
fileStackTrace = None
|
||||
log.error(e)
|
||||
|
||||
errorType = "NA"
|
||||
errorFile = "NA"
|
||||
|
||||
if latestStackFrame is not None:
|
||||
if fileStackTrace is None:
|
||||
fileStackTrace = os.path.split(latestStackFrame[0])[1] + ":" + str(latestStackFrame[1])
|
||||
|
||||
codeLine = "NA"
|
||||
if(len(latestStackFrame) > 3 and latestStackFrame[3] != None):
|
||||
codeLine = latestStackFrame[3].strip()
|
||||
|
||||
errorFile = "%s(%s)(%s)" % (fileStackTrace, exc_obj.message, codeLine)
|
||||
errorFile = errorFile[0:499]
|
||||
errorType = "%s" % (exc_type.__name__)
|
||||
#log.error(errorType + " - " + errorFile)
|
||||
|
||||
del(exc_type, exc_obj, exc_tb)
|
||||
|
||||
return errorType, errorFile
|
||||
|
||||
def getBaseData(self):
|
||||
|
||||
# all the data we can send to Google Analytics
|
||||
data = {}
|
||||
data['v'] = '1'
|
||||
data['tid'] = 'UA-101964432-1' # tracking id
|
||||
|
||||
data['ds'] = 'plugin' # data source
|
||||
|
||||
data['an'] = 'EmbyCon' # App Name
|
||||
data['aid'] = '1' # App ID
|
||||
data['av'] = self.version # App Version
|
||||
#data['aiid'] = '1.1' # App installer ID
|
||||
|
||||
data['cid'] = self.device_id # Client ID
|
||||
#data['uid'] = self.user_name # User ID
|
||||
|
||||
data['ua'] = self.userAgent # user agent string
|
||||
|
||||
# add width and height, only add if full screen
|
||||
if self.screen_mode.lower().find("window") == -1:
|
||||
data['sr'] = str(self.screen_width) + "x" + str(self.screen_height)
|
||||
|
||||
data["ul"] = self.lang
|
||||
|
||||
return data
|
||||
|
||||
def sendScreenView(self, name):
|
||||
|
||||
data = self.getBaseData()
|
||||
data['t'] = 'screenview' # action type
|
||||
data['cd'] = name
|
||||
|
||||
self.sendData(data)
|
||||
|
||||
def sendEventData(self, eventCategory, eventAction, eventLabel=None, throttle=False):
|
||||
|
||||
# if throttling is enabled then only log the same event every 5 min
|
||||
if throttle:
|
||||
throttleKey = eventCategory + "-" + eventAction + "-" + str(eventLabel)
|
||||
lastLogged = logEventHistory.get(throttleKey)
|
||||
if lastLogged != None:
|
||||
timeSinceLastLog = time.time() - lastLogged
|
||||
if timeSinceLastLog < 300 :
|
||||
log.info("SKIPPING_LOG_EVENT : " + str(timeSinceLastLog) + " " + throttleKey)
|
||||
return
|
||||
logEventHistory[throttleKey] = time.time()
|
||||
|
||||
data = self.getBaseData()
|
||||
data['t'] = 'event' # action type
|
||||
data['ec'] = eventCategory # Event Category
|
||||
data['ea'] = eventAction # Event Action
|
||||
|
||||
if eventLabel is not None :
|
||||
data['el'] = eventLabel # Event Label
|
||||
|
||||
self.sendData(data)
|
||||
|
||||
def sendData(self, data):
|
||||
|
||||
if not self.enabled:
|
||||
return
|
||||
|
||||
if self.testing:
|
||||
log.info("GA: " + str(data))
|
||||
|
||||
postData = ""
|
||||
for key in data:
|
||||
postData = postData + key + "=" + urllib.quote(data[key]) + "&"
|
||||
|
||||
server = "www.google-analytics.com:443"
|
||||
if self.testing:
|
||||
url_path = "/debug/collect"
|
||||
else:
|
||||
url_path = "/collect"
|
||||
|
||||
ret_data = None
|
||||
try:
|
||||
conn = httplib.HTTPSConnection(server, timeout=40, context=ssl._create_unverified_context())
|
||||
head = {}
|
||||
head["Content-Type"] = "application/x-www-form-urlencoded"
|
||||
conn.request(method="POST", url=url_path, body=postData, headers=head)
|
||||
data = conn.getresponse()
|
||||
if int(data.status) == 200:
|
||||
ret_data = data.read()
|
||||
except Exception as error:
|
||||
log.error("Error sending GA data: " + str(error))
|
||||
|
||||
if self.testing and ret_data is not None:
|
||||
log.info("GA: " + ret_data.encode('utf-8'))
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import xbmc
|
||||
import xbmcgui
|
||||
import xbmcplugin
|
||||
import xbmcaddon
|
||||
|
||||
import sys
|
||||
import json
|
||||
@@ -8,7 +9,7 @@ import json
|
||||
from simple_logging import SimpleLogging
|
||||
|
||||
log = SimpleLogging(__name__)
|
||||
|
||||
addon = xbmcaddon.Addon()
|
||||
|
||||
class HomeWindow():
|
||||
"""
|
||||
@@ -39,7 +40,7 @@ class HomeWindow():
|
||||
def addMenuDirectoryItem(label, path, folder=True, thumbnail=None):
|
||||
li = xbmcgui.ListItem(label, path=path)
|
||||
if thumbnail is None:
|
||||
thumbnail = "special://home/addons/plugin.video.embycon/icon.png"
|
||||
thumbnail = addon.getAddonInfo('icon')
|
||||
li.setIconImage(thumbnail)
|
||||
li.setThumbnailImage(thumbnail)
|
||||
xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=path, listitem=li, isFolder=folder)
|
||||
@@ -56,7 +57,7 @@ def getKodiVersion():
|
||||
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))
|
||||
log.debug("Version : " + str(version) + " - " + str(versionData))
|
||||
except:
|
||||
version = 0.0
|
||||
log.error("Version Error : RAW Version Data : " + str(result))
|
||||
|
||||
@@ -20,7 +20,7 @@ __addon__ = xbmcaddon.Addon(id='plugin.video.embycon')
|
||||
|
||||
|
||||
def showGenreList():
|
||||
log.info("== ENTER: showGenreList() ==")
|
||||
log.debug("== ENTER: showGenreList() ==")
|
||||
|
||||
server = downloadUtils.getServer()
|
||||
if server is None:
|
||||
@@ -30,7 +30,7 @@ def showGenreList():
|
||||
|
||||
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)
|
||||
log.debug("GENRE_LIST_DATA : " + jsonData)
|
||||
except Exception, msg:
|
||||
error = "Get connect : " + str(msg)
|
||||
log.error(error)
|
||||
@@ -55,14 +55,14 @@ def showGenreList():
|
||||
url = sys.argv[0] + ("?url=" + urllib.quote(collection['path']) +
|
||||
"&mode=GET_CONTENT" +
|
||||
"&media_type=" + collection["media_type"])
|
||||
log.info("addMenuDirectoryItem: " + collection.get('title', i18n('unknown')) + " " + str(url))
|
||||
log.debug("addMenuDirectoryItem: " + collection.get('title', i18n('unknown')) + " " + str(url))
|
||||
addMenuDirectoryItem(collection.get('title', i18n('unknown')), url, thumbnail=collection.get("thumbnail"))
|
||||
|
||||
xbmcplugin.endOfDirectory(int(sys.argv[1]))
|
||||
|
||||
|
||||
def showMovieAlphaList():
|
||||
log.info("== ENTER: showMovieAlphaList() ==")
|
||||
log.debug("== ENTER: showMovieAlphaList() ==")
|
||||
|
||||
settings = xbmcaddon.Addon(id='plugin.video.embycon')
|
||||
server = downloadUtils.getServer()
|
||||
@@ -101,14 +101,14 @@ def showMovieAlphaList():
|
||||
for collection in collections:
|
||||
url = (sys.argv[0] + "?url=" + urllib.quote(collection['path']) +
|
||||
"&mode=GET_CONTENT&media_type=" + collection["media_type"])
|
||||
log.info("addMenuDirectoryItem: " + collection.get('title', i18n('unknown')) + " " + str(url))
|
||||
log.debug("addMenuDirectoryItem: " + collection.get('title', i18n('unknown')) + " " + str(url))
|
||||
addMenuDirectoryItem(collection.get('title', i18n('unknown')), url)
|
||||
|
||||
xbmcplugin.endOfDirectory(int(sys.argv[1]))
|
||||
|
||||
|
||||
def displaySections():
|
||||
log.info("== ENTER: displaySections() ==")
|
||||
log.debug("== ENTER: displaySections() ==")
|
||||
xbmcplugin.setContent(int(sys.argv[1]), 'files')
|
||||
|
||||
server = downloadUtils.getServer()
|
||||
@@ -125,7 +125,7 @@ def displaySections():
|
||||
"&mode=GET_CONTENT&media_type=" + collection["media_type"])
|
||||
if collection.get("name_format") is not None:
|
||||
url += "&name_format=" + urllib.quote(collection.get("name_format"))
|
||||
log.info("addMenuDirectoryItem: " + collection.get('title', i18n('unknown')) + " " + str(url))
|
||||
log.debug("addMenuDirectoryItem: " + collection.get('title', i18n('unknown')) + " " + str(url))
|
||||
addMenuDirectoryItem(collection.get('title', i18n('unknown')), url, thumbnail=collection.get("thumbnail"))
|
||||
|
||||
addMenuDirectoryItem(i18n('movies_genre'), "plugin://plugin.video.embycon/?mode=MOVIE_GENRA")
|
||||
@@ -137,7 +137,6 @@ def displaySections():
|
||||
|
||||
addMenuDirectoryItem(i18n('detect_server'), "plugin://plugin.video.embycon/?mode=DETECT_SERVER_USER")
|
||||
addMenuDirectoryItem(i18n('show_settings'), "plugin://plugin.video.embycon/?mode=SHOW_SETTINGS")
|
||||
addMenuDirectoryItem(i18n('set_default_views'), "plugin://plugin.video.embycon/?mode=SET_DEFAULT_VIEWS")
|
||||
|
||||
if collections:
|
||||
addMenuDirectoryItem(i18n('widgets'), "plugin://plugin.video.embycon/?mode=WIDGETS")
|
||||
@@ -146,7 +145,7 @@ def displaySections():
|
||||
|
||||
|
||||
def getCollections(detailsString):
|
||||
log.info("== ENTER: getCollections ==")
|
||||
log.debug("== ENTER: getCollections ==")
|
||||
|
||||
server = downloadUtils.getServer()
|
||||
if server is None:
|
||||
@@ -155,7 +154,7 @@ def getCollections(detailsString):
|
||||
userid = downloadUtils.getUserId()
|
||||
|
||||
if userid == None or len(userid) == 0:
|
||||
log.info("No userid so returning []")
|
||||
log.debug("No userid so returning []")
|
||||
return []
|
||||
|
||||
try:
|
||||
@@ -171,7 +170,7 @@ def getCollections(detailsString):
|
||||
return []
|
||||
|
||||
parentid = result.get("Id")
|
||||
log.info("parentid : " + parentid)
|
||||
log.debug("parentid : " + parentid)
|
||||
|
||||
htmlpath = "{server}/emby/Users/{userid}/items?ParentId=" + parentid + "&Sortby=SortName&format=json"
|
||||
jsonData = downloadUtils.downloadUrl(htmlpath)
|
||||
@@ -189,8 +188,8 @@ def getCollections(detailsString):
|
||||
item_name = (item.get("Name")).encode('utf-8')
|
||||
|
||||
collection_type = item.get('CollectionType', None)
|
||||
log.info("CollectionType: " + str(collection_type))
|
||||
log.info("Title: " + item_name)
|
||||
log.debug("CollectionType: " + str(collection_type))
|
||||
log.debug("Title: " + item_name)
|
||||
|
||||
if collection_type in ["tvshows", "movies", "boxsets"]:
|
||||
collections.append({
|
||||
|
||||
@@ -15,7 +15,6 @@ from utils import PlayUtils, getArt
|
||||
from kodi_utils import HomeWindow
|
||||
from translation import i18n
|
||||
from json_rpc import json_rpc
|
||||
from ga_client import GoogleAnalytics, log_error
|
||||
|
||||
log = SimpleLogging(__name__)
|
||||
downloadUtils = DownloadUtils()
|
||||
@@ -27,7 +26,7 @@ def playFile(play_info):
|
||||
auto_resume = play_info.get("auto_resume")
|
||||
force_transcode = play_info.get("force_transcode")
|
||||
|
||||
log.info("playFile id(%s) resume(%s) force_transcode(%s)" % (id, auto_resume, force_transcode))
|
||||
log.debug("playFile id(%s) resume(%s) force_transcode(%s)" % (id, auto_resume, force_transcode))
|
||||
|
||||
settings = xbmcaddon.Addon('plugin.video.embycon')
|
||||
addon_path = settings.getAddonInfo('path')
|
||||
@@ -58,13 +57,13 @@ def playFile(play_info):
|
||||
resumeDialog.doModal()
|
||||
resume_result = resumeDialog.getResumeAction()
|
||||
del resumeDialog
|
||||
log.info("Resume Dialog Result: " + str(resume_result))
|
||||
log.debug("Resume Dialog Result: " + str(resume_result))
|
||||
|
||||
# check system settings for play action
|
||||
# if prompt is set ask to set it to auto resume
|
||||
params = {"setting": "myvideos.selectaction"}
|
||||
setting_result = json_rpc('Settings.getSettingValue').execute(params)
|
||||
log.info("Current Setting (myvideos.selectaction): %s" % setting_result)
|
||||
log.debug("Current Setting (myvideos.selectaction): %s" % setting_result)
|
||||
current_value = setting_result.get("result", None)
|
||||
if current_value is not None:
|
||||
current_value = current_value.get("value", -1)
|
||||
@@ -73,7 +72,7 @@ def playFile(play_info):
|
||||
if return_value:
|
||||
params = {"setting": "myvideos.selectaction", "value": 2}
|
||||
json_rpc_result = json_rpc('Settings.setSettingValue').execute(params)
|
||||
log.info("Save Setting (myvideos.selectaction): %s" % json_rpc_result)
|
||||
log.debug("Save Setting (myvideos.selectaction): %s" % json_rpc_result)
|
||||
|
||||
if resume_result == 1:
|
||||
seekTime = 0
|
||||
@@ -92,7 +91,7 @@ def playFile(play_info):
|
||||
if not playurl:
|
||||
playurl = PlayUtils().getPlayUrl(id, result, force_transcode)
|
||||
|
||||
log.info("Play URL: " + playurl + " ListItem Properties: " + str(listitem_props))
|
||||
log.debug("Play URL: " + playurl + " ListItem Properties: " + str(listitem_props))
|
||||
|
||||
playback_type_string = "DirectPlay"
|
||||
if playback_type == "2" or force_transcode:
|
||||
@@ -118,34 +117,26 @@ def playFile(play_info):
|
||||
playlist.add(playurl, list_item)
|
||||
xbmc.Player().play(playlist)
|
||||
|
||||
item_type = result.get('Type', 'na')
|
||||
if seekTime == 0:
|
||||
return
|
||||
|
||||
try:
|
||||
if seekTime == 0:
|
||||
count = 0
|
||||
while not xbmc.Player().isPlaying():
|
||||
log.debug("Not playing yet...sleep for 1 sec")
|
||||
count = count + 1
|
||||
if count >= 10:
|
||||
return
|
||||
else:
|
||||
time.sleep(1)
|
||||
|
||||
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)
|
||||
seekTime = seekTime - jump_back_amount
|
||||
|
||||
seekTime = seekTime - jump_back_amount
|
||||
|
||||
while xbmc.Player().getTime() < (seekTime - 5):
|
||||
# xbmc.Player().pause()
|
||||
xbmc.sleep(100)
|
||||
xbmc.Player().seekTime(seekTime)
|
||||
xbmc.sleep(100)
|
||||
# xbmc.Player().play()
|
||||
|
||||
finally:
|
||||
ga = GoogleAnalytics()
|
||||
ga.sendEventData("PlayAction", item_type, playback_type_string)
|
||||
ga.sendScreenView(item_type)
|
||||
while xbmc.Player().getTime() < (seekTime - 5):
|
||||
# xbmc.Player().pause()
|
||||
xbmc.sleep(100)
|
||||
xbmc.Player().seekTime(seekTime)
|
||||
xbmc.sleep(100)
|
||||
# xbmc.Player().play()
|
||||
|
||||
def setListItemProps(id, listItem, result, server, extra_props):
|
||||
# set up item and item info
|
||||
|
||||
@@ -14,7 +14,7 @@ class ResumeDialog(xbmcgui.WindowXMLDialog):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs)
|
||||
log.info("ResumeDialog INITIALISED")
|
||||
log.debug("ResumeDialog INITIALISED")
|
||||
|
||||
def onInit(self):
|
||||
self.action_exitkeys_id = [10, 13]
|
||||
|
||||
@@ -90,7 +90,7 @@ def checkServer(force=False, change_user=False, notify=False):
|
||||
server_address = url_bits.hostname
|
||||
server_port = str(url_bits.port)
|
||||
server_protocol = url_bits.scheme
|
||||
log.info("Detected server info " + server_protocol + " - " + server_address + " - " + server_port)
|
||||
log.debug("Detected server info " + server_protocol + " - " + server_address + " - " + server_port)
|
||||
|
||||
# save the server info
|
||||
settings.setSetting("port", server_port)
|
||||
@@ -111,7 +111,7 @@ def checkServer(force=False, change_user=False, notify=False):
|
||||
# if asked or we have no current user then show user selection screen
|
||||
if change_user or len(current_username) == 0:
|
||||
# get a list of users
|
||||
log.info("Getting user list")
|
||||
log.debug("Getting user list")
|
||||
jsonData = downloadUtils.downloadUrl(serverUrl + "/emby/Users/Public?format=json", authenticate=False)
|
||||
|
||||
log.debug("jsonData : " + str(jsonData))
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
|
||||
import json
|
||||
|
||||
from kodi_utils import HomeWindow
|
||||
from downloadutils import DownloadUtils
|
||||
from simple_logging import SimpleLogging
|
||||
log = SimpleLogging(__name__)
|
||||
|
||||
def getServerId():
|
||||
|
||||
home_screen = HomeWindow()
|
||||
server_id = home_screen.getProperty("server_id")
|
||||
if server_id:
|
||||
log.info("Server ID from stored value: " + server_id)
|
||||
return server_id
|
||||
|
||||
downloadUtils = DownloadUtils()
|
||||
try:
|
||||
url = "{server}/emby/system/info/public"
|
||||
jsonData = downloadUtils.downloadUrl(url, suppress=True, authenticate=False)
|
||||
result = json.loads(jsonData)
|
||||
if result is not None and result.get("Id") is not None:
|
||||
server_id = result.get("Id")
|
||||
log.info("Server ID from server request: " + server_id)
|
||||
home_screen.setProperty("server_id", server_id)
|
||||
return server_id
|
||||
else:
|
||||
return None
|
||||
except Exception as error:
|
||||
log.info("Could not get Server ID: " + str(error))
|
||||
return None
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ from simple_logging import SimpleLogging
|
||||
log = SimpleLogging(__name__)
|
||||
|
||||
def showServerSessions():
|
||||
log.info("showServerSessions Called")
|
||||
log.debug("showServerSessions Called")
|
||||
|
||||
handle = int(sys.argv[1])
|
||||
downloadUtils = DownloadUtils()
|
||||
|
||||
@@ -2,45 +2,38 @@
|
||||
|
||||
import xbmc
|
||||
import xbmcaddon
|
||||
|
||||
from json_rpc import json_rpc
|
||||
|
||||
class SimpleLogging():
|
||||
level = 0
|
||||
name = ""
|
||||
enable_logging = False
|
||||
|
||||
def __init__(self, name):
|
||||
settings = xbmcaddon.Addon(id='plugin.video.embycon')
|
||||
prefix = settings.getAddonInfo('name')
|
||||
log_level = settings.getSetting('logLevel')
|
||||
self.level = int(log_level)
|
||||
self.name = prefix + '.' + name
|
||||
|
||||
def getLevel(self):
|
||||
return self.level
|
||||
params = {"setting": "debug.showloginfo"}
|
||||
setting_result = json_rpc('Settings.getSettingValue').execute(params)
|
||||
current_value = setting_result.get("result", None)
|
||||
if current_value is not None:
|
||||
self.enable_logging = current_value.get("value", False)
|
||||
#xbmc.log("LOGGING_ENABLED %s: %s" % (self.name, str(self.enable_logging)), level=xbmc.LOGDEBUG)
|
||||
|
||||
def __str__(self):
|
||||
return "LogLevel: " + str(self.level)
|
||||
return "LoggingEnabled: " + str(self.enable_logging)
|
||||
|
||||
def error(self, msg):
|
||||
if (self.level >= 0):
|
||||
try:
|
||||
xbmc.log(self.format(msg, "ERROR"), level=xbmc.LOGNOTICE)
|
||||
except UnicodeEncodeError:
|
||||
xbmc.log(self.format(msg, "ERROR").encode('utf-8'), level=xbmc.LOGNOTICE)
|
||||
|
||||
def info(self, msg):
|
||||
if (self.level >= 1):
|
||||
try:
|
||||
xbmc.log(self.format(msg, "INFO"), level=xbmc.LOGNOTICE)
|
||||
except UnicodeEncodeError:
|
||||
xbmc.log(self.format(msg, "INFO").encode('utf-8'), level=xbmc.LOGNOTICE)
|
||||
try:
|
||||
xbmc.log(self.format(msg, "ERROR"), level=xbmc.LOGERROR)
|
||||
except UnicodeEncodeError:
|
||||
xbmc.log(self.format(msg, "ERROR").encode('utf-8'), level=xbmc.LOGERROR)
|
||||
|
||||
def debug(self, msg):
|
||||
if (self.level >= 2):
|
||||
if (self.enable_logging):
|
||||
try:
|
||||
xbmc.log(self.format(msg, "DEBUG"), level=xbmc.LOGNOTICE)
|
||||
xbmc.log(self.format(msg, "DEBUG"), level=xbmc.LOGDEBUG)
|
||||
except UnicodeEncodeError:
|
||||
xbmc.log(self.format(msg, "DEBUG").encode('utf-8'), level=xbmc.LOGNOTICE)
|
||||
xbmc.log(self.format(msg, "DEBUG").encode('utf-8'), level=xbmc.LOGDEBUG)
|
||||
|
||||
def format(self, msg, levelValue):
|
||||
return self.name + "(" + str(levelValue) + ") -> " + msg
|
||||
|
||||
@@ -62,7 +62,6 @@ STRINGS = {
|
||||
'movies_az': 30252,
|
||||
'change_user': 30253,
|
||||
'show_settings': 30254,
|
||||
'set_default_views': 30255,
|
||||
'movies_all': 30256,
|
||||
'movies_recently_added': 30257,
|
||||
'movies_in_progress': 30258,
|
||||
|
||||
@@ -15,20 +15,20 @@ log = SimpleLogging(__name__)
|
||||
###########################################################################
|
||||
class PlayUtils():
|
||||
def getPlayUrl(self, id, result, force_transcode):
|
||||
log.info("getPlayUrl")
|
||||
log.debug("getPlayUrl")
|
||||
addonSettings = xbmcaddon.Addon(id='plugin.video.embycon')
|
||||
playback_type = addonSettings.getSetting("playback_type")
|
||||
server = downloadUtils.getServer()
|
||||
log.info("playback_type: " + playback_type)
|
||||
log.debug("playback_type: " + playback_type)
|
||||
if force_transcode:
|
||||
log.info("playback_type: FORCED_TRANSCODE")
|
||||
log.debug("playback_type: FORCED_TRANSCODE")
|
||||
playurl = None
|
||||
|
||||
# transcode
|
||||
if playback_type == "2" or force_transcode:
|
||||
|
||||
playback_bitrate = addonSettings.getSetting("playback_bitrate")
|
||||
log.info("playback_bitrate: " + playback_bitrate)
|
||||
log.debug("playback_bitrate: " + playback_bitrate)
|
||||
|
||||
width_options = ["640", "720", "1024", "1280", "1440", "1600", "1920", "2600", "4096"]
|
||||
playback_max_width = width_options[int(addonSettings.getSetting("playback_max_width"))]
|
||||
@@ -77,7 +77,7 @@ class PlayUtils():
|
||||
user_token = downloadUtils.authenticate()
|
||||
playurl = playurl + "&api_key=" + user_token
|
||||
|
||||
log.info("Playback URL: " + playurl)
|
||||
log.debug("Playback URL: " + playurl)
|
||||
return playurl.encode('utf-8')
|
||||
|
||||
def getStrmDetails(self, result):
|
||||
@@ -101,7 +101,7 @@ class PlayUtils():
|
||||
elif line != '':
|
||||
playurl = line
|
||||
|
||||
log.info("Playback URL: " + playurl + " ListItem Properties: " + str(listitem_props))
|
||||
log.debug("Playback URL: " + playurl + " ListItem Properties: " + str(listitem_props))
|
||||
return playurl, listitem_props
|
||||
|
||||
|
||||
|
||||
@@ -1,195 +0,0 @@
|
||||
# Gnu General Public License - see LICENSE.TXT
|
||||
|
||||
import os
|
||||
import xbmc
|
||||
import xbmcgui
|
||||
import xbmcaddon
|
||||
|
||||
import json
|
||||
|
||||
from simple_logging import SimpleLogging
|
||||
from translation import i18n
|
||||
|
||||
log = SimpleLogging(__name__)
|
||||
__addon__ = xbmcaddon.Addon(id='plugin.video.embycon')
|
||||
|
||||
|
||||
def loadSkinDefaults():
|
||||
defaultData = {}
|
||||
# load current default views
|
||||
# add a hash of xbmc.getSkinDir() to file name to make it skin specific
|
||||
__addondir__ = xbmc.translatePath(__addon__.getAddonInfo('profile'))
|
||||
view_list_path = os.path.join(__addondir__, "default_views.json")
|
||||
if os.path.exists(view_list_path):
|
||||
dataFile = open(view_list_path, 'r')
|
||||
jsonData = dataFile.read()
|
||||
dataFile.close()
|
||||
defaultData = json.loads(jsonData)
|
||||
|
||||
return defaultData
|
||||
|
||||
|
||||
class DefaultViews(xbmcgui.WindowXMLDialog):
|
||||
viewData = {}
|
||||
sortData = {"Title": "title", "Date": "date"}
|
||||
defaultView = {}
|
||||
defaultSort = {}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
xbmcgui.WindowXMLDialog.__init__(self, *args, **kwargs)
|
||||
log.info("WINDOW INITIALISED")
|
||||
|
||||
def onInit(self):
|
||||
self.action_exitkeys_id = [10, 13]
|
||||
|
||||
# load skin views
|
||||
addonPath = __addon__.getAddonInfo('path')
|
||||
skin_view_file = os.path.join(addonPath, "resources", "data", "skin_views.json")
|
||||
log.info("Loading skin views form: " + skin_view_file)
|
||||
dataFile = open(skin_view_file, 'r')
|
||||
jsonData = dataFile.read()
|
||||
dataFile.close()
|
||||
defaultViewData = json.loads(jsonData)
|
||||
log.info("Loaded skin views: " + str(defaultViewData))
|
||||
skin_used = xbmc.getSkinDir()
|
||||
log.info("Current skin: " + skin_used)
|
||||
skin_views = defaultViewData.get(skin_used, None)
|
||||
log.info("Current skin views: " + str(skin_views))
|
||||
if skin_views is None:
|
||||
xbmcgui.Dialog().notification(__addon__.getAddonInfo('name'), i18n('skin_not_supported') % skin_used, icon='special://home/addons/plugin.video.embycon/icon.png')
|
||||
self.close()
|
||||
return
|
||||
self.viewData = skin_views
|
||||
|
||||
# load current default views
|
||||
savedData = loadSkinDefaults()
|
||||
self.defaultView = savedData.get("view", {})
|
||||
self.defaultSort = savedData.get("sort", {})
|
||||
|
||||
self.getControl(3110).setLabel(i18n('save'))
|
||||
self.getControl(3019).setLabel(i18n('default_sort'))
|
||||
self.getControl(3020).setLabel(i18n('default_view'))
|
||||
self.getControl(3021).setLabel(i18n('movies'))
|
||||
self.getControl(3022).setLabel(i18n('boxsets'))
|
||||
self.getControl(3023).setLabel(i18n('series'))
|
||||
self.getControl(3024).setLabel(i18n('seasons'))
|
||||
self.getControl(3025).setLabel(i18n('episodes'))
|
||||
|
||||
# set default values
|
||||
name = self.getViewNameById(self.defaultView.get("Movies"))
|
||||
self.getControl(3010).setLabel(name)
|
||||
name = self.getViewNameById(self.defaultView.get("BoxSets"))
|
||||
self.getControl(3011).setLabel(name)
|
||||
name = self.getViewNameById(self.defaultView.get("Series"))
|
||||
self.getControl(3012).setLabel(name)
|
||||
name = self.getViewNameById(self.defaultView.get("Seasons"))
|
||||
self.getControl(3013).setLabel(name)
|
||||
name = self.getViewNameById(self.defaultView.get("Episodes"))
|
||||
self.getControl(3014).setLabel(name)
|
||||
|
||||
name = self.getSortNameById(self.defaultSort.get("Movies"))
|
||||
self.getControl(3050).setLabel(name)
|
||||
name = self.getSortNameById(self.defaultSort.get("BoxSets"))
|
||||
self.getControl(3051).setLabel(name)
|
||||
name = self.getSortNameById(self.defaultSort.get("Series"))
|
||||
self.getControl(3052).setLabel(name)
|
||||
name = self.getSortNameById(self.defaultSort.get("Seasons"))
|
||||
self.getControl(3053).setLabel(name)
|
||||
name = self.getSortNameById(self.defaultSort.get("Episodes"))
|
||||
self.getControl(3054).setLabel(name)
|
||||
|
||||
def onFocus(self, controlId):
|
||||
pass
|
||||
|
||||
def doAction(self, actionID):
|
||||
pass
|
||||
|
||||
def getSortNameById(self, sortId):
|
||||
if (sortId == None):
|
||||
return "None"
|
||||
|
||||
for name, id in self.sortData.iteritems():
|
||||
if id == sortId:
|
||||
return name
|
||||
|
||||
return "None"
|
||||
|
||||
def getViewNameById(self, viewId):
|
||||
if (viewId == None):
|
||||
return "None"
|
||||
|
||||
for name, id in self.viewData.iteritems():
|
||||
if id == viewId:
|
||||
return name
|
||||
|
||||
return "None"
|
||||
|
||||
def getNextViewName(self, current):
|
||||
keys = list(self.viewData.keys())
|
||||
if (current not in keys):
|
||||
return keys[0]
|
||||
|
||||
index = keys.index(current)
|
||||
if (index > -1 and index < len(keys) - 1):
|
||||
return keys[index + 1]
|
||||
else:
|
||||
return keys[0]
|
||||
|
||||
def getNextSortName(self, current):
|
||||
keys = list(self.sortData.keys())
|
||||
if (current not in keys):
|
||||
return keys[0]
|
||||
|
||||
index = keys.index(current)
|
||||
if (index > -1 and index < len(keys) - 1):
|
||||
return keys[index + 1]
|
||||
else:
|
||||
return keys[0]
|
||||
|
||||
def onClick(self, controlID):
|
||||
|
||||
if controlID >= 3010 and controlID <= 3014:
|
||||
control = self.getControl(controlID)
|
||||
control.setLabel(self.getNextViewName(control.getLabel()))
|
||||
|
||||
elif controlID >= 3050 and controlID <= 3054:
|
||||
control = self.getControl(controlID)
|
||||
control.setLabel(self.getNextSortName(control.getLabel()))
|
||||
|
||||
elif controlID == 3110:
|
||||
|
||||
self.setViewId("Movies", 3010)
|
||||
self.setViewId("BoxSets", 3011)
|
||||
self.setViewId("Series", 3012)
|
||||
self.setViewId("Seasons", 3013)
|
||||
self.setViewId("Episodes", 3014)
|
||||
|
||||
self.setSortId("Movies", 3050)
|
||||
self.setSortId("BoxSets", 3051)
|
||||
self.setSortId("Series", 3052)
|
||||
self.setSortId("Seasons", 3053)
|
||||
self.setSortId("Episodes", 3054)
|
||||
|
||||
__addondir__ = xbmc.translatePath(__addon__.getAddonInfo('profile'))
|
||||
view_list_path = os.path.join(__addondir__, "default_views.json")
|
||||
dataFile = open(view_list_path, 'w')
|
||||
defaults_data = {"view": self.defaultView, "sort": self.defaultSort}
|
||||
stringdata = json.dumps(defaults_data)
|
||||
dataFile.write(stringdata)
|
||||
dataFile.close()
|
||||
|
||||
self.close()
|
||||
|
||||
def setViewId(self, viewName, labelId):
|
||||
viewId = self.viewData.get(self.getControl(labelId).getLabel())
|
||||
if (viewId == None):
|
||||
return
|
||||
else:
|
||||
self.defaultView[viewName] = viewId
|
||||
|
||||
def setSortId(self, sortName, labelId):
|
||||
sortId = self.sortData.get(self.getControl(labelId).getLabel())
|
||||
if (sortId == None):
|
||||
return
|
||||
else:
|
||||
self.defaultSort[sortName] = sortId
|
||||
@@ -49,9 +49,7 @@
|
||||
<setting id="episode_name_format" type="text" default="{SeriesName} - s{SeasonIndex}e{EpisodeIndex} - {ItemName}" label="30019" />
|
||||
</category>
|
||||
<category label="30022"> <!-- Advanced -->
|
||||
<setting id="logLevel" type="enum" label="30004" values="None|Info|Debug" default="0" />
|
||||
<setting id="profile" type="bool" label="30010" default="false" visible="true" enable="true" />
|
||||
<setting id="cacheEmbyData" type="bool" label="30138" default="false" visible="true" enable="true" />
|
||||
<setting id="metricLogging" type="bool" label="30287" default="true" visible="true" enable="true" />
|
||||
</category>
|
||||
</settings>
|
||||
@@ -1,232 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<window id="3301" type="dialog">
|
||||
<defaultcontrol always="true">3010</defaultcontrol>
|
||||
<zorder>2</zorder>
|
||||
<coordinates>
|
||||
<system>1</system>
|
||||
<left>315</left>
|
||||
<top>50</top>
|
||||
</coordinates>
|
||||
<include>dialogeffect</include>
|
||||
<controls>
|
||||
|
||||
<control type="image">
|
||||
<left>0</left>
|
||||
<top>0</top>
|
||||
<width>650</width>
|
||||
<height>500</height>
|
||||
<texture border="40">bg.png</texture>
|
||||
</control>
|
||||
|
||||
<control type="label" id="3020">
|
||||
<left>150</left>
|
||||
<top>45</top>
|
||||
<width>380</width>
|
||||
<height>40</height>
|
||||
<font>font16</font>
|
||||
<label></label>
|
||||
<align>left</align>
|
||||
<textcolor>blue</textcolor>
|
||||
</control>
|
||||
|
||||
<control type="label" id="3019">
|
||||
<left>400</left>
|
||||
<top>45</top>
|
||||
<width>380</width>
|
||||
<height>40</height>
|
||||
<font>font16</font>
|
||||
<label></label>
|
||||
<align>left</align>
|
||||
<textcolor>blue</textcolor>
|
||||
</control>
|
||||
|
||||
<control type="label" id="3021">
|
||||
<left>30</left>
|
||||
<top>100</top>
|
||||
<width>120</width>
|
||||
<height>40</height>
|
||||
<font>font14</font>
|
||||
<label></label>
|
||||
</control>
|
||||
<control type="button" id="3010">
|
||||
<texturenofocus border="1" colordiffuse="ff161616">white.png</texturenofocus>
|
||||
<texturefocus border="1" colordiffuse="ff525252">white.png</texturefocus>
|
||||
<left>150</left>
|
||||
<top>100</top>
|
||||
<width>200</width>
|
||||
<height>40</height>
|
||||
<label></label>
|
||||
<onup></onup>
|
||||
<onright>3050</onright>
|
||||
<ondown>3011</ondown>
|
||||
<font>font14</font>
|
||||
</control>
|
||||
<control type="button" id="3050">
|
||||
<texturenofocus border="1" colordiffuse="ff161616">white.png</texturenofocus>
|
||||
<texturefocus border="1" colordiffuse="ff525252">white.png</texturefocus>
|
||||
<left>400</left>
|
||||
<top>100</top>
|
||||
<width>200</width>
|
||||
<height>40</height>
|
||||
<label></label>
|
||||
<onup></onup>
|
||||
<onleft>3010</onleft>
|
||||
<ondown>3051</ondown>
|
||||
<font>font14</font>
|
||||
</control>
|
||||
|
||||
<control type="label" id="3022">
|
||||
<left>30</left>
|
||||
<top>160</top>
|
||||
<width>120</width>
|
||||
<height>40</height>
|
||||
<font>font14</font>
|
||||
<label></label>
|
||||
</control>
|
||||
<control type="button" id="3011">
|
||||
<texturenofocus border="1" colordiffuse="ff161616">white.png</texturenofocus>
|
||||
<texturefocus border="1" colordiffuse="ff525252">white.png</texturefocus>
|
||||
<left>150</left>
|
||||
<top>160</top>
|
||||
<width>200</width>
|
||||
<height>40</height>
|
||||
<label></label>
|
||||
<onup>3010</onup>
|
||||
<onright>3051</onright>
|
||||
<ondown>3012</ondown>
|
||||
<font>font14</font>
|
||||
</control>
|
||||
<control type="button" id="3051">
|
||||
<texturenofocus border="1" colordiffuse="ff161616">white.png</texturenofocus>
|
||||
<texturefocus border="1" colordiffuse="ff525252">white.png</texturefocus>
|
||||
<left>400</left>
|
||||
<top>160</top>
|
||||
<width>200</width>
|
||||
<height>40</height>
|
||||
<label></label>
|
||||
<onup>3050</onup>
|
||||
<onleft>3011</onleft>
|
||||
<ondown>3052</ondown>
|
||||
<font>font14</font>
|
||||
</control>
|
||||
|
||||
<control type="label" id="3023">
|
||||
<left>30</left>
|
||||
<top>220</top>
|
||||
<width>120</width>
|
||||
<height>40</height>
|
||||
<font>font14</font>
|
||||
<label></label>
|
||||
</control>
|
||||
<control type="button" id="3012">
|
||||
<texturenofocus border="1" colordiffuse="ff161616">white.png</texturenofocus>
|
||||
<texturefocus border="1" colordiffuse="ff525252">white.png</texturefocus>
|
||||
<left>150</left>
|
||||
<top>220</top>
|
||||
<width>200</width>
|
||||
<height>40</height>
|
||||
<label></label>
|
||||
<onup>3011</onup>
|
||||
<onright>3052</onright>
|
||||
<ondown>3013</ondown>
|
||||
<font>font14</font>
|
||||
</control>
|
||||
<control type="button" id="3052">
|
||||
<texturenofocus border="1" colordiffuse="ff161616">white.png</texturenofocus>
|
||||
<texturefocus border="1" colordiffuse="ff525252">white.png</texturefocus>
|
||||
<left>400</left>
|
||||
<top>220</top>
|
||||
<width>200</width>
|
||||
<height>40</height>
|
||||
<label></label>
|
||||
<onup>3051</onup>
|
||||
<onleft>3012</onleft>
|
||||
<ondown>3053</ondown>
|
||||
<font>font14</font>
|
||||
</control>
|
||||
|
||||
<control type="label" id="3024">
|
||||
<left>30</left>
|
||||
<top>280</top>
|
||||
<width>120</width>
|
||||
<height>40</height>
|
||||
<font>font14</font>
|
||||
<label></label>
|
||||
</control>
|
||||
<control type="button" id="3013">
|
||||
<texturenofocus border="1" colordiffuse="ff161616">white.png</texturenofocus>
|
||||
<texturefocus border="1" colordiffuse="ff525252">white.png</texturefocus>
|
||||
<left>150</left>
|
||||
<top>280</top>
|
||||
<width>200</width>
|
||||
<height>40</height>
|
||||
<label></label>
|
||||
<onup>3012</onup>
|
||||
<onright>3053</onright>
|
||||
<ondown>3014</ondown>
|
||||
<font>font14</font>
|
||||
</control>
|
||||
<control type="button" id="3053">
|
||||
<texturenofocus border="1" colordiffuse="ff161616">white.png</texturenofocus>
|
||||
<texturefocus border="1" colordiffuse="ff525252">white.png</texturefocus>
|
||||
<left>400</left>
|
||||
<top>280</top>
|
||||
<width>200</width>
|
||||
<height>40</height>
|
||||
<label></label>
|
||||
<onup>3052</onup>
|
||||
<onleft>3013</onleft>
|
||||
<ondown>3054</ondown>
|
||||
<font>font14</font>
|
||||
</control>
|
||||
|
||||
<control type="label" id="3025">
|
||||
<left>30</left>
|
||||
<top>340</top>
|
||||
<width>120</width>
|
||||
<height>40</height>
|
||||
<font>font14</font>
|
||||
<label></label>
|
||||
</control>
|
||||
<control type="button" id="3014">
|
||||
<texturenofocus border="1" colordiffuse="ff161616">white.png</texturenofocus>
|
||||
<texturefocus border="1" colordiffuse="ff525252">white.png</texturefocus>
|
||||
<left>150</left>
|
||||
<top>340</top>
|
||||
<width>200</width>
|
||||
<height>40</height>
|
||||
<label></label>
|
||||
<onup>3013</onup>
|
||||
<onright>3054</onright>
|
||||
<ondown>3110</ondown>
|
||||
<font>font14</font>
|
||||
</control>
|
||||
<control type="button" id="3054">
|
||||
<texturenofocus border="1" colordiffuse="ff161616">white.png</texturenofocus>
|
||||
<texturefocus border="1" colordiffuse="ff525252">white.png</texturefocus>
|
||||
<left>400</left>
|
||||
<top>340</top>
|
||||
<width>200</width>
|
||||
<height>40</height>
|
||||
<label></label>
|
||||
<onup>3053</onup>
|
||||
<onleft>3014</onleft>
|
||||
<ondown>3110</ondown>
|
||||
<font>font14</font>
|
||||
</control>
|
||||
|
||||
<control type="button" id="3110">
|
||||
<texturenofocus border="1" colordiffuse="ff161616">white.png</texturenofocus>
|
||||
<texturefocus border="1" colordiffuse="ff525252">white.png</texturefocus>
|
||||
<left>150</left>
|
||||
<top>400</top>
|
||||
<width>200</width>
|
||||
<height>40</height>
|
||||
<label></label>
|
||||
<onup>3014</onup>
|
||||
<ondown></ondown>
|
||||
<font>font14</font>
|
||||
</control>
|
||||
|
||||
</controls>
|
||||
</window>
|
||||
111
service.py
111
service.py
@@ -6,15 +6,12 @@ import xbmcaddon
|
||||
import xbmcgui
|
||||
import time
|
||||
import json
|
||||
import platform
|
||||
|
||||
from resources.lib.downloadutils import DownloadUtils
|
||||
from resources.lib.server_info import getServerId
|
||||
from resources.lib.simple_logging import SimpleLogging
|
||||
from resources.lib.play_utils import playFile
|
||||
from resources.lib.kodi_utils import HomeWindow
|
||||
from resources.lib.translation import i18n
|
||||
from resources.lib.ga_client import GoogleAnalytics, log_error
|
||||
|
||||
# clear user and token when logging in
|
||||
home_window = HomeWindow()
|
||||
@@ -46,7 +43,7 @@ def sendProgress():
|
||||
if play_data is None:
|
||||
return
|
||||
|
||||
log.info("Sending Progress Update")
|
||||
log.debug("Sending Progress Update")
|
||||
|
||||
play_time = xbmc.Player().getTime()
|
||||
play_data["currentPossition"] = play_time
|
||||
@@ -177,19 +174,19 @@ def stopAll(played_information):
|
||||
if len(played_information) == 0:
|
||||
return
|
||||
|
||||
log.info("played_information : " + str(played_information))
|
||||
log.debug("played_information : " + str(played_information))
|
||||
|
||||
for item_url in played_information:
|
||||
data = played_information.get(item_url)
|
||||
if data is not None:
|
||||
log.info("item_url : " + item_url)
|
||||
log.info("item_data : " + str(data))
|
||||
log.debug("item_url : " + item_url)
|
||||
log.debug("item_data : " + str(data))
|
||||
|
||||
current_possition = data.get("currentPossition", 0)
|
||||
emby_item_id = data.get("item_id")
|
||||
|
||||
if hasData(emby_item_id):
|
||||
log.info("Playback Stopped at: " + str(int(current_possition * 10000000)))
|
||||
log.debug("Playback Stopped at: " + str(int(current_possition * 10000000)))
|
||||
|
||||
url = "{server}/emby/Sessions/Playing/Stopped"
|
||||
postdata = {
|
||||
@@ -208,16 +205,15 @@ class Service(xbmc.Player):
|
||||
played_information = {}
|
||||
|
||||
def __init__(self, *args):
|
||||
log.info("Starting monitor service: " + str(args))
|
||||
log.debug("Starting monitor service: " + str(args))
|
||||
self.played_information = {}
|
||||
|
||||
@log_error()
|
||||
def onPlayBackStarted(self):
|
||||
# Will be called when xbmc starts playing a file
|
||||
stopAll(self.played_information)
|
||||
|
||||
current_playing_file = xbmc.Player().getPlayingFile()
|
||||
log.info("onPlayBackStarted: " + current_playing_file)
|
||||
log.debug("onPlayBackStarted: " + current_playing_file)
|
||||
|
||||
home_window = HomeWindow()
|
||||
emby_item_id = home_window.getProperty("item_id")
|
||||
@@ -227,7 +223,7 @@ class Service(xbmc.Player):
|
||||
if emby_item_id is None or len(emby_item_id) == 0:
|
||||
return
|
||||
|
||||
log.info("Sending Playback Started")
|
||||
log.debug("Sending Playback Started")
|
||||
postdata = {
|
||||
'QueueableMediaTypes': "Video",
|
||||
'CanSeek': True,
|
||||
@@ -247,29 +243,26 @@ class Service(xbmc.Player):
|
||||
data["playback_type"] = playback_type
|
||||
self.played_information[current_playing_file] = data
|
||||
|
||||
log.info("ADDING_FILE : " + current_playing_file)
|
||||
log.info("ADDING_FILE : " + str(self.played_information))
|
||||
log.debug("ADDING_FILE : " + current_playing_file)
|
||||
log.debug("ADDING_FILE : " + str(self.played_information))
|
||||
|
||||
@log_error()
|
||||
def onPlayBackEnded(self):
|
||||
# Will be called when kodi stops playing a file
|
||||
log.info("EmbyCon Service -> onPlayBackEnded")
|
||||
log.debug("EmbyCon Service -> onPlayBackEnded")
|
||||
home_window = HomeWindow()
|
||||
home_window.clearProperty("item_id")
|
||||
stopAll(self.played_information)
|
||||
|
||||
@log_error()
|
||||
def onPlayBackStopped(self):
|
||||
# Will be called when user stops kodi playing a file
|
||||
log.info("onPlayBackStopped")
|
||||
log.debug("onPlayBackStopped")
|
||||
home_window = HomeWindow()
|
||||
home_window.clearProperty("item_id")
|
||||
stopAll(self.played_information)
|
||||
|
||||
@log_error()
|
||||
def onPlayBackPaused(self):
|
||||
# Will be called when kodi pauses the video
|
||||
log.info("onPlayBackPaused")
|
||||
log.debug("onPlayBackPaused")
|
||||
current_file = xbmc.Player().getPlayingFile()
|
||||
play_data = monitor.played_information.get(current_file)
|
||||
|
||||
@@ -277,10 +270,9 @@ class Service(xbmc.Player):
|
||||
play_data['paused'] = True
|
||||
sendProgress()
|
||||
|
||||
@log_error()
|
||||
def onPlayBackResumed(self):
|
||||
# Will be called when kodi resumes the video
|
||||
log.info("onPlayBackResumed")
|
||||
log.debug("onPlayBackResumed")
|
||||
current_file = xbmc.Player().getPlayingFile()
|
||||
play_data = monitor.played_information.get(current_file)
|
||||
|
||||
@@ -288,79 +280,40 @@ class Service(xbmc.Player):
|
||||
play_data['paused'] = False
|
||||
sendProgress()
|
||||
|
||||
@log_error()
|
||||
def onPlayBackSeek(self, time, seekOffset):
|
||||
# Will be called when kodi seeks in video
|
||||
log.info("onPlayBackSeek")
|
||||
log.debug("onPlayBackSeek")
|
||||
sendProgress()
|
||||
|
||||
|
||||
monitor = Service()
|
||||
last_progress_update = time.time()
|
||||
lastMetricPing = time.time()
|
||||
lastStartCheck = time.time()
|
||||
startSent = False
|
||||
|
||||
ga = GoogleAnalytics()
|
||||
try:
|
||||
ga.sendEventData("Version", "OS", platform.platform())
|
||||
ga.sendEventData("Version", "Python", platform.python_version())
|
||||
except Exception as error:
|
||||
log.error("Exception in sending client meta info: " + str(error))
|
||||
xbmc_monitor = xbmc.Monitor()
|
||||
while not xbmc_monitor.abortRequested():
|
||||
|
||||
try:
|
||||
while not xbmc.abortRequested:
|
||||
home_window = HomeWindow()
|
||||
|
||||
home_window = HomeWindow()
|
||||
if xbmc.Player().isPlaying():
|
||||
|
||||
try:
|
||||
if not startSent and (time.time() - lastStartCheck) > 30:
|
||||
lastStartCheck = time.time()
|
||||
server_id = getServerId()
|
||||
if server_id is not None:
|
||||
startSent = True
|
||||
ga = GoogleAnalytics()
|
||||
ga.sendEventData("Application", "Startup", server_id)
|
||||
if (time.time() - last_progress_update) > 10:
|
||||
last_progress_update = time.time()
|
||||
sendProgress()
|
||||
|
||||
except Exception as error:
|
||||
log.error("Exception in sending start message: " + str(error))
|
||||
raise
|
||||
log.error("Exception in Playback Monitor : " + str(error))
|
||||
|
||||
if xbmc.Player().isPlaying():
|
||||
else:
|
||||
play_data = home_window.getProperty("play_item_message")
|
||||
if play_data:
|
||||
home_window.clearProperty("play_item_message")
|
||||
play_info = json.loads(play_data)
|
||||
playFile(play_info)
|
||||
|
||||
try:
|
||||
if (time.time() - lastMetricPing) > 300:
|
||||
lastMetricPing = time.time()
|
||||
ga = GoogleAnalytics()
|
||||
ga.sendEventData("PlayAction", "PlayPing")
|
||||
except Exception, e:
|
||||
log.error("Exception in sending play ping: " + str(e))
|
||||
xbmc_monitor.waitForAbort(1)
|
||||
HomeWindow().setProperty("Service_Timestamp", str(int(time.time())))
|
||||
|
||||
try:
|
||||
if (time.time() - last_progress_update) > 10:
|
||||
last_progress_update = time.time()
|
||||
sendProgress()
|
||||
|
||||
except Exception as error:
|
||||
log.error("Exception in Playback Monitor : " + str(error))
|
||||
|
||||
else:
|
||||
play_data = home_window.getProperty("play_item_message")
|
||||
if play_data:
|
||||
home_window.clearProperty("play_item_message")
|
||||
play_info = json.loads(play_data)
|
||||
playFile(play_info)
|
||||
|
||||
xbmc.sleep(1000)
|
||||
HomeWindow().setProperty("Service_Timestamp", str(int(time.time())))
|
||||
|
||||
except Exception as error:
|
||||
ga = GoogleAnalytics()
|
||||
err_strings = ga.formatException()
|
||||
ga.sendEventData("Exception", err_strings[0], err_strings[1])
|
||||
log.error(str(error))
|
||||
log.error(str(err_strings))
|
||||
raise
|
||||
|
||||
# clear user and token when loggin off
|
||||
home_window = HomeWindow()
|
||||
@@ -368,4 +321,4 @@ home_window.clearProperty("userid")
|
||||
home_window.clearProperty("AccessToken")
|
||||
home_window.clearProperty("Params")
|
||||
|
||||
log.info("Service shutting down")
|
||||
log.debug("Service shutting down")
|
||||
|
||||
Reference in New Issue
Block a user