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 || iTypes > 1) { 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 && 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 (!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; }
/*! \brief Overwrite to fill fileitems from a source \param strDirectory Path to read \param items Fill with items specified in \e strDirectory */ bool CGUIMediaWindow::GetDirectory(const CStdString &strDirectory, CFileItemList &items) { // cleanup items if (items.Size()) items.Clear(); CStdString strParentPath=m_history.GetParentPath(); CLog::Log(LOGDEBUG,"CGUIMediaWindow::GetDirectory (%s)", strDirectory.c_str()); CLog::Log(LOGDEBUG," ParentPath = [%s]", strParentPath.c_str()); // see if we can load a previously cached folder CFileItemList cachedItems(strDirectory); if (!strDirectory.IsEmpty() && cachedItems.Load(GetID())) { items.Assign(cachedItems); } else { unsigned int time = XbmcThreads::SystemClockMillis(); if (strDirectory.IsEmpty()) SetupShares(); if (!m_rootDir.GetDirectory(strDirectory, items)) return false; // took over a second, and not normally cached, so cache it if ((XbmcThreads::SystemClockMillis() - time) > 1000 && items.CacheToDiscIfSlow()) items.Save(GetID()); // if these items should replace the current listing, then pop it off the top if (items.GetReplaceListing()) m_history.RemoveParentPath(); } if (m_guiState.get() && !m_guiState->HideParentDirItems() && !items.GetPath().IsEmpty()) { CFileItemPtr pItem(new CFileItem("..")); pItem->SetPath(strParentPath); pItem->m_bIsFolder = true; pItem->m_bIsShareOrDrive = false; items.AddFront(pItem, 0); } int iWindow = GetID(); CStdStringArray regexps; // TODO: Do we want to limit the directories we apply the video ones to? if (iWindow == WINDOW_VIDEO_NAV) regexps = g_advancedSettings.m_videoExcludeFromListingRegExps; if (iWindow == WINDOW_MUSIC_FILES) regexps = g_advancedSettings.m_audioExcludeFromListingRegExps; if (iWindow == WINDOW_PICTURES) regexps = g_advancedSettings.m_pictureExcludeFromListingRegExps; if (regexps.size()) { for (int i=0; i < items.Size();) { if (CUtil::ExcludeFileOrFolder(items[i]->GetPath(), regexps)) items.Remove(i); else i++; } } // clear the filter SetProperty("filter", ""); return true; }
int CMetadataResolverMusic::ReadMusicFolder(const CStdString& strPath, CResolvingFolder& folder, BXMetadataScannerJob* pJob) { CLog::Log(LOGDEBUG,"CMetadataResolverMusic::ReadMusicFolder reading music folder %s (musicresolver)", strPath.c_str()); // Update folder path folder.strFolderPath = strPath; // We wont try to resolve RAR or ZIP folder - in this case the files will stay unresolved if (CUtil::IsRAR(strPath) || CUtil::IsZIP(strPath)) { CLog::Log(LOGDEBUG,"CMetadataResolverMusic::ReadMusicFolder file %s is compressed file - keep it unresolved (musicresolver)", strPath.c_str()); return RESOLVER_SUCCESS; } CFileItemList items; if (!DIRECTORY::CDirectory::GetDirectory(strPath, items)) { CLog::Log(LOGDEBUG,"CMetadataResolverMusic::ReadMusicFolder unable to read directory %s (musicresolver)", strPath.c_str()); return RESOLVER_FAILED; } for (int i=0; i < items.Size() && pJob->IsActive(); i++) { CFileItemPtr pItem = items[i]; if (pItem->IsAudio() && !pItem->IsHidden() && !pItem->IsRAR() && !pItem->IsZIP() && !pItem->IsPlayList(false)) { CResolvingTrack track(pItem->m_strPath); track.strFolderPath = strPath; folder.vecTracks.push_back(track); } else if (pItem->IsPlayList(false)) { // TODO: Handle playlists } else if (pItem->IsPicture()) { CStdString extension = CUtil::GetExtension(pItem->m_strPath); CStdString supportedExtensions = ".png|.jpg|.jpeg|.bmp|.gif"; CStdStringArray thumbs; StringUtils::SplitString(supportedExtensions, "|", thumbs); for (unsigned int j = 0; j < thumbs.size(); ++j) { if (extension.CompareNoCase(thumbs[j]) == 0) { folder.vecThumbs.push_back(pItem->m_strPath); break; } } } } if (!pJob->IsActive()) { CLog::Log(LOGDEBUG,"CMetadataResolverMusic::ReadMusicFolder aborted, resolver was paused when reading folder %s (pause) (musicresolver) ", strPath.c_str()); return RESOLVER_ABORTED; } folder.strFolderPath = strPath; folder.strEffectiveFolderName = BOXEE::BXUtils::GetEffectiveFolderName(strPath); CLog::Log(LOGDEBUG,"CMetadataResolverMusic::ReadMusicFolder successfully finished reading folder %s (musicresolver) ", strPath.c_str()); return RESOLVER_SUCCESS; }
PyObject* Dialog_Browse(PyObject *self, PyObject *args) { int browsetype = 0; char useThumbs = false; char useFileDirectories = false; char enableMultiple = false; CStdString value; CStdStringArray valuelist; PyObject* unicodeLine[3]; string utf8Line[3]; char *cDefault = NULL; PyObject *result; for (int i = 0; i < 3; i++) unicodeLine[i] = NULL; if (!PyArg_ParseTuple(args, (char*)"iOO|Obbsb", &browsetype , &unicodeLine[0], &unicodeLine[1], &unicodeLine[2], &useThumbs, &useFileDirectories, &cDefault, &enableMultiple)) { return NULL; } for (int i = 0; i < 3; i++) { if (unicodeLine[i] && !PyXBMCGetUnicodeString(utf8Line[i], unicodeLine[i], i+1)) return NULL; } VECSOURCES *shares = g_settings.GetSourcesFromType(utf8Line[1]); if (!shares) return NULL; if (useFileDirectories && !utf8Line[2].size() == 0) utf8Line[2] += "|.rar|.zip"; value = cDefault; CPyThreadState pyState; if (browsetype == 1) { if (enableMultiple) CGUIDialogFileBrowser::ShowAndGetFileList(*shares, utf8Line[2], utf8Line[0], valuelist, 0 != useThumbs, 0 != useFileDirectories); else CGUIDialogFileBrowser::ShowAndGetFile(*shares, utf8Line[2], utf8Line[0], value, 0 != useThumbs, 0 != useFileDirectories); } else if (browsetype == 2) { if (enableMultiple) CGUIDialogFileBrowser::ShowAndGetImageList(*shares, utf8Line[0], valuelist); else CGUIDialogFileBrowser::ShowAndGetImage(*shares, utf8Line[0], value); } else CGUIDialogFileBrowser::ShowAndGetDirectory(*shares, utf8Line[0], value, browsetype != 0); pyState.Restore(); if (enableMultiple && (browsetype == 1 || browsetype == 2)) { result = PyTuple_New(valuelist.size()); if (!result) return NULL; for (unsigned int i = 0; i < valuelist.size(); i++) PyTuple_SetItem(result, i, PyString_FromString(valuelist.at(i).c_str())); return result; } else return Py_BuildValue((char*)"s", value.c_str()); }
void CGUIInfoLabel::Parse(const CStdString &label, int context) { m_info.clear(); // Step 1: Replace all $LOCALIZE[number] with the real string CStdString work = ReplaceLocalize(label); // Step 2: Replace all $ADDON[id number] with the real string work = ReplaceAddonStrings(work); // Step 3: Find all $INFO[info,prefix,postfix] blocks EINFOFORMAT format; do { format = NONE; int pos1 = work.size(); int pos2; int len = 0; for (size_t i = 0; i < sizeof(infoformatmap) / sizeof(infoformat); i++) { pos2 = work.Find(infoformatmap[i].str); if (pos2 != (int)string::npos && pos2 < pos1) { pos1 = pos2; len = strlen(infoformatmap[i].str); format = infoformatmap[i].val; } } if (format != NONE) { if (pos1 > 0) m_info.push_back(CInfoPortion(0, work.Left(pos1), "")); pos2 = StringUtils::FindEndBracket(work, '[', ']', pos1 + len); if (pos2 > pos1) { // decipher the block CStdString block = work.Mid(pos1 + len, pos2 - pos1 - len); CStdStringArray params; StringUtils::SplitString(block, ",", params); int info; if (format == FORMATVAR) { info = g_infoManager.TranslateSkinVariableString(params[0], context); if (info == 0) info = g_infoManager.RegisterSkinVariableString(g_SkinInfo->CreateSkinVariable(params[0], context)); if (info == 0) // skinner didn't define this conditional label! CLog::Log(LOGWARNING, "Label Formating: $VAR[%s] is not defined", params[0].c_str()); } else info = g_infoManager.TranslateString(params[0]); CStdString prefix, postfix; if (params.size() > 1) prefix = params[1]; if (params.size() > 2) postfix = params[2]; m_info.push_back(CInfoPortion(info, prefix, postfix, format == FORMATESCINFO)); // and delete it from our work string work = work.Mid(pos2 + 1); } else { CLog::Log(LOGERROR, "Error parsing label - missing ']' in \"%s\"", label.c_str()); return; } } } while (format != NONE); if (!work.IsEmpty()) m_info.push_back(CInfoPortion(0, work, "")); }
LibraryLoader* DllLoaderContainer::FindModule(const char* sName, const char* sCurrentDir, bool bLoadSymbols) { if (URIUtils::IsInArchive(sName)) { CURL url(sName); CStdString newName = "special://temp/"; newName += url.GetFileName(); CFile::Cache(sName, newName); return FindModule(newName, sCurrentDir, bLoadSymbols); } if (CURL::IsFullPath(sName)) { // Has a path, just try to load return LoadDll(sName, bLoadSymbols); } #ifdef TARGET_POSIX else if (strcmp(sName, "xbmc.so") == 0) return LoadDll(sName, bLoadSymbols); #endif else if (sCurrentDir) { // in the path of the parent dll? CStdString strPath=sCurrentDir; strPath+=sName; if (CFile::Exists(strPath)) return LoadDll(strPath.c_str(), bLoadSymbols); } // in environment variable? CStdStringArray vecEnv; #if defined(TARGET_ANDROID) CStdString systemLibs = getenv("XBMC_ANDROID_SYSTEM_LIBS"); StringUtils::SplitString(systemLibs, ":", vecEnv); CStdString localLibs = getenv("XBMC_ANDROID_LIBS"); vecEnv.insert(vecEnv.begin(),localLibs); #else StringUtils::SplitString(ENV_PATH, ";", vecEnv); #endif LibraryLoader* pDll = NULL; for (int i=0; i<(int)vecEnv.size(); ++i) { CStdString strPath=vecEnv[i]; URIUtils::AddSlashAtEnd(strPath); #ifdef LOGALL CLog::Log(LOGDEBUG, "Searching for the dll %s in directory %s", sName, strPath.c_str()); #endif strPath+=sName; // Have we already loaded this dll if ((pDll = GetModule(strPath.c_str())) != NULL) return pDll; if (CFile::Exists(strPath)) return LoadDll(strPath.c_str(), bLoadSymbols); } // can't find it in any of our paths - could be a system dll if ((pDll = LoadDll(sName, bLoadSymbols)) != NULL) return pDll; CLog::Log(LOGDEBUG, "Dll %s was not found in path", sName); return NULL; }
PyObject* Control_SetAnimations(Control* self, PyObject* args) { PyObject *pList = NULL; if (!PyArg_ParseTuple(args, (char*)"O", &pList) || pList == NULL || !PyObject_TypeCheck(pList, &PyList_Type)) { PyErr_SetString(PyExc_TypeError, "Object should be of type List"); return NULL; } CXBMCTinyXML xmlDoc; TiXmlElement xmlRootElement("control"); TiXmlNode *pRoot = xmlDoc.InsertEndChild(xmlRootElement); if (!pRoot) { PyErr_SetString(PyExc_TypeError, "TiXmlNode creation error"); return NULL; } vector<CAnimation> animations; for (int anim = 0; anim < PyList_Size(pList); anim++) { PyObject *pTuple = NULL; char *cEvent = NULL; char *cAttr = NULL; pTuple = PyList_GetItem(pList, anim); if (pTuple == NULL || !PyObject_TypeCheck(pTuple, &PyTuple_Type)) { PyErr_SetString(PyExc_TypeError, "List must only contain tuples"); return NULL; } if (!PyArg_ParseTuple(pTuple, (char*)"ss", &cEvent, &cAttr)) { PyErr_SetString(PyExc_TypeError, "Error unpacking tuple found in list"); return NULL; } if (NULL != cAttr && NULL != cEvent) { TiXmlElement pNode("animation"); CStdStringArray attrs; StringUtils::SplitString(cAttr, " ", attrs); for (unsigned int i = 0; i < attrs.size(); i++) { CStdStringArray attrs2; StringUtils::SplitString(attrs[i], "=", attrs2); if (attrs2.size() == 2) pNode.SetAttribute(attrs2[0], attrs2[1]); } TiXmlText value(cEvent); pNode.InsertEndChild(value); pRoot->InsertEndChild(pNode); } } //bool ret = xmlDoc.SaveFile("special://profile/test.txt"); const CRect animRect((float)self->dwPosX, (float)self->dwPosY, (float)self->dwPosX + self->dwWidth, (float)self->dwPosY + self->dwHeight); PyXBMCGUILock(); if (self->pGUIControl) { CGUIControlFactory::GetAnimations(pRoot, animRect, self->iParentId, animations); self->pGUIControl->SetAnimations(animations); } PyXBMCGUIUnlock(); Py_INCREF(Py_None); return Py_None; }
void CGUIRSSControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions) { bool dirty = false; if (CSettings::Get().GetBool("lookandfeel.enablerssfeeds") && CRssManager::Get().IsActive()) { CSingleLock lock(m_criticalSection); // Create RSS background/worker thread if needed if (m_pReader == NULL) { RssUrls::const_iterator iter = CRssManager::Get().GetUrls().find(m_urlset); if (iter != CRssManager::Get().GetUrls().end()) { m_rtl = iter->second.rtl; m_vecUrls = iter->second.url; m_vecIntervals = iter->second.interval; if (m_scrollInfo.pixelSpeed > 0 && m_rtl) m_scrollInfo.pixelSpeed *= -1; else if (m_scrollInfo.pixelSpeed < 0 && !m_rtl) m_scrollInfo.pixelSpeed *= -1; } dirty = true; if (CRssManager::Get().GetReader(GetID(), GetParentID(), this, m_pReader)) m_scrollInfo.characterPos = m_pReader->m_SavedScrollPos; else { if (m_strRSSTags != "") { CStdStringArray vecSplitTags; StringUtils::SplitString(m_strRSSTags, ",", vecSplitTags); for (unsigned int i = 0;i < vecSplitTags.size();i++) m_pReader->AddTag(vecSplitTags[i]); } // use half the width of the control as spacing between feeds, and double this between feed sets float spaceWidth = (m_label.font) ? m_label.font->GetCharWidth(L' ') : 15; m_pReader->Create(this, m_vecUrls, m_vecIntervals, (int)(0.5f*GetWidth() / spaceWidth) + 1, m_rtl); } } if(m_dirty) dirty = true; m_dirty = false; if (m_label.font) { if ( m_stopped ) m_scrollInfo.SetSpeed(0); else m_scrollInfo.SetSpeed(m_label.scrollSpeed); if(m_label.font->UpdateScrollInfo(m_feed, m_scrollInfo)) dirty = true; } } if(dirty) MarkDirtyRegion(); CGUIControl::Process(currentTime, dirtyregions); }
bool CEdl::ReadEdl(const CStdString& strMovie, const float fFramesPerSecond) { Clear(); CStdString edlFilename(URIUtils::ReplaceExtension(strMovie, ".edl")); if (!CFile::Exists(edlFilename)) return false; CFile edlFile; if (!edlFile.Open(edlFilename)) { CLog::Log(LOGERROR, "%s - Could not open EDL file: %s", __FUNCTION__, edlFilename.c_str()); return false; } bool bError = false; int iLine = 0; CStdString strBuffer; while (edlFile.ReadString(strBuffer.GetBuffer(1024), 1024)) { strBuffer.ReleaseBuffer(); // Log any errors from previous run in the loop if (bError) CLog::Log(LOGWARNING, "%s - Error on line %i in EDL file: %s", __FUNCTION__, iLine, edlFilename.c_str()); bError = false; iLine++; CStdStringArray strFields(2); int iAction; int iFieldsRead = sscanf(strBuffer, "%512s %512s %i", strFields[0].GetBuffer(512), strFields[1].GetBuffer(512), &iAction); strFields[0].ReleaseBuffer(); strFields[1].ReleaseBuffer(); if (iFieldsRead != 2 && iFieldsRead != 3) // Make sure we read the right number of fields { bError = true; continue; } if (iFieldsRead == 2) // If only 2 fields read, then assume it's a scene marker. { iAction = atoi(strFields[1]); strFields[1] = strFields[0]; } /* * For each of the first two fields read, parse based on whether it is a time string * (HH:MM:SS.sss), frame marker (#12345), or normal seconds string (123.45). */ int64_t iCutStartEnd[2]; for (int i = 0; i < 2; i++) { if (strFields[i].Find(":") != -1) // HH:MM:SS.sss format { CStdStringArray fieldParts; StringUtils::SplitString(strFields[i], ".", fieldParts); if (fieldParts.size() == 1) // No ms { iCutStartEnd[i] = StringUtils::TimeStringToSeconds(fieldParts[0]) * 1000; // seconds to ms } else if (fieldParts.size() == 2) // Has ms. Everything after the dot (.) is ms { /* * Have to pad or truncate the ms portion to 3 characters before converting to ms. */ if (fieldParts[1].length() == 1) { fieldParts[1] = fieldParts[1] + "00"; } else if (fieldParts[1].length() == 2) { fieldParts[1] = fieldParts[1] + "0"; } else if (fieldParts[1].length() > 3) { fieldParts[1] = fieldParts[1].Left(3); } iCutStartEnd[i] = StringUtils::TimeStringToSeconds(fieldParts[0]) * 1000 + atoi(fieldParts[1]); // seconds to ms } else { bError = true; continue; } } else if (strFields[i].Left(1) == "#") // #12345 format for frame number { iCutStartEnd[i] = (int64_t)(atol(strFields[i].Mid(1)) / fFramesPerSecond * 1000); // frame number to ms } else // Plain old seconds in float format, e.g. 123.45 { iCutStartEnd[i] = (int64_t)(atof(strFields[i]) * 1000); // seconds to ms } } if (bError) // If there was an error in the for loop, ignore and continue with the next line continue; Cut cut; cut.start = iCutStartEnd[0]; cut.end = iCutStartEnd[1]; switch (iAction) { case 0: cut.action = CUT; if (!AddCut(cut)) { CLog::Log(LOGWARNING, "%s - Error adding cut from line %i in EDL file: %s", __FUNCTION__, iLine, edlFilename.c_str()); continue; } break; case 1: cut.action = MUTE; if (!AddCut(cut)) { CLog::Log(LOGWARNING, "%s - Error adding mute from line %i in EDL file: %s", __FUNCTION__, iLine, edlFilename.c_str()); continue; } break; case 2: if (!AddSceneMarker(cut.end)) { CLog::Log(LOGWARNING, "%s - Error adding scene marker from line %i in EDL file: %s", __FUNCTION__, iLine, edlFilename.c_str()); continue; } break; case 3: cut.action = COMM_BREAK; if (!AddCut(cut)) { CLog::Log(LOGWARNING, "%s - Error adding commercial break from line %i in EDL file: %s", __FUNCTION__, iLine, edlFilename.c_str()); continue; } break; default: CLog::Log(LOGWARNING, "%s - Invalid action on line %i in EDL file: %s", __FUNCTION__, iLine, edlFilename.c_str()); continue; } } strBuffer.ReleaseBuffer(); if (bError) // Log last line warning, if there was one, since while loop will have terminated. CLog::Log(LOGWARNING, "%s - Error on line %i in EDL file: %s", __FUNCTION__, iLine, edlFilename.c_str()); edlFile.Close(); if (HasCut() || HasSceneMarker()) { CLog::Log(LOGDEBUG, "%s - Read %"PRIuS" cuts and %"PRIuS" scene markers in EDL file: %s", __FUNCTION__, m_vecCuts.size(), m_vecSceneMarkers.size(), edlFilename.c_str()); return true; } else { CLog::Log(LOGDEBUG, "%s - No cuts or scene markers found in EDL file: %s", __FUNCTION__, edlFilename.c_str()); return false; } }
CZoomEffect::CZoomEffect(const TiXmlElement *node, const CRect &rect) : CAnimEffect(node, EFFECT_TYPE_ZOOM) { // effect defaults m_startX = m_startY = 100; m_endX = m_endY = 100; m_center = CPoint(0,0); m_autoCenter = false; float startPosX = rect.x1; float startPosY = rect.y1; float endPosX = rect.x1; float endPosY = rect.y1; float width = max(rect.Width(), 0.001f); float height = max(rect.Height(),0.001f); const char *start = node->Attribute("start"); if (start) { CStdStringArray params; StringUtils::SplitString(start, ",", params); if (params.size() == 1) { g_SkinInfo->ResolveConstant(params[0], m_startX); m_startY = m_startX; } else if (params.size() == 2) { g_SkinInfo->ResolveConstant(params[0], m_startX); g_SkinInfo->ResolveConstant(params[1], m_startY); } else if (params.size() == 4) { // format is start="x,y,width,height" // use width and height from our rect to calculate our sizing g_SkinInfo->ResolveConstant(params[0], startPosX); g_SkinInfo->ResolveConstant(params[1], startPosY); g_SkinInfo->ResolveConstant(params[2], m_startX); g_SkinInfo->ResolveConstant(params[3], m_startY); m_startX *= 100.0f / width; m_startY *= 100.0f / height; } } const char *end = node->Attribute("end"); if (end) { CStdStringArray params; StringUtils::SplitString(end, ",", params); if (params.size() == 1) { g_SkinInfo->ResolveConstant(params[0], m_endX); m_endY = m_endX; } else if (params.size() == 2) { g_SkinInfo->ResolveConstant(params[0], m_endX); g_SkinInfo->ResolveConstant(params[1], m_endY); } else if (params.size() == 4) { // format is start="x,y,width,height" // use width and height from our rect to calculate our sizing g_SkinInfo->ResolveConstant(params[0], endPosX); g_SkinInfo->ResolveConstant(params[1], endPosY); g_SkinInfo->ResolveConstant(params[2], m_endX); g_SkinInfo->ResolveConstant(params[3], m_endY); m_endX *= 100.0f / width; m_endY *= 100.0f / height; } } const char *centerPos = node->Attribute("center"); if (centerPos) { if (strcmpi(centerPos, "auto") == 0) m_autoCenter = true; else { vector<CStdString> commaSeparated; StringUtils::SplitString(centerPos, ",", commaSeparated); if (commaSeparated.size() > 1) g_SkinInfo->ResolveConstant(commaSeparated[1], m_center.y); g_SkinInfo->ResolveConstant(commaSeparated[0], m_center.x); } } else { // no center specified // calculate the center position... if (m_startX) { float scale = m_endX / m_startX; if (scale != 1) m_center.x = (endPosX - scale*startPosX) / (1 - scale); } if (m_startY) { float scale = m_endY / m_startY; if (scale != 1) m_center.y = (endPosY - scale*startPosY) / (1 - scale); } } }
bool CWebSocketV13::Handshake(const char* data, size_t length, std::string &response) { string strHeader(data, length); const char *value; HttpParser header; if (header.addBytes(data, length) != HttpParser::Done) { CLog::Log(LOGINFO, "WebSocket [RFC6455]: incomplete handshake received"); return false; } // The request must be GET value = header.getMethod(); if (value == NULL || strnicmp(value, WS_HTTP_METHOD, strlen(WS_HTTP_METHOD)) != 0) { CLog::Log(LOGINFO, "WebSocket [RFC6455]: invalid HTTP method received (GET expected)"); return false; } // The request must be HTTP/1.1 or higher size_t pos; if ((pos = strHeader.find(WS_HTTP_TAG)) == string::npos) { CLog::Log(LOGINFO, "WebSocket [RFC6455]: invalid handshake received"); return false; } pos += strlen(WS_HTTP_TAG); istringstream converter(strHeader.substr(pos, strHeader.find_first_of(" \r\n\t", pos) - pos)); float fVersion; converter >> fVersion; if (fVersion < 1.1f) { CLog::Log(LOGINFO, "WebSocket [RFC6455]: invalid HTTP version %f (1.1 or higher expected)", fVersion); return false; } string websocketKey, websocketProtocol; // There must be a "Host" header value = header.getValue("host"); if (value == NULL || strlen(value) == 0) { CLog::Log(LOGINFO, "WebSocket [RFC6455]: \"Host\" header missing"); return true; } // There must be a "Upgrade" header with the value "websocket" value = header.getValue(WS_HEADER_UPGRADE_LC); if (value == NULL || strnicmp(value, WS_HEADER_UPGRADE_VALUE, strlen(WS_HEADER_UPGRADE_VALUE)) != 0) { CLog::Log(LOGINFO, "WebSocket [RFC6455]: invalid \"%s\" received", WS_HEADER_UPGRADE); return true; } // There must be a "Connection" header with the value "Upgrade" value = header.getValue(WS_HEADER_CONNECTION_LC); if (value == NULL || strstr(value, WS_HEADER_UPGRADE) == NULL) { CLog::Log(LOGINFO, "WebSocket [RFC6455]: invalid \"%s\" received", WS_HEADER_CONNECTION_LC); return true; } // There must be a base64 encoded 16 byte (=> 24 byte as base62) "Sec-WebSocket-Key" header value = header.getValue(WS_HEADER_KEY_LC); if (value == NULL || (websocketKey = value).size() != 24) { CLog::Log(LOGINFO, "WebSocket [RFC6455]: invalid \"Sec-WebSocket-Key\" received"); return true; } // There might be a "Sec-WebSocket-Protocol" header value = header.getValue(WS_HEADER_PROTOCOL_LC); if (value && strlen(value) > 0) { CStdStringArray protocols; StringUtils::SplitString(value, ",", protocols); for (unsigned int index = 0; index < protocols.size(); index++) { if (protocols.at(index).Trim().Equals(WS_PROTOCOL_JSONRPC)) { websocketProtocol = WS_PROTOCOL_JSONRPC; break; } } } CHttpResponse httpResponse(HTTP::Get, HTTP::SwitchingProtocols, HTTP::Version1_1); httpResponse.AddHeader(WS_HEADER_UPGRADE, WS_HEADER_UPGRADE_VALUE); httpResponse.AddHeader(WS_HEADER_CONNECTION, WS_HEADER_UPGRADE); std::string responseKey = calculateKey(websocketKey); httpResponse.AddHeader(WS_HEADER_ACCEPT, responseKey); if (!websocketProtocol.empty()) httpResponse.AddHeader(WS_HEADER_PROTOCOL, websocketProtocol); char *responseBuffer; int responseLength = httpResponse.Create(responseBuffer); response = std::string(responseBuffer, responseLength); m_state = WebSocketStateConnected; return true; }