int CPVRClients::AddClientToDb(const AddonPtr client) { /* add this client to the database if it's not in there yet */ CPVRDatabase *database = GetPVRDatabase(); int iClientDbId = database ? database->Persist(client) : -1; if (iClientDbId <= 0) { CLog::Log(LOGERROR, "PVR - %s - can't add client '%s' to the database", __FUNCTION__, client->Name().c_str()); } return iClientDbId; }
bool CAddonInstallJob::Install(const CStdString &installFrom) { CStdString addonFolder(installFrom); URIUtils::RemoveSlashAtEnd(addonFolder); addonFolder = URIUtils::AddFileToFolder("special://home/addons/", URIUtils::GetFileName(addonFolder)); CFileItemList install; install.Add(CFileItemPtr(new CFileItem(installFrom, true))); install[0]->Select(true); CFileOperationJob job(CFileOperationJob::ActionReplace, install, "special://home/addons/"); AddonPtr addon; if (!job.DoWork() || !CAddonMgr::Get().LoadAddonDescription(addonFolder, addon)) { // failed extraction or failed to load addon description CStdString addonID = URIUtils::GetFileName(addonFolder); ReportInstallError(addonID, addonID); CLog::Log(LOGERROR,"Could not read addon description of %s", addonID.c_str()); DeleteAddon(addonFolder); return false; } // resolve dependencies CAddonMgr::Get().FindAddons(); // needed as GetDeps() grabs directly from c-pluff via the addon manager ADDONDEPS deps = addon->GetDeps(); CStdString referer; referer.Format("Referer=%s-%s.zip",addon->ID().c_str(),addon->Version().c_str()); for (ADDONDEPS::iterator it = deps.begin(); it != deps.end(); ++it) { if (it->first.Equals("xbmc.metadata")) continue; const CStdString &addonID = it->first; const AddonVersion &version = it->second.first; bool optional = it->second.second; AddonPtr dependency; bool haveAddon = CAddonMgr::Get().GetAddon(addonID, dependency); if ((haveAddon && !dependency->MeetsVersion(version)) || (!haveAddon && !optional)) { // we have it but our version isn't good enough, or we don't have it and we need it bool force=(dependency != NULL); // dependency is already queued up for install - ::Install will fail // instead we wait until the Job has finished. note that we // recall install on purpose in case prior installation failed if (CAddonInstaller::Get().HasJob(addonID)) { while (CAddonInstaller::Get().HasJob(addonID)) Sleep(50); force = false; } // don't have the addon or the addon isn't new enough - grab it (no new job for these) if (!CAddonInstaller::Get().Install(addonID, force, referer, false)) { DeleteAddon(addonFolder); return false; } } } return true; }
bool CPluginDirectory::RunScriptWithParams(const CStdString& strPath) { CURL url(strPath); if (url.GetHostName().IsEmpty()) // called with no script - should never happen return false; AddonPtr addon; if (!CAddonMgr::Get().GetAddon(url.GetHostName(), addon, ADDON_PLUGIN) && !CAddonInstaller::Get().PromptForInstall(url.GetHostName(), addon)) { CLog::Log(LOGERROR, "Unable to find plugin %s", url.GetHostName().c_str()); return false; } // options CStdString options = url.GetOptions(); URIUtils::RemoveSlashAtEnd(options); // This MAY kill some scripts (eg though with a URL ending with a slash), but // is needed for all others, as XBMC adds slashes to "folders" url.SetOptions(""); // do this because we can then use the url to generate the basepath // which is passed to the plugin (and represents the share) CStdString basePath(url.Get()); // setup our parameters to send the script CStdString strHandle; strHandle.Format("%i", -1); vector<string> argv; argv.push_back(basePath); argv.push_back(strHandle); argv.push_back(options); // run the script CLog::Log(LOGDEBUG, "%s - calling plugin %s('%s','%s','%s')", __FUNCTION__, addon->Name().c_str(), argv[0].c_str(), argv[1].c_str(), argv[2].c_str()); if (CScriptInvocationManager::Get().Execute(addon->LibPath(), addon, argv) >= 0) return true; else CLog::Log(LOGERROR, "Unable to run plugin %s", addon->Name().c_str()); return false; }
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 CAddonInstaller::DoInstall(const AddonPtr &addon, const RepositoryPtr& repo, const std::string &hash /* = "" */, bool background /* = true */, bool modal /* = false */, bool autoUpdate /* = false*/) { // check whether we already have the addon installing CSingleLock lock(m_critSection); if (m_downloadJobs.find(addon->ID()) != m_downloadJobs.end()) return false; CAddonInstallJob* installJob = new CAddonInstallJob(addon, repo, hash, autoUpdate); if (background) { // Workaround: because CAddonInstallJob is blocking waiting for other jobs, it needs to be run // with priority dedicated. unsigned int jobID = CJobManager::GetInstance().AddJob(installJob, this, CJob::PRIORITY_DEDICATED); m_downloadJobs.insert(make_pair(addon->ID(), CDownloadJob(jobID))); m_idle.Reset(); return true; } m_downloadJobs.insert(make_pair(addon->ID(), CDownloadJob(0))); m_idle.Reset(); lock.Leave(); bool result = false; if (modal) result = installJob->DoModal(); else result = installJob->DoWork(); delete installJob; lock.Enter(); JobMap::iterator i = m_downloadJobs.find(addon->ID()); m_downloadJobs.erase(i); if (m_downloadJobs.empty()) m_idle.Set(); return result; }
AddonPtr CBinaryAddonCache::GetAddonInstance(const std::string& strId, TYPE type) { AddonPtr addon; CSingleLock lock(m_critSection); auto it = m_addons.find(type); if (it != m_addons.end()) { VECADDONS& addons = it->second; auto itAddon = std::find_if(addons.begin(), addons.end(), [&strId](const AddonPtr& addon) { return addon->ID() == strId; }); if (itAddon != addons.end()) addon = *itAddon; } return addon; }
bool CAddonInstaller::InstallFromZip(const std::string &path) { if (!g_passwordManager.CheckMenuLock(WINDOW_ADDON_BROWSER)) return false; // grab the descriptive XML document from the zip, and read it in CFileItemList items; // BUG: some zip files return a single item (root folder) that we think is stored, so we don't use the zip:// protocol CURL pathToUrl(path); CURL zipDir = URIUtils::CreateArchivePath("zip", pathToUrl, ""); if (!CDirectory::GetDirectory(zipDir, items) || items.Size() != 1 || !items[0]->m_bIsFolder) { CEventLog::GetInstance().AddWithNotification( EventPtr(new CNotificationEvent(EventLevelError, 24045, StringUtils::Format(g_localizeStrings.Get(24143).c_str(), path.c_str()))), false); return false; } // TODO: possibly add support for github generated zips here? std::string archive = URIUtils::AddFileToFolder(items[0]->GetPath(), "addon.xml"); CXBMCTinyXML xml; AddonPtr addon; if (xml.LoadFile(archive) && CAddonMgr::GetInstance().LoadAddonDescriptionFromMemory(xml.RootElement(), addon)) { // set the correct path addon->Props().path = items[0]->GetPath(); addon->Props().icon = URIUtils::AddFileToFolder(items[0]->GetPath(), "icon.png"); // install the addon return DoInstall(addon); } CEventLog::GetInstance().AddWithNotification( EventPtr(new CNotificationEvent(EventLevelError, 24045, StringUtils::Format(g_localizeStrings.Get(24143).c_str(), path.c_str()))), false); return false; }
bool CAddonMgr::GetAddon(const CStdString &str, AddonPtr &addon, const TYPE &type/*=ADDON_UNKNOWN*/, bool enabledOnly /*= true*/, bool install /*= false*/) { 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); m_cpluff->release_info(m_cp_context, cpaddon); if (addon.get() && enabledOnly && m_database.IsAddonDisabled(addon->ID())) return false; return NULL != addon.get(); } else { if (install) { if (!CGUIDialogYesNo::ShowAndGetInput(g_localizeStrings.Get(24076), g_localizeStrings.Get(24100), str.c_str(), g_localizeStrings.Get(24101))) return false; if (CAddonInstaller::Get().Install(str.c_str(), true, "", false)) { cp_plugin_info_t *cpaddon = m_cpluff->get_plugin_info(m_cp_context, str.c_str(), &status); addon = GetAddonFromDescriptor(cpaddon); m_cpluff->release_info(m_cp_context, cpaddon); if (status == CP_OK && cpaddon) return NULL != addon.get(); } } } if (cpaddon) m_cpluff->release_info(m_cp_context, cpaddon); return false; }
bool CPVRClients::UpdateAddons(void) { ADDON::VECADDONS addons; bool bReturn(CAddonMgr::Get().GetAddons(ADDON_PVRDLL, addons, true)); if (bReturn) { CSingleLock lock(m_critSection); m_addons = addons; } // handle "new" addons which aren't yet in the db - these have to be added first for (unsigned iClientPtr = 0; iClientPtr < m_addons.size(); iClientPtr++) { const AddonPtr clientAddon = m_addons.at(iClientPtr); if (!m_addonDb.HasAddon(clientAddon->ID())) { m_addonDb.AddAddon(clientAddon, -1); } } if ((!bReturn || addons.size() == 0) && !m_bNoAddonWarningDisplayed && !CAddonMgr::Get().HasAddons(ADDON_PVRDLL, false) && (g_PVRManager.GetState() == ManagerStateStarted || g_PVRManager.GetState() == ManagerStateStarting)) { // No PVR add-ons could be found // You need a tuner, backend software, and an add-on for the backend to be able to use PVR. // Please visit xbmc.org/pvr to learn more. m_bNoAddonWarningDisplayed = true; g_guiSettings.SetBool("pvrmanager.enabled", false); CGUIDialogOK::ShowAndGetInput(19271, 19272, 19273, 19274); CGUIMessage msg(GUI_MSG_UPDATE, WINDOW_SETTINGS_MYPVR, 0); g_windowManager.SendThreadMessage(msg, WINDOW_SETTINGS_MYPVR); } return bReturn; }
int CActiveAEDSP::GetAudioDSPAddonId(const AddonPtr &addon) const { CSingleLock lock(m_critUpdateSection); for (auto &entry : m_addonMap) { if (entry.second->ID() == addon->ID()) { return entry.first; } } return -1; }
bool CAddonMgr::GetAllOutdatedAddons(VECADDONS &addons, bool enabled /*= true*/) { CSingleLock lock(m_critSection); for (int i = ADDON_UNKNOWN+1; i < ADDON_VIZ_LIBRARY; ++i) { VECADDONS temp; if (CAddonMgr::Get().GetAddons((TYPE)i, temp, enabled)) { AddonPtr repoAddon; for (unsigned int j = 0; j < temp.size(); j++) { if (!m_database.GetAddon(temp[j]->ID(), repoAddon)) continue; if (temp[j]->Version() < repoAddon->Version() && !m_database.IsAddonBlacklisted(temp[j]->ID(), repoAddon->Version().c_str())) addons.push_back(repoAddon); } } } return !addons.empty(); }
int CPVRClients::GetClientId(const AddonPtr &client) const { CSingleLock lock(m_critSection); for (auto &entry : m_clientMap) { if (entry.second->ID() == client->ID()) { return entry.first; } } return -1; }
AddonPtr CAddonInstallJob::GetRepoForAddon(const AddonPtr& addon) { AddonPtr repoPtr; CAddonDatabase database; if (!database.Open()) return repoPtr; std::string repo; if (!database.GetRepoForAddon(addon->ID(), repo)) return repoPtr; if (!CAddonMgr::GetInstance().GetAddon(repo, repoPtr)) return repoPtr; if (std::dynamic_pointer_cast<CRepository>(repoPtr) == NULL) { repoPtr.reset(); return repoPtr; } return repoPtr; }
bool CPVRClients::InitialiseClient(AddonPtr client) { bool bReturn(false); if (!client->Enabled()) return bReturn; CLog::Log(LOGDEBUG, "%s - initialising add-on '%s'", __FUNCTION__, client->Name().c_str()); /* register this client in the db */ int iClientId = AddClientToDb(client); if (iClientId == -1) return bReturn; /* load and initialise the client libraries */ boost::shared_ptr<CPVRClient> addon; { CSingleLock lock(m_critSection); CLIENTMAPITR existingClient = m_clientMap.find(iClientId); if (existingClient != m_clientMap.end()) { addon = existingClient->second; } else { addon = boost::dynamic_pointer_cast<CPVRClient>(client); m_clientMap.insert(std::make_pair(iClientId, addon)); } } if (addon) bReturn = addon->Create(iClientId); if (!bReturn) CLog::Log(LOGERROR, "PVR - %s - can't initialise add-on '%s'", __FUNCTION__, client->Name().c_str()); return bReturn; }
bool CAddonInstaller::CheckDependencies(const AddonPtr &addon, std::vector<std::string>& preDeps, CAddonDatabase &database, std::pair<std::string, std::string> &failedDep) { if (addon == NULL) return true; // a NULL addon has no dependencies if (!database.Open()) return false; ADDONDEPS deps = addon->GetDeps(); for (ADDONDEPS::const_iterator i = deps.begin(); i != deps.end(); ++i) { const std::string &addonID = i->first; const AddonVersion &version = i->second.first; bool optional = i->second.second; AddonPtr dep; bool haveAddon = CAddonMgr::GetInstance().GetAddon(addonID, dep); if ((haveAddon && !dep->MeetsVersion(version)) || (!haveAddon && !optional)) { // we have it but our version isn't good enough, or we don't have it and we need it if (!database.GetAddon(addonID, dep) || !dep->MeetsVersion(version)) { // we don't have it in a repo, or we have it but the version isn't good enough, so dep isn't satisfied. CLog::Log(LOGDEBUG, "CAddonInstallJob[%s]: requires %s version %s which is not available", addon->ID().c_str(), addonID.c_str(), version.asString().c_str()); database.Close(); // fill in the details of the failed dependency failedDep.first = addon->ID(); failedDep.second = version.asString(); return false; } } // at this point we have our dep, or the dep is optional (and we don't have it) so check that it's OK as well // TODO: should we assume that installed deps are OK? if (dep && std::find(preDeps.begin(), preDeps.end(), dep->ID()) == preDeps.end()) { if (!CheckDependencies(dep, preDeps, database, failedDep)) { database.Close(); preDeps.push_back(dep->ID()); return false; } } } database.Close(); return true; }
std::unique_ptr<CRepository> CRepository::FromExtension(CAddonInfo addonInfo, const cp_extension_t* ext) { DirList dirs; AddonVersion version("0.0.0"); AddonPtr addonver; if (CServiceBroker::GetAddonMgr().GetAddon("xbmc.addon", addonver)) version = addonver->Version(); for (size_t i = 0; i < ext->configuration->num_children; ++i) { if(ext->configuration->children[i].name && strcmp(ext->configuration->children[i].name, "dir") == 0) { AddonVersion min_version(CServiceBroker::GetAddonMgr().GetExtValue(&ext->configuration->children[i], "@minversion")); if (min_version <= version) { DirInfo dir; dir.version = min_version; dir.checksum = CServiceBroker::GetAddonMgr().GetExtValue(&ext->configuration->children[i], "checksum"); dir.info = CServiceBroker::GetAddonMgr().GetExtValue(&ext->configuration->children[i], "info"); dir.datadir = CServiceBroker::GetAddonMgr().GetExtValue(&ext->configuration->children[i], "datadir"); dir.hashes = CServiceBroker::GetAddonMgr().GetExtValue(&ext->configuration->children[i], "hashes") == "true"; dirs.push_back(std::move(dir)); } } } if (!CServiceBroker::GetAddonMgr().GetExtValue(ext->configuration, "info").empty()) { DirInfo info; info.checksum = CServiceBroker::GetAddonMgr().GetExtValue(ext->configuration, "checksum"); info.info = CServiceBroker::GetAddonMgr().GetExtValue(ext->configuration, "info"); info.datadir = CServiceBroker::GetAddonMgr().GetExtValue(ext->configuration, "datadir"); info.hashes = CServiceBroker::GetAddonMgr().GetExtValue(ext->configuration, "hashes") == "true"; dirs.push_back(std::move(info)); } return std::unique_ptr<CRepository>(new CRepository(std::move(addonInfo), std::move(dirs))); }
//@{ bool CActiveAEDSP::HaveMenuHooks(AE_DSP_MENUHOOK_CAT cat, int iDSPAddonID) { for (AE_DSP_ADDONMAP_CITR citr = m_addonMap.begin(); citr != m_addonMap.end(); ++citr) { if (citr->second->ReadyToUse()) { if (citr->second->HaveMenuHooks(cat)) { if (iDSPAddonID > 0 && citr->second->GetID() == iDSPAddonID) return true; else if (iDSPAddonID < 0) return true; } else if (cat == AE_DSP_MENUHOOK_SETTING) { AddonPtr addon; if (CAddonMgr::GetInstance().GetAddon(citr->second->ID(), addon) && addon->HasSettings()) return true; } } } return false; }
bool CPluginDirectory::RunScriptWithParams(const std::string& strPath) { CURL url(strPath); if (url.GetHostName().empty()) // called with no script - should never happen return false; AddonPtr addon; if (!CAddonMgr::Get().GetAddon(url.GetHostName(), addon, ADDON_PLUGIN) && !CAddonInstaller::Get().PromptForInstall(url.GetHostName(), addon)) { CLog::Log(LOGERROR, "Unable to find plugin %s", url.GetHostName().c_str()); return false; } // options std::string options = url.GetOptions(); url.SetOptions(""); // do this because we can then use the url to generate the basepath // which is passed to the plugin (and represents the share) std::string basePath(url.Get()); // setup our parameters to send the script std::string strHandle = StringUtils::Format("%i", -1); vector<string> argv; argv.push_back(basePath); argv.push_back(strHandle); argv.push_back(options); // run the script CLog::Log(LOGDEBUG, "%s - calling plugin %s('%s','%s','%s')", __FUNCTION__, addon->Name().c_str(), argv[0].c_str(), argv[1].c_str(), argv[2].c_str()); if (CScriptInvocationManager::Get().Execute(addon->LibPath(), addon, argv) >= 0) return true; else CLog::Log(LOGERROR, "Unable to run plugin %s", addon->Name().c_str()); return false; }
void CGUIWindowWeather::CallScript() { #ifdef HAS_PYTHON if (!g_guiSettings.GetString("weather.script").Equals(DEFAULT_WEATHER_ADDON)) { AddonPtr addon; if (!ADDON::CAddonMgr::Get().GetAddon(g_guiSettings.GetString("weather.script"), addon, ADDON_SCRIPT_WEATHER)) return; // initialize our sys.argv variables std::vector<CStdString> argv; argv.push_back(addon->LibPath()); // if script is running we wait for another timeout only when in weather window if (g_windowManager.GetActiveWindow() == WINDOW_WEATHER) { int id = g_pythonParser.getScriptId(argv[0]); if (id != -1 && g_pythonParser.isRunning(id)) { m_scriptTimer.StartZero(); return; } } // get the current locations area code CStdString strSetting; strSetting.Format("weather.areacode%i", m_iCurWeather + 1); argv.push_back(CWeather::GetAreaCode(g_guiSettings.GetString(strSetting))); // call our script, passing the areacode g_pythonParser.evalFile(argv[0], argv); CLog::Log(LOGDEBUG, "%s - Weather script called: %s (%s)", __FUNCTION__, argv[0].c_str(), argv[1].c_str()); } #endif }
int CPVRDatabase::Persist(const AddonPtr client) { int iReturn(-1); /* invalid client uid or name */ if (client->Name().IsEmpty() || client->ID().IsEmpty()) { CLog::Log(LOGERROR, "PVR - %s - invalid client uid or name", __FUNCTION__); return iReturn; } /* only add this client if it's not already in the database */ iReturn = GetClientId(client->ID()); if (iReturn <= 0) { CStdString strQuery = FormatSQL("INSERT INTO clients (sName, sUid) VALUES ('%s', '%s');", client->Name().c_str(), client->ID().c_str()); if (ExecuteQuery(strQuery)) iReturn = (int) m_pDS->lastinsertid(); } return iReturn; }
bool CAddonInstaller::DoInstall(const AddonPtr &addon, const RepositoryPtr& repo, const std::string &hash /* = "" */, bool background /* = true */, bool modal /* = false */) { // check whether we already have the addon installing CSingleLock lock(m_critSection); if (m_downloadJobs.find(addon->ID()) != m_downloadJobs.end()) return false; CAddonInstallJob* installJob = new CAddonInstallJob(addon, repo, hash); if (background) { unsigned int jobID = CJobManager::GetInstance().AddJob(installJob, this); m_downloadJobs.insert(make_pair(addon->ID(), CDownloadJob(jobID))); m_idle.Reset(); return true; } m_downloadJobs.insert(make_pair(addon->ID(), CDownloadJob(0))); m_idle.Reset(); lock.Leave(); bool result = false; if (modal) result = installJob->DoModal(); else result = installJob->DoWork(); delete installJob; lock.Enter(); JobMap::iterator i = m_downloadJobs.find(addon->ID()); m_downloadJobs.erase(i); if (m_downloadJobs.empty()) m_idle.Set(); return result; }
void CAddonInstallJob::ReportInstallError(const CStdString& addonID, const CStdString& fileName) { AddonPtr addon; CAddonDatabase database; database.Open(); database.GetAddon(addonID, addon); if (addon) { AddonPtr addon2; CAddonMgr::Get().GetAddon(addonID, addon2); CGUIDialogKaiToast::QueueNotification(addon->Icon(), addon->Name(), g_localizeStrings.Get(addon2 ? 113 : 114), TOAST_DISPLAY_TIME, false); } else { CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, fileName, g_localizeStrings.Get(114), TOAST_DISPLAY_TIME, false); } }
//@{ bool CActiveAEDSP::StopAudioDSPAddon(AddonPtr addon, bool bRestart) { CSingleLock lock(m_critSection); int iId = GetAudioDSPAddonId(addon->ID()); AE_DSP_ADDON mappedAddon; if (GetReadyAudioDSPAddon(iId, mappedAddon)) { if (bRestart) mappedAddon->ReCreate(); else mappedAddon->Destroy(); return true; } return false; }
bool CAddonDatabase::GetAddon(const CStdString& id, AddonPtr& addon) { try { if (NULL == m_pDB.get()) return false; if (NULL == m_pDS2.get()) return false; CStdString sql = PrepareSQL("select id from addon where addonID='%s' order by version desc",id.c_str()); m_pDS2->query(sql.c_str()); if (!m_pDS2->eof()) return GetAddon(m_pDS2->fv(0).get_asInt(),addon); } catch (...) { CLog::Log(LOGERROR, "%s failed on addon %s", __FUNCTION__, id.c_str()); } addon.reset(); return false; }
void CServiceAddonManager::Start(const AddonPtr& addon) { CSingleLock lock(m_criticalSection); if (m_services.find(addon->ID()) != m_services.end()) { CLog::Log(LOGDEBUG, "CServiceAddonManager: %s already started.", addon->ID().c_str()); return; } if (StringUtils::EndsWith(addon->LibPath(), ".py")) { CLog::Log(LOGDEBUG, "CServiceAddonManager: starting %s", addon->ID().c_str()); auto handle = CScriptInvocationManager::GetInstance().ExecuteAsync(addon->LibPath(), addon); if (handle == -1) { CLog::Log(LOGERROR, "CServiceAddonManager: %s failed to start", addon->ID().c_str()); return; } m_services[addon->ID()] = handle; } }
bool CAddonDatabase::GetAddon(const std::string& id, AddonPtr& addon) { try { if (NULL == m_pDB.get()) return false; if (NULL == m_pDS2.get()) return false; // there may be multiple addons with this id (eg from different repositories) in the database, // so we want to retrieve the latest version. Order by version won't work as the database // won't know that 1.10 > 1.2, so grab them all and order outside std::string sql = PrepareSQL("select id,version from addon where addonID='%s'",id.c_str()); m_pDS2->query(sql.c_str()); if (m_pDS2->eof()) return false; AddonVersion maxversion("0.0.0"); int maxid = 0; while (!m_pDS2->eof()) { AddonVersion version(m_pDS2->fv(1).get_asString()); if (version > maxversion) { maxid = m_pDS2->fv(0).get_asInt(); maxversion = version; } m_pDS2->next(); } return GetAddon(maxid,addon); } catch (...) { CLog::Log(LOGERROR, "%s failed on addon %s", __FUNCTION__, id.c_str()); } addon.reset(); return false; }
bool CAddonInstallJob::Install(const CStdString &installFrom) { CStdString addonFolder(installFrom); URIUtils::RemoveSlashAtEnd(addonFolder); addonFolder = URIUtils::AddFileToFolder("special://home/addons/", URIUtils::GetFileName(addonFolder)); CFileItemList install; install.Add(CFileItemPtr(new CFileItem(installFrom, true))); install[0]->Select(true); CFileOperationJob job(CFileOperationJob::ActionReplace, install, "special://home/addons/"); AddonPtr addon; if (!job.DoWork() || !CAddonMgr::Get().LoadAddonDescription(addonFolder, addon)) { // failed extraction or failed to load addon description CStdString addonID = URIUtils::GetFileName(addonFolder); ReportInstallError(addonID, addonID); CLog::Log(LOGERROR,"Could not read addon description of %s", addonID.c_str()); DeleteAddon(addonFolder); return false; } // resolve dependencies CAddonMgr::Get().FindAddons(); // needed as GetDeps() grabs directly from c-pluff via the addon manager ADDONDEPS deps = addon->GetDeps(); CStdString referer; referer.Format("Referer=%s-%s.zip",addon->ID().c_str(),addon->Version().c_str()); for (ADDONDEPS::iterator it = deps.begin(); it != deps.end(); ++it) { if (it->first.Equals("xbmc.metadata")) continue; AddonPtr dependency; if (!CAddonMgr::Get().GetAddon(it->first,dependency) || dependency->Version() < it->second.first) { // don't have the addon or the addon isn't new enough - grab it (no new job for these) if (!CAddonInstaller::Get().Install(it->first, dependency != NULL, referer, false)) { DeleteAddon(addonFolder); return false; } } } return true; }
bool CAddonInstaller::DoInstall(const AddonPtr &addon, const CStdString &hash, bool update, const CStdString &referer, bool background) { // check whether we already have the addon installing CSingleLock lock(m_critSection); if (m_downloadJobs.find(addon->ID()) != m_downloadJobs.end()) return false; // check whether all the dependencies are available or not // TODO: we currently assume that dependencies will install correctly (and each of their dependencies and so on). // it may be better to install the dependencies first to minimise the chance of an addon becoming orphaned due to // missing deps. if (!CheckDependencies(addon)) { CGUIDialogKaiToast::QueueNotification(addon->Icon(), addon->Name(), g_localizeStrings.Get(24044), TOAST_DISPLAY_TIME, false); return false; } if (background) { unsigned int jobID = CJobManager::GetInstance().AddJob(new CAddonInstallJob(addon, hash, update, referer), this); m_downloadJobs.insert(make_pair(addon->ID(), CDownloadJob(jobID))); } else { m_downloadJobs.insert(make_pair(addon->ID(), CDownloadJob(0))); lock.Leave(); CAddonInstallJob job(addon, hash, update, referer); if (!job.DoWork()) { // TODO: dump something to debug log? return false; } lock.Enter(); JobMap::iterator i = m_downloadJobs.find(addon->ID()); m_downloadJobs.erase(i); } return true; }
void OnPostUnInstall(const AddonPtr& addon) { addon->OnPostUnInstall(); }
// \brief With this function you can react on a users click in the list/thumb panel. // It returns true, if the click is handled. // This function calls OnPlayMedia() bool CGUIMediaWindow::OnClick(int iItem) { if ( iItem < 0 || iItem >= (int)m_vecItems->Size() ) return true; CFileItemPtr pItem = m_vecItems->Get(iItem); if (pItem->IsParentFolder()) { GoParentFolder(); return true; } if (pItem->GetPath() == "add" || pItem->GetPath() == "sources://add/") // 'add source button' in empty root { OnContextButton(iItem, CONTEXT_BUTTON_ADD_SOURCE); return true; } if (!pItem->m_bIsFolder && pItem->IsFileFolder()) { XFILE::IFileDirectory *pFileDirectory = NULL; pFileDirectory = XFILE::CFactoryFileDirectory::Create(pItem->GetPath(), pItem.get(), ""); if(pFileDirectory) pItem->m_bIsFolder = true; else if(pItem->m_bIsFolder) pItem->m_bIsFolder = false; delete pFileDirectory; } if (pItem->IsScript()) { // execute the script CURL url(pItem->GetPath()); AddonPtr addon; if (CAddonMgr::Get().GetAddon(url.GetHostName(), addon)) { #ifdef HAS_PYTHON if (!g_pythonParser.StopScript(addon->LibPath())) g_pythonParser.evalFile(addon->LibPath(),addon); #endif return true; } } if (pItem->m_bIsFolder) { if ( pItem->m_bIsShareOrDrive ) { const CStdString& strLockType=m_guiState->GetLockType(); if (g_settings.GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE) if (!strLockType.IsEmpty() && !g_passwordManager.IsItemUnlocked(pItem.get(), strLockType)) return true; if (!HaveDiscOrConnection(pItem->GetPath(), pItem->m_iDriveType)) return true; } // check for the partymode playlist items - they may not exist yet if ((pItem->GetPath() == g_settings.GetUserDataItem("PartyMode.xsp")) || (pItem->GetPath() == g_settings.GetUserDataItem("PartyMode-Video.xsp"))) { // party mode playlist item - if it doesn't exist, prompt for user to define it if (!XFILE::CFile::Exists(pItem->GetPath())) { m_vecItems->RemoveDiscCache(GetID()); if (CGUIDialogSmartPlaylistEditor::EditPlaylist(pItem->GetPath())) Update(m_vecItems->GetPath()); return true; } } // remove the directory cache if the folder is not normally cached CFileItemList items(pItem->GetPath()); if (!items.AlwaysCache()) items.RemoveDiscCache(GetID()); CFileItem directory(*pItem); if (!Update(directory.GetPath())) ShowShareErrorMessage(&directory); return true; } else if (pItem->IsPlugin() && !pItem->GetProperty("isplayable").asBoolean()) { return XFILE::CPluginDirectory::RunScriptWithParams(pItem->GetPath()); } else { m_iSelectedItem = m_viewControl.GetSelectedItem(); if (pItem->GetPath() == "newplaylist://") { m_vecItems->RemoveDiscCache(GetID()); g_windowManager.ActivateWindow(WINDOW_MUSIC_PLAYLIST_EDITOR,"newplaylist://"); return true; } else if (pItem->GetPath().Left(19).Equals("newsmartplaylist://")) { m_vecItems->RemoveDiscCache(GetID()); if (CGUIDialogSmartPlaylistEditor::NewPlaylist(pItem->GetPath().Mid(19))) Update(m_vecItems->GetPath()); return true; } else if (pItem->GetPath().Left(14).Equals("addons://more/")) { CBuiltins::Execute("ActivateWindow(AddonBrowser,addons://all/xbmc.addon." + pItem->GetPath().Mid(14) + ",return)"); return true; } // If karaoke song is being played AND popup autoselector is enabled, the playlist should not be added bool do_not_add_karaoke = g_guiSettings.GetBool("karaoke.enabled") && g_guiSettings.GetBool("karaoke.autopopupselector") && pItem->IsKaraoke(); bool autoplay = m_guiState.get() && m_guiState->AutoPlayNextItem(); if (pItem->IsPlugin()) { CURL url(pItem->GetPath()); AddonPtr addon; if (CAddonMgr::Get().GetAddon(url.GetHostName(),addon)) { PluginPtr plugin = boost::dynamic_pointer_cast<CPluginSource>(addon); if (plugin && plugin->Provides(CPluginSource::AUDIO) && pItem->IsAudio()) { autoplay = g_guiSettings.GetBool("musicplayer.autoplaynextitem"); } } } if (autoplay && !g_partyModeManager.IsEnabled() && !pItem->IsPlayList() && !do_not_add_karaoke) { return OnPlayAndQueueMedia(pItem); } else { return OnPlayMedia(iItem); } } return false; }