2 * Copyright (C) 2011-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, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
22 #include "AddonsOperations.h"
23 #include "JSONUtils.h"
24 #include "addons/AddonManager.h"
25 #include "addons/AddonDatabase.h"
26 #include "addons/PluginSource.h"
27 #include "ApplicationMessenger.h"
28 #include "TextureCache.h"
29 #include "filesystem/File.h"
32 using namespace JSONRPC;
33 using namespace ADDON;
34 using namespace XFILE;
36 JSONRPC_STATUS CAddonsOperations::GetAddons(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result)
38 vector<TYPE> addonTypes;
39 TYPE addonType = TranslateType(parameterObject["type"].asString());
40 CPluginSource::Content content = CPluginSource::Translate(parameterObject["content"].asString());
41 CVariant enabled = parameterObject["enabled"];
43 // ignore the "content" parameter if the type is specified but not a plugin or script
44 if (addonType != ADDON_UNKNOWN && addonType != ADDON_PLUGIN && addonType != ADDON_SCRIPT)
45 content = CPluginSource::UNKNOWN;
47 if (addonType >= ADDON_VIDEO && addonType <= ADDON_EXECUTABLE)
49 addonTypes.push_back(ADDON_PLUGIN);
50 addonTypes.push_back(ADDON_SCRIPT);
55 content = CPluginSource::VIDEO;
58 content = CPluginSource::AUDIO;
61 content = CPluginSource::IMAGE;
63 case ADDON_EXECUTABLE:
64 content = CPluginSource::EXECUTABLE;
72 addonTypes.push_back(addonType);
75 for (vector<TYPE>::const_iterator typeIt = addonTypes.begin(); typeIt != addonTypes.end(); typeIt++)
78 if (*typeIt == ADDON_UNKNOWN)
80 if (!enabled.isBoolean())
82 CAddonMgr::Get().GetAllAddons(typeAddons, false);
83 CAddonMgr::Get().GetAllAddons(typeAddons, true);
86 CAddonMgr::Get().GetAllAddons(typeAddons, enabled.asBoolean());
90 if (!enabled.isBoolean())
92 CAddonMgr::Get().GetAddons(*typeIt, typeAddons, false);
93 VECADDONS enabledAddons;
94 CAddonMgr::Get().GetAddons(*typeIt, enabledAddons, true);
95 typeAddons.insert(typeAddons.end(), enabledAddons.begin(), enabledAddons.end());
98 CAddonMgr::Get().GetAddons(*typeIt, typeAddons, enabled.asBoolean());
101 addons.insert(addons.end(), typeAddons.begin(), typeAddons.end());
104 // remove library addons
105 for (int index = 0; index < (int)addons.size(); index++)
108 if (content != CPluginSource::UNKNOWN)
109 plugin = boost::dynamic_pointer_cast<CPluginSource>(addons.at(index));
111 if ((addons.at(index)->Type() <= ADDON_UNKNOWN || addons.at(index)->Type() >= ADDON_VIZ_LIBRARY) ||
112 ((content != CPluginSource::UNKNOWN && plugin == NULL) || (plugin != NULL && !plugin->Provides(content))))
114 addons.erase(addons.begin() + index);
120 HandleLimits(parameterObject, result, addons.size(), start, end);
122 CAddonDatabase addondb;
123 for (int index = start; index < end; index++)
124 FillDetails(addons.at(index), parameterObject["properties"], result["addons"], addondb, true);
129 JSONRPC_STATUS CAddonsOperations::GetAddonDetails(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result)
131 string id = parameterObject["addonid"].asString();
133 if (!CAddonMgr::Get().GetAddon(id, addon, ADDON::ADDON_UNKNOWN, false) || addon.get() == NULL ||
134 addon->Type() <= ADDON_UNKNOWN || addon->Type() >= ADDON_VIZ_LIBRARY)
135 return InvalidParams;
137 CAddonDatabase addondb;
138 FillDetails(addon, parameterObject["properties"], result["addon"], addondb);
143 JSONRPC_STATUS CAddonsOperations::SetAddonEnabled(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result)
145 CAddonDatabase addondatabase;
146 if (!addondatabase.Open())
147 return InternalError;
149 string id = parameterObject["addonid"].asString();
150 bool disabled = false;
151 if (parameterObject["enabled"].isBoolean())
152 disabled = !parameterObject["enabled"].asBoolean();
153 // we need to toggle the current disabled state of the addon
154 else if (parameterObject["enabled"].isString())
155 disabled = !addondatabase.IsAddonDisabled(id);
157 return InvalidParams;
159 if (!addondatabase.DisableAddon(id, disabled))
160 return InvalidParams;
165 JSONRPC_STATUS CAddonsOperations::ExecuteAddon(const CStdString &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result)
167 string id = parameterObject["addonid"].asString();
169 if (!CAddonMgr::Get().GetAddon(id, addon) || addon.get() == NULL ||
170 addon->Type() < ADDON_VIZ || addon->Type() >= ADDON_VIZ_LIBRARY)
171 return InvalidParams;
174 CVariant params = parameterObject["params"];
175 if (params.isObject())
177 for (CVariant::const_iterator_map it = params.begin_map(); it != params.end_map(); it++)
179 if (it != params.begin_map())
181 argv += it->first + "=" + it->second.asString();
184 else if (params.isArray())
186 for (CVariant::const_iterator_array it = params.begin_array(); it != params.end_array(); it++)
188 if (it != params.begin_array())
190 argv += it->asString();
195 if (params.size() == 0)
196 cmd.Format("RunAddon(%s)", id.c_str());
198 cmd.Format("RunAddon(%s, %s)", id.c_str(), argv.c_str());
199 CApplicationMessenger::Get().ExecBuiltIn(cmd, parameterObject["wait"].asBoolean());
204 void CAddonsOperations::FillDetails(AddonPtr addon, const CVariant& fields, CVariant &result, CAddonDatabase &addondb, bool append /* = false */)
206 if (addon.get() == NULL)
210 addon->Props().Serialize(addonInfo);
213 object["addonid"] = addonInfo["addonid"];
214 object["type"] = addonInfo["type"];
216 for (unsigned int index = 0; index < fields.size(); index++)
218 string field = fields[index].asString();
220 // we need to manually retrieve the enabled state of every addon
221 // from the addon database because it can't be read from addon.xml
222 if (field == "enabled")
224 if (!addondb.IsOpen() && !addondb.Open())
226 object[field] = !addondb.IsAddonDisabled(addon->ID());
228 else if (field == "fanart" || field == "thumbnail")
230 CStdString url = addonInfo[field].asString();
231 // We need to check the existence of fanart and thumbnails as the addon simply
232 // holds where the art will be, not whether it exists.
234 CStdString image = CTextureCache::Get().CheckCachedImage(url, false, needsRecaching);
235 if (!image.empty() || CFile::Exists(url))
236 object[field] = CTextureCache::Get().GetWrappedImageURL(url);
240 else if (addonInfo.isMember(field))
241 object[field] = addonInfo[field];
245 result.append(object);