/* Searches for a control in Window->vecControls * If we can't find any but the window has the controlId (in case of a not python window) * we create a new control with basic functionality */ Control* Window::GetControlById(int iControlId, CCriticalSection* gc) { XBMC_TRACE; // find in window vector first!!! // this saves us from creating a complete new control std::vector<AddonClass::Ref<Control> >::iterator it = vecControls.begin(); while (it != vecControls.end()) { AddonClass::Ref<Control> control = (*it); if (control->iControlId == iControlId) { return control.get(); } else ++it; } // lock xbmc GUI before accessing data from it MaybeLock lock(gc); // check if control exists CGUIControl* pGUIControl = (CGUIControl*)ref(window)->GetControl(iControlId); if (!pGUIControl) { // control does not exist. throw WindowException("Non-Existent Control %d",iControlId); } // allocate a new control with a new reference CLabelInfo li; Control* pControl = NULL; // TODO: Yuck! Should probably be done with a Factory pattern switch(pGUIControl->GetControlType()) { case CGUIControl::GUICONTROL_BUTTON: pControl = new ControlButton(); li = ((CGUIButtonControl *)pGUIControl)->GetLabelInfo(); // note: conversion from infocolors -> plain colors here ((ControlButton*)pControl)->disabledColor = li.disabledColor; ((ControlButton*)pControl)->focusedColor = li.focusedColor; ((ControlButton*)pControl)->textColor = li.textColor; ((ControlButton*)pControl)->shadowColor = li.shadowColor; if (li.font) ((ControlButton*)pControl)->strFont = li.font->GetFontName(); ((ControlButton*)pControl)->align = li.align; break; case CGUIControl::GUICONTROL_CHECKMARK: pControl = new ControlCheckMark(); li = ((CGUICheckMarkControl *)pGUIControl)->GetLabelInfo(); // note: conversion to plain colors from infocolors. ((ControlCheckMark*)pControl)->disabledColor = li.disabledColor; //((ControlCheckMark*)pControl)->shadowColor = li.shadowColor; ((ControlCheckMark*)pControl)->textColor = li.textColor; if (li.font) ((ControlCheckMark*)pControl)->strFont = li.font->GetFontName(); ((ControlCheckMark*)pControl)->align = li.align; break; case CGUIControl::GUICONTROL_LABEL: pControl = new ControlLabel(); break; case CGUIControl::GUICONTROL_SPIN: pControl = new ControlSpin(); break; case CGUIControl::GUICONTROL_FADELABEL: pControl = new ControlFadeLabel(); break; case CGUIControl::GUICONTROL_TEXTBOX: pControl = new ControlTextBox(); break; case CGUIControl::GUICONTROL_IMAGE: pControl = new ControlImage(); break; case CGUIControl::GUICONTROL_PROGRESS: pControl = new ControlProgress(); break; case CGUIControl::GUICONTROL_SLIDER: pControl = new ControlSlider(); break; case CGUIControl::GUICONTAINER_LIST: case CGUIControl::GUICONTAINER_WRAPLIST: case CGUIControl::GUICONTAINER_FIXEDLIST: case CGUIControl::GUICONTAINER_PANEL: pControl = new ControlList(); // create a python spin control ((ControlList*)pControl)->pControlSpin = new ControlSpin(); break; case CGUIControl::GUICONTROL_GROUP: pControl = new ControlGroup(); break; case CGUIControl::GUICONTROL_RADIO: pControl = new ControlRadioButton(); li = ((CGUIRadioButtonControl *)pGUIControl)->GetLabelInfo(); // note: conversion from infocolors -> plain colors here ((ControlRadioButton*)pControl)->disabledColor = li.disabledColor; ((ControlRadioButton*)pControl)->focusedColor = li.focusedColor; ((ControlRadioButton*)pControl)->textColor = li.textColor; ((ControlRadioButton*)pControl)->shadowColor = li.shadowColor; if (li.font) ((ControlRadioButton*)pControl)->strFont = li.font->GetFontName(); ((ControlRadioButton*)pControl)->align = li.align; break; case CGUIControl::GUICONTROL_EDIT: pControl = new ControlEdit(); li = ((CGUIEditControl *)pGUIControl)->GetLabelInfo(); // note: conversion from infocolors -> plain colors here ((ControlEdit*)pControl)->disabledColor = li.disabledColor; ((ControlEdit*)pControl)->textColor = li.textColor; if (li.font) ((ControlEdit*)pControl)->strFont = li.font->GetFontName(); ((ControlButton*)pControl)->align = li.align; break; default: break; } if (!pControl) // throw an exeption throw WindowException("Unknown control type for python"); // we have a valid control here, fill in all the 'Control' data pControl->pGUIControl = pGUIControl; pControl->iControlId = pGUIControl->GetID(); pControl->iParentId = iWindowId; pControl->dwHeight = (int)pGUIControl->GetHeight(); pControl->dwWidth = (int)pGUIControl->GetWidth(); pControl->dwPosX = (int)pGUIControl->GetXPosition(); pControl->dwPosY = (int)pGUIControl->GetYPosition(); pControl->iControlUp = pGUIControl->GetNavigateAction(ACTION_MOVE_UP).GetNavigation(); pControl->iControlDown = pGUIControl->GetNavigateAction(ACTION_MOVE_DOWN).GetNavigation(); pControl->iControlLeft = pGUIControl->GetNavigateAction(ACTION_MOVE_LEFT).GetNavigation(); pControl->iControlRight = pGUIControl->GetNavigateAction(ACTION_MOVE_RIGHT).GetNavigation(); // It got this far so means the control isn't actually in the vector of controls // so lets add it to save doing all that next time vecControls.push_back(AddonClass::Ref<Control>(pControl)); // return the control with increased reference (+1) return pControl; }
namespace Python { static AddonClass::Ref<PythonLanguageHook> instance; static CCriticalSection hooksMutex; static std::map<PyInterpreterState*,AddonClass::Ref<PythonLanguageHook> > hooks; // vtab instantiation PythonLanguageHook::~PythonLanguageHook() { XBMC_TRACE; XBMCAddon::LanguageHook::deallocating(); } void PythonLanguageHook::MakePendingCalls() { XBMC_TRACE; PythonCallbackHandler::makePendingCalls(); } void PythonLanguageHook::DelayedCallOpen() { XBMC_TRACE; PyGILLock::releaseGil(); } void PythonLanguageHook::DelayedCallClose() { XBMC_TRACE; PyGILLock::acquireGil(); } void PythonLanguageHook::RegisterMe() { XBMC_TRACE; CSingleLock lock(hooksMutex); hooks[m_interp] = AddonClass::Ref<PythonLanguageHook>(this); } void PythonLanguageHook::UnregisterMe() { XBMC_TRACE; CSingleLock lock(hooksMutex); hooks.erase(m_interp); } static AddonClass::Ref<XBMCAddon::Python::PythonLanguageHook> g_languageHook; // Ok ... we're going to get it even if it doesn't exist. If it doesn't exist then // we're going to assume we're not in control of the interpreter. This (apparently) // can be the case. E.g. Libspotify manages to call into a script using a ctypes // extension but under the control of an Interpreter we know nothing about. In // cases like this we're going to use a global interpreter AddonClass::Ref<PythonLanguageHook> PythonLanguageHook::GetIfExists(PyInterpreterState* interp) { XBMC_TRACE; CSingleLock lock(hooksMutex); std::map<PyInterpreterState*,AddonClass::Ref<PythonLanguageHook> >::iterator iter = hooks.find(interp); if (iter != hooks.end()) return AddonClass::Ref<PythonLanguageHook>(iter->second); // if we got here then we need to use the global one. if (g_languageHook.isNull()) g_languageHook = new XBMCAddon::Python::PythonLanguageHook(); return g_languageHook; } bool PythonLanguageHook::IsAddonClassInstanceRegistered(AddonClass* obj) { for (std::map<PyInterpreterState*,AddonClass::Ref<PythonLanguageHook> >::iterator iter = hooks.begin(); iter != hooks.end(); ++iter) { if ((iter->second)->HasRegisteredAddonClassInstance(obj)) return true; } return false; } /** * PythonCallbackHandler expects to be instantiated PER AddonClass instance * that is to be used as a callback. This is why this cannot be instantiated * once. * * There is an expectation that this method is called from the Python thread * that instantiated an AddonClass that has the potential for a callback. * * See RetardedAsyncCallbackHandler for more details. * See PythonCallbackHandler for more details * See PythonCallbackHandler::PythonCallbackHandler for more details */ XBMCAddon::CallbackHandler* PythonLanguageHook::GetCallbackHandler() { XBMC_TRACE; return new PythonCallbackHandler(); } String PythonLanguageHook::GetAddonId() { XBMC_TRACE; // 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* pyid = PyDict_GetItemString(global_dict, "__xbmcaddonid__"); if (pyid) return PyString_AsString(pyid); return ""; } String PythonLanguageHook::GetAddonVersion() { XBMC_TRACE; // 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* pyversion = PyDict_GetItemString(global_dict, "__xbmcapiversion__"); if (pyversion) return PyString_AsString(pyversion); return ""; } long PythonLanguageHook::GetInvokerId() { XBMC_TRACE; // 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* pyid = PyDict_GetItemString(global_dict, "__xbmcinvokerid__"); if (pyid) return PyLong_AsLong(pyid); return -1; } void PythonLanguageHook::RegisterPlayerCallback(IPlayerCallback* player) { XBMC_TRACE; g_pythonParser.RegisterPythonPlayerCallBack(player); } void PythonLanguageHook::UnregisterPlayerCallback(IPlayerCallback* player) { XBMC_TRACE; g_pythonParser.UnregisterPythonPlayerCallBack(player); } void PythonLanguageHook::RegisterMonitorCallback(XBMCAddon::xbmc::Monitor* monitor) { XBMC_TRACE; g_pythonParser.RegisterPythonMonitorCallBack(monitor); } void PythonLanguageHook::UnregisterMonitorCallback(XBMCAddon::xbmc::Monitor* monitor) { XBMC_TRACE; g_pythonParser.UnregisterPythonMonitorCallBack(monitor); } bool PythonLanguageHook::WaitForEvent(CEvent& hEvent, unsigned int milliseconds) { XBMC_TRACE; return g_pythonParser.WaitForEvent(hEvent,milliseconds); } void PythonLanguageHook::RegisterAddonClassInstance(AddonClass* obj) { XBMC_TRACE; CSingleLock l(*this); obj->Acquire(); currentObjects.insert(obj); } void PythonLanguageHook::UnregisterAddonClassInstance(AddonClass* obj) { XBMC_TRACE; CSingleLock l(*this); if (currentObjects.erase(obj) > 0) obj->Release(); } bool PythonLanguageHook::HasRegisteredAddonClassInstance(AddonClass* obj) { XBMC_TRACE; CSingleLock l(*this); return currentObjects.find(obj) != currentObjects.end(); } }