Skip to content

Commit

Permalink
addons: add new kodi.resource(.language) addon type
Browse files Browse the repository at this point in the history
  • Loading branch information
Montellese committed Mar 6, 2015
1 parent 580fe4e commit d96e69c
Show file tree
Hide file tree
Showing 10 changed files with 424 additions and 3 deletions.
8 changes: 8 additions & 0 deletions addons/kodi.resource/addon.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<addon id="kodi.resource" version="1.0.0" provider-name="Team-Kodi">
<backwards-compatibility abi="1.0"/>
<requires>
<import addon="xbmc.core" version="0.1.0"/>
</requires>
<extension-point id="resource.language" schema="language.xsd"/>
</addon>
61 changes: 61 additions & 0 deletions addons/kodi.resource/language.xsd
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE schema PUBLIC "-//W3C//DTD XMLSCHEMA 200102//EN" "http://www.w3.org/2001/XMLSchema.dtd">
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="extension">
<xs:complexType>
<xs:sequence>
<xs:element name="charsets">
<xs:complexType>
<xs:sequence>
<xs:element name="gui">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="unicodefont" type="xs:boolean"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="subtitle" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="sorttokens" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="token" minOccurs="1" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="separators" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="dvd" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="menu" type="xs:string" minOccurs="0"/>
<xs:element name="audio" type="xs:string" minOccurs="0"/>
<xs:element name="subtitle" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="point" type="xs:string" use="required"/>
<xs:attribute name="id" type="simpleIdentifier"/>
<xs:attribute name="name" type="xs:string"/>
<xs:attribute name="locale" type="xs:string"/>
<xs:attribute name="language" type="xs:string"/>
<xs:attribute name="region" type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:simpleType name="simpleIdentifier">
<xs:restriction base="xs:string">
<xs:pattern value="[^.]+"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
12 changes: 10 additions & 2 deletions language/English/strings.po
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand Down
3 changes: 2 additions & 1 deletion xbmc/addons/Addon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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*/)
{
Expand Down
11 changes: 11 additions & 0 deletions xbmc/addons/AddonManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions xbmc/addons/IAddon.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
200 changes: 200 additions & 0 deletions xbmc/addons/LanguageResource.cpp
Original file line number Diff line number Diff line change
@@ -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
* <http://www.gnu.org/licenses/>.
*
*/
#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 <extension> attributes
std::string locale = CAddonMgr::Get().GetExtValue(ext->configuration, "@locale");
m_locale = CLocale::FromString(locale);

// parse <charsets>
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 <dvd>
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 <sorttokens>
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<CLanguageResource*>(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;
}

}
Loading

0 comments on commit d96e69c

Please sign in to comment.