CStdString CKeyboardStat::GetKeyName(int KeyID) { int keyid; CStdString keyname; XBMCKEYTABLE keytable; keyname.clear(); // Get modifiers if (KeyID & CKey::MODIFIER_CTRL) keyname.append("ctrl-"); if (KeyID & CKey::MODIFIER_SHIFT) keyname.append("shift-"); if (KeyID & CKey::MODIFIER_ALT) keyname.append("alt-"); if (KeyID & CKey::MODIFIER_SUPER) keyname.append("win-"); if (KeyID & CKey::MODIFIER_META) keyname.append("meta-"); // Now get the key name keyid = KeyID & 0xFF; if (KeyTableLookupVKeyName(keyid, &keytable)) keyname.append(keytable.keyname); else keyname.AppendFormat("%i", keyid); keyname.AppendFormat(" (0x%02x)", KeyID); return keyname; }
bool XMLUtils::GetAdditiveString(const TiXmlNode* pRootNode, const char* strTag, const CStdString& strSeparator, CStdString& strStringValue, bool clear) { CStdString strTemp; const TiXmlElement* node = pRootNode->FirstChildElement(strTag); bool bResult=false; if (node && node->FirstChild() && clear) strStringValue.clear(); while (node) { if (node->FirstChild()) { bResult = true; strTemp = node->FirstChild()->Value(); const char* clear=node->Attribute("clear"); if (strStringValue.IsEmpty() || (clear && strcasecmp(clear,"true")==0)) strStringValue = strTemp; else strStringValue += strSeparator+strTemp; } node = node->NextSiblingElement(strTag); } return bResult; }
void CAirPlayServer::CTCPClient::ComposeAuthRequestAnswer(CStdString& responseHeader, CStdString& responseBody) { int16_t random=rand(); CStdString randomStr = StringUtils::Format("%i", random); m_authNonce=XBMC::XBMC_MD5::GetMD5(randomStr); responseHeader = StringUtils::Format(AUTH_REQUIRED, m_authNonce.c_str()); responseBody.clear(); }
bool CPictureThumbLoader::LoadItem(CFileItem* pItem) { if (pItem->m_bIsShareOrDrive) return true; if (pItem->IsParentFolder()) return true; if (pItem->HasThumbnail() && m_regenerateThumbs) { CTextureCache::Get().ClearCachedImage(pItem->GetThumbnailImage()); CTextureDatabase db; if (db.Open()) db.ClearTextureForPath(pItem->GetPath(), "thumb"); pItem->SetThumbnailImage(""); } CStdString thumb; if (pItem->IsPicture() && !pItem->IsZIP() && !pItem->IsRAR() && !pItem->IsCBZ() && !pItem->IsCBR() && !pItem->IsPlayList()) { // load the thumb from the image file thumb = pItem->HasThumbnail() ? pItem->GetThumbnailImage() : CTextureCache::GetWrappedThumbURL(pItem->GetPath()); } else if (pItem->IsVideo() && !pItem->IsZIP() && !pItem->IsRAR() && !pItem->IsCBZ() && !pItem->IsCBR() && !pItem->IsPlayList()) { // video thumb = pItem->GetCachedVideoThumb(); if (!CFile::Exists(thumb)) { CStdString strPath, strFileName; URIUtils::Split(thumb, strPath, strFileName); CStdString autoThumb = strPath + "auto-" + strFileName; // this is abit of a hack to avoid loading zero sized images // which we know will fail. They will just display empty image // we should really have some way for the texture loader to // do fallbacks to default images for a failed image instead if (CFile::Exists(autoThumb)) { thumb = autoThumb; } else if (g_guiSettings.GetBool("myvideos.extractthumb") && g_guiSettings.GetBool("myvideos.extractflags")) { CFileItem item(*pItem); CThumbExtractor* extract = new CThumbExtractor(item, pItem->GetPath(), true, autoThumb); AddJob(extract); thumb.clear(); } } } else if (!pItem->HasThumbnail()) { // folder, zip, cbz, rar, cbr, playlist may have a previously cached image thumb = GetCachedImage(*pItem, "thumb"); } if (!thumb.IsEmpty()) { CTextureCache::Get().BackgroundCacheImage(thumb); pItem->SetThumbnailImage(thumb); } pItem->FillInDefaultIcon(); return true; }
bool CAirTunesServer::StartServer(int port, bool nonlocal, bool usePassword, const CStdString &password/*=""*/) { bool success = false; CStdString pw = password; CNetworkInterface *net = g_application.getNetwork().GetFirstConnectedInterface(); StopServer(true); if (net) { m_macAddress = net->GetMacAddress(); StringUtils::Replace(m_macAddress, ":",""); while (m_macAddress.size() < 12) { m_macAddress = CStdString("0") + m_macAddress; } } else { m_macAddress = "000102030405"; } if (!usePassword) { pw.clear(); } ServerInstance = new CAirTunesServer(port, nonlocal); if (ServerInstance->Initialize(pw)) { success = true; CStdString appName = StringUtils::Format("%s@%s", m_macAddress.c_str(), g_infoManager.GetLabel(SYSTEM_FRIENDLY_NAME).c_str()); std::vector<std::pair<std::string, std::string> > txt; txt.push_back(std::make_pair("txtvers", "1")); txt.push_back(std::make_pair("cn", "0,1")); txt.push_back(std::make_pair("ch", "2")); txt.push_back(std::make_pair("ek", "1")); txt.push_back(std::make_pair("et", "0,1")); txt.push_back(std::make_pair("sv", "false")); txt.push_back(std::make_pair("tp", "UDP")); txt.push_back(std::make_pair("sm", "false")); txt.push_back(std::make_pair("ss", "16")); txt.push_back(std::make_pair("sr", "44100")); txt.push_back(std::make_pair("pw", usePassword?"true":"false")); txt.push_back(std::make_pair("vn", "3")); txt.push_back(std::make_pair("da", "true")); txt.push_back(std::make_pair("vs", "130.14")); txt.push_back(std::make_pair("md", "0,1,2")); txt.push_back(std::make_pair("am", "Xbmc,1")); CZeroconf::GetInstance()->PublishService("servers.airtunes", "_raop._tcp", appName, port, txt); } return success; }
TEST_F(TestCharsetConverter, getCharsetNameByLabel) { CStdString varstr = g_charsetConverter.getCharsetNameByLabel("Western Europe (ISO)"); EXPECT_STREQ("ISO-8859-1", varstr.c_str()); varstr.clear(); varstr = g_charsetConverter.getCharsetNameByLabel("Bogus"); EXPECT_STREQ("", varstr.c_str()); }
bool CPictureThumbLoader::LoadItemCached(CFileItem* pItem) { if (pItem->m_bIsShareOrDrive || pItem->IsParentFolder()) return false; if (pItem->HasArt("thumb") && m_regenerateThumbs) { CTextureCache::Get().ClearCachedImage(pItem->GetArt("thumb")); if (m_textureDatabase->Open()) { m_textureDatabase->ClearTextureForPath(pItem->GetPath(), "thumb"); m_textureDatabase->Close(); } pItem->SetArt("thumb", ""); } CStdString thumb; if (pItem->IsPicture() && !pItem->IsZIP() && !pItem->IsRAR() && !pItem->IsCBZ() && !pItem->IsCBR() && !pItem->IsPlayList()) { // load the thumb from the image file thumb = pItem->HasArt("thumb") ? pItem->GetArt("thumb") : CTextureCache::GetWrappedThumbURL(pItem->GetPath()); } else if (pItem->IsVideo() && !pItem->IsZIP() && !pItem->IsRAR() && !pItem->IsCBZ() && !pItem->IsCBR() && !pItem->IsPlayList()) { // video CVideoThumbLoader loader; if (!loader.FillThumb(*pItem)) { CStdString thumbURL = CVideoThumbLoader::GetEmbeddedThumbURL(*pItem); if (CTextureCache::Get().HasCachedImage(thumbURL)) { thumb = thumbURL; } else if (CSettings::Get().GetBool("myvideos.extractthumb") && CSettings::Get().GetBool("myvideos.extractflags")) { CFileItem item(*pItem); CThumbExtractor* extract = new CThumbExtractor(item, pItem->GetPath(), true, thumbURL); AddJob(extract); thumb.clear(); } } } else if (!pItem->HasArt("thumb")) { // folder, zip, cbz, rar, cbr, playlist may have a previously cached image thumb = GetCachedImage(*pItem, "thumb"); } if (!thumb.IsEmpty()) { CTextureCache::Get().BackgroundCacheImage(thumb); pItem->SetArt("thumb", thumb); } pItem->FillInDefaultIcon(); return true; }
void CWeatherJob::LocalizeOverview(CStdString &str) { CStdStringArray words; StringUtils::SplitString(str, " ", words); str.clear(); for (unsigned int i = 0; i < words.size(); i++) { LocalizeOverviewToken(words[i]); str += words[i] + " "; } str.TrimRight(" "); }
void CHttpHeader::GetHeader(CStdString& strHeader) { strHeader.clear(); HeaderParamsIter iter = m_params.begin(); while (iter != m_params.end()) { strHeader += ((*iter).first + ": " + (*iter).second + "\n"); } strHeader += "\n"; }
void CHttpHeader::GetHeader(CStdString& strHeader) const { strHeader.clear(); std::map<CStdString,CStdString>::const_iterator iter = m_params.begin(); while (iter != m_params.end()) { strHeader += ((*iter).first + ": " + (*iter).second + "\n"); iter++; } strHeader += "\n"; }
bool GUIFontManager::GetFirstFontSetUnicode(CStdString& strFontSet) { strFontSet.clear(); // Load our font file CXBMCTinyXML xmlDoc; if (!OpenFontFile(xmlDoc)) return false; TiXmlElement* pRootElement = xmlDoc.RootElement(); const TiXmlNode *pChild = pRootElement->FirstChild(); CStdString strValue = pChild->Value(); if (strValue == "fontset") { while (pChild) { strValue = pChild->Value(); if (strValue == "fontset") { const char* idAttr = ((TiXmlElement*) pChild)->Attribute("id"); const char* unicodeAttr = ((TiXmlElement*) pChild)->Attribute("unicode"); // Check if this is a fontset with a ttf attribute set to true if (unicodeAttr != NULL && stricmp(unicodeAttr, "true") == 0) { // This is the first ttf fontset strFontSet=idAttr; break; } } pChild = pChild->NextSibling(); } // If no fontset was loaded if (pChild == NULL) CLog::Log(LOGWARNING, "file doesnt have <fontset> with attribute unicode=\"true\""); } else { CLog::Log(LOGERROR, "file doesnt have <fontset> in <fonts>, but rather %s", strValue.c_str()); } return !strFontSet.empty(); }
bool XMLUtils::GetPath(const TiXmlNode* pRootNode, const char* strTag, CStdString& strStringValue) { const TiXmlElement* pElement = pRootNode->FirstChildElement(strTag); if (!pElement) return false; const char* encoded = pElement->Attribute("urlencoded"); const TiXmlNode* pNode = pElement->FirstChild(); if (pNode != NULL) { strStringValue = pNode->Value(); if (encoded && strcasecmp(encoded,"yes") == 0) strStringValue = CURL::Decode(strStringValue); return true; } strStringValue.clear(); return false; }
CStdString CTextureCache::GetCachedImage(const CStdString &image, CStdString &cachedHash, bool trackUsage) { cachedHash.clear(); CStdString url = UnwrapImageURL(image); if (IsCachedImage(url)) return url; // lookup the item in the database CTextureDetails details; if (GetCachedTexture(url, details)) { if (trackUsage) IncrementUseCount(details); return GetCachedPath(details.file); } return ""; }
void CTextSearch::GetAndCutNextTerm(CStdString &strSearchTerm, CStdString &strNextTerm) { CStdString strFindNext(" "); if (StringUtils::EndsWith(strSearchTerm, "\"")) { strSearchTerm.erase(0, 1); strFindNext = "\""; } int iNextPos = strSearchTerm.Find(strFindNext); if (iNextPos != -1) { strNextTerm = strSearchTerm.Left(iNextPos); strSearchTerm.erase(0, iNextPos + 1); } else { strNextTerm = strSearchTerm; strSearchTerm.clear(); } }
bool CFanart::ParseColors(const CStdString &colorsIn, CStdString &colorsOut) { // Formats: // 0: XBMC ARGB Hexadecimal string comma seperated "FFFFFFFF,DDDDDDDD,AAAAAAAA" // 1: The TVDB RGB Int Triplets, pipe seperate with leading/trailing pipes "|68,69,59|69,70,58|78,78,68|" // Essentially we read the colors in using the proper format, and store them in our own fixed temporary format (3 DWORDS), and then // write them back in in the specified format. if (colorsIn.empty()) return false; // check for the TVDB RGB triplets "|68,69,59|69,70,58|78,78,68|" if (colorsIn[0] == '|') { // need conversion colorsOut.clear(); CStdStringArray strColors; StringUtils::SplitString(colorsIn, "|", strColors); for (int i = 0; i < std::min((int)strColors.size()-1, (int)max_fanart_colors); i++) { // split up each color CStdStringArray strTriplets; StringUtils::SplitString(strColors[i+1], ",", strTriplets); if (strTriplets.size() == 3) { // convert if (colorsOut.size()) colorsOut += ","; colorsOut += StringUtils::Format("FF%2x%2x%2x", atol(strTriplets[0].c_str()), atol(strTriplets[1].c_str()), atol(strTriplets[2].c_str())); } } } else { // assume is our format colorsOut = colorsIn; } return true; }
// Allow user to select a Fanart void CGUIDialogMusicInfo::OnGetFanart() { CFileItemList items; if (m_albumItem->HasProperty("fanart_image")) { CFileItemPtr itemCurrent(new CFileItem("fanart://Current",false)); itemCurrent->SetThumbnailImage(m_albumItem->GetProperty("fanart_image").asString()); itemCurrent->SetLabel(g_localizeStrings.Get(20440)); items.Add(itemCurrent); } // Grab the thumbnails from the web for (unsigned int i = 0; i < m_artist.fanart.GetNumFanarts(); i++) { CStdString strItemPath; strItemPath.Format("fanart://Remote%i",i); CFileItemPtr item(new CFileItem(strItemPath, false)); CStdString thumb = m_artist.fanart.GetPreviewURL(i); item->SetThumbnailImage(CTextureCache::GetWrappedThumbURL(thumb)); item->SetIconImage("DefaultPicture.png"); item->SetLabel(g_localizeStrings.Get(20441)); // TODO: Do we need to clear the cached image? // CTextureCache::Get().ClearCachedImage(thumb); items.Add(item); } // Grab a local thumb CMusicDatabase database; database.Open(); CStdString strArtistPath; database.GetArtistPath(m_artist.idArtist,strArtistPath); CFileItem item(strArtistPath,true); CStdString strLocal = item.GetLocalFanart(); if (!strLocal.IsEmpty()) { CFileItemPtr itemLocal(new CFileItem("fanart://Local",false)); itemLocal->SetThumbnailImage(strLocal); itemLocal->SetLabel(g_localizeStrings.Get(20438)); // TODO: Do we need to clear the cached image? CTextureCache::Get().ClearCachedImage(strLocal); items.Add(itemLocal); } else { CFileItemPtr itemNone(new CFileItem("fanart://None", false)); itemNone->SetIconImage("DefaultArtist.png"); itemNone->SetLabel(g_localizeStrings.Get(20439)); items.Add(itemNone); } CStdString result; VECSOURCES sources(g_settings.m_musicSources); g_mediaManager.GetLocalDrives(sources); bool flip=false; if (!CGUIDialogFileBrowser::ShowAndGetImage(items, sources, g_localizeStrings.Get(20437), result, &flip, 20445)) return; // user cancelled // delete the thumbnail if that's what the user wants, else overwrite with the // new thumbnail if (result.Equals("fanart://Current")) return; if (result.Equals("fanart://Local")) result = strLocal; if (result.Left(15) == "fanart://Remote") { int iFanart = atoi(result.Mid(15).c_str()); m_artist.fanart.SetPrimaryFanart(iFanart); result = m_artist.fanart.GetImageURL(); } else if (result.Equals("fanart://None") || !CFile::Exists(result)) result.clear(); if (flip && !result.empty()) result = CTextureCache::GetWrappedImageURL(result, "", "flipped"); // update thumb in the database CMusicDatabase db; if (db.Open()) { db.SetArtForItem(m_albumItem->GetMusicInfoTag()->GetDatabaseId(), m_albumItem->GetMusicInfoTag()->GetType(), "fanart", result); db.Close(); } if (!result.empty()) m_albumItem->SetProperty("fanart_image",result); else m_albumItem->ClearProperty("fanart_image"); m_hasUpdatedThumb = true; // tell our GUI to completely reload all controls (as some of them // are likely to have had this image in use so will need refreshing) CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_REFRESH_THUMBS); g_windowManager.SendMessage(msg); // Update our screen Update(); }
bool URIUtils::GetParentPath(const CStdString& strPath, CStdString& strParent) { strParent = ""; CURL url(strPath); CStdString strFile = url.GetFileName(); if ( URIUtils::ProtocolHasParentInHostname(url.GetProtocol()) && strFile.IsEmpty()) { strFile = url.GetHostName(); return GetParentPath(strFile, strParent); } else if ((url.GetProtocol() == "videodb" || url.GetProtocol() == "musicdb") && !url.GetOptions().empty()) { CStdString options = url.GetOptions(); size_t filterStart = options.find("filter="); if (filterStart != string::npos) { size_t filterEnd = options.find("&", filterStart); options.erase(filterStart, filterEnd - filterStart); if (options.Equals("?")) options.clear(); url.SetOptions(options); strParent = url.Get(); return true; } } else if (url.GetProtocol() == "stack") { CStackDirectory dir; CFileItemList items; dir.GetDirectory(strPath,items); GetDirectory(items[0]->GetPath(),items[0]->m_strDVDLabel); if (items[0]->m_strDVDLabel.Mid(0,6).Equals("rar://") || items[0]->m_strDVDLabel.Mid(0,6).Equals("zip://")) GetParentPath(items[0]->m_strDVDLabel, strParent); else strParent = items[0]->m_strDVDLabel; for( int i=1;i<items.Size();++i) { GetDirectory(items[i]->GetPath(),items[i]->m_strDVDLabel); if (items[0]->m_strDVDLabel.Mid(0,6).Equals("rar://") || items[0]->m_strDVDLabel.Mid(0,6).Equals("zip://")) items[i]->SetPath(GetParentPath(items[i]->m_strDVDLabel)); else items[i]->SetPath(items[i]->m_strDVDLabel); GetCommonPath(strParent,items[i]->GetPath()); } return true; } else if (url.GetProtocol() == "multipath") { // get the parent path of the first item return GetParentPath(CMultiPathDirectory::GetFirstPath(strPath), strParent); } else if (url.GetProtocol() == "plugin") { if (!url.GetOptions().IsEmpty()) { url.SetOptions(""); strParent = url.Get(); return true; } if (!url.GetFileName().IsEmpty()) { url.SetFileName(""); strParent = url.Get(); return true; } if (!url.GetHostName().IsEmpty()) { url.SetHostName(""); strParent = url.Get(); return true; } return true; // already at root } else if (url.GetProtocol() == "special") { if (HasSlashAtEnd(strFile) ) strFile = strFile.Left(strFile.size() - 1); if(strFile.ReverseFind('/') < 0) return false; } else if (strFile.size() == 0) { if (url.GetHostName().size() > 0) { // we have an share with only server or workgroup name // set hostname to "" and return true to get back to root url.SetHostName(""); strParent = url.Get(); return true; } return false; } if (HasSlashAtEnd(strFile) ) { strFile = strFile.Left(strFile.size() - 1); } int iPos = strFile.ReverseFind('/'); #ifndef _LINUX if (iPos < 0) { iPos = strFile.ReverseFind('\\'); } #endif if (iPos < 0) { url.SetFileName(""); strParent = url.Get(); return true; } strFile = strFile.Left(iPos); AddSlashAtEnd(strFile); url.SetFileName(strFile); strParent = url.Get(); return true; }
void CGUIDialogSubtitles::OnDownloadComplete(const CFileItemList *items, const std::string &language) { if (items->IsEmpty()) { CFileItemPtr service = GetService(); if (service) CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, service->GetLabel(), g_localizeStrings.Get(24113)); UpdateStatus(SEARCH_COMPLETE); return; } CStdString strFileName; CStdString strDestPath; #if 0 // TODO: Code to download all subtitles for all stack items in one run if (g_application.CurrentFileItem().IsStack()) { for (int i = 0; i < items->Size(); i++) { // check for all stack items and match to given subs, item [0] == CD1, item [1] == CD2 // CLog::Log(LOGDEBUG, "Stack Subs [%s} Found", vecItems[i]->GetLabel().c_str()); } } #endif // Get (unstacked) path const CStdString &strCurrentFile = g_application.CurrentUnstackedItem().GetPath(); if (StringUtils::StartsWith(strCurrentFile, "http://")) { strFileName = "TemporarySubs"; strDestPath = "special://temp/"; } else { strFileName = URIUtils::GetFileName(strCurrentFile); if (CSettings::Get().GetBool("subtitles.savetomoviefolder")) { strDestPath = URIUtils::GetDirectory(strCurrentFile); if (!CUtil::SupportsWriteFileOperations(strDestPath)) strDestPath.clear(); } if (strDestPath.empty()) { if (CSpecialProtocol::TranslatePath("special://subtitles").empty()) strDestPath = "special://temp"; else strDestPath = "special://subtitles"; } } // Extract the language and appropriate extension CStdString strSubLang; g_LangCodeExpander.ConvertToTwoCharCode(strSubLang, language); CStdString strUrl = items->Get(0)->GetPath(); CStdString strSubExt = URIUtils::GetExtension(strUrl); // construct subtitle path URIUtils::RemoveExtension(strFileName); CStdString strSubName = StringUtils::Format("%s.%s%s", strFileName.c_str(), strSubLang.c_str(), strSubExt.c_str()); CStdString strSubPath = URIUtils::AddFileToFolder(strDestPath, strSubName); // and copy the file across CFile::Cache(strUrl, strSubPath); // for ".sub" subtitles we check if ".idx" counterpart exists and copy that as well if (strSubExt.Equals(".sub")) { strUrl = URIUtils::ReplaceExtension(strUrl, ".idx"); if(CFile::Exists(strUrl)) { CStdString strSubNameIdx = StringUtils::Format("%s.%s.idx", strFileName.c_str(), strSubLang.c_str()); strSubPath = URIUtils::AddFileToFolder(strDestPath, strSubNameIdx); CFile::Cache(strUrl, strSubPath); } } SetSubtitles(strSubPath); // Close the window Close(); }
CStdString CSpecialProtocol::TranslatePath(const CURL &url) { // check for special-protocol, if not, return if (!url.GetProtocol().Equals("special")) { #if defined(TARGET_POSIX) && defined(_DEBUG) CStdString path(url.Get()); if (path.length() >= 2 && path[1] == ':') { CLog::Log(LOGWARNING, "Trying to access old style dir: %s\n", path.c_str()); // printf("Trying to access old style dir: %s\n", path.c_str()); } #endif return url.Get(); } CStdString FullFileName = url.GetFileName(); CStdString translatedPath; CStdString FileName; CStdString RootDir; // Split up into the special://root and the rest of the filename int pos = FullFileName.Find('/'); if (pos != -1 && pos > 1) { RootDir = FullFileName.Left(pos); if (pos < FullFileName.GetLength()) FileName = FullFileName.Mid(pos + 1); } else RootDir = FullFileName; if (RootDir.Equals("subtitles")) translatedPath = URIUtils::AddFileToFolder(CSettings::Get().GetString("subtitles.custompath"), FileName); else if (RootDir.Equals("userdata")) translatedPath = URIUtils::AddFileToFolder(CProfilesManager::Get().GetUserDataFolder(), FileName); else if (RootDir.Equals("database")) translatedPath = URIUtils::AddFileToFolder(CProfilesManager::Get().GetDatabaseFolder(), FileName); else if (RootDir.Equals("thumbnails")) translatedPath = URIUtils::AddFileToFolder(CProfilesManager::Get().GetThumbnailsFolder(), FileName); else if (RootDir.Equals("recordings") || RootDir.Equals("cdrips")) translatedPath = URIUtils::AddFileToFolder(CSettings::Get().GetString("audiocds.recordingpath"), FileName); else if (RootDir.Equals("screenshots")) translatedPath = URIUtils::AddFileToFolder(CSettings::Get().GetString("debug.screenshotpath"), FileName); else if (RootDir.Equals("musicplaylists")) translatedPath = URIUtils::AddFileToFolder(CUtil::MusicPlaylistsLocation(), FileName); else if (RootDir.Equals("videoplaylists")) translatedPath = URIUtils::AddFileToFolder(CUtil::VideoPlaylistsLocation(), FileName); else if (RootDir.Equals("skin")) translatedPath = URIUtils::AddFileToFolder(g_graphicsContext.GetMediaDir(), FileName); else if (RootDir.Equals("logpath")) translatedPath = URIUtils::AddFileToFolder(g_advancedSettings.m_logFolder, FileName); // from here on, we have our "real" special paths else if (RootDir.Equals("xbmc") || RootDir.Equals("xbmcbin") || RootDir.Equals("home") || RootDir.Equals("userhome") || RootDir.Equals("temp") || RootDir.Equals("profile") || RootDir.Equals("masterprofile") || RootDir.Equals("frameworks")) { CStdString basePath = GetPath(RootDir); if (!basePath.IsEmpty()) translatedPath = URIUtils::AddFileToFolder(basePath, FileName); else translatedPath.clear(); } // check if we need to recurse in if (URIUtils::IsSpecial(translatedPath)) { // we need to recurse in, as there may be multiple translations required return TranslatePath(translatedPath); } // Validate the final path, just in case return CUtil::ValidatePath(translatedPath); }
void CGUIDialogPVRGuideSearch::OnSearch() { CStdString strTmp; CGUISpinControlEx *pSpin; CGUIEditControl *pEdit; CGUIRadioButtonControl *pRadioButton; if (!m_searchFilter) return; pEdit = (CGUIEditControl *)GetControl(CONTROL_EDIT_SEARCH); if (pEdit) m_searchFilter->m_strSearchTerm = pEdit->GetLabel2(); pRadioButton = (CGUIRadioButtonControl *)GetControl(CONTROL_BTN_INC_DESC); if (pRadioButton) m_searchFilter->m_bSearchInDescription = pRadioButton->IsSelected(); pRadioButton = (CGUIRadioButtonControl *)GetControl(CONTROL_BTN_CASE_SENS); if (pRadioButton) m_searchFilter->m_bIsCaseSensitive = pRadioButton->IsSelected(); pRadioButton = (CGUIRadioButtonControl *)GetControl(CONTROL_BTN_FTA_ONLY); if (pRadioButton) m_searchFilter->m_bFTAOnly = pRadioButton->IsSelected(); pRadioButton = (CGUIRadioButtonControl *)GetControl(CONTROL_BTN_UNK_GENRE); if (pRadioButton) m_searchFilter->m_bIncludeUnknownGenres = pRadioButton->IsSelected(); pRadioButton = (CGUIRadioButtonControl *)GetControl(CONTROL_BTN_IGNORE_REC); if (pRadioButton) m_searchFilter->m_bIgnorePresentRecordings = pRadioButton->IsSelected(); pRadioButton = (CGUIRadioButtonControl *)GetControl(CONTROL_BTN_IGNORE_TMR); if (pRadioButton) m_searchFilter->m_bIgnorePresentTimers = pRadioButton->IsSelected(); pRadioButton = (CGUIRadioButtonControl *)GetControl(CONTROL_SPIN_NO_REPEATS); if (pRadioButton) m_searchFilter->m_bPreventRepeats = pRadioButton->IsSelected(); pSpin = (CGUISpinControlEx *)GetControl(CONTROL_SPIN_GENRE); if (pSpin) m_searchFilter->m_iGenreType = pSpin->GetValue(); pSpin = (CGUISpinControlEx *)GetControl(CONTROL_SPIN_MIN_DURATION); if (pSpin) m_searchFilter->m_iMinimumDuration = pSpin->GetValue(); pSpin = (CGUISpinControlEx *)GetControl(CONTROL_SPIN_MAX_DURATION); if (pSpin) m_searchFilter->m_iMaximumDuration = pSpin->GetValue(); pSpin = (CGUISpinControlEx *)GetControl(CONTROL_SPIN_CHANNELS); if (pSpin) m_searchFilter->m_iChannelNumber = pSpin->GetValue(); pSpin = (CGUISpinControlEx *)GetControl(CONTROL_SPIN_GROUPS); if (pSpin) m_searchFilter->m_iChannelGroup = pSpin->GetValue(); pEdit = (CGUIEditControl *)GetControl(CONTROL_EDIT_START_TIME); if (pEdit) strTmp = pEdit->GetLabel2(); pEdit = (CGUIEditControl *)GetControl(CONTROL_EDIT_START_DATE); if (pEdit) ReadDateTime(pEdit->GetLabel2(), strTmp, m_searchFilter->m_startDateTime); strTmp.clear(); pEdit = (CGUIEditControl *)GetControl(CONTROL_EDIT_STOP_TIME); if (pEdit) strTmp = pEdit->GetLabel2(); pEdit = (CGUIEditControl *)GetControl(CONTROL_EDIT_STOP_DATE); if (pEdit) ReadDateTime(pEdit->GetLabel2(), strTmp, m_searchFilter->m_endDateTime); }
void COptions::SetOption(int nOptionID, LPCTSTR value, bool save /*=true*/) { CStdString str = value; Init(); switch (nOptionID) { case OPTION_SERVERPORT: case OPTION_TLSPORTS: { std::set<int> portSet; str.TrimLeft(_T(" ,")); int pos = str.FindOneOf(_T(" ,")); while (pos != -1) { int port = _ttoi(str.Left(pos)); if (port >= 1 && port <= 65535) portSet.insert(port); str = str.Mid(pos + 1); str.TrimLeft(_T(" ,")); pos = str.FindOneOf(_T(" ,")); } if (str != _T("")) { int port = _ttoi(str); if (port >= 1 && port <= 65535) portSet.insert(port); } str = _T(""); for (std::set<int>::const_iterator iter = portSet.begin(); iter != portSet.end(); iter++) { CStdString tmp; tmp.Format(_T("%d "), *iter); str += tmp; } str.TrimRight(' '); } break; case OPTION_WELCOMEMESSAGE: { std::vector<CStdString> msgLines; int oldpos = 0; str.Replace(_T("\r\n"), _T("\n")); int pos = str.Find(_T("\n")); CStdString line; while (pos != -1) { if (pos) { line = str.Mid(oldpos, pos - oldpos); line = line.Left(CONST_WELCOMEMESSAGE_LINESIZE); line.TrimRight(_T(" ")); if (msgLines.size() || line != _T("")) msgLines.push_back(line); } oldpos = pos + 1; pos = str.Find(_T("\n"), oldpos); } line = str.Mid(oldpos); if (line != _T("")) { line = line.Left(CONST_WELCOMEMESSAGE_LINESIZE); msgLines.push_back(line); } str = _T(""); for (unsigned int i = 0; i < msgLines.size(); i++) str += msgLines[i] + _T("\r\n"); str.TrimRight(_T("\r\n")); if (str == _T("")) { str = _T("%v"); str += _T("\r\nwritten by Tim Kosse ([email protected])"); str += _T("\r\nPlease visit https://filezilla-project.org/"); } } break; case OPTION_ADMINIPBINDINGS: { CStdString sub; std::list<CStdString> ipBindList; for (unsigned int i = 0; i<_tcslen(value); i++) { TCHAR cur = value[i]; if ((cur < '0' || cur > '9') && cur != '.' && cur != ':') { if (sub == _T("") && cur == '*') { ipBindList.clear(); ipBindList.push_back(_T("*")); break; } if (sub != _T("")) { if (IsIpAddress(sub)) ipBindList.push_back(sub); sub = _T(""); } } else sub += cur; } if (sub != _T("")) { if (IsIpAddress(sub)) ipBindList.push_back(sub); } str = _T(""); for (std::list<CStdString>::iterator iter = ipBindList.begin(); iter!=ipBindList.end(); iter++) if (!IsLocalhost(*iter)) str += *iter + _T(" "); str.TrimRight(_T(" ")); } break; case OPTION_ADMINPASS: if (str != _T("") && str.GetLength() < 6) return; break; case OPTION_MODEZ_DISALLOWED_IPS: case OPTION_IPFILTER_ALLOWED: case OPTION_IPFILTER_DISALLOWED: case OPTION_ADMINIPADDRESSES: { str.Replace('\r', ' '); str.Replace('\n', ' '); str.Replace('\r', ' '); while (str.Replace(_T(" "), _T(" "))); str += _T(" "); CStdString ips; int pos = str.Find(' '); while (pos != -1) { CStdString sub = str.Left(pos); str = str.Mid(pos + 1); str.TrimLeft(' '); if (sub == _T("*")) ips += _T(" ") + sub; else { if (IsValidAddressFilter(sub)) ips += " " + sub; pos = str.Find(' '); } } ips.TrimLeft(' '); str = ips; } break; case OPTION_IPBINDINGS: { std::list<CStdString> ipBindList; str += _T(" "); while (!str.empty()) { int pos = str.Find(' '); if (pos < 0) { break; } CStdString sub = str.Left(pos); str = str.Mid(pos + 1); if (sub == _T("*")) { ipBindList.clear(); ipBindList.push_back(_T("*")); break; } else if (IsIpAddress(sub, true)) { ipBindList.push_back(sub); } } if (ipBindList.empty()) ipBindList.push_back(_T("*")); str.clear(); for (auto const& ip : ipBindList) { str += ip + _T(" "); } str.TrimRight(_T(" ")); } break; case OPTION_CUSTOMPASVIPSERVER: if (str.Find(_T("filezilla.sourceforge.net")) != -1) str = _T("http://ip.filezilla-project.org/ip.php"); break; } { simple_lock lock(m_mutex); m_sOptionsCache[nOptionID-1].bCached = TRUE; m_sOptionsCache[nOptionID-1].nType = 0; m_sOptionsCache[nOptionID-1].str = str; m_OptionsCache[nOptionID-1]=m_sOptionsCache[nOptionID-1]; } if (!save) return; USES_CONVERSION; CStdString xmlFileName = GetExecutableDirectory() + _T("FileZilla Server.xml"); char* bufferA = T2A(xmlFileName); if (!bufferA) return; TiXmlDocument document; if (!document.LoadFile(bufferA)) return; TiXmlElement* pRoot = document.FirstChildElement("FileZillaServer"); if (!pRoot) return; TiXmlElement* pSettings = pRoot->FirstChildElement("Settings"); if (!pSettings) pSettings = pRoot->LinkEndChild(new TiXmlElement("Settings"))->ToElement(); TiXmlElement* pItem; for (pItem = pSettings->FirstChildElement("Item"); pItem; pItem = pItem->NextSiblingElement("Item")) { const char* pName = pItem->Attribute("name"); if (!pName) continue; CStdString name(pName); if (name != m_Options[nOptionID-1].name) continue; break; } if (!pItem) pItem = pSettings->LinkEndChild(new TiXmlElement("Item"))->ToElement(); pItem->Clear(); pItem->SetAttribute("name", ConvToNetwork(m_Options[nOptionID - 1].name).c_str()); pItem->SetAttribute("type", "string"); pItem->LinkEndChild(new TiXmlText(ConvToNetwork(value).c_str())); document.SaveFile(bufferA); }
// Allow user to select a Fanart void CGUIDialogVideoInfo::OnGetFanart() { CFileItemList items; CFileItem item(*m_movieItem->GetVideoInfoTag()); if (item.HasArt("fanart")) { CFileItemPtr itemCurrent(new CFileItem("fanart://Current",false)); itemCurrent->SetArt("thumb", item.GetArt("fanart")); itemCurrent->SetLabel(g_localizeStrings.Get(20440)); items.Add(itemCurrent); } // ensure the fanart is unpacked m_movieItem->GetVideoInfoTag()->m_fanart.Unpack(); // Grab the thumbnails from the web for (unsigned int i = 0; i < m_movieItem->GetVideoInfoTag()->m_fanart.GetNumFanarts(); i++) { CStdString strItemPath; strItemPath.Format("fanart://Remote%i",i); CFileItemPtr item(new CFileItem(strItemPath, false)); CStdString thumb = m_movieItem->GetVideoInfoTag()->m_fanart.GetPreviewURL(i); item->SetArt("thumb", CTextureCache::GetWrappedThumbURL(thumb)); item->SetIconImage("DefaultPicture.png"); item->SetLabel(g_localizeStrings.Get(20441)); // TODO: Do we need to clear the cached image? // CTextureCache::Get().ClearCachedImage(thumb); items.Add(item); } CStdString strLocal = item.GetLocalFanart(); if (!strLocal.IsEmpty()) { CFileItemPtr itemLocal(new CFileItem("fanart://Local",false)); itemLocal->SetArt("thumb", strLocal); itemLocal->SetLabel(g_localizeStrings.Get(20438)); // TODO: Do we need to clear the cached image? CTextureCache::Get().ClearCachedImage(strLocal); items.Add(itemLocal); } else { CFileItemPtr itemNone(new CFileItem("fanart://None", false)); itemNone->SetIconImage("DefaultVideo.png"); itemNone->SetLabel(g_localizeStrings.Get(20439)); items.Add(itemNone); } CStdString result; VECSOURCES sources(*CMediaSourceSettings::Get().GetSources("video")); AddItemPathToFileBrowserSources(sources, item); g_mediaManager.GetLocalDrives(sources); bool flip=false; if (!CGUIDialogFileBrowser::ShowAndGetImage(items, sources, g_localizeStrings.Get(20437), result, &flip, 20445) || result.Equals("fanart://Current")) return; // user cancelled if (result.Equals("fanart://Local")) result = strLocal; if (result.Left(15) == "fanart://Remote") { int iFanart = atoi(result.Mid(15).c_str()); // set new primary fanart, and update our database accordingly m_movieItem->GetVideoInfoTag()->m_fanart.SetPrimaryFanart(iFanart); CVideoDatabase db; if (db.Open()) { db.UpdateFanart(*m_movieItem, (VIDEODB_CONTENT_TYPE)m_movieItem->GetVideoContentType()); db.Close(); } result = m_movieItem->GetVideoInfoTag()->m_fanart.GetImageURL(); } else if (result.Equals("fanart://None") || !CFile::Exists(result)) result.clear(); // set the fanart image if (flip && !result.IsEmpty()) result = CTextureCache::GetWrappedImageURL(result, "", "flipped"); CVideoDatabase db; if (db.Open()) { db.SetArtForItem(m_movieItem->GetVideoInfoTag()->m_iDbId, m_movieItem->GetVideoInfoTag()->m_type, "fanart", result); db.Close(); } CUtil::DeleteVideoDatabaseDirectoryCache(); // to get them new thumbs to show m_movieItem->SetArt("fanart", result); m_hasUpdatedThumb = true; // Update our screen Update(); }
TEST_F(CLuaTest, LoadConfig) { CStdString config; config = "name = \"hill\"\r\n" "age = 23\r\n" "married = true\r\n" "salary = 50432.34\r\n" "company = {'adobe', 'flukenetworks', 'cisco'}\r\n" "skill = {cplus='good', python='excellent', c=100, algorithm='excellent', pass=true}\r\n"; ASSERT_EQ(m_lua.doString(config), 0); CStdString value; bool bValue; double dValue; // // test the string value // ASSERT_TRUE(m_lua.loadString("name", value)); ASSERT_TRUE(value == "hill"); value.clear(); ASSERT_FALSE(m_lua.loadString("novalue", value)); value.clear(); ASSERT_TRUE(m_lua.loadString("age", value)); ASSERT_TRUE(value == "23"); // // test the bool value // value.clear(); ASSERT_FALSE(m_lua.loadString("married", value)); value.clear(); ASSERT_TRUE(m_lua.loadBoolean("married", bValue)); ASSERT_TRUE(bValue); // // test the number value // value.clear(); ASSERT_TRUE(m_lua.loadString("salary", value)); ASSERT_TRUE(value == "50432.34"); value.clear(); ASSERT_TRUE(m_lua.loadDouble("salary", dValue)); ASSERT_TRUE(dValue == 50432.34); // // test the array value // vector<CStdString> arrValue; ASSERT_TRUE(m_lua.loadArray_s("company", arrValue)); ASSERT_TRUE(arrValue[0] == "adobe"); ASSERT_TRUE(arrValue[1] == "flukenetworks"); ASSERT_TRUE(arrValue[2] == "cisco"); ASSERT_FALSE(m_lua.loadArray_s("NOcompany", arrValue)); // // test the table value // LuaObject objValue; ASSERT_FALSE(m_lua.loadObject("NObject", objValue)); ASSERT_TRUE(m_lua.loadObject("skill", objValue)); ASSERT_TRUE(objValue["cplus"] == "good"); ASSERT_TRUE(objValue["python"] == "excellent"); ASSERT_TRUE(objValue["pass"] == "true"); ASSERT_TRUE(objValue["c"] == "100"); ASSERT_TRUE(objValue["algorithm"] == "excellent"); ASSERT_FALSE(m_lua.loadObject("NObject", objValue)); }
void InfoExpression::Parse(const CStdString &expression) { stack<char> operators; CStdString operand; for (unsigned int i = 0; i < expression.size(); i++) { if (GetOperator(expression[i])) { // cleanup any operand, translate and put into our expression list if (!operand.empty()) { unsigned int info = g_infoManager.Register(operand, m_context); if (info) { m_postfix.push_back(m_operands.size()); m_operands.push_back(info); } operand.clear(); } // handle closing parenthesis if (expression[i] == ']') { while (!operators.empty()) { char oper = operators.top(); operators.pop(); if (oper == '[') break; m_postfix.push_back(-GetOperator(oper)); // negative denotes operator } } else { // all other operators we pop off the stack any operator // that has a higher priority than the one we have. while (!operators.empty() && GetOperator(operators.top()) > GetOperator(expression[i])) { // only handle parenthesis once they're closed. if (operators.top() == '[' && expression[i] != ']') break; m_postfix.push_back(-GetOperator(operators.top())); // negative denotes operator operators.pop(); } operators.push(expression[i]); } } else { operand += expression[i]; } } if (!operand.empty()) { unsigned int info = g_infoManager.Register(operand, m_context); if (info) { m_postfix.push_back(m_operands.size()); m_operands.push_back(info); } } // finish up by adding any operators while (!operators.empty()) { m_postfix.push_back(-GetOperator(operators.top())); // negative denotes operator operators.pop(); } // test evaluate bool test; if (!Evaluate(NULL, test)) CLog::Log(LOGERROR, "Error evaluating boolean expression %s", expression.c_str()); }
bool CRecentlyAddedJob::UpdateMusic() { CGUIWindow* home = g_windowManager.GetWindow(WINDOW_HOME); if ( home == NULL ) return false; CLog::Log(LOGDEBUG, "CRecentlyAddedJob::UpdateMusic() - Running RecentlyAdded home screen update"); int i = 0; CFileItemList musicItems; CMusicDatabase musicdatabase; CMusicThumbLoader loader; loader.Initialize(); musicdatabase.Open(); if (musicdatabase.GetRecentlyAddedAlbumSongs("musicdb://4/", musicItems, NUM_ITEMS)) { long idAlbum = -1; CStdString strAlbumThumb; CStdString strAlbumFanart; for (; i < musicItems.Size(); ++i) { CFileItemPtr item = musicItems.Get(i); CStdString value; value.Format("%i", i + 1); CStdString strRating; CStdString strAlbum = item->GetMusicInfoTag()->GetAlbum(); CStdString strArtist = StringUtils::Join(item->GetMusicInfoTag()->GetArtist(), g_advancedSettings.m_musicItemSeparator); if (idAlbum != item->GetMusicInfoTag()->GetAlbumId()) { strAlbumThumb.clear(); strAlbumFanart.clear(); idAlbum = item->GetMusicInfoTag()->GetAlbumId(); if (loader.LoadItem(item.get())) { strAlbumThumb = item->GetArt("thumb"); strAlbumFanart = item->GetArt("fanart"); } } strRating.Format("%c", item->GetMusicInfoTag()->GetRating()); home->SetProperty("LatestSong." + value + ".Title" , item->GetMusicInfoTag()->GetTitle()); home->SetProperty("LatestSong." + value + ".Year" , item->GetMusicInfoTag()->GetYear()); home->SetProperty("LatestSong." + value + ".Artist" , strArtist); home->SetProperty("LatestSong." + value + ".Album" , strAlbum); home->SetProperty("LatestSong." + value + ".Rating" , strRating); home->SetProperty("LatestSong." + value + ".Path" , item->GetMusicInfoTag()->GetURL()); home->SetProperty("LatestSong." + value + ".Thumb" , strAlbumThumb); home->SetProperty("LatestSong." + value + ".Fanart" , strAlbumFanart); } } for (; i < NUM_ITEMS; ++i) { CStdString value; value.Format("%i", i + 1); home->SetProperty("LatestSong." + value + ".Title" , ""); home->SetProperty("LatestSong." + value + ".Year" , ""); home->SetProperty("LatestSong." + value + ".Artist" , ""); home->SetProperty("LatestSong." + value + ".Album" , ""); home->SetProperty("LatestSong." + value + ".Rating" , ""); home->SetProperty("LatestSong." + value + ".Path" , ""); home->SetProperty("LatestSong." + value + ".Thumb" , ""); home->SetProperty("LatestSong." + value + ".Fanart" , ""); } i = 0; VECALBUMS albums; if (musicdatabase.GetRecentlyAddedAlbums(albums, NUM_ITEMS)) { for (; i < (int)albums.size(); ++i) { CStdString value; CStdString strPath; CStdString strThumb; CStdString strFanart; CStdString strDBpath; CStdString strSQLAlbum; CAlbum& album=albums[i]; value.Format("%i", i + 1); strThumb = musicdatabase.GetArtForItem(album.idAlbum, "album", "thumb"); strFanart = musicdatabase.GetArtistArtForItem(album.idAlbum, "album", "fanart"); strDBpath.Format("musicdb://3/%i/", album.idAlbum); strSQLAlbum.Format("idAlbum=%i", album.idAlbum); CStdString strArtist = musicdatabase.GetSingleValue("albumview", "strArtists", strSQLAlbum); home->SetProperty("LatestAlbum." + value + ".Title" , album.strAlbum); home->SetProperty("LatestAlbum." + value + ".Year" , album.iYear); home->SetProperty("LatestAlbum." + value + ".Artist" , strArtist); home->SetProperty("LatestAlbum." + value + ".Rating" , album.iRating); home->SetProperty("LatestAlbum." + value + ".Path" , strDBpath); home->SetProperty("LatestAlbum." + value + ".Thumb" , strThumb); home->SetProperty("LatestAlbum." + value + ".Fanart" , strFanart); } } for (; i < NUM_ITEMS; ++i) { CStdString value; value.Format("%i", i + 1); home->SetProperty("LatestAlbum." + value + ".Title" , ""); home->SetProperty("LatestAlbum." + value + ".Year" , ""); home->SetProperty("LatestAlbum." + value + ".Artist" , ""); home->SetProperty("LatestAlbum." + value + ".Rating" , ""); home->SetProperty("LatestAlbum." + value + ".Path" , ""); home->SetProperty("LatestAlbum." + value + ".Thumb" , ""); home->SetProperty("LatestAlbum." + value + ".Fanart" , ""); } musicdatabase.Close(); return true; }
void CGUIDialogMediaFilter::OnSettingChanged(SettingInfo &setting) { map<uint32_t, Filter>::iterator it = m_filters.find(setting.id); if (it == m_filters.end()) return; bool changed = true; bool remove = false; Filter& filter = it->second; switch (filter.type) { case SettingInfo::STRING: case SettingInfo::EDIT: { CStdString *str = static_cast<CStdString*>(filter.data); if (!str->empty()) { if (filter.rule == NULL) filter.rule = AddRule(filter.field, filter.ruleOperator); filter.rule->m_parameter.clear(); filter.rule->m_parameter.push_back(*str); } else remove = true; break; } case SettingInfo::CHECK: { int choice = *(int *)setting.data; if (choice > CHECK_ALL) { CSmartPlaylistRule::SEARCH_OPERATOR ruleOperator = choice == CHECK_YES ? CSmartPlaylistRule::OPERATOR_TRUE : CSmartPlaylistRule::OPERATOR_FALSE; if (filter.rule == NULL) filter.rule = AddRule(filter.field, ruleOperator); else filter.rule->m_operator = ruleOperator; } else remove = true; break; } case SettingInfo::BUTTON: { CFileItemList items; OnBrowse(filter, items); if (items.Size() > 0) { if (filter.rule == NULL) filter.rule = AddRule(filter.field, filter.ruleOperator); filter.rule->m_parameter.clear(); for (int index = 0; index < items.Size(); index++) filter.rule->m_parameter.push_back(items[index]->GetLabel()); *(CStdString *)filter.data = filter.rule->GetLocalizedParameter(m_mediaType); } else { remove = true; *(CStdString *)filter.data = ""; } SET_CONTROL_LABEL2(filter.controlIndex, *(CStdString *)filter.data); break; } case SettingInfo::RANGE: { SettingInfo &setting = m_settings[filter.controlIndex - CONTROL_START]; float *valueLower = ((float **)filter.data)[0]; float *valueUpper = ((float **)filter.data)[1]; if (*valueLower > setting.min || *valueUpper < setting.max) { if (filter.rule == NULL) filter.rule = AddRule(filter.field, filter.ruleOperator); filter.rule->m_parameter.clear(); if (filter.field == FieldAirDate) { CDateTime lower = (time_t)*valueLower; CDateTime upper = (time_t)*valueUpper; filter.rule->m_parameter.push_back(lower.GetAsDBDate()); filter.rule->m_parameter.push_back(upper.GetAsDBDate()); } else { CStdString tmp; tmp.Format("%.1f", *valueLower); filter.rule->m_parameter.push_back(tmp); tmp.clear(); tmp.Format("%.1f", *valueUpper); filter.rule->m_parameter.push_back(tmp); } } else { remove = true; *((float **)filter.data)[0] = setting.min; *((float **)filter.data)[1] = setting.max; } break; } default: changed = false; break; } // we need to remove the existing rule for the title if (remove && filter.rule != NULL) { DeleteRule(filter.field); filter.rule = NULL; } if (changed) { CGUIMessage message(GUI_MSG_NOTIFY_ALL, GetID(), 0, GUI_MSG_FILTER_ITEMS, 10); // 10 for advanced g_windowManager.SendMessage(message); UpdateControls(); } }
void CGUIDialogMediaSource::OnPathBrowse(int item) { if (item < 0 || item > m_paths->Size()) return; // Browse is called. Open the filebrowser dialog. // Ignore current path is best at this stage?? CStdString path; bool allowNetworkShares(m_type != "programs"); VECSOURCES extraShares; if (m_name != CUtil::GetTitleFromPath(m_paths->Get(item)->GetPath())) m_bNameChanged=true; if (m_type == "music") { CMediaSource share1; #if defined(TARGET_ANDROID) // add the default android music directory std::string path; if (CXBMCApp::GetExternalStorage(path, "music") && !path.empty() && CFile::Exists(path)) { share1.strPath = path; share1.strName = g_localizeStrings.Get(20240); share1.m_ignore = true; extraShares.push_back(share1); } #endif // add the music playlist location share1.strPath = "special://musicplaylists/"; share1.strName = g_localizeStrings.Get(20011); share1.m_ignore = true; extraShares.push_back(share1); share1.strPath = "sap://"; share1.strName = "SAP Streams"; extraShares.push_back(share1); if (CSettings::Get().GetString("audiocds.recordingpath") != "") { share1.strPath = "special://recordings/"; share1.strName = g_localizeStrings.Get(21883); extraShares.push_back(share1); } } else if (m_type == "video") { CMediaSource share1; #if defined(TARGET_ANDROID) // add the default android video directory std::string path; if (CXBMCApp::GetExternalStorage(path, "videos") && !path.empty() && CFile::Exists(path)) { share1.strPath = path; share1.strName = g_localizeStrings.Get(20241); share1.m_ignore = true; extraShares.push_back(share1); } #endif // add the video playlist location share1.m_ignore = true; share1.strPath = "special://videoplaylists/"; share1.strName = g_localizeStrings.Get(20012); extraShares.push_back(share1); share1.strPath = "rtv://*/"; share1.strName = "ReplayTV Devices"; extraShares.push_back(share1); share1.strPath = "hdhomerun://"; share1.strName = "HDHomerun Devices"; extraShares.push_back(share1); share1.strPath = "sap://"; share1.strName = "SAP Streams"; extraShares.push_back(share1); // add the recordings dir as needed if (CPVRDirectory::HasRecordings()) { share1.strPath = "pvr://recordings/"; share1.strName = g_localizeStrings.Get(19017); // TV Recordings extraShares.push_back(share1); } } else if (m_type == "pictures") { CMediaSource share1; #if defined(TARGET_ANDROID) // add the default android music directory std::string path; if (CXBMCApp::GetExternalStorage(path, "pictures") && !path.empty() && CFile::Exists(path)) { share1.strPath = path; share1.strName = g_localizeStrings.Get(20242); share1.m_ignore = true; extraShares.push_back(share1); } path.clear(); if (CXBMCApp::GetExternalStorage(path, "photos") && !path.empty() && CFile::Exists(path)) { share1.strPath = path; share1.strName = g_localizeStrings.Get(20243); share1.m_ignore = true; extraShares.push_back(share1); } #endif share1.m_ignore = true; if (CSettings::Get().GetString("debug.screenshotpath") != "") { share1.strPath = "special://screenshots/"; share1.strName = g_localizeStrings.Get(20008); extraShares.push_back(share1); } } else if (m_type == "programs") { // nothing to add } if (CGUIDialogFileBrowser::ShowAndGetSource(path, allowNetworkShares, extraShares.size()==0?NULL:&extraShares)) { if (item < m_paths->Size()) // if the skin does funky things, m_paths may have been cleared m_paths->Get(item)->SetPath(path); if (!m_bNameChanged || m_name.empty()) { CURL url(path); m_name = url.GetWithoutUserDetails(); URIUtils::RemoveSlashAtEnd(m_name); m_name = CUtil::GetTitleFromPath(m_name); } UpdateButtons(); } }
CStdString CID3Tag::ParseMP3Genre(const CStdString& str) const { m_dll.Load(); CStdString strTemp = str; set<CStdString> setGenres; while (!strTemp.IsEmpty()) { // remove any leading spaces strTemp.TrimLeft(); if (strTemp.IsEmpty()) break; // start off looking for (something) if (strTemp[0] == '(') { strTemp.erase(0, 1); if (strTemp.empty()) break; // now look for ((something)) if (strTemp[0] == '(') { // remove ((something)) int i = strTemp.find_first_of(')'); strTemp.erase(0, i + 2); } } // no parens, so we have a start of a string // push chars into temp string until valid terminator found // valid terminators are ) or , or ; else { CStdString t; size_t i = strTemp.find_first_of("),;"); if (i != std::string::npos) { t = strTemp.Left(i); strTemp.erase(0, i + 1); } else { t = strTemp; strTemp.clear(); } // remove any leading or trailing white space // from temp string t.Trim(); if (!t.length()) continue; // if the temp string is natural number try to convert it to a genre string if (StringUtils::IsNaturalNumber(t)) { id3_ucs4_t* ucs4=m_dll.id3_latin1_ucs4duplicate((id3_latin1_t*)t.c_str()); const id3_ucs4_t* genre=m_dll.id3_genre_name(ucs4); m_dll.id3_ucs4_free(ucs4); t=ToStringCharset(genre, ID3_FIELD_TEXTENCODING_ISO_8859_1); } // convert RX to Remix as per ID3 V2.3 spec else if ((t == "RX") || (t == "Rx") || (t == "rX") || (t == "rx")) { t = "Remix"; } // convert CR to Cover as per ID3 V2.3 spec else if ((t == "CR") || (t == "Cr") || (t == "cR") || (t == "cr")) { t = "Cover"; } // insert genre name in set setGenres.insert(t); } } // return a " / " seperated string CStdString strGenre; set<CStdString>::iterator it; for (it = setGenres.begin(); it != setGenres.end(); it++) { CStdString strTemp = *it; if (!strGenre.IsEmpty()) strGenre += g_advancedSettings.m_musicItemSeparator; strGenre += strTemp; } return strGenre; }
void CDVDPlayerVideo::Process() { CLog::Log(LOGNOTICE, "running thread: video_thread"); DVDVideoPicture picture; CPulldownCorrection pulldown; CDVDVideoPPFFmpeg mPostProcess(""); CStdString sPostProcessType; bool bPostProcessDeint = false; memset(&picture, 0, sizeof(DVDVideoPicture)); double pts = 0; double frametime = (double)DVD_TIME_BASE / m_fFrameRate; int iDropped = 0; //frames dropped in a row bool bRequestDrop = false; m_videoStats.Start(); while (!m_bStop) { int iQueueTimeOut = (int)(m_stalled ? frametime / 4 : frametime * 10) / 1000; int iPriority = (m_speed == DVD_PLAYSPEED_PAUSE && m_started) ? 1 : 0; CDVDMsg* pMsg; MsgQueueReturnCode ret = m_messageQueue.Get(&pMsg, iQueueTimeOut, iPriority); if (MSGQ_IS_ERROR(ret) || ret == MSGQ_ABORT) { CLog::Log(LOGERROR, "Got MSGQ_ABORT or MSGO_IS_ERROR return true"); break; } else if (ret == MSGQ_TIMEOUT) { // if we only wanted priority messages, this isn't a stall if( iPriority ) continue; //Okey, start rendering at stream fps now instead, we are likely in a stillframe if( !m_stalled ) { if(m_started) CLog::Log(LOGINFO, "CDVDPlayerVideo - Stillframe detected, switching to forced %f fps", m_fFrameRate); m_stalled = true; pts+= frametime*4; } //Waiting timed out, output last picture if( picture.iFlags & DVP_FLAG_ALLOCATED ) { //Remove interlaced flag before outputting //no need to output this as if it was interlaced picture.iFlags &= ~DVP_FLAG_INTERLACED; picture.iFlags |= DVP_FLAG_NOSKIP; OutputPicture(&picture, pts); pts+= frametime; } continue; } if (pMsg->IsType(CDVDMsg::GENERAL_SYNCHRONIZE)) { ((CDVDMsgGeneralSynchronize*)pMsg)->Wait( &m_bStop, SYNCSOURCE_VIDEO ); CLog::Log(LOGDEBUG, "CDVDPlayerVideo - CDVDMsg::GENERAL_SYNCHRONIZE"); pMsg->Release(); /* we may be very much off correct pts here, but next picture may be a still*/ /* make sure it isn't dropped */ m_iNrOfPicturesNotToSkip = 5; continue; } else if (pMsg->IsType(CDVDMsg::GENERAL_RESYNC)) { CDVDMsgGeneralResync* pMsgGeneralResync = (CDVDMsgGeneralResync*)pMsg; if(pMsgGeneralResync->m_timestamp != DVD_NOPTS_VALUE) pts = pMsgGeneralResync->m_timestamp; double delay = m_FlipTimeStamp - m_pClock->GetAbsoluteClock(); if( delay > frametime ) delay = frametime; else if( delay < 0 ) delay = 0; if(pMsgGeneralResync->m_clock) { CLog::Log(LOGDEBUG, "CDVDPlayerVideo - CDVDMsg::GENERAL_RESYNC(%f, 1)", pts); m_pClock->Discontinuity(pts - delay); } else CLog::Log(LOGDEBUG, "CDVDPlayerVideo - CDVDMsg::GENERAL_RESYNC(%f, 0)", pts); pMsgGeneralResync->Release(); continue; } else if (pMsg->IsType(CDVDMsg::GENERAL_DELAY)) { if (m_speed != DVD_PLAYSPEED_PAUSE) { double timeout = static_cast<CDVDMsgDouble*>(pMsg)->m_value; CLog::Log(LOGDEBUG, "CDVDPlayerVideo - CDVDMsg::GENERAL_DELAY(%f)", timeout); timeout *= (double)DVD_PLAYSPEED_NORMAL / abs(m_speed); timeout += CDVDClock::GetAbsoluteClock(); while(!m_bStop && CDVDClock::GetAbsoluteClock() < timeout) Sleep(1); } } else if (pMsg->IsType(CDVDMsg::VIDEO_SET_ASPECT)) { CLog::Log(LOGDEBUG, "CDVDPlayerVideo - CDVDMsg::VIDEO_SET_ASPECT"); m_fForcedAspectRatio = *((CDVDMsgDouble*)pMsg); } else if (pMsg->IsType(CDVDMsg::GENERAL_RESET)) { if(m_pVideoCodec) m_pVideoCodec->Reset(); picture.iFlags &= ~DVP_FLAG_ALLOCATED; m_packets.clear(); m_started = false; } else if (pMsg->IsType(CDVDMsg::GENERAL_FLUSH)) // private message sent by (CDVDPlayerVideo::Flush()) { if(m_pVideoCodec) m_pVideoCodec->Reset(); picture.iFlags &= ~DVP_FLAG_ALLOCATED; m_packets.clear(); m_pullupCorrection.Flush(); //we need to recalculate the framerate //TODO: this needs to be set on a streamchange instead ResetFrameRateCalc(); m_stalled = true; m_started = false; } else if (pMsg->IsType(CDVDMsg::VIDEO_NOSKIP)) { // libmpeg2 is also returning incomplete frames after a dvd cell change // so the first few pictures are not the correct ones to display in some cases // just display those together with the correct one. // (setting it to 2 will skip some menu stills, 5 is working ok for me). m_iNrOfPicturesNotToSkip = 5; } else if (pMsg->IsType(CDVDMsg::PLAYER_SETSPEED)) { m_speed = static_cast<CDVDMsgInt*>(pMsg)->m_value; if(m_speed == DVD_PLAYSPEED_PAUSE) m_iNrOfPicturesNotToSkip = 0; } else if (pMsg->IsType(CDVDMsg::PLAYER_STARTED)) { if(m_started) m_messageParent.Put(new CDVDMsgInt(CDVDMsg::PLAYER_STARTED, DVDPLAYER_VIDEO)); } else if (pMsg->IsType(CDVDMsg::GENERAL_STREAMCHANGE)) { CDVDMsgVideoCodecChange* msg(static_cast<CDVDMsgVideoCodecChange*>(pMsg)); OpenStream(msg->m_hints, msg->m_codec); msg->m_codec = NULL; picture.iFlags &= ~DVP_FLAG_ALLOCATED; } if (pMsg->IsType(CDVDMsg::DEMUXER_PACKET)) { DemuxPacket* pPacket = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacket(); bool bPacketDrop = ((CDVDMsgDemuxerPacket*)pMsg)->GetPacketDrop(); if (m_stalled) { CLog::Log(LOGINFO, "CDVDPlayerVideo - Stillframe left, switching to normal playback"); m_stalled = false; //don't allow the first frames after a still to be dropped //sometimes we get multiple stills (long duration frames) after each other //in normal mpegs m_iNrOfPicturesNotToSkip = 5; } else if( iDropped*frametime > DVD_MSEC_TO_TIME(100) && m_iNrOfPicturesNotToSkip == 0 ) { // if we dropped too many pictures in a row, insert a forced picture m_iNrOfPicturesNotToSkip = 1; } #ifdef PROFILE bRequestDrop = false; #else if (m_messageQueue.GetDataSize() == 0 || m_speed < 0) { bRequestDrop = false; m_iDroppedRequest = 0; m_iLateFrames = 0; } #endif // if player want's us to drop this packet, do so nomatter what if(bPacketDrop) bRequestDrop = true; // tell codec if next frame should be dropped // problem here, if one packet contains more than one frame // both frames will be dropped in that case instead of just the first // decoder still needs to provide an empty image structure, with correct flags m_pVideoCodec->SetDropState(bRequestDrop); // ask codec to do deinterlacing if possible EDEINTERLACEMODE mDeintMode = g_settings.m_currentVideoSettings.m_DeinterlaceMode; EINTERLACEMETHOD mInt = g_renderManager.AutoInterlaceMethod(g_settings.m_currentVideoSettings.m_InterlaceMethod); unsigned int mFilters = 0; if (mDeintMode != VS_DEINTERLACEMODE_OFF) { if (mInt == VS_INTERLACEMETHOD_DEINTERLACE) mFilters = CDVDVideoCodec::FILTER_DEINTERLACE_ANY; else if(mInt == VS_INTERLACEMETHOD_DEINTERLACE_HALF) mFilters = CDVDVideoCodec::FILTER_DEINTERLACE_ANY | CDVDVideoCodec::FILTER_DEINTERLACE_HALFED; if (mDeintMode == VS_DEINTERLACEMODE_AUTO && mFilters) mFilters |= CDVDVideoCodec::FILTER_DEINTERLACE_FLAGGED; } mFilters = m_pVideoCodec->SetFilters(mFilters); int iDecoderState = m_pVideoCodec->Decode(pPacket->pData, pPacket->iSize, pPacket->dts, pPacket->pts); // buffer packets so we can recover should decoder flush for some reason if(m_pVideoCodec->GetConvergeCount() > 0) { m_packets.push_back(DVDMessageListItem(pMsg, 0)); if(m_packets.size() > m_pVideoCodec->GetConvergeCount() || m_packets.size() * frametime > DVD_SEC_TO_TIME(10)) m_packets.pop_front(); } m_videoStats.AddSampleBytes(pPacket->iSize); // assume decoder dropped a picture if it didn't give us any // picture from a demux packet, this should be reasonable // for libavformat as a demuxer as it normally packetizes // pictures when they come from demuxer if(bRequestDrop && !bPacketDrop && (iDecoderState & VC_BUFFER) && !(iDecoderState & VC_PICTURE)) { m_iDroppedFrames++; iDropped++; } // loop while no error while (!m_bStop) { // if decoder was flushed, we need to seek back again to resume rendering if (iDecoderState & VC_FLUSHED) { CLog::Log(LOGDEBUG, "CDVDPlayerVideo - video decoder was flushed"); while(!m_packets.empty()) { CDVDMsgDemuxerPacket* msg = (CDVDMsgDemuxerPacket*)m_packets.front().message->Acquire(); m_packets.pop_front(); // all packets except the last one should be dropped // if prio packets and current packet should be dropped, this is likely a new reset msg->m_drop = !m_packets.empty() || (iPriority > 0 && bPacketDrop); m_messageQueue.Put(msg, iPriority + 10); } m_pVideoCodec->Reset(); m_packets.clear(); break; } // if decoder had an error, tell it to reset to avoid more problems if (iDecoderState & VC_ERROR) { CLog::Log(LOGDEBUG, "CDVDPlayerVideo - video decoder returned error"); break; } // check for a new picture if (iDecoderState & VC_PICTURE) { do { // note: decoder may have multiple buffers to return to us, so // keep popping out buffers until there are no more: m_pVideoCodec->ClearPicture(&picture); if (! m_pVideoCodec->GetPicture(&picture)) break; sPostProcessType.clear(); picture.iGroupId = pPacket->iGroupId; if(picture.iDuration == 0.0) picture.iDuration = frametime; if(bPacketDrop) picture.iFlags |= DVP_FLAG_DROPPED; if (m_iNrOfPicturesNotToSkip > 0) { picture.iFlags |= DVP_FLAG_NOSKIP; m_iNrOfPicturesNotToSkip--; } // validate picture timing, // if both dts/pts invalid, use pts calulated from picture.iDuration // if pts invalid use dts, else use picture.pts as passed if (picture.dts == DVD_NOPTS_VALUE && picture.pts == DVD_NOPTS_VALUE) picture.pts = pts; else if (picture.pts == DVD_NOPTS_VALUE) picture.pts = picture.dts; /* use forced aspect if any */ if( m_fForcedAspectRatio != 0.0f ) picture.iDisplayWidth = (int) (picture.iDisplayHeight * m_fForcedAspectRatio); //Deinterlace if codec said format was interlaced or if we have selected we want to deinterlace //this video if ((mDeintMode == VS_DEINTERLACEMODE_AUTO && (picture.iFlags & DVP_FLAG_INTERLACED)) || mDeintMode == VS_DEINTERLACEMODE_FORCE) { if(mInt == VS_INTERLACEMETHOD_SW_BLEND) { if (!sPostProcessType.empty()) sPostProcessType += ","; sPostProcessType += g_advancedSettings.m_videoPPFFmpegDeint; bPostProcessDeint = true; } } if (g_settings.m_currentVideoSettings.m_PostProcess) { if (!sPostProcessType.empty()) sPostProcessType += ","; // This is what mplayer uses for its "high-quality filter combination" sPostProcessType += g_advancedSettings.m_videoPPFFmpegPostProc; } if (!sPostProcessType.empty()) { mPostProcess.SetType(sPostProcessType, bPostProcessDeint); if (mPostProcess.Process(&picture)) mPostProcess.GetPicture(&picture); } /* if frame has a pts (usually originiating from demux packet), use that */ if(picture.pts != DVD_NOPTS_VALUE) { if(pulldown.enabled()) picture.pts += pulldown.pts(); pts = picture.pts; } if(pulldown.enabled()) { picture.iDuration = pulldown.dur(); pulldown.next(); } if (picture.iRepeatPicture) picture.iDuration *= picture.iRepeatPicture + 1; #if 1 int iResult = OutputPicture(&picture, pts); #elif 0 // testing NV12 rendering functions DVDVideoPicture* pTempNV12Picture = CDVDCodecUtils::ConvertToNV12Picture(&picture); int iResult = OutputPicture(pTempNV12Picture, pts); CDVDCodecUtils::FreePicture(pTempNV12Picture); #elif 0 // testing YUY2 or UYVY rendering functions // WARNING: since this scales a full YV12 frame, weaving artifacts will show on interlaced content // even with the deinterlacer on DVDVideoPicture* pTempYUVPackedPicture = CDVDCodecUtils::ConvertToYUV422PackedPicture(&picture, DVDVideoPicture::FMT_UYVY); //DVDVideoPicture* pTempYUVPackedPicture = CDVDCodecUtils::ConvertToYUV422PackedPicture(&picture, DVDVideoPicture::FMT_YUY2); int iResult = OutputPicture(pTempYUVPackedPicture, pts); CDVDCodecUtils::FreePicture(pTempYUVPackedPicture); #endif if(m_started == false) { m_codecname = m_pVideoCodec->GetName(); m_started = true; m_messageParent.Put(new CDVDMsgInt(CDVDMsg::PLAYER_STARTED, DVDPLAYER_VIDEO)); } // guess next frame pts. iDuration is always valid if (m_speed != 0) pts += picture.iDuration * m_speed / abs(m_speed); if( iResult & EOS_ABORT ) { //if we break here and we directly try to decode again wihout //flushing the video codec things break for some reason //i think the decoder (libmpeg2 atleast) still has a pointer //to the data, and when the packet is freed that will fail. iDecoderState = m_pVideoCodec->Decode(NULL, 0, DVD_NOPTS_VALUE, DVD_NOPTS_VALUE); break; } if( (iResult & EOS_DROPPED) && !bPacketDrop ) { m_iDroppedFrames++; iDropped++; } else iDropped = 0; bRequestDrop = (iResult & EOS_VERYLATE) == EOS_VERYLATE; } while (true); } /* if (iDecoderState & VC_USERDATA) { // found some userdata while decoding a frame // could be closed captioning DVDVideoUserData videoUserData; if (m_pVideoCodec->GetUserData(&videoUserData)) { ProcessVideoUserData(&videoUserData, pts); } } */ // if the decoder needs more data, we just break this loop // and try to get more data from the videoQueue if (iDecoderState & VC_BUFFER) break; // the decoder didn't need more data, flush the remaning buffer iDecoderState = m_pVideoCodec->Decode(NULL, 0, DVD_NOPTS_VALUE, DVD_NOPTS_VALUE); } } // all data is used by the decoder, we can safely free it now pMsg->Release(); } // we need to let decoder release any picture retained resources. m_pVideoCodec->ClearPicture(&picture); }
void CGUIDialogVideoInfo::OnGetArt() { map<string, string> currentArt; string type = ChooseArtType(*m_movieItem, currentArt); if (type.empty()) return; // cancelled // TODO: this can be removed once these are unified. if (type == "fanart") OnGetFanart(); else { CFileItemList items; // Current thumb if (m_movieItem->HasArt(type)) { CFileItemPtr item(new CFileItem("thumb://Current", false)); item->SetArt("thumb", m_movieItem->GetArt(type)); item->SetLabel(g_localizeStrings.Get(13512)); items.Add(item); } else if ((type == "poster" || type == "banner") && currentArt.find("thumb") != currentArt.end()) { // add the 'thumb' type in CFileItemPtr item(new CFileItem("thumb://Thumb", false)); item->SetArt("thumb", currentArt["thumb"]); item->SetLabel(g_localizeStrings.Get(13512)); items.Add(item); } // Grab the thumbnails from the web vector<CStdString> thumbs; int season = (m_movieItem->GetVideoInfoTag()->m_type == "season") ? m_movieItem->GetVideoInfoTag()->m_iSeason : -1; m_movieItem->GetVideoInfoTag()->m_strPictureURL.GetThumbURLs(thumbs, type, season); for (unsigned int i = 0; i < thumbs.size(); ++i) { CStdString strItemPath; strItemPath.Format("thumb://Remote%i", i); CFileItemPtr item(new CFileItem(strItemPath, false)); item->SetArt("thumb", thumbs[i]); item->SetIconImage("DefaultPicture.png"); item->SetLabel(g_localizeStrings.Get(13513)); // TODO: Do we need to clear the cached image? // CTextureCache::Get().ClearCachedImage(thumb); items.Add(item); } CStdString localThumb = CVideoThumbLoader::GetLocalArt(*m_movieItem, type); if (!localThumb.empty()) { CFileItemPtr item(new CFileItem("thumb://Local", false)); item->SetArt("thumb", localThumb); item->SetLabel(g_localizeStrings.Get(13514)); items.Add(item); } else { // no local thumb exists, so we are just using the IMDb thumb or cached thumb // which is probably the IMDb thumb. These could be wrong, so allow the user // to delete the incorrect thumb CFileItemPtr item(new CFileItem("thumb://None", false)); item->SetIconImage("DefaultVideo.png"); item->SetLabel(g_localizeStrings.Get(13515)); items.Add(item); } CStdString result; VECSOURCES sources(*CMediaSourceSettings::Get().GetSources("video")); AddItemPathToFileBrowserSources(sources, *m_movieItem); g_mediaManager.GetLocalDrives(sources); if (CGUIDialogFileBrowser::ShowAndGetImage(items, sources, g_localizeStrings.Get(13511), result) && result != "thumb://Current") // user didn't choose the one they have { CStdString newThumb; if (result.Left(14) == "thumb://Remote") { int number = atoi(result.Mid(14)); newThumb = thumbs[number]; } else if (result == "thumb://Thumb") newThumb = currentArt["thumb"]; else if (result == "thumb://Local") newThumb = localThumb; else if (CFile::Exists(result)) newThumb = result; else // none newThumb.clear(); // update thumb in the database CVideoDatabase db; if (db.Open()) { db.SetArtForItem(m_movieItem->GetVideoInfoTag()->m_iDbId, m_movieItem->GetVideoInfoTag()->m_type, type, newThumb); db.Close(); } CUtil::DeleteVideoDatabaseDirectoryCache(); // to get them new thumbs to show m_movieItem->SetArt(type, newThumb); if (m_movieItem->HasProperty("set_folder_thumb")) { // have a folder thumb to set as well VIDEO::CVideoInfoScanner::ApplyThumbToFolder(m_movieItem->GetProperty("set_folder_thumb").asString(), newThumb); } m_hasUpdatedThumb = true; } } // Update our screen Update(); // re-open the art selection dialog as we come back from // the image selection dialog OnGetArt(); }