From 748c65efe7d416219906e5dbcbcc18ec0a6d7623 Mon Sep 17 00:00:00 2001 From: angelblue05 Date: Thu, 4 Feb 2016 06:22:33 -0600 Subject: [PATCH 01/13] Validate strings for translation --- resources/language/English/strings.xml | 73 ++++++++++++-------------- resources/lib/videonodes.py | 56 ++++++++++++-------- 2 files changed, 66 insertions(+), 63 deletions(-) diff --git a/resources/language/English/strings.xml b/resources/language/English/strings.xml index ccc61957..880efe68 100644 --- a/resources/language/English/strings.xml +++ b/resources/language/English/strings.xml @@ -126,21 +126,10 @@ - Loop Theme Music Enable Background Image (Requires Restart) Services - Enable Info Loader (Requires Restart) - Enable Menu Loader (Requires Restart) - Enable WebSocket Remote (Requires Restart) - Enable In Progress Loader (Requires Restart) - Enable Recent Info Loader (Requires Restart) - Enable Random Loader (Requires Restart) - Enable Next Up Loader (Requires Restart) Skin does not support setting views Select item action (Requires Restart) - Show Indicators - - Show Watched Indicator - - Show Unplayed Count Indicator - - Show Played Percentage Indicator Sort NextUp by Show Title Enable Enhanced Images (eg CoverArt) Metadata @@ -151,26 +140,26 @@ Add Season Number Flatten Seasons - Direct Play - HTTP + Direct Play - HTTP Direct Play Transcoding Server Detection Succeeded Found server Address : - - Recently Added Tv Shows - In Progress Tv Shows + + Recently Added TV Shows + In Progress TV Shows All Music - Channels - Recently Added Movies - Recently Added Episodes + Channels + Recently Added Movies + Recently Added Episodes Recently Added Albums - In Progress Movies - In Progress Episodes - Next Episodes - Favorite Movies - Favorite Shows + In Progress Movies + In Progress Episodes + Next Episodes + Favorite Movies + Favorite Shows Favorite Episodes Frequent Played Albums Upcoming TV @@ -178,7 +167,7 @@ Trailers Music Videos Photos - Unwatched Movies + Unwatched Movies Movie Genres Movie Studios Movie Actors @@ -207,7 +196,7 @@ Enable Theme Videos (Requires Restart) - Loop Theme Videos - + AutoPlay remaining episodes in a season Compress Artwork Latest @@ -220,33 +209,37 @@ Random Movies Random Episodes - Random Items - Recommended Items + Random Items + Recommended Items Extras Sync Theme Music Sync Extra Fanart - Sync Movie BoxSets + Sync Movie BoxSets Reset local Kodi database Enable watched/resume status sync DB Sync Indication: Play Count Sync Indication: Enable HTTPS + Force Transcoding Codecs + Enable Netflix style next up notification + - The number of seconds before the end to show the notification + Show Emby Info dialog on play/select action Enable server connection message on startup - Recently added Home Videos - Recently added Photos - Favourite Home Videos - Favourite Photos + Recently added Home Videos + Recently added Photos + Favourite Home Videos + Favourite Photos Favourite Albums - Recently added Music videos - In progress Music videos - Unwatched Music videos + Recently added Music videos + In progress Music videos + Unwatched Music videos - + Active Clear Settings Movies @@ -260,8 +253,8 @@ Music Videos Music Tracks Channels - - + + Emby options Clear like for this item Like this item @@ -305,8 +298,8 @@ Startup delay (in seconds) Enable server restart message Enable new content notification - Duration for the video library (in seconds) - Duration for the music library (in seconds) + For the video library (in seconds) + For the music library (in seconds) Welcome diff --git a/resources/lib/videonodes.py b/resources/lib/videonodes.py index 4ef8d273..6b5aba72 100644 --- a/resources/lib/videonodes.py +++ b/resources/lib/videonodes.py @@ -54,6 +54,7 @@ class VideoNodes(object): def viewNode(self, indexnumber, tagname, mediatype, viewtype, delete=False): + window = utils.window kodiversion = self.kodiversion cleantagname = utils.normalize_nodes(tagname.encode('utf-8')) @@ -92,13 +93,13 @@ class VideoNodes(object): path = "library://video/Emby - %s/" % dirname for i in range(1, indexnumber): # Verify to make sure we don't create duplicates - if utils.window('Emby.nodes.%s.index' % i) == path: + if window('Emby.nodes.%s.index' % i) == path: return - if mediatype=="photos": + if mediatype == "photos": path = "plugin://plugin.video.emby/?id=%s&mode=getsubfolders" % indexnumber - utils.window('Emby.nodes.%s.index' % indexnumber, value=path) + window('Emby.nodes.%s.index' % indexnumber, value=path) # Root if not mediatype=="photos": @@ -163,13 +164,14 @@ class VideoNodes(object): '8': 30255, '11': 30254 }, + 'musicvideos': { '1': tagname, '2': 30256, '4': 30257, '6': 30258 - }, + } } nodes = mediatypes[mediatype] @@ -189,10 +191,12 @@ class VideoNodes(object): # Set window properties if (mediatype == "homevideos" or mediatype == "photos") and nodetype == "all": # Custom query - path = "plugin://plugin.video.emby/?id=%s&mode=browsecontent&type=%s" %(tagname,mediatype) + path = ("plugin://plugin.video.emby/?id=%s&mode=browsecontent&type=%s" + % (tagname, mediatype)) elif (mediatype == "homevideos" or mediatype == "photos"): # Custom query - path = "plugin://plugin.video.emby/?id=%s&mode=browsecontent&type=%s&folderid=%s" %(tagname,mediatype,nodetype) + path = ("plugin://plugin.video.emby/?id=%s&mode=browsecontent&type=%s&folderid=%s" + % (tagname, mediatype, nodetype)) elif nodetype == "nextepisodes": # Custom query path = "plugin://plugin.video.emby/?id=%s&mode=nextup&limit=25" % tagname @@ -218,19 +222,20 @@ class VideoNodes(object): templabel = label embynode = "Emby.nodes.%s" % indexnumber - utils.window('%s.title' % embynode, value=templabel) - utils.window('%s.path' % embynode, value=windowpath) - utils.window('%s.content' % embynode, value=path) - utils.window('%s.type' % embynode, value=mediatype) + window('%s.title' % embynode, value=templabel) + window('%s.path' % embynode, value=windowpath) + window('%s.content' % embynode, value=path) + window('%s.type' % embynode, value=mediatype) else: embynode = "Emby.nodes.%s.%s" % (indexnumber, nodetype) - utils.window('%s.title' % embynode, value=label) - utils.window('%s.path' % embynode, value=windowpath) - utils.window('%s.content' % embynode, value=path) + window('%s.title' % embynode, value=label) + window('%s.path' % embynode, value=windowpath) + window('%s.content' % embynode, value=path) - if mediatype=="photos": - #for photos we do not create a node in videos but we do want the window props to be created - #todo: add our photos nodes to kodi picture sources somehow + if mediatype == "photos": + # For photos, we do not create a node in videos but we do want the window props + # to be created. + # To do: add our photos nodes to kodi picture sources somehow continue if xbmcvfs.exists(nodeXML): @@ -238,7 +243,8 @@ class VideoNodes(object): continue # Create the root - if nodetype == "nextepisodes" or (kodiversion == 14 and nodetype in ('recentepisodes', 'inprogressepisodes')) or mediatype=="homevideos": + if (nodetype == "nextepisodes" or mediatype == "homevideos" or + (kodiversion == 14 and nodetype in ('recentepisodes', 'inprogressepisodes'))): # Folder type with plugin path root = self.commonRoot(order=node, label=label, tagname=tagname, roottype=2) etree.SubElement(root, 'path').text = path @@ -311,6 +317,8 @@ class VideoNodes(object): def singleNode(self, indexnumber, tagname, mediatype, itemtype): + window = utils.window + tagname = tagname.encode('utf-8') cleantagname = utils.normalize_nodes(tagname) nodepath = xbmc.translatePath("special://profile/library/video/").decode('utf-8') @@ -334,10 +342,10 @@ class VideoNodes(object): } label = utils.language(labels[tagname]) embynode = "Emby.nodes.%s" % indexnumber - utils.window('%s.title' % embynode, value=label) - utils.window('%s.path' % embynode, value=windowpath) - utils.window('%s.content' % embynode, value=path) - utils.window('%s.type' % embynode, value=itemtype) + window('%s.title' % embynode, value=label) + window('%s.path' % embynode, value=windowpath) + window('%s.content' % embynode, value=path) + window('%s.type' % embynode, value=itemtype) if xbmcvfs.exists(nodeXML): # Don't recreate xml if already exists @@ -359,8 +367,10 @@ class VideoNodes(object): def clearProperties(self): + window = utils.window + self.logMsg("Clearing nodes properties.", 1) - embyprops = utils.window('Emby.nodes.total') + embyprops = window('Emby.nodes.total') propnames = [ "index","path","title","content", @@ -379,4 +389,4 @@ class VideoNodes(object): totalnodes = int(embyprops) for i in range(totalnodes): for prop in propnames: - utils.window('Emby.nodes.%s.%s' % (str(i), prop), clear=True) \ No newline at end of file + window('Emby.nodes.%s.%s' % (str(i), prop), clear=True) \ No newline at end of file From ce3d2bbb7f96a7bd585ddead994384e08bb1ccab Mon Sep 17 00:00:00 2001 From: Shaun Date: Fri, 5 Feb 2016 08:54:01 +1100 Subject: [PATCH 02/13] bump version --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index 8e2256bd..29f31f80 100644 --- a/addon.xml +++ b/addon.xml @@ -1,7 +1,7 @@ From 01ab7c7a291dcd4abe6df96e5161c9fd85e61180 Mon Sep 17 00:00:00 2001 From: angelblue05 Date: Thu, 4 Feb 2016 16:24:23 -0600 Subject: [PATCH 03/13] Update strings.xml --- resources/language/English/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/language/English/strings.xml b/resources/language/English/strings.xml index 880efe68..6effb2c2 100644 --- a/resources/language/English/strings.xml +++ b/resources/language/English/strings.xml @@ -298,8 +298,8 @@ Startup delay (in seconds) Enable server restart message Enable new content notification - For the video library (in seconds) - For the music library (in seconds) + Duration of the video library pop up (in seconds) + Duration of the music library pop up (in seconds) Welcome From d75af5009bd4c0f9701c3a5f53c2ff9111d91a76 Mon Sep 17 00:00:00 2001 From: Shaun Date: Fri, 5 Feb 2016 10:02:04 +1100 Subject: [PATCH 04/13] fix map error when new server plugin is not installed --- resources/lib/librarysync.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/lib/librarysync.py b/resources/lib/librarysync.py index 4ea39bdd..b0fc454b 100644 --- a/resources/lib/librarysync.py +++ b/resources/lib/librarysync.py @@ -112,7 +112,7 @@ class LibrarySync(threading.Thread): url = "{server}/Emby.Kodi.SyncQueue/GetServerDateTime?format=json" result = self.doUtils.downloadUrl(url) retention_time = "2010-01-01T00:00:00Z" - if result and result['RetentionDateTime']: + if result and result.get("RetentionDateTime"): self.logMsg("RetentionDateTime Found", 1) retention_time = result['RetentionDateTime'] retention_time = datetime.strptime(retention_time, "%Y-%m-%dT%H:%M:%SZ") From afcb3461b427f399a04eff2e33c42d8c2c1c7e05 Mon Sep 17 00:00:00 2001 From: Shaun Date: Fri, 5 Feb 2016 10:02:43 +1100 Subject: [PATCH 05/13] bump ver --- addon.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addon.xml b/addon.xml index 29f31f80..3daccf12 100644 --- a/addon.xml +++ b/addon.xml @@ -1,7 +1,7 @@ From 256d98c6f3c3f128015498222d9d0f77e935d013 Mon Sep 17 00:00:00 2001 From: angelblue05 Date: Thu, 4 Feb 2016 19:09:47 -0600 Subject: [PATCH 06/13] Fix datetime error Known kodi/python issue where datetime.strptime throws a Nonetype error for no reason, after being used once. --- resources/lib/librarysync.py | 8 ++++---- resources/lib/utils.py | 11 +++++++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/resources/lib/librarysync.py b/resources/lib/librarysync.py index b0fc454b..2a7697cd 100644 --- a/resources/lib/librarysync.py +++ b/resources/lib/librarysync.py @@ -105,17 +105,17 @@ class LibrarySync(threading.Thread): lastSync = "2010-01-01T00:00:00Z" self.logMsg("Last sync run: %s" % lastSync, 1) - lastSyncTime = datetime.strptime(lastSync, "%Y-%m-%dT%H:%M:%SZ") + lastSyncTime = utils.convertdate(lastSync) self.logMsg("LastIncrementalSync : %s" % lastSyncTime, 1) # get server RetentionDateTime url = "{server}/Emby.Kodi.SyncQueue/GetServerDateTime?format=json" result = self.doUtils.downloadUrl(url) retention_time = "2010-01-01T00:00:00Z" - if result and result.get("RetentionDateTime"): + if result and result.get('RetentionDateTime'): self.logMsg("RetentionDateTime Found", 1) retention_time = result['RetentionDateTime'] - retention_time = datetime.strptime(retention_time, "%Y-%m-%dT%H:%M:%SZ") + retention_time = utils.convertdate(retention_time) self.logMsg("RetentionDateTime : %s" % retention_time, 1) # if last sync before retention time do a full sync @@ -155,7 +155,7 @@ class LibrarySync(threading.Thread): result = self.doUtils.downloadUrl(url) try: # datetime fails when used more than once, TypeError server_time = result['ServerDateTime'] - server_time = datetime.strptime(server_time, "%Y-%m-%dT%H:%M:%SZ") + server_time = utils.convertdate(server_time) except Exception as e: # If the server plugin is not installed or an error happened. diff --git a/resources/lib/utils.py b/resources/lib/utils.py index 8da3c9d9..a83fb48b 100644 --- a/resources/lib/utils.py +++ b/resources/lib/utils.py @@ -6,6 +6,7 @@ import cProfile import inspect import pstats import sqlite3 +from datetime import datetime, time import time import unicodedata import xml.etree.ElementTree as etree @@ -238,6 +239,16 @@ def stopProfiling(pr, profileName): "{0}".format(cumulative_time), func_name, filename)) f.close() +def convertdate(date): + try: + date = datetime.strptime(date, "%Y-%m-%dT%H:%M:%SZ") + except TypeError: + # TypeError: attribute of type 'NoneType' is not callable + # Known Kodi/python error + date = datetime(*(time.strptime(date, "%Y-%m-%dT%H:%M:%SZ")[0:6])) + + return date + def normalize_nodes(text): # For video nodes text = text.replace(":", "") From 5f2e378c1321bd10a309c18a11e570bb9b01b247 Mon Sep 17 00:00:00 2001 From: angelblue05 Date: Thu, 4 Feb 2016 21:25:01 -0600 Subject: [PATCH 07/13] Update changelog --- changelog.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/changelog.txt b/changelog.txt index e2fb89aa..14c2e746 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,11 @@ +version 2.0.3 +- Add new retention time option that the latest server Sync plugin uses to help determine if full sync or inc sync should be used. +- Add control over new content pop up display time. You will find the settings under Extras > Enable new content notification +- Change to the transcode H265 setting. You will need to re-select the proper resolution, if you had the setting enabled. +- Change to the paths added to sources.xml +- Fix to the manual sync for the music library +- Fix resume when launching playback via the web client + version 1.1.81 - Fix missing deviceId - Fix to newly added album/songs (if you experienced the bug, you will need to reset to fix it. Know that moving forward, it is corrected.) From 0d7672930292cb06f43b443034a55b857c72fece Mon Sep 17 00:00:00 2001 From: angelblue05 Date: Fri, 5 Feb 2016 14:30:32 -0600 Subject: [PATCH 08/13] Fix tag contains to tag is --- resources/lib/entrypoint.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/lib/entrypoint.py b/resources/lib/entrypoint.py index e31a889e..c30a2384 100644 --- a/resources/lib/entrypoint.py +++ b/resources/lib/entrypoint.py @@ -706,7 +706,7 @@ def getNextUpEpisodes(tagname, limit): 'filter': { 'and': [ {'operator': "true", 'field': "inprogress", 'value': ""}, - {'operator': "contains", 'field': "tag", 'value': "%s" % tagname} + {'operator': "is", 'field': "tag", 'value': "%s" % tagname} ]}, 'properties': ['title', 'studio', 'mpaa', 'file', 'art'] } @@ -804,7 +804,7 @@ def getInProgressEpisodes(tagname, limit): 'filter': { 'and': [ {'operator': "true", 'field': "inprogress", 'value': ""}, - {'operator': "contains", 'field': "tag", 'value': "%s" % tagname} + {'operator': "is", 'field': "tag", 'value': "%s" % tagname} ]}, 'properties': ['title', 'studio', 'mpaa', 'file', 'art'] } @@ -872,7 +872,7 @@ def getRecentEpisodes(tagname, limit): 'params': { 'sort': {'order': "descending", 'method': "dateadded"}, - 'filter': {'operator': "contains", 'field': "tag", 'value': "%s" % tagname}, + 'filter': {'operator': "is", 'field': "tag", 'value': "%s" % tagname}, 'properties': ["title","sorttitle"] } } From 47a0f99da0c6b8de466e50e7b8971713d5384c5c Mon Sep 17 00:00:00 2001 From: angelblue05 Date: Fri, 5 Feb 2016 14:38:39 -0600 Subject: [PATCH 09/13] Adjust video quality settings To always display, even if play from http is disabled. --- resources/settings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/settings.xml b/resources/settings.xml index be8a72c1..3889f837 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -53,7 +53,7 @@ - + From dfd5479d8e9ad25f464c6555e9570415f90f32a5 Mon Sep 17 00:00:00 2001 From: angelblue05 Date: Fri, 5 Feb 2016 15:49:25 -0600 Subject: [PATCH 10/13] OnSettings adjust logic For playback mode changes, do not update the window prop --- resources/lib/kodimonitor.py | 1 - 1 file changed, 1 deletion(-) diff --git a/resources/lib/kodimonitor.py b/resources/lib/kodimonitor.py index ac781e5a..99cb60f7 100644 --- a/resources/lib/kodimonitor.py +++ b/resources/lib/kodimonitor.py @@ -49,7 +49,6 @@ class KodiMonitor(xbmc.Monitor): if utils.window('emby_pluginpath') != currentPath: # Plugin path value changed. Offer to reset self.logMsg("Changed to playback mode detected", 1) - utils.window('emby_pluginpath', value=currentPath) resp = xbmcgui.Dialog().yesno( heading="Playback mode change detected", line1=( From da66d61f6c71698725debb86ac95b1fc84fb9849 Mon Sep 17 00:00:00 2001 From: angelblue05 Date: Fri, 5 Feb 2016 16:17:37 -0600 Subject: [PATCH 11/13] Revert "OnSettings adjust logic" This reverts commit dfd5479d8e9ad25f464c6555e9570415f90f32a5. --- resources/lib/kodimonitor.py | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lib/kodimonitor.py b/resources/lib/kodimonitor.py index 99cb60f7..ac781e5a 100644 --- a/resources/lib/kodimonitor.py +++ b/resources/lib/kodimonitor.py @@ -49,6 +49,7 @@ class KodiMonitor(xbmc.Monitor): if utils.window('emby_pluginpath') != currentPath: # Plugin path value changed. Offer to reset self.logMsg("Changed to playback mode detected", 1) + utils.window('emby_pluginpath', value=currentPath) resp = xbmcgui.Dialog().yesno( heading="Playback mode change detected", line1=( From 5e6e606031aed0f82b9873a012ca4133733ba417 Mon Sep 17 00:00:00 2001 From: angelblue05 Date: Sat, 6 Feb 2016 23:06:05 -0600 Subject: [PATCH 12/13] Make the transcode h265 more robust To prevent any errors, since the setting used to be different. --- resources/lib/playutils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/lib/playutils.py b/resources/lib/playutils.py index 4504bc4a..7978b567 100644 --- a/resources/lib/playutils.py +++ b/resources/lib/playutils.py @@ -100,7 +100,7 @@ class PlayUtils(): videotrack = item['MediaSources'][0]['Name'] transcodeH265 = utils.settings('transcodeH265') - if transcodeH265 != "0" and ("HEVC" in videotrack or "H265" in videotrack): + if transcodeH265 in ("1", "2", "3") and ("HEVC" in videotrack or "H265" in videotrack): # Avoid H265/HEVC depending on the resolution resolution = int(videotrack.split("P", 1)[0]) res = { @@ -211,7 +211,7 @@ class PlayUtils(): videotrack = item['MediaSources'][0]['Name'] transcodeH265 = utils.settings('transcodeH265') - if transcodeH265 != "0" and ("HEVC" in videotrack or "H265" in videotrack): + if transcodeH265 in ("1", "2", "3") and ("HEVC" in videotrack or "H265" in videotrack): # Avoid H265/HEVC depending on the resolution resolution = int(videotrack.split("P", 1)[0]) res = { From 3b95536539e0477d427c9eccd404ee53cd82ae30 Mon Sep 17 00:00:00 2001 From: im85288 Date: Sun, 7 Feb 2016 09:45:08 +0000 Subject: [PATCH 13/13] fix for Failed to import _strptime because the import lockis held by another thread. --- service.py | 1 + 1 file changed, 1 insertion(+) diff --git a/service.py b/service.py index 76f31395..244e77c8 100644 --- a/service.py +++ b/service.py @@ -10,6 +10,7 @@ from datetime import datetime import xbmc import xbmcaddon import xbmcgui +import _strptime import xbmcvfs #################################################################################################