Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 669 lines (599 sloc) 18.716 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"
23 #include "StringUtils.h"
24 #include "RegExp.h"
25 #include "XMLUtils.h"
26 #include "FileItem.h"
27 #include "Settings.h"
28 #include "GUISettings.h"
29 #include "DownloadQueueManager.h"
dacdca0 changed: moved CAddonStatusHandler to separate files
alcoheca authored
30 #include "log.h"
074db86 merged: addons-fw branch
elupus authored
31
32 #ifdef HAS_VISUALISATION
055f806 cosmetic/tidyup move all addon classes to /xbmc/addons/
alcoheca authored
33 #include "DllVisualisation.h"
34 #include "Visualisation.h"
074db86 merged: addons-fw branch
elupus authored
35 #endif
36 #ifdef HAS_SCREENSAVER
055f806 cosmetic/tidyup move all addon classes to /xbmc/addons/
alcoheca authored
37 #include "DllScreenSaver.h"
38 #include "ScreenSaver.h"
074db86 merged: addons-fw branch
elupus authored
39 #endif
40 //#ifdef HAS_SCRAPERS
055f806 cosmetic/tidyup move all addon classes to /xbmc/addons/
alcoheca authored
41 #include "Scraper.h"
074db86 merged: addons-fw branch
elupus authored
42 //#endif
43
af8cb2a Revert "wip"
alcoheca authored
44
074db86 merged: addons-fw branch
elupus authored
45 namespace ADDON
46 {
47
48
49 /**********************************************************
50 * CAddonMgr
51 *
52 */
53
54 CAddonMgr* CAddonMgr::m_pInstance = NULL;
55 std::map<TYPE, IAddonMgrCallback*> CAddonMgr::m_managers;
56
57 CAddonMgr::CAddonMgr()
58 {
59 }
60
61 CAddonMgr::~CAddonMgr()
62 {
63 }
64
65 CAddonMgr* CAddonMgr::Get()
66 {
67 if (!m_pInstance)
68 {
69 m_pInstance = new CAddonMgr();
70 }
71 return m_pInstance;
72 }
73
74 IAddonMgrCallback* CAddonMgr::GetCallbackForType(TYPE type)
75 {
76 if (m_managers.find(type) == m_managers.end())
77 return NULL;
78 else
79 return m_managers[type];
80 }
81
82 bool CAddonMgr::RegisterAddonMgrCallback(const TYPE type, IAddonMgrCallback* cb)
83 {
84 if (cb == NULL)
85 return false;
86
87 m_managers.erase(type);
88 m_managers[type] = cb;
89
90 return true;
91 }
92
93 void CAddonMgr::UnregisterAddonMgrCallback(TYPE type)
94 {
95 m_managers.erase(type);
96 }
97
cc3b982 fixed: don't crash if an (visualization) addon is disabled
elupus authored
98 bool CAddonMgr::HasAddons(const TYPE &type, const CONTENT_TYPE &content/*= CONTENT_NONE*/, bool enabledOnly/*= true*/)
074db86 merged: addons-fw branch
elupus authored
99 {
af8cb2a Revert "wip"
alcoheca authored
100 if (m_addons.empty())
101 {
102 VECADDONS add;
103 GetAllAddons(add,false);
104 }
105
106 if (content == CONTENT_NONE)
107 return (m_addons.find(type) != m_addons.end());
074db86 merged: addons-fw branch
elupus authored
108
109 VECADDONS addons;
cc3b982 fixed: don't crash if an (visualization) addon is disabled
elupus authored
110 return GetAddons(type, addons, content, enabledOnly);
074db86 merged: addons-fw branch
elupus authored
111 }
112
113 bool CAddonMgr::GetAllAddons(VECADDONS &addons, bool enabledOnly/*= true*/)
114 {
af8cb2a Revert "wip"
alcoheca authored
115 VECADDONS temp;
116 if (CAddonMgr::Get()->GetAddons(ADDON_PLUGIN, temp, CONTENT_NONE, enabledOnly))
117 addons.insert(addons.end(), temp.begin(), temp.end());
118 if (CAddonMgr::Get()->GetAddons(ADDON_SCRAPER, temp, CONTENT_NONE, enabledOnly))
119 addons.insert(addons.end(), temp.begin(), temp.end());
120 if (CAddonMgr::Get()->GetAddons(ADDON_SCREENSAVER, temp, CONTENT_NONE, enabledOnly))
121 addons.insert(addons.end(), temp.begin(), temp.end());
122 if (CAddonMgr::Get()->GetAddons(ADDON_SCRIPT, temp, CONTENT_NONE, enabledOnly))
123 addons.insert(addons.end(), temp.begin(), temp.end());
124 if (CAddonMgr::Get()->GetAddons(ADDON_VIZ, temp, CONTENT_NONE, enabledOnly))
125 addons.insert(addons.end(), temp.begin(), temp.end());
126 return !addons.empty();
074db86 merged: addons-fw branch
elupus authored
127 }
128
129 bool CAddonMgr::GetAddons(const TYPE &type, VECADDONS &addons, const CONTENT_TYPE &content/*= CONTENT_NONE*/, bool enabledOnly/*= true*/)
130 {
4e5b98a added: locks to addon manager
spiff_ authored
131 CSingleLock lock(m_critSection);
af8cb2a Revert "wip"
alcoheca authored
132 addons.clear();
133 if (m_addons.find(type) != m_addons.end())
134 {
135 IVECADDONS itr = m_addons[type].begin();
136 while (itr != m_addons[type].end())
137 { // filter out what we're not looking for
dea84cb changed: Disabled() -> Enabled() - more intuitive
spiff_ authored
138 if ((enabledOnly && !(*itr)->Enabled())
af8cb2a Revert "wip"
alcoheca authored
139 || (content != CONTENT_NONE && !(*itr)->Supports(content)))
140 {
141 ++itr;
142 continue;
143 }
144 addons.push_back(*itr);
145 ++itr;
146 }
147 }
148 return !addons.empty();
074db86 merged: addons-fw branch
elupus authored
149 }
150
cc3b982 fixed: don't crash if an (visualization) addon is disabled
elupus authored
151 bool CAddonMgr::GetAddon(const CStdString &str, AddonPtr &addon, const TYPE &type/*=ADDON_UNKNOWN*/, bool enabledOnly/*= true*/)
074db86 merged: addons-fw branch
elupus authored
152 {
4e5b98a added: locks to addon manager
spiff_ authored
153 CSingleLock lock(m_critSection);
2ca76f9 changed: all addons should be store below either special://home/addons o...
alcoheca authored
154 if (type != ADDON_UNKNOWN && m_addons.find(type) == m_addons.end())
074db86 merged: addons-fw branch
elupus authored
155 return false;
156
7411555 changed: renamed UUID to ID. we now accept any string as an identifier,
alcoheca authored
157 if (m_idMap[str])
158 {
159 addon = m_idMap[str];
cc3b982 fixed: don't crash if an (visualization) addon is disabled
elupus authored
160 if(enabledOnly)
dea84cb changed: Disabled() -> Enabled() - more intuitive
spiff_ authored
161 return addon->Enabled();
cc3b982 fixed: don't crash if an (visualization) addon is disabled
elupus authored
162 else
163 return true;
7411555 changed: renamed UUID to ID. we now accept any string as an identifier,
alcoheca authored
164 }
074db86 merged: addons-fw branch
elupus authored
165
166 VECADDONS &addons = m_addons[type];
167 IVECADDONS adnItr = addons.begin();
168 while (adnItr != addons.end())
169 {
170 //FIXME scrapers were previously registered by filename
7411555 changed: renamed UUID to ID. we now accept any string as an identifier,
alcoheca authored
171 if ((*adnItr)->Name() == str || (type == ADDON_SCRAPER && (*adnItr)->LibName() == str))
074db86 merged: addons-fw branch
elupus authored
172 {
173 addon = (*adnItr);
cc3b982 fixed: don't crash if an (visualization) addon is disabled
elupus authored
174 if(enabledOnly)
dea84cb changed: Disabled() -> Enabled() - more intuitive
spiff_ authored
175 return addon->Enabled();
cc3b982 fixed: don't crash if an (visualization) addon is disabled
elupus authored
176 else
177 return true;
074db86 merged: addons-fw branch
elupus authored
178 }
179 adnItr++;
180 }
181
182 return false;
183 }
184
185 //TODO handle all 'default' cases here, not just scrapers & vizs
186 bool CAddonMgr::GetDefault(const TYPE &type, AddonPtr &addon, const CONTENT_TYPE &content)
187 {
188 if (type != ADDON_SCRAPER && type != ADDON_VIZ)
189 return false;
190
191 CStdString setting;
192 if (type == ADDON_VIZ)
193 setting = g_guiSettings.GetString("musicplayer.visualisation");
194 else
195 {
196 switch (content)
197 {
198 case CONTENT_MOVIES:
199 {
200 setting = g_guiSettings.GetString("scrapers.moviedefault");
201 break;
202 }
203 case CONTENT_TVSHOWS:
204 {
205 setting = g_guiSettings.GetString("scrapers.tvshowdefault");
206 break;
207 }
208 case CONTENT_MUSICVIDEOS:
209 {
210 setting = g_guiSettings.GetString("scrapers.musicvideodefault");
211 break;
212 }
213 case CONTENT_ALBUMS:
214 case CONTENT_ARTISTS:
215 {
216 setting = g_guiSettings.GetString("musiclibrary.scraper");
217 break;
218 }
219 default:
220 return false;
221 }
222 }
2ca76f9 changed: all addons should be store below either special://home/addons o...
alcoheca authored
223 return GetAddon(setting, addon, type);
074db86 merged: addons-fw branch
elupus authored
224 }
225
7411555 changed: renamed UUID to ID. we now accept any string as an identifier,
alcoheca authored
226 CStdString CAddonMgr::GetString(const CStdString &id, const int number)
074db86 merged: addons-fw branch
elupus authored
227 {
7411555 changed: renamed UUID to ID. we now accept any string as an identifier,
alcoheca authored
228 AddonPtr addon = m_idMap[id];
074db86 merged: addons-fw branch
elupus authored
229 if (addon)
230 return addon->GetString(number);
231
232 return "";
233 }
234
af8cb2a Revert "wip"
alcoheca authored
235 void CAddonMgr::FindAddons()
236 {
4e5b98a added: locks to addon manager
spiff_ authored
237 CSingleLock lock(m_critSection);
af8cb2a Revert "wip"
alcoheca authored
238 // parse the user & system dirs for addons of the requested type
239 CFileItemList items;
240 if (!CSpecialProtocol::XBMCIsHome())
241 CDirectory::GetDirectory("special://home/addons", items);
242 CDirectory::GetDirectory("special://xbmc/addons", items);
243
244 // store any addons with unresolved deps, then recheck at the end
245 VECADDONS unresolved;
246
247 // for all folders found
248 for (int i = 0; i < items.Size(); ++i)
249 {
250 CFileItemPtr item = items[i];
251
252 if(!item->m_bIsFolder)
253 continue;
254
255 // read description.xml and populate the addon
256 AddonPtr addon;
257 if (!AddonFromInfoXML(item->m_strPath, addon))
258 continue;
259
260 // refuse to store addons with missing library
261 CStdString library(CUtil::AddFileToFolder(addon->Path(), addon->LibName()));
262 if (!CFile::Exists(library))
263 {
264 CLog::Log(LOGDEBUG, "ADDON: Missing library file %s, bypassing package", library.c_str());
265 continue;
266 }
267
268 // check for/cache icon thumbnail
269 //TODO cache one thumb per addon id instead
270 CFileItem item2(CUtil::AddFileToFolder(addon->Path(), addon->LibName()), false);
271 item2.SetCachedProgramThumb();
272 if (!item2.HasThumbnail())
273 item2.SetUserProgramThumb();
274 if (!item2.HasThumbnail())
275 item2.SetThumbnailImage(addon->Icon());
276 if (item2.HasThumbnail())
277 {
278 XFILE::CFile::Cache(item2.GetThumbnailImage(),item->GetCachedProgramThumb());
279 }
280
281 if (!DependenciesMet(addon))
282 {
283 unresolved.push_back(addon);
284 continue;
285 }
286 else
287 { // everything ok, add to available addons if new
288 if (UpdateIfKnown(addon))
289 continue;
290 else
291 {
292 m_addons[addon->Type()].push_back(addon);
293 m_idMap.insert(std::make_pair(addon->ID(), addon));
294 }
295 }
296 }
297
298 for (unsigned i = 0; i < unresolved.size(); i++)
299 {
300 AddonPtr& addon = unresolved[i];
301 if (DependenciesMet(addon))
302 {
303 if (!UpdateIfKnown(addon))
304 {
305 m_addons[addon->Type()].push_back(addon);
306 m_idMap.insert(std::make_pair(addon->ID(), addon));
307 }
308 }
309 }
310 // CLog::Log(LOGINFO, "ADDON: Found %"PRIuS" addons", m_addons.find(type) == m_addons.end() ? 0: m_addons[type].size(), TranslateType(type).c_str());
311 }
312
313 bool CAddonMgr::UpdateIfKnown(AddonPtr &addon)
314 {
315 if (m_addons.find(addon->Type()) != m_addons.end())
316 {
317 for (unsigned i = 0; i < m_addons[addon->Type()].size(); i++)
318 {
319 if (m_addons[addon->Type()][i]->ID() == addon->ID())
320 {
321 //TODO inform any manager first, and request removal
322 //TODO choose most recent version if varying
323 m_addons[addon->Type()][i] = addon;
324 CStdString id = addon->ID();
325 m_idMap.erase(id);
326 m_idMap.insert(std::make_pair(addon->ID(), addon));
327 return true;
328 }
329 }
330 }
331 return false;
332 }
333
334 bool CAddonMgr::DependenciesMet(AddonPtr &addon)
335 {
336 // As remote repos are not functioning,
337 // this will fail if a dependency is not found locally
338 if (!addon)
339 return false;
340
4e5b98a added: locks to addon manager
spiff_ authored
341 CSingleLock lock(m_critSection);
af8cb2a Revert "wip"
alcoheca authored
342 ADDONDEPS deps = addon->GetDeps();
343 ADDONDEPS::iterator itr = deps.begin();
344 while (itr != deps.end())
345 {
346 CStdString id;
347 id = (*itr).first;
348 AddonVersion min = (*itr).second.first;
349 AddonVersion max = (*itr).second.second;
350 if (m_idMap.count(id))
351 {
352 AddonPtr dep = m_idMap[id];
353 // we're guaranteed to have at least max OR min here
354 if (!min.str.IsEmpty() && !max.str.IsEmpty())
355 return (dep->Version() >= min && dep->Version() <= max);
356 else if (!min.str.IsEmpty())
357 return (dep->Version() >= min);
358 else
359 return (dep->Version() <= max);
360 }
361 itr++;
362 }
363 return deps.empty();
364 }
365
366 bool CAddonMgr::AddonFromInfoXML(const CStdString &path, AddonPtr &addon)
367 {
368 // First check that we can load description.xml
369 CStdString strPath(CUtil::AddFileToFolder(path, ADDON_METAFILE));
370 if(!CFile::Exists(strPath))
371 return false;
372
373 TiXmlDocument xmlDoc;
374 if (!xmlDoc.LoadFile(strPath))
375 {
376 CLog::Log(LOGERROR, "Unable to load: %s, Line %d\n%s", strPath.c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
377 return false;
378 }
379
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
380 const TiXmlElement *element = xmlDoc.RootElement();
af8cb2a Revert "wip"
alcoheca authored
381 if (!element || strcmpi(element->Value(), "addoninfo") != 0)
382 {
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
383 CLog::Log(LOGERROR, "ADDON: Error loading %s: cannot find <addon> root element", xmlDoc.Value());
af8cb2a Revert "wip"
alcoheca authored
384 return false;
385 }
386
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
387 return AddonFromInfoXML(element, addon, strPath);
388 }
389
390 bool CAddonMgr::AddonFromInfoXML(const TiXmlElement *rootElement,
391 AddonPtr &addon, const CStdString &strPath)
392 {
af8cb2a Revert "wip"
alcoheca authored
393 /* Steps required to meet package requirements
394 * 1. id exists and is valid
395 * 2. type exists and is valid
396 * 3. version exists
397 * 4. a license is specified
398 * 5. operating system matches ours
399 * 6. summary exists
400 * 7. for scrapers & plugins, support at least one type of content
401 *
402 * NOTE: addon dependencies are handled in ::FindAddons()
403 */
404
405 /* Validate id */
406 CStdString id;
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
407 const TiXmlElement *element = rootElement->FirstChildElement("id");
af8cb2a Revert "wip"
alcoheca authored
408 if (!element)
409 {
410 CLog::Log(LOGERROR, "ADDON: %s missing <id> element, ignoring", strPath.c_str());
411 return false;
412 }
413 id = element->GetText();
414 //FIXME since we no longer required uuids, should we bother validating anything?
415 if (id.IsEmpty())
416 {
417 CLog::Log(LOGERROR, "ADDON: %s has invalid <id> element, ignoring", strPath.c_str());
418 return false;
419 }
420
421 /* Validate type */
422 TYPE type;
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
423 element = rootElement->FirstChildElement("type");
af8cb2a Revert "wip"
alcoheca authored
424 if (!element)
425 {
f6bc944 fixed: typo
spiff_ authored
426 CLog::Log(LOGERROR, "ADDON: %s missing <type> element, ignoring", strPath.c_str());
af8cb2a Revert "wip"
alcoheca authored
427 return false;
428 }
429 type = TranslateType(element->GetText());
430 if (type == ADDON_UNKNOWN)
431 {
432 CLog::Log(LOGERROR, "ADDON: %s has invalid type identifier: '%d'", strPath.c_str(), type);
433 return false;
434 }
435
436 /* Retrieve Name */
437 CStdString name;
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
438 element = rootElement->FirstChildElement("title");
af8cb2a Revert "wip"
alcoheca authored
439 if (!element)
440 {
441 CLog::Log(LOGERROR, "ADDON: %s missing <title> element, ignoring", strPath.c_str());
442 return false;
443 }
444 name = element->GetText();
445
446 /* Retrieve version */
447 CStdString version;
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
448 element = rootElement->FirstChildElement("version");
af8cb2a Revert "wip"
alcoheca authored
449 if (!element)
450 {
451 CLog::Log(LOGERROR, "ADDON: %s missing <version> element, ignoring", strPath.c_str());
452 return false;
453 }
454 /* Validate version */
455 version = element->GetText();
456 CRegExp versionRE;
457 versionRE.RegComp(ADDON_VERSION_RE.c_str());
458 if (versionRE.RegFind(version.c_str()) != 0)
459 {
460 CLog::Log(LOGERROR, "ADDON: %s has invalid <version> element, ignoring", strPath.c_str());
461 return false;
462 }
463
464 /* Path, ID & Version are valid */
465 AddonProps addonProps(id, type, version);
466 addonProps.name = name;
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
467 CUtil::GetDirectory(strPath,addonProps.path);
468 addonProps.icon = CUtil::AddFileToFolder(addonProps.path, "default.tbn");
af8cb2a Revert "wip"
alcoheca authored
469
470 /* Retrieve license */
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
471 element = rootElement->FirstChildElement("license");
af8cb2a Revert "wip"
alcoheca authored
472 /* if (!element)
473 {
474 CLog::Log(LOGERROR, "ADDON: %s missing <license> element, ignoring", strPath.c_str());
475 return false;
476 }
477 addonProps.license = element->GetText();*/
478
479 /* Retrieve platforms which this addon supports */
480 CStdString platform;
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
481 element = rootElement->FirstChildElement("platforms")->FirstChildElement("platform");
af8cb2a Revert "wip"
alcoheca authored
482 if (!element)
483 {
484 CLog::Log(LOGERROR, "ADDON: %s missing <platforms> element, ignoring", strPath.c_str());
485 return false;
486 }
487
488 bool all(false);
489 std::set<CStdString> platforms;
490 do
491 {
492 CStdString platform = element->GetText();
493 if (platform == "all")
494 {
495 all = true;
496 break;
497 }
498 platforms.insert(platform);
499 element = element->NextSiblingElement("platform");
500 } while (element != NULL);
501
502 if (!all)
503 {
504 #if defined(_LINUX) && !defined(__APPLE__)
505 if (!platforms.count("linux"))
506 {
507 CLog::Log(LOGNOTICE, "ADDON: %s is not supported under Linux, ignoring", strPath.c_str());
508 return false;
509 }
510 #elif defined(_WIN32)
511 if (!platforms.count("windows"))
512 {
513 CLog::Log(LOGNOTICE, "ADDON: %s is not supported under Windows, ignoring", strPath.c_str());
514 return false;
515 }
516 #elif defined(__APPLE__)
517 if (!platforms.count("osx"))
518 {
519 CLog::Log(LOGNOTICE, "ADDON: %s is not supported under OSX, ignoring", strPath.c_str());
520 return false;
521 }
522 #elif defined(_XBOX)
523 if (!platforms.count("xbox"))
524 {
525 CLog::Log(LOGNOTICE, "ADDON: %s is not supported under XBOX, ignoring", strPath.c_str());
526 return false;
527 }
528 #endif
529 }
530
531 /* Retrieve summary */
532 CStdString summary;
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
533 element = rootElement->FirstChildElement("summary");
af8cb2a Revert "wip"
alcoheca authored
534 if (!element)
535 {
536 CLog::Log(LOGERROR, "ADDON: %s missing <summary> element, ignoring", strPath.c_str());
537 return false;
538 }
539 addonProps.summary = element->GetText();
540
541 if (addonProps.type == ADDON_SCRAPER || addonProps.type == ADDON_PLUGIN)
542 {
543 /* Retrieve content types that this addon supports */
544 CStdString platform;
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
545 if (rootElement->FirstChildElement("supportedcontent"))
af8cb2a Revert "wip"
alcoheca authored
546 {
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
547 element = rootElement->FirstChildElement("supportedcontent")->FirstChildElement("content");
af8cb2a Revert "wip"
alcoheca authored
548 }
549 if (!element)
550 {
551 CLog::Log(LOGERROR, "ADDON: %s missing <supportedcontent> element, ignoring", strPath.c_str());
552 return false;
553 }
554
555 std::set<CONTENT_TYPE> contents;
556 do
557 {
558 CONTENT_TYPE content = TranslateContent(element->GetText());
559 if (content != CONTENT_NONE)
560 {
561 contents.insert(content);
562 }
563 element = element->NextSiblingElement("content");
564 } while (element != NULL);
565
566 if (contents.empty())
567 {
568 CLog::Log(LOGERROR, "ADDON: %s %s supports no available content-types, ignoring", TranslateType(addonProps.type).c_str(), addonProps.name.c_str());
569 return false;
570 }
571 else
572 {
573 addonProps.contents = contents;
574 }
575 }
576
577 /*** Beginning of optional fields ***/
578 /* Retrieve description */
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
579 element = rootElement->FirstChildElement("description");
af8cb2a Revert "wip"
alcoheca authored
580 if (element)
581 addonProps.description = element->GetText();
582
583 /* Retrieve author */
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
584 element = rootElement->FirstChildElement("author");
af8cb2a Revert "wip"
alcoheca authored
585 if (element)
586 addonProps.author = element->GetText();
587
588 /* Retrieve disclaimer */
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
589 element = rootElement->FirstChildElement("disclaimer");
af8cb2a Revert "wip"
alcoheca authored
590 if (element)
591 addonProps.disclaimer = element->GetText();
592
593 /* Retrieve library file name */
594 // will be replaced with default library name if unspecified
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
595 element = rootElement->FirstChildElement("library");
af8cb2a Revert "wip"
alcoheca authored
596 if (element)
597 addonProps.libname = element->GetText();
598
599 //TODO move this to addon specific class, if it's needed at all..
600 #ifdef _WIN32
601 /* Retrieve WIN32 library file name in case it is present
602 * This is required for no overwrite to the fixed WIN32 add-on's
603 * during compile time
604 */
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
605 element = rootElement->FirstChildElement("librarywin32");
af8cb2a Revert "wip"
alcoheca authored
606 if (element) // If it is found overwrite standard library name
607 addonProps.libname = element->GetText();
608 #endif
609
610 /* Retrieve dependencies that this addon requires */
611 std::map<CStdString, std::pair<const AddonVersion, const AddonVersion> > deps;
4ccec44 changed: refactor addon info loading to make it reusable elsewhere
spiff_ authored
612 element = rootElement->FirstChildElement("dependencies");
af8cb2a Revert "wip"
alcoheca authored
613 if (element)
614 {
615 element = element->FirstChildElement("dependency");
616 if (!element)
617 CLog::Log(LOGDEBUG, "ADDON: %s missing at least one <dependency> element, will ignore this dependency", strPath.c_str());
618 else
619 {
620 do
621 {
622 CStdString min = element->Attribute("minversion");
623 CStdString max = element->Attribute("maxversion");
624 CStdString id = element->GetText();
625 if (!id || (!min && ! max))
626 {
627 CLog::Log(LOGDEBUG, "ADDON: %s malformed <dependency> element, will ignore this dependency", strPath.c_str());
628 continue;
629 }
630 deps.insert(std::make_pair(id, std::make_pair(AddonVersion(min), AddonVersion(max))));
631 element = element->NextSiblingElement("dependency");
632 } while (element != NULL);
633 addonProps.dependencies = deps;
634 }
635 }
636
637 /*** end of optional fields ***/
638
639 /* Create an addon object and store in a shared_ptr */
eca3c5b changed: refactor
spiff_ authored
640 addon = AddonFromProps(addonProps);
641
642 return addon.get() != NULL;
643 }
644
645 AddonPtr CAddonMgr::AddonFromProps(AddonProps& addonProps)
646 {
647 switch (addonProps.type)
af8cb2a Revert "wip"
alcoheca authored
648 {
649 case ADDON_PLUGIN:
650 case ADDON_SCRIPT:
eca3c5b changed: refactor
spiff_ authored
651 return AddonPtr(new CAddon(addonProps));
af8cb2a Revert "wip"
alcoheca authored
652 case ADDON_SCRAPER:
eca3c5b changed: refactor
spiff_ authored
653 return AddonPtr(new CScraper(addonProps));
af8cb2a Revert "wip"
alcoheca authored
654 case ADDON_VIZ:
eca3c5b changed: refactor
spiff_ authored
655 return AddonPtr(new CVisualisation(addonProps));
af8cb2a Revert "wip"
alcoheca authored
656 case ADDON_SCREENSAVER:
eca3c5b changed: refactor
spiff_ authored
657 return AddonPtr(new CScreenSaver(addonProps));
af8cb2a Revert "wip"
alcoheca authored
658 case ADDON_SCRAPER_LIBRARY:
659 case ADDON_VIZ_LIBRARY:
eca3c5b changed: refactor
spiff_ authored
660 return AddonPtr(new CAddonLibrary(addonProps));
af8cb2a Revert "wip"
alcoheca authored
661 default:
eca3c5b changed: refactor
spiff_ authored
662 break;
af8cb2a Revert "wip"
alcoheca authored
663 }
eca3c5b changed: refactor
spiff_ authored
664 return AddonPtr();
af8cb2a Revert "wip"
alcoheca authored
665 }
666
074db86 merged: addons-fw branch
elupus authored
667 } /* namespace ADDON */
668
Something went wrong with that request. Please try again.