diff --git a/addon.xml b/addon.xml index 3b82c5b..58f335e 100644 --- a/addon.xml +++ b/addon.xml @@ -2,20 +2,25 @@ - + executable - Language Preference Manager - Sets the audio and subtitle track according to your language preferences - For bugs, requests or general questions visit the Language Preference Manager thread on the Kodi forum. + Language Preference Manager + Sets the audio and subtitle track according to your language preferences + For bugs, requests or general questions visit the Language Preference Manager thread on the Kodi forum. all + Updated with changes required for Kodi 19 / Python 3 + + resources/icon.png + + diff --git a/changelog.txt b/changelog.txt index 4156f2a..535948e 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,12 +1,3 @@ ---- Version 0.0.8 - -- Fix compatibility with leia -- Added support for forced subtitles (ability to choose between normal or forced, in UI and conditional settings - ---- Version 0.0.7 - -- ? - --- Version 0.0.6 - Fix compatibility with jarvis and krypton diff --git a/default.py b/default.py index b5c0bcb..6d563b0 100644 --- a/default.py +++ b/default.py @@ -1,8 +1,5 @@ -# -*- coding: utf-8 -*- -# Your code goes below this line - import os, sys, re -import xbmc, xbmcaddon +import xbmc, xbmcaddon, xbmcvfs import json as simplejson @@ -11,8 +8,8 @@ __addonid__ = __addon__.getAddonInfo('id') __addonname__ = __addon__.getAddonInfo('name') __addonPath__ = __addon__.getAddonInfo('path') -__addonResourcePath__ = xbmc.translatePath(os.path.join(__addonPath__, 'resources', 'lib')) -__addonIconFile__ = xbmc.translatePath(os.path.join(__addonPath__, 'icon.png')) +__addonResourcePath__ = xbmcvfs.translatePath(os.path.join(__addonPath__, 'resources', 'lib')) +__addonIconFile__ = xbmcvfs.translatePath(os.path.join(__addonPath__, 'icon.png')) sys.path.append(__addonResourcePath__) from langcodes import * @@ -33,11 +30,7 @@ def log(level, msg): l = xbmc.LOGINFO elif level == LOG_DEBUG: l = xbmc.LOGDEBUG - - if isinstance(msg, dict): - xbmc.log("[Language Preference Manager]: " + str(msg), l) - else: - xbmc.log('[Language Preference Manager]: ' + msg.encode('ascii','replace'), l) + xbmc.log("[Language Preference Manager]: " + str(msg), l) class LangPref_Monitor( xbmc.Monitor ): @@ -62,9 +55,9 @@ def _init_vars( self ): self.Player = LangPrefMan_Player() def _daemon( self ): - while (not xbmc.abortRequested): - xbmc.sleep(500) - + while (not self.Monitor.abortRequested()): + self.Monitor.waitForAbort(1) + class LangPrefMan_Player(xbmc.Player) : @@ -109,8 +102,7 @@ def evalPrefs(self): if settings.turn_subs_off: log(LOG_INFO, 'Subtitle: disabling subs' ) self.showSubtitles(False) - - #import web_pdb; web_pdb.set_trace() + if settings.audio_prefs_on and not fa: if settings.custom_audio_prefs_on: trackIndex = self.evalAudioPrefs(settings.custom_audio) @@ -199,11 +191,11 @@ def evalAudioPrefs(self, audio_prefs): name, codes = pref codes = codes.split(r',') for code in codes: - if (code == 'non'): + if (code is None): log(LOG_DEBUG,'continue') continue if (self.selected_audio_stream and - self.selected_audio_stream.has_key('language') and + 'language' in self.selected_audio_stream and (code == self.selected_audio_stream['language'] or name == self.selected_audio_stream['language'])): log(LOG_INFO, 'Selected audio language matches preference {0} ({1})'.format(i, name) ) return -1 @@ -230,18 +222,20 @@ def evalSubPrefs(self, sub_prefs): name, codes, forced = pref codes = codes.split(r',') for code in codes: - if (code == 'non'): + if (code is None): log(LOG_DEBUG,'continue') continue - - for sub in sorted(self.subtitles, key=lambda subElt: (self.isExternalSub(subElt['name']))): - log(LOG_DEBUG, u'Wanted name={0}, wanted forced={1}, stream sub index={2} lang={3} name={4}, for iteration {5}'.format(name, forced, sub['index'], sub['language'], sub['name'], i)) - if ((code == sub['language']) or (name == sub['language'])): - if (self.testForcedFlag(forced, sub['name'])): - log(LOG_INFO, u'Subtitle language of subtitle {0} matches preference {1} ({2}) forced {3}'.format(sub['index'], i, name, forced) ) + if (self.selected_sub and + 'language' in self.selected_sub and + ((code == self.selected_sub['language'] or name == self.selected_sub['language']) and self.testForcedFlag(forced, self.selected_sub['name']))): + log(LOG_INFO, 'Selected subtitle language matches preference {0} ({1})'.format(i, name) ) + return -1 + else: + for sub in self.subtitles: + if ((code == sub['language'] or name == sub['language']) and self.testForcedFlag(forced, sub['name'])): + log(LOG_INFO, 'Subtitle language of subtitle {0} matches preference {1} ({2})'.format(sub['index'], i, name) ) return sub['index'] - - log(LOG_INFO, u'Subtitle: preference {0} ({1}:{2}) not available'.format(i, name, code) ) + log(LOG_INFO, 'Subtitle: preference {0} ({1}:{2}) not available'.format(i, name, code) ) return -2 def evalCondSubPrefs(self, condsub_prefs): @@ -263,40 +257,40 @@ def evalCondSubPrefs(self, condsub_prefs): log(LOG_INFO,'Cond Sub: genre/tag preference {0} met with intersection {1}'.format(g_t, (self.genres_and_tags & g_t))) for pref in preferences: audio_name, audio_code, sub_name, sub_code, forced = pref - if (audio_code == 'non'): + if (audio_code is None): log(LOG_DEBUG,'continue') continue if (self.selected_audio_stream and - self.selected_audio_stream.has_key('language') and + 'language' in self.selected_audio_stream and (audio_code == self.selected_audio_stream['language'] or audio_name == self.selected_audio_stream['language'])): - log(LOG_INFO, u'Selected audio language matches conditional preference {0} ({1}:{2}), force tag is {3}'.format(i, audio_name, sub_name, forced) ) - if (sub_code == 'non'): + log(LOG_INFO, 'Selected audio language matches conditional preference {0} ({1}:{2}), force tag is {3}'.format(i, audio_name, sub_name, forced) ) + if (sub_code is None): return -1 else: for sub in self.subtitles: if ((sub_code == sub['language']) or (sub_name == sub['language'])): if (self.testForcedFlag(forced, sub['name'])): - log(LOG_INFO, u'Language of subtitle {0} matches conditional preference {1} ({2}:{3}) forced {4}'.format(sub['index'], i, audio_name, sub_name, forced) ) + log(LOG_INFO, 'Language of subtitle {0} matches conditional preference {1} ({2}:{3}) forced {4}'.format(sub['index'], i, audio_name, sub_name, forced) ) return sub['index'] - log(LOG_INFO, u'Conditional subtitle: no match found for preference {0} ({1}:{2})'.format(i, audio_name, sub_name) ) + log(LOG_INFO, 'Conditional subtitle: no match found for preference {0} ({1}:{2})'.format(i, audio_name, sub_name) ) return -2 - + def testForcedFlag(self, forced, subName): test = subName.lower() - matches = [u'forced', u'forcés'] + matches = ['forced', 'forcés'] found = any(x in test for x in matches) return ((forced == 'false') and not found) or ((forced == 'true') and found) def isExternalSub(self, subName): test = subName.lower() - matches = [u'ext'] + matches = ['ext'] return any(x in test for x in matches) - + def getDetails(self): activePlayers ='{"jsonrpc": "2.0", "method": "Player.GetActivePlayers", "id": 1}' json_query = xbmc.executeJSONRPC(activePlayers) - json_query = unicode(json_query, 'utf-8', errors='ignore') + #json_query = unicode(json_query, 'utf-8', errors='ignore') json_response = simplejson.loads(json_query) activePlayerID = json_response['result'][0]['playerid'] details_query_dict = { "jsonrpc": "2.0", @@ -308,10 +302,10 @@ def getDetails(self): "id": 1} details_query_string = simplejson.dumps(details_query_dict) json_query = xbmc.executeJSONRPC(details_query_string) - json_query = unicode(json_query, 'utf-8', errors='ignore') + #json_query = unicode(json_query, 'utf-8', errors='ignore') json_response = simplejson.loads(json_query) - if json_response.has_key('result') and json_response['result'] != None: + if 'result' in json_response and json_response['result'] != None: self.selected_audio_stream = json_response['result']['currentaudiostream'] self.selected_sub = json_response['result']['currentsubtitle'] self.selected_sub_enabled = json_response['result']['subtitleenabled'] @@ -326,13 +320,13 @@ def getDetails(self): "id": 1} genre_tags_query_string = simplejson.dumps(genre_tags_query_dict) json_query = xbmc.executeJSONRPC(genre_tags_query_string) - json_query = unicode(json_query, 'utf-8', errors='ignore') + #json_query = unicode(json_query, 'utf-8', errors='ignore') json_response = simplejson.loads(json_query) - if json_response.has_key('result') and json_response['result'] != None: + if 'result' in json_response and json_response['result'] != None: gt = [] - if json_response['result']['item'].has_key('genre'): + if 'genre' in json_response['result']['item']: gt = json_response['result']['item']['genre'] - if json_response['result']['item'].has_key('tag'): + if 'tag' in json_response['result']['item']: gt.extend(json_response['result']['item']['tag']) self.genres_and_tags = set(map(lambda x:x.lower(), gt)) log(LOG_DEBUG, 'Video tags/genres: {0}'.format(self.genres_and_tags)) diff --git a/resources/icon.png b/resources/icon.png new file mode 100644 index 0000000..c312af5 Binary files /dev/null and b/resources/icon.png differ diff --git a/resources/language/resource.language.en_gb/strings.po b/resources/language/resource.language.en_gb/strings.po new file mode 100644 index 0000000..b0089c3 --- /dev/null +++ b/resources/language/resource.language.en_gb/strings.po @@ -0,0 +1,290 @@ +# Kodi Media Center language file +# Addon Name: Language Preference Manager +# Addon id: service.languagepreferencemanager +# Addon Provider: ace20022 +msgid "" +msgstr "" +"Project-Id-Version: Kodi Addons\n" +"Report-Msgid-Bugs-To: https://forum.kodi.tv/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: Team-Kodi\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_GB\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30100" +msgid "Languages" +msgstr "" + +msgctxt "#30101" +msgid "Primary Language" +msgstr "" + +msgctxt "#30102" +msgid "Secondary Language" +msgstr "" + +msgctxt "#30103" +msgid "Third Language" +msgstr "" + +msgctxt "#30104" +msgid "Audio Preferences" +msgstr "" + +msgctxt "#30105" +msgid "Subtitle Preferences" +msgstr "" + +msgctxt "#30106" +msgid "Conditional Subtitle Preferences" +msgstr "" + +msgctxt "#30107" +msgid "Enable Preference" +msgstr "" + +msgctxt "#30108" +msgid "Enable Language Preference Manager" +msgstr "" + +msgctxt "#30109" +msgid "Pause while evaluating preferences" +msgstr "" + +msgctxt "#30110" +msgid "If audio language is " +msgstr "" + +msgctxt "#30111" +msgid "then display subtitles with language" +msgstr "" + +msgctxt "#30112" +msgid "Delay the evaluation by the following value [ms]" +msgstr "" + +msgctxt "#30113" +msgid "Turn on subtitles if a subtitle prefrence matched" +msgstr "" + +msgctxt "#30114" +msgid "Turn off subtitles if no subtitle prefrence matched" +msgstr "" + +msgctxt "#30115" +msgid "Advanced/Custom settings" +msgstr "" + +msgctxt "#30116" +msgid "Try to set the audio and/or subtitle track from the filename first" +msgstr "" + +msgctxt "#30117" +msgid "Regular expression for filename based preferences" +msgstr "" + +msgctxt "#30118" +msgid "Use custom pref, e.g. eng>ger>fin :" +msgstr "" + +msgctxt "#30119" +msgid "Use custom pref, e.g. eng>ger>fin :" +msgstr "" + +msgctxt "#30120" +msgid "Forced" +msgstr "" + +msgctxt "#30121" +msgid "Use custom pref, e.g. jpn:eng>eng:ger :" +msgstr "" + +msgctxt "#30122" +msgid "General" +msgstr "" + +msgctxt "#30201" +msgid "Albanian" +msgstr "" + +msgctxt "#30202" +msgid "Arabic" +msgstr "" + +msgctxt "#30203" +msgid "Belarusian" +msgstr "" + +msgctxt "#30204" +msgid "Bosnian (Latin)" +msgstr "" + +msgctxt "#30205" +msgid "Bulgarian" +msgstr "" + +msgctxt "#30206" +msgid "Catalan" +msgstr "" + +msgctxt "#30207" +msgid "Chinese" +msgstr "" + +msgctxt "#30208" +msgid "Croatian" +msgstr "" + +msgctxt "#30209" +msgid "Czech" +msgstr "" + +msgctxt "#30210" +msgid "Danish" +msgstr "" + +msgctxt "#30211" +msgid "Dutch" +msgstr "" + +msgctxt "#30212" +msgid "English" +msgstr "" + +msgctxt "#30213" +msgid "Estonian" +msgstr "" + +msgctxt "#30214" +msgid "Finnish" +msgstr "" + +msgctxt "#30215" +msgid "French" +msgstr "" + +msgctxt "#30216" +msgid "German" +msgstr "" + +msgctxt "#30217" +msgid "Greek" +msgstr "" + +msgctxt "#30218" +msgid "Hebrew" +msgstr "" + +msgctxt "#30219" +msgid "Hindi" +msgstr "" + +msgctxt "#30220" +msgid "Hungarian" +msgstr "" + +msgctxt "#30221" +msgid "Icelandic" +msgstr "" + +msgctxt "#30222" +msgid "Indonesian" +msgstr "" + +msgctxt "#30224" +msgid "Italian" +msgstr "" + +msgctxt "#30225" +msgid "Japanese" +msgstr "" + +msgctxt "#30226" +msgid "Korean" +msgstr "" + +msgctxt "#30227" +msgid "Latvian" +msgstr "" + +msgctxt "#30228" +msgid "Lithuanian" +msgstr "" + +msgctxt "#30229" +msgid "Macedonian" +msgstr "" + +msgctxt "#30230" +msgid "Norwegian" +msgstr "" + +msgctxt "#30232" +msgid "Polish" +msgstr "" + +msgctxt "#30233" +msgid "Portuguese" +msgstr "" + +msgctxt "#30234" +msgid "Portuguese (Brazil)" +msgstr "" + +msgctxt "#30235" +msgid "Romanian" +msgstr "" + +msgctxt "#30236" +msgid "Russian" +msgstr "" + +msgctxt "#30237" +msgid "SerbianLatin" +msgstr "" + +msgctxt "#30238" +msgid "Slovak" +msgstr "" + +msgctxt "#30239" +msgid "Slovenian" +msgstr "" + +msgctxt "#30240" +msgid "Spanish" +msgstr "" + +msgctxt "#30242" +msgid "Swedish" +msgstr "" + +msgctxt "#30243" +msgid "Thai" +msgstr "" + +msgctxt "#30244" +msgid "Turkish" +msgstr "" + +msgctxt "#30245" +msgid "Ukrainian" +msgstr "" + +msgctxt "#30246" +msgid "Vietnamese" +msgstr "" + +msgctxt "#30247" +msgid "Farsi" +msgstr "" + +msgctxt "#30248" +msgid "None" +msgstr "" + diff --git a/resources/lib/prefparser.py b/resources/lib/prefparser.py index 98c766c..f6ec180 100644 --- a/resources/lib/prefparser.py +++ b/resources/lib/prefparser.py @@ -31,7 +31,6 @@ def __init__( self ): self.custom_g_t_pref_delim = r'#' self.custom_g_t_delim = r',' self.custom_condSub_delim = r':' - self.custom_condType_delim = r'/' def parsePrefString(self, pref_string): preferences = [] @@ -80,30 +79,13 @@ def parsePref(self, prefs): self.log(LOG_INFO, 'Custom cond subs prefs parse error: {0}'.format(pref)) else: temp_a = (languageTranslate(pref[0], 3, 0), pref[0]) - tmp_s = pref[1].split(self.custom_condType_delim) - if len(tmp_s) != 2: - self.log(LOG_INFO, 'Custom cond type prefs parse error: {0}'.format(tmp_s)) + temp_s = (languageTranslate(pref[1], 3, 0), pref[1]) + if (temp_a[0] and temp_a[1] and temp_s[0] and temp_s[1]): + lang_prefs.append((temp_a[0], temp_a[1], temp_s[0], temp_s[1])) else: - temp_s = (languageTranslate(tmp_s[0], 3, 0), tmp_s[0]) - temp_t = tmp_s[1] - if (temp_a[0] and temp_a[1] and temp_s[0] and temp_s[1] and temp_t): - lang_prefs.append((temp_a[0], temp_a[1], temp_s[0], temp_s[1], temp_t)) - else: - self.log(LOG_INFO, 'Custom cond sub prefs: lang code not found in db!'\ - ' Please report this: {0}:{1}'.format(temp_a, temp_s)) - # custom sub pref - elif (pref.find(self.custom_condType_delim) > 0): - tmp_pref = pref.split(self.custom_condType_delim) - if len(tmp_pref) != 2: - self.log(LOG_INFO, 'Custom sub prefs parse error: {0}'.format(tmp_pref)) - temp_pref = (languageTranslate(tmp_pref[0], 3, 0), tmp_pref[0]) - temp_t = tmp_pref[1] - if (temp_pref[0] and temp_t): - lang_prefs.append(temp_pref, temp_t) - else: - self.log(LOG_INFO, 'Custom sub prefs: lang code {0} not found in db!'\ - ' Please report this'.format(pref)) - # custom audio pref + self.log(LOG_INFO, 'Custom cond sub prefs: lang code not found in db!'\ + ' Please report this: {0}:{1}'.format(temp_a, temp_s)) + # custom audio or subtitle pref else: temp_pref = (languageTranslate(pref, 3, 0), pref) if temp_pref[0]: diff --git a/resources/settings.xml b/resources/settings.xml index 6a051eb..428aa8e 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -1,59 +1,829 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +
+ + + + false + + + + 1 + + + + + + + + + + + + + + false + + + + false + + + + false + + + + audiostream[_|.|-]*\d+|subtitle[_|.|-]*\d+ + + false + + + 30117 + + + + 300 + + 30112 + + + + false + + + + + + + + + false + + + + + + 46 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 46 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 46 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + 30118 + + + + + + + + false + + + + + + 46 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + 46 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + 46 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + false + + + 30119 + + + + + + + + false + + + + + + 46 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 46 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + 46 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 46 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + 46 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 46 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + false + + + + + + + + false + + + 30121 + + + + +