From 7e7e9184cd6329ebb6f0851612e81a983e724fae Mon Sep 17 00:00:00 2001 From: anxdpanic Date: Mon, 29 May 2017 06:19:33 -0400 Subject: [PATCH] I18n and house-keeping (#6) * convert strings.xml to strings.po for improved translation support * set blank heading for error * i18n: map ints to strings for readability/maintenance * simple_logging - add prefix, add log.warning * remove unneccesary Addon() instances * uniform whitespace * remove log warning, i18n log failure as error * settings - create as needed --- default.py | 8 +- resources/language/English/strings.po | 411 ++++++++++++++ resources/language/English/strings.xml | 121 ---- resources/lib/clientinfo.py | 11 +- resources/lib/datamanager.py | 63 ++- resources/lib/downloadutils.py | 150 ++--- resources/lib/functions.py | 733 +++++++++++++------------ resources/lib/kodi_utils.py | 2 +- resources/lib/menu_functions.py | 79 +-- resources/lib/play_utils.py | 18 +- resources/lib/resume_dialog.py | 30 +- resources/lib/server_detect.py | 34 +- resources/lib/simple_logging.py | 14 +- resources/lib/translation.py | 81 +++ resources/lib/utils.py | 9 +- resources/lib/views.py | 74 ++- resources/settings.xml | 2 +- service.py | 31 +- 18 files changed, 1136 insertions(+), 735 deletions(-) create mode 100644 resources/language/English/strings.po delete mode 100644 resources/language/English/strings.xml create mode 100644 resources/lib/translation.py diff --git a/default.py b/default.py index a7ddd51..91b0a33 100644 --- a/default.py +++ b/default.py @@ -3,13 +3,11 @@ from resources.lib.simple_logging import SimpleLogging from resources.lib.functions import mainEntryPoint -log = SimpleLogging("EmbyCon.default") +log = SimpleLogging('default') log.info("About to enter mainEntryPoint()") mainEntryPoint() - -#clear done and exit. -#sys.modules.clear() - +# clear done and exit. +# sys.modules.clear() diff --git a/resources/language/English/strings.po b/resources/language/English/strings.po new file mode 100644 index 0000000..8efa248 --- /dev/null +++ b/resources/language/English/strings.po @@ -0,0 +1,411 @@ +msgid "" +msgstr "" +"Project-Id-Version: EmbyCon\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Server Address: " +msgstr "" + +msgctxt "#30001" +msgid "Server Port: " +msgstr "" + +msgctxt "#30004" +msgid "Log Level: " +msgstr "" + +msgctxt "#30005" +msgid "Username: " +msgstr "" + +msgctxt "#30006" +msgid "Password: " +msgstr "" + +msgctxt "#30007" +msgid "Samba Username: " +msgstr "" + +msgctxt "#30008" +msgid "Samba Password: " +msgstr "" + +msgctxt "#30010" +msgid "Enable performance profiling" +msgstr "" + +msgctxt "#30011" +msgid "Detect Server" +msgstr "" + +msgctxt "#30012" +msgid "Change User" +msgstr "" + +msgctxt "#30014" +msgid "Emby" +msgstr "" + +msgctxt "#30015" +msgid "Network" +msgstr "" + +msgctxt "#30016" +msgid "Device Name" +msgstr "" + +msgctxt "#30022" +msgid "Advanced" +msgstr "" + +msgctxt "#30024" +msgid "Username:" +msgstr "" + +msgctxt "#30025" +msgid "Password:" +msgstr "" + +msgctxt "#30044" +msgid "Incorrect Username/Password" +msgstr "" + +msgctxt "#30045" +msgid "Username not found" +msgstr "" + +msgctxt "#30052" +msgid "Deleting" +msgstr "" + +msgctxt "#30053" +msgid "Waiting for server to delete" +msgstr "" + +msgctxt "#30060" +msgid "%s (Secured)" +msgstr "" + +msgctxt "#30061" +msgid "%s (User-defined)" +msgstr "" + +msgctxt "#30062" +msgid "Hidden user (User-input)" +msgstr "" + +msgctxt "#30063" +msgid "N/A" +msgstr "" + +msgctxt "#30091" +msgid "Confirm file delete?" +msgstr "" + +msgctxt "#30092" +msgid "Delete this item? This action will delete media and associated data files." +msgstr "" + +msgctxt "#30110" +msgid "Interface" +msgstr "" + +msgctxt "#30114" +msgid "On Resume Jump Back Seconds" +msgstr "" + +msgctxt "#30116" +msgid "Add Item and Played Counts" +msgstr "" + +msgctxt "#30117" +msgid "Background Art Refresh Rate (seconds)" +msgstr "" + +msgctxt "#30118" +msgid "Add Resume Percent" +msgstr "" + +msgctxt "#30119" +msgid "Add Episode Number" +msgstr "" + +msgctxt "#30120" +msgid "Show Load Progress" +msgstr "" + +msgctxt "#30125" +msgid "Done" +msgstr "" + +msgctxt "#30126" +msgid "Processing Item : " +msgstr "" + +msgctxt "#30128" +msgid "Play Error" +msgstr "" + +msgctxt "#30129" +msgid "This item is not playable" +msgstr "" + +msgctxt "#30135" +msgid "Error" +msgstr "" + +msgctxt "#30136" +msgid "EmbyCon service is not running" +msgstr "" + +msgctxt "#30137" +msgid "Please restart Kodi" +msgstr "" + +msgctxt "#30138" +msgid "Cache Emby Data Locally" +msgstr "" + +msgctxt "#30139" +msgid "No Media Type Set" +msgstr "" + +msgctxt "#30150" +msgid "Skin does not support setting views" +msgstr "" + +msgctxt "#30151" +msgid "Select item action (Requires Restart)" +msgstr "" + +msgctxt "#30162" +msgid "Add Season Number" +msgstr "" + +msgctxt "#30166" +msgid "Select Server" +msgstr "" + +msgctxt "#30167" +msgid "Server Detection Succeeded" +msgstr "" + +msgctxt "#30168" +msgid "Found server" +msgstr "" + +msgctxt "#30169" +msgid "Address: " +msgstr "" + +msgctxt "#30180" +msgid "Select User" +msgstr "" + +msgctxt "#30200" +msgid "URL error: %s" +msgstr "" + +msgctxt "#30201" +msgid "Unable to connect to server" +msgstr "" + +msgctxt "#30202" +msgid "Error Extracting Server host:port" +msgstr "" + +msgctxt "#30203" +msgid "Error in ArtworkRotationThread" +msgstr "" + +msgctxt "#30204" +msgid "Unable to connect to host" +msgstr "" + +msgctxt "#30205" +msgid "Error in LoadMenuOptionsThread" +msgstr "" + +msgctxt "#30206" +msgid "Playback Type" +msgstr "" + +msgctxt "#30207" +msgid "Playback" +msgstr "" + +msgctxt "#30208" +msgid "Playback Bitrate (Kbits)" +msgstr "" + +msgctxt "#30209" +msgid "File Direct Path" +msgstr "" + +msgctxt "#30210" +msgid "HTTP Direct Stream" +msgstr "" + +msgctxt "#30211" +msgid "HTTP Transcode" +msgstr "" + +msgctxt "#30230" +msgid "Default View" +msgstr "" + +msgctxt "#30231" +msgid "Movies" +msgstr "" + +msgctxt "#30232" +msgid "BoxSets" +msgstr "" + +msgctxt "#30233" +msgid "Series" +msgstr "" + +msgctxt "#30234" +msgid "Seasons" +msgstr "" + +msgctxt "#30235" +msgid "Episodes" +msgstr "" + +msgctxt "#30236" +msgid "Save" +msgstr "" + +msgctxt "#30237" +msgid "Start from beginning" +msgstr "" + +msgctxt "#30238" +msgid "Default Sort" +msgstr "" + +msgctxt "#30247" +msgid "Widgets" +msgstr "" + +msgctxt "#30248" +msgid "Emby - Movies" +msgstr "" + +msgctxt "#30249" +msgid "Emby - TV Shows" +msgstr "" + +msgctxt "#30250" +msgid "Unknown" +msgstr "" + +msgctxt "#30251" +msgid "Movies (Genre)" +msgstr "" + +msgctxt "#30252" +msgid "Movies (A-Z)" +msgstr "" + +msgctxt "#30253" +msgid "Change User" +msgstr "" + +msgctxt "#30254" +msgid "Show Settings" +msgstr "" + +msgctxt "#30255" +msgid "Set Default Views" +msgstr "" + +msgctxt "#30256" +msgid "Movies - All" +msgstr "" + +msgctxt "#30257" +msgid "Movies - Recently Added" +msgstr "" + +msgctxt "#30258" +msgid "Movies - In Progress" +msgstr "" + +msgctxt "#30259" +msgid "Movies - Favorites" +msgstr "" + +msgctxt "#30260" +msgid "BoxSets" +msgstr "" + +msgctxt "#30261" +msgid "TV Shows - All" +msgstr "" + +msgctxt "#30262" +msgid "TV Shows - Favorites" +msgstr "" + +msgctxt "#30263" +msgid "Episodes - Recently Added" +msgstr "" + +msgctxt "#30264" +msgid "Episodes - In Progress" +msgstr "" + +msgctxt "#30265" +msgid "Episodes - Next Up" +msgstr "" + +msgctxt "#30266" +msgid "Upcoming TV" +msgstr "" + +msgctxt "#30267" +msgid " - In Progress" +msgstr "" + +msgctxt "#30268" +msgid " - Recently Added" +msgstr "" + +msgctxt "#30269" +msgid "Movies - Random" +msgstr "" + +msgctxt "#30270" +msgid "Emby: Mark watched" +msgstr "" + +msgctxt "#30271" +msgid "Emby: Mark unwatched" +msgstr "" + +msgctxt "#30272" +msgid "Emby: Set favourite" +msgstr "" + +msgctxt "#30273" +msgid "Emby: Unset favourite" +msgstr "" + +msgctxt "#30274" +msgid "Emby: Delete" +msgstr "" + +msgctxt "#30280" +msgid "Missing Title" +msgstr "" diff --git a/resources/language/English/strings.xml b/resources/language/English/strings.xml deleted file mode 100644 index 7de05d9..0000000 --- a/resources/language/English/strings.xml +++ /dev/null @@ -1,121 +0,0 @@ - - - Server Address: - Server Port: - Log Level: - Username: - Password: - Samba Username: - Samba Password: - Enable performance profiling - Detect Server - Change User - - Emby - Network - Device Name - - Advanced - Username: - Password: - - Incorrect Username/Password - Username not found - - Waiting for server to delete - - %s (Secured) - %s (User-defined) - Hidden user (User-input) - N/A - - Confirm file delete? - Delete this item? This action will delete media and associated data files. - - Interface - On Resume Jump Back Seconds - Add Item and Played Counts - Background Art Refresh Rate (seconds) - Add Resume Percent - Add Episode Number - Show Load Progress - Done - Processing Item : - Play Error - This item is not playable - Error - EmbyCon service is not running - Please restart Kodi - Cache Emby Data Locally - No Media Type Set - - - Skin does not support setting views - Select item action (Requires Restart) - - Add Season Number - Select Server - Server Detection Succeeded - Found server - Address: - - Select User - - URL error: %s - Unable to connect to server - Error Extracting Server host:port - Error in ArtworkRotationThread - Unable to connect to host - Error in LoadMenuOptionsThread - - Playback Type - Playback - Playback Bitrate (Kbits) - File Direct Path - HTTP Direct Stream - HTTP Transcode - - Default View - Movies - BoxSets - Series - Seasons - Episodes - Save - Start from beginning - Default Sort - - Widgets - Emby - Movies - Emby - TV Shows - - Unknown - Movies (Genre) - Movies (A-Z) - Change User - Show Settings - Set Default Views - Movies - All - Movies - Recently Added - Movies - In Progress - Movies - Favorites - BoxSets - TV Shows - All - TV Shows - Favorites - Episodes - Recently Added - Episodes - In Progress - Episodes - Next Up - Upcoming TV - - In Progress - - Recently Added - Movies - Random - - Emby: Mark watched - Emby: Mark unwatched - Emby: Set favourite - Emby: Unset favourite - Emby: Delete - - Missing Title - - \ No newline at end of file diff --git a/resources/lib/clientinfo.py b/resources/lib/clientinfo.py index 9eb1b84..d4b9998 100644 --- a/resources/lib/clientinfo.py +++ b/resources/lib/clientinfo.py @@ -8,12 +8,13 @@ import xbmcvfs from kodi_utils import HomeWindow from simple_logging import SimpleLogging -log = SimpleLogging("EmbyCon." + __name__) +log = SimpleLogging(__name__) +__addon__ = xbmcaddon.Addon(id="plugin.video.embycon") + class ClientInformation(): - def getDeviceId(self): - + WINDOW = HomeWindow() client_id = WINDOW.getProperty("client_id") @@ -35,9 +36,9 @@ class ClientInformation(): WINDOW.setProperty("client_id", client_id) return client_id - + def getVersion(self): - version = xbmcaddon.Addon(id="plugin.video.embycon").getAddonInfo("version") + version = __addon__.getAddonInfo("version") return version def getClient(self): diff --git a/resources/lib/datamanager.py b/resources/lib/datamanager.py index 1a272fb..87a58e2 100644 --- a/resources/lib/datamanager.py +++ b/resources/lib/datamanager.py @@ -13,27 +13,27 @@ from simple_logging import SimpleLogging from utils import getChecksum from kodi_utils import HomeWindow -log = SimpleLogging("EmbyCon." + __name__) +log = SimpleLogging(__name__) + class DataManager(): - cacheDataResult = None dataUrl = None cacheDataPath = None canRefreshNow = False - + def __init__(self, *args): - log.info("DataManager __init__") + log.info("DataManager __init__") def getCacheValidatorFromData(self, result): result = result.get("Items") - if(result == None): + if (result == None): result = [] itemCount = 0 - unwatchedItemCount = 0 + unwatchedItemCount = 0 dataHashString = "" - + for item in result: item_hash_string = getChecksum(item) item_hash_string = str(itemCount) + "_" + item.get("Name", "-") + "_" + item_hash_string + "|" @@ -46,15 +46,15 @@ class DataManager(): m = hashlib.md5() m.update(dataHashString) validatorString = m.hexdigest() - + log.debug("getCacheValidatorFromData : RawData : " + dataHashString) log.debug("getCacheValidatorFromData : hashData : " + validatorString) - + return validatorString def loadJasonData(self, jsonData): - return json.loads(jsonData) - + return json.loads(jsonData) + def GetContent(self, url): __addon__ = xbmcaddon.Addon(id='plugin.video.embycon') @@ -68,25 +68,25 @@ class DataManager(): log.info("Returning Loaded Result") return result - # first get the url hash + # first get the url hash m = hashlib.md5() m.update(url) urlHash = m.hexdigest() - + # build cache data path - __addondir__ = xbmc.translatePath( __addon__.getAddonInfo('profile')) + __addondir__ = xbmc.translatePath(__addon__.getAddonInfo('profile')) if not os.path.exists(os.path.join(__addondir__, "cache")): os.makedirs(os.path.join(__addondir__, "cache")) cacheDataPath = os.path.join(__addondir__, "cache", urlHash) - + log.info("Cache_Data_Manager:" + cacheDataPath) - + # are we forcing a reload WINDOW = HomeWindow() force_data_reload = WINDOW.getProperty("force_data_reload") == "true" WINDOW.clearProperty("force_data_reload") - + 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 @@ -95,7 +95,7 @@ class DataManager(): jsonData = cachedfie.read() cachedfie.close() result = self.loadJasonData(jsonData) - + # start a worker thread to process the cache validity self.cacheDataResult = result self.dataUrl = url @@ -115,34 +115,33 @@ class DataManager(): cachedfie.close() result = self.loadJasonData(jsonData) self.cacheManagerFinished = True - log.info("Returning Loaded Result") + log.info("Returning Loaded Result") return result - - -class CacheManagerThread(threading.Thread): + +class CacheManagerThread(threading.Thread): dataManager = None - + def __init__(self, *args): threading.Thread.__init__(self, *args) - + def setCacheData(self, data): self.dataManager = data - + def run(self): - + log.info("CacheManagerThread Started") - + cacheValidatorString = self.dataManager.getCacheValidatorFromData(self.dataManager.cacheDataResult) log.info("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 + ")") - + # if they dont match then save the data and trigger a content reload - if(cacheValidatorString != loadedValidatorString): + if (cacheValidatorString != loadedValidatorString): log.info("CacheManagerThread Saving new cache data and reloading container") cachedfie = open(self.dataManager.cacheDataPath, 'w') cachedfie.write(jsonData) @@ -150,11 +149,11 @@ class CacheManagerThread(threading.Thread): # we need to refresh but will wait until the main function has finished loops = 0 - while(self.dataManager.canRefreshNow == False and loops < 200): + while (self.dataManager.canRefreshNow == False and loops < 200): log.debug("Cache_Data_Manager: Not finished yet") xbmc.sleep(100) loops = loops + 1 - + log.info("Sending container refresh (" + str(loops) + ")") xbmc.executebuiltin("Container.Refresh") diff --git a/resources/lib/downloadutils.py b/resources/lib/downloadutils.py index 9cfb5d3..e749bba 100644 --- a/resources/lib/downloadutils.py +++ b/resources/lib/downloadutils.py @@ -13,19 +13,19 @@ import json from kodi_utils import HomeWindow from clientinfo import ClientInformation from simple_logging import SimpleLogging +from translation import i18n + +log = SimpleLogging(__name__) -log = SimpleLogging("EmbyCon." + __name__) class DownloadUtils(): - getString = None def __init__(self, *args): - settings = xbmcaddon.Addon(id='plugin.video.embycon') - self.getString = settings.getLocalizedString - self.addon_name = settings.getAddonInfo('name') + self.addon = xbmcaddon.Addon(id='plugin.video.embycon') + self.addon_name = self.addon.getAddonInfo('name') - def getArtwork(self, data, art_type, parent = False, index = "0", width = 10000, height = 10000, server=None): + def getArtwork(self, data, art_type, parent=False, index="0", width=10000, height=10000, server=None): id = data.get("Id") ''' @@ -38,32 +38,32 @@ class DownloadUtils(): id = data.get("SeriesId") imageTag = "" - #"e3ab56fe27d389446754d0fb04910a34" # a place holder tag, needs to be in this format + # "e3ab56fe27d389446754d0fb04910a34" # a place holder tag, needs to be in this format itemType = data.get("Type") - + # for episodes always use the parent BG - if(itemType == "Episode" and art_type == "Backdrop"): + if (itemType == "Episode" and art_type == "Backdrop"): id = data.get("ParentBackdropItemId") bgItemTags = data.get("ParentBackdropImageTags") - if(bgItemTags != None and len(bgItemTags) > 0): + if (bgItemTags != None and len(bgItemTags) > 0): imageTag = bgItemTags[0] - elif(art_type == "Backdrop") and (parent == True): + elif (art_type == "Backdrop") and (parent == True): id = data.get("ParentBackdropItemId") bgItemTags = data.get("ParentBackdropImageTags") - if(bgItemTags != None and len(bgItemTags) > 0): + if (bgItemTags != None and len(bgItemTags) > 0): imageTag = bgItemTags[0] - elif(art_type == "Backdrop"): + elif (art_type == "Backdrop"): BGTags = data.get("BackdropImageTags") - if(BGTags != None and len(BGTags) > 0): + if (BGTags != None and len(BGTags) > 0): bgIndex = int(index) imageTag = data.get("BackdropImageTags")[bgIndex] - log.debug("Background Image Tag:" + imageTag) - elif(parent == False): - if(data.get("ImageTags") != None and data.get("ImageTags").get(art_type) != None): + log.debug("Background Image Tag:" + imageTag) + elif (parent == False): + if (data.get("ImageTags") != None and data.get("ImageTags").get(art_type) != None): imageTag = data.get("ImageTags").get(art_type) log.debug("Image Tag:" + imageTag) - elif(parent == True): + elif (parent == True): if (itemType == "Episode") and (art_type == 'Primary'): tagName = 'SeriesPrimaryImageTag' idName = 'SeriesId' @@ -75,16 +75,16 @@ class DownloadUtils(): imageTag = data.get(tagName) log.debug("Parent Image Tag:" + imageTag) - if(imageTag == "" or imageTag == None) and (art_type != 'Banner'): # ParentTag not passed for Banner + if (imageTag == "" or imageTag == None) and (art_type != 'Banner'): # ParentTag not passed for Banner log.debug("No Image Tag for request:" + art_type + " item:" + itemType + " parent:" + str(parent)) return "" query = "" - + artwork = "http://%s/emby/Items/%s/Images/%s/%s?MaxWidth=%s&MaxHeight=%s&Format=original&Tag=%s%s" % (server, id, art_type, index, width, height, imageTag, query) - + log.debug("getArtwork : " + artwork) - + ''' # do not return non-existing images if ( (art_type != "Backdrop" and imageTag == "") | @@ -93,7 +93,7 @@ class DownloadUtils(): ): artwork = '' ''' - + return artwork def imageUrl(self, id, art_type, index, width, height, imageTag, server): @@ -108,17 +108,17 @@ class DownloadUtils(): str(height) + "/" + str(width) + "/0") ''' return artwork - + def getUserId(self): WINDOW = HomeWindow() userid = WINDOW.getProperty("userid") - if(userid != None and userid != ""): + if (userid != None and userid != ""): log.info("EmbyCon DownloadUtils -> Returning saved UserID : " + userid) return userid - settings = xbmcaddon.Addon(id='plugin.video.embycon') + settings = xbmcaddon.Addon('plugin.video.embycon') port = settings.getSetting('port') host = settings.getSetting('ipaddress') userName = settings.getSetting('username') @@ -143,17 +143,17 @@ class DownloadUtils(): result = json.loads(jsonData) except Exception, e: log.info("jsonload : " + str(e) + " (" + jsonData + ")") - return "" + return "" log.info("GETUSER_JSONDATA_02:" + str(result)) userid = "" secure = False for user in result: - if(user.get("Name") == userName): + if (user.get("Name") == userName): userid = user.get("Id") log.info("Username Found:" + user.get("Name")) - if(user.get("HasPassword") == True): + if (user.get("HasPassword") == True): secure = True log.info("Username Is Secure (HasPassword=True)") break @@ -161,37 +161,37 @@ class DownloadUtils(): if (secure) or (not userid): authOk = self.authenticate() if (authOk == ""): - return_value = xbmcgui.Dialog().ok(self.getString(30044), self.getString(30044)) + return_value = xbmcgui.Dialog().ok(self.addon_name, i18n('incorrect_user_pass')) return "" if not userid: userid = WINDOW.getProperty("userid") if userid == "": - return_value = xbmcgui.Dialog().ok(self.getString(30045),self.getString(30045)) + return_value = xbmcgui.Dialog().ok(self.addon_name, i18n('username_not_found')) log.info("userid : " + userid) WINDOW.setProperty("userid", userid) - return userid - + return userid + def authenticate(self): - + WINDOW = HomeWindow() token = WINDOW.getProperty("AccessToken") - if(token != None and token != ""): + if (token != None and token != ""): log.info("EmbyCon DownloadUtils -> Returning saved AccessToken : " + token) return token - settings = xbmcaddon.Addon(id='plugin.video.embycon') + settings = xbmcaddon.Addon('plugin.video.embycon') port = settings.getSetting("port") host = settings.getSetting("ipaddress") - if(host == None or host == "" or port == None or port == ""): + if (host == None or host == "" or port == None or port == ""): return "" - + url = "http://" + host + ":" + port + "/emby/Users/AuthenticateByName?format=json" - + clientInfo = ClientInformation() txt_mac = clientInfo.getDeviceId() version = clientInfo.getVersion() @@ -201,9 +201,9 @@ class DownloadUtils(): deviceName = deviceName.replace("\"", "_") authString = "Mediabrowser Client=\"" + client + "\",Device=\"" + deviceName + "\",DeviceId=\"" + txt_mac + "\",Version=\"" + version + "\"" - headers = {'Accept-encoding': 'gzip', 'Authorization' : authString} + headers = {'Accept-encoding': 'gzip', 'Authorization': authString} sha1 = hashlib.sha1(settings.getSetting('password')) - + messageData = "username=" + settings.getSetting('username') + "&password=" + sha1.hexdigest() resp = self.downloadUrl(url, postBody=messageData, method="POST", suppress=True, authenticate=False) @@ -217,7 +217,7 @@ class DownloadUtils(): except: pass - if(accessToken != None): + if (accessToken != None): log.info("User Authenticated : " + accessToken) WINDOW.setProperty("AccessToken", accessToken) WINDOW.setProperty("userid", userid) @@ -227,39 +227,39 @@ class DownloadUtils(): WINDOW.setProperty("AccessToken", "") WINDOW.setProperty("userid", "") return "" - + def getAuthHeader(self, authenticate=True): clientInfo = ClientInformation() txt_mac = clientInfo.getDeviceId() version = clientInfo.getVersion() client = clientInfo.getClient() - settings = xbmcaddon.Addon(id='plugin.video.embycon') + settings = xbmcaddon.Addon('plugin.video.embycon') deviceName = settings.getSetting('deviceName') deviceName = deviceName.replace("\"", "_") headers = {} headers["Accept-encoding"] = "gzip" headers["Accept-Charset"] = "UTF-8,*" - - if(authenticate == False): + + if (authenticate == False): authString = "MediaBrowser Client=\"" + client + "\",Device=\"" + deviceName + "\",DeviceId=\"" + txt_mac + "\",Version=\"" + version + "\"" headers["Authorization"] = authString - headers['X-Emby-Authorization'] = authString + headers['X-Emby-Authorization'] = authString return headers else: userid = self.getUserId() authString = "MediaBrowser UserId=\"" + userid + "\",Client=\"" + client + "\",Device=\"" + deviceName + "\",DeviceId=\"" + txt_mac + "\",Version=\"" + version + "\"" headers["Authorization"] = authString - headers['X-Emby-Authorization'] = authString - + headers['X-Emby-Authorization'] = authString + authToken = self.authenticate() - if(authToken != ""): + if (authToken != ""): headers["X-MediaBrowser-Token"] = authToken - + log.info("EmbyCon Authentication Header : " + str(headers)) return headers - + def downloadUrl(self, url, suppress=False, postBody=None, method="GET", popup=0, authenticate=True): log.info("downloadUrl") link = "" @@ -272,25 +272,25 @@ class DownloadUtils(): urlsplit = 1 server = url.split('/')[serversplit] - urlPath = "/"+"/".join(url.split('/')[urlsplit:]) + urlPath = "/" + "/".join(url.split('/')[urlsplit:]) log.info("DOWNLOAD_URL = " + url) - log.debug("server = "+str(server)) - log.debug("urlPath = "+str(urlPath)) - + log.debug("server = " + str(server)) + log.debug("urlPath = " + str(urlPath)) + # check the server details tokens = server.split(':') host = tokens[0] port = tokens[1] - if(host == "" or host == "" or port == ""): + if (host == "" or host == "" or port == ""): return "" - + conn = httplib.HTTPConnection(server, timeout=40) - + head = self.getAuthHeader(authenticate) log.info("HEADERS : " + str(head)) - if(postBody != None): + if (postBody != None): if isinstance(postBody, dict): content_type = "application/json" postBody = json.dumps(postBody) @@ -313,7 +313,7 @@ class DownloadUtils(): retData = data.read() contentType = data.getheader('content-encoding') log.debug("Data Len Before : " + str(len(retData))) - if(contentType == "gzip"): + if (contentType == "gzip"): retData = StringIO.StringIO(retData) gzipper = gzip.GzipFile(fileobj=retData) link = gzipper.read() @@ -325,9 +325,11 @@ class DownloadUtils(): log.debug(link) log.debug("====== 200 finished ======") - elif ( int(data.status) == 301 ) or ( int(data.status) == 302 ): - try: conn.close() - except: pass + elif (int(data.status) == 301) or (int(data.status) == 302): + try: + conn.close() + except: + pass return data.getheader('Location') elif int(data.status) >= 400: @@ -335,12 +337,14 @@ class DownloadUtils(): log.error(error) if suppress is False: if popup == 0: - xbmc.executebuiltin("Notification(%s, %s)" % (self.addon_name, self.getString(30200) % str(data.reason))) + xbmc.executebuiltin("Notification(%s, %s)" % (self.addon_name, i18n('url_error_') % str(data.reason))) else: - xbmcgui.Dialog().ok(self.getString(30135),server) + xbmcgui.Dialog().ok(self.addon_name, i18n('url_error_') % str(data.reason)) log.error(error) - try: conn.close() - except: pass + try: + conn.close() + except: + pass return "" else: link = "" @@ -349,12 +353,14 @@ class DownloadUtils(): log.error(error) if suppress is False: if popup == 0: - xbmc.executebuiltin("Notification(%s, %s)" % (self.addon_name, self.getString(30200) % self.getString(30201))) + xbmc.executebuiltin("Notification(%s, %s)" % (self.addon_name, i18n('url_error_') % i18n('unable_connect_server'))) else: - xbmcgui.Dialog().ok("",self.getString(30204)) + xbmcgui.Dialog().ok(self.addon_name, i18n('url_error_') % i18n('unable_connect_server')) raise else: - try: conn.close() - except: pass + try: + conn.close() + except: + pass return link diff --git a/resources/lib/functions.py b/resources/lib/functions.py index 60301e0..f324ee9 100644 --- a/resources/lib/functions.py +++ b/resources/lib/functions.py @@ -24,28 +24,28 @@ from views import DefaultViews, loadSkinDefaults from server_detect import checkServer from simple_logging import SimpleLogging from menu_functions import displaySections, showMovieAlphaList, showGenreList, showWidgets +from translation import i18n -__settings__ = xbmcaddon.Addon(id='plugin.video.embycon') __addon__ = xbmcaddon.Addon(id='plugin.video.embycon') -__language__ = __addon__.getLocalizedString -__addondir__ = xbmc.translatePath( __addon__.getAddonInfo('profile')) -__cwd__ = __settings__.getAddonInfo('path') -PLUGINPATH = xbmc.translatePath(os.path.join( __cwd__)) +__addondir__ = xbmc.translatePath(__addon__.getAddonInfo('profile')) +__cwd__ = __addon__.getAddonInfo('path') +PLUGINPATH = xbmc.translatePath(os.path.join(__cwd__)) -log = SimpleLogging("EmbyCon." + __name__) +log = SimpleLogging(__name__) kodi_version = int(xbmc.getInfoLabel('System.BuildVersion')[:2]) downloadUtils = DownloadUtils() dataManager = DataManager() + def mainEntryPoint(): - log.info("===== EmbyCon START =====") - - profile_code = __settings__.getSetting('profile') == "true" + + settings = xbmcaddon.Addon(id='plugin.video.embycon') + profile_code = settings.getSetting('profile') == "true" pr = None - if(profile_code): + if (profile_code): return_value = xbmcgui.Dialog().yesno("Profiling Enabled", "Do you want to run profiling?") if return_value: pr = cProfile.Profile() @@ -54,7 +54,7 @@ def mainEntryPoint(): 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 BuildVersion: " + xbmc.getInfoLabel("System.BuildVersion")) log.info("Kodi Version: " + str(kodi_version)) log.info("Script argument data: " + str(sys.argv)) @@ -62,23 +62,23 @@ def mainEntryPoint(): params = get_params(sys.argv[2]) except: params = {} - - if(len(params) == 0): + + if (len(params) == 0): home_window = HomeWindow() windowParams = home_window.getProperty("Params") log.info("windowParams : " + windowParams) - #home_window.clearProperty("Params") - if(windowParams): + # home_window.clearProperty("Params") + if (windowParams): try: params = get_params(windowParams) except: - params = {} - + params = {} + log.info("Script params = " + str(params)) param_url = params.get('url', None) - if param_url and ( param_url.startswith('http') or param_url.startswith('file') ): + if param_url and (param_url.startswith('http') or param_url.startswith('file')): param_url = urllib.unquote(param_url) mode = params.get("mode", None) @@ -112,7 +112,7 @@ def mainEntryPoint(): elif mode == "WIDGETS": showWidgets() elif mode == "SHOW_SETTINGS": - __settings__.openSettings() + __addon__.openSettings() WINDOW = xbmcgui.getCurrentWindowId() if WINDOW == 10000: log.info("Currently in home - refreshing to allow new settings to be taken") @@ -120,7 +120,7 @@ def mainEntryPoint(): elif sys.argv[1] == "refresh": home_window = HomeWindow() home_window.setProperty("force_data_reload", "true") - xbmc.executebuiltin("Container.Refresh") + xbmc.executebuiltin("Container.Refresh") elif mode == "SET_DEFAULT_VIEWS": showSetViews() elif mode == "WIDGET_CONTENT": @@ -130,27 +130,27 @@ def mainEntryPoint(): checkServer(notify=False) showParentContent(sys.argv[0], int(sys.argv[1]), params) elif mode == "SHOW_CONTENT": - #plugin://plugin.video.embycon?mode=SHOW_CONTENT&item_type=Movie|Series + # plugin://plugin.video.embycon?mode=SHOW_CONTENT&item_type=Movie|Series checkService() checkServer(notify=False) showContent(sys.argv[0], int(sys.argv[1]), params) else: - + checkService() checkServer(notify=False) - + pluginhandle = int(sys.argv[1]) log.info("EmbyCon -> Mode: " + str(mode)) log.info("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 ): + # 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 ): # displaySections(pluginhandle) if mode == "GET_CONTENT": media_type = params.get("media_type", None) if not media_type: - xbmcgui.Dialog().ok(__language__(30135), __language__(30139)) + xbmcgui.Dialog().ok(i18n('error'), i18n('no_media_type')) log.info("EmbyCon -> media_type: " + str(media_type)) getContent(param_url, pluginhandle, media_type) @@ -161,10 +161,9 @@ def mainEntryPoint(): displaySections() dataManager.canRefreshNow = True - - if(pr): - pr.disable() + if (pr): + pr.disable() fileTimeStamp = time.strftime("%Y%m%d-%H%M%S") tabFileName = __addondir__ + "profile(" + fileTimeStamp + ").txt" @@ -195,91 +194,103 @@ def mainEntryPoint(): log.info("===== EmbyCon FINISHED =====") + def markWatched(item_id): log.info("Mark Item Watched : " + item_id) + settings = xbmcaddon.Addon(id='plugin.video.embycon') userId = downloadUtils.getUserId() - server = __settings__.getSetting('ipaddress') + ":" + __settings__.getSetting('port') + server = settings.getSetting('ipaddress') + ":" + settings.getSetting('port') url = "http://" + server + "/emby/Users/" + userId + "/PlayedItems/" + item_id downloadUtils.downloadUrl(url, postBody="", method="POST") home_window = HomeWindow() home_window.setProperty("force_data_reload", "true") xbmc.executebuiltin("Container.Refresh") + def markUnwatched(item_id): log.info("Mark Item UnWatched : " + item_id) + settings = xbmcaddon.Addon(id='plugin.video.embycon') userId = downloadUtils.getUserId() - server = __settings__.getSetting('ipaddress') + ":" + __settings__.getSetting('port') + server = settings.getSetting('ipaddress') + ":" + settings.getSetting('port') url = "http://" + server + "/emby/Users/" + userId + "/PlayedItems/" + item_id downloadUtils.downloadUrl(url, method="DELETE") home_window = HomeWindow() home_window.setProperty("force_data_reload", "true") xbmc.executebuiltin("Container.Refresh") + def markFavorite(item_id): log.info("Add item to favourites : " + item_id) + settings = xbmcaddon.Addon(id='plugin.video.embycon') userId = downloadUtils.getUserId() - server = __settings__.getSetting('ipaddress') + ":" + __settings__.getSetting('port') + server = settings.getSetting('ipaddress') + ":" + settings.getSetting('port') url = "http://" + server + "/emby/Users/" + userId + "/FavoriteItems/" + item_id downloadUtils.downloadUrl(url, postBody="", method="POST") home_window = HomeWindow() home_window.setProperty("force_data_reload", "true") xbmc.executebuiltin("Container.Refresh") - + + def unmarkFavorite(item_id): log.info("Remove item from favourites : " + item_id) + settings = xbmcaddon.Addon(id='plugin.video.embycon') userId = downloadUtils.getUserId() - server = __settings__.getSetting('ipaddress') + ":" + __settings__.getSetting('port') + server = settings.getSetting('ipaddress') + ":" + settings.getSetting('port') url = "http://" + server + "/emby/Users/" + userId + "/FavoriteItems/" + item_id downloadUtils.downloadUrl(url, method="DELETE") home_window = HomeWindow() home_window.setProperty("force_data_reload", "true") xbmc.executebuiltin("Container.Refresh") - -def delete (item_id): - return_value = xbmcgui.Dialog().yesno(__language__(30091),__language__(30092)) + + +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) - server = __settings__.getSetting('ipaddress') + ":" + __settings__.getSetting('port') + settings = xbmcaddon.Addon(id='plugin.video.embycon') + server = settings.getSetting('ipaddress') + ":" + settings.getSetting('port') url = 'http://' + server + '/emby/Items/' + item_id progress = xbmcgui.DialogProgress() - progress.create(__language__(30052), __language__(30053)) + progress.create(i18n('deleting'), i18n('waiting_server_delete')) downloadUtils.downloadUrl(url, method="DELETE") progress.close() xbmc.executebuiltin("Container.Refresh") - -def addGUIItem( url, details, extraData, folder=True ): + +def addGUIItem(url, details, extraData, folder=True): home_window = HomeWindow() + settings = xbmcaddon.Addon(id='plugin.video.embycon') + url = url.encode('utf-8') - log.debug("Adding GuiItem for [%s]" % details.get('title','Unknown')) + log.debug("Adding GuiItem for [%s]" % details.get('title', i18n('unknown'))) log.debug("Passed details: " + str(details)) log.debug("Passed extraData: " + str(extraData)) if details.get('title', '') == '': return - if extraData.get('mode',None) is None: - mode="&mode=0" + if extraData.get('mode', None) is None: + mode = "&mode=0" else: - mode="&mode=%s" % extraData['mode'] - - #Create the URL to pass to the item + mode = "&mode=%s" % extraData['mode'] + + # Create the URL to pass to the item if url.startswith('http'): u = sys.argv[0] + "?url=" + urllib.quote(url) + mode + "&media_type=" + extraData["itemtype"] else: u = sys.argv[0] + "?item_id=" + url + "&mode=PLAY" - #Create the ListItem that will be displayed - thumbPath=str(extraData.get('thumb','')) - - listItemName = details.get('title','Unknown') - + # Create the ListItem that will be displayed + thumbPath = str(extraData.get('thumb', '')) + + listItemName = details.get('title', i18n('unknown')) + # calculate percentage cappedPercentage = None if (extraData.get('resumetime') != None and int(extraData.get('resumetime')) > 0): duration = float(extraData.get('duration')) - if(duration > 0): + if (duration > 0): resume = float(extraData.get('resumetime')) percentage = int((resume / duration) * 100.0) cappedPercentage = percentage @@ -290,17 +301,17 @@ def addGUIItem( url, details, extraData, folder=True ): if(cappedPercentage == 100): cappedPercentage = 90 ''' - + if (extraData.get('TotalEpisodes') != None and extraData.get('TotalEpisodes') != "0"): totalItems = int(extraData.get('TotalEpisodes')) watched = int(extraData.get('WatchedEpisodes')) percentage = int((float(watched) / float(totalItems)) * 100.0) - cappedPercentage = percentage - if(cappedPercentage == 0): + cappedPercentage = percentage + if (cappedPercentage == 0): cappedPercentage = None - if(cappedPercentage == 100): + if (cappedPercentage == 100): cappedPercentage = None - + ''' cappedPercentage = percentage - (percentage % 10) if(cappedPercentage == 0): @@ -308,15 +319,15 @@ def addGUIItem( url, details, extraData, folder=True ): if(cappedPercentage == 100): cappedPercentage = 90 ''' - + countsAdded = False - addCounts = __settings__.getSetting('addCounts') == 'true' + addCounts = settings.getSetting('addCounts') == 'true' if addCounts and extraData.get('UnWatchedEpisodes') != "0": countsAdded = True - listItemName = listItemName + " (" + extraData.get('UnWatchedEpisodes') + ")" - - addResumePercent = __settings__.getSetting('addResumePercent') == 'true' - if(countsAdded == False and addResumePercent and details.get('title') != None and cappedPercentage != None): + listItemName = listItemName + " (" + extraData.get('UnWatchedEpisodes') + ")" + + addResumePercent = settings.getSetting('addResumePercent') == 'true' + if (countsAdded == False and addResumePercent and details.get('title') != None and cappedPercentage != None): listItemName = listItemName + " (" + str(cappedPercentage) + "%)" # update title with new name, this sets the new name in the deailts that are later passed to video info @@ -328,47 +339,47 @@ def addGUIItem( url, details, extraData, folder=True ): list_item = xbmcgui.ListItem(listItemName, iconImage=thumbPath, thumbnailImage=thumbPath) log.debug("Setting thumbnail as " + thumbPath) - + # calculate percentage if (cappedPercentage != None): list_item.setProperty("complete_percentage", str(cappedPercentage)) - - #For all end items - if(not folder): - #list_item.setProperty('IsPlayable', 'true') - if extraData.get('type','video').lower() == "video": + + # For all end items + if (not folder): + # list_item.setProperty('IsPlayable', 'true') + if extraData.get('type', 'video').lower() == "video": list_item.setProperty('TotalTime', str(extraData.get('duration'))) list_item.setProperty('ResumeTime', str(int(extraData.get('resumetime')))) - - #StartPercent - + + # StartPercent + artTypes = ['thumb', 'poster', 'fanart', 'clearlogo', 'discart', 'banner', 'clearart', 'landscape', 'tvshow.poster'] artLinks = {} for artType in artTypes: artLinks[artType] = extraData.get(artType, '') log.debug("Setting " + artType + " as " + artLinks[artType]) - list_item.setProperty('fanart_image', artLinks['fanart']) # back compat - list_item.setProperty('discart', artLinks['discart']) # not avail to setArt - list_item.setProperty('tvshow.poster', artLinks['tvshow.poster']) # not avail to setArt + list_item.setProperty('fanart_image', artLinks['fanart']) # back compat + list_item.setProperty('discart', artLinks['discart']) # not avail to setArt + list_item.setProperty('tvshow.poster', artLinks['tvshow.poster']) # not avail to setArt list_item.setArt(artLinks) menuItems = addContextMenu(details, extraData, folder) - if(len(menuItems) > 0): - list_item.addContextMenuItems( menuItems, True ) + if (len(menuItems) > 0): + list_item.addContextMenuItems(menuItems, True) # new way videoInfoLabels = {} - - if(extraData.get('type') == None or extraData.get('type') == "Video"): + + if (extraData.get('type') == None or extraData.get('type') == "Video"): videoInfoLabels.update(details) else: - list_item.setInfo( type = extraData.get('type','Video'), infoLabels = details ) - + list_item.setInfo(type=extraData.get('type', 'Video'), infoLabels=details) + videoInfoLabels["duration"] = extraData.get("duration") videoInfoLabels["playcount"] = extraData.get("playcount") if (extraData.get('favorite') == 'true'): - videoInfoLabels["top250"] = "1" - + videoInfoLabels["top250"] = "1" + videoInfoLabels["mpaa"] = extraData.get('mpaa') videoInfoLabels["rating"] = extraData.get('rating') videoInfoLabels["director"] = extraData.get('director') @@ -376,38 +387,42 @@ def addGUIItem( url, details, extraData, folder=True ): videoInfoLabels["year"] = extraData.get('year') videoInfoLabels["studio"] = extraData.get('studio') videoInfoLabels["genre"] = extraData.get('genre') - + videoInfoLabels["episode"] = details.get('episode') videoInfoLabels["season"] = details.get('season') videoInfoLabels["mediatype"] = "video" list_item.setInfo('video', videoInfoLabels) - - list_item.addStreamInfo('video', {'duration': extraData.get('duration'), 'aspect': extraData.get('aspectratio'),'codec': extraData.get('videocodec'), 'width' : extraData.get('width'), 'height' : extraData.get('height')}) - list_item.addStreamInfo('audio', {'codec': extraData.get('audiocodec'),'channels': extraData.get('channels')}) - + + list_item.addStreamInfo('video', + {'duration': extraData.get('duration'), 'aspect': extraData.get('aspectratio'), + 'codec': extraData.get('videocodec'), 'width': extraData.get('width'), + 'height': extraData.get('height')}) + list_item.addStreamInfo('audio', {'codec': extraData.get('audiocodec'), 'channels': extraData.get('channels')}) + list_item.setProperty('CriticRating', str(extraData.get('criticrating'))) list_item.setProperty('ItemType', extraData.get('itemtype')) if extraData.get('totaltime') != None: list_item.setProperty('TotalTime', extraData.get('totaltime')) if extraData.get('TotalSeasons') != None: - list_item.setProperty('TotalSeasons',extraData.get('TotalSeasons')) - if extraData.get('TotalEpisodes') != None: - list_item.setProperty('TotalEpisodes',extraData.get('TotalEpisodes')) + list_item.setProperty('TotalSeasons', extraData.get('TotalSeasons')) + if extraData.get('TotalEpisodes') != None: + list_item.setProperty('TotalEpisodes', extraData.get('TotalEpisodes')) if extraData.get('WatchedEpisodes') != None: - list_item.setProperty('WatchedEpisodes',extraData.get('WatchedEpisodes')) + list_item.setProperty('WatchedEpisodes', extraData.get('WatchedEpisodes')) if extraData.get('UnWatchedEpisodes') != None: - list_item.setProperty('UnWatchedEpisodes',extraData.get('UnWatchedEpisodes')) + list_item.setProperty('UnWatchedEpisodes', extraData.get('UnWatchedEpisodes')) if extraData.get('NumEpisodes') != None: - list_item.setProperty('NumEpisodes',extraData.get('NumEpisodes')) - + list_item.setProperty('NumEpisodes', extraData.get('NumEpisodes')) + list_item.setProperty('ItemGUID', extraData.get('guiid')) list_item.setProperty('id', extraData.get('id')) - + return (u, list_item, folder) + def addContextMenu(details, extraData, folder): commands = [] @@ -418,24 +433,25 @@ def addContextMenu(details, extraData, folder): # watched/unwatched if extraData.get("playcount") == "0": argsToPass = 'markWatched,' + extraData.get('id') - commands.append((__language__(30270), "RunScript(" + scriptToRun + ", " + argsToPass + ")")) + commands.append((i18n('emby_mark_watched'), "RunScript(" + scriptToRun + ", " + argsToPass + ")")) else: argsToPass = 'markUnwatched,' + extraData.get('id') - commands.append((__language__(30271), "RunScript(" + scriptToRun + ", " + argsToPass + ")")) - + commands.append((i18n('emby_mark_unwatched'), "RunScript(" + scriptToRun + ", " + argsToPass + ")")) + # favourite add/remove if extraData.get('favorite') != 'true': argsToPass = 'markFavorite,' + extraData.get('id') - commands.append((__language__(30272), "RunScript(" + scriptToRun + ", " + argsToPass + ")")) + commands.append((i18n('emby_set_favorite'), "RunScript(" + scriptToRun + ", " + argsToPass + ")")) else: argsToPass = 'unmarkFavorite,' + extraData.get('id') - commands.append((__language__(30273), "RunScript(" + scriptToRun + ", " + argsToPass + ")")) - + commands.append((i18n('emby_unset_favorite'), "RunScript(" + scriptToRun + ", " + argsToPass + ")")) + # delete argsToPass = 'delete,' + extraData.get('id') - commands.append((__language__(30274), "RunScript(" + scriptToRun + ", " + argsToPass + ")")) - - return(commands) + commands.append((i18n('emby_delete'), "RunScript(" + scriptToRun + ", " + argsToPass + ")")) + + return (commands) + def get_params(paramstring): log.debug("Parameter string: " + paramstring) @@ -462,13 +478,14 @@ def get_params(paramstring): log.debug("EmbyCon -> Detected parameters: " + str(param)) return param - -def getContent(url, pluginhandle, media_type): + +def getContent(url, pluginhandle, media_type): log.info("== ENTER: getContent ==") log.info("URL: " + str(url)) log.info("MediaType: " + str(media_type)) + settings = xbmcaddon.Addon(id='plugin.video.embycon') # determine view type, map it from media type to view type viewType = "" media_type = str(media_type).lower().strip() @@ -510,19 +527,19 @@ def getContent(url, pluginhandle, media_type): # show a progress indicator if needed progress = None - if(__settings__.getSetting('showLoadProgress') == "true"): + if (settings.getSetting('showLoadProgress') == "true"): progress = xbmcgui.DialogProgress() progress.create("Loading Content") progress.update(0, "Retrieving Data") - + # use the data manager to get the data result = dataManager.GetContent(url) - + if result == None or len(result) == 0: - if(progress != None): + if (progress != None): progress.close() return - + dirItems = processDirectory(url, result, progress, pluginhandle) xbmcplugin.addDirectoryItems(pluginhandle, dirItems) @@ -532,15 +549,16 @@ def getContent(url, pluginhandle, media_type): log.info("SETTING_VIEW : " + str(viewType) + " : " + str(viewNum)) if viewNum is not None: xbmc.executebuiltin("Container.SetViewMode(%s)" % int(viewNum)) - + xbmcplugin.endOfDirectory(pluginhandle, cacheToDisc=False) - - if(progress != None): - progress.update(100, __language__(30125)) + + if (progress != None): + progress.update(100, i18n('done')) progress.close() - + return + def processDirectory(url, results, progress, pluginhandle): cast = ['None'] log.info("== ENTER: processDirectory ==") @@ -555,32 +573,32 @@ def processDirectory(url, results, progress, pluginhandle): server = host + ":" + port detailsString = getDetailsString() - + dirItems = [] result = results.get("Items") - if(result == None): + if (result == None): result = [] item_count = len(result) current_item = 1 for item in result: - - if(progress != None): + + if (progress != None): percentDone = (float(current_item) / float(item_count)) * 100 - progress.update(int(percentDone), __language__(30126) + str(current_item)) + progress.update(int(percentDone), i18n('processing_item:') + str(current_item)) current_item = current_item + 1 - - if(item.get("Name") != None): + + if (item.get("Name") != None): tempTitle = item.get("Name").encode('utf-8') else: - tempTitle = __language__(20280) - + tempTitle = i18n('missing_title') + id = str(item.get("Id")).encode('utf-8') guiid = id isFolder = item.get("IsFolder") - + item_type = str(item.get("Type")).encode('utf-8') - + tempEpisode = "" if (item.get("IndexNumber") != None): episodeNum = item.get("IndexNumber") @@ -588,7 +606,7 @@ def processDirectory(url, results, progress, pluginhandle): tempEpisode = "0" + str(episodeNum) else: tempEpisode = str(episodeNum) - + tempSeason = "" if (str(item.get("ParentIndexNumber")) != None): tempSeason = str(item.get("ParentIndexNumber")) @@ -598,30 +616,30 @@ def processDirectory(url, results, progress, pluginhandle): if item.get("Type") == "Season": guiid = item.get("SeriesId") elif item.get("Type") == "Episode": - prefix='' - if __settings__.getSetting('addSeasonNumber') == 'true': + prefix = '' + if settings.getSetting('addSeasonNumber') == 'true': prefix = "S" + str(tempSeason) - if __settings__.getSetting('addEpisodeNumber') == 'true': + if settings.getSetting('addEpisodeNumber') == 'true': prefix = prefix + "E" - #prefix = str(tempEpisode) - if __settings__.getSetting('addEpisodeNumber') == 'true': + # prefix = str(tempEpisode) + if settings.getSetting('addEpisodeNumber') == 'true': prefix = prefix + str(tempEpisode) if prefix != '': tempTitle = prefix + ' - ' + tempTitle guiid = item.get("SeriesId") - - if(item.get("PremiereDate") != None): + + if (item.get("PremiereDate") != None): premieredatelist = (item.get("PremiereDate")).split("T") premieredate = premieredatelist[0] else: premieredate = "" - + # add the premiered date for Upcoming TV if item.get("LocationType") == "Virtual": airtime = item.get("AirTime") - tempTitle = tempTitle + ' - ' + str(premieredate) + ' - ' + str(airtime) + tempTitle = tempTitle + ' - ' + str(premieredate) + ' - ' + str(airtime) - # Process MediaStreams + # Process MediaStreams channels = '' videocodec = '' audiocodec = '' @@ -630,37 +648,37 @@ def processDirectory(url, results, progress, pluginhandle): aspectratio = '1:1' aspectfloat = 0.0 mediaStreams = item.get("MediaStreams") - if(mediaStreams != None): + if (mediaStreams != None): for mediaStream in mediaStreams: - if(mediaStream.get("Type") == "Video"): + if (mediaStream.get("Type") == "Video"): videocodec = mediaStream.get("Codec") height = str(mediaStream.get("Height")) width = str(mediaStream.get("Width")) aspectratio = mediaStream.get("AspectRatio") if aspectratio != None and len(aspectratio) >= 3: try: - aspectwidth,aspectheight = aspectratio.split(':') + aspectwidth, aspectheight = aspectratio.split(':') aspectfloat = float(aspectwidth) / float(aspectheight) except: aspectfloat = 1.85 - if(mediaStream.get("Type") == "Audio"): + if (mediaStream.get("Type") == "Audio"): audiocodec = mediaStream.get("Codec") channels = mediaStream.get("Channels") - + # Process People director = '' writer = '' cast = [] people = item.get("People") - if(people != None): + if (people != None): for person in people: - if(person.get("Type") == "Director"): - director = director + person.get("Name") + ' ' - if(person.get("Type") == "Writing"): + if (person.get("Type") == "Director"): + director = director + person.get("Name") + ' ' + if (person.get("Type") == "Writing"): writer = person.get("Name") - if(person.get("Type") == "Writer"): - writer = person.get("Name") - if(person.get("Type") == "Actor"): + if (person.get("Type") == "Writer"): + writer = person.get("Name") + if (person.get("Type") == "Actor"): Name = person.get("Name") Role = person.get("Role") if Role == None: @@ -670,28 +688,28 @@ def processDirectory(url, results, progress, pluginhandle): # Process Studios studio = "" studios = item.get("Studios") - if(studios != None): + if (studios != None): for studio_string in studios: - if studio=="": #Just take the first one - temp=studio_string.get("Name") - studio=temp.encode('utf-8') + if studio == "": # Just take the first one + temp = studio_string.get("Name") + studio = temp.encode('utf-8') # Process Genres genre = "" genres = item.get("Genres") - if(genres != None and genres != []): + if (genres != None and genres != []): for genre_string in genres: - if genre == "": #Just take the first genre + if genre == "": # Just take the first genre genre = genre_string elif genre_string != None: genre = genre + " / " + genre_string - + # Process UserData userData = item.get("UserData") PlaybackPositionTicks = '100' overlay = "0" favorite = "false" seekTime = 0 - if(userData != None): + if (userData != None): if userData.get("Played") != True: overlay = "7" watched = "true" @@ -709,33 +727,33 @@ def processDirectory(url, results, progress, pluginhandle): PlaybackPositionTicks = str(userData.get("PlaybackPositionTicks")) reasonableTicks = int(userData.get("PlaybackPositionTicks")) / 1000 seekTime = reasonableTicks / 10000 - + playCount = 0 - if(userData != None and userData.get("Played") == True): + if (userData != None and userData.get("Played") == True): playCount = 1 # Populate the details list - details={'title' : tempTitle, - 'plot' : item.get("Overview"), - 'episode' : tempEpisode, - #'watched' : watched, - 'Overlay' : overlay, - 'playcount' : str(playCount), - #'aired' : episode.get('originallyAvailableAt','') , - 'TVShowTitle' : item.get("SeriesName"), - 'season' : tempSeason - } - + details = {'title': tempTitle, + 'plot': item.get("Overview"), + 'episode': tempEpisode, + # 'watched' : watched, + 'Overlay': overlay, + 'playcount': str(playCount), + # 'aired' : episode.get('originallyAvailableAt','') , + 'TVShowTitle': item.get("SeriesName"), + 'season': tempSeason + } + try: - tempDuration = str(int(item.get("RunTimeTicks", "0"))/(10000000)) + tempDuration = str(int(item.get("RunTimeTicks", "0")) / (10000000)) RunTimeTicks = str(item.get("RunTimeTicks", "0")) except TypeError: try: - tempDuration = str(int(item.get("CumulativeRunTimeTicks"))/(10000000)) + tempDuration = str(int(item.get("CumulativeRunTimeTicks")) / (10000000)) RunTimeTicks = str(item.get("CumulativeRunTimeTicks")) except TypeError: tempDuration = "0" RunTimeTicks = "0" - + TotalSeasons = 0 if item.get("ChildCount") == None else item.get("ChildCount") TotalEpisodes = 0 if item.get("RecursiveItemCount") == None else item.get("RecursiveItemCount") WatchedEpisodes = 0 if userData.get("UnplayedItemCount") == None else TotalEpisodes - userData.get("UnplayedItemCount") @@ -744,60 +762,60 @@ def processDirectory(url, results, progress, pluginhandle): art = getArt(item, server) # Populate the extraData list - extraData={'thumb' : art['thumb'], - 'fanart' : art['fanart'], - 'poster' : art['poster'], - 'banner' : art['banner'], - 'clearlogo' : art['clearlogo'], - 'discart' : art['discart'], - 'clearart' : art['clearart'], - 'landscape' : art['landscape'], - 'tvshow.poster': art['tvshow.poster'], - 'id' : id , - 'guiid' : guiid , - 'mpaa' : item.get("OfficialRating"), - 'rating' : item.get("CommunityRating"), - 'criticrating' : item.get("CriticRating"), - 'year' : item.get("ProductionYear"), - 'locationtype' : item.get("LocationType"), - 'premieredate' : premieredate, - 'studio' : studio, - 'genre' : genre, - 'playcount' : str(playCount), - 'director' : director, - 'writer' : writer, - 'channels' : channels, - 'videocodec' : videocodec, - 'aspectratio' : str(aspectfloat), - 'audiocodec' : audiocodec, - 'height' : height, - 'width' : width, - 'cast' : cast, - 'favorite' : favorite, - 'parenturl' : url, - 'resumetime' : str(seekTime), - 'totaltime' : tempDuration, - 'duration' : tempDuration, - 'RecursiveItemCount' : item.get("RecursiveItemCount"), - 'RecursiveUnplayedItemCount' : userData.get("UnplayedItemCount"), - 'TotalSeasons' : str(TotalSeasons), - 'TotalEpisodes': str(TotalEpisodes), - 'WatchedEpisodes': str(WatchedEpisodes), - 'UnWatchedEpisodes': str(UnWatchedEpisodes), - 'NumEpisodes' : str(NumEpisodes), - 'itemtype' : item_type} + extraData = {'thumb': art['thumb'], + 'fanart': art['fanart'], + 'poster': art['poster'], + 'banner': art['banner'], + 'clearlogo': art['clearlogo'], + 'discart': art['discart'], + 'clearart': art['clearart'], + 'landscape': art['landscape'], + 'tvshow.poster': art['tvshow.poster'], + 'id': id, + 'guiid': guiid, + 'mpaa': item.get("OfficialRating"), + 'rating': item.get("CommunityRating"), + 'criticrating': item.get("CriticRating"), + 'year': item.get("ProductionYear"), + 'locationtype': item.get("LocationType"), + 'premieredate': premieredate, + 'studio': studio, + 'genre': genre, + 'playcount': str(playCount), + 'director': director, + 'writer': writer, + 'channels': channels, + 'videocodec': videocodec, + 'aspectratio': str(aspectfloat), + 'audiocodec': audiocodec, + 'height': height, + 'width': width, + 'cast': cast, + 'favorite': favorite, + 'parenturl': url, + 'resumetime': str(seekTime), + 'totaltime': tempDuration, + 'duration': tempDuration, + 'RecursiveItemCount': item.get("RecursiveItemCount"), + 'RecursiveUnplayedItemCount': userData.get("UnplayedItemCount"), + 'TotalSeasons': str(TotalSeasons), + 'TotalEpisodes': str(TotalEpisodes), + 'WatchedEpisodes': str(WatchedEpisodes), + 'UnWatchedEpisodes': str(UnWatchedEpisodes), + 'NumEpisodes': str(NumEpisodes), + 'itemtype': item_type} extraData["Path"] = item.get("Path") extraData['mode'] = "GET_CONTENT" - + if isFolder == True: - u = ('http://' + server + '/emby/Users/' + - userid + - '/items?ParentId=' + id + - '&IsVirtualUnAired=false&IsMissing=false&Fields=' + - detailsString + '&format=json') - + u = ('http://' + server + '/emby/Users/' + + userid + + '/items?ParentId=' + id + + '&IsVirtualUnAired=false&IsMissing=false&Fields=' + + detailsString + '&format=json') + if (item.get("RecursiveItemCount") != 0): dirItems.append(addGUIItem(u, details, extraData)) else: @@ -806,95 +824,97 @@ def processDirectory(url, results, progress, pluginhandle): return dirItems + def showSetViews(): log.info("showSetViews Called") - + defaultViews = DefaultViews("DefaultViews.xml", __cwd__, "default", "720p") defaultViews.doModal() del defaultViews - + + def getWigetContent(pluginName, handle, params): log.info("getWigetContent Called" + str(params)) home_window = HomeWindow() - port = __settings__.getSetting('port') - host = __settings__.getSetting('ipaddress') - server = host + ":" + port - + settings = xbmcaddon.Addon(id='plugin.video.embycon') + port = settings.getSetting('port') + host = settings.getSetting('ipaddress') + server = host + ":" + port + type = params.get("type") - if(type == None): + if (type == None): log.error("getWigetContent type not set") return - + userid = downloadUtils.getUserId() - + itemsUrl = ("http://" + server + "/emby/Users/" + userid + "/Items" - "?Limit=20" - "&format=json" - "&ImageTypeLimit=1" - "&IsMissing=False" - "&Fields=" + getDetailsString()) - - if(type == "recent_movies"): + "?Limit=20" + "&format=json" + "&ImageTypeLimit=1" + "&IsMissing=False" + "&Fields=" + getDetailsString()) + + if (type == "recent_movies"): itemsUrl += ("&Recursive=true" - "&SortBy=DateCreated" - "&SortOrder=Descending" - "&Filters=IsUnplayed,IsNotFolder" - "&IsVirtualUnaired=false" - "&IsMissing=False" - "&IncludeItemTypes=Movie") - elif(type == "inprogress_movies"): + "&SortBy=DateCreated" + "&SortOrder=Descending" + "&Filters=IsUnplayed,IsNotFolder" + "&IsVirtualUnaired=false" + "&IsMissing=False" + "&IncludeItemTypes=Movie") + elif (type == "inprogress_movies"): itemsUrl += ("&Recursive=true" - "&SortBy=DatePlayed" - "&SortOrder=Descending" - "&Filters=IsResumable" - "&IsVirtualUnaired=false" - "&IsMissing=False" - "&IncludeItemTypes=Movie") - elif(type == "random_movies"): + "&SortBy=DatePlayed" + "&SortOrder=Descending" + "&Filters=IsResumable" + "&IsVirtualUnaired=false" + "&IsMissing=False" + "&IncludeItemTypes=Movie") + elif (type == "random_movies"): itemsUrl += ("&Recursive=true" - "&SortBy=Random" - "&SortOrder=Descending" - "&Filters=IsUnplayed,IsNotFolder" - "&IsVirtualUnaired=false" - "&IsMissing=False" - "&IncludeItemTypes=Movie") - elif(type == "recent_episodes"): + "&SortBy=Random" + "&SortOrder=Descending" + "&Filters=IsUnplayed,IsNotFolder" + "&IsVirtualUnaired=false" + "&IsMissing=False" + "&IncludeItemTypes=Movie") + elif (type == "recent_episodes"): itemsUrl += ("&Recursive=true" - "&SortBy=DateCreated" - "&SortOrder=Descending" - "&Filters=IsUnplayed,IsNotFolder" - "&IsVirtualUnaired=false" - "&IsMissing=False" - "&IncludeItemTypes=Episode") - elif(type == "inprogress_episodes"): + "&SortBy=DateCreated" + "&SortOrder=Descending" + "&Filters=IsUnplayed,IsNotFolder" + "&IsVirtualUnaired=false" + "&IsMissing=False" + "&IncludeItemTypes=Episode") + elif (type == "inprogress_episodes"): itemsUrl += ("&Recursive=true" - "&SortBy=DatePlayed" - "&SortOrder=Descending" - "&Filters=IsResumable" - "&IsVirtualUnaired=false" - "&IsMissing=False" - "&IncludeItemTypes=Episode") - elif(type == "nextup_episodes"): + "&SortBy=DatePlayed" + "&SortOrder=Descending" + "&Filters=IsResumable" + "&IsVirtualUnaired=false" + "&IsMissing=False" + "&IncludeItemTypes=Episode") + elif (type == "nextup_episodes"): itemsUrl = ("http://" + server + "/emby/Shows/NextUp" - "?Limit=20" - "&userid=" + userid + "" - "&Recursive=true" - "&format=json" - "&ImageTypeLimit=1" - "&Fields=" + getDetailsString()) - + "?Limit=20" + "&userid=" + userid + "" + "&Recursive=true" + "&format=json" + "&ImageTypeLimit=1" + "&Fields=" + getDetailsString()) log.debug("WIDGET_DATE_URL: " + itemsUrl) - + # get the items - jsonData = downloadUtils.downloadUrl(itemsUrl, suppress=False, popup=1 ) + jsonData = downloadUtils.downloadUrl(itemsUrl, suppress=False, popup=1) log.debug("Recent(Items) jsonData: " + jsonData) result = json.loads(jsonData) - + result = result.get("Items") - if(result == None): - result = [] + if (result == None): + result = [] itemCount = 1 listItems = [] @@ -903,28 +923,28 @@ def getWigetContent(pluginName, handle, params): name = item.get("Name") episodeDetails = "" log.debug("WIDGET_DATE_NAME: " + name) - + title = item.get("Name") tvshowtitle = "" - - if(item.get("Type") == "Episode" and item.get("SeriesName") != None): + + if (item.get("Type") == "Episode" and item.get("SeriesName") != None): eppNumber = "X" tempEpisodeNumber = "0" - if(item.get("IndexNumber") != None): + if (item.get("IndexNumber") != None): eppNumber = item.get("IndexNumber") if eppNumber < 10: tempEpisodeNumber = "0" + str(eppNumber) else: - tempEpisodeNumber = str(eppNumber) + tempEpisodeNumber = str(eppNumber) seasonNumber = item.get("ParentIndexNumber") if seasonNumber < 10: tempSeasonNumber = "0" + str(seasonNumber) else: - tempSeasonNumber = str(seasonNumber) - - episodeDetails = "S" + tempSeasonNumber + "E" + tempEpisodeNumber + tempSeasonNumber = str(seasonNumber) + + episodeDetails = "S" + tempSeasonNumber + "E" + tempEpisodeNumber name = item.get("SeriesName") + " " + episodeDetails tvshowtitle = episodeDetails title = item.get("SeriesName") @@ -936,8 +956,8 @@ def getWigetContent(pluginName, handle, params): else: list_item = xbmcgui.ListItem(label=name, iconImage=art['thumb']) - #list_item.setLabel2(episodeDetails) - list_item.setInfo( type="Video", infoLabels={ "title": title, "tvshowtitle": tvshowtitle } ) + # list_item.setLabel2(episodeDetails) + list_item.setInfo(type="Video", infoLabels={"title": title, "tvshowtitle": tvshowtitle}) list_item.setProperty('fanart_image', art['fanart']) # back compat list_item.setProperty('discart', art['discart']) # not avail to setArt list_item.setArt(art) @@ -946,10 +966,10 @@ def getWigetContent(pluginName, handle, params): itemCount = itemCount + 1 list_item.setProperty('IsPlayable', 'true') - + totalTime = str(int(float(item.get("RunTimeTicks", "0")) / (10000000 * 60))) list_item.setProperty('TotalTime', str(totalTime)) - + # add stream info # Process MediaStreams channels = '' @@ -960,87 +980,93 @@ def getWigetContent(pluginName, handle, params): aspectratio = '1:1' aspectfloat = 0.0 mediaStreams = item.get("MediaStreams") - if(mediaStreams != None): + if (mediaStreams != None): for mediaStream in mediaStreams: - if(mediaStream.get("Type") == "Video"): + if (mediaStream.get("Type") == "Video"): videocodec = mediaStream.get("Codec") height = str(mediaStream.get("Height")) width = str(mediaStream.get("Width")) aspectratio = mediaStream.get("AspectRatio") if aspectratio != None and len(aspectratio) >= 3: try: - aspectwidth,aspectheight = aspectratio.split(':') + aspectwidth, aspectheight = aspectratio.split(':') aspectfloat = float(aspectwidth) / float(aspectheight) except: aspectfloat = 1.85 - if(mediaStream.get("Type") == "Audio"): + if (mediaStream.get("Type") == "Audio"): audiocodec = mediaStream.get("Codec") channels = mediaStream.get("Channels") - - list_item.addStreamInfo('video', {'duration': str(totalTime), 'aspect': str(aspectratio), 'codec': str(videocodec), 'width' : str(width), 'height' : str(height)}) - list_item.addStreamInfo('audio', {'codec': str(audiocodec),'channels': str(channels)}) - + + list_item.addStreamInfo('video', {'duration': str(totalTime), 'aspect': str(aspectratio), + 'codec': str(videocodec), 'width': str(width), 'height': str(height)}) + list_item.addStreamInfo('audio', {'codec': str(audiocodec), 'channels': str(channels)}) + # add progress percent userData = item.get("UserData") - if(userData != None): + if (userData != None): playBackTicks = float(userData.get("PlaybackPositionTicks")) - if(playBackTicks != None and playBackTicks > 0): + if (playBackTicks != None and playBackTicks > 0): runTimeTicks = float(item.get("RunTimeTicks", "0")) - if(runTimeTicks > 0): - + if (runTimeTicks > 0): playBackPos = int(((playBackTicks / 1000) / 10000) / 60) list_item.setProperty('ResumeTime', str(playBackPos)) - + percentage = int((playBackTicks / runTimeTicks) * 100.0) - #cappedPercentage = percentage - (percentage % 10) - #if(cappedPercentage == 0): + # cappedPercentage = percentage - (percentage % 10) + # if(cappedPercentage == 0): # cappedPercentage = 10 - #if(cappedPercentage == 100): + # if(cappedPercentage == 100): # cappedPercentage = 90 list_item.setProperty("complete_percentage", str(percentage)) - playurl = "plugin://plugin.video.embycon/?item_id=" + item_id + '&mode=PLAY'# + "×tamp=" + str(datetime.today()) - + playurl = "plugin://plugin.video.embycon/?item_id=" + item_id + '&mode=PLAY' # + "×tamp=" + str(datetime.today()) + itemTupple = (playurl, list_item, False) listItems.append(itemTupple) - + xbmcplugin.addDirectoryItems(handle, listItems) xbmcplugin.endOfDirectory(handle, cacheToDisc=False) - + + def showContent(pluginName, handle, params): log.info("showContent Called: " + str(params)) - - port = __settings__.getSetting('port') - host = __settings__.getSetting('ipaddress') + + settings = xbmcaddon.Addon(id='plugin.video.embycon') + port = settings.getSetting('port') + host = settings.getSetting('ipaddress') server = host + ":" + port - + item_type = params.get("item_type") userid = downloadUtils.getUserId() media_type = params.get("media_type", None) if not media_type: - xbmcgui.Dialog().ok(__language__(30135), __language__(30139)) - - contentUrl = ("http://" + server + "/emby/Users/" + userid + "/Items" - "?format=json" - "&ImageTypeLimit=1" - "&IsMissing=False" - "&Fields=" + getDetailsString() + "" - "&Recursive=true" - "&IsVirtualUnaired=false" - "&IsMissing=False" - "&IncludeItemTypes=" + item_type) + xbmcgui.Dialog().ok(i18n('error'), i18n('no_media_type')) + + contentUrl = ("http://" + server + "/emby/Users/" + userid + + "/Items" + "?format=json" + "&ImageTypeLimit=1" + "&IsMissing=False" + "&Fields=" + getDetailsString() + + "" + "&Recursive=true" + "&IsVirtualUnaired=false" + "&IsMissing=False" + "&IncludeItemTypes=" + item_type) log.info("showContent Content Url : " + str(contentUrl)) - + getContent(contentUrl, handle, media_type) - + + def showParentContent(pluginName, handle, params): log.info("showParentContent Called: " + str(params)) - - port = __settings__.getSetting('port') - host = __settings__.getSetting('ipaddress') + + settings = xbmcaddon.Addon(id='plugin.video.embycon') + port = settings.getSetting('port') + host = settings.getSetting('ipaddress') server = host + ":" + port - + parentId = params.get("ParentId") name = params.get("Name") detailsString = getDetailsString() @@ -1048,8 +1074,8 @@ def showParentContent(pluginName, handle, params): media_type = params.get("media_type", None) if not media_type: - xbmcgui.Dialog().ok(__language__(30135), __language__(30139)) - + xbmcgui.Dialog().ok(i18n('error'), i18n('no_media_type')) + contentUrl = ( "http://" + server + "/emby/Users/" + userid + "/items?ParentId=" + parentId + @@ -1059,30 +1085,31 @@ def showParentContent(pluginName, handle, params): "&CollapseBoxSetItems=true" + "&Fields=" + detailsString + "&format=json") - + log.info("showParentContent Content Url : " + str(contentUrl)) - + getContent(contentUrl, handle, media_type) - + + def checkService(): home_window = HomeWindow() timeStamp = home_window.getProperty("Service_Timestamp") loops = 0 - while(timeStamp == ""): + while (timeStamp == ""): timeStamp = home_window.getProperty("Service_Timestamp") loops = loops + 1 - if(loops == 40): + if (loops == 40): log.error("EmbyCon Service Not Running, no time stamp, exiting") - xbmcgui.Dialog().ok(__language__(30135), __language__(30136), __language__(30137)) + xbmcgui.Dialog().ok(i18n('error'), i18n('service_not_running'), i18n('restart_kodi')) sys.exit() xbmc.sleep(200) - + log.info("EmbyCon Service Timestamp: " + timeStamp) log.info("EmbyCon Current Timestamp: " + str(int(time.time()))) - - if((int(timeStamp) + 240) < int(time.time())): + + if ((int(timeStamp) + 240) < int(time.time())): log.error("EmbyCon Service Not Running, time stamp to old, exiting") - xbmcgui.Dialog().ok(__language__(30135), __language__(30136), __language__(30137)) + xbmcgui.Dialog().ok(i18n('error'), i18n('service_not_running'), i18n('restart_kodi')) sys.exit() diff --git a/resources/lib/kodi_utils.py b/resources/lib/kodi_utils.py index fa49ecd..13d4fb6 100644 --- a/resources/lib/kodi_utils.py +++ b/resources/lib/kodi_utils.py @@ -7,7 +7,7 @@ import json from simple_logging import SimpleLogging -log = SimpleLogging("EmbyCon." + __name__) +log = SimpleLogging(__name__) class HomeWindow(): diff --git a/resources/lib/menu_functions.py b/resources/lib/menu_functions.py index 552a11f..160560b 100644 --- a/resources/lib/menu_functions.py +++ b/resources/lib/menu_functions.py @@ -11,12 +11,13 @@ from downloadutils import DownloadUtils from utils import getDetailsString from kodi_utils import addMenuDirectoryItem from simple_logging import SimpleLogging +from translation import i18n -log = SimpleLogging("EmbyCon." + __name__) +log = SimpleLogging(__name__) downloadUtils = DownloadUtils() __addon__ = xbmcaddon.Addon(id='plugin.video.embycon') -__language__ = __addon__.getLocalizedString + def showGenreList(): log.info("== ENTER: showGenreList() ==") @@ -57,8 +58,8 @@ def showGenreList(): url = sys.argv[0] + ("?url=" + urllib.quote('http://%s%s' % (collection['address'], collection['path'])) + "&mode=GET_CONTENT" + "&media_type=" + collection["media_type"]) - log.info("addMenuDirectoryItem: " + collection.get('title', __language__(30250)) + " " + str(url)) - addMenuDirectoryItem(collection.get('title', __language__(30250)), url, thumbnail=collection.get("thumbnail")) + log.info("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])) @@ -103,12 +104,13 @@ def showMovieAlphaList(): for collection in collections: url = (sys.argv[0] + "?url=" + urllib.quote('http://%s%s' % (collection['address'], collection['path'])) + - "&mode=GET_CONTENT&media_type=" + collection["media_type"]) - log.info("addMenuDirectoryItem: " + collection.get('title', __language__(30250)) + " " + str(url)) - addMenuDirectoryItem(collection.get('title', __language__(30250)), url) + "&mode=GET_CONTENT&media_type=" + collection["media_type"]) + log.info("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() ==") xbmcplugin.setContent(int(sys.argv[1]), 'files') @@ -123,19 +125,20 @@ def displaySections(): collections = getCollections(detailsString) for collection in collections: url = (sys.argv[0] + "?url=" + urllib.quote('http://%s%s' % (collection['address'], collection['path'])) + - "&mode=GET_CONTENT&media_type=" + collection["media_type"]) - log.info("addMenuDirectoryItem: " + collection.get('title', __language__(30250)) + " " + str(url)) - addMenuDirectoryItem(collection.get('title', __language__(30250)), url, thumbnail=collection.get("thumbnail")) + "&mode=GET_CONTENT&media_type=" + collection["media_type"]) + log.info("addMenuDirectoryItem: " + collection.get('title', i18n('unknown')) + " " + str(url)) + addMenuDirectoryItem(collection.get('title', i18n('unknown')), url, thumbnail=collection.get("thumbnail")) - addMenuDirectoryItem(__language__(30251), "plugin://plugin.video.embycon/?mode=MOVIE_GENRA") - addMenuDirectoryItem(__language__(30252), "plugin://plugin.video.embycon/?mode=MOVIE_ALPHA") - addMenuDirectoryItem(__language__(30253), "plugin://plugin.video.embycon/?mode=CHANGE_USER") - addMenuDirectoryItem(__language__(30254), "plugin://plugin.video.embycon/?mode=SHOW_SETTINGS") - addMenuDirectoryItem(__language__(30255), "plugin://plugin.video.embycon/?mode=SET_DEFAULT_VIEWS") - addMenuDirectoryItem(__language__(30247), "plugin://plugin.video.embycon/?mode=WIDGETS") + addMenuDirectoryItem(i18n('movies_genre'), "plugin://plugin.video.embycon/?mode=MOVIE_GENRA") + addMenuDirectoryItem(i18n('movies_az'), "plugin://plugin.video.embycon/?mode=MOVIE_ALPHA") + addMenuDirectoryItem(i18n('change_user'), "plugin://plugin.video.embycon/?mode=CHANGE_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") + addMenuDirectoryItem(i18n('widgets'), "plugin://plugin.video.embycon/?mode=WIDGETS") xbmcplugin.endOfDirectory(int(sys.argv[1])) + def getCollections(detailsString): log.info("== ENTER: getCollections ==") @@ -171,7 +174,7 @@ def getCollections(detailsString): jsonData = downloadUtils.downloadUrl( htmlpath + userid + "/items?ParentId=" + parentid + "&Sortby=SortName&format=json") log.debug("jsonData : " + jsonData) - collections=[] + collections = [] result = [] try: @@ -204,7 +207,7 @@ def getCollections(detailsString): if collection_type == "movies": collections.append({ - 'title': item_name + __language__(30267), + 'title': item_name + i18n('_in_progress'), 'address': server, 'thumbnail': downloadUtils.getArtwork(item, "Primary", server=server), 'path': ('/emby/Users/' + userid + '/Items' + @@ -218,7 +221,7 @@ def getCollections(detailsString): 'media_type': collection_type}) collections.append({ - 'title': item_name + __language__(30268), + 'title': item_name + i18n('_recently_added'), 'address': server, 'thumbnail': downloadUtils.getArtwork(item, "Primary", server=server), 'path': ('/emby/Users/' + userid + '/Items' + @@ -236,7 +239,7 @@ def getCollections(detailsString): # Add standard nodes item_data = {} item_data['address'] = server - item_data['title'] = __language__(30256) + item_data['title'] = i18n('movies_all') item_data['media_type'] = 'Movies' item_data[ 'path'] = '/emby/Users/' + userid + '/Items?Fields=' + detailsString + '&Recursive=true&IncludeItemTypes=Movie&CollapseBoxSetItems=true&ImageTypeLimit=1&format=json' @@ -244,7 +247,7 @@ def getCollections(detailsString): item_data = {} item_data['address'] = server - item_data['title'] = __language__(30257) + item_data['title'] = i18n('movies_recently_added') item_data['media_type'] = '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' @@ -252,7 +255,7 @@ def getCollections(detailsString): item_data = {} item_data['address'] = server - item_data['title'] = __language__(30258) + item_data['title'] = i18n('movies_in_progress') item_data['media_type'] = 'Movies' item_data[ 'path'] = '/emby/Users/' + userid + '/Items?Limit=' + '20' + '&Recursive=true&Fields=' + detailsString + '&Filters=IsResumable&IncludeItemTypes=Movie&ImageTypeLimit=1&format=json' @@ -260,7 +263,7 @@ def getCollections(detailsString): item_data = {} item_data['address'] = server - item_data['title'] = __language__(30259) + item_data['title'] = i18n('movies_favorites') item_data['media_type'] = 'Movies' item_data[ 'path'] = '/emby/Users/' + userid + '/Items?Fields=' + detailsString + '&Recursive=true&Filters=IsFavorite&IncludeItemTypes=Movie&CollapseBoxSetItems=true&ImageTypeLimit=1&format=json' @@ -268,7 +271,7 @@ def getCollections(detailsString): item_data = {} item_data['address'] = server - item_data['title'] = __language__(30260) + item_data['title'] = i18n('movies_boxsets') item_data['media_type'] = 'BoxSets' item_data[ 'path'] = '/emby/Users/' + userid + '/Items?Recursive=true&Fields=' + detailsString + '&IncludeItemTypes=BoxSet&ImageTypeLimit=1&format=json' @@ -276,7 +279,7 @@ def getCollections(detailsString): item_data = {} item_data['address'] = server - item_data['title'] = __language__(30261) + item_data['title'] = i18n('tvshows_all') item_data['media_type'] = 'tvshows' item_data[ 'path'] = '/emby/Users/' + userid + '/Items?Fields=' + detailsString + '&Recursive=true&IncludeItemTypes=Series&ImageTypeLimit=1&format=json' @@ -284,7 +287,7 @@ def getCollections(detailsString): item_data = {} item_data['address'] = server - item_data['title'] = __language__(30262) + item_data['title'] = i18n('tvshows_favorites') item_data['media_type'] = 'tvshows' item_data[ 'path'] = '/emby/Users/' + userid + '/Items?Fields=' + detailsString + '&Recursive=true&Filters=IsFavorite&IncludeItemTypes=Series&ImageTypeLimit=1&format=json' @@ -292,7 +295,7 @@ def getCollections(detailsString): item_data = {} item_data['address'] = server - item_data['title'] = __language__(30263) + item_data['title'] = i18n('episodes_recently_added') item_data['media_type'] = 'Season' 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' @@ -300,7 +303,7 @@ def getCollections(detailsString): item_data = {} item_data['address'] = server - item_data['title'] = __language__(30264) + item_data['title'] = i18n('episodes_in_progress') item_data['media_type'] = 'Episodes' item_data[ 'path'] = '/emby/Users/' + userid + '/Items?Limit=' + '20' + '&Recursive=true&Fields=' + detailsString + '&Filters=IsResumable&IncludeItemTypes=Episode&ImageTypeLimit=1&format=json' @@ -308,7 +311,7 @@ def getCollections(detailsString): item_data = {} item_data['address'] = server - item_data['title'] = __language__(30265) + item_data['title'] = i18n('episodes_up_next') item_data['media_type'] = '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' @@ -316,7 +319,7 @@ def getCollections(detailsString): item_data = {} item_data['address'] = server - item_data['title'] = __language__(30266) + item_data['title'] = i18n('upcoming_tv') item_data['media_type'] = 'Episodes' 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' @@ -326,14 +329,14 @@ def getCollections(detailsString): def showWidgets(): - addMenuDirectoryItem(__language__(30248), 'plugin://plugin.video.embycon/?mode=SHOW_CONTENT&item_type=Movie&media_type=Movies') - addMenuDirectoryItem(__language__(30249), 'plugin://plugin.video.embycon/?mode=SHOW_CONTENT&item_type=Series&media_type=TVShows') + addMenuDirectoryItem(i18n('emby_movies'), 'plugin://plugin.video.embycon/?mode=SHOW_CONTENT&item_type=Movie&media_type=Movies') + addMenuDirectoryItem(i18n('emby_tvshows'), 'plugin://plugin.video.embycon/?mode=SHOW_CONTENT&item_type=Series&media_type=TVShows') - addMenuDirectoryItem(__language__(30257), 'plugin://plugin.video.embycon/?mode=WIDGET_CONTENT&type=recent_movies') - addMenuDirectoryItem(__language__(30258), 'plugin://plugin.video.embycon/?mode=WIDGET_CONTENT&type=inprogress_movies') - addMenuDirectoryItem(__language__(30269), 'plugin://plugin.video.embycon/?mode=WIDGET_CONTENT&type=random_movies') - addMenuDirectoryItem(__language__(30263), 'plugin://plugin.video.embycon/?mode=WIDGET_CONTENT&type=recent_episodes') - addMenuDirectoryItem(__language__(30264), 'plugin://plugin.video.embycon/?mode=WIDGET_CONTENT&type=inprogress_episodes') - addMenuDirectoryItem(__language__(30265), 'plugin://plugin.video.embycon/?mode=WIDGET_CONTENT&type=nextup_episodes') + addMenuDirectoryItem(i18n('movies_recently_added'), 'plugin://plugin.video.embycon/?mode=WIDGET_CONTENT&type=recent_movies') + addMenuDirectoryItem(i18n('movies_in_progress'), 'plugin://plugin.video.embycon/?mode=WIDGET_CONTENT&type=inprogress_movies') + addMenuDirectoryItem(i18n('movies_random'), 'plugin://plugin.video.embycon/?mode=WIDGET_CONTENT&type=random_movies') + addMenuDirectoryItem(i18n('episodes_recently_added'), 'plugin://plugin.video.embycon/?mode=WIDGET_CONTENT&type=recent_episodes') + addMenuDirectoryItem(i18n('episodes_in_progress'), 'plugin://plugin.video.embycon/?mode=WIDGET_CONTENT&type=inprogress_episodes') + addMenuDirectoryItem(i18n('episodes_up_next'), 'plugin://plugin.video.embycon/?mode=WIDGET_CONTENT&type=nextup_episodes') xbmcplugin.endOfDirectory(int(sys.argv[1])) diff --git a/resources/lib/play_utils.py b/resources/lib/play_utils.py index c47bc3b..8be3ee7 100644 --- a/resources/lib/play_utils.py +++ b/resources/lib/play_utils.py @@ -13,18 +13,18 @@ from downloadutils import DownloadUtils from resume_dialog import ResumeDialog from utils import PlayUtils, getArt from kodi_utils import HomeWindow +from translation import i18n -log = SimpleLogging("EmbyCon." + __name__) -__addon__ = xbmcaddon.Addon(id='plugin.video.embycon') -__language__ = __addon__.getLocalizedString +log = SimpleLogging(__name__) downloadUtils = DownloadUtils() + def playFile(id, auto_resume): log.info("playFile id(" + str(id) + ") resume(" + str(auto_resume) + ")") userid = downloadUtils.getUserId() - settings = xbmcaddon.Addon(id='plugin.video.embycon') + settings = xbmcaddon.Addon('plugin.video.embycon') addon_path = settings.getAddonInfo('path') playback_type = settings.getSetting("playback_type") @@ -73,7 +73,7 @@ def playFile(id, auto_resume): home_window = HomeWindow() home_window.setProperty("PlaybackType_" + id, playback_type_string) - listItem = xbmcgui.ListItem(label=result.get("Name", __language__(30280)), path=playurl) + listItem = xbmcgui.ListItem(label=result.get("Name", i18n('missing_title')), path=playurl) listItem = setListItemProps(id, listItem, result, server) @@ -95,11 +95,11 @@ def playFile(id, auto_resume): time.sleep(1) while xbmc.Player().getTime() < (seekTime - 5): - #xbmc.Player().pause() + # xbmc.Player().pause() xbmc.sleep(100) xbmc.Player().seekTime(seekTime) xbmc.sleep(100) - #xbmc.Player().play() + # xbmc.Player().play() def setListItemProps(id, listItem, result, server): @@ -119,7 +119,7 @@ def setListItemProps(id, listItem, result, server): # play info details = { - 'title': result.get("Name", __language__(30280)), + 'title': result.get("Name", i18n('missing_title')), 'plot': result.get("Overview") } @@ -131,4 +131,4 @@ def setListItemProps(id, listItem, result, server): listItem.setInfo("Video", infoLabels=details) - return listItem \ No newline at end of file + return listItem diff --git a/resources/lib/resume_dialog.py b/resources/lib/resume_dialog.py index e45e7be..62afea5 100644 --- a/resources/lib/resume_dialog.py +++ b/resources/lib/resume_dialog.py @@ -1,16 +1,14 @@ # Gnu General Public License - see LICENSE.TXT import xbmcgui -import xbmcaddon from simple_logging import SimpleLogging +from translation import i18n + +log = SimpleLogging(__name__) -log = SimpleLogging("EmbyCon." + __name__) -__addon__ = xbmcaddon.Addon(id='plugin.video.embycon') -__language__ = __addon__.getLocalizedString class ResumeDialog(xbmcgui.WindowXMLDialog): - resumePlay = -1 resumeTimeStamp = "" @@ -21,31 +19,27 @@ class ResumeDialog(xbmcgui.WindowXMLDialog): def onInit(self): self.action_exitkeys_id = [10, 13] self.getControl(3010).setLabel(self.resumeTimeStamp) - self.getControl(3011).setLabel(__language__(30237)) + self.getControl(3011).setLabel(i18n('start_from_beginning')) - def onFocus(self, controlId): + def onFocus(self, controlId): pass - + def doAction(self, actionID): pass def onClick(self, controlID): - - if(controlID == 3010): + + if (controlID == 3010): self.resumePlay = 0 self.close() - if(controlID == 3011): + if (controlID == 3011): self.resumePlay = 1 self.close() - + pass - + def setResumeTime(self, timeStamp): self.resumeTimeStamp = timeStamp - + def getResumeAction(self): return self.resumePlay - - - - \ No newline at end of file diff --git a/resources/lib/server_detect.py b/resources/lib/server_detect.py index 2081cc0..4c0f496 100644 --- a/resources/lib/server_detect.py +++ b/resources/lib/server_detect.py @@ -11,29 +11,30 @@ import xbmc from kodi_utils import HomeWindow from downloadutils import DownloadUtils from simple_logging import SimpleLogging +from translation import i18n -log = SimpleLogging("EmbyCon." + __name__) +log = SimpleLogging(__name__) __addon__ = xbmcaddon.Addon(id='plugin.video.embycon') -__language__ = __addon__.getLocalizedString __addon_name__ = __addon__.getAddonInfo('name') downloadUtils = DownloadUtils() + def getServerDetails(): log.debug("Getting Server Details from Network") MESSAGE = "who is EmbyServer?" MULTI_GROUP = ("", 7359) - + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.settimeout(6.0) - - sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 10) #timeout - + + sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 10) # timeout + sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) sock.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_LOOP, 1) sock.setsockopt(socket.IPPROTO_IP, socket.SO_REUSEADDR, 1) - + log.debug("MutliGroup : " + str(MULTI_GROUP)) log.debug("Sending UDP Data : " + MESSAGE) sock.sendto(MESSAGE, MULTI_GROUP) @@ -77,8 +78,8 @@ def checkServer(force=False, change_user=False, notify=False): serverNames = [] for server in serverInfo: - serverNames.append(server.get("Name", __language__(30063))) - return_index = xbmcgui.Dialog().select(__language__(30166), serverNames) + serverNames.append(server.get("Name", i18n('n/a'))) + return_index = xbmcgui.Dialog().select(i18n('select_server'), serverNames) if (return_index == -1): xbmc.executebuiltin("ActivateWindow(Home)") @@ -98,7 +99,8 @@ def checkServer(force=False, change_user=False, notify=False): settings.setSetting("ipaddress", server_address) if notify: - xbmcgui.Dialog().ok(__language__(30167), __language__(30168), __language__(30169) + server_address, __language__(30030) + server_port) + xbmcgui.Dialog().ok(i18n('server_detect_succeeded'), i18n('found_server'), + i18n('address:') + server_address, i18n('server_port:') + server_port) # we need to change the user current_username = settings.getSetting("username") @@ -123,29 +125,29 @@ def checkServer(force=False, change_user=False, notify=False): user_list.append(name) if (user.get("HasPassword") is True): secured.append(True) - name = __language__(30060) % name + name = i18n('username_secured') % name else: secured.append(False) names.append(name) if (len(current_username) > 0) and (not any(n == current_username for n in user_list)): - names.insert(0, __language__(30061) % current_username) + names.insert(0, i18n('username_userdefined') % current_username) user_list.insert(0, current_username) secured.insert(0, True) - names.insert(0, __language__(30062)) + names.insert(0, i18n('username_userinput')) user_list.insert(0, '') secured.insert(0, True) log.debug("User List : " + str(names)) log.debug("User List : " + str(user_list)) - return_value = xbmcgui.Dialog().select(__language__(30180), names) + return_value = xbmcgui.Dialog().select(i18n('select_user'), names) if (return_value > -1): log.debug("Selected User Index : " + str(return_value)) if return_value == 0: kb = xbmc.Keyboard() - kb.setHeading(__language__(30005)) + kb.setHeading(i18n('username:')) kb.doModal() if kb.isConfirmed(): selected_user = kb.getText() @@ -162,7 +164,7 @@ def checkServer(force=False, change_user=False, notify=False): settings.setSetting("username", selected_user) if secured[return_value] is True: kb = xbmc.Keyboard() - kb.setHeading(__language__(30006)) + kb.setHeading(i18n('password:')) kb.setHiddenInput(True) kb.doModal() if kb.isConfirmed(): diff --git a/resources/lib/simple_logging.py b/resources/lib/simple_logging.py index b60067e..0e8b522 100644 --- a/resources/lib/simple_logging.py +++ b/resources/lib/simple_logging.py @@ -3,16 +3,17 @@ import xbmc import xbmcaddon -class SimpleLogging(): +class SimpleLogging(): level = 0 name = "" 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 = name + self.name = prefix + '.' + name def getLevel(self): return self.level @@ -21,26 +22,25 @@ class SimpleLogging(): return "LogLevel: " + str(self.level) def error(self, msg): - if(self.level >= 0): + 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): + 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) def debug(self, msg): - if(self.level >= 2): + if (self.level >= 2): try: xbmc.log(self.format(msg, "DEBUG"), level=xbmc.LOGNOTICE) except UnicodeEncodeError: xbmc.log(self.format(msg, "DEBUG").encode('utf-8'), level=xbmc.LOGNOTICE) def format(self, msg, levelValue): - return self.name + "(" + str(levelValue) + ") -> " + msg \ No newline at end of file + return self.name + "(" + str(levelValue) + ") -> " + msg diff --git a/resources/lib/translation.py b/resources/lib/translation.py new file mode 100644 index 0000000..07e19ae --- /dev/null +++ b/resources/lib/translation.py @@ -0,0 +1,81 @@ +import xbmcaddon +from simple_logging import SimpleLogging + +log = SimpleLogging(__name__) +addon = xbmcaddon.Addon() + + +def i18n(string_id): + try: + return addon.getLocalizedString(STRINGS[string_id]).encode('utf-8', 'ignore') + except Exception as e: + log.error('Failed String Lookup: %s (%s)' % (string_id, e)) + return string_id + + +STRINGS = { + 'server_port:': 30001, + 'username:': 30005, + 'password:': 30006, + 'incorrect_user_pass': 30044, + 'username_not_found': 30045, + 'deleting': 30052, + 'waiting_server_delete': 30053, + 'username_secured': 30060, + 'username_userdefined': 30061, + 'username_userinput': 30062, + 'n/a': 30063, + 'confirm_file_delete': 30091, + 'file_delete_confirm': 30092, + 'done': 30125, + 'processing_item:': 30126, + 'error': 30135, + 'service_not_running': 30136, + 'restart_kodi': 30137, + 'no_media_type': 30139, + 'select_server': 30166, + 'server_detect_succeeded': 30167, + 'found_server': 30168, + 'address:': 30169, + 'select_user': 30180, + 'url_error_': 30200, + 'unable_connect_server': 30201, + 'default_view': 30230, + 'movies': 30231, + 'boxsets': 30232, + 'series': 30233, + 'seasons': 30234, + 'episodes': 30235, + 'save': 30236, + 'start_from_beginning': 30237, + 'default_sort': 30238, + 'widgets': 30247, + 'emby_movies': 30248, + 'emby_tvshows': 30249, + 'unknown': 30250, + 'movies_genre': 30251, + 'movies_az': 30252, + 'change_user': 30253, + 'show_settings': 30254, + 'set_default_views': 30255, + 'movies_all': 30256, + 'movies_recently_added': 30257, + 'movies_in_progress': 30258, + 'movies_favorites': 30259, + 'movies_boxsets': 30260, + 'tvshows_all': 30261, + 'tvshows_favorites': 30262, + 'episodes_recently_added': 30263, + 'episodes_in_progress': 30264, + 'episodes_up_next': 30265, + 'upcoming_tv': 30266, + '_in_progress': 30267, + '_recently_added': 30268, + 'movies_random': 30269, + 'emby_mark_watched': 30270, + 'emby_mark_unwatched': 30271, + 'emby_set_favorite': 30272, + 'emby_unset_favorite': 30273, + 'emby_delete': 30274, + 'missing_title': 30280 +} diff --git a/resources/lib/utils.py b/resources/lib/utils.py index 895c7c5..6f3f420 100644 --- a/resources/lib/utils.py +++ b/resources/lib/utils.py @@ -6,9 +6,10 @@ from downloadutils import DownloadUtils from simple_logging import SimpleLogging from clientinfo import ClientInformation -#define our global download utils +# define our global download utils downloadUtils = DownloadUtils() -log = SimpleLogging("EmbyCon." + __name__) +log = SimpleLogging(__name__) + ########################################################################### class PlayUtils(): @@ -76,9 +77,10 @@ class PlayUtils(): def getDetailsString(): detailsString = "EpisodeCount,SeasonCount,Path,Genres,Studios,CumulativeRunTimeTicks,MediaStreams,Overview,Etag" - #detailsString = "EpisodeCount,SeasonCount,Path,Genres,CumulativeRunTimeTicks" + # detailsString = "EpisodeCount,SeasonCount,Path,Genres,CumulativeRunTimeTicks" return detailsString + def getChecksum(item): userdata = item['UserData'] checksum = "%s_%s_%s_%s_%s_%s_%s" % ( @@ -93,6 +95,7 @@ def getChecksum(item): return checksum + def getArt(item, server, widget=False): art = { 'thumb': '', diff --git a/resources/lib/views.py b/resources/lib/views.py index c521a04..3f714a6 100644 --- a/resources/lib/views.py +++ b/resources/lib/views.py @@ -8,17 +8,17 @@ import xbmcaddon import json from simple_logging import SimpleLogging +from translation import i18n -log = SimpleLogging("EmbyCon." + __name__) +log = SimpleLogging(__name__) __addon__ = xbmcaddon.Addon(id='plugin.video.embycon') -__language__ = __addon__.getLocalizedString + 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')) + __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') @@ -28,8 +28,8 @@ def loadSkinDefaults(): return defaultData + class DefaultViews(xbmcgui.WindowXMLDialog): - viewData = {} sortData = {"Title": "title", "Date": "date"} defaultView = {} @@ -41,36 +41,35 @@ class DefaultViews(xbmcgui.WindowXMLDialog): def onInit(self): self.action_exitkeys_id = [10, 13] - + # load skin views - addonSettings = xbmcaddon.Addon(id='plugin.video.embycon') - addonPath = addonSettings.getAddonInfo('path') + 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) + 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)) self.viewData = skin_views - + # load current default views savedData = loadSkinDefaults() self.defaultView = savedData.get("view", {}) self.defaultSort = savedData.get("sort", {}) - self.getControl(3110).setLabel(__language__(30236)) - self.getControl(3019).setLabel(__language__(30238)) - self.getControl(3020).setLabel(__language__(30230)) - self.getControl(3021).setLabel(__language__(30231)) - self.getControl(3022).setLabel(__language__(30232)) - self.getControl(3023).setLabel(__language__(30233)) - self.getControl(3024).setLabel(__language__(30234)) - self.getControl(3025).setLabel(__language__(30235)) + 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")) @@ -82,7 +81,7 @@ class DefaultViews(xbmcgui.WindowXMLDialog): name = self.getViewNameById(self.defaultView.get("Seasons")) self.getControl(3013).setLabel(name) name = self.getViewNameById(self.defaultView.get("Episodes")) - self.getControl(3014).setLabel(name) + self.getControl(3014).setLabel(name) name = self.getSortNameById(self.defaultSort.get("Movies")) self.getControl(3050).setLabel(name) @@ -95,9 +94,9 @@ class DefaultViews(xbmcgui.WindowXMLDialog): name = self.getSortNameById(self.defaultSort.get("Episodes")) self.getControl(3054).setLabel(name) - def onFocus(self, controlId): + def onFocus(self, controlId): pass - + def doAction(self, actionID): pass @@ -112,22 +111,22 @@ class DefaultViews(xbmcgui.WindowXMLDialog): return "None" def getViewNameById(self, viewId): - if(viewId == None): + 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): + if (current not in keys): return keys[0] - + index = keys.index(current) - if(index > -1 and index < len(keys)-1): + if (index > -1 and index < len(keys) - 1): return keys[index + 1] else: return keys[0] @@ -144,7 +143,7 @@ class DefaultViews(xbmcgui.WindowXMLDialog): return keys[0] def onClick(self, controlID): - + if controlID >= 3010 and controlID <= 3014: control = self.getControl(controlID) control.setLabel(self.getNextViewName(control.getLabel())) @@ -154,7 +153,7 @@ class DefaultViews(xbmcgui.WindowXMLDialog): control.setLabel(self.getNextSortName(control.getLabel())) elif controlID == 3110: - + self.setViewId("Movies", 3010) self.setViewId("BoxSets", 3011) self.setViewId("Series", 3012) @@ -166,30 +165,29 @@ class DefaultViews(xbmcgui.WindowXMLDialog): self.setSortId("Series", 3052) self.setSortId("Seasons", 3053) self.setSortId("Episodes", 3054) - - __addon__ = xbmcaddon.Addon(id='plugin.video.embycon') - __addondir__ = xbmc.translatePath( __addon__.getAddonInfo('profile')) + + __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() + dataFile.close() self.close() - + pass - + def setViewId(self, viewName, labelId): viewId = self.viewData.get(self.getControl(labelId).getLabel()) - if(viewId == None): + 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): + if (sortId == None): return else: self.defaultSort[sortName] = sortId diff --git a/resources/settings.xml b/resources/settings.xml index d427387..8de612d 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -2,7 +2,7 @@ - + diff --git a/service.py b/service.py index 4928a72..eb9f4e6 100644 --- a/service.py +++ b/service.py @@ -17,7 +17,7 @@ home_window.clearProperty("userid") home_window.clearProperty("AccessToken") home_window.clearProperty("Params") -log = SimpleLogging("EmbyCon.service") +log = SimpleLogging('service') download_utils = DownloadUtils() # auth the service @@ -26,14 +26,15 @@ try: except Exception, e: pass + def hasData(data): if data is None or len(data) == 0 or data == "None": return False else: return True -def sendProgress(): +def sendProgress(): playing_file = xbmc.Player().getPlayingFile() play_data = monitor.played_information.get(playing_file) @@ -76,21 +77,20 @@ def sendProgress(): def stopAll(played_information): - if len(played_information) == 0: return - + log.info("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)) - + current_possition = data.get("currentPossition") emby_item_id = data.get("item_id") - + if hasData(emby_item_id): log.info("Playback Stopped at: " + str(int(current_possition * 10000000))) @@ -108,21 +108,20 @@ def stopAll(played_information): download_utils.downloadUrl(url, postBody=postdata, method="POST") played_information.clear() - - -class Service(xbmc.Player): + +class Service(xbmc.Player): played_information = {} - + def __init__(self, *args): log.info("Starting monitor service: " + str(args)) self.played_information = {} pass - + 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) @@ -158,7 +157,7 @@ class Service(xbmc.Player): data["paused"] = False 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)) @@ -204,7 +203,7 @@ class Service(xbmc.Player): monitor = Service() last_progress_update = datetime.today() - + while not xbmc.abortRequested: home_window = HomeWindow() @@ -217,7 +216,7 @@ while not xbmc.abortRequested: if sec_diff > 10: sendProgress() last_progress_update = datetime.today() - + except Exception, e: log.error("Exception in Playback Monitor : " + str(e)) pass