void CAddonsDirectory::GenerateListing(CURL &path, VECADDONS& addons, CFileItemList &items, bool reposAsFolders) { CStdString xbmcPath = CSpecialProtocol::TranslatePath("special://xbmc/addons"); items.ClearItems(); for (unsigned i=0; i < addons.size(); i++) { AddonPtr addon = addons[i]; CFileItemPtr pItem; if (reposAsFolders && addon->Type() == ADDON_REPOSITORY) pItem = FileItemFromAddon(addon, "addons://", true); else pItem = FileItemFromAddon(addon, path.Get(), false); AddonPtr addon2; if (CAddonMgr::Get().GetAddon(addon->ID(),addon2)) pItem->SetProperty("Addon.Status",g_localizeStrings.Get(305)); else if ((addon->Type() == ADDON_PVRDLL) && (CStdString(pItem->GetProperty("Addon.Path").asString()).Left(xbmcPath.size()).Equals(xbmcPath))) pItem->SetProperty("Addon.Status",g_localizeStrings.Get(24023)); if (!addon->Props().broken.IsEmpty()) pItem->SetProperty("Addon.Status",g_localizeStrings.Get(24098)); if (addon2 && addon2->Version() < addon->Version()) { pItem->SetProperty("Addon.Status",g_localizeStrings.Get(24068)); pItem->SetProperty("Addon.UpdateAvail", true); } CAddonDatabase::SetPropertiesFromAddon(addon,pItem); items.Add(pItem); } }
bool CAddonDatabase::SearchTitle(const CStdString& search, VECADDONS& addons) { try { if (NULL == m_pDB.get()) return false; if (NULL == m_pDS.get()) return false; CStdString strSQL; strSQL=PrepareSQL("select idAddon from addon where name like '%s%%'", search.c_str()); if (!m_pDS->query(strSQL.c_str())) return false; if (m_pDS->num_rows() == 0) return false; while (!m_pDS->eof()) { AddonPtr addon; GetAddon(m_pDS->fv(0).get_asInt(),addon); if (addon->Type() >= ADDON_UNKNOWN+1 && addon->Type() < ADDON_SCRAPER_LIBRARY) addons.push_back(addon); m_pDS->next(); } m_pDS->close(); return true; } catch (...) { CLog::Log(LOGERROR, "%s failed", __FUNCTION__); } return false; }
bool CAddonDatabase::Search(const std::string& search, VECADDONS& addons) { try { if (NULL == m_pDB.get()) return false; if (NULL == m_pDS.get()) return false; std::string strSQL; strSQL=PrepareSQL("SELECT addonID FROM addon WHERE name LIKE '%%%s%%' OR summary LIKE '%%%s%%' OR description LIKE '%%%s%%'", search.c_str(), search.c_str(), search.c_str()); CLog::Log(LOGDEBUG, "%s query: %s", __FUNCTION__, strSQL.c_str()); if (!m_pDS->query(strSQL.c_str())) return false; if (m_pDS->num_rows() == 0) return false; while (!m_pDS->eof()) { AddonPtr addon; GetAddon(m_pDS->fv(0).get_asString(),addon); if (addon->Type() >= ADDON_UNKNOWN+1 && addon->Type() < ADDON_SCRAPER_LIBRARY) addons.push_back(addon); m_pDS->next(); } m_pDS->close(); return true; } catch (...) { CLog::Log(LOGERROR, "%s failed", __FUNCTION__); } return false; }
CFileItemPtr CAddonsDirectory::FileItemFromAddon(AddonPtr &addon, const CStdString &basePath, bool folder) { if (!addon) return CFileItemPtr(); // TODO: This can probably be done more efficiently CURL url(basePath); url.SetFileName(addon->ID()); CStdString path(url.Get()); if (folder) URIUtils::AddSlashAtEnd(path); CFileItemPtr item(new CFileItem(path, folder)); CStdString strLabel(addon->Name()); if (url.GetHostName().Equals("search")) strLabel.Format("%s - %s", TranslateType(addon->Type(), true), addon->Name()); item->SetLabel(strLabel); if (!(basePath.Equals("addons://") && addon->Type() == ADDON_REPOSITORY)) item->SetLabel2(addon->Version().c_str()); item->SetArt("thumb", addon->Icon()); item->SetLabelPreformated(true); item->SetIconImage("DefaultAddon.png"); if (!addon->FanArt().IsEmpty() && (URIUtils::IsInternetStream(addon->FanArt()) || CFile::Exists(addon->FanArt()))) { item->SetArt("fanart", addon->FanArt()); } CAddonDatabase::SetPropertiesFromAddon(addon, item); return item; }
void CAddonDatabase::SetPropertiesFromAddon(const AddonPtr& addon, CFileItemPtr& pItem) { pItem->SetProperty("Addon.ID", addon->ID()); pItem->SetProperty("Addon.Type", TranslateType(addon->Type(),true)); pItem->SetProperty("Addon.intType", TranslateType(addon->Type())); pItem->SetProperty("Addon.Name", addon->Name()); pItem->SetProperty("Addon.Version", addon->Version().asString()); pItem->SetProperty("Addon.Summary", addon->Summary()); pItem->SetProperty("Addon.Description", addon->Description()); pItem->SetProperty("Addon.Creator", addon->Author()); pItem->SetProperty("Addon.Disclaimer", addon->Disclaimer()); pItem->SetProperty("Addon.Rating", addon->Stars()); std::string starrating = StringUtils::Format("rating%d.png", addon->Stars()); pItem->SetProperty("Addon.StarRating",starrating); pItem->SetProperty("Addon.Path", addon->Path()); if (addon->Props().broken == "DEPSNOTMET") pItem->SetProperty("Addon.Broken", g_localizeStrings.Get(24044)); else pItem->SetProperty("Addon.Broken", addon->Props().broken); std::map<std::string,std::string>::iterator it = addon->Props().extrainfo.find("language"); if (it != addon->Props().extrainfo.end()) pItem->SetProperty("Addon.Language", it->second); }
int CAddonDatabase::AddAddon(const AddonPtr& addon, int idRepo) { try { if (NULL == m_pDB.get()) return -1; if (NULL == m_pDS.get()) return -1; bool bDisablePVRAddon = addon->Type() == ADDON_PVRDLL && !HasAddon(addon->ID()); CStdString sql = PrepareSQL("insert into addon (id, type, name, summary," "description, stars, path, icon, changelog, " "fanart, addonID, version, author, disclaimer, minversion)" " values(NULL, '%s', '%s', '%s', '%s', %i," "'%s', '%s', '%s', '%s', '%s','%s','%s','%s','%s')", TranslateType(addon->Type(),false).c_str(), addon->Name().c_str(), addon->Summary().c_str(), addon->Description().c_str(),addon->Stars(), addon->Path().c_str(), addon->Props().icon.c_str(), addon->ChangeLog().c_str(),addon->FanArt().c_str(), addon->ID().c_str(), addon->Version().c_str(), addon->Author().c_str(),addon->Disclaimer().c_str(), addon->MinVersion().c_str()); m_pDS->exec(sql.c_str()); int idAddon = (int)m_pDS->lastinsertid(); sql = PrepareSQL("insert into addonlinkrepo (idRepo, idAddon) values (%i,%i)",idRepo,idAddon); m_pDS->exec(sql.c_str()); const InfoMap &info = addon->ExtraInfo(); for (InfoMap::const_iterator i = info.begin(); i != info.end(); ++i) { sql = PrepareSQL("insert into addonextra(id, key, value) values (%i, '%s', '%s')", idAddon, i->first.c_str(), i->second.c_str()); m_pDS->exec(sql.c_str()); } const ADDONDEPS &deps = addon->GetDeps(); for (ADDONDEPS::const_iterator i = deps.begin(); i != deps.end(); ++i) { sql = PrepareSQL("insert into dependencies(id, addon, version, optional) values (%i, '%s', '%s', %i)", idAddon, i->first.c_str(), i->second.first.c_str(), i->second.second ? 1 : 0); m_pDS->exec(sql.c_str()); } // these need to be configured if (bDisablePVRAddon) DisableAddon(addon->ID(), true); return idAddon; } catch (...) { CLog::Log(LOGERROR, "%s failed on addon '%s'", __FUNCTION__, addon->Name().c_str()); } return -1; }
JSONRPC_STATUS CAddonsOperations::GetAddonDetails(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result) { std::string id = parameterObject["addonid"].asString(); AddonPtr addon; if (!CServiceBroker::GetAddonMgr().GetAddon(id, addon, ADDON::ADDON_UNKNOWN, false) || addon.get() == NULL || addon->Type() <= ADDON_UNKNOWN || addon->Type() >= ADDON_MAX) return InvalidParams; CAddonDatabase addondb; FillDetails(addon, parameterObject["properties"], result["addon"], addondb); return OK; }
bool CAddonMgr::GetAddon(const CStdString &str, AddonPtr &addon, const TYPE &type/*=ADDON_UNKNOWN*/, bool enabledOnly /*= true*/) { CSingleLock lock(m_critSection); cp_status_t status; cp_plugin_info_t *cpaddon = m_cpluff->get_plugin_info(m_cp_context, str.c_str(), &status); if (status == CP_OK && cpaddon) { addon = GetAddonFromDescriptor(cpaddon, type==ADDON_UNKNOWN?"":TranslateType(type)); m_cpluff->release_info(m_cp_context, cpaddon); if (addon && addon.get()) { if (enabledOnly && m_database.IsAddonDisabled(addon->ID())) return false; if (addon->Type() == ADDON_PVRDLL && g_PVRManager.IsStarted()) { AddonPtr pvrAddon; if (g_PVRClients->GetClient(addon->ID(), pvrAddon)) addon = pvrAddon; } } return NULL != addon.get(); } if (cpaddon) m_cpluff->release_info(m_cp_context, cpaddon); return false; }
bool CAddonMgr::CanAddonBeDisabled(const std::string& ID) { if (ID.empty()) return false; CSingleLock lock(m_critSection); // can't disable an already disabled addon if (IsAddonDisabled(ID)) return false; AddonPtr localAddon; // can't disable an addon that isn't installed if (!IsAddonInstalled(ID, localAddon)) return false; // can't disable an addon that is in use if (localAddon->IsInUse()) return false; // installed PVR addons can always be disabled if (localAddon->Type() == ADDON_PVRDLL) return true; std::string systemAddonsPath = CSpecialProtocol::TranslatePath("special://xbmc/addons"); // can't disable system addons if (StringUtils::StartsWith(localAddon->Path(), systemAddonsPath)) return false; return true; }
void CAddonsDirectory::GenerateListing(CURL &path, VECADDONS& addons, CFileItemList &items, bool reposAsFolders) { items.ClearItems(); for (unsigned i=0; i < addons.size(); i++) { AddonPtr addon = addons[i]; CFileItemPtr pItem; if (reposAsFolders && addon->Type() == ADDON_REPOSITORY) pItem = FileItemFromAddon(addon, "addons://", true); else pItem = FileItemFromAddon(addon, path.Get(), false); AddonPtr addon2; if (CAddonMgr::Get().GetAddon(addon->ID(),addon2)) pItem->SetProperty("Addon.Status",g_localizeStrings.Get(305)); else if (CAddonMgr::Get().IsAddonDisabled(addon->ID())) pItem->SetProperty("Addon.Status",g_localizeStrings.Get(24023)); if (addon->Props().broken == "DEPSNOTMET") pItem->SetProperty("Addon.Status",g_localizeStrings.Get(24049)); else if (!addon->Props().broken.empty()) pItem->SetProperty("Addon.Status",g_localizeStrings.Get(24098)); if (addon2 && addon2->Version() < addon->Version()) { pItem->SetProperty("Addon.Status",g_localizeStrings.Get(24068)); pItem->SetProperty("Addon.UpdateAvail", true); } CAddonDatabase::SetPropertiesFromAddon(addon,pItem); items.Add(pItem); } }
bool CAddonMgr::GetAddon(const CStdString &str, AddonPtr &addon, const TYPE &type/*=ADDON_UNKNOWN*/, bool enabledOnly /*= true*/) { CSingleLock lock(m_critSection); CStdString xbmcPath = _P("special://xbmc/addons"); cp_status_t status; cp_plugin_info_t *cpaddon = m_cpluff->get_plugin_info(m_cp_context, str.c_str(), &status); if (status == CP_OK && cpaddon) { addon = GetAddonFromDescriptor(cpaddon); m_cpluff->release_info(m_cp_context, cpaddon); if (addon && addon.get() && enabledOnly) { if (addon->Type() == ADDON_PVRDLL && addon->Path().Left(xbmcPath.size()).Equals(xbmcPath)) { if (!m_database.IsSystemPVRAddonEnabled(addon->ID())) return false; } else if (m_database.IsAddonDisabled(addon->ID())) return false; } return NULL != addon.get(); } if (cpaddon) m_cpluff->release_info(m_cp_context, cpaddon); return false; }
JSONRPC_STATUS CAddonsOperations::ExecuteAddon(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result) { std::string id = parameterObject["addonid"].asString(); AddonPtr addon; if (!CServiceBroker::GetAddonMgr().GetAddon(id, addon) || addon.get() == NULL || addon->Type() < ADDON_VIZ || addon->Type() >= ADDON_MAX) return InvalidParams; std::string argv; CVariant params = parameterObject["params"]; if (params.isObject()) { for (CVariant::const_iterator_map it = params.begin_map(); it != params.end_map(); it++) { if (it != params.begin_map()) argv += ","; argv += it->first + "=" + it->second.asString(); } } else if (params.isArray()) { for (CVariant::const_iterator_array it = params.begin_array(); it != params.end_array(); it++) { if (it != params.begin_array()) argv += ","; argv += StringUtils::Paramify(it->asString()); } } else if (params.isString()) { if (!params.empty()) argv = StringUtils::Paramify(params.asString()); } std::string cmd; if (params.empty()) cmd = StringUtils::Format("RunAddon(%s)", id.c_str()); else cmd = StringUtils::Format("RunAddon(%s, %s)", id.c_str(), argv.c_str()); if (params["wait"].asBoolean()) CApplicationMessenger::GetInstance().SendMsg(TMSG_EXECUTE_BUILT_IN, -1, -1, nullptr, cmd); else CApplicationMessenger::GetInstance().PostMsg(TMSG_EXECUTE_BUILT_IN, -1, -1, nullptr, cmd); return ACK; }
void CAddonDatabase::SetPropertiesFromAddon(const AddonPtr& addon, CFileItemPtr& pItem) { pItem->SetProperty("Addon.ID", addon->ID()); pItem->SetProperty("Addon.Type", TranslateType(addon->Type(),true)); pItem->SetProperty("Addon.intType", TranslateType(addon->Type())); pItem->SetProperty("Addon.Name", addon->Name()); pItem->SetProperty("Addon.Version", addon->Version().c_str()); pItem->SetProperty("Addon.Summary", addon->Summary()); pItem->SetProperty("Addon.Description", addon->Description()); pItem->SetProperty("Addon.Creator", addon->Author()); pItem->SetProperty("Addon.Disclaimer", addon->Disclaimer()); pItem->SetProperty("Addon.Rating", addon->Stars()); CStdString starrating; starrating.Format("rating%d.png", addon->Stars()); pItem->SetProperty("Addon.StarRating",starrating); pItem->SetProperty("Addon.Path", addon->Path()); pItem->SetProperty("Addon.Broken", addon->Props().broken); }
JSONRPC_STATUS CAddonsOperations::SetAddonEnabled(const std::string &method, ITransportLayer *transport, IClient *client, const CVariant ¶meterObject, CVariant &result) { std::string id = parameterObject["addonid"].asString(); AddonPtr addon; if (!CServiceBroker::GetAddonMgr().GetAddon(id, addon, ADDON::ADDON_UNKNOWN, false) || addon == nullptr || addon->Type() <= ADDON_UNKNOWN || addon->Type() >= ADDON_MAX) return InvalidParams; bool disabled = false; if (parameterObject["enabled"].isBoolean()) disabled = !parameterObject["enabled"].asBoolean(); // we need to toggle the current disabled state of the addon else if (parameterObject["enabled"].isString()) disabled = !CServiceBroker::GetAddonMgr().IsAddonDisabled(id); else return InvalidParams; bool success = disabled ? CServiceBroker::GetAddonMgr().DisableAddon(id) : CServiceBroker::GetAddonMgr().EnableAddon(id); return success ? ACK : InvalidParams; }
void CAddonDatabase::SetPropertiesFromAddon(const AddonPtr& addon, CFileItemPtr& pItem) { pItem->SetProperty("Addon.ID", addon->ID()); pItem->SetProperty("Addon.Type", TranslateType(addon->Type(),true)); pItem->SetProperty("Addon.intType", TranslateType(addon->Type())); pItem->SetProperty("Addon.Name", addon->Name()); pItem->SetProperty("Addon.Version", addon->Version().c_str()); pItem->SetProperty("Addon.Summary", addon->Summary()); pItem->SetProperty("Addon.Description", addon->Description()); pItem->SetProperty("Addon.Creator", addon->Author()); pItem->SetProperty("Addon.Disclaimer", addon->Disclaimer()); pItem->SetProperty("Addon.Rating", addon->Stars()); CStdString starrating; starrating.Format("rating%d.png", addon->Stars()); pItem->SetProperty("Addon.StarRating",starrating); pItem->SetProperty("Addon.Path", addon->Path()); pItem->SetProperty("Addon.Broken", addon->Props().broken); std::map<CStdString,CStdString>::iterator it = addon->Props().extrainfo.find("language"); if (it != addon->Props().extrainfo.end()) pItem->SetProperty("Addon.Language", it->second); }
bool CAddonSystemSettings::UnsetActive(const AddonPtr& addon) { auto it = m_activeSettings.find(addon->Type()); if (it == m_activeSettings.end()) return true; auto setting = std::static_pointer_cast<CSettingString>(CServiceBroker::GetSettings().GetSetting(it->second)); if (setting->GetValue() != addon->ID()) return true; if (setting->GetDefault() == addon->ID()) return false; // Cant unset defaults setting->Reset(); return true; }
bool CAddonSystemSettings::UnsetActive(const AddonPtr& addon) { auto it = settingMap.find(addon->Type()); if (it == settingMap.end()) return true; auto setting = static_cast<CSettingString*>(CSettings::GetInstance().GetSetting(it->second)); if (setting->GetValue() != addon->ID()) return true; if (setting->GetDefault() == addon->ID()) return false; // Cant unset defaults setting->Reset(); return true; }
int CAddonDatabase::AddAddon(const AddonPtr& addon, int idRepo) { try { if (NULL == m_pDB.get()) return -1; if (NULL == m_pDS.get()) return -1; CStdString sql = PrepareSQL("insert into addon (id, type, name, summary," "description, stars, path, icon, changelog, " "fanart, addonID, version, author, disclaimer)" " values(NULL, '%s', '%s', '%s', '%s', %i," "'%s', '%s', '%s', '%s', '%s','%s','%s','%s')", TranslateType(addon->Type(),false).c_str(), addon->Name().c_str(), addon->Summary().c_str(), addon->Description().c_str(),addon->Stars(), addon->Path().c_str(), addon->Props().icon.c_str(), addon->ChangeLog().c_str(),addon->FanArt().c_str(), addon->ID().c_str(), addon->Version().str.c_str(), addon->Author().c_str(),addon->Disclaimer().c_str()); m_pDS->exec(sql.c_str()); int idAddon = (int)m_pDS->lastinsertid(); sql = PrepareSQL("insert into addonlinkrepo (idRepo, idAddon) values (%i,%i)",idRepo,idAddon); m_pDS->exec(sql.c_str()); const InfoMap &info = addon->ExtraInfo(); for (InfoMap::const_iterator i = info.begin(); i != info.end(); ++i) { sql = PrepareSQL("insert into addonextra(id, key, value) values (%i, '%s', '%s')", idAddon, i->first.c_str(), i->second.c_str()); m_pDS->exec(sql.c_str()); } return idAddon; } catch (...) { CLog::Log(LOGERROR, "%s failed on addon '%s'", __FUNCTION__, addon->Name().c_str()); } return -1; }
static CVariant Serialize(const AddonPtr& addon) { CVariant variant; variant["addonid"] = addon->ID(); variant["type"] = CAddonInfo::TranslateType(addon->Type(), false); variant["name"] = addon->Name(); variant["version"] = addon->Version().asString(); variant["summary"] = addon->Summary(); variant["description"] = addon->Description(); variant["path"] = addon->Path(); variant["author"] = addon->Author(); variant["thumbnail"] = addon->Icon(); variant["disclaimer"] = addon->Disclaimer(); variant["fanart"] = addon->FanArt(); variant["dependencies"] = CVariant(CVariant::VariantTypeArray); for (const auto& dep : addon->GetDependencies()) { CVariant info(CVariant::VariantTypeObject); info["addonid"] = dep.id; info["version"] = dep.requiredVersion.asString(); info["optional"] = dep.optional; variant["dependencies"].push_back(std::move(info)); } if (addon->Broken().empty()) variant["broken"] = false; else variant["broken"] = addon->Broken(); variant["extrainfo"] = CVariant(CVariant::VariantTypeArray); for (const auto& kv : addon->ExtraInfo()) { CVariant info(CVariant::VariantTypeObject); info["key"] = kv.first; info["value"] = kv.second; variant["extrainfo"].push_back(std::move(info)); } variant["rating"] = -1; return variant; }
void CGUIWindowAddonBrowser::GetContextButtons(int itemNumber, CContextButtons& buttons) { CFileItemPtr pItem = m_vecItems->Get(itemNumber); if (pItem->GetPath().Equals("addons://enabled/")) buttons.Add(CONTEXT_BUTTON_SCAN,24034); AddonPtr addon; if (!CAddonMgr::Get().GetAddon(pItem->GetProperty("Addon.ID").asString(), addon, ADDON_UNKNOWN, false)) // allow disabled addons return; if (addon->Type() == ADDON_REPOSITORY && pItem->m_bIsFolder) { buttons.Add(CONTEXT_BUTTON_SCAN,24034); buttons.Add(CONTEXT_BUTTON_UPDATE_LIBRARY,24035); } buttons.Add(CONTEXT_BUTTON_INFO,24003); if (addon->HasSettings()) buttons.Add(CONTEXT_BUTTON_SETTINGS,24020); }
bool CRetroPlayerDialogs::InstallGameClientDialog(const CFileItem &file, GameClientPtr &result) { VECADDONS addons; CGameManager::GetAllGameClients(addons); map<string, GameClientPtr> candidates; for (VECADDONS::const_iterator itRemote = addons.begin(); itRemote != addons.end(); ++itRemote) { if (!(*itRemote)->IsType(ADDON_GAMEDLL)) continue; GameClientPtr gc = boost::dynamic_pointer_cast<CGameClient>(*itRemote); // Only add game clients to the list if they provide extensions or platforms if (!gc || (gc->GetExtensions().empty() /* && gc->GetPlatforms().empty() */)) continue; if (!gc->CanOpen(file)) continue; // If the game client is already installed and enabled, exclude it from the list AddonPtr addon; if (CAddonMgr::Get().GetAddon(gc->ID(), addon, ADDON_GAMEDLL, true)) continue; // If GetAddon() returns false, but addon is non-NULL, then the add-on exists but is disabled bool bEnabled = (addon.get() == NULL); bool bBroken = !(*itRemote)->Props().broken.empty(); if (bEnabled && bBroken) continue; string strName = gc->Name(); // Append "(Disabled)" to the name if the add-on is disabled if (!bEnabled) strName = StringUtils::Format("%s (%s)", strName.c_str(), g_localizeStrings.Get(1223).c_str()); candidates[strName] = gc; } if (candidates.empty()) { CLog::Log(LOGDEBUG, "RetroPlayer: No compatible game clients for installation"); // "Playback failed" // "No compatible emulators found for file:" // "FILENAME" CGUIDialogOK::ShowAndGetInput(16026, 16023, URIUtils::GetFileName(file.GetPath()), 0); return false; } // CContextButtons doesn't support keying by string, only int, so use a // parallel array to track the string values (client name) CContextButtons choicesInt; unsigned int i = 0; // Vector to translate button IDs to game client pointers vector<string> choicesStr; for (map<string, GameClientPtr>::const_iterator it = candidates.begin(); it != candidates.end(); ++it) { const string& strName = it->first; choicesInt.Add(i++, strName); choicesStr.push_back(strName); } int btnid = CGUIDialogContextMenu::ShowAndGetChoice(choicesInt); if (btnid < 0 || btnid >= (int)candidates.size()) { CLog::Log(LOGDEBUG, "RetroPlayer: User canceled game client installation selection"); return false; } map<string, GameClientPtr>::iterator it = candidates.find(choicesStr[btnid]); if (it == candidates.end()) return false; // Shouldn't happen GameClientPtr &gc = it->second; // determining disabled status is the same test as earlier // TODO: Preserve disabled values in parallel array // TODO: Don't use parallel arrays AddonPtr addon; // Return value, will be assigned to result bool disabled = !CAddonMgr::Get().GetAddon(gc->ID(), addon, ADDON_GAMEDLL, true) && addon; if (disabled) { // TODO: Prompt the user to enable it CLog::Log(LOGDEBUG, "RetroPlayer: Game client %s installed but disabled, enabling it", gc->ID().c_str()); CGameManager::Get().ClearAutoLaunch(); // Don't auto-launch queued game when the add-on is enabled CAddonMgr::Get().DisableAddon(gc->ID(), false); // Retrieve the newly-enabled add-on if (!CAddonMgr::Get().GetAddon(gc->ID(), addon) || !addon) return false; } else { CLog::Log(LOGDEBUG, "RetroPlayer: Installing game client %s", gc->ID().c_str()); bool success = CAddonInstaller::Get().PromptForInstall(gc->ID(), addon); if (!success || !addon || addon->Type() != ADDON_GAMEDLL) { CLog::Log(LOGDEBUG, "RetroPlayer: Game client installation failed"); // "id" // "Installation failed" // "Check the log file for details." CGUIDialogOK::ShowAndGetInput(gc->ID().c_str(), 114, 16029, 0); return false; } } GameClientPtr gameClient = boost::dynamic_pointer_cast<CGameClient>(addon); if (!gameClient) { CLog::Log(LOGERROR, "RetroPlayer: Add-on was not a game client!"); return false; } result = gameClient; return true; }