int CHTTPWebinterfaceAddonsHandler::HandleRequest() { m_responseData = ADDON_HEADER; ADDON::VECADDONS addons; if (!ADDON::CAddonMgr::GetInstance().GetAddons(addons, ADDON::ADDON_WEB_INTERFACE) || addons.empty()) { m_response.type = HTTPError; m_response.status = MHD_HTTP_INTERNAL_SERVER_ERROR; return MHD_YES; } for (ADDON::IVECADDONS addon = addons.begin(); addon != addons.end(); ++addon) m_responseData += "<li><a href=/addons/" + (*addon)->ID() + "/>" + (*addon)->Name() + "</a></li>\n"; m_responseData += "</ul>\n</body></html>"; m_responseRange.SetData(m_responseData.c_str(), m_responseData.size()); m_response.type = HTTPMemoryDownloadNoFreeCopy; m_response.status = MHD_HTTP_OK; m_response.contentType = "text/html"; m_response.totalLength = m_responseData.size(); return MHD_YES; }
bool CPVRClients::UpdateAndInitialiseClients(bool bInitialiseAllClients /* = false */) { bool bReturn(true); ADDON::VECADDONS map; { CSingleLock lock(m_critSection); map = m_addons; } for (unsigned iClientPtr = 0; iClientPtr < map.size(); iClientPtr++) { const AddonPtr clientAddon = map.at(iClientPtr); if (!clientAddon->Enabled() && IsKnownClient(clientAddon)) { /* stop the client and remove it from the db */ bReturn &= StopClient(clientAddon, false) && bReturn; } else if (clientAddon->Enabled() && (bInitialiseAllClients || !IsKnownClient(clientAddon))) { /* register the new client and initialise it */ bReturn &= InitialiseClient(clientAddon) && bReturn; } } /* check whether all clients are (still) connected */ { CSingleLock lock(m_critSection); m_bAllClientsConnected = (ConnectedClientAmount() == EnabledClientAmount()); } return bReturn; }
void CActiveAEDSPDatabase::CreateTables() { BeginTransaction(); CLog::Log(LOGINFO, "Audio DSP - %s - creating tables", __FUNCTION__); CLog::Log(LOGDEBUG, "Audio DSP - %s - creating table 'addons'", __FUNCTION__); m_pDS->exec( "CREATE TABLE addons (" "idAddon integer primary key, " "sName varchar(64), " "sUid varchar(32)" ")" ); CLog::Log(LOGDEBUG, "Audio DSP - %s - creating table 'modes'", __FUNCTION__); m_pDS->exec( "CREATE TABLE modes (" "idMode integer primary key, " "iType integer, " "iPosition integer, " "iStreamTypeFlags integer, " "iBaseType integer, " "bIsEnabled bool, " "sOwnIconPath varchar(255), " "sOverrideIconPath varchar(255), " "iModeName integer, " "iModeSetupName integer, " "iModeHelp integer, " "iModeDescription integer, " "sAddonModeName varchar(64), " "iAddonId integer, " "iAddonModeNumber integer, " "bHasSettings bool" ")" ); CLog::Log(LOGDEBUG, "Audio DSP - %s - create settings table", __FUNCTION__); m_pDS->exec( "CREATE TABLE settings (" "id integer primary key, " "strPath varchar(255), " "strFileName varchar(255), " "MasterStreamTypeSel integer, " "MasterStreamType integer, " "MasterBaseType integer, " "MasterModeId integer" ")" ); // disable all Audio DSP add-on when started the first time ADDON::VECADDONS addons; if (CAddonMgr::Get().GetAddons(ADDON_ADSPDLL, addons, true)) CLog::Log(LOGERROR, "Audio DSP - %s - failed to get add-ons from the add-on manager", __FUNCTION__); else { for (IVECADDONS it = addons.begin(); it != addons.end(); it++) CAddonMgr::Get().DisableAddon(it->get()->ID()); } }
void CPVRDatabase::UpdateTables(int iVersion) { if (iVersion < 13) m_pDS->exec("ALTER TABLE channels ADD idEpg integer;"); if (iVersion < 14) m_pDS->exec("ALTER TABLE channelsettings ADD fCustomVerticalShift float;"); if (iVersion < 15) { m_pDS->exec("ALTER TABLE channelsettings ADD bCustomNonLinStretch bool;"); m_pDS->exec("ALTER TABLE channelsettings ADD bPostProcess bool;"); m_pDS->exec("ALTER TABLE channelsettings ADD iScalingMethod integer;"); } if (iVersion < 16) { /* sqlite apparently can't delete columns from an existing table, so just leave the extra column alone */ } if (iVersion < 17) { m_pDS->exec("ALTER TABLE channelsettings ADD iDeinterlaceMode integer"); m_pDS->exec("UPDATE channelsettings SET iDeinterlaceMode = 2 WHERE iInterlaceMethod NOT IN (0,1)"); // anything other than none: method auto => mode force m_pDS->exec("UPDATE channelsettings SET iDeinterlaceMode = 1 WHERE iInterlaceMethod = 1"); // method auto => mode auto m_pDS->exec("UPDATE channelsettings SET iDeinterlaceMode = 0, iInterlaceMethod = 1 WHERE iInterlaceMethod = 0"); // method none => mode off, method auto } if (iVersion < 19) { // bit of a hack, but we need to keep the version/contents of the non-pvr databases the same to allow clean upgrades ADDON::VECADDONS addons; if (!CAddonMgr::Get().GetAddons(ADDON_PVRDLL, addons, true)) CLog::Log(LOGERROR, "PVR - %s - failed to get add-ons from the add-on manager", __FUNCTION__); else { CAddonDatabase database; database.Open(); for (IVECADDONS it = addons.begin(); it != addons.end(); it++) { if (!database.IsSystemPVRAddonEnabled(it->get()->ID())) CAddonMgr::Get().DisableAddon(it->get()->ID()); } database.Close(); } } if (iVersion < 20) m_pDS->exec("ALTER TABLE channels ADD bIsUserSetIcon bool"); if (iVersion < 21) m_pDS->exec("ALTER TABLE channelgroups ADD iGroupType integer"); if (iVersion < 22) m_pDS->exec("ALTER TABLE channels ADD bIsLocked bool"); if (iVersion < 23) m_pDS->exec("ALTER TABLE channelgroups ADD iLastWatched integer"); }
void CLangInfo::SettingOptionsLanguageNamesFiller(const CSetting *setting, std::vector< std::pair<std::string, std::string> > &list, std::string ¤t, void *data) { // find languages... ADDON::VECADDONS addons; if (!ADDON::CAddonMgr::GetInstance().GetAddons(ADDON::ADDON_RESOURCE_LANGUAGE, addons, true)) return; for (ADDON::VECADDONS::const_iterator addon = addons.begin(); addon != addons.end(); ++addon) list.push_back(make_pair((*addon)->Name(), (*addon)->Name())); sort(list.begin(), list.end(), SortLanguage()); }
std::set<std::string> CGUIControllerList::GetNewControllerIDs(ADDON::VECADDONS& addonCache) const { std::set<std::string> controllerIds; CAddonMgr::GetInstance().GetAddons(addonCache, ADDON_GAME_CONTROLLER); std::transform(addonCache.begin(), addonCache.end(), std::inserter(controllerIds, controllerIds.end()), [](const AddonPtr& addon) { return addon->ID(); }); return controllerIds; }
void CGUIControllerList::RegisterController(const std::string& addonId, const ADDON::VECADDONS& addonCache) { auto it = std::find_if(addonCache.begin(), addonCache.end(), [addonId](const AddonPtr& addon) { return addon->ID() == addonId; }); if (it != addonCache.end()) { ControllerPtr newController = std::dynamic_pointer_cast<CController>(*it); if (newController && newController->LoadLayout()) m_controllers.push_back(newController); } }
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; }
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; } 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; CGUIDialogOK::ShowAndGetInput(19271, 19272, 19273, 19274); } return bReturn; }
int CGUIWindowAddonBrowser::SelectAddonID(ADDON::TYPE type, CStdStringArray &addonIDs, bool showNone /*= false*/, bool multipleSelection /*= true*/) { CGUIDialogSelect *dialog = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT); if (type == ADDON_UNKNOWN || !dialog) return 0; ADDON::VECADDONS addons; if (type == ADDON_AUDIO) CAddonsDirectory::GetScriptsAndPlugins("audio",addons); else if (type == ADDON_EXECUTABLE) CAddonsDirectory::GetScriptsAndPlugins("executable",addons); else if (type == ADDON_IMAGE) CAddonsDirectory::GetScriptsAndPlugins("image",addons); else if (type == ADDON_VIDEO) CAddonsDirectory::GetScriptsAndPlugins("video",addons); else CAddonMgr::Get().GetAddons(type, addons); CFileItemList items; for (ADDON::IVECADDONS i = addons.begin(); i != addons.end(); ++i) items.Add(CAddonsDirectory::FileItemFromAddon(*i, "")); dialog->SetHeading(TranslateType(type, true)); dialog->Reset(); dialog->SetUseDetails(true); if (multipleSelection) { showNone = false; dialog->EnableButton(true, 186); } else dialog->EnableButton(true, 21452); if (showNone) { CFileItemPtr item(new CFileItem("", false)); item->SetLabel(g_localizeStrings.Get(231)); item->SetLabel2(g_localizeStrings.Get(24040)); item->SetIconImage("DefaultAddonNone.png"); item->SetSpecialSort(SORT_ON_TOP); items.Add(item); } items.Sort(SORT_METHOD_LABEL, SORT_ORDER_ASC); if (addonIDs.size() > 0) { for (CStdStringArray::const_iterator it = addonIDs.begin(); it != addonIDs.end() ; it++) { CFileItemPtr item = items.Get(*it); if (item) item->Select(true); } } dialog->SetItems(&items); dialog->SetMultiSelection(multipleSelection); dialog->DoModal(); if (!multipleSelection && dialog->IsButtonPressed()) { // switch to the addons browser. vector<CStdString> params; params.push_back("addons://all/"+TranslateType(type,false)+"/"); params.push_back("return"); g_windowManager.ActivateWindow(WINDOW_ADDON_BROWSER, params); return 2; } if (!multipleSelection && dialog->GetSelectedLabel() == -1) return 0; addonIDs.clear(); const CFileItemList& list = dialog->GetSelectedItems(); for (int i = 0 ; i < list.Size() ; i++) addonIDs.push_back(list.Get(i)->GetPath()); return 1; }
bool CPVRDatabase::UpdateOldVersion(int iVersion) { bool bReturn = true; BeginTransaction(); try { if (iVersion < 11) { CLog::Log(LOGERROR, "PVR - %s - updating from table versions < 11 not supported. please delete '%s'", __FUNCTION__, GetBaseDBName()); bReturn = false; } else { if (iVersion < 12) m_pDS->exec("DROP VIEW vw_last_watched;"); if (iVersion < 13) m_pDS->exec("ALTER TABLE channels ADD idEpg integer;"); if (iVersion < 14) m_pDS->exec("ALTER TABLE channelsettings ADD fCustomVerticalShift float;"); if (iVersion < 15) { m_pDS->exec("ALTER TABLE channelsettings ADD bCustomNonLinStretch bool;"); m_pDS->exec("ALTER TABLE channelsettings ADD bPostProcess bool;"); m_pDS->exec("ALTER TABLE channelsettings ADD iScalingMethod integer;"); } if (iVersion < 16) { /* sqlite apparently can't delete columns from an existing table, so just leave the extra column alone */ } if (iVersion < 17) { m_pDS->exec("ALTER TABLE channelsettings ADD iDeinterlaceMode integer"); m_pDS->exec("UPDATE channelsettings SET iDeinterlaceMode = 2 WHERE iInterlaceMethod NOT IN (0,1)"); // anything other than none: method auto => mode force m_pDS->exec("UPDATE channelsettings SET iDeinterlaceMode = 1 WHERE iInterlaceMethod = 1"); // method auto => mode auto m_pDS->exec("UPDATE channelsettings SET iDeinterlaceMode = 0, iInterlaceMethod = 1 WHERE iInterlaceMethod = 0"); // method none => mode off, method auto } if (iVersion < 18) { m_pDS->exec("DROP INDEX idx_channels_iClientId;"); m_pDS->exec("DROP INDEX idx_channels_iLastWatched;"); m_pDS->exec("DROP INDEX idx_channels_bIsRadio;"); m_pDS->exec("DROP INDEX idx_channels_bIsHidden;"); m_pDS->exec("DROP INDEX idx_idChannel_idGroup;"); m_pDS->exec("DROP INDEX idx_idGroup_iChannelNumber;"); m_pDS->exec("CREATE UNIQUE INDEX idx_channels_iClientId_iUniqueId on channels(iClientId, iUniqueId);"); m_pDS->exec("CREATE UNIQUE INDEX idx_idGroup_idChannel on map_channelgroups_channels(idGroup, idChannel);"); } if (iVersion < 19) { // bit of a hack, but we need to keep the version/contents of the non-pvr databases the same to allow clean upgrades ADDON::VECADDONS addons; if ((bReturn = CAddonMgr::Get().GetAddons(ADDON_PVRDLL, addons, true, false)) == false) CLog::Log(LOGERROR, "PVR - %s - failed to get add-ons from the add-on manager", __FUNCTION__); else { CAddonDatabase database; database.Open(); for (IVECADDONS it = addons.begin(); it != addons.end(); it++) { if (!database.IsSystemPVRAddonEnabled(it->get()->ID())) database.DisableAddon(it->get()->ID()); } database.Close(); } } if (iVersion < 20) m_pDS->exec("ALTER TABLE channels ADD bIsUserSetIcon bool"); if (iVersion < 21) m_pDS->exec("ALTER TABLE channelgroups ADD iGroupType integer"); } } catch (...) { CLog::Log(LOGERROR, "PVR - %s - error attempting to update the database version!", __FUNCTION__); bReturn = false; } if (bReturn) CommitTransaction(); else RollbackTransaction(); return bReturn; }
void CPVRDatabase::CreateTables() { CLog::Log(LOGINFO, "PVR - %s - creating tables", __FUNCTION__); CLog::Log(LOGDEBUG, "PVR - %s - creating table 'clients'", __FUNCTION__); m_pDS->exec( "CREATE TABLE clients (" "idClient integer primary key, " "sName varchar(64), " "sUid varchar(32)" ")" ); CLog::Log(LOGDEBUG, "PVR - %s - creating table 'channels'", __FUNCTION__); m_pDS->exec( "CREATE TABLE channels (" "idChannel integer primary key, " "iUniqueId integer, " "bIsRadio bool, " "bIsHidden bool, " "bIsUserSetIcon bool, " "bIsLocked bool, " "sIconPath varchar(255), " "sChannelName varchar(64), " "bIsVirtual bool, " "bEPGEnabled bool, " "sEPGScraper varchar(32), " "iLastWatched integer," // TODO use mapping table "iClientId integer, " "iClientChannelNumber integer, " "sInputFormat varchar(32), " "sStreamURL varchar(255), " "iEncryptionSystem integer, " "idEpg integer" ")" ); // TODO use a mapping table so multiple backends per channel can be implemented // CLog::Log(LOGDEBUG, "PVR - %s - creating table 'map_channels_clients'", __FUNCTION__); // m_pDS->exec( // "CREATE TABLE map_channels_clients (" // "idChannel integer primary key, " // "idClient integer, " // "iClientChannelNumber integer," // "sInputFormat string," // "sStreamURL string," // "iEncryptionSystem integer" // ");" // ); // m_pDS->exec("CREATE UNIQUE INDEX idx_idChannel_idClient on map_channels_clients(idChannel, idClient);"); CLog::Log(LOGDEBUG, "PVR - %s - creating table 'channelgroups'", __FUNCTION__); m_pDS->exec( "CREATE TABLE channelgroups (" "idGroup integer primary key," "bIsRadio bool, " "iGroupType integer, " "sName varchar(64), " "iLastWatched integer" ")" ); CLog::Log(LOGDEBUG, "PVR - %s - creating table 'map_channelgroups_channels'", __FUNCTION__); m_pDS->exec( "CREATE TABLE map_channelgroups_channels (" "idChannel integer, " "idGroup integer, " "iChannelNumber integer" ")" ); CLog::Log(LOGDEBUG, "PVR - %s - creating table 'channelsettings'", __FUNCTION__); m_pDS->exec( "CREATE TABLE channelsettings (" "idChannel integer primary key, " "iInterlaceMethod integer, " "iViewMode integer, " "fCustomZoomAmount float, " "fPixelRatio float, " "iAudioStream integer, " "iSubtitleStream integer," "fSubtitleDelay float, " "bSubtitles bool, " "fBrightness float, " "fContrast float, " "fGamma float," "fVolumeAmplification float, " "fAudioDelay float, " "bOutputToAllSpeakers bool, " "bCrop bool, " "iCropLeft integer, " "iCropRight integer, " "iCropTop integer, " "iCropBottom integer, " "fSharpness float, " "fNoiseReduction float, " "fCustomVerticalShift float, " "bCustomNonLinStretch bool, " "bPostProcess bool, " "iScalingMethod integer, " "iDeinterlaceMode integer " ")" ); // disable all PVR add-on when started the first time ADDON::VECADDONS addons; if (!CAddonMgr::Get().GetAddons(ADDON_PVRDLL, addons, true)) CLog::Log(LOGERROR, "PVR - %s - failed to get add-ons from the add-on manager", __FUNCTION__); else { for (IVECADDONS it = addons.begin(); it != addons.end(); it++) CAddonMgr::Get().DisableAddon(it->get()->ID()); } }
void XBPyThread::Process() { CLog::Log(LOGDEBUG,"Python thread: start processing"); int m_Py_file_input = Py_file_input; // get the global lock PyEval_AcquireLock(); PyThreadState* state = Py_NewInterpreter(); if (!state) { PyEval_ReleaseLock(); CLog::Log(LOGERROR,"Python thread: FAILED to get thread state!"); return; } // swap in my thread state PyThreadState_Swap(state); m_pExecuter->InitializeInterpreter(); CLog::Log(LOGDEBUG, "%s - The source file to load is %s", __FUNCTION__, m_source); // get path from script file name and add python path's // this is used for python so it will search modules from script path first CStdString scriptDir; URIUtils::GetDirectory(_P(m_source), scriptDir); URIUtils::RemoveSlashAtEnd(scriptDir); CStdString path = scriptDir; // add on any addon modules the user has installed ADDON::VECADDONS addons; ADDON::CAddonMgr::Get().GetAddons(ADDON::ADDON_SCRIPT_MODULE, addons); for (unsigned int i = 0; i < addons.size(); ++i) path += PY_PATH_SEP + _P(addons[i]->LibPath()); // and add on whatever our default path is path += PY_PATH_SEP; { // we want to use sys.path so it includes site-packages // if this fails, default to using Py_GetPath PyObject *sysMod(PyImport_ImportModule((char*)"sys")); // must call Py_DECREF when finished PyObject *sysModDict(PyModule_GetDict(sysMod)); // borrowed ref, no need to delete PyObject *pathObj(PyDict_GetItemString(sysModDict, "path")); // borrowed ref, no need to delete if( pathObj && PyList_Check(pathObj) ) { for( int i = 0; i < PyList_Size(pathObj); i++ ) { PyObject *e = PyList_GetItem(pathObj, i); // borrowed ref, no need to delete if( e && PyString_Check(e) ) { path += PyString_AsString(e); // returns internal data, don't delete or modify path += PY_PATH_SEP; } } } else { path += Py_GetPath(); } Py_DECREF(sysMod); // release ref to sysMod } // set current directory and python's path. if (m_argv != NULL) PySys_SetArgv(m_argc, m_argv); CLog::Log(LOGDEBUG, "%s - Setting the Python path to %s", __FUNCTION__, path.c_str()); PySys_SetPath((char *)path.c_str()); CLog::Log(LOGDEBUG, "%s - Entering source directory %s", __FUNCTION__, scriptDir.c_str()); PyObject* module = PyImport_AddModule((char*)"__main__"); PyObject* moduleDict = PyModule_GetDict(module); // when we are done initing we store thread state so we can be aborted PyThreadState_Swap(NULL); PyEval_ReleaseLock(); // we need to check if we was asked to abort before we had inited bool stopping = false; { CSingleLock lock(m_pExecuter->m_critSection); m_threadState = state; stopping = m_stopping; } PyEval_AcquireLock(); PyThreadState_Swap(state); if (!stopping) { if (m_type == 'F') { // run script from file // We need to have python open the file because on Windows the DLL that python // is linked against may not be the DLL that xbmc is linked against so // passing a FILE* to python from an fopen has the potential to crash. PyObject* file = PyFile_FromString((char *) _P(m_source).c_str(), (char*)"r"); FILE *fp = PyFile_AsFile(file); if (fp) { PyObject *f = PyString_FromString(_P(m_source).c_str()); PyDict_SetItemString(moduleDict, "__file__", f); Py_DECREF(f); PyRun_File(fp, _P(m_source).c_str(), m_Py_file_input, moduleDict, moduleDict); // Get a reference to the main module // and global dictionary PyObject* main_module = PyImport_AddModule((char*)"__main__"); PyObject* global_dict = PyModule_GetDict(main_module); // Extract a reference to the function "func_name" // from the global dictionary PyObject* expression = PyDict_GetItemString(global_dict, "xbmcclosefilehack"); if (!PyObject_CallFunction(expression,(char*)"(O)",file)) CLog::Log(LOGERROR,"Failed to close the script file %s",_P(m_source).c_str()); } else CLog::Log(LOGERROR, "%s not found!", m_source); } else { //run script PyRun_String(m_source, m_Py_file_input, moduleDict, moduleDict); } } if (!PyErr_Occurred()) CLog::Log(LOGINFO, "Scriptresult: Success"); else if (PyErr_ExceptionMatches(PyExc_SystemExit)) CLog::Log(LOGINFO, "Scriptresult: Aborted"); else { PyObject* exc_type; PyObject* exc_value; PyObject* exc_traceback; PyObject* pystring; pystring = NULL; PyErr_Fetch(&exc_type, &exc_value, &exc_traceback); if (exc_type == 0 && exc_value == 0 && exc_traceback == 0) { CLog::Log(LOGINFO, "Strange: No Python exception occured"); } else { if (exc_type != NULL && (pystring = PyObject_Str(exc_type)) != NULL && (PyString_Check(pystring))) { PyObject *tracebackModule; CLog::Log(LOGINFO, "-->Python script returned the following error<--"); CLog::Log(LOGERROR, "Error Type: %s", PyString_AsString(PyObject_Str(exc_type))); if (PyObject_Str(exc_value)) CLog::Log(LOGERROR, "Error Contents: %s", PyString_AsString(PyObject_Str(exc_value))); tracebackModule = PyImport_ImportModule((char*)"traceback"); if (tracebackModule != NULL) { PyObject *tbList, *emptyString, *strRetval; tbList = PyObject_CallMethod(tracebackModule, (char*)"format_exception", (char*)"OOO", exc_type, exc_value == NULL ? Py_None : exc_value, exc_traceback == NULL ? Py_None : exc_traceback); emptyString = PyString_FromString(""); strRetval = PyObject_CallMethod(emptyString, (char*)"join", (char*)"O", tbList); CLog::Log(LOGERROR, "%s", PyString_AsString(strRetval)); Py_DECREF(tbList); Py_DECREF(emptyString); Py_DECREF(strRetval); Py_DECREF(tracebackModule); } CLog::Log(LOGINFO, "-->End of Python script error report<--"); } else { pystring = NULL; CLog::Log(LOGINFO, "<unknown exception type>"); } CGUIDialogKaiToast *pDlgToast = (CGUIDialogKaiToast*)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST); if (pDlgToast) { CStdString desc; CStdString path; CStdString script; URIUtils::Split(m_source, path, script); if (script.Equals("default.py")) { CStdString path2; URIUtils::RemoveSlashAtEnd(path); URIUtils::Split(path, path2, script); } desc.Format(g_localizeStrings.Get(2100), script); pDlgToast->QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(257), desc); } } Py_XDECREF(exc_type); Py_XDECREF(exc_value); // caller owns all 3 Py_XDECREF(exc_traceback); // already NULL'd out Py_XDECREF(pystring); } PyObject *m = PyImport_AddModule((char*)"xbmc"); if(!m || PyObject_SetAttrString(m, (char*)"abortRequested", PyBool_FromLong(1))) CLog::Log(LOGERROR, "Scriptresult: failed to set abortRequested"); // make sure all sub threads have finished for(PyThreadState* s = state->interp->tstate_head, *old = NULL; s;) { if(s == state) { s = s->next; continue; } if(old != s) { CLog::Log(LOGINFO, "Scriptresult: Waiting on thread %"PRIu64, (uint64_t)s->thread_id); old = s; } CPyThreadState pyState; Sleep(100); pyState.Restore(); s = state->interp->tstate_head; } // pending calls must be cleared out PyXBMC_ClearPendingCalls(state); PyThreadState_Swap(NULL); PyEval_ReleaseLock(); { CSingleLock lock(m_pExecuter->m_critSection); m_threadState = NULL; } PyEval_AcquireLock(); PyThreadState_Swap(state); m_pExecuter->DeInitializeInterpreter(); Py_EndInterpreter(state); PyThreadState_Swap(NULL); PyEval_ReleaseLock(); }
bool CPythonInvoker::execute(const std::string &script, const std::vector<std::string> &arguments) { // copy the code/script into a local string buffer m_sourceFile = script; // copy the arguments into a local buffer m_argc = arguments.size(); m_argv = new char*[m_argc]; for (unsigned int i = 0; i < m_argc; i++) { m_argv[i] = new char[arguments.at(i).length() + 1]; strcpy(m_argv[i], arguments.at(i).c_str()); } CLog::Log(LOGDEBUG, "CPythonInvoker(%d, %s): start processing", GetId(), m_sourceFile.c_str()); int m_Py_file_input = Py_file_input; // get the global lock PyEval_AcquireLock(); PyThreadState* state = Py_NewInterpreter(); if (state == NULL) { PyEval_ReleaseLock(); CLog::Log(LOGERROR, "CPythonInvoker(%d, %s): FAILED to get thread state!", GetId(), m_sourceFile.c_str()); return false; } // swap in my thread state PyThreadState_Swap(state); XBMCAddon::AddonClass::Ref<XBMCAddon::Python::PythonLanguageHook> languageHook(new XBMCAddon::Python::PythonLanguageHook(state->interp)); languageHook->RegisterMe(); onInitialization(); setState(InvokerStateInitialized); std::string realFilename(CSpecialProtocol::TranslatePath(m_sourceFile)); if (realFilename == m_sourceFile) CLog::Log(LOGDEBUG, "CPythonInvoker(%d, %s): the source file to load is \"%s\"", GetId(), m_sourceFile.c_str(), m_sourceFile.c_str()); else CLog::Log(LOGDEBUG, "CPythonInvoker(%d, %s): the source file to load is \"%s\" (\"%s\")", GetId(), m_sourceFile.c_str(), m_sourceFile.c_str(), realFilename.c_str()); // get path from script file name and add python path's // this is used for python so it will search modules from script path first std::string scriptDir = URIUtils::GetDirectory(realFilename); URIUtils::RemoveSlashAtEnd(scriptDir); addPath(scriptDir); // add all addon module dependecies to path if (m_addon) { std::set<std::string> paths; getAddonModuleDeps(m_addon, paths); for (std::set<std::string>::const_iterator it = paths.begin(); it != paths.end(); ++it) addPath(*it); } else { // for backwards compatibility. // we don't have any addon so just add all addon modules installed CLog::Log(LOGWARNING, "CPythonInvoker(%d): Script invoked without an addon. Adding all addon " "modules installed to python path as fallback. This behaviour will be removed in future " "version.", GetId()); ADDON::VECADDONS addons; ADDON::CAddonMgr::Get().GetAddons(ADDON::ADDON_SCRIPT_MODULE, addons); for (unsigned int i = 0; i < addons.size(); ++i) addPath(CSpecialProtocol::TranslatePath(addons[i]->LibPath())); } // we want to use sys.path so it includes site-packages // if this fails, default to using Py_GetPath PyObject *sysMod(PyImport_ImportModule((char*)"sys")); // must call Py_DECREF when finished PyObject *sysModDict(PyModule_GetDict(sysMod)); // borrowed ref, no need to delete PyObject *pathObj(PyDict_GetItemString(sysModDict, "path")); // borrowed ref, no need to delete if (pathObj != NULL && PyList_Check(pathObj)) { for (int i = 0; i < PyList_Size(pathObj); i++) { PyObject *e = PyList_GetItem(pathObj, i); // borrowed ref, no need to delete if (e != NULL && PyString_Check(e)) addNativePath(PyString_AsString(e)); // returns internal data, don't delete or modify } } else addNativePath(Py_GetPath()); Py_DECREF(sysMod); // release ref to sysMod // set current directory and python's path. if (m_argv != NULL) PySys_SetArgv(m_argc, m_argv); #ifdef TARGET_WINDOWS std::string pyPathUtf8; g_charsetConverter.systemToUtf8(m_pythonPath, pyPathUtf8, false); CLog::Log(LOGDEBUG, "CPythonInvoker(%d, %s): setting the Python path to %s", GetId(), m_sourceFile.c_str(), pyPathUtf8.c_str()); #else // ! TARGET_WINDOWS CLog::Log(LOGDEBUG, "CPythonInvoker(%d, %s): setting the Python path to %s", GetId(), m_sourceFile.c_str(), m_pythonPath.c_str()); #endif // ! TARGET_WINDOWS PySys_SetPath((char *)m_pythonPath.c_str()); CLog::Log(LOGDEBUG, "CPythonInvoker(%d, %s): entering source directory %s", GetId(), m_sourceFile.c_str(), scriptDir.c_str()); PyObject* module = PyImport_AddModule((char*)"__main__"); PyObject* moduleDict = PyModule_GetDict(module); // when we are done initing we store thread state so we can be aborted PyThreadState_Swap(NULL); PyEval_ReleaseLock(); // we need to check if we was asked to abort before we had inited bool stopping = false; { CSingleLock lock(m_critical); m_threadState = state; stopping = m_stop; } PyEval_AcquireLock(); PyThreadState_Swap(state); bool failed = false; if (!stopping) { try { // run script from file // We need to have python open the file because on Windows the DLL that python // is linked against may not be the DLL that xbmc is linked against so // passing a FILE* to python from an fopen has the potential to crash. std::string nativeFilename(realFilename); // filename in system encoding #ifdef TARGET_WINDOWS if (!g_charsetConverter.utf8ToSystem(nativeFilename, true)) { CLog::Log(LOGERROR, "CPythonInvoker(%d, %s): can't convert filename \"%s\" to system encoding", GetId(), m_sourceFile.c_str(), realFilename.c_str()); return false; } #endif PyObject* file = PyFile_FromString((char *)nativeFilename.c_str(), (char*)"r"); FILE *fp = PyFile_AsFile(file); if (fp != NULL) { PyObject *f = PyString_FromString(nativeFilename.c_str()); PyDict_SetItemString(moduleDict, "__file__", f); onPythonModuleInitialization(moduleDict); Py_DECREF(f); setState(InvokerStateRunning); XBMCAddon::Python::PyContext pycontext; // this is a guard class that marks this callstack as being in a python context PyRun_FileExFlags(fp, nativeFilename.c_str(), m_Py_file_input, moduleDict, moduleDict, 1, NULL); } else CLog::Log(LOGERROR, "CPythonInvoker(%d, %s): %s not found!", GetId(), m_sourceFile.c_str(), m_sourceFile.c_str()); } catch (const XbmcCommons::Exception& e) { setState(InvokerStateFailed); e.LogThrowMessage(); failed = true; } catch (...) { setState(InvokerStateFailed); CLog::Log(LOGERROR, "CPythonInvoker(%d, %s): failure in script", GetId(), m_sourceFile.c_str()); failed = true; } } bool systemExitThrown = false; InvokerState stateToSet; if (!failed && !PyErr_Occurred()) { CLog::Log(LOGINFO, "CPythonInvoker(%d, %s): script successfully run", GetId(), m_sourceFile.c_str()); stateToSet = InvokerStateDone; onSuccess(); } else if (PyErr_ExceptionMatches(PyExc_SystemExit)) { systemExitThrown = true; CLog::Log(LOGINFO, "CPythonInvoker(%d, %s): script aborted", GetId(), m_sourceFile.c_str()); stateToSet = InvokerStateFailed; onAbort(); } else { stateToSet = InvokerStateFailed; // if it failed with an exception we already logged the details if (!failed) { PythonBindings::PythonToCppException e; e.LogThrowMessage(); } onError(); } // no need to do anything else because the script has already stopped if (failed) { setState(stateToSet); return true; } PyObject *m = PyImport_AddModule((char*)"xbmc"); if (m == NULL || PyObject_SetAttrString(m, (char*)"abortRequested", PyBool_FromLong(1))) CLog::Log(LOGERROR, "CPythonInvoker(%d, %s): failed to set abortRequested", GetId(), m_sourceFile.c_str()); // make sure all sub threads have finished for (PyThreadState* s = state->interp->tstate_head, *old = NULL; s;) { if (s == state) { s = s->next; continue; } if (old != s) { CLog::Log(LOGINFO, "CPythonInvoker(%d, %s): waiting on thread %" PRIu64, GetId(), m_sourceFile.c_str(), (uint64_t)s->thread_id); old = s; } CPyThreadState pyState; Sleep(100); pyState.Restore(); s = state->interp->tstate_head; } // pending calls must be cleared out XBMCAddon::RetardedAsynchCallbackHandler::clearPendingCalls(state); PyThreadState_Swap(NULL); PyEval_ReleaseLock(); // set stopped event - this allows ::stop to run and kill remaining threads // this event has to be fired without holding m_critical // also the GIL (PyEval_AcquireLock) must not be held // if not obeyed there is still no deadlock because ::stop waits with timeout (smart one!) m_stoppedEvent.Set(); { CSingleLock lock(m_critical); m_threadState = NULL; } PyEval_AcquireLock(); PyThreadState_Swap(state); onDeinitialization(); // run the gc before finishing // // if the script exited by throwing a SystemExit excepton then going back // into the interpreter causes this python bug to get hit: // http://bugs.python.org/issue10582 // and that causes major failures. So we are not going to go back in // to run the GC if that's the case. if (!m_stop && languageHook->HasRegisteredAddonClasses() && !systemExitThrown && PyRun_SimpleString(GC_SCRIPT) == -1) CLog::Log(LOGERROR, "CPythonInvoker(%d, %s): failed to run the gc to clean up after running prior to shutting down the Interpreter", GetId(), m_sourceFile.c_str()); Py_EndInterpreter(state); // If we still have objects left around, produce an error message detailing what's been left behind if (languageHook->HasRegisteredAddonClasses()) CLog::Log(LOGWARNING, "CPythonInvoker(%d, %s): the python script \"%s\" has left several " "classes in memory that we couldn't clean up. The classes include: %s", GetId(), m_sourceFile.c_str(), m_sourceFile.c_str(), getListOfAddonClassesAsString(languageHook).c_str()); // unregister the language hook languageHook->UnregisterMe(); PyEval_ReleaseLock(); setState(stateToSet); return true; }
int CGUIWindowAddonBrowser::SelectAddonID(const vector<ADDON::TYPE> &types, CStdStringArray &addonIDs, bool showNone /*= false*/, bool multipleSelection /*= true*/) { CGUIDialogSelect *dialog = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT); if (!dialog) return 0; CFileItemList items; CStdString heading; int iTypes = 0; for (vector<ADDON::TYPE>::const_iterator it = types.begin(); it != types.end(); ++it) { if (*it == ADDON_UNKNOWN) continue; ADDON::VECADDONS addons; iTypes++; if (*it == ADDON_AUDIO) CAddonsDirectory::GetScriptsAndPlugins("audio",addons); else if (*it == ADDON_EXECUTABLE) CAddonsDirectory::GetScriptsAndPlugins("executable",addons); else if (*it == ADDON_IMAGE) CAddonsDirectory::GetScriptsAndPlugins("image",addons); else if (*it == ADDON_VIDEO) CAddonsDirectory::GetScriptsAndPlugins("video",addons); else CAddonMgr::Get().GetAddons(*it, addons); for (ADDON::IVECADDONS it2 = addons.begin() ; it2 != addons.end() ; ++it2) { CFileItemPtr item(CAddonsDirectory::FileItemFromAddon(*it2, "")); if (!items.Contains(item->GetPath())) items.Add(item); } if (!heading.IsEmpty()) heading += ", "; heading += TranslateType(*it, true); } if (iTypes == 0) return 0; dialog->SetHeading(heading); dialog->Reset(); dialog->SetUseDetails(true); if (multipleSelection) showNone = false; if (multipleSelection || iTypes > 1) dialog->EnableButton(true, 186); else dialog->EnableButton(true, 21452); if (showNone) { CFileItemPtr item(new CFileItem("", false)); item->SetLabel(g_localizeStrings.Get(231)); item->SetLabel2(g_localizeStrings.Get(24040)); item->SetIconImage("DefaultAddonNone.png"); item->SetSpecialSort(SortSpecialOnTop); items.Add(item); } items.Sort(SORT_METHOD_LABEL, SortOrderAscending); if (addonIDs.size() > 0) { for (CStdStringArray::const_iterator it = addonIDs.begin(); it != addonIDs.end() ; it++) { CFileItemPtr item = items.Get(*it); if (item) item->Select(true); } } dialog->SetItems(&items); dialog->SetMultiSelection(multipleSelection); dialog->DoModal(); if (!multipleSelection && iTypes == 1 && dialog->IsButtonPressed()) { // switch to the addons browser. vector<CStdString> params; params.push_back("addons://all/"+TranslateType(types[0],false)+"/"); params.push_back("return"); g_windowManager.ActivateWindow(WINDOW_ADDON_BROWSER, params); return 2; } if (!dialog->IsConfirmed()) return 0; addonIDs.clear(); const CFileItemList& list = dialog->GetSelectedItems(); for (int i = 0 ; i < list.Size() ; i++) addonIDs.push_back(list.Get(i)->GetPath()); return 1; }
CDVDInputStream* CDVDFactoryInputStream::CreateInputStream(IVideoPlayer* pPlayer, const CFileItem &fileitem, bool scanforextaudio) { std::string file = fileitem.GetPath(); if (scanforextaudio) { // find any available external audio tracks std::vector<std::string> filenames; filenames.push_back(file); CUtil::ScanForExternalAudio(file, filenames); CUtil::ScanForExternalDemuxSub(file, filenames); if (filenames.size() >= 2) { return CreateInputStream(pPlayer, fileitem, filenames); } } ADDON::VECADDONS addons; ADDON::CBinaryAddonCache &addonCache = CServiceBroker::GetBinaryAddonCache(); addonCache.GetAddons(addons, ADDON::ADDON_INPUTSTREAM); for (size_t i=0; i<addons.size(); ++i) { std::shared_ptr<ADDON::CInputStream> input(std::static_pointer_cast<ADDON::CInputStream>(addons[i])); if (input->Supports(fileitem)) { std::shared_ptr<ADDON::CInputStream> addon = input; if (!input->UseParent()) addon = std::shared_ptr<ADDON::CInputStream>(new ADDON::CInputStream(*input)); ADDON_STATUS status = addon->Create(); if (status == ADDON_STATUS_OK) { unsigned int videoWidth, videoHeight; pPlayer->GetVideoResolution(videoWidth, videoHeight); addon->SetVideoResolution(videoWidth, videoHeight); return new CInputStreamAddon(fileitem, addon); } } } if (fileitem.IsDiscImage()) { #ifdef HAVE_LIBBLURAY CURL url("udf://"); url.SetHostName(file); url.SetFileName("BDMV/index.bdmv"); if(XFILE::CFile::Exists(url.Get())) return new CDVDInputStreamBluray(pPlayer, fileitem); #endif return new CDVDInputStreamNavigator(pPlayer, fileitem); } #ifdef HAS_DVD_DRIVE if(file.compare(g_mediaManager.TranslateDevicePath("")) == 0) { #ifdef HAVE_LIBBLURAY if(XFILE::CFile::Exists(URIUtils::AddFileToFolder(file, "BDMV/index.bdmv"))) return new CDVDInputStreamBluray(pPlayer, fileitem); #endif return new CDVDInputStreamNavigator(pPlayer, fileitem); } #endif if (fileitem.IsDVDFile(false, true)) return (new CDVDInputStreamNavigator(pPlayer, fileitem)); else if(file.substr(0, 6) == "pvr://") return new CDVDInputStreamPVRManager(pPlayer, fileitem); #ifdef HAVE_LIBBLURAY else if (fileitem.IsType(".bdmv") || fileitem.IsType(".mpls") || file.substr(0, 7) == "bluray:") return new CDVDInputStreamBluray(pPlayer, fileitem); #endif else if(file.substr(0, 6) == "rtp://" || file.substr(0, 7) == "rtsp://" || file.substr(0, 6) == "sdp://" || file.substr(0, 6) == "udp://" || file.substr(0, 6) == "tcp://" || file.substr(0, 6) == "mms://" || file.substr(0, 7) == "mmst://" || file.substr(0, 7) == "mmsh://") return new CDVDInputStreamFFmpeg(fileitem); #ifdef ENABLE_DVDINPUTSTREAM_STACK else if(file.substr(0, 8) == "stack://") return new CDVDInputStreamStack(fileitem); #endif else if (fileitem.IsInternetStream()) { if (fileitem.IsType(".m3u8")) return new CDVDInputStreamFFmpeg(fileitem); if (fileitem.GetMimeType() == "application/vnd.apple.mpegurl") return new CDVDInputStreamFFmpeg(fileitem); } // our file interface handles all these types of streams return (new CDVDInputStreamFile(fileitem)); }
bool CLangInfo::SetLanguage(bool& fallback, const std::string &strLanguage /* = "" */, bool reloadServices /* = true */) { fallback = false; std::string language = strLanguage; if (language.empty()) { language = CSettings::GetInstance().GetString(CSettings::SETTING_LOCALE_LANGUAGE); if (language.empty()) { CLog::Log(LOGFATAL, "CLangInfo: cannot load empty language."); return false; } } LanguageResourcePtr languageAddon = GetLanguageAddon(language); if (languageAddon == NULL) { CLog::Log(LOGWARNING, "CLangInfo: unable to load language \"%s\". Trying to determine matching language addon...", language.c_str()); // we may have to fall back to the default language std::string defaultLanguage = static_cast<CSettingString*>(CSettings::GetInstance().GetSetting(CSettings::SETTING_LOCALE_LANGUAGE))->GetDefault(); std::string newLanguage = defaultLanguage; // try to determine a language addon matching the given language in name if (!ADDON::CLanguageResource::FindLanguageAddonByName(language, newLanguage)) { CLog::Log(LOGWARNING, "CLangInfo: unable to find an installed language addon matching \"%s\". Trying to find an installable language...", language.c_str()); bool foundMatchingAddon = false; CAddonDatabase addondb; if (addondb.Open()) { // update the addon repositories to check if there's a matching language addon available for download CAddonInstaller::GetInstance().UpdateRepos(true, true); ADDON::VECADDONS languageAddons; if (addondb.GetAddons(languageAddons, ADDON::ADDON_RESOURCE_LANGUAGE) && !languageAddons.empty()) { // try to get the proper language addon by its name from all available language addons if (ADDON::CLanguageResource::FindLanguageAddonByName(language, newLanguage, languageAddons)) { if (CAddonInstaller::GetInstance().Install(newLanguage, true, "", false, false)) { CLog::Log(LOGINFO, "CLangInfo: successfully installed language addon \"%s\" matching current language \"%s\"", newLanguage.c_str(), language.c_str()); foundMatchingAddon = true; } else CLog::Log(LOGERROR, "CLangInfo: failed to installed language addon \"%s\" matching current language \"%s\"", newLanguage.c_str(), language.c_str()); } else CLog::Log(LOGERROR, "CLangInfo: unable to match old language \"%s\" to any available language addon", language.c_str()); } else CLog::Log(LOGERROR, "CLangInfo: no language addons available to match against \"%s\"", language.c_str()); } else CLog::Log(LOGERROR, "CLangInfo: unable to open addon database to look for a language addon matching \"%s\"", language.c_str()); // if the new language matches the default language we are loading the // default language as a fallback if (!foundMatchingAddon && newLanguage == defaultLanguage) { CLog::Log(LOGINFO, "CLangInfo: fall back to the default language \"%s\"", defaultLanguage.c_str()); fallback = true; } } if (!CSettings::GetInstance().SetString(CSettings::SETTING_LOCALE_LANGUAGE, newLanguage)) return false; CSettings::GetInstance().Save(); return true; } CLog::Log(LOGINFO, "CLangInfo: loading %s language information...", language.c_str()); if (!Load(language)) { CLog::LogF(LOGFATAL, "CLangInfo: failed to load %s language information", language.c_str()); return false; } CLog::Log(LOGINFO, "CLangInfo: loading %s language strings...", language.c_str()); if (!g_localizeStrings.Load(GetLanguagePath(), language)) { CLog::LogF(LOGFATAL, "CLangInfo: failed to load %s language strings", language.c_str()); return false; } if (reloadServices) { // also tell our weather and skin to reload as these are localized g_weatherManager.Refresh(); g_PVRManager.LocalizationChanged(); CApplicationMessenger::GetInstance().PostMsg(TMSG_EXECUTE_BUILT_IN, -1, -1, nullptr, "ReloadSkin"); } return true; }
bool CSystemGUIInfo::GetBool(bool& value, const CGUIListItem *gitem, int contextWindow, const CGUIInfo &info) const { switch (info.m_info) { /////////////////////////////////////////////////////////////////////////////////////////////// // SYSTEM_* /////////////////////////////////////////////////////////////////////////////////////////////// case SYSTEM_ALWAYS_TRUE: value = true; return true; case SYSTEM_ALWAYS_FALSE: value = false; return true; case SYSTEM_ETHERNET_LINK_ACTIVE: // wtf: not implementated - always returns true?! value = true; return true; case SYSTEM_PLATFORM_LINUX: #if defined(TARGET_LINUX) || defined(TARGET_FREEBSD) value = true; #else value = false; #endif return true; case SYSTEM_PLATFORM_WINDOWS: #ifdef TARGET_WINDOWS value = true; #else value = false; #endif return true; case SYSTEM_PLATFORM_UWP: #ifdef TARGET_WINDOWS_STORE value = true; #else value = false; #endif return true; case SYSTEM_PLATFORM_DARWIN: #ifdef TARGET_DARWIN value = true; #else value = false; #endif return true; case SYSTEM_PLATFORM_DARWIN_OSX: #ifdef TARGET_DARWIN_OSX value = true; #else value = false; #endif return true; case SYSTEM_PLATFORM_DARWIN_IOS: #ifdef TARGET_DARWIN_IOS value = true; #else value = false; #endif return true; case SYSTEM_PLATFORM_ANDROID: #if defined(TARGET_ANDROID) value = true; #else value = false; #endif return true; case SYSTEM_PLATFORM_LINUX_RASPBERRY_PI: #if defined(TARGET_RASPBERRY_PI) value = true; #else value = false; #endif return true; case SYSTEM_MEDIA_DVD: value = g_mediaManager.IsDiscInDrive(); return true; case SYSTEM_MEDIA_AUDIO_CD: #ifdef HAS_DVD_DRIVE if (g_mediaManager.IsDiscInDrive()) { MEDIA_DETECT::CCdInfo *pCdInfo = g_mediaManager.GetCdInfo(); value = pCdInfo && (pCdInfo->IsAudio(1) || pCdInfo->IsCDExtra(1) || pCdInfo->IsMixedMode(1)); } else #endif { value = false; } return true; #ifdef HAS_DVD_DRIVE case SYSTEM_DVDREADY: value = g_mediaManager.GetDriveStatus() != DRIVE_NOT_READY; return true; case SYSTEM_TRAYOPEN: value = g_mediaManager.GetDriveStatus() == DRIVE_OPEN; return true; #endif case SYSTEM_CAN_POWERDOWN: value = CServiceBroker::GetPowerManager().CanPowerdown(); return true; case SYSTEM_CAN_SUSPEND: value = CServiceBroker::GetPowerManager().CanSuspend(); return true; case SYSTEM_CAN_HIBERNATE: value = CServiceBroker::GetPowerManager().CanHibernate(); return true; case SYSTEM_CAN_REBOOT: value = CServiceBroker::GetPowerManager().CanReboot(); return true; case SYSTEM_SCREENSAVER_ACTIVE: value = g_application.IsInScreenSaver(); return true; case SYSTEM_DPMS_ACTIVE: value = g_application.IsDPMSActive(); return true; case SYSTEM_HASLOCKS: value = CServiceBroker::GetSettingsComponent()->GetProfileManager()->GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE; return true; case SYSTEM_HAS_PVR: value = true; return true; case SYSTEM_HAS_PVR_ADDON: { ADDON::VECADDONS pvrAddons; ADDON::CBinaryAddonCache &addonCache = CServiceBroker::GetBinaryAddonCache(); addonCache.GetAddons(pvrAddons, ADDON::ADDON_PVRDLL); value = (pvrAddons.size() > 0); return true; } case SYSTEM_HAS_CMS: #if defined(HAS_GL) || defined(HAS_DX) value = true; #else value = false; #endif return true; case SYSTEM_ISMASTER: value = CServiceBroker::GetSettingsComponent()->GetProfileManager()->GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE && g_passwordManager.bMasterUser; return true; case SYSTEM_ISFULLSCREEN: value = CServiceBroker::GetWinSystem()->IsFullScreen(); return true; case SYSTEM_ISSTANDALONE: value = g_application.IsStandAlone(); return true; case SYSTEM_ISINHIBIT: value = g_application.IsIdleShutdownInhibited(); return true; case SYSTEM_HAS_SHUTDOWN: value = (CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_POWERMANAGEMENT_SHUTDOWNTIME) > 0); return true; case SYSTEM_LOGGEDON: value = !(CServiceBroker::GetGUI()->GetWindowManager().GetActiveWindow() == WINDOW_LOGIN_SCREEN); return true; case SYSTEM_SHOW_EXIT_BUTTON: value = CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_showExitButton; return true; case SYSTEM_HAS_LOGINSCREEN: value = CServiceBroker::GetSettingsComponent()->GetProfileManager()->UsingLoginScreen(); return true; case SYSTEM_INTERNET_STATE: { g_sysinfo.GetInfo(info.m_info); value = g_sysinfo.HasInternet(); return true; } case SYSTEM_IDLE_TIME: value = g_application.GlobalIdleTime() >= static_cast<int>(info.GetData1()); return true; case SYSTEM_HAS_CORE_ID: value = g_cpuInfo.HasCoreId(info.GetData1()); return true; case SYSTEM_DATE: { if (info.GetData2() == -1) // info doesn't contain valid startDate return false; const CDateTime date = CDateTime::GetCurrentDateTime(); int currentDate = date.GetMonth() * 100 + date.GetDay(); int startDate = info.GetData1(); int stopDate = info.GetData2(); if (stopDate < startDate) value = currentDate >= startDate || currentDate < stopDate; else value = currentDate >= startDate && currentDate < stopDate; return true; } case SYSTEM_TIME: { int currentTime = CDateTime::GetCurrentDateTime().GetMinuteOfDay(); int startTime = info.GetData1(); int stopTime = info.GetData2(); if (stopTime < startTime) value = currentTime >= startTime || currentTime < stopTime; else value = currentTime >= startTime && currentTime < stopTime; return true; } case SYSTEM_ALARM_LESS_OR_EQUAL: { int time = std::lrint(g_alarmClock.GetRemaining(info.GetData3())); int timeCompare = info.GetData2(); if (time > 0) value = timeCompare >= time; else value = false; return true; } case SYSTEM_HAS_ALARM: value = g_alarmClock.HasAlarm(info.GetData3()); return true; case SYSTEM_GET_BOOL: value = CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(info.GetData3()); return true; case SYSTEM_SETTING: { if (StringUtils::EqualsNoCase(info.GetData3(), "hidewatched")) { CGUIMediaWindow* window = GUIINFO::GetMediaWindow(contextWindow); if (window) { value = CMediaSettings::GetInstance().GetWatchedMode(window->CurrentDirectory().GetContent()) == WatchedModeUnwatched; return true; } } break; } } return false; }
void XBPyThread::Process() { CLog::Log(LOGDEBUG,"Python thread: start processing"); int m_Py_file_input = Py_file_input; // get the global lock PyEval_AcquireLock(); PyThreadState* state = Py_NewInterpreter(); if (!state) { PyEval_ReleaseLock(); CLog::Log(LOGERROR,"Python thread: FAILED to get thread state!"); return; } // swap in my thread state PyThreadState_Swap(state); XBMCAddon::AddonClass::Ref<XBMCAddon::Python::LanguageHook> languageHook(new XBMCAddon::Python::LanguageHook(state->interp)); languageHook->RegisterMe(); m_pExecuter->InitializeInterpreter(addon); CLog::Log(LOGDEBUG, "%s - The source file to load is %s", __FUNCTION__, m_source); // get path from script file name and add python path's // this is used for python so it will search modules from script path first CStdString scriptDir; URIUtils::GetDirectory(CSpecialProtocol::TranslatePath(m_source), scriptDir); URIUtils::RemoveSlashAtEnd(scriptDir); CStdString path = scriptDir; // add on any addon modules the user has installed ADDON::VECADDONS addons; ADDON::CAddonMgr::Get().GetAddons(ADDON::ADDON_SCRIPT_MODULE, addons); for (unsigned int i = 0; i < addons.size(); ++i) #ifdef TARGET_WINDOWS { CStdString strTmp(CSpecialProtocol::TranslatePath(addons[i]->LibPath())); g_charsetConverter.utf8ToSystem(strTmp); path += PY_PATH_SEP + strTmp; } #else path += PY_PATH_SEP + CSpecialProtocol::TranslatePath(addons[i]->LibPath()); #endif // and add on whatever our default path is path += PY_PATH_SEP; // we want to use sys.path so it includes site-packages // if this fails, default to using Py_GetPath PyObject *sysMod(PyImport_ImportModule((char*)"sys")); // must call Py_DECREF when finished PyObject *sysModDict(PyModule_GetDict(sysMod)); // borrowed ref, no need to delete PyObject *pathObj(PyDict_GetItemString(sysModDict, "path")); // borrowed ref, no need to delete if( pathObj && PyList_Check(pathObj) ) { for( int i = 0; i < PyList_Size(pathObj); i++ ) { PyObject *e = PyList_GetItem(pathObj, i); // borrowed ref, no need to delete if( e && PyString_Check(e) ) { path += PyString_AsString(e); // returns internal data, don't delete or modify path += PY_PATH_SEP; } } } else { path += Py_GetPath(); } Py_DECREF(sysMod); // release ref to sysMod // set current directory and python's path. if (m_argv != NULL) PySys_SetArgv(m_argc, m_argv); CLog::Log(LOGDEBUG, "%s - Setting the Python path to %s", __FUNCTION__, path.c_str()); PySys_SetPath((char *)path.c_str()); CLog::Log(LOGDEBUG, "%s - Entering source directory %s", __FUNCTION__, scriptDir.c_str()); PyObject* module = PyImport_AddModule((char*)"__main__"); PyObject* moduleDict = PyModule_GetDict(module); // when we are done initing we store thread state so we can be aborted PyThreadState_Swap(NULL); PyEval_ReleaseLock(); // we need to check if we was asked to abort before we had inited bool stopping = false; { CSingleLock lock(m_pExecuter->m_critSection); m_threadState = state; stopping = m_stopping; } PyEval_AcquireLock(); PyThreadState_Swap(state); if (!stopping) { try { if (m_type == 'F') { // run script from file // We need to have python open the file because on Windows the DLL that python // is linked against may not be the DLL that xbmc is linked against so // passing a FILE* to python from an fopen has the potential to crash. PyObject* file = PyFile_FromString((char *) CSpecialProtocol::TranslatePath(m_source).c_str(), (char*)"r"); FILE *fp = PyFile_AsFile(file); if (fp) { PyObject *f = PyString_FromString(CSpecialProtocol::TranslatePath(m_source).c_str()); PyDict_SetItemString(moduleDict, "__file__", f); if (addon.get() != NULL) { PyObject *pyaddonid = PyString_FromString(addon->ID().c_str()); PyDict_SetItemString(moduleDict, "__xbmcaddonid__", pyaddonid); CStdString version = ADDON::GetXbmcApiVersionDependency(addon); PyObject *pyxbmcapiversion = PyString_FromString(version.c_str()); PyDict_SetItemString(moduleDict, "__xbmcapiversion__", pyxbmcapiversion); CLog::Log(LOGDEBUG,"Instantiating addon using automatically obtained id of \"%s\" dependent on version %s of the xbmc.python api",addon->ID().c_str(),version.c_str()); } Py_DECREF(f); XBMCAddon::Python::PyContext pycontext; // this is a guard class that marks this callstack as being in a python context PyRun_FileExFlags(fp, CSpecialProtocol::TranslatePath(m_source).c_str(), m_Py_file_input, moduleDict, moduleDict,1,NULL); } else CLog::Log(LOGERROR, "%s not found!", m_source); } else { //run script PyRun_String(m_source, m_Py_file_input, moduleDict, moduleDict); } } catch (const XbmcCommons::Exception& e) { e.LogThrowMessage(); } catch (...) { CLog::Log(LOGERROR, "failure in %s", m_source); } } if (!PyErr_Occurred()) CLog::Log(LOGINFO, "Scriptresult: Success"); else if (PyErr_ExceptionMatches(PyExc_SystemExit)) CLog::Log(LOGINFO, "Scriptresult: Aborted"); else { PythonBindings::PythonToCppException e; e.LogThrowMessage(); { CPyThreadState releaseGil; CSingleLock gc(g_graphicsContext); CGUIDialogKaiToast *pDlgToast = (CGUIDialogKaiToast*)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST); if (pDlgToast) { CStdString desc; CStdString path; CStdString script; URIUtils::Split(m_source, path, script); if (script.Equals("default.py")) { CStdString path2; URIUtils::RemoveSlashAtEnd(path); URIUtils::Split(path, path2, script); } desc.Format(g_localizeStrings.Get(2100), script); pDlgToast->QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(257), desc); } } } PyObject *m = PyImport_AddModule((char*)"xbmc"); if(!m || PyObject_SetAttrString(m, (char*)"abortRequested", PyBool_FromLong(1))) CLog::Log(LOGERROR, "Scriptresult: failed to set abortRequested"); // make sure all sub threads have finished for(PyThreadState* s = state->interp->tstate_head, *old = NULL; s;) { if(s == state) { s = s->next; continue; } if(old != s) { CLog::Log(LOGINFO, "Scriptresult: Waiting on thread %"PRIu64, (uint64_t)s->thread_id); old = s; } CPyThreadState pyState; Sleep(100); pyState.Restore(); s = state->interp->tstate_head; } // pending calls must be cleared out XBMCAddon::RetardedAsynchCallbackHandler::clearPendingCalls(state); PyThreadState_Swap(NULL); PyEval_ReleaseLock(); //set stopped event - this allows ::stop to run and kill remaining threads //this event has to be fired without holding m_pExecuter->m_critSection //before //Also the GIL (PyEval_AcquireLock) must not be held //if not obeyed there is still no deadlock because ::stop waits with timeout (smart one!) stoppedEvent.Set(); { CSingleLock lock(m_pExecuter->m_critSection); m_threadState = NULL; } PyEval_AcquireLock(); PyThreadState_Swap(state); m_pExecuter->DeInitializeInterpreter(); // run the gc before finishing if (!m_stopping && languageHook->HasRegisteredAddonClasses() && PyRun_SimpleString(GC_SCRIPT) == -1) CLog::Log(LOGERROR,"Failed to run the gc to clean up after running prior to shutting down the Interpreter %s",m_source); Py_EndInterpreter(state); // This is a total hack. Python doesn't necessarily release // all of the objects associated with the interpreter when // you end the interpreter. As a result there are objects // managed by the windowing system that still receive events // until python decides to clean them up. Python will eventually // clean them up on the creation or ending of a subsequent // interpreter. So we are going to keep creating and ending // interpreters until we have no more python objects hanging // around. if (languageHook->HasRegisteredAddonClasses()) { CLog::Log(LOGDEBUG, "The python script \"%s\" has left several " "classes in memory that we will be attempting to clean up. The classes include: %s", m_source, getListOfAddonClassesAsString(languageHook).c_str()); int countLimit; for (countLimit = 0; languageHook->HasRegisteredAddonClasses() && countLimit < 100; countLimit++) { PyThreadState* tmpstate = Py_NewInterpreter(); PyThreadState* oldstate = PyThreadState_Swap(tmpstate); if (PyRun_SimpleString(GC_SCRIPT) == -1) CLog::Log(LOGERROR,"Failed to run the gc to clean up after running %s",m_source); PyThreadState_Swap(oldstate); Py_EndInterpreter(tmpstate); } // If necessary and successfull, debug log the results. if (countLimit > 0 && !languageHook->HasRegisteredAddonClasses()) CLog::Log(LOGDEBUG,"It took %d Py_NewInterpreter/Py_EndInterpreter calls" " to clean up the classes leftover from running \"%s.\"", countLimit,m_source); // If not successful, produce an error message detailing what's been left behind if (languageHook->HasRegisteredAddonClasses()) CLog::Log(LOGERROR, "The python script \"%s\" has left several " "classes in memory that we couldn't clean up. The classes include: %s", m_source, getListOfAddonClassesAsString(languageHook).c_str()); } // unregister the language hook languageHook->UnregisterMe(); PyThreadState_Swap(NULL); PyEval_ReleaseLock(); }
bool CPVRClients::UpdateAndInitialiseClients(bool bInitialiseAllClients /* = false */) { bool bReturn(true); ADDON::VECADDONS map; ADDON::VECADDONS disableAddons; { CSingleLock lock(m_critSection); map = m_addons; } if (map.size() == 0) return false; for (unsigned iClientPtr = 0; iClientPtr < map.size(); iClientPtr++) { const AddonPtr clientAddon = map.at(iClientPtr); bool bEnabled = clientAddon->Enabled() && !m_addonDb.IsAddonDisabled(clientAddon->ID()); if (!bEnabled && IsKnownClient(clientAddon)) { CSingleLock lock(m_critSection); /* stop the client and remove it from the db */ StopClient(clientAddon, false); ADDON::VECADDONS::iterator addonPtr = std::find(m_addons.begin(), m_addons.end(), clientAddon); if (addonPtr != m_addons.end()) m_addons.erase(addonPtr); } else if (bEnabled && (bInitialiseAllClients || !IsKnownClient(clientAddon) || !IsConnectedClient(clientAddon))) { bool bDisabled(false); // register the add-on in the pvr db, and create the CPVRClient instance int iClientId = RegisterClient(clientAddon); if (iClientId < 0) { // failed to register or create the add-on, disable it CLog::Log(LOGWARNING, "%s - failed to register add-on %s, disabling it", __FUNCTION__, clientAddon->Name().c_str()); disableAddons.push_back(clientAddon); bDisabled = true; } else { PVR_CLIENT addon; if (!GetClient(iClientId, addon)) { CLog::Log(LOGWARNING, "%s - failed to find add-on %s, disabling it", __FUNCTION__, clientAddon->Name().c_str()); disableAddons.push_back(clientAddon); bDisabled = true; } // re-check the enabled status. newly installed clients get disabled when they're added to the db else if (addon->Enabled() && !addon->Create(iClientId)) { CLog::Log(LOGWARNING, "%s - failed to create add-on %s", __FUNCTION__, clientAddon->Name().c_str()); if (!addon.get() || !addon->DllLoaded()) { // failed to load the dll of this add-on, disable it CLog::Log(LOGWARNING, "%s - failed to load the dll for add-on %s, disabling it", __FUNCTION__, clientAddon->Name().c_str()); disableAddons.push_back(clientAddon); bDisabled = true; } } } if (bDisabled && (g_PVRManager.GetState() == ManagerStateStarted || g_PVRManager.GetState() == ManagerStateStarting)) CGUIDialogOK::ShowAndGetInput(24070, 24071, 16029, 0); } } // disable add-ons that failed to initialise if (disableAddons.size() > 0) { CSingleLock lock(m_critSection); for (ADDON::VECADDONS::iterator it = disableAddons.begin(); it != disableAddons.end(); it++) { // disable in the add-on db m_addonDb.DisableAddon((*it)->ID(), true); // remove from the pvr add-on list ADDON::VECADDONS::iterator addonPtr = std::find(m_addons.begin(), m_addons.end(), *it); if (addonPtr != m_addons.end()) m_addons.erase(addonPtr); } } return bReturn; }
bool CPythonInvoker::execute(const std::string &script, const std::vector<std::string> &arguments) { // copy the code/script into a local string buffer #ifdef TARGET_WINDOWS CStdString strsrc = script; g_charsetConverter.utf8ToSystem(strsrc); m_source = new char[strsrc.length() + 1]; strcpy(m_source, strsrc); #else m_source = new char[script.length() + 1]; strcpy(m_source, script.c_str()); #endif // copy the arguments into a local buffer m_argc = arguments.size(); m_argv = new char*[m_argc]; for (unsigned int i = 0; i < m_argc; i++) { m_argv[i] = new char[arguments.at(i).length() + 1]; strcpy(m_argv[i], arguments.at(i).c_str()); } CLog::Log(LOGDEBUG, "CPythonInvoker(%d, %s): start processing", GetId(), m_source); int m_Py_file_input = Py_file_input; // get the global lock PyEval_AcquireLock(); PyThreadState* state = Py_NewInterpreter(); if (state == NULL) { PyEval_ReleaseLock(); CLog::Log(LOGERROR, "CPythonInvoker(%d, %s): FAILED to get thread state!", GetId(), m_source); return false; } // swap in my thread state PyThreadState_Swap(state); XBMCAddon::AddonClass::Ref<XBMCAddon::Python::LanguageHook> languageHook(new XBMCAddon::Python::LanguageHook(state->interp)); languageHook->RegisterMe(); g_pythonParser.InitializeInterpreter(m_addon); setState(InvokerStateInitialized); CLog::Log(LOGDEBUG, "CPythonInvoker(%d, %s): the source file to load is %s", GetId(), m_source, m_source); // get path from script file name and add python path's // this is used for python so it will search modules from script path first CStdString scriptDir; URIUtils::GetDirectory(CSpecialProtocol::TranslatePath(m_source), scriptDir); URIUtils::RemoveSlashAtEnd(scriptDir); addPath(scriptDir); // add on any addon modules the user has installed ADDON::VECADDONS addons; ADDON::CAddonMgr::Get().GetAddons(ADDON::ADDON_SCRIPT_MODULE, addons); for (unsigned int i = 0; i < addons.size(); ++i) addPath(CSpecialProtocol::TranslatePath(addons[i]->LibPath())); // we want to use sys.path so it includes site-packages // if this fails, default to using Py_GetPath PyObject *sysMod(PyImport_ImportModule((char*)"sys")); // must call Py_DECREF when finished PyObject *sysModDict(PyModule_GetDict(sysMod)); // borrowed ref, no need to delete PyObject *pathObj(PyDict_GetItemString(sysModDict, "path")); // borrowed ref, no need to delete if (pathObj != NULL && PyList_Check(pathObj)) { for (int i = 0; i < PyList_Size(pathObj); i++) { PyObject *e = PyList_GetItem(pathObj, i); // borrowed ref, no need to delete if (e != NULL && PyString_Check(e)) addPath(PyString_AsString(e)); // returns internal data, don't delete or modify } } else addPath(Py_GetPath()); Py_DECREF(sysMod); // release ref to sysMod // set current directory and python's path. if (m_argv != NULL) PySys_SetArgv(m_argc, m_argv); CLog::Log(LOGDEBUG, "CPythonInvoker(%d, %s): setting the Python path to %s", GetId(), m_source, m_pythonPath.c_str()); PySys_SetPath((char *)m_pythonPath.c_str()); CLog::Log(LOGDEBUG, "CPythonInvoker(%d, %s): entering source directory %s", GetId(), m_source, scriptDir.c_str()); PyObject* module = PyImport_AddModule((char*)"__main__"); PyObject* moduleDict = PyModule_GetDict(module); // when we are done initing we store thread state so we can be aborted PyThreadState_Swap(NULL); PyEval_ReleaseLock(); // we need to check if we was asked to abort before we had inited bool stopping = false; { CSingleLock lock(m_critical); m_threadState = state; stopping = m_stop; } PyEval_AcquireLock(); PyThreadState_Swap(state); bool failed = false; if (!stopping) { try { // run script from file // We need to have python open the file because on Windows the DLL that python // is linked against may not be the DLL that xbmc is linked against so // passing a FILE* to python from an fopen has the potential to crash. PyObject* file = PyFile_FromString((char *) CSpecialProtocol::TranslatePath(m_source).c_str(), (char*)"r"); FILE *fp = PyFile_AsFile(file); if (fp != NULL) { PyObject *f = PyString_FromString(CSpecialProtocol::TranslatePath(m_source).c_str()); PyDict_SetItemString(moduleDict, "__file__", f); if (m_addon.get() != NULL) { PyObject *pyaddonid = PyString_FromString(m_addon->ID().c_str()); PyDict_SetItemString(moduleDict, "__xbmcaddonid__", pyaddonid); CStdString version = ADDON::GetXbmcApiVersionDependency(m_addon); PyObject *pyxbmcapiversion = PyString_FromString(version.c_str()); PyDict_SetItemString(moduleDict, "__xbmcapiversion__", pyxbmcapiversion); CLog::Log(LOGDEBUG, "CPythonInvoker(%d, %s): instantiating addon using automatically obtained id of \"%s\" dependent on version %s of the xbmc.python api", GetId(), m_source, m_addon->ID().c_str(), version.c_str()); } Py_DECREF(f); setState(InvokerStateRunning); XBMCAddon::Python::PyContext pycontext; // this is a guard class that marks this callstack as being in a python context PyRun_FileExFlags(fp, CSpecialProtocol::TranslatePath(m_source).c_str(), m_Py_file_input, moduleDict, moduleDict,1,NULL); } else CLog::Log(LOGERROR, "CPythonInvoker(%d, %s): %s not found!", GetId(), m_source, m_source); } catch (const XbmcCommons::Exception& e) { setState(InvokerStateFailed); e.LogThrowMessage(); failed = true; } catch (...) { setState(InvokerStateFailed); CLog::Log(LOGERROR, "CPythonInvoker(%d, %s): failure in script", GetId(), m_source); failed = true; } } bool systemExitThrown = false; if (!failed && !PyErr_Occurred()) { CLog::Log(LOGINFO, "CPythonInvoker(%d, %s): script successfully run", GetId(), m_source); setState(InvokerStateDone); } else if (PyErr_ExceptionMatches(PyExc_SystemExit)) { systemExitThrown = true; CLog::Log(LOGINFO, "CPythonInvoker(%d, %s): script aborted", GetId(), m_source); setState(InvokerStateFailed); } else { setState(InvokerStateFailed); // if it failed with an exception we already logged the details if (!failed) { PythonBindings::PythonToCppException e; e.LogThrowMessage(); } { CPyThreadState releaseGil; CSingleLock gc(g_graphicsContext); CGUIDialogKaiToast *pDlgToast = (CGUIDialogKaiToast*)g_windowManager.GetWindow(WINDOW_DIALOG_KAI_TOAST); if (pDlgToast != NULL) { CStdString desc; CStdString script; if (m_addon.get() != NULL) script = m_addon->Name(); else { CStdString path; URIUtils::Split(m_source, path, script); if (script.Equals("default.py")) { CStdString path2; URIUtils::RemoveSlashAtEnd(path); URIUtils::Split(path, path2, script); } } desc.Format(g_localizeStrings.Get(2100), script); pDlgToast->QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(257), desc); } } } // no need to do anything else because the script has already stopped if (failed) return true; PyObject *m = PyImport_AddModule((char*)"xbmc"); if (m == NULL || PyObject_SetAttrString(m, (char*)"abortRequested", PyBool_FromLong(1))) CLog::Log(LOGERROR, "CPythonInvoker(%d, %s): failed to set abortRequested", GetId(), m_source); // make sure all sub threads have finished for (PyThreadState* s = state->interp->tstate_head, *old = NULL; s;) { if (s == state) { s = s->next; continue; } if (old != s) { CLog::Log(LOGINFO, "CPythonInvoker(%d, %s): waiting on thread %"PRIu64, GetId(), m_source, (uint64_t)s->thread_id); old = s; } CPyThreadState pyState; Sleep(100); pyState.Restore(); s = state->interp->tstate_head; } // pending calls must be cleared out XBMCAddon::RetardedAsynchCallbackHandler::clearPendingCalls(state); PyThreadState_Swap(NULL); PyEval_ReleaseLock(); // set stopped event - this allows ::stop to run and kill remaining threads // this event has to be fired without holding m_critical // also the GIL (PyEval_AcquireLock) must not be held // if not obeyed there is still no deadlock because ::stop waits with timeout (smart one!) m_stoppedEvent.Set(); { CSingleLock lock(m_critical); m_threadState = NULL; } PyEval_AcquireLock(); PyThreadState_Swap(state); g_pythonParser.DeInitializeInterpreter(); // run the gc before finishing // // if the script exited by throwing a SystemExit excepton then going back // into the interpreter causes this python bug to get hit: // http://bugs.python.org/issue10582 // and that causes major failures. So we are not going to go back in // to run the GC if that's the case. if (!m_stop && languageHook->HasRegisteredAddonClasses() && !systemExitThrown && PyRun_SimpleString(GC_SCRIPT) == -1) CLog::Log(LOGERROR, "CPythonInvoker(%d, %s): failed to run the gc to clean up after running prior to shutting down the Interpreter", GetId(), m_source); Py_EndInterpreter(state); // If we still have objects left around, produce an error message detailing what's been left behind if (languageHook->HasRegisteredAddonClasses()) CLog::Log(LOGWARNING, "CPythonInvoker(%d, %s): the python script \"%s\" has left several " "classes in memory that we couldn't clean up. The classes include: %s", GetId(), m_source, m_source, getListOfAddonClassesAsString(languageHook).c_str()); // unregister the language hook languageHook->UnregisterMe(); PyEval_ReleaseLock(); return true; }
bool CPVRClients::UpdateAndInitialiseClients(bool bInitialiseAllClients /* = false */) { bool bReturn(true); ADDON::VECADDONS map; ADDON::VECADDONS disableAddons; { CSingleLock lock(m_critSection); map = m_addons; } if (map.size() == 0) return false; for (unsigned iClientPtr = 0; iClientPtr < map.size(); iClientPtr++) { const AddonPtr clientAddon = map.at(iClientPtr); bool bEnabled = clientAddon->Enabled() && !m_addonDb.IsAddonDisabled(clientAddon->ID()); if (!bEnabled && IsKnownClient(clientAddon)) { CSingleLock lock(m_critSection); /* stop the client and remove it from the db */ StopClient(clientAddon, false); ADDON::VECADDONS::iterator addonPtr = std::find(m_addons.begin(), m_addons.end(), clientAddon); if (addonPtr != m_addons.end()) m_addons.erase(addonPtr); } else if (bEnabled && (bInitialiseAllClients || !IsKnownClient(clientAddon) || !IsConnectedClient(clientAddon))) { bool bDisabled(false); // register the add-on in the pvr db, and create the CPVRClient instance int iClientId = RegisterClient(clientAddon); if (iClientId < 0) { // failed to register or create the add-on, disable it CLog::Log(LOGWARNING, "%s - failed to register add-on %s, disabling it", __FUNCTION__, clientAddon->Name().c_str()); disableAddons.push_back(clientAddon); bDisabled = true; } else { ADDON_STATUS status(ADDON_STATUS_UNKNOWN); PVR_CLIENT addon; { CSingleLock lock(m_critSection); if (!GetClient(iClientId, addon)) { CLog::Log(LOGWARNING, "%s - failed to find add-on %s, disabling it", __FUNCTION__, clientAddon->Name().c_str()); disableAddons.push_back(clientAddon); bDisabled = true; } } // throttle connection attempts, no more than 1 attempt per 5 seconds if (!bDisabled && addon->Enabled()) { time_t now; CDateTime::GetCurrentDateTime().GetAsTime(now); std::map<int, time_t>::iterator it = m_connectionAttempts.find(iClientId); if (it != m_connectionAttempts.end() && now < it->second) continue; m_connectionAttempts[iClientId] = now + 5; } // re-check the enabled status. newly installed clients get disabled when they're added to the db if (!bDisabled && addon->Enabled() && (status = addon->Create(iClientId)) != ADDON_STATUS_OK) { CLog::Log(LOGWARNING, "%s - failed to create add-on %s, status = %d", __FUNCTION__, clientAddon->Name().c_str(), status); if (!addon.get() || !addon->DllLoaded() || status == ADDON_STATUS_PERMANENT_FAILURE) { // failed to load the dll of this add-on, disable it CLog::Log(LOGWARNING, "%s - failed to load the dll for add-on %s, disabling it", __FUNCTION__, clientAddon->Name().c_str()); disableAddons.push_back(clientAddon); bDisabled = true; } } } if (bDisabled && (g_PVRManager.GetState() == ManagerStateStarted || g_PVRManager.GetState() == ManagerStateStarting)) CGUIDialogOK::ShowAndGetInput(24070, 24071, 16029, 0); } } // disable add-ons that failed to initialise if (disableAddons.size() > 0) { CSingleLock lock(m_critSection); for (ADDON::VECADDONS::iterator it = disableAddons.begin(); it != disableAddons.end(); it++) { // disable in the add-on db m_addonDb.DisableAddon((*it)->ID(), true); // remove from the pvr add-on list ADDON::VECADDONS::iterator addonPtr = std::find(m_addons.begin(), m_addons.end(), *it); if (addonPtr != m_addons.end()) m_addons.erase(addonPtr); } } return bReturn; }
CDVDInputStream* CDVDFactoryInputStream::CreateInputStream(IVideoPlayer* pPlayer, CFileItem fileitem) { std::string file = fileitem.GetPath(); ADDON::VECADDONS addons; ADDON::CAddonMgr::GetInstance().GetAddons(addons, ADDON::ADDON_INPUTSTREAM); for (size_t i=0; i<addons.size(); ++i) { std::shared_ptr<ADDON::CInputStream> input(std::static_pointer_cast<ADDON::CInputStream>(addons[i])); ADDON::CInputStream* clone = new ADDON::CInputStream(*input); ADDON_STATUS status = clone->Supports(fileitem) ? clone->Create() : ADDON_STATUS_PERMANENT_FAILURE; if (status == ADDON_STATUS_OK) { if (clone->Supports(fileitem)) { return new CInputStreamAddon(fileitem, clone); } } delete clone; } if (fileitem.IsDiscImage()) { #ifdef HAVE_LIBBLURAY CURL url("udf://"); url.SetHostName(file); url.SetFileName("BDMV/index.bdmv"); if(XFILE::CFile::Exists(url.Get())) return new CDVDInputStreamBluray(pPlayer, fileitem); #endif return new CDVDInputStreamNavigator(pPlayer, fileitem); } #ifdef HAS_DVD_DRIVE if(file.compare(g_mediaManager.TranslateDevicePath("")) == 0) { #ifdef HAVE_LIBBLURAY if(XFILE::CFile::Exists(URIUtils::AddFileToFolder(file, "BDMV/index.bdmv"))) return new CDVDInputStreamBluray(pPlayer, fileitem); #endif return new CDVDInputStreamNavigator(pPlayer, fileitem); } #endif if (fileitem.IsDVDFile(false, true)) return (new CDVDInputStreamNavigator(pPlayer, fileitem)); else if(file.substr(0, 6) == "pvr://") return new CDVDInputStreamPVRManager(pPlayer, fileitem); #ifdef HAVE_LIBBLURAY else if (fileitem.IsType(".bdmv") || fileitem.IsType(".mpls") || file.substr(0, 7) == "bluray:") return new CDVDInputStreamBluray(pPlayer, fileitem); #endif else if(file.substr(0, 6) == "rtp://" || file.substr(0, 7) == "rtsp://" || file.substr(0, 6) == "sdp://" || file.substr(0, 6) == "udp://" || file.substr(0, 6) == "tcp://" || file.substr(0, 6) == "mms://" || file.substr(0, 7) == "mmst://" || file.substr(0, 7) == "mmsh://") return new CDVDInputStreamFFmpeg(fileitem); #ifdef ENABLE_DVDINPUTSTREAM_STACK else if(file.substr(0, 8) == "stack://") return new CDVDInputStreamStack(fileitem); #endif #ifdef HAS_LIBRTMP else if(file.substr(0, 7) == "rtmp://" || file.substr(0, 8) == "rtmpt://" || file.substr(0, 8) == "rtmpe://" || file.substr(0, 9) == "rtmpte://" || file.substr(0, 8) == "rtmps://") return new CDVDInputStreamRTMP(fileitem); #endif else if (fileitem.IsInternetStream()) { if (fileitem.IsType(".m3u8")) return new CDVDInputStreamFFmpeg(fileitem); if (fileitem.ContentLookup()) { // request header fileitem.SetMimeType(""); fileitem.FillInMimeType(); } if (fileitem.GetMimeType() == "application/vnd.apple.mpegurl") return new CDVDInputStreamFFmpeg(fileitem); } // our file interface handles all these types of streams return (new CDVDInputStreamFile(fileitem)); }