diff --git a/plugin.audio.mp3streams/default.py b/plugin.audio.mp3streams/default.py
index 08f2f50c..d6ad75ea 100644
--- a/plugin.audio.mp3streams/default.py
+++ b/plugin.audio.mp3streams/default.py
@@ -107,6 +107,28 @@ def return_to_main_menu():
xbmc.executebuiltin('Container.Update(%s,isdir)' % addon_root_url())
sys.exit(0)
+def track_number_from_title(title):
+ title = settings.decode_text(title or '')
+ match = re.match(r'^\s*(\d+)\.\s+', title)
+ return match.group(1) if match else ''
+
+def numbered_song_title(track, songname):
+ songname = settings.decode_text(songname or '')
+ if not track:
+ return songname
+ if re.match(r'^\s*%s\.\s+' % re.escape(str(track)), songname):
+ return songname
+ return "%s. %s" % (track, songname)
+
+def album_download_names(name):
+ name = settings.decode_text(name or '')
+ parts = name.split(' - ')
+ if len(parts) < 2:
+ return 'Various', name
+ artist = parts[0]
+ album_parts = parts[1:-1] if len(parts) > 2 and re.match(r'^\d{4}$', parts[-1]) else parts[1:]
+ return artist, ' - '.join(album_parts)
+
# RunPlugin / action-only modes must not call endOfDirectory or Kodi shows a blank list.
PLUGIN_ACTION_MODES = (8, 61, 62, 64, 65, 67, 68, 89, 99, 100, 201, 202, 333, 500)
@@ -669,9 +691,9 @@ def play_song(url, name, songname, artist, album, iconimage, dur, clear):
def download_song(url, name, songname, artist, album, iconimage):
display_name = settings.decode_text(songname or name)
notification('MP3 Streams', 'Downloading: %s' % display_name, '3000', iconimage or iconart)
- dot = name.find('. ')
- track = name[:dot] if dot >= 0 else ''
- safe_songname = settings.sanitize_filename(settings.decode_text(songname))
+ track = track_number_from_title(name)
+ filename_title = numbered_song_title(track, songname)
+ safe_songname = settings.sanitize_filename(filename_title)
artist_path = create_directory(settings.music_dir(), settings.decode_text(artist))
album_path = create_directory(artist_path, settings.decode_text(album))
list_data = "%s<>%s<>%s<>%s<>%s%s" % (album_path,artist,album,track,safe_songname,'.mp3')
@@ -711,9 +733,8 @@ def run(self):
xbmc.executebuiltin(notify)
'''
def download_album(url, name, iconimage):
- nartist = name.split(' - ')[0]
+ nartist, nalbum = album_download_names(name)
xbmc.log("nartist = {0}".format(nartist), xbmc.LOGINFO)
- nalbum = name.split(' - ')[1]
xbmc.log("nalbum = {0}".format(nalbum), xbmc.LOGINFO)
if GOLDEN_PATH:
url = url.replace('http','https').replace('musicmp3','www.goldenmp3').replace('artist_','/').replace('__album_','/').replace('.html','')
@@ -737,6 +758,7 @@ def download_album(url, name, iconimage):
xbmc.log("match = {0}".format(match), xbmc.LOGINFO)
nSong = len(match)
count = 0
+ album_path = create_directory(settings.music_dir(), nalbum)
for track, id, songurl, meta, album, artist, songname, dur in match:
count += 1
songname = settings.decode_text(songname)
@@ -752,8 +774,6 @@ def download_album(url, name, iconimage):
playlist.append(songname)
title = "%s. %s" % (track.replace('track',''), songname)
safe_title = settings.sanitize_filename(title)
- artist_path = create_directory(settings.music_dir(), artist)
- album_path = create_directory(artist_path, album)
list_data = "%s<>%s<>%s<>%s<>%s%s" % (album_path,artist,album,trn,safe_title,'.mp3')
create_file(settings.music_dir(), "downloading.txt")
local_filename = os.path.join(album_path, safe_title + '.mp3')
@@ -768,7 +788,7 @@ def download_album(url, name, iconimage):
text = "%s of %s tracks downloaded" % (trn, nSong)
notification(artist + ' ' + album, text, '3000', iconimage)
add_to_list(list_data, DOWNLOAD_LIST, False)
- notification(name.split(' - ')[0] + ' ' + name.split(' - ')[1], 'Album download finished', '3000', iconimage)
+ notification(nartist + ' ' + nalbum, 'Album download finished', '3000', iconimage)
if os.path.exists(download_lock_path()):
os.remove(download_lock_path())
diff --git a/plugin.video.redlight/resources/lib/caches/settings_cache.py b/plugin.video.redlight/resources/lib/caches/settings_cache.py
index b1b26f14..2c5ef48c 100644
--- a/plugin.video.redlight/resources/lib/caches/settings_cache.py
+++ b/plugin.video.redlight/resources/lib/caches/settings_cache.py
@@ -1227,6 +1227,10 @@ def default_settings():
{'setting_id': 'scraper_720p_highlight', 'setting_type': 'string', 'setting_default': 'FF3C9900'},
{'setting_id': 'scraper_SD_highlight', 'setting_type': 'string', 'setting_default': 'FF0166FF'},
{'setting_id': 'scraper_single_highlight', 'setting_type': 'string', 'setting_default': 'FF008EB2'},
+{'setting_id': 'scraper_progress_4k_highlight', 'setting_type': 'string', 'setting_default': 'FFFFFFFF'},
+{'setting_id': 'scraper_progress_1080p_highlight', 'setting_type': 'string', 'setting_default': 'FFFFFFFF'},
+{'setting_id': 'scraper_progress_720p_highlight', 'setting_type': 'string', 'setting_default': 'FFFFFFFF'},
+{'setting_id': 'scraper_progress_SD_highlight', 'setting_type': 'string', 'setting_default': 'FFFFFFFF'},
{'setting_id': 'highlight.tint_focused_background', 'setting_type': 'boolean', 'setting_default': 'false'},
{'setting_id': 'highlight.background_opacity', 'setting_type': 'string', 'setting_default': '66'},
{'setting_id': 'highlight.background_opacity_name', 'setting_type': 'string', 'setting_default': '40%'},
diff --git a/plugin.video.redlight/resources/lib/modules/episode_tools.py b/plugin.video.redlight/resources/lib/modules/episode_tools.py
index a5cd1bb2..b8c6540f 100644
--- a/plugin.video.redlight/resources/lib/modules/episode_tools.py
+++ b/plugin.video.redlight/resources/lib/modules/episode_tools.py
@@ -102,7 +102,9 @@ def get_random_episode(self, continual=False, first_run=True):
'episode': episode, 'premiered': premiered, 'plot': plot})
url_params = {'media_type': 'episode', 'tmdb_id': tmdb_id, 'tvshowtitle': self.meta_get('rootname'), 'season': season, 'episode': episode,
'playcount': playcount, 'autoplay': 'true'}
- if continual: url_params['random_continual'] = 'true'
+ if continual:
+ url_params['random_continual'] = 'true'
+ url_params['watch_count'] = self.meta_get('watch_count', 1)
else: url_params['random'] = 'true'
if not first_run:
url_params['background'] = 'true'
diff --git a/plugin.video.redlight/resources/lib/modules/player.py b/plugin.video.redlight/resources/lib/modules/player.py
index 9bd56dc3..7cf2ec03 100644
--- a/plugin.video.redlight/resources/lib/modules/player.py
+++ b/plugin.video.redlight/resources/lib/modules/player.py
@@ -16,6 +16,7 @@
PROP_NEXTEP_PREP_DECLINED = 'redlight.nextep_prep_declined'
PROP_AUTOSCRAPE_NEXTEP_READY = 'redlight.autoscrape_nextep_ready'
PROP_NEXTEP_AUTOPLAY_CANCELLED = 'redlight.nextep_autoplay_cancelled'
+PROP_RANDOM_CONTINUAL_SKIP_ATTEMPTS = 'redlight.random_continual_skip_attempts'
# Movies-only: fire stingers alert ~3 min before other alert sources would (typical 90% vs 95% gap on ~1 hr).
_STINGER_EARLY_OFFSET_SEC = 180
_NEXTEP_SUB_FETCH_DEFER_SEC = 45
@@ -1035,6 +1036,7 @@ def set_constants(self, url, obj):
ku.clear_property(PROP_NEXTEP_PREP_SCHEDULED)
ku.clear_property(PROP_NEXTEP_PREP_DECLINED)
ku.clear_property(PROP_AUTOSCRAPE_NEXTEP_READY)
+ ku.clear_property(PROP_RANDOM_CONTINUAL_SKIP_ATTEMPTS)
ku.clear_property(PROP_NEXTEP_AUTOPLAY_CANCELLED)
self._autoscrape_ready_notified = False
self._nextep_alert_pending_logged = False
diff --git a/plugin.video.redlight/resources/lib/modules/sources.py b/plugin.video.redlight/resources/lib/modules/sources.py
index b31fff6f..f2d3785a 100644
--- a/plugin.video.redlight/resources/lib/modules/sources.py
+++ b/plugin.video.redlight/resources/lib/modules/sources.py
@@ -25,6 +25,8 @@
PROP_NEXTEP_SCRAPE_KEY = 'redlight.nextep_scrape_key'
PROP_NEXTEP_AUTOPLAY_CANCELLED = 'redlight.nextep_autoplay_cancelled'
PROP_AUTOSCRAPE_NEXTEP_READY = 'redlight.autoscrape_nextep_ready'
+PROP_RANDOM_CONTINUAL_SKIP_ATTEMPTS = 'redlight.random_continual_skip_attempts'
+RANDOM_CONTINUAL_MAX_SKIPS = 25
_NEXTEP_AUTOPLAY_STASH = {}
_NEXTEP_PLAY_STASH_PATH = None
@@ -266,7 +268,9 @@ def playback_prep(self, params=None):
if self.background and self.play_type in ('autoplay_nextep', 'autoscrape_nextep', 'random_continual'):
self._log_nextep_scrape_started()
self._prefetch_nextep_segment_data()
- if self.background and self.autoplay_nextep and self.nextep_settings and not getattr(self, '_nextep_alert_handled', False):
+ if self.background and self.play_type == 'random_continual' and not self.nextep_settings:
+ self.nextep_settings = {'watching_check': settings.auto_nextep_settings('autoplay_nextep')['watching_check']}
+ if self.background and (self.autoplay_nextep or self.play_type == 'random_continual') and self.nextep_settings and not getattr(self, '_nextep_alert_handled', False):
if not self.still_watching_check():
self._decline_nextep_prep('still watching')
kodi_utils.notification('Cancel Autoplay', icon=self.meta.get('poster'))
@@ -1191,10 +1195,30 @@ def _show_playback_failed_dialog(self, text=None):
return self._show_modal_message('Playback failed', message)
def _no_results(self):
+ if self.random_continual and self.media_type == 'episode' and self.tmdb_id:
+ return self._random_continual_skip()
self._close_progress_before_modal()
+ return self._show_no_results()
+
+ def _show_no_results(self):
heading = self.meta.get('rootname', '') or self.meta.get('title', '') or 'Red Light'
return self._show_modal_message(heading, 'No results found.', '[B]Next Up:[/B] No Results')
+ def _random_continual_skip(self):
+ """Continual random play: an episode with no links should not stop the chain, so retry with another random episode."""
+ from modules.episode_tools import EpisodeTools
+ attempts = int(kodi_utils.get_property(PROP_RANDOM_CONTINUAL_SKIP_ATTEMPTS) or 0)
+ self._close_progress_before_modal()
+ if attempts >= RANDOM_CONTINUAL_MAX_SKIPS:
+ kodi_utils.clear_property(PROP_RANDOM_CONTINUAL_SKIP_ATTEMPTS)
+ return self._show_no_results()
+ kodi_utils.set_property(PROP_RANDOM_CONTINUAL_SKIP_ATTEMPTS, str(attempts + 1))
+ kodi_utils.logger('Red Light', 'Continual random play: no results for %s S%02dE%02d, skipping to another episode' % (
+ self.meta.get('title', ''), self.meta.get('season', 0), self.meta.get('episode', 0)))
+ meta = metadata.tvshow_meta('tmdb_id', self.tmdb_id, settings.tmdb_api_key(), settings.mpaa_region(), get_datetime())
+ meta['watch_count'] = self.meta.get('watch_count', 1)
+ return EpisodeTools(meta).play_random_continual(first_run=False)
+
def get_search_title(self):
search_title = self.meta.get('custom_title', None) or self.meta.get('english_title') or self.meta.get('title')
return search_title
diff --git a/plugin.video.redlight/resources/lib/windows/sources.py b/plugin.video.redlight/resources/lib/windows/sources.py
index 38a8969c..ab9adc00 100644
--- a/plugin.video.redlight/resources/lib/windows/sources.py
+++ b/plugin.video.redlight/resources/lib/windows/sources.py
@@ -473,6 +473,10 @@ def set_scraper_properties(self):
self.setProperty('results_720p', '0')
self.setProperty('results_sd', '0')
self.setProperty('results_total', '0')
+ self.setProperty('progress_4k_color', get_setting('redlight.scraper_progress_4k_highlight', 'FFFFFFFF'))
+ self.setProperty('progress_1080p_color', get_setting('redlight.scraper_progress_1080p_highlight', 'FFFFFFFF'))
+ self.setProperty('progress_720p_color', get_setting('redlight.scraper_progress_720p_highlight', 'FFFFFFFF'))
+ self.setProperty('progress_sd_color', get_setting('redlight.scraper_progress_SD_highlight', 'FFFFFFFF'))
self.setProperty('percent', '0')
def set_resolver_properties(self):
diff --git a/plugin.video.redlight/resources/skins/Default/1080i/settings_manager.xml b/plugin.video.redlight/resources/skins/Default/1080i/settings_manager.xml
index 5a449c9e..94ef7cd6 100644
--- a/plugin.video.redlight/resources/skins/Default/1080i/settings_manager.xml
+++ b/plugin.video.redlight/resources/skins/Default/1080i/settings_manager.xml
@@ -3393,6 +3393,44 @@
Choose Single color for all results
RunPlugin(plugin://plugin.video.redlight/?mode=scraper_color_choice&setting_id=scraper_single_highlight)
+ -
+ Container(2000).HasFocus(70)
+ Scrape Progress Count Colors
+ separator
+ noop
+
+ -
+ Container(2000).HasFocus(70)
+ - 4K Count Color
+ action
+ [COLOR $INFO[Window(10000).Property(redlight.scraper_progress_4k_highlight)]]$INFO[Window(10000).Property(redlight.scraper_progress_4k_highlight)][/COLOR]
+ Choose 4K source count color on the scrape progress dialog
+ RunPlugin(plugin://plugin.video.redlight/?mode=scraper_color_choice&setting_id=scraper_progress_4k_highlight)
+
+ -
+ Container(2000).HasFocus(70)
+ - 1080P Count Color
+ action
+ [COLOR $INFO[Window(10000).Property(redlight.scraper_progress_1080p_highlight)]]$INFO[Window(10000).Property(redlight.scraper_progress_1080p_highlight)][/COLOR]
+ Choose 1080P source count color on the scrape progress dialog
+ RunPlugin(plugin://plugin.video.redlight/?mode=scraper_color_choice&setting_id=scraper_progress_1080p_highlight)
+
+ -
+ Container(2000).HasFocus(70)
+ - 720P Count Color
+ action
+ [COLOR $INFO[Window(10000).Property(redlight.scraper_progress_720p_highlight)]]$INFO[Window(10000).Property(redlight.scraper_progress_720p_highlight)][/COLOR]
+ Choose 720P source count color on the scrape progress dialog
+ RunPlugin(plugin://plugin.video.redlight/?mode=scraper_color_choice&setting_id=scraper_progress_720p_highlight)
+
+ -
+ Container(2000).HasFocus(70)
+ - SD Count Color
+ action
+ [COLOR $INFO[Window(10000).Property(redlight.scraper_progress_SD_highlight)]]$INFO[Window(10000).Property(redlight.scraper_progress_SD_highlight)][/COLOR]
+ Choose SD source count color on the scrape progress dialog
+ RunPlugin(plugin://plugin.video.redlight/?mode=scraper_color_choice&setting_id=scraper_progress_SD_highlight)
+
-
Container(2000).HasFocus(70)
Tint Focused Result Background
diff --git a/plugin.video.redlight/resources/skins/Default/1080i/sources_playback.xml b/plugin.video.redlight/resources/skins/Default/1080i/sources_playback.xml
index 49850a9c..16f53a5a 100644
--- a/plugin.video.redlight/resources/skins/Default/1080i/sources_playback.xml
+++ b/plugin.video.redlight/resources/skins/Default/1080i/sources_playback.xml
@@ -429,7 +429,7 @@
center
center
font12
-
+
@@ -452,7 +452,7 @@
center
center
font12
-
+
@@ -475,7 +475,7 @@
center
center
font12
-
+
@@ -498,7 +498,7 @@
center
center
font12
-
+
diff --git a/plugin.video.redlight/resources/text/changelog.txt b/plugin.video.redlight/resources/text/changelog.txt
index 33d873aa..3701ef56 100644
--- a/plugin.video.redlight/resources/text/changelog.txt
+++ b/plugin.video.redlight/resources/text/changelog.txt
@@ -1,3 +1,6 @@
+[COLOR red][B]Version 1.7.6[/B][/COLOR]
+- [B]Scrape Progress[/B]: added per-quality count colours under [B]Results Color Highlights[/B] so [B]4K[/B], [B]1080[/B], [B]720[/B], and [B]SD[/B] labels can stay muted while the updating counts use separate colours. Defaults remain white.
+
[COLOR red][B]Version 1.7.5[/B][/COLOR]
- Fixed [B]Autoplay Next Episode[/B] flashing the episode list when choosing [B]Close[/B] (or at natural episode end): stashed resolve now starts a few seconds before fullscreen closes so the resolver covers the transition instead of [B]DialogBusy[/B] (which Kodi tears down when playback stops).
- Fixed [B]Autoplay Next Episode[/B] [B]Cancel[/B] on the alert still autoplaying after the current episode ended.
@@ -475,4 +478,4 @@
- Code cleaned up.
[COLOR red][B]Version 0.0.1[/B][/COLOR]
-- Initial release.
\ No newline at end of file
+- Initial release.