From d96e69c818c8995aa03769d773b6996b9052d1bd Mon Sep 17 00:00:00 2001 From: montellese Date: Wed, 22 Oct 2014 11:25:01 +0200 Subject: [PATCH] addons: add new kodi.resource(.language) addon type --- addons/kodi.resource/addon.xml | 8 ++ addons/kodi.resource/language.xsd | 61 +++++++++ language/English/strings.po | 12 +- xbmc/addons/Addon.cpp | 3 +- xbmc/addons/AddonManager.cpp | 11 ++ xbmc/addons/IAddon.h | 1 + xbmc/addons/LanguageResource.cpp | 200 ++++++++++++++++++++++++++++++ xbmc/addons/LanguageResource.h | 80 ++++++++++++ xbmc/addons/Makefile | 1 + xbmc/addons/Resource.h | 50 ++++++++ 10 files changed, 424 insertions(+), 3 deletions(-) create mode 100644 addons/kodi.resource/addon.xml create mode 100644 addons/kodi.resource/language.xsd create mode 100644 xbmc/addons/LanguageResource.cpp create mode 100644 xbmc/addons/LanguageResource.h create mode 100644 xbmc/addons/Resource.h diff --git a/addons/kodi.resource/addon.xml b/addons/kodi.resource/addon.xml new file mode 100644 index 0000000000000..8002e410c8dd2 --- /dev/null +++ b/addons/kodi.resource/addon.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/addons/kodi.resource/language.xsd b/addons/kodi.resource/language.xsd new file mode 100644 index 0000000000000..63d5cae3bb842 --- /dev/null +++ b/addons/kodi.resource/language.xsd @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/language/English/strings.po b/language/English/strings.po index e95433f75b562..4ccf60d6607a6 100644 --- a/language/English/strings.po +++ b/language/English/strings.po @@ -12377,7 +12377,10 @@ msgctxt "#24025" msgid "Context Items" msgstr "" -#empty string with id 24026 +#: xbmc/addons/Addon.cpp +msgctxt "#24026" +msgid "Languages" +msgstr "" #: xbmc/addons/Addon.cpp msgctxt "#24027" @@ -12896,7 +12899,12 @@ msgctxt "#24131" msgid "Enable to parse for CC in video stream. Puts slightly more load on the CPU" msgstr "" -#empty strings from id 24132 to 24998 +#: xbmc/addons/LanguageResource.cpp +msgctxt "#24132" +msgid "Would you like to switch to this language?" +msgstr "" + +#empty strings from id 24133 to 24998 msgctxt "#24999" msgid "Hide incompatible" diff --git a/xbmc/addons/Addon.cpp b/xbmc/addons/Addon.cpp index bd4ad7bf59dc2..d59b099cece02 100644 --- a/xbmc/addons/Addon.cpp +++ b/xbmc/addons/Addon.cpp @@ -91,7 +91,8 @@ static const TypeMapping types[] = {"xbmc.addon.executable", ADDON_EXECUTABLE, 1043, "DefaultAddonProgram.png" }, {"xbmc.audioencoder", ADDON_AUDIOENCODER, 200, "DefaultAddonAudioEncoder.png" }, {"kodi.audiodecoder", ADDON_AUDIODECODER, 201, "DefaultAddonAudioDecoder.png" }, - {"xbmc.service", ADDON_SERVICE, 24018, "DefaultAddonService.png" }}; + {"xbmc.service", ADDON_SERVICE, 24018, "DefaultAddonService.png" }, + {"kodi.resource.language", ADDON_RESOURCE_LANGUAGE, 24026, "DefaultAddonLanguage.png" }}; const std::string TranslateType(const ADDON::TYPE &type, bool pretty/*=false*/) { diff --git a/xbmc/addons/AddonManager.cpp b/xbmc/addons/AddonManager.cpp index 67a7f62b1f33f..75d263442eb61 100644 --- a/xbmc/addons/AddonManager.cpp +++ b/xbmc/addons/AddonManager.cpp @@ -22,6 +22,7 @@ #include "AudioEncoder.h" #include "AudioDecoder.h" #include "DllLibCPluff.h" +#include "LanguageResource.h" #include "utils/StringUtils.h" #include "utils/JobManager.h" #include "threads/SingleLock.h" @@ -172,6 +173,8 @@ AddonPtr CAddonMgr::Factory(const cp_extension_t *props) } case ADDON_SKIN: return AddonPtr(new CSkinInfo(props)); + case ADDON_RESOURCE_LANGUAGE: + return AddonPtr(new CLanguageResource(props)); case ADDON_VIZ_LIBRARY: return AddonPtr(new CAddonLibrary(props)); case ADDON_REPOSITORY: @@ -531,6 +534,9 @@ bool CAddonMgr::GetDefault(const TYPE &type, AddonPtr &addon) case ADDON_WEB_INTERFACE: setting = CSettings::Get().GetString("services.webskin"); break; + case ADDON_RESOURCE_LANGUAGE: + setting = CSettings::Get().GetString("locale.language"); + break; default: return false; } @@ -562,6 +568,9 @@ bool CAddonMgr::SetDefault(const TYPE &type, const std::string &addonID) case ADDON_SCRAPER_TVSHOWS: CSettings::Get().SetString("scrapers.tvshowsdefault",addonID); break; + case ADDON_RESOURCE_LANGUAGE: + CSettings::Get().SetString("locale.language", addonID); + break; default: return false; } @@ -759,6 +768,8 @@ AddonPtr CAddonMgr::AddonFromProps(AddonProps& addonProps) return AddonPtr(new CAudioEncoder(addonProps)); case ADDON_AUDIODECODER: return AddonPtr(new CAudioDecoder(addonProps)); + case ADDON_RESOURCE_LANGUAGE: + return AddonPtr(new CLanguageResource(addonProps)); case ADDON_REPOSITORY: return AddonPtr(new CRepository(addonProps)); case ADDON_CONTEXT_ITEM: diff --git a/xbmc/addons/IAddon.h b/xbmc/addons/IAddon.h index 8cbcd043ef518..576169cf4cc4f 100644 --- a/xbmc/addons/IAddon.h +++ b/xbmc/addons/IAddon.h @@ -52,6 +52,7 @@ namespace ADDON ADDON_AUDIOENCODER, ADDON_CONTEXT_ITEM, ADDON_AUDIODECODER, + ADDON_RESOURCE_LANGUAGE, ADDON_VIDEO, // virtual addon types ADDON_AUDIO, ADDON_IMAGE, diff --git a/xbmc/addons/LanguageResource.cpp b/xbmc/addons/LanguageResource.cpp new file mode 100644 index 0000000000000..d45450d78aec8 --- /dev/null +++ b/xbmc/addons/LanguageResource.cpp @@ -0,0 +1,200 @@ +/* +* Copyright (C) 2005-2013 Team XBMC +* http://xbmc.org +* +* This Program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2, or (at your option) +* any later version. +* +* This Program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with XBMC; see the file COPYING. If not, see +* . +* +*/ +#include "LanguageResource.h" +#include "LangInfo.h" +#include "addons/AddonManager.h" +#include "dialogs/GUIDialogKaiToast.h" +#include "dialogs/GUIDialogYesNo.h" +#include "guilib/GUIWindowManager.h" +#include "settings/Settings.h" +#include "utils/StringUtils.h" + +#define LANGUAGE_SETTING "locale.language" +#define LANGUAGE_ADDON_PREFIX "resource.language." + +using namespace std; + +namespace ADDON +{ + +CLanguageResource::CLanguageResource(const cp_extension_t *ext) + : CResource(ext) +{ + m_forceUnicodeFont = false; + if (ext != NULL) + { + // parse attributes + std::string locale = CAddonMgr::Get().GetExtValue(ext->configuration, "@locale"); + m_locale = CLocale::FromString(locale); + + // parse + cp_cfg_element_t *charsetsElement = CAddonMgr::Get().GetExtElement(ext->configuration, "charsets"); + if (charsetsElement != NULL) + { + m_charsetGui = CAddonMgr::Get().GetExtValue(charsetsElement, "gui"); + m_forceUnicodeFont = CAddonMgr::Get().GetExtValue(charsetsElement, "gui@unicodefont") == "true"; + m_charsetSubtitle = CAddonMgr::Get().GetExtValue(charsetsElement, "subtitle"); + } + + // parse + cp_cfg_element_t *dvdElement = CAddonMgr::Get().GetExtElement(ext->configuration, "dvd"); + if (dvdElement != NULL) + { + m_dvdLanguageMenu = CAddonMgr::Get().GetExtValue(dvdElement, "menu"); + m_dvdLanguageAudio = CAddonMgr::Get().GetExtValue(dvdElement, "audio"); + m_dvdLanguageSubtitle = CAddonMgr::Get().GetExtValue(dvdElement, "subtitle"); + } + // fall back to the language of the addon if a DVD language is not defined + if (m_dvdLanguageMenu.empty()) + m_dvdLanguageMenu = m_locale.GetLanguageCode(); + if (m_dvdLanguageAudio.empty()) + m_dvdLanguageAudio = m_locale.GetLanguageCode(); + if (m_dvdLanguageSubtitle.empty()) + m_dvdLanguageSubtitle = m_locale.GetLanguageCode(); + + // parse + cp_cfg_element_t *sorttokensElement = CAddonMgr::Get().GetExtElement(ext->configuration, "sorttokens"); + if (sorttokensElement != NULL) + { + for (size_t i = 0; i < sorttokensElement->num_children; ++i) + { + cp_cfg_element_t &tokenElement = sorttokensElement->children[i]; + if (tokenElement.name != NULL && strcmp(tokenElement.name, "token") == 0 && + tokenElement.value != NULL) + { + std::string token(tokenElement.value); + std::string separators = CAddonMgr::Get().GetExtValue(&tokenElement, "@separators"); + if (separators.empty()) + separators = " ._"; + + for (std::string::const_iterator separator = separators.begin(); separator != separators.end(); ++separator) + m_sortTokens.insert(token + *separator); + } + } + } + } +} + +CLanguageResource::CLanguageResource(const CLanguageResource &rhs) + : CResource(rhs), + m_locale(rhs.m_locale) +{ } + +AddonPtr CLanguageResource::Clone() const +{ + return AddonPtr(new CLanguageResource(*this)); +} + +bool CLanguageResource::IsInUse() const +{ + return StringUtils::EqualsNoCase(CSettings::Get().GetString(LANGUAGE_SETTING), ID()); +} + +bool CLanguageResource::OnPreInstall() +{ + return IsInUse(); +} + +void CLanguageResource::OnPostInstall(bool restart, bool update) +{ + if (restart || + (!update && CGUIDialogYesNo::ShowAndGetInput(Name(), g_localizeStrings.Get(24132), "", ""))) + { + CGUIDialogKaiToast *toast = (CGUIDialogKaiToast *)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST); + if (toast) + { + toast->ResetTimer(); + toast->Close(true); + } + + if (IsInUse()) + g_langInfo.SetLanguage(ID()); + else + CSettings::Get().SetString(LANGUAGE_SETTING, ID()); + } +} + +bool CLanguageResource::IsAllowed(const std::string &file) const +{ + return file.empty() || + StringUtils::EqualsNoCase(file.c_str(), "langinfo.xml") || + StringUtils::EqualsNoCase(file.c_str(), "strings.po") || + StringUtils::EqualsNoCase(file.c_str(), "strings.xml"); +} + +std::string CLanguageResource::GetAddonId(const std::string& locale) +{ + if (locale.empty()) + return ""; + + std::string addonId = locale; + if (!StringUtils::StartsWith(addonId, LANGUAGE_ADDON_PREFIX)) + addonId = LANGUAGE_ADDON_PREFIX + locale; + + StringUtils::ToLower(addonId); + return addonId; +} + +bool CLanguageResource::FindLegacyLanguage(const std::string &locale, std::string &legacyLanguage) +{ + if (locale.empty()) + return false; + + std::string addonId = GetAddonId(locale); + + AddonPtr addon; + if (!CAddonMgr::Get().GetAddon(addonId, addon, ADDON_RESOURCE_LANGUAGE, true)) + return false; + + legacyLanguage = addon->Name(); + return true; +} + +bool CLanguageResource::FindLanguageAddonByName(const std::string &legacyLanguage, std::string &addonId, const VECADDONS &languageAddons /* = VECADDONS() */) +{ + if (legacyLanguage.empty()) + return false; + + VECADDONS addons; + if (!languageAddons.empty()) + addons = languageAddons; + else if (!CAddonMgr::Get().GetAddons(ADDON_RESOURCE_LANGUAGE, addons, true) || addons.empty()) + return false; + + // try to find a language that matches the old language in name or id + for (VECADDONS::const_iterator addon = addons.begin(); addon != addons.end(); ++addon) + { + const CLanguageResource* languageAddon = static_cast(addon->get()); + + // check if the old language matches the language addon id, the language + // locale or the language addon name + if (legacyLanguage.compare((*addon)->ID()) == 0 || + languageAddon->GetLocale().Equals(legacyLanguage) || + StringUtils::EqualsNoCase(legacyLanguage, languageAddon->Name())) + { + addonId = (*addon)->ID(); + return true; + } + } + + return false; +} + +} diff --git a/xbmc/addons/LanguageResource.h b/xbmc/addons/LanguageResource.h new file mode 100644 index 0000000000000..8167fb60195be --- /dev/null +++ b/xbmc/addons/LanguageResource.h @@ -0,0 +1,80 @@ +#pragma once +/* + * Copyright (C) 2014 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#include + +#include "addons/Resource.h" +#include "utils/Locale.h" + +namespace ADDON +{ +class CLanguageResource : public CResource +{ +public: + CLanguageResource(const AddonProps &props) + : CResource(props) + { } + CLanguageResource(const cp_extension_t *ext); + virtual ~CLanguageResource() { } + + virtual AddonPtr Clone() const; + + virtual bool IsInUse() const; + + virtual bool OnPreInstall(); + virtual void OnPostInstall(bool restart, bool update); + + virtual bool IsAllowed(const std::string &file) const; + + const CLocale& GetLocale() const { return m_locale; } + + const std::string& GetGuiCharset() const { return m_charsetGui; } + bool ForceUnicodeFont() const { return m_forceUnicodeFont; } + const std::string& GetSubtitleCharset() const { return m_charsetSubtitle; } + + const std::string& GetDvdMenuLanguage() const { return m_dvdLanguageMenu; } + const std::string& GetDvdAudioLanguage() const { return m_dvdLanguageAudio; } + const std::string& GetDvdSubtitleLanguage() const { return m_dvdLanguageSubtitle; } + + const std::set& GetSortTokens() const { return m_sortTokens; } + + static std::string GetAddonId(const std::string& locale); + + static bool FindLegacyLanguage(const std::string &locale, std::string &legacyLanguage); + static bool FindLanguageAddonByName(const std::string &legacyLanguage, std::string &addonId, const VECADDONS &languageAddons = VECADDONS()); + +private: + CLanguageResource(const CLanguageResource &rhs); + + CLocale m_locale; + + std::string m_charsetGui; + bool m_forceUnicodeFont; + std::string m_charsetSubtitle; + + std::string m_dvdLanguageMenu; + std::string m_dvdLanguageAudio; + std::string m_dvdLanguageSubtitle; + + std::set m_sortTokens; +}; + +} diff --git a/xbmc/addons/Makefile b/xbmc/addons/Makefile index e8eca6ad05049..6ab60b733409c 100644 --- a/xbmc/addons/Makefile +++ b/xbmc/addons/Makefile @@ -16,6 +16,7 @@ SRCS=Addon.cpp \ GUIDialogAddonSettings.cpp \ GUIViewStateAddonBrowser.cpp \ GUIWindowAddonBrowser.cpp \ + LanguageResource.cpp \ PluginSource.cpp \ Repository.cpp \ Scraper.cpp \ diff --git a/xbmc/addons/Resource.h b/xbmc/addons/Resource.h new file mode 100644 index 0000000000000..4e4884e9987b7 --- /dev/null +++ b/xbmc/addons/Resource.h @@ -0,0 +1,50 @@ +#pragma once +/* + * Copyright (C) 2014 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * . + * + */ + +#include + +#include "addons/Addon.h" + +namespace ADDON +{ + +class CResource : public CAddon +{ +public: + virtual ~CResource() { } + + virtual AddonPtr Clone() const = 0; + + virtual bool IsAllowed(const std::string &file) const = 0; + +protected: + CResource(const AddonProps &props) + : CAddon(props) + { } + CResource(const cp_extension_t *ext) + : CAddon(ext) + { } + CResource(const CResource &rhs) + : CAddon(rhs) + { } +}; + +}