diff --git a/resources/language/resource.language.en_gb/strings.po b/resources/language/resource.language.en_gb/strings.po
index 471a367..751e428 100644
--- a/resources/language/resource.language.en_gb/strings.po
+++ b/resources/language/resource.language.en_gb/strings.po
@@ -210,6 +210,10 @@ msgctxt "#32048"
msgid "No downloaded videos for offline mode!"
msgstr ""
+msgctxt "#32049"
+msgid "Use subtitles to show video locations"
+msgstr ""
+
msgctxt "#32075"
msgid "Enable 4K (default 1080p)"
msgstr ""
diff --git a/resources/language/resource.language.es_es/strings.po b/resources/language/resource.language.es_es/strings.po
index 45922be..947b120 100644
--- a/resources/language/resource.language.es_es/strings.po
+++ b/resources/language/resource.language.es_es/strings.po
@@ -210,6 +210,10 @@ msgctxt "#32048"
msgid "No downloaded videos for offline mode!"
msgstr ""
+msgctxt "#32049"
+msgid "Use subtitles to show video locations"
+msgstr ""
+
msgctxt "#32075"
msgid "Enable 4K (default 1080p)"
msgstr "Habilitar 4K"
diff --git a/resources/language/resource.language.pt_pt/strings.po b/resources/language/resource.language.pt_pt/strings.po
index 6c0a836..46bb081 100644
--- a/resources/language/resource.language.pt_pt/strings.po
+++ b/resources/language/resource.language.pt_pt/strings.po
@@ -210,6 +210,10 @@ msgctxt "#32048"
msgid "Offline mode but no downloaded videos!"
msgstr "Modo offline ativo mas não existem videos no disco"
+msgctxt "#32049"
+msgid "Use subtitles to show video locations"
+msgstr ""
+
msgctxt "#32075"
msgid "Enable 4K (default 1080p)"
msgstr "Ativar 4K"
diff --git a/resources/lib/atv.py b/resources/lib/atv.py
index eaf1303..37d1aa9 100644
--- a/resources/lib/atv.py
+++ b/resources/lib/atv.py
@@ -7,7 +7,10 @@
"""
import json
+import os
+import tempfile
import threading
+import time
import xbmc
import xbmcgui
@@ -129,9 +132,42 @@ def onAction(self, action):
addon.setSettingBool("is_locked", False)
self.clearAll()
+ def create_sub(self, pois):
+ subfile = tempfile.NamedTemporaryFile(suffix=".srt", delete=False)
+ cursec = 0
+ for i, poi in enumerate(pois, start=1):
+ subfile.write("{}\n".format(i).encode())
+ start_ts = time.strftime('%H:%M:%S,000', time.gmtime(poi.secs))
+ if i < len(pois):
+ end_ts = time.strftime('%H:%M:%S,000', time.gmtime(pois[i].secs))
+ else:
+ end_ts = "99:59:59,999"
+ subfile.write("{} --> {}\n".format(start_ts, end_ts).encode())
+ subfile.write("{}\n\n".format(poi.description).encode())
+ subfile.close()
+ return subfile.name
+
+ def do_play(self, url, pois):
+ do_subs = addon.getSettingBool("show-subtitles")
+ if do_subs:
+ subfile_path = self.create_sub(pois)
+ else:
+ subfile_path = None
+
+ self.atv4player.play(url, windowed=True)
+
+ if do_subs:
+ while not self.atv4player.isPlaying():
+ xbmc.sleep(100)
+ self.atv4player.setSubtitles(subfile_path)
+ self.atv4player.showSubtitles(True)
+
+ return subfile_path
+
def start_playback(self):
self.playindex = 0
- self.atv4player.play(self.video_playlist[self.playindex], windowed=True)
+ playlist_item = self.video_playlist[self.playindex]
+ subfile_path = self.do_play(playlist_item.url, playlist_item.pois)
while self.active and not monitor.abortRequested():
monitor.waitForAbort(1)
# If we finish playing the video
@@ -142,8 +178,10 @@ def start_playback(self):
else:
self.playindex = 0
# Using the updated iterator, start playing the next video
- self.atv4player.play(self.video_playlist[self.playindex], windowed=True)
-
+ playlist_item = self.video_playlist[self.playindex]
+ if subfile_path:
+ os.remove(subfile_path)
+ subfile_path = self.do_play(playlist_item.url, playlist_item.pois)
def run(params=False):
if not params:
diff --git a/resources/lib/playlist.py b/resources/lib/playlist.py
index 013cc24..04349b4 100644
--- a/resources/lib/playlist.py
+++ b/resources/lib/playlist.py
@@ -7,6 +7,7 @@
"""
import json
+import plistlib
import os
import tarfile
from random import shuffle
@@ -26,6 +27,18 @@
# Local save location of the entries.json file containing video URLs
local_entries_json_path = os.path.join(addon_path, "resources", "entries.json")
+# Path to the local file where we store the plist with video descriptions
+local_plist_path_parts = [addon_path, "resources", "TVIdleScreenStrings.bundle", "{}.lproj", "Localizable.nocache.strings"]
+
+# location in the tar file for the plist file with descriptions
+language_description_format_str = "TVIdleScreenStrings.bundle/{}.lproj/Localizable.nocache.strings"
+
+def tar_has_member(tar, key):
+ try:
+ tar.getmember(key)
+ return True
+ except KeyError:
+ return False
# Fetch the TAR file containing the latest entries.json and overwrite the local copy
def get_latest_entries_from_apple():
@@ -35,13 +48,32 @@ def get_latest_entries_from_apple():
request.urlretrieve(apple_resources_tar_url, apple_local_tar_path)
# https://www.tutorialspoint.com/How-are-files-extracted-from-a-tar-file-using-Python
apple_tar = tarfile.open(apple_local_tar_path)
- xbmc.log("Extracting entries.json from resources.tar and placing in ./resources", level=xbmc.LOGDEBUG)
- apple_tar.extract("entries.json", os.path.join(addon_path, "resources"))
+ xbmc.log("Extracting entries.json and video descriptions from resources.tar and placing in ./resources", level=xbmc.LOGDEBUG)
+ dest_dir = os.path.join(addon_path, "resources")
+ apple_tar.extract("entries.json", dest_dir)
+ language = xbmc.getLanguage(xbmc.ISO_639_1)
+ if tar_has_member(apple_tar, language_description_format_str.format(language)):
+ apple_tar.extract(language_description_format_str.format(language), dest_dir)
+ else:
+ xmbc.log("No descriptions for language {}, defaulting to English", level=xbmc.LOGWARNING)
+ apple_tar.extract(language_description_format_str.format('en'), dest_dir)
apple_tar.close()
- xbmc.log("Deleting resources.tar now that we've grabbed entries.json from it", level=xbmc.LOGDEBUG)
+ xbmc.log("Deleting resources.tar now that we've grabbed what we need from it", level=xbmc.LOGDEBUG)
os.remove(apple_local_tar_path)
+class PlaylistEntry:
+ def __init__(self, url, location, pois):
+ self.url = url
+ self.location = location
+ self.pois = pois
+
+class POI:
+ def __init__(self, secs, description):
+ self.secs = secs
+ self.description = description
+ def __repr__(self):
+ return "POI secs:{}, description: {}".format(self.secs, self.description)
class AtvPlaylist:
def __init__(self, ):
@@ -61,6 +93,21 @@ def __init__(self, ):
# Regardless of if we grabbed new Apple JSON, hit an exception, or are in offline mode, load the local copy
with open(local_entries_json_path, "r") as f:
self.top_level_json = json.loads(f.read())
+
+ language = xbmc.getLanguage(xbmc.ISO_639_1)
+ plist_language_parts = local_plist_path_parts.copy()
+ plist_language_parts[3] = plist_language_parts[3].format(language)
+ plist_path = os.path.join(*plist_language_parts)
+ if not xbmcvfs.exists(plist_path):
+ xbmc.log("No descriptions for language {}, defaulting to English", level=xbmc.LOGWARNING)
+ plist_language_parts[3] = "en.lproj"
+ plist_path = os.path.join(*plist_language_parts)
+ if xbmcvfs.exists(plist_path):
+ with open(plist_path, "rb") as f:
+ self.plist = plistlib.loads(f.read())
+ else:
+ xbmc.log("Could not find description file, cannot enable subtitles", level=xbmc.LOGWARNING)
+ self.plist = None
else:
self.top_level_json = {}
@@ -122,7 +169,18 @@ def compute_playlist_array(self):
# If the file exists locally or we're not in offline mode, add it to the playlist
if exists_on_disk or not self.force_offline:
xbmc.log("Adding video for location {} to playlist".format(location), level=xbmc.LOGDEBUG)
- self.playlist.append(url)
+ pois = []
+ if self.plist:
+ if "pointsOfInterest" in block:
+ for secs, key in block["pointsOfInterest"].items():
+ if key in self.plist:
+ pois.append(POI(int(secs), self.plist[key]))
+ elif "shotID" in block and block["shotID"] in self.plist:
+ pois.append(POI(0,self.plist[block["shotID"]]))
+ else:
+ xbmc.log("Could not find any descriptions for {}".format(url), level=xbmc.LOGWARNING)
+ pois.sort(key=lambda poi: poi.secs, reverse=False)
+ self.playlist.append(PlaylistEntry(url, location, pois))
# Now that we're done building the playlist, shuffle and return to the caller
shuffle(self.playlist)
diff --git a/resources/settings.xml b/resources/settings.xml
index bde0650..1b43c84 100644
--- a/resources/settings.xml
+++ b/resources/settings.xml
@@ -13,6 +13,11 @@
false
+
+ 0
+ false
+
+
0
false