17
17
* <http://www.gnu.org/licenses/>.
20
21
#include "AddonManager.h"
22
23
#include "AudioEncoder.h"
24
#include "AudioDecoder.h"
25
#include "ContextMenuManager.h"
23
26
#include "DllLibCPluff.h"
27
#include "LanguageResource.h"
28
#include "UISoundsResource.h"
24
29
#include "utils/StringUtils.h"
25
30
#include "utils/JobManager.h"
26
31
#include "threads/SingleLock.h"
28
32
#include "LangInfo.h"
29
33
#include "settings/AdvancedSettings.h"
30
34
#include "settings/Settings.h"
163
168
else if (type == ADDON_AUDIOENCODER)
164
169
return AddonPtr(new CAudioEncoder(props));
170
else if (type == ADDON_AUDIODECODER)
171
return AddonPtr(new CAudioDecoder(props));
166
173
return AddonPtr(new CScreenSaver(props));
169
176
return AddonPtr(new CSkinInfo(props));
177
case ADDON_RESOURCE_LANGUAGE:
178
return AddonPtr(new CLanguageResource(props));
179
case ADDON_RESOURCE_UISOUNDS:
180
return AddonPtr(new CUISoundsResource(props));
170
181
case ADDON_VIZ_LIBRARY:
171
182
return AddonPtr(new CAddonLibrary(props));
172
183
case ADDON_REPOSITORY:
173
184
return AddonPtr(new CRepository(props));
185
case ADDON_CONTEXT_ITEM:
186
return AddonPtr(new CContextItemAddon(props));
275
288
m_cp_context = m_cpluff->create_context(&status);
276
289
assert(m_cp_context);
277
290
status = m_cpluff->register_pcollection(m_cp_context, CSpecialProtocol::TranslatePath("special://home/addons").c_str());
293
CLog::Log(LOGERROR, "ADDONS: Fatal Error, cp_register_pcollection() returned status: %i", status);
278
297
status = m_cpluff->register_pcollection(m_cp_context, CSpecialProtocol::TranslatePath("special://xbmc/addons").c_str());
300
CLog::Log(LOGERROR, "ADDONS: Fatal Error, cp_register_pcollection() returned status: %i", status);
279
304
status = m_cpluff->register_pcollection(m_cp_context, CSpecialProtocol::TranslatePath("special://xbmcbin/addons").c_str());
280
305
if (status != CP_OK)
321
// disable some system addons by default because they are optional
323
GetAddons(ADDON_PVRDLL, addons);
324
GetAddons(ADDON_AUDIODECODER, addons);
325
std::string systemAddonsPath = CSpecialProtocol::TranslatePath("special://xbmc/addons");
326
for (auto &addon : addons)
328
if (StringUtils::StartsWith(addon->Path(), systemAddonsPath))
330
if (!m_database.IsSystemAddonRegistered(addon->ID()))
332
m_database.DisableAddon(addon->ID());
333
m_database.AddSystemAddon(addon->ID());
338
std::vector<std::string> disabled;
339
m_database.GetDisabled(disabled);
340
m_disabled.insert(disabled.begin(), disabled.end());
297
343
if (GetAddons(ADDON_REPOSITORY, repos))
322
368
return GetAddons(type, addons, enabled);
325
bool CAddonMgr::GetAllAddons(VECADDONS &addons, bool enabled /*= true*/, bool allowRepos /* = false */)
371
bool CAddonMgr::GetAllAddons(VECADDONS &addons, bool enabled /*= true*/)
327
for (int i = ADDON_UNKNOWN+1; i < ADDON_MAX; ++i)
373
CSingleLock lock(m_critSection);
379
cp_plugin_info_t **cpaddons = m_cpluff->get_plugins_info(m_cp_context, &status, &num);
381
for (int i = 0; i < num; ++i)
329
if (!allowRepos && ADDON_REPOSITORY == (TYPE)i)
332
if (CAddonMgr::Get().GetAddons((TYPE)i, temp, enabled))
333
addons.insert(addons.end(), temp.begin(), temp.end());
383
const cp_plugin_info_t *cpaddon = cpaddons[i];
384
if (cpaddon->extensions && IsAddonDisabled(cpaddon->identifier) != enabled)
386
//Get the first extension only
387
AddonPtr addon = Factory(&cpaddon->extensions[0]);
392
// if the addon has a running instance, grab that
393
AddonPtr runningAddon = addon->GetRunningInstance();
395
addon = runningAddon;
397
addons.push_back(addon);
401
m_cpluff->release_info(m_cp_context, cpaddons);
335
402
return !addons.empty();
572
644
NotifyObservers(ObservableMessageAddons);
575
void CAddonMgr::RemoveAddon(const std::string& ID)
647
void CAddonMgr::UnregisterAddon(const std::string& ID)
649
CSingleLock lock(m_critSection);
650
m_disabled.erase(ID);
577
651
if (m_cpluff && m_cp_context)
579
m_cpluff->uninstall_plugin(m_cp_context,ID.c_str());
653
m_cpluff->uninstall_plugin(m_cp_context, ID.c_str());
581
656
NotifyObservers(ObservableMessageAddons);
585
bool CAddonMgr::DisableAddon(const std::string& ID, bool disable)
587
CSingleLock lock(m_critSection);
588
if (m_database.DisableAddon(ID, disable))
590
m_disabled[ID] = disable;
660
bool CAddonMgr::DisableAddon(const std::string& id)
662
CSingleLock lock(m_critSection);
663
if (m_disabled.find(id) != m_disabled.end())
664
return true; //already disabled
666
if (!CanAddonBeDisabled(id))
668
if (!m_database.DisableAddon(id))
670
if (!m_disabled.insert(id).second)
674
ADDON::OnDisabled(id);
678
bool CAddonMgr::EnableAddon(const std::string& id)
680
CSingleLock lock(m_critSection);
681
if (m_disabled.find(id) == m_disabled.end())
682
return true; //already enabled
684
if (!m_database.DisableAddon(id, false))
686
if (m_disabled.erase(id) == 0)
690
ADDON::OnEnabled(id);
597
694
bool CAddonMgr::IsAddonDisabled(const std::string& ID)
599
696
CSingleLock lock(m_critSection);
600
std::map<std::string, bool>::const_iterator it = m_disabled.find(ID);
601
if (it != m_disabled.end())
604
bool ret = m_database.IsAddonDisabled(ID);
605
m_disabled.insert(pair<std::string, bool>(ID, ret));
697
return m_disabled.find(ID) != m_disabled.end();
700
bool CAddonMgr::CanAddonBeDisabled(const std::string& ID)
705
CSingleLock lock(m_critSection);
707
// can't disable an addon that isn't installed
708
if (!GetAddon(ID, localAddon, ADDON_UNKNOWN, false))
711
// can't disable an addon that is in use
712
if (localAddon->IsInUse())
715
// installed PVR addons can always be disabled
716
if (localAddon->Type() == ADDON_PVRDLL)
719
// installed audio decoder addons can always be disabled
720
if (localAddon->Type() == ADDON_AUDIODECODER)
723
// installed audio encoder addons can always be disabled
724
if (localAddon->Type() == ADDON_AUDIOENCODER)
727
std::string systemAddonsPath = CSpecialProtocol::TranslatePath("special://xbmc/addons");
728
// can't disable system addons
729
if (StringUtils::StartsWith(localAddon->Path(), systemAddonsPath))
735
bool CAddonMgr::IsAddonInstalled(const std::string& ID)
738
return GetAddon(ID, tmp, ADDON_UNKNOWN, false);
741
bool CAddonMgr::CanAddonBeInstalled(const std::string& ID)
746
CSingleLock lock(m_critSection);
747
// can't install already installed addon
748
if (IsAddonInstalled(ID))
751
// can't install broken addons
752
if (!m_database.IsAddonBroken(ID).empty())
758
bool CAddonMgr::CanAddonBeInstalled(const AddonPtr& addon)
763
CSingleLock lock(m_critSection);
764
// can't install already installed addon
765
if (IsAddonInstalled(addon->ID()))
768
// can't install broken addons
769
if (!addon->Props().broken.empty())
610
775
std::string CAddonMgr::GetTranslatedString(const cp_cfg_element_t *root, const char *tag)
615
const cp_cfg_element_t *eng = NULL;
780
std::map<std::string, std::string> translatedValues;
616
781
for (unsigned int i = 0; i < root->num_children; i++)
618
783
const cp_cfg_element_t &child = root->children[i];
619
784
if (strcmp(tag, child.name) == 0)
620
{ // see if we have a "lang" attribute
786
// see if we have a "lang" attribute
621
787
const char *lang = m_cpluff->lookup_cfg_value((cp_cfg_element_t*)&child, "@lang");
622
if (lang && 0 == strcmp(lang,g_langInfo.GetLanguageLocale(true).c_str()))
623
return child.value ? child.value : "";
624
if (!lang || 0 == strcmp(lang, "en"))
788
if (lang != NULL && g_langInfo.GetLocale().Matches(lang))
789
translatedValues.insert(std::make_pair(lang, child.value != NULL ? child.value : ""));
790
else if (lang == NULL || strcmp(lang, "en") == 0 || strcmp(lang, "en_GB") == 0)
791
translatedValues.insert(std::make_pair("en_GB", child.value != NULL ? child.value : ""));
628
return (eng && eng->value) ? eng->value : "";
795
// put together a list of languages
796
std::set<std::string> languages;
797
for (auto const& translatedValue : translatedValues)
798
languages.insert(translatedValue.first);
800
// find the language from the list that matches the current locale best
801
std::string matchingLanguage = g_langInfo.GetLocale().FindBestMatch(languages);
802
if (matchingLanguage.empty())
803
matchingLanguage = "en_GB";
805
auto const& translatedValue = translatedValues.find(matchingLanguage);
806
if (translatedValue != translatedValues.end())
807
return translatedValue->second;
631
812
AddonPtr CAddonMgr::AddonFromProps(AddonProps& addonProps)
785
975
return AddonPtr(new CAddon(info));
788
// grab a relevant extension point, ignoring our xbmc.addon.metadata extension point
978
// grab a relevant extension point, ignoring our kodi.addon.metadata extension point
789
979
for (unsigned int i = 0; i < info->num_extensions; ++i)
791
if (0 != strcmp("xbmc.addon.metadata", info->extensions[i].ext_point_id) &&
981
if (0 != strcmp("xbmc.addon.metadata" , info->extensions[i].ext_point_id) && //<! backword compatibilty
982
0 != strcmp("kodi.addon.metadata" , info->extensions[i].ext_point_id) &&
792
983
(type.empty() || 0 == strcmp(type.c_str(), info->extensions[i].ext_point_id)))
793
984
{ // note that Factory takes care of whether or not we have platform support
794
985
return Factory(&info->extensions[i]);