2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
20 #include "AddonManager.h"
22 #include "DllLibCPluff.h"
23 #include "utils/StringUtils.h"
24 #include "utils/JobManager.h"
25 #include "threads/SingleLock.h"
28 #include "settings/AdvancedSettings.h"
29 #include "settings/Settings.h"
30 #include "utils/log.h"
31 #include "utils/XBMCTinyXML.h"
32 #ifdef HAS_VISUALISATION
33 #include "Visualisation.h"
35 #ifdef HAS_SCREENSAVER
36 #include "ScreenSaver.h"
39 #include "DllPVRClient.h"
40 #include "pvr/addons/PVRClient.h"
45 #include "PluginSource.h"
46 #include "Repository.h"
49 #include "pvr/PVRManager.h"
50 #include "pvr/addons/PVRClients.h"
59 cp_log_severity_t clog_to_cp(int lvl);
60 void cp_fatalErrorHandler(const char *msg);
61 void cp_logger(cp_log_severity_t level, const char *msg, const char *apid, void *user_data);
63 /**********************************************************
68 map<TYPE, IAddonMgrCallback*> CAddonMgr::m_managers;
70 AddonPtr CAddonMgr::Factory(const cp_extension_t *props)
72 if (!PlatformSupportsAddon(props->plugin))
75 /* Check if user directories need to be created */
76 const cp_cfg_element_t *settings = GetExtElement(props->configuration, "settings");
78 CheckUserDirs(settings);
80 const TYPE type = TranslateType(props->ext_point_id);
85 return AddonPtr(new CPluginSource(props));
86 case ADDON_SCRIPT_LIBRARY:
87 case ADDON_SCRIPT_LYRICS:
88 case ADDON_SCRIPT_MODULE:
89 case ADDON_SUBTITLE_MODULE:
90 case ADDON_WEB_INTERFACE:
91 return AddonPtr(new CAddon(props));
92 case ADDON_SCRIPT_WEATHER:
94 // Eden (API v2.0) broke old weather add-ons
95 AddonPtr result(new CAddon(props));
96 AddonVersion ver1 = AddonVersion(GetXbmcApiVersionDependency(result));
97 AddonVersion ver2 = AddonVersion("2.0");
100 CLog::Log(LOGINFO,"%s: Weather add-ons for api < 2.0 unsupported (%s)",__FUNCTION__,result->ID().c_str());
106 return AddonPtr(new CService(props));
107 case ADDON_SCRAPER_ALBUMS:
108 case ADDON_SCRAPER_ARTISTS:
109 case ADDON_SCRAPER_MOVIES:
110 case ADDON_SCRAPER_MUSICVIDEOS:
111 case ADDON_SCRAPER_TVSHOWS:
112 case ADDON_SCRAPER_LIBRARY:
113 return AddonPtr(new CScraper(props));
115 case ADDON_SCREENSAVER:
117 { // begin temporary platform handling for Dlls
118 // ideally platforms issues will be handled by C-Pluff
119 // this is not an attempt at a solution
121 if (type == ADDON_SCREENSAVER && 0 == strnicmp(props->plugin->identifier, "screensaver.xbmc.builtin.", 25))
122 { // built in screensaver
123 return AddonPtr(new CAddon(props));
125 if (type == ADDON_SCREENSAVER)
126 { // Python screensaver
127 CStdString library = CAddonMgr::Get().GetExtValue(props->configuration, "@library");
128 if (URIUtils::HasExtension(library, ".py"))
129 return AddonPtr(new CScreenSaver(props));
131 #if defined(TARGET_ANDROID)
132 if ((value = GetExtValue(props->plugin->extensions->configuration, "@library_android")) && value.empty())
134 #elif defined(TARGET_LINUX) || defined(TARGET_FREEBSD)
135 if ((value = GetExtValue(props->plugin->extensions->configuration, "@library_linux")) && value.empty())
137 #elif defined(TARGET_WINDOWS) && defined(HAS_SDL_OPENGL)
138 if ((value = GetExtValue(props->plugin->extensions->configuration, "@library_wingl")) && value.empty())
140 #elif defined(TARGET_WINDOWS) && defined(HAS_DX)
141 if ((value = GetExtValue(props->plugin->extensions->configuration, "@library_windx")) && value.empty())
143 #elif defined(TARGET_DARWIN)
144 if ((value = GetExtValue(props->plugin->extensions->configuration, "@library_osx")) && value.empty())
147 if (type == ADDON_VIZ)
149 #if defined(HAS_VISUALISATION)
150 return AddonPtr(new CVisualisation(props));
153 else if (type == ADDON_PVRDLL)
155 #ifdef HAS_PVRCLIENTS
156 return AddonPtr(new CPVRClient(props));
160 return AddonPtr(new CScreenSaver(props));
163 return AddonPtr(new CSkinInfo(props));
164 case ADDON_VIZ_LIBRARY:
165 return AddonPtr(new CAddonLibrary(props));
166 case ADDON_REPOSITORY:
167 return AddonPtr(new CRepository(props));
174 bool CAddonMgr::CheckUserDirs(const cp_cfg_element_t *settings)
179 const cp_cfg_element_t *userdirs = GetExtElement((cp_cfg_element_t *)settings, "userdirs");
184 if (!GetExtElements((cp_cfg_element_t *)userdirs, "userdir", elements))
187 ELEMENTS::iterator itr = elements.begin();
188 while (itr != elements.end())
190 CStdString path = GetExtValue(*itr++, "@path");
191 if (!CFile::Exists(path))
193 if (!CUtil::CreateDirectoryEx(path))
195 CLog::Log(LOGERROR, "CAddonMgr::CheckUserDirs: Unable to create directory %s.", path.c_str());
204 CAddonMgr::CAddonMgr()
209 CAddonMgr::~CAddonMgr()
214 CAddonMgr &CAddonMgr::Get()
216 static CAddonMgr sAddonMgr;
220 IAddonMgrCallback* CAddonMgr::GetCallbackForType(TYPE type)
222 if (m_managers.find(type) == m_managers.end())
225 return m_managers[type];
228 bool CAddonMgr::RegisterAddonMgrCallback(const TYPE type, IAddonMgrCallback* cb)
233 m_managers.erase(type);
234 m_managers[type] = cb;
239 void CAddonMgr::UnregisterAddonMgrCallback(TYPE type)
241 m_managers.erase(type);
244 bool CAddonMgr::Init()
246 m_cpluff = new DllLibCPluff;
251 if (!m_cpluff->IsLoaded())
253 CLog::Log(LOGERROR, "ADDONS: Fatal Error, could not load libcpluff");
257 m_cpluff->set_fatal_error_handler(cp_fatalErrorHandler);
260 status = m_cpluff->init();
263 CLog::Log(LOGERROR, "ADDONS: Fatal Error, cp_init() returned status: %i", status);
267 //TODO could separate addons into different contexts
268 // would allow partial unloading of addon framework
269 m_cp_context = m_cpluff->create_context(&status);
270 assert(m_cp_context);
271 status = m_cpluff->register_pcollection(m_cp_context, CSpecialProtocol::TranslatePath("special://home/addons"));
272 status = m_cpluff->register_pcollection(m_cp_context, CSpecialProtocol::TranslatePath("special://xbmc/addons"));
273 status = m_cpluff->register_pcollection(m_cp_context, CSpecialProtocol::TranslatePath("special://xbmcbin/addons"));
276 CLog::Log(LOGERROR, "ADDONS: Fatal Error, cp_register_pcollection() returned status: %i", status);
280 status = m_cpluff->register_logger(m_cp_context, cp_logger,
281 &CAddonMgr::Get(), clog_to_cp(g_advancedSettings.m_logLevel));
284 CLog::Log(LOGERROR, "ADDONS: Fatal Error, cp_register_logger() returned status: %i", status);
291 if (GetAddons(ADDON_REPOSITORY, repos))
293 VECADDONS::iterator it = repos.begin();
294 for (;it != repos.end(); ++it)
295 CLog::Log(LOGNOTICE, "ADDONS: Using repository %s", (*it)->ID().c_str());
301 void CAddonMgr::DeInit()
310 bool CAddonMgr::HasAddons(const TYPE &type, bool enabled /*= true*/)
312 // TODO: This isn't particularly efficient as we create an addon type for each addon using the Factory, just so
313 // we can check addon dependencies in the addon constructor.
315 return GetAddons(type, addons, enabled);
318 bool CAddonMgr::GetAllAddons(VECADDONS &addons, bool enabled /*= true*/, bool allowRepos /* = false */)
320 for (int i = ADDON_UNKNOWN+1; i < ADDON_VIZ_LIBRARY; ++i)
322 if (!allowRepos && ADDON_REPOSITORY == (TYPE)i)
325 if (CAddonMgr::Get().GetAddons((TYPE)i, temp, enabled))
326 addons.insert(addons.end(), temp.begin(), temp.end());
328 return !addons.empty();
331 void CAddonMgr::AddToUpdateableAddons(AddonPtr &pAddon)
333 CSingleLock lock(m_critSection);
334 m_updateableAddons.push_back(pAddon);
337 void CAddonMgr::RemoveFromUpdateableAddons(AddonPtr &pAddon)
339 CSingleLock lock(m_critSection);
340 VECADDONS::iterator it = std::find(m_updateableAddons.begin(), m_updateableAddons.end(), pAddon);
342 if(it != m_updateableAddons.end())
344 m_updateableAddons.erase(it);
350 AddonIdFinder(const CStdString& id)
354 bool operator()(const AddonPtr& addon)
356 return m_id.Equals(addon->ID());
362 bool CAddonMgr::ReloadSettings(const CStdString &id)
364 CSingleLock lock(m_critSection);
365 VECADDONS::iterator it = std::find_if(m_updateableAddons.begin(), m_updateableAddons.end(), AddonIdFinder(id));
367 if( it != m_updateableAddons.end())
369 return (*it)->ReloadSettings();
374 bool CAddonMgr::GetAllOutdatedAddons(VECADDONS &addons, bool getLocalVersion /*= false*/)
376 CSingleLock lock(m_critSection);
377 for (int i = ADDON_UNKNOWN+1; i < ADDON_VIZ_LIBRARY; ++i)
380 if (CAddonMgr::Get().GetAddons((TYPE)i, temp, true))
383 for (unsigned int j = 0; j < temp.size(); j++)
385 // Ignore duplicates due to add-ons with multiple extension points
387 for (VECADDONS::const_iterator addonIt = addons.begin(); addonIt != addons.end(); addonIt++)
389 if ((*addonIt)->ID() == temp[j]->ID())
393 if (found || !m_database.GetAddon(temp[j]->ID(), repoAddon))
396 if (temp[j]->Version() < repoAddon->Version() &&
397 !m_database.IsAddonBlacklisted(temp[j]->ID(),
398 repoAddon->Version().c_str()))
401 repoAddon->Props().version = temp[j]->Version();
402 addons.push_back(repoAddon);
407 return !addons.empty();
410 bool CAddonMgr::HasOutdatedAddons()
413 return GetAllOutdatedAddons(dummy);
416 bool CAddonMgr::GetAddons(const TYPE &type, VECADDONS &addons, bool enabled /* = true */)
418 CSingleLock lock(m_critSection);
422 CStdString ext_point(TranslateType(type));
423 cp_extension_t **exts = m_cpluff->get_extensions_info(m_cp_context, ext_point.c_str(), &status, &num);
424 for(int i=0; i <num; i++)
426 const cp_extension_t *props = exts[i];
427 if (IsAddonDisabled(props->plugin->identifier) != enabled)
429 // get a pointer to a running pvrclient if it's already started, or we won't be able to change settings
430 if (TranslateType(props->ext_point_id) == ADDON_PVRDLL &&
432 g_PVRManager.IsStarted())
435 if (g_PVRClients->GetClient(props->plugin->identifier, pvrAddon))
437 addons.push_back(pvrAddon);
442 AddonPtr addon(Factory(props));
444 addons.push_back(addon);
447 m_cpluff->release_info(m_cp_context, exts);
448 return addons.size() > 0;
451 bool CAddonMgr::GetAddon(const CStdString &str, AddonPtr &addon, const TYPE &type/*=ADDON_UNKNOWN*/, bool enabledOnly /*= true*/)
453 CSingleLock lock(m_critSection);
456 cp_plugin_info_t *cpaddon = m_cpluff->get_plugin_info(m_cp_context, str.c_str(), &status);
457 if (status == CP_OK && cpaddon)
459 addon = GetAddonFromDescriptor(cpaddon, type==ADDON_UNKNOWN?"":TranslateType(type));
460 m_cpluff->release_info(m_cp_context, cpaddon);
462 if (addon && addon.get())
464 if (enabledOnly && IsAddonDisabled(addon->ID()))
467 if (addon->Type() == ADDON_PVRDLL && g_PVRManager.IsStarted())
470 if (g_PVRClients->GetClient(addon->ID(), pvrAddon))
474 return NULL != addon.get();
477 m_cpluff->release_info(m_cp_context, cpaddon);
482 //TODO handle all 'default' cases here, not just scrapers & vizs
483 bool CAddonMgr::GetDefault(const TYPE &type, AddonPtr &addon)
489 setting = CSettings::Get().GetString("musicplayer.visualisation");
491 case ADDON_SCREENSAVER:
492 setting = CSettings::Get().GetString("screensaver.mode");
494 case ADDON_SCRAPER_ALBUMS:
495 setting = CSettings::Get().GetString("musiclibrary.albumsscraper");
497 case ADDON_SCRAPER_ARTISTS:
498 setting = CSettings::Get().GetString("musiclibrary.artistsscraper");
500 case ADDON_SCRAPER_MOVIES:
501 setting = CSettings::Get().GetString("scrapers.moviesdefault");
503 case ADDON_SCRAPER_MUSICVIDEOS:
504 setting = CSettings::Get().GetString("scrapers.musicvideosdefault");
506 case ADDON_SCRAPER_TVSHOWS:
507 setting = CSettings::Get().GetString("scrapers.tvshowsdefault");
509 case ADDON_WEB_INTERFACE:
510 setting = CSettings::Get().GetString("services.webskin");
515 return GetAddon(setting, addon, type);
518 bool CAddonMgr::SetDefault(const TYPE &type, const CStdString &addonID)
523 CSettings::Get().SetString("musicplayer.visualisation",addonID);
525 case ADDON_SCREENSAVER:
526 CSettings::Get().SetString("screensaver.mode",addonID);
528 case ADDON_SCRAPER_ALBUMS:
529 CSettings::Get().SetString("musiclibrary.albumsscraper",addonID);
531 case ADDON_SCRAPER_ARTISTS:
532 CSettings::Get().SetString("musiclibrary.artistsscraper",addonID);
534 case ADDON_SCRAPER_MOVIES:
535 CSettings::Get().SetString("scrapers.moviesdefault",addonID);
537 case ADDON_SCRAPER_MUSICVIDEOS:
538 CSettings::Get().SetString("scrapers.musicvideosdefault",addonID);
540 case ADDON_SCRAPER_TVSHOWS:
541 CSettings::Get().SetString("scrapers.tvshowsdefault",addonID);
550 CStdString CAddonMgr::GetString(const CStdString &id, const int number)
553 if (GetAddon(id, addon))
554 return addon->GetString(number);
559 void CAddonMgr::FindAddons()
562 CSingleLock lock(m_critSection);
563 if (m_cpluff && m_cp_context)
565 m_cpluff->scan_plugins(m_cp_context, CP_SP_UPGRADE);
569 NotifyObservers(ObservableMessageAddons);
572 void CAddonMgr::RemoveAddon(const CStdString& ID)
574 if (m_cpluff && m_cp_context)
576 m_cpluff->uninstall_plugin(m_cp_context,ID.c_str());
578 NotifyObservers(ObservableMessageAddons);
582 bool CAddonMgr::DisableAddon(const std::string& ID, bool disable)
584 CSingleLock lock(m_critSection);
585 if (m_database.DisableAddon(ID, disable))
587 m_disabled[ID] = disable;
594 bool CAddonMgr::IsAddonDisabled(const std::string& ID)
596 CSingleLock lock(m_critSection);
597 std::map<std::string, bool>::const_iterator it = m_disabled.find(ID);
598 if (it != m_disabled.end())
601 bool ret = m_database.IsAddonDisabled(ID);
602 m_disabled.insert(pair<std::string, bool>(ID, ret));
607 const char *CAddonMgr::GetTranslatedString(const cp_cfg_element_t *root, const char *tag)
612 const cp_cfg_element_t *eng = NULL;
613 for (unsigned int i = 0; i < root->num_children; i++)
615 const cp_cfg_element_t &child = root->children[i];
616 if (strcmp(tag, child.name) == 0)
617 { // see if we have a "lang" attribute
618 const char *lang = m_cpluff->lookup_cfg_value((cp_cfg_element_t*)&child, "@lang");
619 if (lang && 0 == strcmp(lang,g_langInfo.GetLanguageLocale(true).c_str()))
621 if (!lang || 0 == strcmp(lang, "en"))
625 return (eng) ? eng->value : NULL;
628 AddonPtr CAddonMgr::AddonFromProps(AddonProps& addonProps)
630 switch (addonProps.type)
634 return AddonPtr(new CPluginSource(addonProps));
635 case ADDON_SCRIPT_LIBRARY:
636 case ADDON_SCRIPT_LYRICS:
637 case ADDON_SCRIPT_WEATHER:
638 case ADDON_SCRIPT_MODULE:
639 case ADDON_SUBTITLE_MODULE:
640 case ADDON_WEB_INTERFACE:
641 return AddonPtr(new CAddon(addonProps));
643 return AddonPtr(new CService(addonProps));
644 case ADDON_SCRAPER_ALBUMS:
645 case ADDON_SCRAPER_ARTISTS:
646 case ADDON_SCRAPER_MOVIES:
647 case ADDON_SCRAPER_MUSICVIDEOS:
648 case ADDON_SCRAPER_TVSHOWS:
649 case ADDON_SCRAPER_LIBRARY:
650 return AddonPtr(new CScraper(addonProps));
652 return AddonPtr(new CSkinInfo(addonProps));
653 #if defined(HAS_VISUALISATION)
655 return AddonPtr(new CVisualisation(addonProps));
657 case ADDON_SCREENSAVER:
658 return AddonPtr(new CScreenSaver(addonProps));
659 case ADDON_VIZ_LIBRARY:
660 return AddonPtr(new CAddonLibrary(addonProps));
662 return AddonPtr(new CPVRClient(addonProps));
663 case ADDON_REPOSITORY:
664 return AddonPtr(new CRepository(addonProps));
672 * libcpluff interaction
675 bool CAddonMgr::PlatformSupportsAddon(const cp_plugin_info_t *plugin) const
677 if (!plugin || !plugin->num_extensions)
679 const cp_extension_t *metadata = GetExtension(plugin, "xbmc.addon.metadata");
683 vector<CStdString> platforms;
684 if (CAddonMgr::Get().GetExtList(metadata->configuration, "platform", platforms))
686 for (unsigned int i = 0; i < platforms.size(); ++i)
688 if (platforms[i] == "all")
690 #if defined(TARGET_ANDROID)
691 if (platforms[i] == "android")
692 #elif defined(TARGET_LINUX) || defined(TARGET_FREEBSD)
693 if (platforms[i] == "linux")
694 #elif defined(TARGET_WINDOWS) && defined(HAS_SDL_OPENGL)
695 if (platforms[i] == "wingl")
696 #elif defined(TARGET_WINDOWS) && defined(HAS_DX)
697 if (platforms[i] == "windx")
698 #elif defined(TARGET_DARWIN_OSX)
699 // Remove this after Frodo and add an architecture filter
700 // in addition to platform.
701 #if defined(__x86_64__)
702 if (platforms[i] == "osx64" || platforms[i] == "osx")
704 if (platforms[i] == "osx32" || platforms[i] == "osx")
706 #elif defined(TARGET_DARWIN_IOS)
707 if (platforms[i] == "ios")
711 return false; // no <platform> works for us
713 return true; // assume no <platform> is equivalent to <platform>all</platform>
716 const cp_cfg_element_t *CAddonMgr::GetExtElement(cp_cfg_element_t *base, const char *path)
718 const cp_cfg_element_t *element = NULL;
720 element = m_cpluff->lookup_cfg_element(base, path);
724 bool CAddonMgr::GetExtElements(cp_cfg_element_t *base, const char *path, ELEMENTS &elements)
729 for (unsigned int i = 0; i < base->num_children; i++)
731 CStdString temp = base->children[i].name;
732 if (!temp.compare(path))
733 elements.push_back(&base->children[i]);
736 return !elements.empty();
739 const cp_extension_t *CAddonMgr::GetExtension(const cp_plugin_info_t *props, const char *extension) const
743 for (unsigned int i = 0; i < props->num_extensions; ++i)
745 if (0 == strcmp(props->extensions[i].ext_point_id, extension))
746 return &props->extensions[i];
751 CStdString CAddonMgr::GetExtValue(cp_cfg_element_t *base, const char *path)
753 const char *value = NULL;
754 if (base && (value = m_cpluff->lookup_cfg_value(base, path)))
755 return CStdString(value);
756 else return CStdString();
759 bool CAddonMgr::GetExtList(cp_cfg_element_t *base, const char *path, vector<CStdString> &result) const
763 CStdString all = m_cpluff->lookup_cfg_value(base, path);
766 StringUtils::SplitString(all, " ", result);
770 AddonPtr CAddonMgr::GetAddonFromDescriptor(const cp_plugin_info_t *info,
771 const CStdString& type)
776 if (!info->extensions)
777 { // no extensions, so we need only the dep information
778 return AddonPtr(new CAddon(info));
781 // FIXME: If we want to support multiple extension points per addon, we'll need to extend this to not just take
782 // the first extension point (eg use the TYPE information we pass in)
784 // grab a relevant extension point, ignoring our xbmc.addon.metadata extension point
785 for (unsigned int i = 0; i < info->num_extensions; ++i)
787 if (0 != strcmp("xbmc.addon.metadata", info->extensions[i].ext_point_id) &&
788 (type.empty() || 0 == strcmp(type.c_str(), info->extensions[i].ext_point_id)))
789 { // note that Factory takes care of whether or not we have platform support
790 return Factory(&info->extensions[i]);
796 // FIXME: This function may not be required
797 bool CAddonMgr::LoadAddonDescription(const CStdString &path, AddonPtr &addon)
800 cp_plugin_info_t *info = m_cpluff->load_plugin_descriptor(m_cp_context, CSpecialProtocol::TranslatePath(path).c_str(), &status);
803 addon = GetAddonFromDescriptor(info);
804 m_cpluff->release_info(m_cp_context, info);
805 return NULL != addon.get();
810 bool CAddonMgr::AddonsFromRepoXML(const TiXmlElement *root, VECADDONS &addons)
812 // create a context for these addons
814 cp_context_t *context = m_cpluff->create_context(&status);
815 if (!root || !context)
818 // each addon XML should have a UTF-8 declaration
819 TiXmlDeclaration decl("1.0", "UTF-8", "");
820 const TiXmlElement *element = root->FirstChildElement("addon");
823 // dump the XML back to text
828 cp_plugin_info_t *info = m_cpluff->load_plugin_descriptor_from_memory(context, xml.c_str(), xml.size(), &status);
831 AddonPtr addon = GetAddonFromDescriptor(info);
833 addons.push_back(addon);
834 m_cpluff->release_info(context, info);
836 element = element->NextSiblingElement("addon");
838 m_cpluff->destroy_context(context);
842 bool CAddonMgr::LoadAddonDescriptionFromMemory(const TiXmlElement *root, AddonPtr &addon)
844 // create a context for these addons
846 cp_context_t *context = m_cpluff->create_context(&status);
847 if (!root || !context)
850 // dump the XML back to text
852 xml << TiXmlDeclaration("1.0", "UTF-8", "");
854 cp_plugin_info_t *info = m_cpluff->load_plugin_descriptor_from_memory(context, xml.c_str(), xml.size(), &status);
857 addon = GetAddonFromDescriptor(info);
858 m_cpluff->release_info(context, info);
860 m_cpluff->destroy_context(context);
861 return addon != NULL;
864 bool CAddonMgr::StartServices(const bool beforelogin)
866 CLog::Log(LOGDEBUG, "ADDON: Starting service addons.");
869 if (!GetAddons(ADDON_SERVICE, services))
873 for (IVECADDONS it = services.begin(); it != services.end(); ++it)
875 boost::shared_ptr<CService> service = boost::dynamic_pointer_cast<CService>(*it);
878 if ( (beforelogin && service->GetStartOption() == CService::STARTUP)
879 || (!beforelogin && service->GetStartOption() == CService::LOGIN) )
880 ret &= service->Start();
887 void CAddonMgr::StopServices(const bool onlylogin)
889 CLog::Log(LOGDEBUG, "ADDON: Stopping service addons.");
892 if (!GetAddons(ADDON_SERVICE, services))
895 for (IVECADDONS it = services.begin(); it != services.end(); ++it)
897 boost::shared_ptr<CService> service = boost::dynamic_pointer_cast<CService>(*it);
900 if ( (onlylogin && service->GetStartOption() == CService::LOGIN)
907 int cp_to_clog(cp_log_severity_t lvl)
909 if (lvl >= CP_LOG_ERROR)
914 cp_log_severity_t clog_to_cp(int lvl)
916 if (lvl >= LOG_LEVEL_DEBUG)
921 void cp_fatalErrorHandler(const char *msg)
923 CLog::Log(LOGERROR, "ADDONS: CPluffFatalError(%s)", msg);
926 void cp_logger(cp_log_severity_t level, const char *msg, const char *apid, void *user_data)
929 CLog::Log(cp_to_clog(level), "ADDON: cpluff: '%s'", msg);
931 CLog::Log(cp_to_clog(level), "ADDON: cpluff: '%s' reports '%s'", apid, msg);
934 } /* namespace ADDON */