diff --git a/resources/language/resource.language.de/strings.po b/resources/language/resource.language.de/strings.po
index 61f6323..4543f78 100644
--- a/resources/language/resource.language.de/strings.po
+++ b/resources/language/resource.language.de/strings.po
@@ -1281,3 +1281,47 @@ msgstr "Forced-Untertitel bevorzugen"
msgctxt "#30690"
msgid "SRT vor PGS/Bild-Untertiteln bevorzugen"
msgstr "SRT vor PGS/Bild-Untertiteln bevorzugen"
+
+msgctxt "#30691"
+msgid "Deutsch"
+msgstr "Deutsch"
+
+msgctxt "#30692"
+msgid "Englisch"
+msgstr "Englisch"
+
+msgctxt "#30693"
+msgid "Französisch"
+msgstr "Französisch"
+
+msgctxt "#30694"
+msgid "Spanisch"
+msgstr "Spanisch"
+
+msgctxt "#30695"
+msgid "Italienisch"
+msgstr "Italienisch"
+
+msgctxt "#30696"
+msgid "Japanisch"
+msgstr "Japanisch"
+
+msgctxt "#30697"
+msgid "Russisch"
+msgstr "Russisch"
+
+msgctxt "#30698"
+msgid "Andere"
+msgstr "Andere"
+
+msgctxt "#30699"
+msgid "Keine (nur Audio-Sprache)"
+msgstr "Keine (nur Audio-Sprache)"
+
+msgctxt "#30700"
+msgid "Bei keinem Treffer automatisch 'Keine Untertitel' wählen"
+msgstr "Bei keinem Treffer automatisch 'Keine Untertitel' wählen"
+
+msgctxt "#30701"
+msgid "Abspielen mit Track-Auswahl"
+msgstr "Abspielen mit Track-Auswahl"
diff --git a/resources/language/resource.language.en_gb/strings.po b/resources/language/resource.language.en_gb/strings.po
index 2e6494e..9f4a57b 100644
--- a/resources/language/resource.language.en_gb/strings.po
+++ b/resources/language/resource.language.en_gb/strings.po
@@ -1272,3 +1272,47 @@ msgstr "Prefer forced subtitles"
msgctxt "#30690"
msgid "Prefer SRT over PGS/image subtitles"
msgstr "Prefer SRT over PGS/image subtitles"
+
+msgctxt "#30691"
+msgid "German"
+msgstr "German"
+
+msgctxt "#30692"
+msgid "English"
+msgstr "English"
+
+msgctxt "#30693"
+msgid "French"
+msgstr "French"
+
+msgctxt "#30694"
+msgid "Spanish"
+msgstr "Spanish"
+
+msgctxt "#30695"
+msgid "Italian"
+msgstr "Italian"
+
+msgctxt "#30696"
+msgid "Japanese"
+msgstr "Japanese"
+
+msgctxt "#30697"
+msgid "Russian"
+msgstr "Russian"
+
+msgctxt "#30698"
+msgid "Other"
+msgstr "Other"
+
+msgctxt "#30699"
+msgid "None (audio language only)"
+msgstr "None (audio language only)"
+
+msgctxt "#30700"
+msgid "Auto-select 'No subtitles' if no match found"
+msgstr "Auto-select 'No subtitles' if no match found"
+
+msgctxt "#30701"
+msgid "Play with track selection"
+msgstr "Play with track selection"
diff --git a/resources/lib/functions.py b/resources/lib/functions.py
index a630104..fa618f2 100644
--- a/resources/lib/functions.py
+++ b/resources/lib/functions.py
@@ -923,6 +923,9 @@ def play_action(params):
audio_stream_index = params.get("audio_stream_index")
log.debug("audio_stream_index: {0}".format(audio_stream_index))
+ force_track_selection = params.get("force_track_selection", "false") == "true"
+ log.debug("force_track_selection: {0}".format(force_track_selection))
+
action = params.get("action", "play")
# set the current playing item id
@@ -939,6 +942,7 @@ def play_action(params):
play_info["media_source_id"] = media_source_id
play_info["subtitle_stream_index"] = subtitle_stream_index
play_info["audio_stream_index"] = audio_stream_index
+ play_info["force_track_selection"] = force_track_selection
log.info("Sending jellycon_play_action : {0}".format(play_info))
play_file(play_info)
diff --git a/resources/lib/item_functions.py b/resources/lib/item_functions.py
index 45dd2e1..da3ec4b 100644
--- a/resources/lib/item_functions.py
+++ b/resources/lib/item_functions.py
@@ -595,6 +595,20 @@ def add_gui_item(url, item_details, display_options, folder=True, default_sort=F
list_item.setProperties(item_properties)
+ # Add context menu for playable video items
+ if not folder and is_video and item_details.item_type.lower() in ['movie', 'episode']:
+ from . import translation
+ context_menu = []
+
+ # Add "Play with track selection" option
+ play_with_selection_url = (
+ 'RunPlugin(plugin://plugin.video.jellycon/'
+ '?mode=PLAY&item_id={}&force_track_selection=true)'.format(item_details.id)
+ )
+ context_menu.append((translation.translate_string(30701), play_with_selection_url))
+
+ list_item.addContextMenuItems(context_menu)
+
return u, list_item, folder
diff --git a/resources/lib/play_utils.py b/resources/lib/play_utils.py
index 955fd7a..37cb6a9 100644
--- a/resources/lib/play_utils.py
+++ b/resources/lib/play_utils.py
@@ -242,8 +242,10 @@ def play_file(play_info):
media_source_id = play_info.get("media_source_id", "")
subtitle_stream_index = play_info.get("subtitle_stream_index", None)
audio_stream_index = play_info.get("audio_stream_index", None)
+ force_track_selection = play_info.get("force_track_selection", False)
- log.debug("playFile id({0}) resume({1}) force_transcode({2})".format(item_id, auto_resume, force_transcode))
+ log.debug("playFile id({0}) resume({1}) force_transcode({2}) force_track_selection({3})".format(
+ item_id, auto_resume, force_transcode, force_track_selection))
addon_path = settings.getAddonInfo('path')
force_auto_resume = settings.getSetting('forceAutoResume') == 'true'
@@ -461,7 +463,7 @@ def play_file(play_info):
if playback_type == "2": # if transcoding then prompt for audio and subtitle
playurl = audio_subs_pref(playurl, list_item, selected_media_source, item_id, audio_stream_index,
- subtitle_stream_index)
+ subtitle_stream_index, force_track_selection)
log.debug("New playurl for transcoding: {0}".format(playurl))
elif playback_type == "1": # for direct stream add any streamable subtitles
@@ -778,7 +780,7 @@ def set_list_item_props(item_id, list_item, result, server, extra_props, title):
# Present the list of audio and subtitles to select from
# for external streamable subtitles add the URL to the Kodi item and let Kodi handle it
# else ask for the subtitles to be burnt in when transcoding
-def audio_subs_pref(url, list_item, media_source, item_id, audio_stream_index, subtitle_stream_index):
+def audio_subs_pref(url, list_item, media_source, item_id, audio_stream_index, subtitle_stream_index, force_track_selection=False):
dialog = xbmcgui.Dialog()
audio_streams_list = {}
audio_streams = []
@@ -795,11 +797,51 @@ def audio_subs_pref(url, list_item, media_source, item_id, audio_stream_index, s
source_id = media_source["Id"]
# Read user preferences
- preferred_audio_lang = settings.getSetting("preferred_audio_language").lower()
+ # Map select index to language code
+ lang_index_map = ['ger', 'eng', 'fra', 'spa', 'ita', 'jpn', 'rus', ''] # '' = other/custom
+ sub_lang_index_map = ['', 'ger', 'eng', 'fra', 'spa', 'ita', 'jpn', 'rus', ''] # First is 'none'
+
+ audio_lang_index = int(settings.getSetting("preferred_audio_language") or "0")
+ preferred_audio_lang = lang_index_map[audio_lang_index] if audio_lang_index < len(lang_index_map) else ''
+
auto_select_default_audio = settings.getSetting("auto_select_default_audio") == "true"
- preferred_sub_lang = settings.getSetting("preferred_subtitle_language").lower()
+
+ sub_lang_index = int(settings.getSetting("preferred_subtitle_language") or "1")
+ preferred_sub_lang = sub_lang_index_map[sub_lang_index] if sub_lang_index < len(sub_lang_index_map) else ''
+
prefer_forced = settings.getSetting("prefer_forced_subtitles") == "true"
prefer_srt = settings.getSetting("prefer_srt_over_pgs") == "true"
+ auto_no_subs = settings.getSetting("auto_no_subtitles_if_no_match") == "true"
+
+ # Language code mapping for better matching
+ language_map = {
+ 'ger': ['ger', 'deu', 'de', 'german', 'deutsch'],
+ 'eng': ['eng', 'en', 'english'],
+ 'fra': ['fra', 'fr', 'fre', 'french', 'français'],
+ 'spa': ['spa', 'es', 'spanish', 'español'],
+ 'ita': ['ita', 'it', 'italian', 'italiano'],
+ 'jpn': ['jpn', 'ja', 'japanese', '日本語'],
+ 'rus': ['rus', 'ru', 'russian'],
+ }
+
+ # Helper function to check if language matches
+ def language_matches(stream_lang, preferred_lang):
+ stream_lang = stream_lang.lower()
+ preferred_lang = preferred_lang.lower()
+
+ # Direct match
+ if preferred_lang in stream_lang or stream_lang in preferred_lang:
+ return True
+
+ # Check against language map
+ for key, variations in language_map.items():
+ if preferred_lang in variations:
+ # Check if stream language matches any variation
+ for variant in variations:
+ if variant in stream_lang or stream_lang.startswith(variant[:2]):
+ return True
+
+ return False
media_streams = media_source['MediaStreams']
@@ -856,7 +898,8 @@ def audio_subs_pref(url, list_item, media_source, item_id, audio_stream_index, s
subtitle_streams_data.append(stream)
# Auto-select audio track based on preferences
- if select_audio_index is None and len(audio_streams_data) > 0:
+ # Only auto-select if not already set by server/remote control AND not forcing manual selection
+ if not force_track_selection and select_audio_index is None and len(audio_streams_data) > 0 and (preferred_audio_lang or auto_select_default_audio):
auto_selected = None
best_score = -1
@@ -864,10 +907,10 @@ def audio_subs_pref(url, list_item, media_source, item_id, audio_stream_index, s
if preferred_audio_lang:
for stream in audio_streams_data:
score = 0
- stream_lang = stream.get('Language', '').lower()
+ stream_lang = stream.get('Language', '')
- # Match against common variations (ger, deu, de, german)
- if preferred_audio_lang in stream_lang or stream_lang.startswith(preferred_audio_lang[:3]):
+ # Match against common variations using language map
+ if language_matches(stream_lang, preferred_audio_lang):
score += 100 # Language match
# Bonus for default track
@@ -911,19 +954,29 @@ def audio_subs_pref(url, list_item, media_source, item_id, audio_stream_index, s
log.debug("Auto-selected audio (index {0}, score {1})".format(auto_selected, best_score))
# Auto-select subtitle track based on preferences
- if select_subs_index is None and len(subtitle_streams_data) > 0:
+ # Only auto-select if not already set by server/remote control AND not forcing manual selection
+ if force_track_selection:
+ log.debug("Forcing manual track selection (from context menu)")
+ elif select_subs_index is not None:
+ log.debug("Using subtitle index from server/remote: {0}".format(select_subs_index))
+ elif len(subtitle_streams_data) == 0:
+ log.debug("No subtitle streams available")
+ elif len(subtitle_streams_data) > 0 and preferred_sub_lang: # Only if user configured a language preference
auto_selected = None
best_score = -1
+ log.debug("Auto-selecting subtitle: preferred_lang={0}, prefer_forced={1}, prefer_srt={2}".format(
+ preferred_sub_lang, prefer_forced, prefer_srt))
+
for stream in subtitle_streams_data:
score = 0
- stream_lang = stream.get('Language', '').lower()
+ stream_lang = stream.get('Language', '')
codec = stream.get('Codec', '').lower()
is_forced = stream.get('IsForced', False)
is_default = stream.get('IsDefault', False)
# Score based on language match
- if preferred_sub_lang and (preferred_sub_lang in stream_lang or stream_lang.startswith(preferred_sub_lang[:3])):
+ if preferred_sub_lang and language_matches(stream_lang, preferred_sub_lang):
score += 100
# Bonus for forced if preferred
@@ -950,6 +1003,9 @@ def audio_subs_pref(url, list_item, media_source, item_id, audio_stream_index, s
if auto_selected is not None and best_score >= 100: # Only auto-select if language matched
select_subs_index = auto_selected
log.debug("Auto-selected subtitle (index {0}, score {1})".format(auto_selected, best_score))
+ elif auto_no_subs and preferred_sub_lang: # No match found but user wants auto "no subs"
+ select_subs_index = -1 # Special value to indicate "no subtitles"
+ log.debug("No matching subtitle found - auto-selected 'No subtitles'")
# set audio index
if select_audio_index is not None:
@@ -967,8 +1023,12 @@ def audio_subs_pref(url, list_item, media_source, item_id, audio_stream_index, s
# set subtitle index
if select_subs_index is not None:
+ # Handle special "no subtitles" value
+ if select_subs_index == -1:
+ # User wants no subtitles - do nothing
+ pass
# Load subtitles in the listitem if downloadable
- if select_subs_index in downloadable_streams:
+ elif select_subs_index in downloadable_streams:
subtitle_url = "%s/Videos/%s/%s/Subtitles/%s/Stream.srt"
subtitle_url = subtitle_url % (settings.getSetting('server_address'), item_id, source_id, select_subs_index)
log.debug("Streaming subtitles url: {0} {1}".format(select_subs_index, subtitle_url))
diff --git a/resources/settings.xml b/resources/settings.xml
index de1bc06..85958c2 100644
--- a/resources/settings.xml
+++ b/resources/settings.xml
@@ -50,11 +50,12 @@
-
+
-
+
+