void CGUIWindowMusicPlaylistEditor::OnLoadPlaylist() { // prompt user for file to load std::string playlist; VECSOURCES shares; m_rootDir.GetSources(shares); // add the playlist share CMediaSource share; share.strName = g_localizeStrings.Get(20011); share.strPath = "special://musicplaylists/"; if (find(shares.begin(), shares.end(), share) == shares.end()) shares.push_back(share); if (CGUIDialogFileBrowser::ShowAndGetFile(shares, ".m3u|.pls|.b4s|.wpl", g_localizeStrings.Get(656), playlist)) LoadPlaylist(playlist); }
// NOTE: This function does NOT save the sources.xml file - you need to call SaveSources() separately. bool CMediaSourceSettings::UpdateSource(const std::string &strType, const std::string &strOldName, const std::string &strUpdateChild, const std::string &strUpdateValue) { VECSOURCES *pShares = GetSources(strType); if (pShares == NULL) return false; for (IVECSOURCES it = pShares->begin(); it != pShares->end(); it++) { if (it->strName == strOldName) { if (strUpdateChild == "name") it->strName = strUpdateValue; else if (strUpdateChild == "lockmode") it->m_iLockMode = (LockType)std::strtol(strUpdateValue.c_str(), NULL, 10); else if (strUpdateChild == "lockcode") it->m_strLockCode = strUpdateValue; else if (strUpdateChild == "badpwdcount") it->m_iBadPwdCount = (int)std::strtol(strUpdateValue.c_str(), NULL, 10); else if (strUpdateChild == "thumbnail") it->m_strThumbnailImage = strUpdateValue; else if (strUpdateChild == "path") { it->vecPaths.clear(); it->strPath = strUpdateValue; it->vecPaths.push_back(strUpdateValue); } else return false; return true; } } return false; }
bool CMediaSourceSettings::UpdateShare(const std::string &type, const std::string &oldName, const CMediaSource &share) { VECSOURCES *pShares = GetSources(type); if (pShares == NULL) return false; // update our current share list CMediaSource* pShare = NULL; for (IVECSOURCES it = pShares->begin(); it != pShares->end(); it++) { if (it->strName == oldName) { it->strName = share.strName; it->strPath = share.strPath; it->vecPaths = share.vecPaths; pShare = &(*it); break; } } if (pShare == NULL) return false; // Update our XML file as well return Save(); }
void CGUIDialogMediaSource::OnOK() { // verify the path by doing a GetDirectory. CFileItemList items; CMediaSource share; share.FromNameAndPaths(m_type, m_name, GetPaths()); // hack: Need to temporarily add the share, then get path, then remove share VECSOURCES *shares = g_settings.GetSourcesFromType(m_type); if (shares) shares->push_back(share); if (share.strPath.Left(9).Equals("plugin://") || CDirectory::GetDirectory(share.strPath, items, "", false, true) || CGUIDialogYesNo::ShowAndGetInput(1001,1025,1003,1004)) { m_confirmed = true; Close(); } // Special handling of multipath:// shares. // * GetScraperForPath takes the first path of the multipath:// element to fetch needed scraper and scan settings. // * SetScraperForPath loops through all elements and adds the appropriate settings for each path. if (CUtil::IsMultiPath(share.strPath)) { CVideoDatabase database; database.Open(); m_info = database.GetScraperForPath(share.strPath, m_settings); database.SetScraperForPath(share.strPath, m_info, m_settings); database.Close(); } // and remove the share again if (shares) shares->erase(--shares->end()); }
bool CMediaSourceSettings::SetSources(TiXmlNode *root, const char *section, const VECSOURCES &shares, const std::string &defaultPath) const { TiXmlElement sectionElement(section); TiXmlNode *sectionNode = root->InsertEndChild(sectionElement); if (sectionNode == NULL) return false; XMLUtils::SetPath(sectionNode, "default", defaultPath); for (CIVECSOURCES it = shares.begin(); it != shares.end(); it++) { const CMediaSource &share = *it; if (share.m_ignore) continue; TiXmlElement source(XML_SOURCE); XMLUtils::SetString(&source, "name", share.strName); for (unsigned int i = 0; i < share.vecPaths.size(); i++) XMLUtils::SetPath(&source, "path", share.vecPaths[i]); if (share.m_iHasLock) { XMLUtils::SetInt(&source, "lockmode", share.m_iLockMode); XMLUtils::SetString(&source, "lockcode", share.m_strLockCode); XMLUtils::SetInt(&source, "badpwdcount", share.m_iBadPwdCount); } if (!share.m_strThumbnailImage.empty()) XMLUtils::SetPath(&source, "thumbnail", share.m_strThumbnailImage); sectionNode->InsertEndChild(source); } return true; }
void CFileScanner::InitSourcesOnStart() { VECSOURCES sources = *(g_settings.GetSourcesFromType("all")); CMediaSource* pShare = NULL; for (IVECSOURCES it = sources.begin(); it != sources.end(); it++) { pShare = &(*it); time_t iLastScanned; if (!BOXEE::Boxee::GetInstance().GetMetadataEngine().GetScanTime(pShare->strName, pShare->strPath, pShare->m_type, iLastScanned)) { CLog::Log(LOGWARNING,"CFileScanner::InitSourcesOnStart - FAILED to read LastScanTime of [name=%s][path=%s][type=%d]. [m_bPaused=%d][m_bStop=%d] (fs)",pShare->strName.c_str(),pShare->strPath.c_str(),pShare->m_iScanType,m_bPaused,m_bStop); continue; } if (iLastScanned == SHARE_TIMESTAMP_RESOLVING) { CLog::Log(LOGDEBUG,"CFileScanner::InitSourcesOnStart - for [name=%s][path=%s][type=%d] LastScanTime is [%lu=RESOLVING] going to reset it. [m_bPaused=%d][m_bStop=%d] (fs)",pShare->strName.c_str(),pShare->strPath.c_str(),pShare->m_iScanType,iLastScanned,m_bPaused,m_bStop); if (!BOXEE::Boxee::GetInstance().GetMetadataEngine().UpdateScanTime(pShare->strName, pShare->strPath, pShare->m_type, SHARE_TIMESTAMP_NOT_SCANNED)) { CLog::Log(LOGERROR,"CFileScanner::InitSourcesOnStart - FAILED to reset iLastScanned of source [name=%s][path=%s][type=%d]. [m_bPaused=%d][m_bStop=%d] (fs)",pShare->strName.c_str(),pShare->strPath.c_str(),pShare->m_iScanType,m_bPaused,m_bStop); } } } }
void CGUIDialogMediaSource::OnOK() { // verify the path by doing a GetDirectory. CFileItemList items; CMediaSource share; share.FromNameAndPaths(m_type, m_name, GetPaths()); // hack: Need to temporarily add the share, then get path, then remove share VECSOURCES *shares = CMediaSourceSettings::Get().GetSources(m_type); if (shares) shares->push_back(share); if (StringUtils::StartsWithNoCase(share.strPath, "plugin://") || CDirectory::GetDirectory(share.strPath, items, "", DIR_FLAG_NO_FILE_DIRS | DIR_FLAG_ALLOW_PROMPT) || CGUIDialogYesNo::ShowAndGetInput(1001,1025,1003,1004)) { m_confirmed = true; Close(); if (m_type == "video" && !URIUtils::IsLiveTV(share.strPath) && !StringUtils::StartsWithNoCase(share.strPath, "rss://") && !StringUtils::StartsWithNoCase(share.strPath, "upnp://")) { CGUIWindowVideoBase::OnAssignContent(share.strPath); } } // and remove the share again if (shares) shares->erase(--shares->end()); }
void CGUIDialogMediaSource::OnOK() { // verify the path by doing a GetDirectory. CFileItemList items; CMediaSource share; share.FromNameAndPaths(m_type, m_name, GetPaths()); // hack: Need to temporarily add the share, then get path, then remove share VECSOURCES *shares = g_settings.GetSourcesFromType(m_type); if (shares) shares->push_back(share); if (share.strPath.Left(9).Equals("plugin://") || CDirectory::GetDirectory(share.strPath, items, "", false, true) || CGUIDialogYesNo::ShowAndGetInput(1001,1025,1003,1004)) { m_confirmed = true; Close(); if (m_type == "video" && !URIUtils::IsLiveTV(share.strPath) && !share.strPath.Left(6).Equals("rss://")) { CGUIWindowVideoBase::OnAssignContent(share.strPath, 0, m_info, m_settings); } } // and remove the share again if (shares) shares->erase(--shares->end()); }
void CGUIDialogMediaSource::OnOK() { // verify the path by doing a GetDirectory. CFileItemList items; CMediaSource share; share.FromNameAndPaths(m_type, m_name, GetPaths()); // hack: Need to temporarily add the share, then get path, then remove share VECSOURCES *shares = g_settings.GetSourcesFromType(m_type); if (shares) shares->push_back(share); if (share.strPath.Left(9).Equals("plugin://") || CDirectory::GetDirectory(share.strPath, items, "", false, true) || CGUIDialogYesNo::ShowAndGetInput(1001,1025,1003,1004)) { if (share.strPath.Left(9).Equals("plugin://")) { CStdString strPath=share.strPath; strPath.Replace("plugin://","special://home/system/plugins/"); CFileItem item(strPath,true); item.SetCachedProgramThumb(); if (!item.HasThumbnail()) item.SetUserProgramThumb(); if (!item.HasThumbnail()) { item.SetPath(URIUtils::AddFileToFolder(strPath,"default.py")); item.m_bIsFolder = false; item.SetCachedProgramThumb(); if (!item.HasThumbnail()) item.SetUserProgramThumb(); } if (item.HasThumbnail() && m_paths->Size()) { CFileItem item2(share.strPath,true); XFILE::CFile::Cache(item.GetThumbnailImage(),item2.GetCachedProgramThumb()); m_paths->Get(0)->SetThumbnailImage(item2.GetCachedProgramThumb()); } } m_confirmed = true; Close(); } // Special handling of multipath:// shares. // * GetScraperForPath takes the first path of the multipath:// element to fetch needed scraper and scan settings. // * SetScraperForPath loops through all elements and adds the appropriate settings for each path. if (URIUtils::IsMultiPath(share.strPath)) { CVideoDatabase database; database.Open(); database.GetScraperForPath(share.strPath, m_info, m_settings); database.SetScraperForPath(share.strPath, m_info, m_settings); database.Close(); } // and remove the share again if (shares) shares->erase(--shares->end()); }
void CBoxeeBrowseMenuDirectory::CreateSourcesButtons(const VECSOURCES& Sources, CFileItemList& itemsList) { // NOTE: currently handling only "video" sources for (VECSOURCES::const_iterator it = Sources.begin(); it != Sources.end(); it++) { CFileItemPtr sourceItem(new CFileItem()); sourceItem->SetLabel(it->strName); sourceItem->m_strPath = "boxeeui://movies/?category=local&source="; sourceItem->m_strPath += it->strPath; sourceItem->SetProperty("isClickable",true); itemsList.Add(sourceItem); } }
void CGUIPassword::LockSources(bool lock) { // lock or unlock all sources (those with locks) const char* strType[] = {"programs", "music", "video", "pictures", "files", "games"}; for (unsigned int i = 0; i < sizeof(strType) / sizeof(*strType); ++i) { VECSOURCES *shares = CMediaSourceSettings::GetInstance().GetSources(strType[i]); for (IVECSOURCES it=shares->begin();it != shares->end();++it) if (it->m_iLockMode != LOCK_MODE_EVERYONE) it->m_iHasLock = lock ? 2 : 1; } CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_UPDATE_SOURCES); CServiceBroker::GetGUI()->GetWindowManager().SendThreadMessage(msg); }
void CGUIPassword::LockSources(bool lock) { // lock or unlock all sources (those with locks) const char* strType[5] = {"programs","music","video","pictures","files"}; for (int i=0;i<5;++i) { VECSOURCES *shares = CMediaSourceSettings::Get().GetSources(strType[i]); for (IVECSOURCES it=shares->begin();it != shares->end();++it) if (it->m_iLockMode != LOCK_MODE_EVERYONE) it->m_iHasLock = lock ? 2 : 1; } CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_UPDATE_SOURCES); g_windowManager.SendThreadMessage(msg); }
void CWin32StorageProvider::Initialize() { // check for a DVD drive VECSOURCES vShare; CWIN32Util::GetDrivesByType(vShare, DVD_DRIVES); if(!vShare.empty()) g_mediaManager.SetHasOpticalDrive(true); // Can be removed once the StorageHandler supports optical media VECSOURCES::const_iterator it; for(it=vShare.begin();it!=vShare.end();++it) if(g_mediaManager.GetDriveStatus(it->strPath) == DRIVE_CLOSED_MEDIA_PRESENT) CJobManager::GetInstance().AddJob(new CDetectDisc(it->strPath, false), NULL); // remove end }
bool CGUIControlButtonSetting::GetPath(CSettingPath *pathSetting) { if (pathSetting == NULL) return false; CStdString path = pathSetting->GetValue(); VECSOURCES shares; const std::vector<std::string>& sources = pathSetting->GetSources(); for (std::vector<std::string>::const_iterator source = sources.begin(); source != sources.end(); ++source) { VECSOURCES *sources = CMediaSourceSettings::Get().GetSources(*source); if (sources != NULL) shares.insert(shares.end(), sources->begin(), sources->end()); } g_mediaManager.GetNetworkLocations(shares); g_mediaManager.GetLocalDrives(shares); if (!CGUIDialogFileBrowser::ShowAndGetDirectory(shares, g_localizeStrings.Get(pathSetting->GetHeading()), path, pathSetting->Writable())) return false; return pathSetting->SetValue(path); }
void CGUIViewState::AddLiveTVSources() { VECSOURCES *sources = CMediaSourceSettings::GetInstance().GetSources("video"); for (IVECSOURCES it = sources->begin(); it != sources->end(); it++) { if (URIUtils::IsLiveTV((*it).strPath)) { CMediaSource source; source.strPath = (*it).strPath; source.strName = (*it).strName; source.vecPaths = (*it).vecPaths; source.m_strThumbnailImage = ""; source.FromNameAndPaths("video", source.strName, source.vecPaths); m_sources.push_back(source); } } }
void CGUIViewState::AddLiveTVSources() { VECSOURCES *sources = g_settings.GetSourcesFromType("video"); for (IVECSOURCES it = sources->begin(); it != sources->end(); it++) { if (URIUtils::IsLiveTV((*it).strPath)) { CMediaSource source; source.strPath = (*it).strPath; source.strName = (*it).strName; source.vecPaths = (*it).vecPaths; source.m_strThumbnailImage = ""; source.m_iDriveType = CMediaSource::SOURCE_TYPE_REMOTE; m_sources.push_back(source); } } }
void CGUIPassword::RemoveSourceLocks() { // remove lock from all sources const char* strType[5] = {"programs","music","video","pictures","files"}; for (int i=0;i<5;++i) { VECSOURCES *shares = CMediaSourceSettings::Get().GetSources(strType[i]); for (IVECSOURCES it=shares->begin();it != shares->end();++it) if (it->m_iLockMode != LOCK_MODE_EVERYONE) // remove old info { it->m_iHasLock = 0; it->m_iLockMode = LOCK_MODE_EVERYONE; CMediaSourceSettings::Get().UpdateSource(strType[i], it->strName, "lockmode", "0"); // removes locks from xml } } CMediaSourceSettings::Get().Save(); CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0, GUI_MSG_UPDATE_SOURCES); g_windowManager.SendThreadMessage(msg); }
void CWin32StorageProvider::Initialize() { // check for a DVD drive VECSOURCES vShare; GetDrivesByType(vShare, DVD_DRIVES); if(!vShare.empty()) g_mediaManager.SetHasOpticalDrive(true); else CLog::Log(LOGDEBUG, "%s: No optical drive found.", __FUNCTION__); #ifdef HAS_DVD_DRIVE // Can be removed once the StorageHandler supports optical media VECSOURCES::const_iterator it; for(it=vShare.begin();it!=vShare.end();++it) if(g_mediaManager.GetDriveStatus(it->strPath) == DRIVE_CLOSED_MEDIA_PRESENT) CJobManager::GetInstance().AddJob(new CDetectDisc(it->strPath, false), NULL); // remove end #endif }
bool CGUIPassword::LockSource(const std::string& strType, const std::string& strName, bool bState) { VECSOURCES* pShares = CMediaSourceSettings::Get().GetSources(strType); bool bResult = false; for (IVECSOURCES it=pShares->begin();it != pShares->end();++it) { if (it->strName == strName) { if (it->m_iHasLock > 0) { it->m_iHasLock = bState?2:1; bResult = true; } break; } } CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_UPDATE_SOURCES); g_windowManager.SendThreadMessage(msg); return bResult; }
bool CMediaSourceSettings::DeleteSource(const std::string &strType, const std::string &strName, const std::string &strPath, bool virtualSource /* = false */) { VECSOURCES *pShares = GetSources(strType); if (pShares == NULL) return false; bool found = false; for (IVECSOURCES it = pShares->begin(); it != pShares->end(); it++) { if (it->strName == strName && it->strPath == strPath) { CLog::Log(LOGDEBUG, "CMediaSourceSettings: found share, removing!"); pShares->erase(it); found = true; break; } } if (virtualSource) return found; return Save(); }
int CHTTPVfsHandler::HandleHTTPRequest(const HTTPRequest &request) { if (request.url.size() > 5) { m_path = request.url.substr(5); /* In old version of libmicrohttpd the path was decoded, this was wrong. * This was fix in version 0.9.35.0 : https://gnunet.org/bugs/view.php?id=3371 * The path must be decoded in XBMC */ #if MHD_VERSION >= 0x00093500 m_path = CURL::Decode(m_path); #endif if (XFILE::CFile::Exists(m_path)) { bool accessible = false; if (m_path.substr(0, 8) == "image://") accessible = true; else { string sourceTypes[] = { "video", "music", "pictures" }; unsigned int size = sizeof(sourceTypes) / sizeof(string); string realPath = URIUtils::GetRealPath(m_path); // for rar:// and zip:// paths we need to extract the path to the archive // instead of using the VFS path while (URIUtils::IsInArchive(realPath)) realPath = CURL(realPath).GetHostName(); VECSOURCES *sources = NULL; for (unsigned int index = 0; index < size && !accessible; index++) { sources = CMediaSourceSettings::Get().GetSources(sourceTypes[index]); if (sources == NULL) continue; for (VECSOURCES::const_iterator source = sources->begin(); source != sources->end() && !accessible; source++) { // don't allow access to locked / disabled sharing sources if (source->m_iHasLock == 2 || !source->m_allowSharing) continue; for (vector<CStdString>::const_iterator path = source->vecPaths.begin(); path != source->vecPaths.end(); path++) { string realSourcePath = URIUtils::GetRealPath(*path); if (URIUtils::IsInPath(realPath, realSourcePath)) { accessible = true; break; } } } } } if (accessible) { m_responseCode = MHD_HTTP_OK; m_responseType = HTTPFileDownload; } // the file exists but not in one of the defined sources so we deny access to it else { m_responseCode = MHD_HTTP_UNAUTHORIZED; m_responseType = HTTPError; } } else { m_responseCode = MHD_HTTP_NOT_FOUND; m_responseType = HTTPError; } } else { m_responseCode = MHD_HTTP_BAD_REQUEST; m_responseType = HTTPError; } return MHD_YES; }
CHTTPVfsHandler::CHTTPVfsHandler(const HTTPRequest &request) : CHTTPFileHandler(request) { std::string file; int responseStatus = MHD_HTTP_BAD_REQUEST; if (m_request.pathUrl.size() > 5) { file = m_request.pathUrl.substr(5); if (XFILE::CFile::Exists(file)) { bool accessible = false; if (file.substr(0, 8) == "image://") accessible = true; else { std::string sourceTypes[] = { "video", "music", "pictures" }; unsigned int size = sizeof(sourceTypes) / sizeof(std::string); std::string realPath = URIUtils::GetRealPath(file); // for rar:// and zip:// paths we need to extract the path to the archive instead of using the VFS path while (URIUtils::IsInArchive(realPath)) realPath = CURL(realPath).GetHostName(); VECSOURCES *sources = NULL; for (unsigned int index = 0; index < size && !accessible; index++) { sources = CMediaSourceSettings::GetInstance().GetSources(sourceTypes[index]); if (sources == NULL) continue; for (VECSOURCES::const_iterator source = sources->begin(); source != sources->end() && !accessible; ++source) { // don't allow access to locked / disabled sharing sources if (source->m_iHasLock == 2 || !source->m_allowSharing) continue; for (std::vector<std::string>::const_iterator path = source->vecPaths.begin(); path != source->vecPaths.end(); ++path) { std::string realSourcePath = URIUtils::GetRealPath(*path); if (URIUtils::PathHasParent(realPath, realSourcePath, true)) { accessible = true; break; } } } } } if (accessible) responseStatus = MHD_HTTP_OK; // the file exists but not in one of the defined sources so we deny access to it else responseStatus = MHD_HTTP_UNAUTHORIZED; } else responseStatus = MHD_HTTP_NOT_FOUND; } // set the file and the HTTP response status SetFile(file, responseStatus); }
void CFileScanner::Process() { #ifdef _WIN32 ::SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL); #endif InitSourcesOnStart(); time_t now; int iMillisecondsToSleep = BXConfiguration::GetInstance().GetIntParam("Boxee.FileScanner.Scan.Interval", 180000); // let everything initialize first before we start the first scan. this is to prevent a cpu-boost on startup int iDelayStartInMS = BXConfiguration::GetInstance().GetIntParam("Boxee.FileScanner.Delay.Start", 60000); CLog::Log(LOGDEBUG,"CFileScanner::Process - wait for %d ms before start (fs)",iDelayStartInMS); InterruptibleSleep(iDelayStartInMS);; while (!m_bStop) { // Clear the set of private paths m_PrivatePaths.clear(); time(&now); if (m_bExtendedLog) CLog::Log(LOGDEBUG,"CFileScanner::Process, scan round started (filescanner)"); CheckPause(); CLog::Log(LOGDEBUG,"CFileScanner::Process - going to scan VIDEO shares. [m_bPaused=%d][m_bStop=%d] (fs)",m_bPaused,m_bStop); VECSOURCES video = *g_settings.GetSourcesFromType("video"); ScanShares(&video, "video"); CleanMediaFolders("videoFolder", video); CLog::Log(LOGDEBUG,"CFileScanner::Process - going to scan MUSIC shares. [m_bPaused=%d][m_bStop=%d] (fs)",m_bPaused,m_bStop); VECSOURCES audio = *g_settings.GetSourcesFromType("music"); ScanShares(&audio, "music"); CleanMediaFolders("musicFolder", audio); std::set<std::pair<CStdString, CStdString> > setUserPaths; { CSingleLock lock(m_lock); setUserPaths = m_setUserPaths; } int counter = 0; CLog::Log(LOGDEBUG,"CFileScanner::Process - going to scan USER paths [UserPathsSize=%zu]. [m_bPaused=%d][m_bStop=%d] (fs)",setUserPaths.size(),m_bPaused,m_bStop); std::set<std::pair<CStdString, CStdString> >::iterator it = setUserPaths.begin(); while (it != setUserPaths.end() && !m_bStop) { counter++; CStdString strPath = (*it).first; CStdString strType = (*it).second; CLog::Log(LOGDEBUG,"CFileScanner::Process - [%d/%zu] - handle [path=%s][type=%s]. [m_bPaused=%d][m_bStop=%d] (fs)",counter,setUserPaths.size(),strPath.c_str(),strType.c_str(),m_bPaused,m_bStop); // scan path can be share or directory VECSOURCES shares = *g_settings.GetSourcesFromType(strType); VECSOURCES::iterator shareIt = shares.begin(); CMediaSource* pShare = NULL; while (shareIt != shares.end()) { if (_P(shareIt->strPath) == strPath) { pShare = &(*shareIt); break; } shareIt++; } if (pShare) { ScanShare(pShare, strType); } else { ScanMediaFolder(strPath, strType, strPath); UpdateScanLabel(g_localizeStrings.Get(53160)); } // Notify using a message that the path has been scanned CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_FILE_SCANNER_UPDATE); msg.SetStringParam(strPath); g_windowManager.SendThreadMessage(msg); it++; } { CSingleLock lock(m_lock); m_setUserPaths.clear(); } time_t then = time(NULL); if (m_bExtendedLog) CLog::Log(LOGDEBUG,"CFileScanner::Process, scan round finished, time = %lu (filescanner)", then - now); do { CLog::Log(LOGDEBUG,"CFileScanner::Process - BEFORE sleep for [%dms]. [m_bPaused=%d][m_bStop=%d] (fs)",iMillisecondsToSleep,m_bPaused,m_bStop); InterruptibleSleep(iMillisecondsToSleep); CLog::Log(LOGDEBUG,"CFileScanner::Process - AFTER sleep for [%dms]. [m_bPaused=%d][m_bStop=%d] (fs)",iMillisecondsToSleep,m_bPaused,m_bStop); } while (g_application.IsPlayingVideo() && !m_bStop); } // while CLog::Log(LOGDEBUG,"Boxee File Scanner, Exiting process loop (filescanner)"); }
bool CGUIDialogFileBrowser::ShowAndGetSource(std::string &path, bool allowNetworkShares, VECSOURCES* additionalShare /* = NULL */, const std::string& strType /* = "" */) { // Technique is // 1. Show Filebrowser with currently defined local, and optionally the network locations. // 2. Have the "Add Network Location" option in addition. // 3a. If the "Add Network Location" is pressed, then: // a) Fire up the network location dialog to grab the new location // b) Check the location by doing a GetDirectory() - if it fails, prompt the user // to allow them to add currently disconnected network shares. // c) Save this location to our xml file (network.xml) // d) Return to 1. // 3b. If the "Add Source" is pressed, then: // a) Fire up the media source dialog to add the new location // 4. Optionally allow user to browse the local and network locations for their share. // 5. On OK, return. // Create a new filebrowser window CGUIDialogFileBrowser *browser = new CGUIDialogFileBrowser(); if (!browser) return false; // Add it to our window manager CServiceBroker::GetGUI()->GetWindowManager().AddUniqueInstance(browser); VECSOURCES shares; if (!strType.empty()) { if (additionalShare) shares = *additionalShare; browser->m_addSourceType = strType; } else { browser->SetHeading(g_localizeStrings.Get(1023)); g_mediaManager.GetLocalDrives(shares); // Now the additional share if appropriate if (additionalShare) { shares.insert(shares.end(),additionalShare->begin(),additionalShare->end()); } // Now add the network shares... if (allowNetworkShares) { g_mediaManager.GetNetworkLocations(shares); } } browser->SetSources(shares); browser->m_rootDir.SetMask("/"); browser->m_rootDir.AllowNonLocalSources(false); // don't allow plug n play shares browser->m_browsingForFolders = 1; browser->m_addNetworkShareEnabled = allowNetworkShares; browser->m_selectedPath = ""; browser->Open(); bool confirmed = browser->IsConfirmed(); if (confirmed) path = browser->m_selectedPath; CServiceBroker::GetGUI()->GetWindowManager().Remove(browser->GetID()); delete browser; return confirmed; }
void CGUIDialogSmartPlaylistRule::OnBrowse() { CFileItemList items; CMusicDatabase database; database.Open(); CVideoDatabase videodatabase; videodatabase.Open(); VIDEODB_CONTENT_TYPE type = VIDEODB_CONTENT_MOVIES; if (m_type.Equals("tvshows")) type = VIDEODB_CONTENT_TVSHOWS; else if (m_type.Equals("musicvideos")) type = VIDEODB_CONTENT_MUSICVIDEOS; else if (m_type.Equals("episodes")) type = VIDEODB_CONTENT_EPISODES; int iLabel = 0; if (m_rule.m_field == FieldGenre) { if (m_type.Equals("tvshows") || m_type.Equals("episodes") || m_type.Equals("movies")) videodatabase.GetGenresNav("videodb://2/1/",items,type); else if (m_type.Equals("songs") || m_type.Equals("albums") || m_type.Equals("artists") || m_type.Equals("mixed")) database.GetGenresNav("musicdb://1/",items); if (m_type.Equals("musicvideos") || m_type.Equals("mixed")) { CFileItemList items2; videodatabase.GetGenresNav("videodb://3/1/",items2,VIDEODB_CONTENT_MUSICVIDEOS); items.Append(items2); } iLabel = 515; } else if (m_rule.m_field == FieldCountry) { videodatabase.GetCountriesNav("videodb://2/1/",items,type); iLabel = 574; } else if (m_rule.m_field == FieldArtist || m_rule.m_field == FieldAlbumArtist) { if (m_type.Equals("songs") || m_type.Equals("mixed") || m_type.Equals("albums") || m_type.Equals("artists")) database.GetArtistsNav("musicdb://2/", items, m_rule.m_field == FieldAlbumArtist, -1); if (m_type.Equals("musicvideos") || m_type.Equals("mixed")) { CFileItemList items2; videodatabase.GetMusicVideoArtistsByName("",items2); items.Append(items2); } iLabel = 557; } else if (m_rule.m_field == FieldAlbum) { if (m_type.Equals("songs") || m_type.Equals("mixed") || m_type.Equals("albums")) database.GetAlbumsNav("musicdb://3/", items); if (m_type.Equals("musicvideos") || m_type.Equals("mixed")) { CFileItemList items2; videodatabase.GetMusicVideoAlbumsByName("",items2); items.Append(items2); } iLabel = 558; } else if (m_rule.m_field == FieldActor) { videodatabase.GetActorsNav("",items,type); iLabel = 20337; } else if (m_rule.m_field == FieldYear) { if (m_type.Equals("songs") || m_type.Equals("mixed") || m_type.Equals("albums")) database.GetYearsNav("musicdb://9/", items); if (!m_type.Equals("songs") && !m_type.Equals("albums")) { CFileItemList items2; videodatabase.GetYearsNav("", items2, type); items.Append(items2); } iLabel = 562; } else if (m_rule.m_field == FieldDirector) { videodatabase.GetDirectorsNav("",items,type); iLabel = 20339; } else if (m_rule.m_field == FieldStudio) { videodatabase.GetStudiosNav("",items,type); iLabel = 572; } else if (m_rule.m_field == FieldWriter) { videodatabase.GetWritersNav("",items,type); iLabel = 20417; } else if (m_rule.m_field == FieldTvShowTitle) { videodatabase.GetTvShowsNav("videodb://2/2/",items); iLabel = 20343; } else if (m_rule.m_field == FieldPlaylist) { // use filebrowser to grab another smart playlist // Note: This can cause infinite loops (playlist that refers to the same playlist) but I don't // think there's any decent way to deal with this, as the infinite loop may be an arbitrary // number of playlists deep, eg playlist1 -> playlist2 -> playlist3 ... -> playlistn -> playlist1 CStdString path = "special://videoplaylists/"; if (m_type.Equals("songs") || m_type.Equals("albums")) path = "special://musicplaylists/"; XFILE::CDirectory::GetDirectory(path, items, ".xsp", XFILE::DIR_FLAG_NO_FILE_DIRS); for (int i = 0; i < items.Size(); i++) { CFileItemPtr item = items[i]; CSmartPlaylist playlist; if (playlist.OpenAndReadName(item->GetPath())) item->SetLabel(playlist.GetName()); } iLabel = 559; } else if (m_rule.m_field == FieldPath) { VECSOURCES sources; if (m_type == "songs" || m_type == "mixed") sources = *g_settings.GetSourcesFromType("music"); if (m_type != "songs") { VECSOURCES sources2 = *g_settings.GetSourcesFromType("video"); sources.insert(sources.end(),sources2.begin(),sources2.end()); } g_mediaManager.GetLocalDrives(sources); CStdString path = m_rule.GetLocalizedParameter(m_type); CGUIDialogFileBrowser::ShowAndGetDirectory(sources, g_localizeStrings.Get(657), path, false); if (m_rule.m_parameter.size() > 0) m_rule.m_parameter.clear(); if (!path.empty()) m_rule.m_parameter.push_back(path); UpdateButtons(); return; } else if (m_rule.m_field == FieldSet) { videodatabase.GetSetsNav("videodb://1/7/", items, VIDEODB_CONTENT_MOVIES); iLabel = 20434; } else if (m_rule.m_field == FieldTag) { if (m_type == "movies") videodatabase.GetTagsNav("videodb://1/9/", items, VIDEODB_CONTENT_MOVIES); else return; iLabel = 20459; } else { // TODO: Add browseability in here. assert(false); } // sort the items items.Sort(SORT_METHOD_LABEL, SortOrderAscending); CGUIDialogSelect* pDialog = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT); pDialog->Reset(); pDialog->SetItems(&items); CStdString strHeading; strHeading.Format(g_localizeStrings.Get(13401),g_localizeStrings.Get(iLabel)); pDialog->SetHeading(strHeading); pDialog->SetMultiSelection(true); if (!m_rule.m_parameter.empty()) pDialog->SetSelected(m_rule.m_parameter); pDialog->DoModal(); if (pDialog->IsConfirmed()) { const CFileItemList &items = pDialog->GetSelectedItems(); m_rule.m_parameter.clear(); for (int index = 0; index < items.Size(); index++) m_rule.m_parameter.push_back(items[index]->GetLabel()); UpdateButtons(); } pDialog->Reset(); }
void CGUIDialogSmartPlaylistRule::OnBrowse() { CFileItemList items; CMusicDatabase database; database.Open(); CVideoDatabase videodatabase; videodatabase.Open(); std::string basePath; if (CSmartPlaylist::IsMusicType(m_type)) basePath = "musicdb://"; else basePath = "videodb://"; VIDEODB_CONTENT_TYPE type = VIDEODB_CONTENT_MOVIES; if (m_type == "movies") basePath += "movies/"; else if (m_type == "tvshows") { type = VIDEODB_CONTENT_TVSHOWS; basePath += "tvshows/"; } else if (m_type == "musicvideos") { type = VIDEODB_CONTENT_MUSICVIDEOS; basePath += "musicvideos/"; } else if (m_type == "episodes") { if (m_rule.m_field == FieldGenre || m_rule.m_field == FieldYear || m_rule.m_field == FieldStudio) type = VIDEODB_CONTENT_TVSHOWS; else type = VIDEODB_CONTENT_EPISODES; basePath += "tvshows/"; } int iLabel = 0; if (m_rule.m_field == FieldGenre) { if (m_type == "tvshows" || m_type == "episodes" || m_type == "movies") videodatabase.GetGenresNav(basePath + "genres/", items, type); else if (m_type == "songs" || m_type == "albums" || m_type == "artists" || m_type == "mixed") database.GetGenresNav("musicdb://genres/",items); if (m_type == "musicvideos" || m_type == "mixed") { CFileItemList items2; videodatabase.GetGenresNav("videodb://musicvideos/genres/",items2,VIDEODB_CONTENT_MUSICVIDEOS); items.Append(items2); } iLabel = 515; } else if (m_rule.m_field == FieldCountry) { videodatabase.GetCountriesNav(basePath, items, type); iLabel = 574; } else if (m_rule.m_field == FieldArtist || m_rule.m_field == FieldAlbumArtist) { if (CSmartPlaylist::IsMusicType(m_type)) database.GetArtistsNav("musicdb://artists/", items, m_rule.m_field == FieldAlbumArtist, -1); if (m_type == "musicvideos" || m_type == "mixed") { CFileItemList items2; videodatabase.GetMusicVideoArtistsByName("", items2); items.Append(items2); } iLabel = 557; } else if (m_rule.m_field == FieldAlbum) { if (CSmartPlaylist::IsMusicType(m_type)) database.GetAlbumsNav("musicdb://albums/", items); if (m_type == "musicvideos" || m_type == "mixed") { CFileItemList items2; videodatabase.GetMusicVideoAlbumsByName("", items2); items.Append(items2); } iLabel = 558; } else if (m_rule.m_field == FieldActor) { videodatabase.GetActorsNav(basePath + "actors/",items,type); iLabel = 20337; } else if (m_rule.m_field == FieldYear) { if (CSmartPlaylist::IsMusicType(m_type)) database.GetYearsNav("musicdb://years/", items); if (CSmartPlaylist::IsVideoType(m_type)) { CFileItemList items2; videodatabase.GetYearsNav(basePath + "years/", items2, type); items.Append(items2); } iLabel = 562; } else if (m_rule.m_field == FieldDirector) { videodatabase.GetDirectorsNav(basePath + "directors/", items, type); iLabel = 20339; } else if (m_rule.m_field == FieldStudio) { videodatabase.GetStudiosNav(basePath + "studios/", items, type); iLabel = 572; } else if (m_rule.m_field == FieldWriter) { videodatabase.GetWritersNav(basePath, items, type); iLabel = 20417; } else if (m_rule.m_field == FieldTvShowTitle || (m_type == "tvshows" && m_rule.m_field == FieldTitle)) { videodatabase.GetTvShowsNav(basePath + "titles/", items); iLabel = 20343; } else if (m_rule.m_field == FieldTitle) { if (m_type == "songs" || m_type == "mixed") { database.GetSongsNav("musicdb://songs/", items, -1, -1, -1); iLabel = 134; } if (m_type == "movies") { videodatabase.GetMoviesNav(basePath + "titles/", items); iLabel = 20342; } if (m_type == "episodes") { videodatabase.GetEpisodesNav(basePath + "titles/-1/-1/", items); // we need to replace the db label (<season>x<episode> <title>) with the title only CLabelFormatter format("%T", ""); for (int i = 0; i < items.Size(); i++) format.FormatLabel(items[i].get()); iLabel = 20360; } if (m_type == "musicvideos" || m_type == "mixed") { videodatabase.GetMusicVideosNav(basePath + "titles/", items); iLabel = 20389; } } else if (m_rule.m_field == FieldPlaylist || m_rule.m_field == FieldVirtualFolder) { // use filebrowser to grab another smart playlist // Note: This can cause infinite loops (playlist that refers to the same playlist) but I don't // think there's any decent way to deal with this, as the infinite loop may be an arbitrary // number of playlists deep, eg playlist1 -> playlist2 -> playlist3 ... -> playlistn -> playlist1 if (CSmartPlaylist::IsVideoType(m_type)) XFILE::CDirectory::GetDirectory("special://videoplaylists/", items, ".xsp", XFILE::DIR_FLAG_NO_FILE_DIRS); if (CSmartPlaylist::IsMusicType(m_type)) { CFileItemList items2; XFILE::CDirectory::GetDirectory("special://musicplaylists/", items2, ".xsp", XFILE::DIR_FLAG_NO_FILE_DIRS); items.Append(items2); } for (int i = 0; i < items.Size(); i++) { CFileItemPtr item = items[i]; CSmartPlaylist playlist; // don't list unloadable smartplaylists or any referencable smartplaylists // which do not match the type of the current smartplaylist if (!playlist.Load(item->GetPath()) || (m_rule.m_field == FieldPlaylist && (!CSmartPlaylist::CheckTypeCompatibility(m_type, playlist.GetType()) || (!playlist.GetGroup().empty() || playlist.IsGroupMixed())))) { items.Remove(i); i -= 1; continue; } if (!playlist.GetName().empty()) item->SetLabel(playlist.GetName()); } iLabel = 559; } else if (m_rule.m_field == FieldPath) { VECSOURCES sources; if (m_type == "songs" || m_type == "mixed") sources = *CMediaSourceSettings::GetInstance().GetSources("music"); if (CSmartPlaylist::IsVideoType(m_type)) { VECSOURCES sources2 = *CMediaSourceSettings::GetInstance().GetSources("video"); sources.insert(sources.end(),sources2.begin(),sources2.end()); } g_mediaManager.GetLocalDrives(sources); std::string path = m_rule.GetParameter(); CGUIDialogFileBrowser::ShowAndGetDirectory(sources, g_localizeStrings.Get(657), path, false); if (m_rule.m_parameter.size() > 0) m_rule.m_parameter.clear(); if (!path.empty()) m_rule.m_parameter.push_back(path); UpdateButtons(); return; } else if (m_rule.m_field == FieldSet) { videodatabase.GetSetsNav("videodb://movies/sets/", items, VIDEODB_CONTENT_MOVIES); iLabel = 20434; } else if (m_rule.m_field == FieldTag) { VIDEODB_CONTENT_TYPE type = VIDEODB_CONTENT_MOVIES; if (m_type == "tvshows" || m_type == "episodes") type = VIDEODB_CONTENT_TVSHOWS; else if (m_type == "musicvideos") type = VIDEODB_CONTENT_MUSICVIDEOS; else if (m_type != "movies") return; videodatabase.GetTagsNav(basePath + "tags/", items, type); iLabel = 20459; } else { // TODO: Add browseability in here. assert(false); } // sort the items items.Sort(SortByLabel, SortOrderAscending, CSettings::GetInstance().GetBool(CSettings::SETTING_FILELISTS_IGNORETHEWHENSORTING) ? SortAttributeIgnoreArticle : SortAttributeNone); CGUIDialogSelect* pDialog = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT); pDialog->Reset(); pDialog->SetItems(&items); std::string strHeading = StringUtils::Format(g_localizeStrings.Get(13401).c_str(), g_localizeStrings.Get(iLabel).c_str()); pDialog->SetHeading(CVariant{std::move(strHeading)}); pDialog->SetMultiSelection(m_rule.m_field != FieldPlaylist && m_rule.m_field != FieldVirtualFolder); if (!m_rule.m_parameter.empty()) pDialog->SetSelected(m_rule.m_parameter); pDialog->Open(); if (pDialog->IsConfirmed()) { m_rule.m_parameter.clear(); for (int i : pDialog->GetSelectedItems()) m_rule.m_parameter.push_back(items.Get(i)->GetLabel()); UpdateButtons(); } pDialog->Reset(); }
static void AddHostsFromVecSource(const VECSOURCES& sources, vector<string>& hosts) { for (VECSOURCES::const_iterator it = sources.begin(); it != sources.end(); it++) AddHostsFromMediaSource(*it, hosts); }
void CGUIDialogSmartPlaylistRule::OnBrowse() { CFileItemList items; CMusicDatabase database; database.Open(); CVideoDatabase videodatabase; videodatabase.Open(); VIDEODB_CONTENT_TYPE type = VIDEODB_CONTENT_MOVIES; if (m_type.Equals("tvshows")) type = VIDEODB_CONTENT_TVSHOWS; else if (m_type.Equals("musicvideos")) type = VIDEODB_CONTENT_MUSICVIDEOS; else if (m_type.Equals("episodes")) type = VIDEODB_CONTENT_EPISODES; int iLabel = 0; if (m_rule.m_field == CSmartPlaylistRule::FIELD_GENRE) { if (m_type.Equals("tvshows") || m_type.Equals("episodes") || m_type.Equals("movies")) videodatabase.GetGenresNav("videodb://2/1/",items,type); else if (m_type.Equals("songs") || m_type.Equals("albums") || m_type.Equals("mixed")) database.GetGenresNav("musicdb://4/",items); if (m_type.Equals("musicvideos") || m_type.Equals("mixed")) { CFileItemList items2; videodatabase.GetGenresNav("videodb://3/1/",items2,VIDEODB_CONTENT_MUSICVIDEOS); items.Append(items2); } iLabel = 515; } else if (m_rule.m_field == CSmartPlaylistRule::FIELD_COUNTRY) { videodatabase.GetCountriesNav("videodb://2/1/",items,type); iLabel = 574; } else if (m_rule.m_field == CSmartPlaylistRule::FIELD_ARTIST || m_rule.m_field == CSmartPlaylistRule::FIELD_ALBUMARTIST) { if (m_type.Equals("songs") || m_type.Equals("mixed") || m_type.Equals("albums")) database.GetArtistsNav("musicdb://5/",items,-1,m_rule.m_field == CSmartPlaylistRule::FIELD_ALBUMARTIST); if (m_type.Equals("musicvideos") || m_type.Equals("mixed")) { CFileItemList items2; videodatabase.GetMusicVideoArtistsByName("",items2); items.Append(items2); } iLabel = 557; } else if (m_rule.m_field == CSmartPlaylistRule::FIELD_ALBUM) { if (m_type.Equals("songs") || m_type.Equals("mixed") || m_type.Equals("albums")) database.GetAlbumsNav("musicdb://6/",items,-1,-1,-1,-1); if (m_type.Equals("musicvideos") || m_type.Equals("mixed")) { CFileItemList items2; videodatabase.GetMusicVideoAlbumsByName("",items2); items.Append(items2); } iLabel = 558; } else if (m_rule.m_field == CSmartPlaylistRule::FIELD_ACTOR) { videodatabase.GetActorsNav("",items,type); iLabel = 20337; } else if (m_rule.m_field == CSmartPlaylistRule::FIELD_DIRECTOR) { videodatabase.GetDirectorsNav("",items,type); iLabel = 20339; } else if (m_rule.m_field == CSmartPlaylistRule::FIELD_STUDIO) { videodatabase.GetStudiosNav("",items,type); iLabel = 572; } else if (m_rule.m_field == CSmartPlaylistRule::FIELD_WRITER) { videodatabase.GetWritersNav("",items,type); iLabel = 20417; } else if (m_rule.m_field == CSmartPlaylistRule::FIELD_TVSHOWTITLE) { videodatabase.GetTvShowsNav("",items); iLabel = 20343; } else if (m_rule.m_field == CSmartPlaylistRule::FIELD_PLAYLIST) { // use filebrowser to grab another smart playlist // Note: This can cause infinite loops (playlist that refers to the same playlist) but I don't // think there's any decent way to deal with this, as the infinite loop may be an arbitrary // number of playlists deep, eg playlist1 -> playlist2 -> playlist3 ... -> playlistn -> playlist1 CStdString path = "special://videoplaylists/"; if (m_type.Equals("songs") || m_type.Equals("albums")) path = "special://musicplaylists/"; XFILE::CDirectory::GetDirectory(path, items, ".xsp",false,false,XFILE::DIR_CACHE_ONCE,true,true); iLabel = 559; } else if (m_rule.m_field == CSmartPlaylistRule::FIELD_PATH) { VECSOURCES sources; if (m_type == "songs" || m_type == "mixed") sources = *g_settings.GetSourcesFromType("music"); if (m_type != "songs") { VECSOURCES sources2 = *g_settings.GetSourcesFromType("video"); sources.insert(sources.end(),sources2.begin(),sources2.end()); } g_mediaManager.GetLocalDrives(sources); CGUIDialogFileBrowser::ShowAndGetDirectory(sources,g_localizeStrings.Get(657),m_rule.m_parameter,false); UpdateButtons(); return; } else { // TODO: Add browseability in here. assert(false); } // sort the items items.Sort(SORT_METHOD_LABEL, SORT_ORDER_ASC); CGUIDialogSelect* pDialog = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT); pDialog->Reset(); pDialog->SetItems(&items); CStdString strHeading; strHeading.Format(g_localizeStrings.Get(13401),g_localizeStrings.Get(iLabel)); pDialog->SetHeading(strHeading); pDialog->DoModal(); if (pDialog->GetSelectedLabel() > -1) { m_rule.m_parameter = pDialog->GetSelectedLabelText(); UpdateButtons(); } pDialog->Reset(); }
void CAndroidStorageProvider::GetRemovableDrives(VECSOURCES &removableDrives) { // Uses non-public API: be extra carefull bool inError = false; VECSOURCES droidDrives; CJNIStorageManager manager(CJNIContext::getSystemService("storage")); if (xbmc_jnienv()->ExceptionCheck()) { xbmc_jnienv()->ExceptionClear(); inError = true; } if (!inError) { CJNIStorageVolumes vols = manager.getVolumeList(); if (xbmc_jnienv()->ExceptionCheck()) { xbmc_jnienv()->ExceptionClear(); inError = true; } if (!inError) { for (auto vol : vols) { // CLog::Log(LOGDEBUG, "-- Volume: %s(%s) -- %s", vol.getPath().c_str(), vol.getUserLabel().c_str(), vol.getState().c_str()); bool removable = vol.isRemovable(); if (xbmc_jnienv()->ExceptionCheck()) { xbmc_jnienv()->ExceptionClear(); inError = true; break; } std::string state = vol.getState(); if (xbmc_jnienv()->ExceptionCheck()) { xbmc_jnienv()->ExceptionClear(); inError = true; break; } if (removable && state == CJNIEnvironment::MEDIA_MOUNTED) { CMediaSource share; share.strPath = vol.getPath(); if (xbmc_jnienv()->ExceptionCheck()) { xbmc_jnienv()->ExceptionClear(); inError = true; break; } share.strName = vol.getUserLabel(); if (xbmc_jnienv()->ExceptionCheck()) { xbmc_jnienv()->ExceptionClear(); inError = true; break; } StringUtils::Trim(share.strName); if (share.strName.empty() || share.strName == "?" || StringUtils::CompareNoCase(share.strName, "null") == 0) share.strName = URIUtils::GetFileName(share.strPath); share.m_ignore = true; droidDrives.push_back(share); } } } } if (!inError) removableDrives.insert(removableDrives.end(), droidDrives.begin(), droidDrives.end()); else { for (const auto& mountStr : GetRemovableDrivesLinux()) { // Reject unreadable if (XFILE::CDirectory::Exists(mountStr)) { CMediaSource share; share.strPath = unescape(mountStr); share.strName = URIUtils::GetFileName(mountStr); share.m_ignore = true; removableDrives.push_back(share); } } } }