Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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