Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions resources/language/resource.language.en_gb/strings.po
Original file line number Diff line number Diff line change
Expand Up @@ -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 ""
Expand Down
4 changes: 4 additions & 0 deletions resources/language/resource.language.es_es/strings.po
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
4 changes: 4 additions & 0 deletions resources/language/resource.language.pt_pt/strings.po
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
44 changes: 41 additions & 3 deletions resources/lib/atv.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
"""

import json
import os
import tempfile
import threading
import time

import xbmc
import xbmcgui
Expand Down Expand Up @@ -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
Expand All @@ -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:
Expand Down
66 changes: 62 additions & 4 deletions resources/lib/playlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"""

import json
import plistlib
import os
import tarfile
from random import shuffle
Expand All @@ -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():
Expand All @@ -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, ):
Expand All @@ -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 = {}

Expand Down Expand Up @@ -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)
Expand Down
5 changes: 5 additions & 0 deletions resources/settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
<default>false</default>
<control type="toggle"/>
</setting>
<setting id="show-subtitles" type="boolean" label="32049" help="">
<level>0</level>
<default>false</default>
<control type="toggle"/>
</setting>
<setting id="enable-4k" type="boolean" label="32075" help="">
<level>0</level>
<default>false</default>
Expand Down