2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
22 #include "AddonsDirectory.h"
23 #include "addons/AddonDatabase.h"
24 #include "DirectoryFactory.h"
25 #include "Directory.h"
26 #include "DirectoryCache.h"
28 #include "addons/Repository.h"
29 #include "addons/AddonInstaller.h"
30 #include "addons/PluginSource.h"
31 #include "guilib/TextureManager.h"
33 #include "SpecialProtocol.h"
34 #include "utils/URIUtils.h"
35 #include "utils/StringUtils.h"
38 using namespace ADDON
;
43 CAddonsDirectory::CAddonsDirectory(void)
47 CAddonsDirectory::~CAddonsDirectory(void)
50 bool CAddonsDirectory::GetDirectory(const CStdString
& strPath
, CFileItemList
&items
)
52 CStdString
path1(strPath
);
53 URIUtils::RemoveSlashAtEnd(path1
);
55 items
.ClearProperties();
57 items
.SetContent("addons");
60 // get info from repository
61 bool groupAddons
= true;
62 bool reposAsFolders
= true;
63 if (path
.GetHostName().Equals("enabled"))
65 CAddonMgr::Get().GetAllAddons(addons
, true);
66 items
.SetProperty("reponame",g_localizeStrings
.Get(24062));
67 items
.SetLabel(g_localizeStrings
.Get(24062));
69 else if (path
.GetHostName().Equals("disabled"))
70 { // grab all disabled addons, including disabled repositories
71 reposAsFolders
= false;
73 CAddonMgr::Get().GetAllAddons(addons
, false, true);
74 items
.SetProperty("reponame",g_localizeStrings
.Get(24039));
75 items
.SetLabel(g_localizeStrings
.Get(24039));
77 else if (path
.GetHostName().Equals("outdated"))
79 reposAsFolders
= false;
81 CAddonMgr::Get().GetAllOutdatedAddons(addons
);
82 items
.SetProperty("reponame",g_localizeStrings
.Get(24043));
83 items
.SetLabel(g_localizeStrings
.Get(24043));
85 else if (path
.GetHostName().Equals("repos"))
88 CAddonMgr::Get().GetAddons(ADDON_REPOSITORY
,addons
,true);
89 items
.SetLabel(g_localizeStrings
.Get(24033)); // Get Add-ons
91 else if (path
.GetHostName().Equals("sources"))
93 return GetScriptsAndPlugins(path
.GetFileName(), items
);
95 else if (path
.GetHostName().Equals("all"))
97 CAddonDatabase database
;
99 database
.GetAddons(addons
);
100 items
.SetProperty("reponame",g_localizeStrings
.Get(24032));
101 items
.SetLabel(g_localizeStrings
.Get(24032));
103 else if (path
.GetHostName().Equals("search"))
105 CStdString
search(path
.GetFileName());
106 if (search
.empty() && !GetKeyboardInput(16017, search
))
109 items
.SetProperty("reponame",g_localizeStrings
.Get(283));
110 items
.SetLabel(g_localizeStrings
.Get(283));
112 CAddonDatabase database
;
114 database
.Search(search
, addons
);
115 GenerateListing(path
, addons
, items
, true);
117 path
.SetFileName(search
);
118 items
.SetPath(path
.Get());
123 reposAsFolders
= false;
125 CAddonMgr::Get().GetAddon(path
.GetHostName(),addon
);
129 // ensure our repos are up to date
130 CAddonInstaller::Get().UpdateRepos(false, true);
131 CAddonDatabase database
;
133 database
.GetRepository(addon
->ID(),addons
);
134 items
.SetProperty("reponame",addon
->Name());
135 items
.SetLabel(addon
->Name());
138 if (path
.GetFileName().empty())
142 for (int i
=ADDON_UNKNOWN
+1;i
<ADDON_VIZ_LIBRARY
;++i
)
144 for (unsigned int j
=0;j
<addons
.size();++j
)
146 if (addons
[j
]->IsType((TYPE
)i
))
148 CFileItemPtr
item(new CFileItem(TranslateType((TYPE
)i
,true)));
149 item
->SetPath(URIUtils::AddFileToFolder(strPath
,TranslateType((TYPE
)i
,false)));
150 item
->m_bIsFolder
= true;
151 CStdString thumb
= GetIcon((TYPE
)i
);
152 if (!thumb
.empty() && g_TextureManager
.HasTexture(thumb
))
153 item
->SetArt("thumb", thumb
);
159 items
.SetPath(strPath
);
165 TYPE type
= TranslateType(path
.GetFileName());
166 items
.SetProperty("addoncategory",TranslateType(type
, true));
167 items
.SetLabel(TranslateType(type
, true));
168 items
.SetPath(strPath
);
170 // FIXME: Categorisation of addons needs adding here
171 for (unsigned int j
=0;j
<addons
.size();++j
)
173 if (!addons
[j
]->IsType(type
))
174 addons
.erase(addons
.begin()+j
--);
178 items
.SetPath(strPath
);
179 GenerateListing(path
, addons
, items
, reposAsFolders
);
180 // check for available updates
181 if (path
.GetHostName().Equals("enabled"))
183 CAddonDatabase database
;
185 for (int i
=0;i
<items
.Size();++i
)
188 database
.GetAddon(items
[i
]->GetProperty("Addon.ID").asString(),addon2
);
189 if (addon2
&& addon2
->Version() > AddonVersion(items
[i
]->GetProperty("Addon.Version").asString())
190 && !database
.IsAddonBlacklisted(addon2
->ID(),addon2
->Version().c_str()))
192 items
[i
]->SetProperty("Addon.Status",g_localizeStrings
.Get(24068));
193 items
[i
]->SetProperty("Addon.UpdateAvail", true);
197 if (path
.GetHostName().Equals("repos") && items
.Size() > 1)
199 CFileItemPtr
item(new CFileItem("addons://all/",true));
200 item
->SetLabel(g_localizeStrings
.Get(24032));
203 else if (path
.GetHostName().Equals("outdated") && items
.Size() > 1)
205 CFileItemPtr
item(new CFileItem("addons://update_all/", true));
206 item
->SetLabel(g_localizeStrings
.Get(24122));
207 item
->SetSpecialSort(SortSpecialOnTop
);
214 void CAddonsDirectory::GenerateListing(CURL
&path
, VECADDONS
& addons
, CFileItemList
&items
, bool reposAsFolders
)
216 CStdString xbmcPath
= CSpecialProtocol::TranslatePath("special://xbmc/addons");
218 for (unsigned i
=0; i
< addons
.size(); i
++)
220 AddonPtr addon
= addons
[i
];
222 if (reposAsFolders
&& addon
->Type() == ADDON_REPOSITORY
)
223 pItem
= FileItemFromAddon(addon
, "addons://", true);
225 pItem
= FileItemFromAddon(addon
, path
.Get(), false);
227 if (CAddonMgr::Get().GetAddon(addon
->ID(),addon2
))
228 pItem
->SetProperty("Addon.Status",g_localizeStrings
.Get(305));
229 else if (CAddonMgr::Get().IsAddonDisabled(addon
->ID()))
230 pItem
->SetProperty("Addon.Status",g_localizeStrings
.Get(24023));
232 if (addon
->Props().broken
== "DEPSNOTMET")
233 pItem
->SetProperty("Addon.Status",g_localizeStrings
.Get(24049));
234 else if (!addon
->Props().broken
.empty())
235 pItem
->SetProperty("Addon.Status",g_localizeStrings
.Get(24098));
236 if (addon2
&& addon2
->Version() < addon
->Version())
238 pItem
->SetProperty("Addon.Status",g_localizeStrings
.Get(24068));
239 pItem
->SetProperty("Addon.UpdateAvail", true);
241 CAddonDatabase::SetPropertiesFromAddon(addon
,pItem
);
246 CFileItemPtr
CAddonsDirectory::FileItemFromAddon(const AddonPtr
&addon
, const CStdString
&basePath
, bool folder
)
249 return CFileItemPtr();
251 // TODO: This can probably be done more efficiently
253 url
.SetFileName(addon
->ID());
254 CStdString
path(url
.Get());
256 URIUtils::AddSlashAtEnd(path
);
258 CFileItemPtr
item(new CFileItem(path
, folder
));
260 CStdString
strLabel(addon
->Name());
261 if (url
.GetHostName().Equals("search"))
262 strLabel
= StringUtils::Format("%s - %s", TranslateType(addon
->Type(), true).c_str(), addon
->Name().c_str());
264 item
->SetLabel(strLabel
);
266 if (!(basePath
.Equals("addons://") && addon
->Type() == ADDON_REPOSITORY
))
267 item
->SetLabel2(addon
->Version().c_str());
268 item
->SetArt("thumb", addon
->Icon());
269 item
->SetLabelPreformated(true);
270 item
->SetIconImage("DefaultAddon.png");
271 if (URIUtils::IsInternetStream(addon
->FanArt()) || CFile::Exists(addon
->FanArt()))
272 item
->SetArt("fanart", addon
->FanArt());
273 CAddonDatabase::SetPropertiesFromAddon(addon
, item
);
277 bool CAddonsDirectory::GetScriptsAndPlugins(const CStdString
&content
, VECADDONS
&addons
)
279 CPluginSource::Content type
= CPluginSource::Translate(content
);
280 if (type
== CPluginSource::UNKNOWN
)
283 VECADDONS tempAddons
;
284 CAddonMgr::Get().GetAddons(ADDON_PLUGIN
, tempAddons
);
285 for (unsigned i
=0; i
<tempAddons
.size(); i
++)
287 PluginPtr plugin
= boost::dynamic_pointer_cast
<CPluginSource
>(tempAddons
[i
]);
288 if (plugin
&& plugin
->Provides(type
))
289 addons
.push_back(tempAddons
[i
]);
292 CAddonMgr::Get().GetAddons(ADDON_SCRIPT
, tempAddons
);
293 for (unsigned i
=0; i
<tempAddons
.size(); i
++)
295 PluginPtr plugin
= boost::dynamic_pointer_cast
<CPluginSource
>(tempAddons
[i
]);
296 if (plugin
&& plugin
->Provides(type
))
297 addons
.push_back(tempAddons
[i
]);
302 bool CAddonsDirectory::GetScriptsAndPlugins(const CStdString
&content
, CFileItemList
&items
)
307 if (!GetScriptsAndPlugins(content
, addons
))
310 for (unsigned i
=0; i
<addons
.size(); i
++)
312 CFileItemPtr
item(FileItemFromAddon(addons
[i
],
313 addons
[i
]->Type()==ADDON_PLUGIN
?"plugin://":"script://",
314 addons
[i
]->Type() == ADDON_PLUGIN
));
315 PluginPtr plugin
= boost::dynamic_pointer_cast
<CPluginSource
>(addons
[i
]);
316 if (plugin
->ProvidesSeveral())
318 CURL url
= item
->GetAsUrl();
319 CStdString opt
= StringUtils::Format("?content_type=%s",content
.c_str());
321 item
->SetPath(url
.Get());
326 items
.Add(GetMoreItem(content
));
328 items
.SetContent("addons");
329 items
.SetLabel(g_localizeStrings
.Get(24001)); // Add-ons
331 return items
.Size() > 0;
334 CFileItemPtr
CAddonsDirectory::GetMoreItem(const CStdString
&content
)
336 CFileItemPtr
item(new CFileItem("addons://more/"+content
,false));
337 item
->SetLabelPreformated(true);
338 item
->SetLabel(g_localizeStrings
.Get(21452));
339 item
->SetIconImage("DefaultAddon.png");
340 item
->SetSpecialSort(SortSpecialOnBottom
);