Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 1105 lines (992 sloc) 31.751 kb
074db86 merged: addons-fw branch
elupus authored
1 /*
2 * Copyright (C) 2005-2009 Team XBMC
3 * http://www.xbmc.org
4 *
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)
8 * any later version.
9 *
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.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
19 *
20 */
21 #include "AddonManager.h"
22 #include "Addon.h"
639b314 changed: move addonbrowser to a mediawindow derivate
spiff_ authored
23 #include "AddonDatabase.h"
1b2781c added: basic cpluff support
alcoheca authored
24 #include "DllLibCPluff.h"
074db86 merged: addons-fw branch
elupus authored
25 #include "StringUtils.h"
26 #include "RegExp.h"
27 #include "XMLUtils.h"
639b314 changed: move addonbrowser to a mediawindow derivate
spiff_ authored
28 #include "utils/JobManager.h"
29 #include "utils/SingleLock.h"
074db86 merged: addons-fw branch
elupus authored
30 #include "FileItem.h"
822ca91 added: translatable <description>, <title>, <summary> and <disclaimer…
spiff_ authored
31 #include "LangInfo.h"
074db86 merged: addons-fw branch
elupus authored
32 #include "Settings.h"
33 #include "GUISettings.h"
34 #include "DownloadQueueManager.h"
1b2781c added: basic cpluff support
alcoheca authored
35 #include "AdvancedSettings.h"
dacdca0 changed: moved CAddonStatusHandler to separate files
alcoheca authored
36 #include "log.h"
074db86 merged: addons-fw branch
elupus authored
37
38 #ifdef HAS_VISUALISATION
055f806 cosmetic/tidyup move all addon classes to /xbmc/addons/
alcoheca authored
39 #include "DllVisualisation.h"
40 #include "Visualisation.h"
074db86 merged: addons-fw branch
elupus authored
41 #endif
42 #ifdef HAS_SCREENSAVER
055f806 cosmetic/tidyup move all addon classes to /xbmc/addons/
alcoheca authored
43 #include "DllScreenSaver.h"
44 #include "ScreenSaver.h"
074db86 merged: addons-fw branch
elupus authored
45 #endif
46 //#ifdef HAS_SCRAPERS
055f806 cosmetic/tidyup move all addon classes to /xbmc/addons/
alcoheca authored
47 #include "Scraper.h"
074db86 merged: addons-fw branch
elupus authored
48 //#endif
606248f added: addon repository class
spiff_ authored
49 #include "Repository.h"
553d213 changed: finished moving skins to addon framework
alcoheca authored
50 #include "Skin.h"
af8cb2a Revert "wip"
alcoheca authored
51
88e9b6f changed: expand std namespace
spiff_ authored
52 using namespace std;
53
074db86 merged: addons-fw branch
elupus authored
54 namespace ADDON
55 {
56
b6f0f59 cleanup: Don't expose the AddonManager's privates when not required.
jmarshallnz authored
57 cp_log_severity_t clog_to_cp(int lvl);
58 void cp_fatalErrorHandler(const char *msg);
59 void cp_logger(cp_log_severity_t level, const char *msg, const char *apid, void *user_data);
074db86 merged: addons-fw branch
elupus authored
60
61 /**********************************************************
62 * CAddonMgr
63 *
64 */
65
88e9b6f changed: expand std namespace
spiff_ authored
66 map<TYPE, IAddonMgrCallback*> CAddonMgr::m_managers;
074db86 merged: addons-fw branch
elupus authored
67
c14bf20 changed: moved addonptr factory to CAddonMgr.
alcoheca authored
68 AddonPtr CAddonMgr::Factory(const cp_extension_t *props)
1b2781c added: basic cpluff support
alcoheca authored
69 {
bb4e01c Support creating userdirs in addons. This also has the benefit of bei…
ceros7 authored
70 /* Check if user directories need to be created */
71 const cp_cfg_element_t *settings = GetExtElement(props->plugin->extensions->configuration, "settings");
72 if (settings)
73 CheckUserDirs(settings);
74
1b2781c added: basic cpluff support
alcoheca authored
75 const TYPE type = TranslateType(props->ext_point_id);
76 switch (type)
77 {
78 case ADDON_PLUGIN:
79 case ADDON_SCRIPT:
80 return AddonPtr(new CAddon(props->plugin));
81 case ADDON_SCRAPER:
82 return AddonPtr(new CScraper(props->plugin));
83 case ADDON_VIZ:
84 case ADDON_SCREENSAVER:
c14bf20 changed: moved addonptr factory to CAddonMgr.
alcoheca authored
85 { // begin temporary platform handling for Dlls
86 // ideally platforms issues will be handled by C-Pluff
87 // this is not an attempt at a solution
88 CStdString value;
89 #if defined(_LINUX) && !defined(__APPLE__)
90 if ((value = GetExtValue(props->plugin->extensions->configuration, "@library_linux")) && value.empty())
91 break;
92 #elif defined(_WIN32) && defined(HAS_SDL_OPENGL)
93 if ((value = GetExtValue(props->plugin->extensions->configuration, "@library_wingl")) && value.empty())
94 break;
95 #elif defined(_WIN32) && defined(HAS_DX)
96 if ((value = GetExtValue(props->plugin->extensions->configuration, "@library_windx")) && value.empty())
97 break;
98 #elif defined(__APPLE__)
99 if ((value = GetExtValue(props->plugin->extensions->configuration, "@library_osx")) && value.empty())
100 break;
101 #elif defined(_XBOX)
102 if ((value = GetExtValue(props->plugin->extensions->configuration, "@library_xbox")) && value.empty())
103 break;
104 #endif
105 if (type == ADDON_VIZ)
07e5742 [arm] merge arm-camelot into trunk, thanks to mcgeagh for all his har…
davilla authored
106 {
107 #if defined(HAS_VISUALISATION)
c14bf20 changed: moved addonptr factory to CAddonMgr.
alcoheca authored
108 return AddonPtr(new CVisualisation(props->plugin));
07e5742 [arm] merge arm-camelot into trunk, thanks to mcgeagh for all his har…
davilla authored
109 #endif
110 }
c14bf20 changed: moved addonptr factory to CAddonMgr.
alcoheca authored
111 else
112 return AddonPtr(new CScreenSaver(props->plugin));
113 }
5ff028a added: skin support via cpluff
alcoheca authored
114 case ADDON_SKIN:
115 return AddonPtr(new CSkinInfo(props->plugin));
1b2781c added: basic cpluff support
alcoheca authored
116 case ADDON_SCRAPER_LIBRARY:
d289db4 fixed: script libraries weren't created in CAddonMgr::Factory
jmarshallnz authored
117 case ADDON_SCRIPT_LIBRARY:
1b2781c added: basic cpluff support
alcoheca authored
118 case ADDON_VIZ_LIBRARY:
119 return AddonPtr(new CAddonLibrary(props->plugin));
9ea9065 changed: Move repositories to cpluff
jmarshallnz authored
120 case ADDON_REPOSITORY:
121 return AddonPtr(new CRepository(props->plugin));
1b2781c added: basic cpluff support
alcoheca authored
122 default:
c14bf20 changed: moved addonptr factory to CAddonMgr.
alcoheca authored
123 break;
1b2781c added: basic cpluff support
alcoheca authored
124 }
c14bf20 changed: moved addonptr factory to CAddonMgr.
alcoheca authored
125 return AddonPtr();
1b2781c added: basic cpluff support
alcoheca authored
126 }
127
bb4e01c Support creating userdirs in addons. This also has the benefit of bei…
ceros7 authored
128 bool CAddonMgr::CheckUserDirs(const cp_cfg_element_t *settings)
129 {
130 if (!settings)
131 return false;
132
133 const cp_cfg_element_t *userdirs = GetExtElement((cp_cfg_element_t *)settings, "userdirs");
134 if (!userdirs)
135 return false;
136
137 DEQUEELEMENTS elements;
138 bool status = GetExtElementDeque(elements, (cp_cfg_element_t *)userdirs, "userdir");
139 if (!status)
140 return false;
141
142 IDEQUEELEMENTS itr = elements.begin();
143 while (itr != elements.end())
144 {
145 CStdString path = GetExtValue(*itr++, "@path");
146 if (!CFile::Exists(path))
147 {
148 if (!CUtil::CreateDirectoryEx(path))
149 {
150 CLog::Log(LOGERROR, "CAddonMgr::CheckUserDirs: Unable to create directory %s.", path.c_str());
151 return false;
152 }
153 }
154 }
155
156 return true;
157 }
158
074db86 merged: addons-fw branch
elupus authored
159 CAddonMgr::CAddonMgr()
160 {
639b314 changed: move addonbrowser to a mediawindow derivate
spiff_ authored
161 FindAddons();
162 m_watch.StartZero();
074db86 merged: addons-fw branch
elupus authored
163 }
164
165 CAddonMgr::~CAddonMgr()
166 {
37a994e added: Deinit to the addons manager to ensure we unload cpluff prior …
jmarshallnz authored
167 DeInit();
074db86 merged: addons-fw branch
elupus authored
168 }
169
47a8196 changed: matched other singelton calls
alcoheca authored
170 CAddonMgr &CAddonMgr::Get()
074db86 merged: addons-fw branch
elupus authored
171 {
47a8196 changed: matched other singelton calls
alcoheca authored
172 static CAddonMgr sAddonMgr;
173 return sAddonMgr;
074db86 merged: addons-fw branch
elupus authored
174 }
175
176 IAddonMgrCallback* CAddonMgr::GetCallbackForType(TYPE type)
177 {
178 if (m_managers.find(type) == m_managers.end())
179 return NULL;
180 else
181 return m_managers[type];
182 }
183
184 bool CAddonMgr::RegisterAddonMgrCallback(const TYPE type, IAddonMgrCallback* cb)
185 {
186 if (cb == NULL)
187 return false;
188
189 m_managers.erase(type);
190 m_managers[type] = cb;
191
192 return true;
193 }
194
195 void CAddonMgr::UnregisterAddonMgrCallback(TYPE type)
196 {
197 m_managers.erase(type);
198 }
199
1b2781c added: basic cpluff support
alcoheca authored
200 bool CAddonMgr::Init()
201 {
202 m_cpluff = new DllLibCPluff;
203 m_cpluff->Load();
204
205 if (!m_cpluff->IsLoaded())
206 {
b6076e5 changed: screensavers are now supported via cpluff schema
alcoheca authored
207 CLog::Log(LOGERROR, "ADDONS: Fatal Error, could not load libcpluff");
208 return false;
1b2781c added: basic cpluff support
alcoheca authored
209 }
210
211 m_cpluff->set_fatal_error_handler(cp_fatalErrorHandler);
212
213 cp_status_t status;
214 status = m_cpluff->init();
215 if (status != CP_OK)
216 {
217 CLog::Log(LOGERROR, "ADDONS: Fatal Error, cp_init() returned status: %i", status);
b6076e5 changed: screensavers are now supported via cpluff schema
alcoheca authored
218 return false;
1b2781c added: basic cpluff support
alcoheca authored
219 }
220
221 //TODO could separate addons into different contexts
222 // would allow partial unloading of addon framework
223 m_cp_context = m_cpluff->create_context(&status);
224 assert(m_cp_context);
225 if (!CSpecialProtocol::XBMCIsHome())
226 {
b6076e5 changed: screensavers are now supported via cpluff schema
alcoheca authored
227 status = m_cpluff->register_pcollection(m_cp_context, _P("special://home/addons"));
228 }
229 status = m_cpluff->register_pcollection(m_cp_context, _P("special://xbmc/addons"));
230 if (status != CP_OK)
231 {
232 CLog::Log(LOGERROR, "ADDONS: Fatal Error, cp_register_pcollection() returned status: %i", status);
233 return false;
1b2781c added: basic cpluff support
alcoheca authored
234 }
b6076e5 changed: screensavers are now supported via cpluff schema
alcoheca authored
235
185686a added: even more missing from r29798
alcoheca authored
236 status = m_cpluff->register_logger(m_cp_context, cp_logger,
7188808 changed: bail out immeditaly if CAddonMgr::Init returns false
alcoheca authored
237 &CAddonMgr::Get(), clog_to_cp(g_advancedSettings.m_logLevel));
b6076e5 changed: screensavers are now supported via cpluff schema
alcoheca authored
238 if (status != CP_OK)
239 {
240 CLog::Log(LOGERROR, "ADDONS: Fatal Error, cp_register_logger() returned status: %i", status);
241 return false;
242 }
1b2781c added: basic cpluff support
alcoheca authored
243
b6076e5 changed: screensavers are now supported via cpluff schema
alcoheca authored
244 status = m_cpluff->scan_plugins(m_cp_context, 0);
245 return true;
1b2781c added: basic cpluff support
alcoheca authored
246 }
247
37a994e added: Deinit to the addons manager to ensure we unload cpluff prior …
jmarshallnz authored
248 void CAddonMgr::DeInit()
249 {
250 if (m_cpluff)
251 m_cpluff->destroy();
252 m_cpluff = NULL;
253 }
254
cc3b982 fixed: don't crash if an (visualization) addon is disabled
elupus authored
255 bool CAddonMgr::HasAddons(const TYPE &type, const CONTENT_TYPE &content/*= CONTENT_NONE*/, bool enabledOnly/*= true*/)
074db86 merged: addons-fw branch
elupus authored
256 {
2c2e61e changed: initial move of scrapers to cpluff. since deps aren't handle…
spiff_ authored
257 if (type == ADDON_SCREENSAVER || type == ADDON_SKIN || type == ADDON_VIZ || type == ADDON_SCRIPT || type == ADDON_REPOSITORY || type == ADDON_SCRAPER)
b6076e5 changed: screensavers are now supported via cpluff schema
alcoheca authored
258 {
259 cp_status_t status;
260 int num;
261 CStdString ext_point(TranslateType(type));
2ff4a7d fixed: didn't release all ref counted objects returned from cpluff
alcoheca authored
262 cp_extension_t **exts = m_cpluff->get_extensions_info(m_cp_context, ext_point.c_str(), &status, &num);
263 m_cpluff->release_info(m_cp_context, exts);
b6076e5 changed: screensavers are now supported via cpluff schema
alcoheca authored
264 if (status == CP_OK)
265 return (num > 0);
266 }
267
af8cb2a Revert "wip"
alcoheca authored
268 if (m_addons.empty())
269 {
270 VECADDONS add;
271 GetAllAddons(add,false);
272 }
273
274 if (content == CONTENT_NONE)
275 return (m_addons.find(type) != m_addons.end());
074db86 merged: addons-fw branch
elupus authored
276
277 VECADDONS addons;
cc3b982 fixed: don't crash if an (visualization) addon is disabled
elupus authored
278 return GetAddons(type, addons, content, enabledOnly);
b6076e5 changed: screensavers are now supported via cpluff schema
alcoheca authored
279
074db86 merged: addons-fw branch
elupus authored
280 }
281
282 bool CAddonMgr::GetAllAddons(VECADDONS &addons, bool enabledOnly/*= true*/)
283 {
af8cb2a Revert "wip"
alcoheca authored
284 VECADDONS temp;
7188808 changed: bail out immeditaly if CAddonMgr::Init returns false
alcoheca authored
285 if (CAddonMgr::Get().GetAddons(ADDON_PLUGIN, temp, CONTENT_NONE, enabledOnly))
af8cb2a Revert "wip"
alcoheca authored
286 addons.insert(addons.end(), temp.begin(), temp.end());
7188808 changed: bail out immeditaly if CAddonMgr::Init returns false
alcoheca authored
287 if (CAddonMgr::Get().GetAddons(ADDON_SCRAPER, temp, CONTENT_NONE, enabledOnly))
af8cb2a Revert "wip"
alcoheca authored
288 addons.insert(addons.end(), temp.begin(), temp.end());
7188808 changed: bail out immeditaly if CAddonMgr::Init returns false
alcoheca authored
289 if (CAddonMgr::Get().GetAddons(ADDON_SCREENSAVER, temp, CONTENT_NONE, enabledOnly))
af8cb2a Revert "wip"
alcoheca authored
290 addons.insert(addons.end(), temp.begin(), temp.end());
7188808 changed: bail out immeditaly if CAddonMgr::Init returns false
alcoheca authored
291 if (CAddonMgr::Get().GetAddons(ADDON_SCRIPT, temp, CONTENT_NONE, enabledOnly))
af8cb2a Revert "wip"
alcoheca authored
292 addons.insert(addons.end(), temp.begin(), temp.end());
7188808 changed: bail out immeditaly if CAddonMgr::Init returns false
alcoheca authored
293 if (CAddonMgr::Get().GetAddons(ADDON_SKIN, temp, CONTENT_NONE, enabledOnly))
553d213 changed: finished moving skins to addon framework
alcoheca authored
294 addons.insert(addons.end(), temp.begin(), temp.end());
7188808 changed: bail out immeditaly if CAddonMgr::Init returns false
alcoheca authored
295 if (CAddonMgr::Get().GetAddons(ADDON_VIZ, temp, CONTENT_NONE, enabledOnly))
af8cb2a Revert "wip"
alcoheca authored
296 addons.insert(addons.end(), temp.begin(), temp.end());
297 return !addons.empty();
074db86 merged: addons-fw branch
elupus authored
298 }
299
300 bool CAddonMgr::GetAddons(const TYPE &type, VECADDONS &addons, const CONTENT_TYPE &content/*= CONTENT_NONE*/, bool enabledOnly/*= true*/)
301 {
4e5b98a added: locks to addon manager
spiff_ authored
302 CSingleLock lock(m_critSection);
af8cb2a Revert "wip"
alcoheca authored
303 addons.clear();
2c2e61e changed: initial move of scrapers to cpluff. since deps aren't handle…
spiff_ authored
304 if (type == ADDON_SCREENSAVER || type == ADDON_SKIN || type == ADDON_VIZ || type == ADDON_REPOSITORY || type == ADDON_SCRIPT || type == ADDON_SCRAPER)
b6076e5 changed: screensavers are now supported via cpluff schema
alcoheca authored
305 {
306 cp_status_t status;
307 int num;
308 CStdString ext_point(TranslateType(type));
309 cp_extension_t **exts = m_cpluff->get_extensions_info(m_cp_context, ext_point.c_str(), &status, &num);
310 for(int i=0; i <num; i++)
311 {
c14bf20 changed: moved addonptr factory to CAddonMgr.
alcoheca authored
312 AddonPtr addon(Factory(exts[i]));
2c2e61e changed: initial move of scrapers to cpluff. since deps aren't handle…
spiff_ authored
313 if (addon && (content == CONTENT_NONE || addon->Supports(content)))
b6076e5 changed: screensavers are now supported via cpluff schema
alcoheca authored
314 addons.push_back(addon);
315 }
316 m_cpluff->release_info(m_cp_context, exts);
6933a8d fixed: compile warning
jmarshallnz authored
317 return addons.size() > 0;
b6076e5 changed: screensavers are now supported via cpluff schema
alcoheca authored
318 }
319
af8cb2a Revert "wip"
alcoheca authored
320 if (m_addons.find(type) != m_addons.end())
321 {
322 IVECADDONS itr = m_addons[type].begin();
323 while (itr != m_addons[type].end())
324 { // filter out what we're not looking for
dea84cb changed: Disabled() -> Enabled() - more intuitive
spiff_ authored
325 if ((enabledOnly && !(*itr)->Enabled())
af8cb2a Revert "wip"
alcoheca authored
326 || (content != CONTENT_NONE && !(*itr)->Supports(content)))
327 {
328 ++itr;
329 continue;
330 }
331 addons.push_back(*itr);
332 ++itr;
333 }
334 }
335 return !addons.empty();
074db86 merged: addons-fw branch
elupus authored
336 }
337
cc3b982 fixed: don't crash if an (visualization) addon is disabled
elupus authored
338 bool CAddonMgr::GetAddon(const CStdString &str, AddonPtr &addon, const TYPE &type/*=ADDON_UNKNOWN*/, bool enabledOnly/*= true*/)
074db86 merged: addons-fw branch
elupus authored
339 {
4e5b98a added: locks to addon manager
spiff_ authored
340 CSingleLock lock(m_critSection);
b6076e5 changed: screensavers are now supported via cpluff schema
alcoheca authored
341 if (type != ADDON_UNKNOWN
342 && type != ADDON_SCREENSAVER
5ff028a added: skin support via cpluff
alcoheca authored
343 && type != ADDON_SKIN
f14b201 changed: support visualizations via cpluff
alcoheca authored
344 && type != ADDON_VIZ
9ea9065 changed: Move repositories to cpluff
jmarshallnz authored
345 && type != ADDON_REPOSITORY
79ac8ab changed: Move scripts to cpluff
jmarshallnz authored
346 && type != ADDON_SCRIPT
2c2e61e changed: initial move of scrapers to cpluff. since deps aren't handle…
spiff_ authored
347 && type != ADDON_SCRAPER
b6076e5 changed: screensavers are now supported via cpluff schema
alcoheca authored
348 && m_addons.find(type) == m_addons.end())
074db86 merged: addons-fw branch
elupus authored
349 return false;
350
c22f535 cosmetics
alcoheca authored
351 cp_status_t status;
352 cp_plugin_info_t *cpaddon = NULL;
353 cpaddon = m_cpluff->get_plugin_info(m_cp_context, str.c_str(), &status);
354 if (status == CP_OK && cpaddon->extensions)
355 {
356 addon = Factory(cpaddon->extensions);
357 m_cpluff->release_info(m_cp_context, cpaddon);
358 return true;
359 }
360 if (cpaddon)
361 m_cpluff->release_info(m_cp_context, cpaddon);
b6076e5 changed: screensavers are now supported via cpluff schema
alcoheca authored
362
7411555 changed: renamed UUID to ID. we now accept any string as an identifier,
alcoheca authored
363 if (m_idMap[str])
364 {
365 addon = m_idMap[str];
cc3b982 fixed: don't crash if an (visualization) addon is disabled
elupus authored
366 if(enabledOnly)
dea84cb changed: Disabled() -> Enabled() - more intuitive
spiff_ authored
367 return addon->Enabled();
cc3b982 fixed: don't crash if an (visualization) addon is disabled
elupus authored
368 else
369 return true;
7411555 changed: renamed UUID to ID. we now accept any string as an identifier,
alcoheca authored
370 }
074db86 merged: addons-fw branch
elupus authored
371
372 VECADDONS &addons = m_addons[type];
373 IVECADDONS adnItr = addons.begin();
374 while (adnItr != addons.end())
375 {
376 //FIXME scrapers were previously registered by filename
7411555 changed: renamed UUID to ID. we now accept any string as an identifier,
alcoheca authored
377 if ((*adnItr)->Name() == str || (type == ADDON_SCRAPER && (*adnItr)->LibName() == str))
074db86 merged: addons-fw branch
elupus authored
378 {
379 addon = (*adnItr);
cc3b982 fixed: don't crash if an (visualization) addon is disabled
elupus authored
380 if(enabledOnly)
dea84cb changed: Disabled() -> Enabled() - more intuitive
spiff_ authored
381 return addon->Enabled();
cc3b982 fixed: don't crash if an (visualization) addon is disabled
elupus authored
382 else
383 return true;
074db86 merged: addons-fw branch
elupus authored
384 }
385 adnItr++;
386 }
387
388 return false;
389 }
390
391 //TODO handle all 'default' cases here, not just scrapers & vizs
392 bool CAddonMgr::GetDefault(const TYPE &type, AddonPtr &addon, const CONTENT_TYPE &content)
393 {
394 if (type != ADDON_SCRAPER && type != ADDON_VIZ)
395 return false;
396
397 CStdString setting;
398 if (type == ADDON_VIZ)
399 setting = g_guiSettings.GetString("musicplayer.visualisation");
400 else
401 {
402 switch (content)
403 {
404 case CONTENT_MOVIES:
405 {
406 setting = g_guiSettings.GetString("scrapers.moviedefault");
407 break;
408 }
409 case CONTENT_TVSHOWS:
410 {
411 setting = g_guiSettings.GetString("scrapers.tvshowdefault");
412 break;
413 }
414 case CONTENT_MUSICVIDEOS:
415 {
416 setting = g_guiSettings.GetString("scrapers.musicvideodefault");
417 break;
418 }
419 case CONTENT_ALBUMS:
420 case CONTENT_ARTISTS:
421 {
422 setting = g_guiSettings.GetString("musiclibrary.scraper");
423 break;
424 }
425 default:
426 return false;
427 }
428 }
2ca76f9 changed: all addons should be store below either special://home/addon…
alcoheca authored
429 return GetAddon(setting, addon, type);
074db86 merged: addons-fw branch
elupus authored
430 }
431
7411555 changed: renamed UUID to ID. we now accept any string as an identifier,
alcoheca authored
432 CStdString CAddonMgr::GetString(const CStdString &id, const int number)
074db86 merged: addons-fw branch
elupus authored
433 {
7411555 changed: renamed UUID to ID. we now accept any string as an identifier,
alcoheca authored
434 AddonPtr addon = m_idMap[id];
074db86 merged: addons-fw branch
elupus authored
435 if (addon)
436 return addon->GetString(number);
437
438 return "";
439 }
440
af8cb2a Revert "wip"
alcoheca authored
441 void CAddonMgr::FindAddons()
442 {
4e5b98a added: locks to addon manager
spiff_ authored
443 CSingleLock lock(m_critSection);
639b314 changed: move addonbrowser to a mediawindow derivate
spiff_ authored
444 m_addons.clear();
445 m_idMap.clear();
c8f3bba fixed: dependency resolving
spiff_ authored
446
447 // store any addons with unresolved deps, then recheck at the end
448 map<CStdString, AddonPtr> unresolved;
449
28831ed fixed: don't check special://xbmc/addons twice when running with -p
alcoheca authored
450 if (!CSpecialProtocol::XBMCIsHome())
c8f3bba fixed: dependency resolving
spiff_ authored
451 LoadAddons("special://home/addons",unresolved);
452 LoadAddons("special://xbmc/addons",unresolved);
453
454 for (map<CStdString,AddonPtr>::iterator it = unresolved.begin();
455 it != unresolved.end(); ++it)
456 {
457 if (DependenciesMet(it->second))
458 {
459 if (!UpdateIfKnown(it->second))
460 {
461 m_addons[it->second->Type()].push_back(it->second);
462 m_idMap.insert(make_pair(it->first,it->second));
463 }
464 }
465 }
535b4e7 changed: load addons from user directory first, then load from system…
elupus authored
466 }
467
c8f3bba fixed: dependency resolving
spiff_ authored
468 void CAddonMgr::LoadAddons(const CStdString &path,
469 map<CStdString, AddonPtr>& unresolved)
535b4e7 changed: load addons from user directory first, then load from system…
elupus authored
470 {
af8cb2a Revert "wip"
alcoheca authored
471 // parse the user & system dirs for addons of the requested type
472 CFileItemList items;
535b4e7 changed: load addons from user directory first, then load from system…
elupus authored
473 CDirectory::GetDirectory(path, items);
af8cb2a Revert "wip"
alcoheca authored
474
475 // for all folders found
476 for (int i = 0; i < items.Size(); ++i)
477 {
478 CFileItemPtr item = items[i];
479
480 if(!item->m_bIsFolder)
481 continue;
482
483 // read description.xml and populate the addon
484 AddonPtr addon;
485 if (!AddonFromInfoXML(item->m_strPath, addon))
486 continue;
487
535b4e7 changed: load addons from user directory first, then load from system…
elupus authored
488 // only load if addon with same id isn't already loaded
c8f3bba fixed: dependency resolving
spiff_ authored
489 if(m_idMap.find(addon->ID()) != m_idMap.end() ||
490 unresolved.find(addon->ID()) != unresolved.end())
535b4e7 changed: load addons from user directory first, then load from system…
elupus authored
491 {
492 CLog::Log(LOGDEBUG, "ADDON: already loaded id %s, bypassing package", addon->ID().c_str());
493 continue;
494 }
495
af8cb2a Revert "wip"
alcoheca authored
496 // refuse to store addons with missing library
497 CStdString library(CUtil::AddFileToFolder(addon->Path(), addon->LibName()));
498 if (!CFile::Exists(library))
499 {
500 CLog::Log(LOGDEBUG, "ADDON: Missing library file %s, bypassing package", library.c_str());
501 continue;
502 }
503
504 if (!DependenciesMet(addon))
505 {
c8f3bba fixed: dependency resolving
spiff_ authored
506 unresolved.insert(make_pair(addon->ID(),addon));
af8cb2a Revert "wip"
alcoheca authored
507 continue;
508 }
509 else
510 { // everything ok, add to available addons if new
511 if (UpdateIfKnown(addon))
512 continue;
513 else
514 {
515 m_addons[addon->Type()].push_back(addon);
88e9b6f changed: expand std namespace
spiff_ authored
516 m_idMap.insert(make_pair(addon->ID(), addon));
af8cb2a Revert "wip"
alcoheca authored
517 }
518 }
519 }
520 }
521
522 bool CAddonMgr::UpdateIfKnown(AddonPtr &addon)
523 {
524 if (m_addons.find(addon->Type()) != m_addons.end())
525 {
526 for (unsigned i = 0; i < m_addons[addon->Type()].size(); i++)
527 {
528 if (m_addons[addon->Type()][i]->ID() == addon->ID())
529 {
530 //TODO inform any manager first, and request removal
531 //TODO choose most recent version if varying
532 m_addons[addon->Type()][i] = addon;
533 CStdString id = addon->ID();
534 m_idMap.erase(id);
88e9b6f changed: expand std namespace
spiff_ authored
535 m_idMap.insert(make_pair(addon->ID(), addon));
af8cb2a Revert "wip"
alcoheca authored
536 return true;
537 }
538 }
539 }
540 return false;
541 }
542
543 bool CAddonMgr::DependenciesMet(AddonPtr &addon)
544 {
545 if (!addon)
546 return false;
547
4e5b98a added: locks to addon manager
spiff_ authored
548 CSingleLock lock(m_critSection);
af8cb2a Revert "wip"
alcoheca authored
549 ADDONDEPS deps = addon->GetDeps();
550 ADDONDEPS::iterator itr = deps.begin();
551 while (itr != deps.end())
552 {
553 CStdString id;
554 id = (*itr).first;
555 AddonVersion min = (*itr).second.first;
556 AddonVersion max = (*itr).second.second;
557 if (m_idMap.count(id))
558 {
559 AddonPtr dep = m_idMap[id];
560 // we're guaranteed to have at least max OR min here
561 if (!min.str.IsEmpty() && !max.str.IsEmpty())
c8f3bba fixed: dependency resolving
spiff_ authored
562 {
563 if (dep->Version() < min || dep->Version() > max)
564 return false;
565 }
af8cb2a Revert "wip"
alcoheca authored
566 else if (!min.str.IsEmpty())
c8f3bba fixed: dependency resolving
spiff_ authored
567 {
568 if (dep->Version() < min)
569 return false;
570 }
af8cb2a Revert "wip"
alcoheca authored
571 else
c8f3bba fixed: dependency resolving
spiff_ authored
572 {
573 if (dep->Version() > max)
574 return false;
575 }
af8cb2a Revert "wip"
alcoheca authored
576 }
577 itr++;
578 }
c8f3bba fixed: dependency resolving
spiff_ authored
579 return true;
af8cb2a Revert "wip"
alcoheca authored
580 }
581
582 bool CAddonMgr::AddonFromInfoXML(const CStdString &path, AddonPtr &addon)
583 {
584 // First check that we can load description.xml
585 CStdString strPath(CUtil::AddFileToFolder(path, ADDON_METAFILE));
586 if(!CFile::Exists(strPath))
587 return false;
588
589 TiXmlDocument xmlDoc;
590 if (!xmlDoc.LoadFile(strPath))
591 {
592 CLog::Log(LOGERROR, "Unable to load: %s, Line %d\n%s", strPath.c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
593 return false;
594 }
595
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
596 const TiXmlElement *element = xmlDoc.RootElement();
af8cb2a Revert "wip"
alcoheca authored
597 if (!element || strcmpi(element->Value(), "addoninfo") != 0)
598 {
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
599 CLog::Log(LOGERROR, "ADDON: Error loading %s: cannot find <addon> root element", xmlDoc.Value());
af8cb2a Revert "wip"
alcoheca authored
600 return false;
601 }
602
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
603 return AddonFromInfoXML(element, addon, strPath);
604 }
605
606 bool CAddonMgr::AddonFromInfoXML(const TiXmlElement *rootElement,
607 AddonPtr &addon, const CStdString &strPath)
608 {
af8cb2a Revert "wip"
alcoheca authored
609 /* Steps required to meet package requirements
610 * 1. id exists and is valid
611 * 2. type exists and is valid
612 * 3. version exists
613 * 4. a license is specified
614 * 5. operating system matches ours
615 * 6. summary exists
616 * 7. for scrapers & plugins, support at least one type of content
617 *
618 * NOTE: addon dependencies are handled in ::FindAddons()
619 */
620
621 /* Validate id */
622 CStdString id;
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
623 const TiXmlElement *element = rootElement->FirstChildElement("id");
af8cb2a Revert "wip"
alcoheca authored
624 if (!element)
625 {
349765e cleanup: Removed unnecessary code and changed logging code in addons …
jmarshallnz authored
626 CLog::Log(LOGERROR, "ADDON: %s missing <id> element, ignoring", rootElement->GetDocument()->Value());
af8cb2a Revert "wip"
alcoheca authored
627 return false;
628 }
629 id = element->GetText();
630 //FIXME since we no longer required uuids, should we bother validating anything?
631 if (id.IsEmpty())
632 {
349765e cleanup: Removed unnecessary code and changed logging code in addons …
jmarshallnz authored
633 CLog::Log(LOGERROR, "ADDON: %s has invalid <id> element, ignoring", rootElement->GetDocument()->Value());
af8cb2a Revert "wip"
alcoheca authored
634 return false;
635 }
636
637 /* Validate type */
638 TYPE type;
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
639 element = rootElement->FirstChildElement("type");
af8cb2a Revert "wip"
alcoheca authored
640 if (!element)
641 {
349765e cleanup: Removed unnecessary code and changed logging code in addons …
jmarshallnz authored
642 CLog::Log(LOGERROR, "ADDON: %s missing <type> element, ignoring", rootElement->GetDocument()->Value());
af8cb2a Revert "wip"
alcoheca authored
643 return false;
644 }
645 type = TranslateType(element->GetText());
646 if (type == ADDON_UNKNOWN)
647 {
349765e cleanup: Removed unnecessary code and changed logging code in addons …
jmarshallnz authored
648 CLog::Log(LOGERROR, "ADDON: %s has invalid type identifier: '%d'", rootElement->GetDocument()->Value(), type);
af8cb2a Revert "wip"
alcoheca authored
649 return false;
650 }
651
652 /* Retrieve Name */
653 CStdString name;
822ca91 added: translatable <description>, <title>, <summary> and <disclaimer…
spiff_ authored
654 if (!GetTranslatedString(rootElement,"title",name))
af8cb2a Revert "wip"
alcoheca authored
655 {
349765e cleanup: Removed unnecessary code and changed logging code in addons …
jmarshallnz authored
656 CLog::Log(LOGERROR, "ADDON: %s missing <title> element, ignoring", rootElement->GetDocument()->Value());
af8cb2a Revert "wip"
alcoheca authored
657 return false;
658 }
659
660 /* Retrieve version */
661 CStdString version;
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
662 element = rootElement->FirstChildElement("version");
af8cb2a Revert "wip"
alcoheca authored
663 if (!element)
664 {
349765e cleanup: Removed unnecessary code and changed logging code in addons …
jmarshallnz authored
665 CLog::Log(LOGERROR, "ADDON: %s missing <version> element, ignoring", rootElement->GetDocument()->Value());
af8cb2a Revert "wip"
alcoheca authored
666 return false;
667 }
668 /* Validate version */
669 version = element->GetText();
670 CRegExp versionRE;
671 versionRE.RegComp(ADDON_VERSION_RE.c_str());
672 if (versionRE.RegFind(version.c_str()) != 0)
673 {
349765e cleanup: Removed unnecessary code and changed logging code in addons …
jmarshallnz authored
674 CLog::Log(LOGERROR, "ADDON: %s has invalid <version> element, ignoring", rootElement->GetDocument()->Value());
af8cb2a Revert "wip"
alcoheca authored
675 return false;
676 }
677
678 /* Path, ID & Version are valid */
679 AddonProps addonProps(id, type, version);
680 addonProps.name = name;
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
681 CUtil::GetDirectory(strPath,addonProps.path);
a594abe changed: move addon thumbs back to a fixed image (icon.png). We stil…
jmarshallnz authored
682 /* Set Icon */
683 addonProps.icon = "icon.png";
e90479d added: addon changelog support
spiff_ authored
684 /* Set Changelog */
685 addonProps.changelog = CUtil::AddFileToFolder(addonProps.path,"changelog.txt");
d9e6ddf added: fanart support for addons
spiff_ authored
686 /* Set Fanart */
d3c62cd fixed: Addon changelogs weren't being read.
jmarshallnz authored
687 addonProps.fanart = CUtil::AddFileToFolder(addonProps.path,"fanart.jpg");
af8cb2a Revert "wip"
alcoheca authored
688
689 /* Retrieve license */
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
690 element = rootElement->FirstChildElement("license");
af8cb2a Revert "wip"
alcoheca authored
691 /* if (!element)
692 {
349765e cleanup: Removed unnecessary code and changed logging code in addons …
jmarshallnz authored
693 CLog::Log(LOGERROR, "ADDON: %s missing <license> element, ignoring", rootElement->GetDocument()->Value());
af8cb2a Revert "wip"
alcoheca authored
694 return false;
695 }
696 addonProps.license = element->GetText();*/
697
698 /* Retrieve platforms which this addon supports */
699 CStdString platform;
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
700 element = rootElement->FirstChildElement("platforms")->FirstChildElement("platform");
af8cb2a Revert "wip"
alcoheca authored
701 if (!element)
702 {
349765e cleanup: Removed unnecessary code and changed logging code in addons …
jmarshallnz authored
703 CLog::Log(LOGERROR, "ADDON: %s missing <platforms> element, ignoring", rootElement->GetDocument()->Value());
af8cb2a Revert "wip"
alcoheca authored
704 return false;
705 }
706
707 bool all(false);
88e9b6f changed: expand std namespace
spiff_ authored
708 set<CStdString> platforms;
af8cb2a Revert "wip"
alcoheca authored
709 do
710 {
711 CStdString platform = element->GetText();
712 if (platform == "all")
713 {
714 all = true;
715 break;
716 }
717 platforms.insert(platform);
718 element = element->NextSiblingElement("platform");
719 } while (element != NULL);
720
721 if (!all)
722 {
723 #if defined(_LINUX) && !defined(__APPLE__)
724 if (!platforms.count("linux"))
725 {
349765e cleanup: Removed unnecessary code and changed logging code in addons …
jmarshallnz authored
726 CLog::Log(LOGNOTICE, "ADDON: %s is not supported under Linux, ignoring", rootElement->GetDocument()->Value());
af8cb2a Revert "wip"
alcoheca authored
727 return false;
728 }
78d5324 added: separate addon platforms for windows+dx and windows+opengl
spiff_ authored
729 #elif defined(_WIN32) && defined(HAS_SDL_OPENGL)
730 if (!platforms.count("windows-gl") && !platforms.count("windows"))
af8cb2a Revert "wip"
alcoheca authored
731 {
349765e cleanup: Removed unnecessary code and changed logging code in addons …
jmarshallnz authored
732 CLog::Log(LOGNOTICE, "ADDON: %s is not supported under Windows/OpenGL, ignoring", rootElement->GetDocument()->Value());
78d5324 added: separate addon platforms for windows+dx and windows+opengl
spiff_ authored
733 return false;
734 }
735 #elif defined(_WIN32) && defined(HAS_DX)
736 if (!platforms.count("windows-dx") && !platforms.count("windows"))
737 {
349765e cleanup: Removed unnecessary code and changed logging code in addons …
jmarshallnz authored
738 CLog::Log(LOGNOTICE, "ADDON: %s is not supported under Windows/DirectX, ignoring", rootElement->GetDocument()->Value());
af8cb2a Revert "wip"
alcoheca authored
739 return false;
740 }
741 #elif defined(__APPLE__)
742 if (!platforms.count("osx"))
743 {
349765e cleanup: Removed unnecessary code and changed logging code in addons …
jmarshallnz authored
744 CLog::Log(LOGNOTICE, "ADDON: %s is not supported under OSX, ignoring", rootElement->GetDocument()->Value());
af8cb2a Revert "wip"
alcoheca authored
745 return false;
746 }
747 #elif defined(_XBOX)
748 if (!platforms.count("xbox"))
749 {
349765e cleanup: Removed unnecessary code and changed logging code in addons …
jmarshallnz authored
750 CLog::Log(LOGNOTICE, "ADDON: %s is not supported under XBOX, ignoring", rootElement->GetDocument()->Value());
af8cb2a Revert "wip"
alcoheca authored
751 return false;
752 }
753 #endif
754 }
755
756 /* Retrieve summary */
d10c108 fixed: missing addon summary.
jmarshallnz authored
757 if (!GetTranslatedString(rootElement,"summary",addonProps.summary))
af8cb2a Revert "wip"
alcoheca authored
758 {
349765e cleanup: Removed unnecessary code and changed logging code in addons …
jmarshallnz authored
759 CLog::Log(LOGERROR, "ADDON: %s missing <summary> element, ignoring", rootElement->GetDocument()->Value());
af8cb2a Revert "wip"
alcoheca authored
760 return false;
761 }
762
763 if (addonProps.type == ADDON_SCRAPER || addonProps.type == ADDON_PLUGIN)
764 {
765 /* Retrieve content types that this addon supports */
766 CStdString platform;
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
767 if (rootElement->FirstChildElement("supportedcontent"))
af8cb2a Revert "wip"
alcoheca authored
768 {
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
769 element = rootElement->FirstChildElement("supportedcontent")->FirstChildElement("content");
af8cb2a Revert "wip"
alcoheca authored
770 }
771 if (!element)
772 {
349765e cleanup: Removed unnecessary code and changed logging code in addons …
jmarshallnz authored
773 CLog::Log(LOGERROR, "ADDON: %s missing <supportedcontent> element, ignoring", rootElement->GetDocument()->Value());
af8cb2a Revert "wip"
alcoheca authored
774 return false;
775 }
776
88e9b6f changed: expand std namespace
spiff_ authored
777 set<CONTENT_TYPE> contents;
af8cb2a Revert "wip"
alcoheca authored
778 do
779 {
780 CONTENT_TYPE content = TranslateContent(element->GetText());
781 if (content != CONTENT_NONE)
782 {
783 contents.insert(content);
784 }
785 element = element->NextSiblingElement("content");
786 } while (element != NULL);
787
788 if (contents.empty())
789 {
790 CLog::Log(LOGERROR, "ADDON: %s %s supports no available content-types, ignoring", TranslateType(addonProps.type).c_str(), addonProps.name.c_str());
791 return false;
792 }
793 else
794 {
795 addonProps.contents = contents;
796 }
797 }
798
799 /*** Beginning of optional fields ***/
309adab changed: Read addon icon from the <icon> tag rather than assuming def…
jmarshallnz authored
800 /* Retrieve icon */
801 element = rootElement->FirstChildElement("icon");
802 if (element)
803 addonProps.icon = element->GetText();
804
af8cb2a Revert "wip"
alcoheca authored
805 /* Retrieve description */
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
806 element = rootElement->FirstChildElement("description");
822ca91 added: translatable <description>, <title>, <summary> and <disclaimer…
spiff_ authored
807 GetTranslatedString(rootElement,"description",addonProps.description);
af8cb2a Revert "wip"
alcoheca authored
808
809 /* Retrieve author */
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
810 element = rootElement->FirstChildElement("author");
af8cb2a Revert "wip"
alcoheca authored
811 if (element)
812 addonProps.author = element->GetText();
813
814 /* Retrieve disclaimer */
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
815 element = rootElement->FirstChildElement("disclaimer");
822ca91 added: translatable <description>, <title>, <summary> and <disclaimer…
spiff_ authored
816 GetTranslatedString(rootElement,"disclaimer",addonProps.disclaimer);
af8cb2a Revert "wip"
alcoheca authored
817
818 /* Retrieve library file name */
819 // will be replaced with default library name if unspecified
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
820 element = rootElement->FirstChildElement("library");
af8cb2a Revert "wip"
alcoheca authored
821 if (element)
822 addonProps.libname = element->GetText();
823
824 //TODO move this to addon specific class, if it's needed at all..
825 #ifdef _WIN32
826 /* Retrieve WIN32 library file name in case it is present
827 * This is required for no overwrite to the fixed WIN32 add-on's
828 * during compile time
829 */
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
830 element = rootElement->FirstChildElement("librarywin32");
af8cb2a Revert "wip"
alcoheca authored
831 if (element) // If it is found overwrite standard library name
832 addonProps.libname = element->GetText();
833 #endif
834
835 /* Retrieve dependencies that this addon requires */
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
836 element = rootElement->FirstChildElement("dependencies");
af8cb2a Revert "wip"
alcoheca authored
837 if (element)
838 {
839 element = element->FirstChildElement("dependency");
840 if (!element)
349765e cleanup: Removed unnecessary code and changed logging code in addons …
jmarshallnz authored
841 CLog::Log(LOGDEBUG, "ADDON: %s missing at least one <dependency> element, will ignore this dependency", rootElement->GetDocument()->Value());
af8cb2a Revert "wip"
alcoheca authored
842 else
843 {
844 do
845 {
8a457f5 fixed: somebody must have had a blond moment - you can't check a stds…
spiff_ authored
846 const char* min = element->Attribute("minversion");
847 const char* max = element->Attribute("maxversion");
848 const char* id = element->GetText();
849 if (!id || (!min && !max))
af8cb2a Revert "wip"
alcoheca authored
850 {
349765e cleanup: Removed unnecessary code and changed logging code in addons …
jmarshallnz authored
851 CLog::Log(LOGDEBUG, "ADDON: %s malformed <dependency> element, will ignore this dependency", rootElement->GetDocument()->Value());
8a457f5 fixed: somebody must have had a blond moment - you can't check a stds…
spiff_ authored
852 element = element->NextSiblingElement("dependency");
af8cb2a Revert "wip"
alcoheca authored
853 continue;
854 }
8a457f5 fixed: somebody must have had a blond moment - you can't check a stds…
spiff_ authored
855 addonProps.dependencies.insert(make_pair(CStdString(id), make_pair(AddonVersion(min?min:""), AddonVersion(max?max:""))));
af8cb2a Revert "wip"
alcoheca authored
856 element = element->NextSiblingElement("dependency");
857 } while (element != NULL);
858 }
859 }
860
861 /*** end of optional fields ***/
862
863 /* Create an addon object and store in a shared_ptr */
eca3c5b changed: refactor
spiff_ authored
864 addon = AddonFromProps(addonProps);
865
866 return addon.get() != NULL;
867 }
868
822ca91 added: translatable <description>, <title>, <summary> and <disclaimer…
spiff_ authored
869 bool CAddonMgr::GetTranslatedString(const TiXmlElement *xmldoc, const char *tag, CStdString& data)
870 {
871 const TiXmlElement *element = xmldoc->FirstChildElement(tag);
872 const TiXmlElement *enelement = NULL;
873 while (element)
874 {
875 const char* lang = element->Attribute("lang");
876 if (lang && strcmp(lang,g_langInfo.GetDVDAudioLanguage().c_str()) == 0)
877 break;
878 if (!lang || strcmp(lang,"en") == 0)
879 enelement = element;
880 element = element->NextSiblingElement(tag);
881 }
882 if (!element)
883 element = enelement;
884 if (element)
885 data = element->GetText();
886
887 return element != NULL;
888 }
889
096e8a3 changed: Move description information into addon.xml via the xbmc.add…
jmarshallnz authored
890 const char *CAddonMgr::GetTranslatedString(const cp_cfg_element_t *root, const char *tag)
891 {
892 if (!root)
893 return NULL;
894
895 const cp_cfg_element_t *eng = NULL;
896 for (unsigned int i = 0; i < root->num_children; i++)
897 {
898 const cp_cfg_element_t &child = root->children[i];
899 if (strcmp(tag, child.name) == 0)
900 { // see if we have a "lang" attribute
901 const char *lang = m_cpluff->lookup_cfg_value((cp_cfg_element_t*)&child, "@lang");
902 if (lang && 0 == strcmp(lang,g_langInfo.GetDVDAudioLanguage().c_str()))
903 return child.value;
904 if (!lang || 0 == strcmp(lang, "en"))
905 eng = &child;
906 }
907 }
908 return (eng) ? eng->value : NULL;
909 }
910
eca3c5b changed: refactor
spiff_ authored
911 AddonPtr CAddonMgr::AddonFromProps(AddonProps& addonProps)
912 {
913 switch (addonProps.type)
af8cb2a Revert "wip"
alcoheca authored
914 {
915 case ADDON_PLUGIN:
916 case ADDON_SCRIPT:
eca3c5b changed: refactor
spiff_ authored
917 return AddonPtr(new CAddon(addonProps));
af8cb2a Revert "wip"
alcoheca authored
918 case ADDON_SCRAPER:
eca3c5b changed: refactor
spiff_ authored
919 return AddonPtr(new CScraper(addonProps));
553d213 changed: finished moving skins to addon framework
alcoheca authored
920 case ADDON_SKIN:
921 return AddonPtr(new CSkinInfo(addonProps));
07e5742 [arm] merge arm-camelot into trunk, thanks to mcgeagh for all his har…
davilla authored
922 #if defined(HAS_VISUALISATION)
af8cb2a Revert "wip"
alcoheca authored
923 case ADDON_VIZ:
eca3c5b changed: refactor
spiff_ authored
924 return AddonPtr(new CVisualisation(addonProps));
07e5742 [arm] merge arm-camelot into trunk, thanks to mcgeagh for all his har…
davilla authored
925 #endif
af8cb2a Revert "wip"
alcoheca authored
926 case ADDON_SCREENSAVER:
eca3c5b changed: refactor
spiff_ authored
927 return AddonPtr(new CScreenSaver(addonProps));
af8cb2a Revert "wip"
alcoheca authored
928 case ADDON_SCRAPER_LIBRARY:
929 case ADDON_VIZ_LIBRARY:
6433385 added: script-library addon-type
spiff_ authored
930 case ADDON_SCRIPT_LIBRARY:
eca3c5b changed: refactor
spiff_ authored
931 return AddonPtr(new CAddonLibrary(addonProps));
606248f added: addon repository class
spiff_ authored
932 case ADDON_REPOSITORY:
933 return AddonPtr(new CRepository(addonProps));
af8cb2a Revert "wip"
alcoheca authored
934 default:
eca3c5b changed: refactor
spiff_ authored
935 break;
af8cb2a Revert "wip"
alcoheca authored
936 }
eca3c5b changed: refactor
spiff_ authored
937 return AddonPtr();
af8cb2a Revert "wip"
alcoheca authored
938 }
939
639b314 changed: move addonbrowser to a mediawindow derivate
spiff_ authored
940 void CAddonMgr::UpdateRepos()
941 {
942 CSingleLock lock(m_critSection);
943 if (m_watch.GetElapsedSeconds() < 600)
944 return;
945 m_watch.StartZero();
946 VECADDONS addons;
947 GetAddons(ADDON_REPOSITORY,addons);
948 for (unsigned int i=0;i<addons.size();++i)
949 {
950 RepositoryPtr repo = boost::dynamic_pointer_cast<CRepository>(addons[i]);
951 if (repo->LastUpdate()+CDateTimeSpan(0,6,0,0) < CDateTime::GetCurrentDateTime())
952 {
953 CLog::Log(LOGDEBUG,"Checking repository %s for updates",repo->Name().c_str());
9617e5e cosmetics
spiff_ authored
954 CJobManager::GetInstance().AddJob(new CRepositoryUpdateJob(repo),this);
639b314 changed: move addonbrowser to a mediawindow derivate
spiff_ authored
955 }
956 }
957 }
958
959 void CAddonMgr::OnJobComplete(unsigned int jobID, bool success, CJob* job)
960 {
961 if (!success)
962 return;
963
964 ((CRepositoryUpdateJob*)job)->m_repo->SetUpdated(CDateTime::GetCurrentDateTime());
965 }
966
1b2781c added: basic cpluff support
alcoheca authored
967 /*
968 * libcpluff interaction
969 */
970
bb4e01c Support creating userdirs in addons. This also has the benefit of bei…
ceros7 authored
971 const cp_cfg_element_t *CAddonMgr::GetExtElement(cp_cfg_element_t *base, const char *path)
972 {
973 const cp_cfg_element_t *element = NULL;
974 if (base)
975 element = m_cpluff->lookup_cfg_element(base, path);
976 return element;
977 }
978
979 /* Returns all duplicate elements from a base element */
980 bool CAddonMgr::GetExtElementDeque(DEQUEELEMENTS &elements, cp_cfg_element_t *base, const char *path)
981 {
982 if (!base)
983 return false;
984
985 unsigned int i = 0;
986 while (true)
987 {
988 if (i >= base->num_children)
989 break;
990 CStdString temp = (base->children+i)->name;
991 if (!temp.compare(path))
992 elements.push_back(base->children+i);
993 i++;
994 }
995
996 if (elements.empty()) return false;
997 return true;
998 }
999
096e8a3 changed: Move description information into addon.xml via the xbmc.add…
jmarshallnz authored
1000 const cp_extension_t *CAddonMgr::GetExtension(const cp_plugin_info_t *props, const char *extension)
1001 {
1002 if (!props)
1003 return NULL;
1004 for (unsigned int i = 0; i < props->num_extensions; ++i)
1005 {
1006 if (0 == strcmp(props->extensions[i].ext_point_id, extension))
1007 return &props->extensions[i];
1008 }
1009 return NULL;
1010 }
1011
b6076e5 changed: screensavers are now supported via cpluff schema
alcoheca authored
1012 CStdString CAddonMgr::GetExtValue(cp_cfg_element_t *base, const char *path)
1013 {
1014 const char *value = NULL;
1015 if (base && (value = m_cpluff->lookup_cfg_value(base, path)))
1016 return CStdString(value);
1017 else return CStdString();
1018 }
1019
5bca9c0 cleanup: Rename and document the cpluff versions of loading addon des…
jmarshallnz authored
1020 bool CAddonMgr::LoadAddonDescription(const CStdString &path, AddonPtr &addon)
92afa2e fixed: Addons weren't installed correctly
jmarshallnz authored
1021 {
1022 cp_status_t status;
1023 cp_plugin_info_t *info = m_cpluff->load_plugin_descriptor(m_cp_context, _P(path).c_str(), &status);
1024 if (info)
1025 {
1026 addon = Factory(info->extensions);
1027 m_cpluff->release_info(m_cp_context, info);
1028 return addon.get();
1029 }
1030 return false;
1031 }
1032
5bca9c0 cleanup: Rename and document the cpluff versions of loading addon des…
jmarshallnz authored
1033 bool CAddonMgr::AddonsFromRepoXML(const TiXmlElement *root, VECADDONS &addons)
4488d3a changed: Allow repository to have c-pluff XML files
jmarshallnz authored
1034 {
1035 // create a context for these addons
1036 cp_status_t status;
1037 cp_context_t *context = m_cpluff->create_context(&status);
1038 if (!root || !context)
1039 return false;
1040
cfe53d3 fixed: Put the UTF-8 descriptor on the XML before feeding it to c-pluff
jmarshallnz authored
1041 // each addon XML should have a UTF-8 declaration
1042 TiXmlDeclaration decl("1.0", "UTF-8", "");
4488d3a changed: Allow repository to have c-pluff XML files
jmarshallnz authored
1043 const TiXmlElement *element = root->FirstChildElement("addon");
1044 while (element)
1045 {
cfe53d3 fixed: Put the UTF-8 descriptor on the XML before feeding it to c-pluff
jmarshallnz authored
1046 // dump the XML back to text
4488d3a changed: Allow repository to have c-pluff XML files
jmarshallnz authored
1047 std::string xml;
cfe53d3 fixed: Put the UTF-8 descriptor on the XML before feeding it to c-pluff
jmarshallnz authored
1048 xml << decl;
4488d3a changed: Allow repository to have c-pluff XML files
jmarshallnz authored
1049 xml << *element;
1050 cp_status_t status;
cd2be2f added: Expose cp_load_plugin_descriptor and separate out the from_mem…
jmarshallnz authored
1051 cp_plugin_info_t *info = m_cpluff->load_plugin_descriptor_from_memory(context, xml.c_str(), xml.size(), &status);
4488d3a changed: Allow repository to have c-pluff XML files
jmarshallnz authored
1052 if (info)
1053 {
1054 AddonPtr addon = Factory(info->extensions);
1055 m_cpluff->release_info(context, info);
1056 // FIXME: sanity check here that the addon satisfies our requirements?
ed51e37 fixed: check for NULL before adding the addon in AddonsFromInfoXML
jmarshallnz authored
1057 if (addon.get())
1058 addons.push_back(addon);
4488d3a changed: Allow repository to have c-pluff XML files
jmarshallnz authored
1059 }
1060 element = element->NextSiblingElement("addon");
1061 }
1062 m_cpluff->destroy_context(context);
1063 return true;
1064 }
1065
1b2781c added: basic cpluff support
alcoheca authored
1066 int cp_to_clog(cp_log_severity_t lvl)
1067 {
1068 if( lvl == CP_LOG_DEBUG )
1069 return 0;
1070 else if (lvl == CP_LOG_INFO)
1071 return 1;
1072 else if (lvl == CP_LOG_WARNING)
1073 return 3;
1074 else
1075 return 4;
1076 }
1077
1078 cp_log_severity_t clog_to_cp(int lvl)
1079 {
1080 if (lvl >= 4)
1081 return CP_LOG_ERROR;
1082 else if (lvl == 3)
1083 return CP_LOG_WARNING;
1084 else if (lvl >= 1)
1085 return CP_LOG_INFO;
1086 else
1087 return CP_LOG_DEBUG;
1088 }
1089
b6f0f59 cleanup: Don't expose the AddonManager's privates when not required.
jmarshallnz authored
1090 void cp_fatalErrorHandler(const char *msg)
1091 {
1092 CLog::Log(LOGERROR, "ADDONS: CPluffFatalError(%s)", msg);
1093 }
1094
1095 void cp_logger(cp_log_severity_t level, const char *msg, const char *apid, void *user_data)
1b2781c added: basic cpluff support
alcoheca authored
1096 {
1097 if(!apid)
5b793b6 added: missing change from r29798
alcoheca authored
1098 CLog::Log(cp_to_clog(level), "ADDON: cpluff: '%s'", msg);
1b2781c added: basic cpluff support
alcoheca authored
1099 else
5b793b6 added: missing change from r29798
alcoheca authored
1100 CLog::Log(cp_to_clog(level), "ADDON: cpluff: '%s' reports '%s'", apid, msg);
1b2781c added: basic cpluff support
alcoheca authored
1101 }
1102
074db86 merged: addons-fw branch
elupus authored
1103 } /* namespace ADDON */
1104
Something went wrong with that request. Please try again.