bool CSMBDirectory::GetDirectory(const CURL& url, CFileItemList &items) { // We accept smb://[[[domain;]user[:password@]]server[/share[/path[/file]]]] /* samba isn't thread safe with old interface, always lock */ CSingleLock lock(smb); smb.Init(); //Separate roots for the authentication and the containing items to allow browsing to work correctly std::string strRoot = url.Get(); std::string strAuth; lock.Leave(); // OpenDir is locked int fd = OpenDir(url, strAuth); if (fd < 0) return false; URIUtils::AddSlashAtEnd(strRoot); URIUtils::AddSlashAtEnd(strAuth); std::string strFile; // need to keep the samba lock for as short as possible. // so we first cache all directory entries and then go over them again asking for stat // "stat" is locked each time. that way the lock is freed between stat requests vector<CachedDirEntry> vecEntries; struct smbc_dirent* dirEnt; lock.Enter(); while ((dirEnt = smbc_readdir(fd))) { CachedDirEntry aDir; aDir.type = dirEnt->smbc_type; aDir.name = dirEnt->name; vecEntries.push_back(aDir); } smbc_closedir(fd); lock.Leave(); for (size_t i=0; i<vecEntries.size(); i++) { CachedDirEntry aDir = vecEntries[i]; // We use UTF-8 internally, as does SMB strFile = aDir.name; if (!strFile.empty() && strFile != "." && strFile != ".." && strFile != "lost+found" && aDir.type != SMBC_PRINTER_SHARE && aDir.type != SMBC_IPC_SHARE) { int64_t iSize = 0; bool bIsDir = true; int64_t lTimeDate = 0; bool hidden = false; if(StringUtils::EndsWith(strFile, "$") && aDir.type == SMBC_FILE_SHARE ) continue; // only stat files that can give proper responses if ( aDir.type == SMBC_FILE || aDir.type == SMBC_DIR ) { // set this here to if the stat should fail bIsDir = (aDir.type == SMBC_DIR); struct stat info = {0}; if ((m_flags & DIR_FLAG_NO_FILE_INFO)==0 && g_advancedSettings.m_sambastatfiles) { // make sure we use the authenticated path wich contains any default username const std::string strFullName = strAuth + smb.URLEncode(strFile); lock.Enter(); if( smbc_stat(strFullName.c_str(), &info) == 0 ) { char value[20]; // We poll for extended attributes which symbolizes bits but split up into a string. Where 0x02 is hidden and 0x12 is hidden directory. // According to the libsmbclient.h it's supposed to return 0 if ok, or the length of the string. It seems always to return the length wich is 4 if (smbc_getxattr(strFullName.c_str(), "system.dos_attr.mode", value, sizeof(value)) > 0) { long longvalue = strtol(value, NULL, 16); if (longvalue & SMBC_DOS_MODE_HIDDEN) hidden = true; } else CLog::Log(LOGERROR, "Getting extended attributes for the share: '%s'\nunix_err:'%x' error: '%s'", CURL::GetRedacted(strFullName).c_str(), errno, strerror(errno)); bIsDir = S_ISDIR(info.st_mode); lTimeDate = info.st_mtime; if(lTimeDate == 0) // if modification date is missing, use create date lTimeDate = info.st_ctime; iSize = info.st_size; } else CLog::Log(LOGERROR, "%s - Failed to stat file %s", __FUNCTION__, CURL::GetRedacted(strFullName).c_str()); lock.Leave(); } } FILETIME fileTime, localTime; TimeTToFileTime(lTimeDate, &fileTime); FileTimeToLocalFileTime(&fileTime, &localTime); if (bIsDir) { CFileItemPtr pItem(new CFileItem(strFile)); std::string path(strRoot); // needed for network / workgroup browsing // skip if root if we are given a server if (aDir.type == SMBC_SERVER) { /* create url with same options, user, pass.. but no filename or host*/ CURL rooturl(strRoot); rooturl.SetFileName(""); rooturl.SetHostName(""); path = smb.URLEncode(rooturl); } path = URIUtils::AddFileToFolder(path,aDir.name); URIUtils::AddSlashAtEnd(path); pItem->SetPath(path); pItem->m_bIsFolder = true; pItem->m_dateTime=localTime; if (hidden) pItem->SetProperty("file:hidden", true); items.Add(pItem); } else { CFileItemPtr pItem(new CFileItem(strFile)); pItem->SetPath(strRoot + aDir.name); pItem->m_bIsFolder = false; pItem->m_dwSize = iSize; pItem->m_dateTime=localTime; if (hidden) pItem->SetProperty("file:hidden", true); items.Add(pItem); } } } return true; }
void PLAYLIST::CPlayListPlayer::OnApplicationMessage(KODI::MESSAGING::ThreadMessage* pMsg) { switch (pMsg->dwMessage) { case TMSG_PLAYLISTPLAYER_PLAY: if (pMsg->param1 != -1) Play(pMsg->param1, ""); else Play(); break; case TMSG_PLAYLISTPLAYER_PLAY_SONG_ID: if (pMsg->param1 != -1) { bool *result = (bool*)pMsg->lpVoid; *result = PlaySongId(pMsg->param1); } else Play(); break; case TMSG_PLAYLISTPLAYER_NEXT: PlayNext(); break; case TMSG_PLAYLISTPLAYER_PREV: PlayPrevious(); break; case TMSG_PLAYLISTPLAYER_ADD: if (pMsg->lpVoid) { CFileItemList *list = (CFileItemList *)pMsg->lpVoid; Add(pMsg->param1, (*list)); delete list; } break; case TMSG_PLAYLISTPLAYER_INSERT: if (pMsg->lpVoid) { CFileItemList *list = (CFileItemList *)pMsg->lpVoid; Insert(pMsg->param1, (*list), pMsg->param2); delete list; } break; case TMSG_PLAYLISTPLAYER_REMOVE: if (pMsg->param1 != -1) Remove(pMsg->param1, pMsg->param2); break; case TMSG_PLAYLISTPLAYER_CLEAR: ClearPlaylist(pMsg->param1); break; case TMSG_PLAYLISTPLAYER_SHUFFLE: SetShuffle(pMsg->param1, pMsg->param2 > 0); break; case TMSG_PLAYLISTPLAYER_REPEAT: SetRepeat(pMsg->param1, (PLAYLIST::REPEAT_STATE)pMsg->param2); break; case TMSG_PLAYLISTPLAYER_GET_ITEMS: if (pMsg->lpVoid) { PLAYLIST::CPlayList playlist = GetPlaylist(pMsg->param1); CFileItemList *list = static_cast<CFileItemList*>(pMsg->lpVoid); for (int i = 0; i < playlist.size(); i++) list->Add(std::make_shared<CFileItem>(*playlist[i])); } break; case TMSG_PLAYLISTPLAYER_SWAP: if (pMsg->lpVoid) { auto indexes = static_cast<std::vector<int>*>(pMsg->lpVoid); if (indexes->size() == 2) Swap(pMsg->param1, indexes->at(0), indexes->at(1)); delete indexes; } break; case TMSG_MEDIA_PLAY: { // first check if we were called from the PlayFile() function if (pMsg->lpVoid && pMsg->param2 == 0) { CFileItem *item = (CFileItem *)pMsg->lpVoid; g_application.PlayFile(*item, "", pMsg->param1 != 0); delete item; return; } // restore to previous window if needed if (g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW || g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO || g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION) g_windowManager.PreviousWindow(); g_application.ResetScreenSaver(); g_application.WakeUpScreenSaverAndDPMS(); //g_application.StopPlaying(); // play file if (pMsg->lpVoid) { CFileItemList *list = (CFileItemList *)pMsg->lpVoid; if (list->Size() > 0) { int playlist = PLAYLIST_MUSIC; for (int i = 0; i < list->Size(); i++) { if ((*list)[i]->IsVideo()) { playlist = PLAYLIST_VIDEO; break; } } ClearPlaylist(playlist); SetCurrentPlaylist(playlist); //For single item lists try PlayMedia. This covers some more cases where a playlist is not appropriate //It will fall through to PlayFile if (list->Size() == 1 && !(*list)[0]->IsPlayList()) g_application.PlayMedia(*((*list)[0]), pMsg->strParam, playlist); else { // Handle "shuffled" option if present if (list->HasProperty("shuffled") && list->GetProperty("shuffled").isBoolean()) SetShuffle(playlist, list->GetProperty("shuffled").asBoolean(), false); // Handle "repeat" option if present if (list->HasProperty("repeat") && list->GetProperty("repeat").isInteger()) SetRepeat(playlist, (PLAYLIST::REPEAT_STATE)list->GetProperty("repeat").asInteger(), false); Add(playlist, (*list)); Play(pMsg->param1, pMsg->strParam); } } delete list; } else if (pMsg->param1 == PLAYLIST_MUSIC || pMsg->param1 == PLAYLIST_VIDEO) { if (GetCurrentPlaylist() != pMsg->param1) SetCurrentPlaylist(pMsg->param1); CApplicationMessenger::GetInstance().SendMsg(TMSG_PLAYLISTPLAYER_PLAY, pMsg->param2); } } break; case TMSG_MEDIA_RESTART: g_application.Restart(true); break; case TMSG_MEDIA_STOP: { // restore to previous window if needed bool stopSlideshow = true; bool stopVideo = true; bool stopMusic = true; if (pMsg->param1 >= PLAYLIST_MUSIC && pMsg->param1 <= PLAYLIST_PICTURE) { stopSlideshow = (pMsg->param1 == PLAYLIST_PICTURE); stopVideo = (pMsg->param1 == PLAYLIST_VIDEO); stopMusic = (pMsg->param1 == PLAYLIST_MUSIC); } if ((stopSlideshow && g_windowManager.GetActiveWindow() == WINDOW_SLIDESHOW) || (stopVideo && g_windowManager.GetActiveWindow() == WINDOW_FULLSCREEN_VIDEO) || (stopMusic && g_windowManager.GetActiveWindow() == WINDOW_VISUALISATION)) g_windowManager.PreviousWindow(); g_application.ResetScreenSaver(); g_application.WakeUpScreenSaverAndDPMS(); // stop playing file if (g_application.m_pPlayer->IsPlaying()) g_application.StopPlaying(); } break; case TMSG_MEDIA_PAUSE: if (g_application.m_pPlayer->HasPlayer()) { g_application.ResetScreenSaver(); g_application.WakeUpScreenSaverAndDPMS(); g_application.m_pPlayer->Pause(); } break; case TMSG_MEDIA_UNPAUSE: if (g_application.m_pPlayer->IsPausedPlayback()) { g_application.ResetScreenSaver(); g_application.WakeUpScreenSaverAndDPMS(); g_application.m_pPlayer->Pause(); } break; case TMSG_MEDIA_PAUSE_IF_PLAYING: if (g_application.m_pPlayer->IsPlaying() && !g_application.m_pPlayer->IsPaused()) { g_application.ResetScreenSaver(); g_application.WakeUpScreenSaverAndDPMS(); g_application.m_pPlayer->Pause(); } break; default: break; } }
// Add an "* All ..." folder to the CFileItemList // depending on the child node void CDirectoryNode::AddQueuingFolder(CFileItemList& items) const { CFileItemPtr pItem; // always hide "all" items if (g_advancedSettings.m_bVideoLibraryHideAllItems) return; // no need for "all" item when only one item if (items.GetObjectCount() <= 1) return; // hack - as the season node might return episodes auto_ptr<CDirectoryNode> pNode(ParseURL(items.GetPath())); switch (pNode->GetChildType()) { case NODE_TYPE_SEASONS: { CStdString strLabel = g_localizeStrings.Get(20366); pItem.reset(new CFileItem(strLabel)); // "All Seasons" pItem->SetPath(BuildPath() + "-1/"); // set the number of watched and unwatched items accordingly int watched = 0; int unwatched = 0; for (int i = 0; i < items.Size(); i++) { CFileItemPtr item = items[i]; watched += (int)item->GetProperty("watchedepisodes").asInteger(); unwatched += (int)item->GetProperty("unwatchedepisodes").asInteger(); } pItem->SetProperty("totalepisodes", watched + unwatched); pItem->SetProperty("numepisodes", watched + unwatched); // will be changed later to reflect watchmode setting pItem->SetProperty("watchedepisodes", watched); pItem->SetProperty("unwatchedepisodes", unwatched); if (items.Size() && items[0]->GetVideoInfoTag()) { *pItem->GetVideoInfoTag() = *items[0]->GetVideoInfoTag(); pItem->GetVideoInfoTag()->m_iSeason = -1; } pItem->GetVideoInfoTag()->m_strTitle = strLabel; pItem->GetVideoInfoTag()->m_iEpisode = watched + unwatched; pItem->GetVideoInfoTag()->m_playCount = (unwatched == 0) ? 1 : 0; CVideoDatabase db; if (db.Open()) { pItem->GetVideoInfoTag()->m_iDbId = db.GetSeasonId(pItem->GetVideoInfoTag()->m_iIdShow, -1); db.Close(); } pItem->GetVideoInfoTag()->m_type = "season"; } break; default: break; } if (pItem) { pItem->m_bIsFolder = true; pItem->SetSpecialSort(g_advancedSettings.m_bVideoLibraryAllItemsOnBottom ? SortSpecialOnBottom : SortSpecialOnTop); pItem->SetCanQueue(false); items.Add(pItem); } }
bool CGUIWindowVideoNav::GetDirectory(const CStdString &strDirectory, CFileItemList &items) { if (m_thumbLoader.IsLoading()) m_thumbLoader.StopThread(); items.ClearProperties(); bool bResult = CGUIWindowVideoBase::GetDirectory(strDirectory, items); if (bResult) { if (items.IsVideoDb()) { XFILE::CVideoDatabaseDirectory dir; CQueryParams params; dir.GetQueryParams(items.GetPath(),params); VIDEODATABASEDIRECTORY::NODE_TYPE node = dir.GetDirectoryChildType(items.GetPath()); // perform the flattening logic for tvshows with a single (unwatched) season (+ optional special season) if (node == NODE_TYPE_SEASONS) { int itemsSize = items.GetObjectCount(); int firstIndex = items.Size() - itemsSize; // check if the last item is the "All seasons" item which should be ignored for flattening if (items[items.Size() - 1]->GetVideoInfoTag()->m_iSeason < 0) itemsSize -= 1; int iFlatten = CSettings::Get().GetInt("videolibrary.flattentvshows"); bool bFlatten = (itemsSize == 1 && iFlatten == 1) || iFlatten == 2 || // flatten if one one season or if always flatten is enabled (itemsSize == 2 && iFlatten == 1 && // flatten if one season + specials (items[firstIndex]->GetVideoInfoTag()->m_iSeason == 0 || items[firstIndex + 1]->GetVideoInfoTag()->m_iSeason == 0)); if (iFlatten > 0 && !bFlatten && (WatchedMode)CMediaSettings::Get().GetWatchedMode("tvshows") == WatchedModeUnwatched) { int count = 0; for(int i = 0; i < items.Size(); i++) { const CFileItemPtr item = items.Get(i); if (item->GetProperty("unwatchedepisodes").asInteger() != 0 && item->GetVideoInfoTag()->m_iSeason > 0) count++; } bFlatten = (count < 2); // flatten if there is only 1 unwatched season (not counting specials) } if (bFlatten) { // flatten if one season or flatten always items.Clear(); CVideoDbUrl videoUrl; if (!videoUrl.FromString(items.GetPath())) return false; videoUrl.AppendPath("-2/"); return GetDirectory(videoUrl.ToString(), items); } } items.SetArt("thumb", ""); if (node == VIDEODATABASEDIRECTORY::NODE_TYPE_EPISODES || node == NODE_TYPE_SEASONS || node == NODE_TYPE_RECENTLY_ADDED_EPISODES) { CLog::Log(LOGDEBUG, "WindowVideoNav::GetDirectory"); // grab the show thumb CVideoInfoTag details; m_database.GetTvShowInfo("", details, params.GetTvShowId()); map<string, string> art; if (m_database.GetArtForItem(details.m_iDbId, details.m_type, art)) { items.AppendArt(art, "tvshow"); items.SetArtFallback("fanart", "tvshow.fanart"); if (node == NODE_TYPE_SEASONS) { // set an art fallback for "thumb" if (items.HasArt("tvshow.poster")) items.SetArtFallback("thumb", "tvshow.poster"); else if (items.HasArt("tvshow.banner")) items.SetArtFallback("thumb", "tvshow.banner"); } } // Grab fanart data items.SetProperty("fanart_color1", details.m_fanart.GetColor(0)); items.SetProperty("fanart_color2", details.m_fanart.GetColor(1)); items.SetProperty("fanart_color3", details.m_fanart.GetColor(2)); // save the show description (showplot) items.SetProperty("showplot", details.m_strPlot); // the container folder thumb is the parent (i.e. season or show) if (node == NODE_TYPE_EPISODES || node == NODE_TYPE_RECENTLY_ADDED_EPISODES) { items.SetContent("episodes"); // grab the season thumb as the folder thumb int seasonID = m_database.GetSeasonId(details.m_iDbId, params.GetSeason()); CGUIListItem::ArtMap seasonArt; if (m_database.GetArtForItem(seasonID, "season", seasonArt)) { items.AppendArt(art, "season"); // set an art fallback for "thumb" if (items.HasArt("season.poster")) items.SetArtFallback("thumb", "season.poster"); else if (items.HasArt("season.banner")) items.SetArtFallback("thumb", "season.banner"); } } else items.SetContent("seasons"); } else if (node == NODE_TYPE_TITLE_MOVIES || node == NODE_TYPE_RECENTLY_ADDED_MOVIES) items.SetContent("movies"); else if (node == NODE_TYPE_TITLE_TVSHOWS) items.SetContent("tvshows"); else if (node == NODE_TYPE_TITLE_MUSICVIDEOS || node == NODE_TYPE_RECENTLY_ADDED_MUSICVIDEOS) items.SetContent("musicvideos"); else if (node == NODE_TYPE_GENRE) items.SetContent("genres"); else if (node == NODE_TYPE_COUNTRY) items.SetContent("countries"); else if (node == NODE_TYPE_ACTOR) { if (params.GetContentType() == VIDEODB_CONTENT_MUSICVIDEOS) items.SetContent("artists"); else items.SetContent("actors"); } else if (node == NODE_TYPE_DIRECTOR) items.SetContent("directors"); else if (node == NODE_TYPE_STUDIO) items.SetContent("studios"); else if (node == NODE_TYPE_YEAR) items.SetContent("years"); else if (node == NODE_TYPE_MUSICVIDEOS_ALBUM) items.SetContent("albums"); else if (node == NODE_TYPE_SETS) items.SetContent("sets"); else if (node == NODE_TYPE_TAGS) items.SetContent("tags"); else items.SetContent(""); } else if (!items.IsVirtualDirectoryRoot()) { // load info from the database CStdString label; if (items.GetLabel().empty() && m_rootDir.IsSource(items.GetPath(), CMediaSourceSettings::Get().GetSources("video"), &label)) items.SetLabel(label); if (!items.IsSourcesPath()) LoadVideoInfo(items); } CVideoDbUrl videoUrl; if (videoUrl.FromString(items.GetPath()) && items.GetContent() == "tags" && !items.Contains("newtag://" + videoUrl.GetType())) { CFileItemPtr newTag(new CFileItem("newtag://" + videoUrl.GetType(), false)); newTag->SetLabel(g_localizeStrings.Get(20462)); newTag->SetLabelPreformated(true); newTag->SetSpecialSort(SortSpecialOnTop); items.Add(newTag); } } return bResult; }
/// \brief Add unique file and folders and its subfolders to playlist /// \param pItem The file item to add void CGUIWindowMusicBase::AddItemToPlayList(const CFileItemPtr &pItem, CFileItemList &queuedItems) { if (!pItem->CanQueue() || pItem->IsRAR() || pItem->IsZIP() || pItem->IsParentFolder()) // no zip/rar enques thank you! return; // fast lookup is needed here queuedItems.SetFastLookup(true); if (pItem->IsMusicDb() && pItem->m_bIsFolder && !pItem->IsParentFolder()) { // we have a music database folder, just grab the "all" item underneath it CMusicDatabaseDirectory dir; if (!dir.ContainsSongs(pItem->GetPath())) { // grab the ALL item in this category // Genres will still require 2 lookups, and queuing the entire Genre folder // will require 3 lookups (genre, artist, album) CMusicDbUrl musicUrl; if (musicUrl.FromString(pItem->GetPath())) { musicUrl.AppendPath("-1/"); CFileItemPtr item(new CFileItem(musicUrl.ToString(), true)); item->SetCanQueue(true); // workaround for CanQueue() check above AddItemToPlayList(item, queuedItems); } return; } } if (pItem->m_bIsFolder || (g_windowManager.GetActiveWindow() == WINDOW_MUSIC_NAV && pItem->IsPlayList())) { // Check if we add a locked share if ( pItem->m_bIsShareOrDrive ) { CFileItem item = *pItem; if ( !g_passwordManager.IsItemUnlocked( &item, "music" ) ) return ; } // recursive CFileItemList items; GetDirectory(pItem->GetPath(), items); //OnRetrieveMusicInfo(items); FormatAndSort(items); for (int i = 0; i < items.Size(); ++i) AddItemToPlayList(items[i], queuedItems); } else { if (pItem->IsPlayList()) { std::unique_ptr<CPlayList> pPlayList (CPlayListFactory::Create(*pItem)); if (pPlayList.get()) { // load it if (!pPlayList->Load(pItem->GetPath())) { CGUIDialogOK::ShowAndGetInput(CVariant{6}, CVariant{477}); return; //hmmm unable to load playlist? } CPlayList playlist = *pPlayList; for (int i = 0; i < (int)playlist.size(); ++i) { AddItemToPlayList(playlist[i], queuedItems); } return; } } else if(pItem->IsInternetStream()) { // just queue the internet stream, it will be expanded on play queuedItems.Add(pItem); } else if (pItem->IsPlugin() && pItem->GetProperty("isplayable") == "true") { // python files can be played queuedItems.Add(pItem); } else if (!pItem->IsNFO() && (pItem->IsAudio() || pItem->IsVideo())) { CFileItemPtr itemCheck = queuedItems.Get(pItem->GetPath()); if (!itemCheck || itemCheck->m_lStartOffset != pItem->m_lStartOffset) { // add item CFileItemPtr item(new CFileItem(*pItem)); m_musicdatabase.SetPropertiesForFileItem(*item); queuedItems.Add(item); } } } }
bool CHTTPDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items) { CFileCurl http; CURL url(strPath); CStdString strName, strLink; CStdString strBasePath = url.GetFileName(); if(!http.Open(url, false)) { CLog::Log(LOGERROR, "%s - Unable to get http directory", __FUNCTION__); return false; } CRegExp reItem; reItem.RegComp("<a href=\"(.*)\">(.*)</a>"); /* read response from server into string buffer */ char buffer[MAX_PATH + 1024]; while(http.ReadString(buffer, sizeof(buffer)-1)) { CStdString strBuffer = buffer; StringUtils::RemoveCRLF(strBuffer); if (reItem.RegFind(strBuffer.c_str()) >= 0) { strLink = reItem.GetReplaceString("\\1"); strName = reItem.GetReplaceString("\\2"); if(strLink[0] == '/') strLink = strLink.Mid(1); CStdString strNameTemp = strName.Trim(); CStdString strLinkTemp = strLink; CUtil::RemoveSlashAtEnd(strLinkTemp); CUtil::RemoveSlashAtEnd(strNameTemp); CUtil::UrlDecode(strLinkTemp); if (strNameTemp == strLinkTemp) { g_charsetConverter.stringCharsetToUtf8(strName); CUtil::RemoveSlashAtEnd(strName); CFileItemPtr pItem(new CFileItem(strName)); pItem->m_strPath = strBasePath + strLink; if(CUtil::HasSlashAtEnd(pItem->m_strPath)) pItem->m_bIsFolder = true; url.SetFileName(pItem->m_strPath); url.GetURL(pItem->m_strPath); if (!pItem->m_bIsFolder && g_advancedSettings.m_bHTTPDirectoryStatFilesize) { CFileCurl file; file.Open(url, false); pItem->m_dwSize= file.GetLength(); file.Close(); } if (!pItem->m_bIsFolder && pItem->m_dwSize == 0) { CRegExp reSize; reSize.RegComp(">([0-9.]+)(K|M|G)</td>"); if (reSize.RegFind(strBuffer.c_str()) >= 0) { double Size = atof(reSize.GetReplaceString("\\1")); CStdString strUnit = reSize.GetReplaceString("\\2"); if (strUnit == "M") Size = Size * 1024; else if (strUnit == "G") Size = Size * 1000 * 1024; pItem->m_dwSize = (__int64)(Size * 1024); } } items.Add(pItem); } } } http.Close(); return true; }
bool CDAVDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items) { CFileCurl dav; CURL url(strPath); CStdString strRequest = "PROPFIND"; dav.SetCustomRequest(strRequest); dav.SetMimeType("text/xml; charset=\"utf-8\""); dav.SetRequestHeader("depth", 1); dav.SetPostData( "<?xml version=\"1.0\" encoding=\"utf-8\" ?>" " <D:propfind xmlns:D=\"DAV:\">" " <D:prop>" " <D:resourcetype/>" " <D:getcontentlength/>" " <D:getlastmodified/>" " <D:creationdate/>" " <D:displayname/>" " </D:prop>" " </D:propfind>"); if (!dav.Open(url)) { CLog::Log(LOGERROR, "%s - Unable to get dav directory (%s)", __FUNCTION__, strPath.c_str()); return false; } char buffer[MAX_PATH + 1024]; CStdString strResponse; CStdString strHeader; while (dav.ReadString(buffer, sizeof(buffer))) { if (strstr(buffer, "<D:response") != NULL) { // The header should contain the xml version/utf encoding line // followed by the <multistatus> tag if (strHeader.IsEmpty()) strHeader = strResponse; strResponse = strHeader; } strResponse.append(buffer, strlen(buffer)); if (strstr(buffer, "</D:response") != NULL) { // Close the multistatus tag from the header if (strHeader.Find("<D:multistatus")) strResponse+="</D:multistatus>\n"; TiXmlDocument davResponse; if (!davResponse.Parse(strResponse)) { CLog::Log(LOGERROR, "%s - Unable to process dav directory (%s)", __FUNCTION__, strPath.c_str()); dav.Close(); return false; } TiXmlNode *pChild; // Iterate over all responses for (pChild = davResponse.RootElement()->FirstChild(); pChild != 0; pChild = pChild->NextSibling()) { if (ValueWithoutNamespace(pChild, "response")) { CFileItem item; ParseResponse(pChild->ToElement(), item); CURL url2(strPath); CURL url3(item.m_strPath); URIUtils::AddFileToFolder(url2.GetWithoutFilename(), url3.GetFileName(), item.m_strPath); if (item.GetLabel().IsEmpty()) { CStdString name(item.m_strPath); URIUtils::RemoveSlashAtEnd(name); CURL::Decode(name); item.SetLabel(URIUtils::GetFileName(name)); } if (item.m_bIsFolder) URIUtils::AddSlashAtEnd(item.m_strPath); // Add back protocol options if (!url2.GetProtocolOptions().IsEmpty()) item.m_strPath += "|" + url2.GetProtocolOptions(); if (!item.m_strPath.Equals(strPath)) { CFileItemPtr pItem(new CFileItem(item)); items.Add(pItem); } } } strResponse.clear(); } } dav.Close(); return true; }
int CGUIWindowAddonBrowser::SelectAddonID(const vector<ADDON::TYPE> &types, vector<string> &addonIDs, bool showNone /* = false */, bool showDetails /* = true */, bool multipleSelection /* = true */, bool showInstalled /* = true */, bool showInstallable /* = false */, bool showMore /* = true */) { // if we shouldn't show neither installed nor installable addons the list will be empty if (!showInstalled && !showInstallable) return 0; // can't show the "Get More" button if we already show installable addons if (showInstallable) showMore = false; CGUIDialogSelect *dialog = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT); if (!dialog) return 0; // get rid of any invalid addon types vector<ADDON::TYPE> validTypes(types.size()); std::copy_if(types.begin(), types.end(), validTypes.begin(), [](ADDON::TYPE type) { return type != ADDON_UNKNOWN; }); if (validTypes.empty()) return 0; // get all addons to show VECADDONS addons; if (showInstalled) { for (vector<ADDON::TYPE>::const_iterator type = validTypes.begin(); type != validTypes.end(); ++type) { VECADDONS typeAddons; if (*type == ADDON_AUDIO) CAddonsDirectory::GetScriptsAndPlugins("audio", typeAddons); else if (*type == ADDON_EXECUTABLE) CAddonsDirectory::GetScriptsAndPlugins("executable", typeAddons); else if (*type == ADDON_IMAGE) CAddonsDirectory::GetScriptsAndPlugins("image", typeAddons); else if (*type == ADDON_VIDEO) CAddonsDirectory::GetScriptsAndPlugins("video", typeAddons); else CAddonMgr::GetInstance().GetAddons(*type, typeAddons); addons.insert(addons.end(), typeAddons.begin(), typeAddons.end()); } } if (showInstallable || showMore) { VECADDONS installableAddons; CAddonDatabase database; if (database.Open() && database.GetAddons(installableAddons)) { for (ADDON::IVECADDONS addon = installableAddons.begin(); addon != installableAddons.end();) { AddonPtr pAddon = *addon; // check if the addon matches one of the provided addon types bool matchesType = false; for (vector<ADDON::TYPE>::const_iterator type = validTypes.begin(); type != validTypes.end(); ++type) { if (pAddon->IsType(*type)) { matchesType = true; break; } } // only show addons that match one of the provided addon types and that aren't disabled if (matchesType && !CAddonMgr::GetInstance().IsAddonDisabled(pAddon->ID())) { // check if the addon is installed bool isInstalled = CAddonMgr::GetInstance().IsAddonInstalled(pAddon->ID()); // check if the addon is installed or can be installed if ((showInstallable || showMore) && !isInstalled && CAddonMgr::GetInstance().CanAddonBeInstalled(pAddon)) { ++addon; continue; } } addon = installableAddons.erase(addon); } if (showInstallable) addons.insert(addons.end(), installableAddons.begin(), installableAddons.end()); else if (showMore) showMore = !installableAddons.empty(); } } if (addons.empty() && !showNone) return 0; // turn the addons into items std::map<std::string, AddonPtr> addonMap; CFileItemList items; for (ADDON::IVECADDONS addon = addons.begin(); addon != addons.end(); ++addon) { CFileItemPtr item(CAddonsDirectory::FileItemFromAddon(*addon, (*addon)->ID())); if (!items.Contains(item->GetPath())) { items.Add(item); addonMap.insert(std::make_pair(item->GetPath(), *addon)); } } if (items.IsEmpty() && !showNone) return 0; std::string heading; for (vector<ADDON::TYPE>::const_iterator type = validTypes.begin(); type != validTypes.end(); ++type) { if (!heading.empty()) heading += ", "; heading += TranslateType(*type, true); } dialog->SetHeading(CVariant{std::move(heading)}); dialog->Reset(); dialog->SetUseDetails(showDetails); if (multipleSelection) { showNone = false; showMore = false; dialog->EnableButton(true, 186); } else if (showMore) dialog->EnableButton(true, 21452); if (showNone) { CFileItemPtr item(new CFileItem("", false)); item->SetLabel(g_localizeStrings.Get(231)); item->SetLabel2(g_localizeStrings.Get(24040)); item->SetIconImage("DefaultAddonNone.png"); item->SetSpecialSort(SortSpecialOnTop); items.Add(item); } items.Sort(SortByLabel, SortOrderAscending); if (addonIDs.size() > 0) { for (vector<string>::const_iterator it = addonIDs.begin(); it != addonIDs.end() ; ++it) { CFileItemPtr item = items.Get(*it); if (item) item->Select(true); } } dialog->SetItems(&items); dialog->SetMultiSelection(multipleSelection); dialog->Open(); // if the "Get More" button has been pressed and we haven't shown the // installable addons so far show a list of installable addons if (showMore&& dialog->IsButtonPressed()) return SelectAddonID(types, addonIDs, showNone, showDetails, multipleSelection, false, true, false); if (!dialog->IsConfirmed()) return 0; addonIDs.clear(); for (int i : dialog->GetSelectedItems()) { const CFileItemPtr& item = items.Get(i); // check if one of the selected addons needs to be installed if (showInstallable) { std::map<std::string, AddonPtr>::const_iterator itAddon = addonMap.find(item->GetPath()); if (itAddon != addonMap.end()) { const AddonPtr& addon = itAddon->second; // if the addon isn't installed we need to install it if (!CAddonMgr::GetInstance().IsAddonInstalled(addon->ID())) { AddonPtr installedAddon; if (!CAddonInstaller::GetInstance().InstallModal(addon->ID(), installedAddon, false)) continue; } // if the addon is disabled we need to enable it if (CAddonMgr::GetInstance().IsAddonDisabled(addon->ID())) CAddonMgr::GetInstance().EnableAddon(addon->ID()); } } addonIDs.push_back(item->GetPath()); } return 1; }
bool CGUIControlListSetting::GetIntegerItems(const CSetting *setting, CFileItemList &items) { const CSettingInt *pSettingInt = NULL; std::set<int> values; if (setting->GetType() == SettingTypeInteger) { pSettingInt = static_cast<const CSettingInt*>(setting); values.insert(pSettingInt->GetValue()); } else if (setting->GetType() == SettingTypeList) { const CSettingList *settingList = static_cast<const CSettingList*>(setting); if (settingList->GetElementType() != SettingTypeInteger) return false; pSettingInt = static_cast<const CSettingInt*>(settingList->GetDefinition()); std::vector<CVariant> list = CSettingUtils::GetList(settingList); for (std::vector<CVariant>::const_iterator itValue = list.begin(); itValue != list.end(); ++itValue) { if (!itValue->isInteger()) return false; values.insert((int)itValue->asInteger()); } } else return false; switch (pSettingInt->GetOptionsType()) { case SettingOptionsTypeStatic: { const StaticIntegerSettingOptions& options = pSettingInt->GetOptions(); for (StaticIntegerSettingOptions::const_iterator it = options.begin(); it != options.end(); ++it) { CFileItemPtr pItem = GetItem(g_localizeStrings.Get(it->first), it->second); if (values.find(it->second) != values.end()) pItem->Select(true); items.Add(pItem); } break; } case SettingOptionsTypeDynamic: { DynamicIntegerSettingOptions options = const_cast<CSettingInt*>(pSettingInt)->UpdateDynamicOptions(); for (DynamicIntegerSettingOptions::const_iterator option = options.begin(); option != options.end(); ++option) { CFileItemPtr pItem = GetItem(option->first, option->second); if (values.find(option->second) != values.end()) pItem->Select(true); items.Add(pItem); } break; } case SettingOptionsTypeNone: default: return false; } return true; }
int CGUIWindowAddonBrowser::SelectAddonID(const vector<ADDON::TYPE> &types, CStdStringArray &addonIDs, bool showNone /*= false*/, bool multipleSelection /*= true*/) { CGUIDialogSelect *dialog = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT); if (!dialog) return 0; CFileItemList items; CStdString heading; int iTypes = 0; for (vector<ADDON::TYPE>::const_iterator it = types.begin(); it != types.end(); ++it) { if (*it == ADDON_UNKNOWN) continue; ADDON::VECADDONS addons; iTypes++; if (*it == ADDON_AUDIO) CAddonsDirectory::GetScriptsAndPlugins("audio",addons); else if (*it == ADDON_EXECUTABLE) CAddonsDirectory::GetScriptsAndPlugins("executable",addons); else if (*it == ADDON_IMAGE) CAddonsDirectory::GetScriptsAndPlugins("image",addons); else if (*it == ADDON_VIDEO) CAddonsDirectory::GetScriptsAndPlugins("video",addons); else CAddonMgr::Get().GetAddons(*it, addons); for (ADDON::IVECADDONS it2 = addons.begin() ; it2 != addons.end() ; ++it2) { CFileItemPtr item(CAddonsDirectory::FileItemFromAddon(*it2, "")); if (!items.Contains(item->GetPath())) items.Add(item); } if (!heading.IsEmpty()) heading += ", "; heading += TranslateType(*it, true); } if (iTypes == 0) return 0; dialog->SetHeading(heading); dialog->Reset(); dialog->SetUseDetails(true); if (multipleSelection) showNone = false; if (multipleSelection || iTypes > 1) dialog->EnableButton(true, 186); else dialog->EnableButton(true, 21452); if (showNone) { CFileItemPtr item(new CFileItem("", false)); item->SetLabel(g_localizeStrings.Get(231)); item->SetLabel2(g_localizeStrings.Get(24040)); item->SetIconImage("DefaultAddonNone.png"); item->SetSpecialSort(SortSpecialOnTop); items.Add(item); } items.Sort(SORT_METHOD_LABEL, SortOrderAscending); if (addonIDs.size() > 0) { for (CStdStringArray::const_iterator it = addonIDs.begin(); it != addonIDs.end() ; it++) { CFileItemPtr item = items.Get(*it); if (item) item->Select(true); } } dialog->SetItems(&items); dialog->SetMultiSelection(multipleSelection); dialog->DoModal(); if (!multipleSelection && iTypes == 1 && dialog->IsButtonPressed()) { // switch to the addons browser. vector<CStdString> params; params.push_back("addons://all/"+TranslateType(types[0],false)+"/"); params.push_back("return"); g_windowManager.ActivateWindow(WINDOW_ADDON_BROWSER, params); return 2; } if (!dialog->IsConfirmed()) return 0; addonIDs.clear(); const CFileItemList& list = dialog->GetSelectedItems(); for (int i = 0 ; i < list.Size() ; i++) addonIDs.push_back(list.Get(i)->GetPath()); return 1; }
bool CGUIWindowAddonBrowser::GetDirectory(const std::string& strDirectory, CFileItemList& items) { bool result; if (URIUtils::PathEquals(strDirectory, "addons://downloading/")) { VECADDONS addons; CAddonInstaller::GetInstance().GetInstallList(addons); CURL url(strDirectory); CAddonsDirectory::GenerateAddonListing(url, addons, items, g_localizeStrings.Get(24067)); result = true; items.SetPath(strDirectory); if (m_guiState.get() && !m_guiState->HideParentDirItems()) { CFileItemPtr pItem(new CFileItem("..")); pItem->SetPath(m_history.GetParentPath()); pItem->m_bIsFolder = true; pItem->m_bIsShareOrDrive = false; items.AddFront(pItem, 0); } } else { result = CGUIMediaWindow::GetDirectory(strDirectory, items); if (result && CAddonsDirectory::IsRepoDirectory(CURL(strDirectory))) { if (CSettings::GetInstance().GetBool(CSettings::SETTING_GENERAL_ADDONFOREIGNFILTER)) { int i = 0; while (i < items.Size()) { auto prop = items[i]->GetProperty("Addon.Language"); if (!prop.isNull() && IsForeign(prop.asString())) items.Remove(i); else ++i; } } if (CSettings::GetInstance().GetBool(CSettings::SETTING_GENERAL_ADDONBROKENFILTER)) { for (int i = items.Size() - 1; i >= 0; i--) { if (!items[i]->GetProperty("Addon.Broken").empty()) { //check if it's installed AddonPtr addon; if (!CAddonMgr::GetInstance().GetAddon(items[i]->GetProperty("Addon.ID").asString(), addon)) items.Remove(i); } } } } } if (strDirectory.empty() && CAddonInstaller::GetInstance().IsDownloading()) { CFileItemPtr item(new CFileItem("addons://downloading/", true)); item->SetLabel(g_localizeStrings.Get(24067)); item->SetLabelPreformated(true); item->SetIconImage("DefaultNetwork.png"); items.Add(item); } items.SetContent("addons"); for (int i = 0; i < items.Size(); ++i) SetItemLabel2(items[i]); return result; }
bool CGUIWindowAddonBrowser::GetDirectory(const CStdString& strDirectory, CFileItemList& items) { bool result; if (strDirectory.Equals("addons://downloading/")) { VECADDONS addons; CAddonInstaller::Get().GetInstallList(addons); CURL url(strDirectory); CAddonsDirectory::GenerateListing(url,addons,items); result = true; items.SetProperty("reponame",g_localizeStrings.Get(24067)); items.SetPath(strDirectory); if (m_guiState.get() && !m_guiState->HideParentDirItems()) { CFileItemPtr pItem(new CFileItem("..")); pItem->SetPath(m_history.GetParentPath()); pItem->m_bIsFolder = true; pItem->m_bIsShareOrDrive = false; items.AddFront(pItem, 0); } } else { result = CGUIMediaWindow::GetDirectory(strDirectory,items); if (CSettings::Get().GetBool("general.addonforeignfilter")) { int i=0; while (i < items.Size()) { if (!FilterVar(CSettings::Get().GetBool("general.addonforeignfilter"), items[i]->GetProperty("Addon.Language"), "en") || !FilterVar(CSettings::Get().GetBool("general.addonforeignfilter"), items[i]->GetProperty("Addon.Language"), g_langInfo.GetLanguageLocale())) { i++; } else items.Remove(i); } } } if (strDirectory.IsEmpty() && CAddonInstaller::Get().IsDownloading()) { CFileItemPtr item(new CFileItem("addons://downloading/",true)); item->SetLabel(g_localizeStrings.Get(24067)); item->SetLabelPreformated(true); item->SetIconImage("DefaultNetwork.png"); items.Add(item); } items.SetContent("addons"); for (int i=0;i<items.Size();++i) SetItemLabel2(items[i]); return result; }
bool CPVRRecordings::ChangeRecordingsPlayCount(const CFileItemPtr &item, int count) { bool bResult = false; if (m_database.IsOpen()) { bResult = true; CLog::Log(LOGDEBUG, "CPVRRecordings - %s - item path %s", __FUNCTION__, item->GetPath().c_str()); CFileItemList items; if (item->m_bIsFolder) { XFILE::CDirectory::GetDirectory(item->GetPath(), items); } else items.Add(item); CLog::Log(LOGDEBUG, "CPVRRecordings - %s - will set watched for %d items", __FUNCTION__, items.Size()); for (int i=0;i<items.Size();++i) { CLog::Log(LOGDEBUG, "CPVRRecordings - %s - setting watched for item %d", __FUNCTION__, i); CFileItemPtr pItem=items[i]; if (pItem->m_bIsFolder) { CLog::Log(LOGDEBUG, "CPVRRecordings - %s - path %s is a folder, will call recursively", __FUNCTION__, pItem->GetPath().c_str()); if (pItem->GetLabel() != "..") { ChangeRecordingsPlayCount(pItem, count); } continue; } if (!pItem->HasPVRRecordingInfoTag()) continue; const CPVRRecordingPtr recording = pItem->GetPVRRecordingInfoTag(); if (recording) { if (count == INCREMENT_PLAY_COUNT) recording->IncrementPlayCount(); else recording->SetPlayCount(count); // Clear resume bookmark if (recording->m_playCount > 0) { m_database.ClearBookMarksOfFile(pItem->GetPath(), CBookmark::RESUME); recording->SetLastPlayedPosition(0); } if (count == INCREMENT_PLAY_COUNT) m_database.IncrementPlayCount(*pItem); else m_database.SetPlayCount(*pItem, count); } } } return bResult; }
bool CPVRRecordings::GetDirectory(const std::string& strPath, CFileItemList &items) { CSingleLock lock(m_critSection); bool bGrouped = false; const CURL url(strPath); if (url.HasOption("view")) { const std::string view(url.GetOption("view")); if (view == "grouped") bGrouped = true; else if (view == "flat") bGrouped = false; else { CLog::Log(LOGERROR, "CPVRRecordings - %s - unsupported value '%s' for url parameter 'view'", __FUNCTION__, view.c_str()); return false; } } else { bGrouped = CSettings::GetInstance().GetBool(CSettings::SETTING_PVRRECORD_GROUPRECORDINGS); } CPVRRecordingsPath recPath(url.GetWithoutOptions()); if (recPath.IsValid()) { // Get the directory structure if in non-flatten mode // Deleted view is always flatten. So only for an active view std::string strDirectory(recPath.GetDirectoryPath()); if (!recPath.IsDeleted() && bGrouped) GetSubDirectories(recPath, &items); // get all files of the currrent directory or recursively all files starting at the current directory if in flatten mode for (const auto recording : m_recordings) { CPVRRecordingPtr current = recording.second; // Omit recordings not matching criteria if (!IsDirectoryMember(strDirectory, current->m_strDirectory, bGrouped) || current->IsDeleted() != recPath.IsDeleted() || current->IsRadio() != recPath.IsRadio()) continue; if (m_database.IsOpen()) current->UpdateMetadata(m_database); CFileItemPtr pFileItem(new CFileItem(current)); pFileItem->SetLabel2(current->RecordingTimeAsLocalTime().GetAsLocalizedDateTime(true, false)); pFileItem->m_dateTime = current->RecordingTimeAsLocalTime(); pFileItem->SetPath(current->m_strFileNameAndPath); // Set art if (!current->m_strIconPath.empty()) { pFileItem->SetIconImage(current->m_strIconPath); pFileItem->SetArt("icon", current->m_strIconPath); } if (!current->m_strThumbnailPath.empty()) pFileItem->SetArt("thumb", current->m_strThumbnailPath); if (!current->m_strFanartPath.empty()) pFileItem->SetArt("fanart", current->m_strFanartPath); // Use the channel icon as a fallback when a thumbnail is not available pFileItem->SetArtFallback("thumb", "icon"); pFileItem->SetOverlayImage(CGUIListItem::ICON_OVERLAY_UNWATCHED, pFileItem->GetPVRRecordingInfoTag()->m_playCount > 0); items.Add(pFileItem); } } if (items.IsEmpty()) { // Note: Do not change the ".." label. It has very special meaning/logic. // CFileItem::IsParentFolder() and and other code depends on this. const CFileItemPtr item(new CFileItem("..")); items.Add(item); } return recPath.IsValid(); }
void CGUIDialogBoxeeChannelFilter::OnInitWindow() { CGUIDialog::OnInitWindow(); CStdString sourcesUrl = "boxee://sources/"; int activeWindow = g_windowManager.GetActiveWindow(); if (activeWindow == WINDOW_BOXEE_BROWSE_MOVIES) { sourcesUrl += "movies"; } else { sourcesUrl += "shows"; } CLog::Log(LOGDEBUG,"CGUIDialogBoxeeChannelFilter::OnInitWindow - build source list for [url=%s] (cf)",sourcesUrl.c_str()); CFileItemList sourceList; DIRECTORY::CDirectory::GetDirectory(sourcesUrl,sourceList); if (sourceList.Size() < 1) { CLog::Log(LOGERROR,"CGUIDialogBoxeeChannelFilter::OnInitWindow - FAILED to get sources. [size=%d] (cf)",sourceList.Size()); Close(); return; } if (!LoadExcludedChannels()) { CLog::Log(LOGERROR,"CGUIDialogBoxeeChannelFilter::OnInitWindow - FAILED to load excluded sources (cf)"); Close(); return; } CLog::Log(LOGDEBUG,"CGUIDialogBoxeeChannelFilter::OnInitWindow - [NumOfSources=%d][NumOfExcludedSources=%zu] (cf)",sourceList.Size(),m_excludedChannels.size()); CGUIMessage winmsgResetPremium(GUI_MSG_LABEL_RESET, GetID(), CHANNEL_LIST); OnMessage(winmsgResetPremium); CFileItemList channelItemList; CFileItemList freeChannelItemList; for (int i=0; i<sourceList.Size(); i++) { CFileItemPtr sourceItem = sourceList.Get(i); std::string sourceId = sourceItem->GetProperty("sourceid"); std::string sourceOffer = sourceItem->GetProperty("sourceoffer"); if (sourceOffer.empty()) { CLog::Log(LOGWARNING,"CGUIDialogBoxeeChannelFilter::OnInitWindow - [%d/%d] - for sources [id=%s] the attribute offer is EMPTY. [offer=%s] (cf)",i+1,sourceList.Size(),sourceId.c_str(),sourceOffer.c_str()); continue; } CFileItemPtr source(new CFileItem(*(sourceItem.get()))); source->SetProperty("channelthumb",source->GetProperty("sourcethumb")); source->Select(m_excludedChannels.find(sourceId) == m_excludedChannels.end()); if (stricmp(sourceOffer.c_str(),FREE_OFFER_STRING)) { if (channelItemList.IsEmpty()) { // add PREMIUM separator CFileItemPtr seperator(new CFileItem(g_localizeStrings.Get(53581))); seperator->SetProperty("isseparator",true); channelItemList.Add(seperator); } CLog::Log(LOGDEBUG,"CGUIDialogBoxeeChannelFilter::OnInitWindow - [%d/%d] - [sourceoffer=%s] -> adding PREMIUM source [id=%s] (cf)",i+1,sourceList.Size(),sourceOffer.c_str(),sourceId.c_str()); channelItemList.Add(source); } else { CLog::Log(LOGDEBUG,"CGUIDialogBoxeeChannelFilter::OnInitWindow - [%d/%d] - [sourceoffer=%s] -> adding FREE source [id=%s] (cf)",i+1,sourceList.Size(),sourceOffer.c_str(),sourceId.c_str()); freeChannelItemList.Add(source); } } for (int i=0; i<freeChannelItemList.Size(); i++) { if (i == 0 && !channelItemList.IsEmpty()) { // add FREE separator CFileItemPtr seperator(new CFileItem(g_localizeStrings.Get(53582))); seperator->SetProperty("isseparator",true); channelItemList.Add(seperator); } CFileItemPtr source(new CFileItem(*(freeChannelItemList.Get(i)))); source->SetProperty("channelthumb",source->GetProperty("sourcethumb")); channelItemList.Add(source); } CGUIMessage msgBindToChannelList(GUI_MSG_LABEL_BIND, GetID(), CHANNEL_LIST, 0, 0, &channelItemList); OnMessage(msgBindToChannelList); SET_CONTROL_FOCUS(CHANNEL_LIST, 0); m_dirty = false; }
// Add an "* All ..." folder to the CFileItemList // depending on the child node void CDirectoryNode::AddQueuingFolder(CFileItemList& items) const { CFileItemPtr pItem; // always hide "all" items if (g_advancedSettings.m_bMusicLibraryHideAllItems) return; // no need for "all" item when only one item if (items.GetObjectCount() <= 1) return; switch (GetChildType()) { // Have no queuing folder case NODE_TYPE_ROOT: case NODE_TYPE_OVERVIEW: case NODE_TYPE_TOP100: break; /* no need for all genres case NODE_TYPE_GENRE: pItem.reset(new CFileItem(g_localizeStrings.Get(15105))); // "All Genres" pItem->GetPath() = BuildPath() + "-1/"; break; */ case NODE_TYPE_ARTIST: if (GetType() == NODE_TYPE_OVERVIEW) return; pItem.reset(new CFileItem(g_localizeStrings.Get(15103))); // "All Artists" pItem->SetPath(BuildPath() + "-1/"); break; // All album related nodes case NODE_TYPE_ALBUM: if (GetType() == NODE_TYPE_OVERVIEW) return; case NODE_TYPE_ALBUM_RECENTLY_PLAYED: case NODE_TYPE_ALBUM_RECENTLY_ADDED: case NODE_TYPE_ALBUM_COMPILATIONS: case NODE_TYPE_ALBUM_TOP100: case NODE_TYPE_YEAR_ALBUM: pItem.reset(new CFileItem(g_localizeStrings.Get(15102))); // "All Albums" pItem->SetPath(BuildPath() + "-1/"); break; // All song related nodes /* case NODE_TYPE_ALBUM_RECENTLY_PLAYED_SONGS: case NODE_TYPE_ALBUM_RECENTLY_ADDED_SONGS: case NODE_TYPE_ALBUM_COMPILATIONS_SONGS: case NODE_TYPE_ALBUM_TOP100_SONGS: case NODE_TYPE_SONG_TOP100: case NODE_TYPE_SONG: pItem = new CFileItem(g_localizeStrings.Get(15104)); // "All Songs" pItem->GetPath() = BuildPath() + "-1/"; break;*/ default: break; } if (pItem) { pItem->m_bIsFolder = true; pItem->SetSpecialSort(g_advancedSettings.m_bMusicLibraryAllItemsOnBottom ? SortSpecialOnBottom : SortSpecialOnTop); pItem->SetCanQueue(false); pItem->SetLabelPreformated(true); if (g_advancedSettings.m_bMusicLibraryAllItemsOnBottom) items.Add(pItem); else items.AddFront(pItem, (items.Size() > 0 && items[0]->IsParentFolder()) ? 1 : 0); } }
bool CPosixDirectory::GetDirectory(const CURL& url, CFileItemList &items) { std::string root = url.Get(); if (IsAliasShortcut(root)) TranslateAliasShortcut(root); DIR *dir = opendir(root.c_str()); if (!dir) return false; struct dirent* entry; while ((entry = readdir(dir)) != NULL) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; CFileItemPtr pItem(new CFileItem(entry->d_name)); std::string itemPath(URIUtils::AddFileToFolder(root, entry->d_name)); bool bStat = false; struct stat buffer; // Unix-based readdir implementations may return an incorrect dirent.d_ino value that // is not equal to the (correct) stat() obtained one. In this case the file type // could not be determined and the value of dirent.d_type is set to DT_UNKNOWN. // In order to get a correct value we have to incur the cost of calling stat. if (entry->d_type == DT_UNKNOWN || entry->d_type == DT_LNK) { if (stat(itemPath.c_str(), &buffer) == 0) bStat = true; } if (entry->d_type == DT_DIR || (bStat && buffer.st_mode & S_IFDIR)) { pItem->m_bIsFolder = true; URIUtils::AddSlashAtEnd(itemPath); } else { pItem->m_bIsFolder = false; } if (StringUtils::StartsWith(entry->d_name, ".")) pItem->SetProperty("file:hidden", true); pItem->SetPath(itemPath); if (!(m_flags & DIR_FLAG_NO_FILE_INFO)) { if (bStat || stat(pItem->GetPath(), &buffer) == 0) { FILETIME fileTime, localTime; TimeTToFileTime(buffer.st_mtime, &fileTime); FileTimeToLocalFileTime(&fileTime, &localTime); pItem->m_dateTime = localTime; if (!pItem->m_bIsFolder) pItem->m_dwSize = buffer.st_size; } } items.Add(pItem); } closedir(dir); return true; }
bool CZeroconfDirectory::GetDirectory(const CURL& url, CFileItemList &items) { assert(url.IsProtocol("zeroconf")); std::string strPath = url.Get(); std::string path = strPath.substr(11, strPath.length()); URIUtils::RemoveSlashAtEnd(path); if(path.empty()) { std::vector<CZeroconfBrowser::ZeroconfService> found_services = CZeroconfBrowser::GetInstance()->GetFoundServices(); for(std::vector<CZeroconfBrowser::ZeroconfService>::iterator it = found_services.begin(); it != found_services.end(); ++it) { //only use discovered services we can connect to through directory std::string tmp; if(GetXBMCProtocol(it->GetType(), tmp)) { CFileItemPtr item(new CFileItem("", true)); CURL url; url.SetProtocol("zeroconf"); std::string service_path(CURL::Encode(CZeroconfBrowser::ZeroconfService::toPath(*it))); url.SetFileName(service_path); item->SetPath(url.Get()); //now do the formatting std::string protocol = GetHumanReadableProtocol(it->GetType()); item->SetLabel(it->GetName() + " (" + protocol + ")"); item->SetLabelPreformated(true); //just set the default folder icon item->FillInDefaultIcon(); items.Add(item); } } return true; } else { //decode the path first std::string decoded(CURL::Decode(path)); try { CZeroconfBrowser::ZeroconfService zeroconf_service = CZeroconfBrowser::ZeroconfService::fromPath(decoded); if(!CZeroconfBrowser::GetInstance()->ResolveService(zeroconf_service)) { CLog::Log(LOGINFO, "CZeroconfDirectory::GetDirectory service ( %s ) could not be resolved in time", zeroconf_service.GetName().c_str()); return false; } else { assert(!zeroconf_service.GetIP().empty()); CURL service; service.SetPort(zeroconf_service.GetPort()); service.SetHostName(zeroconf_service.GetIP()); //do protocol conversion (_smb._tcp -> smb) //ToDo: try automatic conversion -> remove leading '_' and '._tcp'? std::string protocol; if(!GetXBMCProtocol(zeroconf_service.GetType(), protocol)) { CLog::Log(LOGERROR, "CZeroconfDirectory::GetDirectory Unknown service type (%s), skipping; ", zeroconf_service.GetType().c_str()); return false; } service.SetProtocol(protocol); //first try to show the txt-record defined path if any if(GetDirectoryFromTxtRecords(zeroconf_service, service, items)) { return true; } else//no txt record path - so let the CDirectory handler show the folders { // CDirectory::GetDirectory returns false if authorization is required // The target vfs directory will call RequireAuthentication but that is // is not good enough as we can be running as a job and not under main thread, // so authentication dialog does not get called. Set it again here so // authentication dialog gets called and we will get called again with user/pass setup. bool status = CDirectory::GetDirectory(service, items, "", DIR_FLAG_ALLOW_PROMPT); if(!status) RequireAuthentication(service); return status; } } } catch (std::runtime_error& e) { CLog::Log(LOGERROR, "CZeroconfDirectory::GetDirectory failed getting directory: '%s'. Error: '%s'", decoded.c_str(), e.what()); return false; } } }
//********************************************************************************************* bool CRTVDirectory::GetDirectory(const CURL& url2, CFileItemList &items) { CURL url(url2); std::string strRoot = url.Get(); URIUtils::AddSlashAtEnd(strRoot); // Host name is "*" so we try to discover all ReplayTVs. This requires some trickery but works. if (url.GetHostName() == "*") { // Check to see whether the URL's path is blank or "Video" if (url.GetFileName() == "" || url.GetFileName() == "Video") { int iOldSize=items.Size(); struct RTV * rtv = NULL; int numRTV; // Request that all ReplayTVs on the LAN identify themselves. Each ReplayTV // is given 3000ms to respond to the request. rtv_discovery returns an array // of structs containing the IP and friendly name of all ReplayTVs found on the LAN. // For some reason, DVArchive doesn't respond to this request (probably only responds // to requests from an IP address of a real ReplayTV). numRTV = rtv_discovery(&rtv, 3000); // Run through the array and add the ReplayTVs found as folders in XBMC. // We must add the IP of each ReplayTV as if it is a file name at the end of a the // auto-discover URL--e.g. rtv://*/192.168.1.100--because XBMC does not permit // dyamically added shares and will not play from them. This little trickery is // the best workaround I could come up with. for (int i = 0; i < numRTV; i++) { CFileItemPtr pItem(new CFileItem(rtv[i].friendlyName)); // This will keep the /Video or / and allow one to set up an auto ReplayTV // share of either type--simple file listing or ReplayGuide listing. pItem->SetPath(strRoot + rtv[i].hostname); pItem->m_bIsFolder = true; pItem->SetLabelPreformated(true); items.Add(pItem); } free(rtv); return (items.Size()>iOldSize); // Else the URL's path should be an IP address of the ReplayTV } else { std::string strURL, strRTV; size_t pos; // Isolate the IP from the URL and replace the "*" with the real IP // of the ReplayTV. E.g., rtv://*/Video/192.168.1.100/ becomes // rtv://192.168.1.100/Video/ . This trickery makes things work. strURL = StringUtils::TrimRight(strRoot, "/"); pos = strURL.rfind('/'); strRTV = strURL.substr(0, pos + 1); StringUtils::Replace(strRTV, "*", strURL.substr(pos + 1)); CURL tmpURL(strRTV); // Force the newly constructed share into the right variables to // be further processed by the remainder of GetDirectory. url = tmpURL; strRoot = strRTV; } } // Allow for ReplayTVs on ports other than 80 std::string strHostAndPort = url.GetHostName(); if (url.HasPort()) { char buffer[10]; sprintf(buffer,"%i",url.GetPort()); strHostAndPort += ':'; strHostAndPort += buffer; } // No path given, list shows from ReplayGuide if (url.GetFileName() == "") { unsigned char * data = NULL; // Get the RTV guide data in XML format rtv_get_guide_xml(&data, strHostAndPort.c_str()); // Begin parsing the XML data CXBMCTinyXML xmlDoc; xmlDoc.Parse( (const char *) data ); if ( xmlDoc.Error() ) { free(data); return false; } TiXmlElement* pRootElement = xmlDoc.RootElement(); if (!pRootElement) { free(data); return false; } const TiXmlNode *pChild = pRootElement->FirstChild(); while (pChild > 0) { std::string strTagName = pChild->ValueStr(); if ( !strcmpi(strTagName.c_str(), "ITEM") ) { const TiXmlNode *nameNode = pChild->FirstChild("DISPLAYNAME"); // const TiXmlNode *qualityNode = pChild->FirstChild("QUALITY"); const TiXmlNode *recordedNode = pChild->FirstChild("RECORDED"); const TiXmlNode *pathNode = pChild->FirstChild("PATH"); // const TiXmlNode *durationNode = pChild->FirstChild("DURATION"); const TiXmlNode *sizeNode = pChild->FirstChild("SIZE"); const TiXmlNode *atrbNode = pChild->FirstChild("ATTRIB"); SYSTEMTIME dtDateTime; DWORD dwFileSize = 0; memset(&dtDateTime, 0, sizeof(dtDateTime)); // DISPLAYNAME const char* szName = NULL; if (nameNode) { szName = nameNode->FirstChild()->Value() ; } else { // Something went wrong, the recording has no name free(data); return false; } // QUALITY // const char* szQuality = NULL; // if (qualityNode) // { // szQuality = qualityNode->FirstChild()->Value() ; // } // RECORDED if (recordedNode && recordedNode->FirstChild()) { std::string strRecorded = recordedNode->FirstChild()->ValueStr(); if (strRecorded.size() >= 19) { /* TODO:STRING_CLEANUP */ int iYear, iMonth, iDay; iYear = atoi(strRecorded.substr(0, 4).c_str()); iMonth = atoi(strRecorded.substr(5, 2).c_str()); iDay = atoi(strRecorded.substr(8, 2).c_str()); dtDateTime.wYear = iYear; dtDateTime.wMonth = iMonth; dtDateTime.wDay = iDay; int iHour, iMin, iSec; iHour = atoi(strRecorded.substr(11, 2).c_str()); iMin = atoi(strRecorded.substr(14, 2).c_str()); iSec = atoi(strRecorded.substr(17, 2).c_str()); dtDateTime.wHour = iHour; dtDateTime.wMinute = iMin; dtDateTime.wSecond = iSec; } } // PATH const char* szPath = NULL; if (pathNode) { szPath = pathNode->FirstChild()->Value() ; } else { // Something went wrong, the recording has no filename free(data); return false; } // DURATION // const char* szDuration = NULL; // if (durationNode) // { // szDuration = durationNode->FirstChild()->Value() ; // } // SIZE // NOTE: Size here is actually just duration in minutes because // filesize is not reported by the stripped down GuideParser I use if (sizeNode) { dwFileSize = atol( sizeNode->FirstChild()->Value() ); } // ATTRIB // NOTE: Not currently reported in the XML guide data, nor is it particularly // needed unless someone wants to add the ability to sub-divide the recordings // into categories, as on a real RTV. int attrib = 0; if (atrbNode) { attrib = atoi( atrbNode->FirstChild()->Value() ); } bool bIsFolder(false); if (attrib & FILE_ATTRIBUTE_DIRECTORY) bIsFolder = true; CFileItemPtr pItem(new CFileItem(szName)); pItem->m_dateTime=dtDateTime; pItem->SetPath(strRoot + szPath); // Hack to show duration of show in minutes as KB in XBMC because // it doesn't currently permit showing duration in minutes. // E.g., a 30 minute show will show as 29.3 KB in XBMC. pItem->m_dwSize = dwFileSize * 1000; pItem->m_bIsFolder = bIsFolder; pItem->SetLabelPreformated(true); items.Add(pItem); } pChild = pChild->NextSibling(); } free(data); // Path given (usually Video), list filenames only } else { unsigned char * data; char * p, * q; unsigned long status; // Return a listing of all files in the given path status = rtv_list_files(&data, strHostAndPort.c_str(), url.GetFileName().c_str()); if (status == 0) { return false; } // Loop through the file list using pointers p and q, where p will point to the current // filename and q will point to the next filename p = (char *) data; while (p) { // Look for the end of the current line of the file listing q = strchr(p, '\n'); // If found, replace the newline character with the NULL terminator if (q) { *q = '\0'; // Increment q so that it points to the next filename q++; // *p should be the current null-terminated filename in the list if (*p) { // Only display MPEG files in XBMC (but not circular.mpg, as that is the RTV // video buffer and XBMC may cause problems if it tries to play it) if (strstr(p, ".mpg") && !strstr(p, "circular")) { CFileItemPtr pItem(new CFileItem(p)); pItem->SetPath(strRoot + p); pItem->m_bIsFolder = false; // The list returned by the RTV doesn't include file sizes, unfortunately //pItem->m_dwSize = atol(szSize); pItem->SetLabelPreformated(true); items.Add(pItem); } } } // Point p to the next filename in the list and loop p = q; } free(data); } return true; }
bool GetDirectoryFromTxtRecords(CZeroconfBrowser::ZeroconfService zeroconf_service, CURL& url, CFileItemList &items) { bool ret = false; //get the txt-records from this service CZeroconfBrowser::ZeroconfService::tTxtRecordMap txtRecords=zeroconf_service.GetTxtRecords(); //if we have some records if(!txtRecords.empty()) { std::string path; std::string username; std::string password; //search for a path key entry CZeroconfBrowser::ZeroconfService::tTxtRecordMap::iterator it = txtRecords.find(TXT_RECORD_PATH_KEY); //if we found the key - be sure there is a value there if( it != txtRecords.end() && !it->second.empty() ) { //from now on we treat the value as a path - everything else would mean //a missconfigured zeroconf server. path=it->second; } //search for a username key entry it = txtRecords.find(TXT_RECORD_USERNAME_KEY); //if we found the key - be sure there is a value there if( it != txtRecords.end() && !it->second.empty() ) { username=it->second; url.SetUserName(username); } //search for a password key entry it = txtRecords.find(TXT_RECORD_PASSWORD_KEY); //if we found the key - be sure there is a value there if( it != txtRecords.end() && !it->second.empty() ) { password=it->second; url.SetPassword(password); } //if we got a path - add a item - else at least we maybe have set username and password to theurl if( !path.empty()) { CFileItemPtr item(new CFileItem("", true)); std::string urlStr(url.Get()); //if path has a leading slash (sure it should have one) if( path.at(0) == '/' ) { URIUtils::RemoveSlashAtEnd(urlStr);//we don't need the slash at and of url then } else//path doesn't start with slash - {//this is some kind of missconfiguration - we fix it by adding a slash to the url URIUtils::AddSlashAtEnd(urlStr); } //add slash at end of path since it has to be a folder URIUtils::AddSlashAtEnd(path); //this is the full path includeing remote stuff (e.x. nfs://ip/path item->SetPath(urlStr + path); //remove the slash at the end of the path or GetFileName will not give the last dir URIUtils::RemoveSlashAtEnd(path); //set the label to the last directory in path if( !URIUtils::GetFileName(path).empty() ) item->SetLabel(URIUtils::GetFileName(path)); else item->SetLabel("/"); item->SetLabelPreformated(true); //just set the default folder icon item->FillInDefaultIcon(); item->m_bIsShareOrDrive=true; items.Add(item); ret = true; } } return ret; }
/** * This method tries to determine what type of disc is located in the given drive and starts to play the content appropriately. */ bool CAutorun::RunDisc(IDirectory* pDir, const CStdString& strDrive, int& nAddedToPlaylist, bool bRoot, bool bypassSettings /* = false */, bool startFromBeginning /* = false */) { bool bPlaying(false); CFileItemList vecItems; const CURL pathToUrl(strDrive); if ( !pDir->GetDirectory( pathToUrl, vecItems ) ) { return false; } // Sorting necessary for easier HDDVD handling vecItems.Sort(SortByLabel, SortOrderAscending); bool bAllowVideo = true; // bool bAllowPictures = true; bool bAllowMusic = true; if (!g_passwordManager.IsMasterLockUnlocked(false)) { bAllowVideo = !CProfilesManager::Get().GetCurrentProfile().videoLocked(); // bAllowPictures = !CProfilesManager::Get().GetCurrentProfile().picturesLocked(); bAllowMusic = !CProfilesManager::Get().GetCurrentProfile().musicLocked(); } // is this a root folder we have to check the content to determine a disc type if( bRoot ) { CStdString hddvdname = ""; CFileItemPtr phddvdItem; // check root folders next, for normal structured dvd's for (int i = 0; i < vecItems.Size(); i++) { CFileItemPtr pItem = vecItems[i]; // is the current item a (non system) folder? if (pItem->m_bIsFolder && pItem->GetPath() != "." && pItem->GetPath() != "..") { CStdString name = pItem->GetPath(); URIUtils::RemoveSlashAtEnd(name); name = URIUtils::GetFileName(name); // Check if the current foldername indicates a DVD structure (name is "VIDEO_TS") if (name.Equals("VIDEO_TS") && bAllowVideo && (bypassSettings || CSettings::Get().GetBool("dvds.autorun"))) { CStdString path = URIUtils::AddFileToFolder(pItem->GetPath(), "VIDEO_TS.IFO"); if(!CFile::Exists(path)) path = URIUtils::AddFileToFolder(pItem->GetPath(), "video_ts.ifo"); CFileItemPtr item(new CFileItem(path, false)); item->SetLabel(g_mediaManager.GetDiskLabel(strDrive)); item->GetVideoInfoTag()->m_strFileNameAndPath = g_mediaManager.GetDiskUniqueId(strDrive); if (!startFromBeginning && !item->GetVideoInfoTag()->m_strFileNameAndPath.empty()) item->m_lStartOffset = STARTOFFSET_RESUME; g_playlistPlayer.ClearPlaylist(PLAYLIST_VIDEO); g_playlistPlayer.SetShuffle (PLAYLIST_VIDEO, false); g_playlistPlayer.Add(PLAYLIST_VIDEO, item); g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_VIDEO); g_playlistPlayer.Play(0); return true; } // Check if the current foldername indicates a Blu-Ray structure (default is "BDMV"). // A BR should also include an "AACS" folder for encryption, Sony-BRs can also include update folders for PS3 (PS3_UPDATE / PS3_VPRM). // ToDo: for the time beeing, the DVD autorun settings are used to determine if the BR should be started automatically. if (name.Equals("BDMV") && bAllowVideo && (bypassSettings || CSettings::Get().GetBool("dvds.autorun"))) { CFileItemPtr item(new CFileItem(URIUtils::AddFileToFolder(pItem->GetPath(), "index.bdmv"), false)); item->SetLabel(g_mediaManager.GetDiskLabel(strDrive)); item->GetVideoInfoTag()->m_strFileNameAndPath = g_mediaManager.GetDiskUniqueId(strDrive); if (!startFromBeginning && !item->GetVideoInfoTag()->m_strFileNameAndPath.empty()) item->m_lStartOffset = STARTOFFSET_RESUME; g_playlistPlayer.ClearPlaylist(PLAYLIST_VIDEO); g_playlistPlayer.SetShuffle (PLAYLIST_VIDEO, false); if (!CGUIWindowVideoBase::ShowPlaySelection(item)) return false; g_playlistPlayer.Add(PLAYLIST_VIDEO, item); g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_VIDEO); g_playlistPlayer.Play(0); return true; } // Check if the current foldername indicates a HD DVD structure (default is "HVDVD_TS"). // Most HD DVD will also include an "ADV_OBJ" folder for advanced content. This folder should be handled first. // ToDo: for the time beeing, the DVD autorun settings are used to determine if the HD DVD should be started automatically. CFileItemList items, sitems; // Advanced Content HD DVD (most discs?) if (name.Equals("ADV_OBJ")) { CLog::Log(LOGINFO,"HD DVD: Checking for playlist."); // find playlist file CDirectory::GetDirectory(pItem->GetPath(), items, "*.xpl"); if (items.Size()) { // HD DVD Standard says the highest numbered playlist has to be handled first. CLog::Log(LOGINFO,"HD DVD: Playlist found. Set filetypes to *.xpl for external player."); items.Sort(SortByLabel, SortOrderDescending); phddvdItem = pItem; hddvdname = URIUtils::GetFileName(items[0]->GetPath()); CLog::Log(LOGINFO,"HD DVD: %s", items[0]->GetPath().c_str()); } } // Standard Content HD DVD (few discs?) if (name.Equals("HVDVD_TS") && bAllowVideo && (bypassSettings || CSettings::Get().GetBool("dvds.autorun"))) { if (hddvdname == "") { CLog::Log(LOGINFO,"HD DVD: Checking for ifo."); // find Video Manager or Title Set Information CDirectory::GetDirectory(pItem->GetPath(), items, "HV*.ifo"); if (items.Size()) { // HD DVD Standard says the lowest numbered ifo has to be handled first. CLog::Log(LOGINFO,"HD DVD: IFO found. Set filename to HV* and filetypes to *.ifo for external player."); items.Sort(SortByLabel, SortOrderAscending); phddvdItem = pItem; hddvdname = URIUtils::GetFileName(items[0]->GetPath()); CLog::Log(LOGINFO,"HD DVD: %s",items[0]->GetPath().c_str()); } } // Find and sort *.evo files for internal playback. // While this algorithm works for all of my HD DVDs, it may fail on other discs. If there are very large extras which are // alphabetically before the main movie they will be sorted to the top of the playlist and get played first. CDirectory::GetDirectory(pItem->GetPath(), items, "*.evo"); if (items.Size()) { // Sort *.evo files in alphabetical order. items.Sort(SortByLabel, SortOrderAscending); int64_t asize = 0; int ecount = 0; // calculate average size of elements above 1gb for (int j = 0; j < items.Size(); j++) if (items[j]->m_dwSize > 1000000000) { ecount++; asize = asize + items[j]->m_dwSize; } asize = asize / ecount; // Put largest files in alphabetical order to top of new list. for (int j = 0; j < items.Size(); j++) if (items[j]->m_dwSize >= asize) sitems.Add (items[j]); // Sort *.evo files by size. items.Sort(SortBySize, SortOrderDescending); // Add other files with descending size to bottom of new list. for (int j = 0; j < items.Size(); j++) if (items[j]->m_dwSize < asize) sitems.Add (items[j]); // Replace list with optimized list. items.Clear(); items.Copy (sitems); sitems.Clear(); } if (hddvdname != "") { CFileItem item(URIUtils::AddFileToFolder(phddvdItem->GetPath(), hddvdname), false); item.SetLabel(g_mediaManager.GetDiskLabel(strDrive)); item.GetVideoInfoTag()->m_strFileNameAndPath = g_mediaManager.GetDiskUniqueId(strDrive); if (!startFromBeginning && !item.GetVideoInfoTag()->m_strFileNameAndPath.empty()) item.m_lStartOffset = STARTOFFSET_RESUME; // get playername CStdString hddvdplayer = CPlayerCoreFactory::Get().GetPlayerName(CPlayerCoreFactory::Get().GetDefaultPlayer(item)); // Single *.xpl or *.ifo files require an external player to handle playback. // If no matching rule was found, DVDPlayer will be default player. if (hddvdplayer != "DVDPlayer") { CLog::Log(LOGINFO,"HD DVD: External singlefile playback initiated: %s",hddvdname.c_str()); g_application.PlayFile(item, false); return true; } else CLog::Log(LOGINFO,"HD DVD: No external player found. Fallback to internal one."); } // internal *.evo playback. CLog::Log(LOGINFO,"HD DVD: Internal multifile playback initiated."); g_playlistPlayer.ClearPlaylist(PLAYLIST_VIDEO); g_playlistPlayer.SetShuffle (PLAYLIST_VIDEO, false); g_playlistPlayer.Add(PLAYLIST_VIDEO, items); g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_VIDEO); g_playlistPlayer.Play(0); return true; } // Video CDs can have multiple file formats. First we need to determine which one is used on the CD CStdString strExt; if (name.Equals("MPEGAV")) strExt = ".dat"; if (name.Equals("MPEG2")) strExt = ".mpg"; // If a file format was extracted we are sure this is a VCD. Autoplay if settings indicate we should. if (!strExt.empty() && bAllowVideo && (bypassSettings || CSettings::Get().GetBool("dvds.autorun"))) { CFileItemList items; CDirectory::GetDirectory(pItem->GetPath(), items, strExt); if (items.Size()) { items.Sort(SortByLabel, SortOrderAscending); g_playlistPlayer.ClearPlaylist(PLAYLIST_VIDEO); g_playlistPlayer.Add(PLAYLIST_VIDEO, items); g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_VIDEO); g_playlistPlayer.Play(0); return true; } } /* Probably want this if/when we add some automedia action dialog... else if (pItem->GetPath().Find("PICTURES") != -1 && bAllowPictures && (bypassSettings)) { bPlaying = true; CStdString strExec = StringUtils::Format("RecursiveSlideShow(%s)", pItem->GetPath().c_str()); CBuiltins::Execute(strExec); return true; } */ } } } // check video first if (!nAddedToPlaylist && !bPlaying && (bypassSettings || CSettings::Get().GetBool("dvds.autorun"))) { // stack video files CFileItemList tempItems; tempItems.Append(vecItems); if (CSettings::Get().GetBool("myvideos.stackvideos")) tempItems.Stack(); CFileItemList itemlist; for (int i = 0; i < tempItems.Size(); i++) { CFileItemPtr pItem = tempItems[i]; if (!pItem->m_bIsFolder && pItem->IsVideo()) { bPlaying = true; if (pItem->IsStack()) { // TODO: remove this once the app/player is capable of handling stacks immediately CStackDirectory dir; CFileItemList items; dir.GetDirectory(pItem->GetURL(), items); itemlist.Append(items); } else itemlist.Add(pItem); } } if (itemlist.Size()) { if (!bAllowVideo) { if (!bypassSettings) return false; if (g_windowManager.GetActiveWindow() != WINDOW_VIDEO_FILES) if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; } g_playlistPlayer.ClearPlaylist(PLAYLIST_VIDEO); g_playlistPlayer.Add(PLAYLIST_VIDEO, itemlist); g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_VIDEO); g_playlistPlayer.Play(0); } } // then music if (!bPlaying && (bypassSettings || CSettings::Get().GetInt("audiocds.autoaction") == AUTOCD_PLAY) && bAllowMusic) { for (int i = 0; i < vecItems.Size(); i++) { CFileItemPtr pItem = vecItems[i]; if (!pItem->m_bIsFolder && pItem->IsAudio()) { nAddedToPlaylist++; g_playlistPlayer.Add(PLAYLIST_MUSIC, pItem); } } } /* Probably want this if/when we add some automedia action dialog... // and finally pictures if (!nAddedToPlaylist && !bPlaying && bypassSettings && bAllowPictures) { for (int i = 0; i < vecItems.Size(); i++) { CFileItemPtr pItem = vecItems[i]; if (!pItem->m_bIsFolder && pItem->IsPicture()) { bPlaying = true; CStdString strExec = StringUtils::Format("RecursiveSlideShow(%s)", strDrive.c_str()); CBuiltins::Execute(strExec); break; } } } */ // check subdirs if we are not playing yet if (!bPlaying) { for (int i = 0; i < vecItems.Size(); i++) { CFileItemPtr pItem = vecItems[i]; if (pItem->m_bIsFolder) { if (pItem->GetPath() != "." && pItem->GetPath() != ".." ) { if (RunDisc(pDir, pItem->GetPath(), nAddedToPlaylist, false, bypassSettings, startFromBeginning)) { bPlaying = true; break; } } } // if (non system) folder } // for all items in directory } // if root folder return bPlaying; }
bool CPVRChannelGroupsContainer::GetDirectory(const std::string& strPath, CFileItemList &results) const { std::string strBase(strPath); URIUtils::RemoveSlashAtEnd(strBase); /* get the filename from curl */ CURL url(strPath); std::string fileName = url.GetFileName(); URIUtils::RemoveSlashAtEnd(fileName); if (fileName == "channels") { CFileItemPtr item; /* all tv channels */ item.reset(new CFileItem(strBase + "/tv/", true)); item->SetLabel(g_localizeStrings.Get(19020)); item->SetLabelPreformatted(true); results.Add(item); /* all radio channels */ item.reset(new CFileItem(strBase + "/radio/", true)); item->SetLabel(g_localizeStrings.Get(19021)); item->SetLabelPreformatted(true); results.Add(item); return true; } else if (fileName == "channels/tv") { return GetGroupsDirectory(&results, false); } else if (fileName == "channels/radio") { return GetGroupsDirectory(&results, true); } else if (StringUtils::StartsWith(fileName, "channels/tv/")) { std::string strGroupName(fileName.substr(12)); URIUtils::RemoveSlashAtEnd(strGroupName); CPVRChannelGroupPtr group; if (strGroupName == "*") // all channels group = GetGroupAllTV(); else group = GetTV()->GetByName(strGroupName); if (group) { group->GetMembers(results, !StringUtils::EndsWithNoCase(fileName, ".hidden")); } else { CLog::Log(LOGERROR, "CPVRChannelGroupsContainer - %s - unable to obtain members of channel group '%s'", __FUNCTION__, strGroupName.c_str()); return false; } FilterDirectory(url, results); return true; } else if (StringUtils::StartsWith(fileName, "channels/radio/")) { std::string strGroupName(fileName.substr(15)); URIUtils::RemoveSlashAtEnd(strGroupName); CPVRChannelGroupPtr group; if (strGroupName == "*") // all channels group = GetGroupAllRadio(); else group = GetRadio()->GetByName(strGroupName); if (group) { group->GetMembers(results, !StringUtils::EndsWithNoCase(fileName, ".hidden")); } else { CLog::Log(LOGERROR, "CPVRChannelGroupsContainer - %s - unable to obtain members of channel group '%s'", __FUNCTION__, strGroupName.c_str()); return false; } FilterDirectory(url, results); return true; } return false; }
bool CGUIWindowMusicBase::GetDirectory(const std::string &strDirectory, CFileItemList &items) { items.ClearArt(); bool bResult = CGUIMediaWindow::GetDirectory(strDirectory, items); if (bResult) { CMusicThumbLoader loader; loader.FillThumb(items); CQueryParams params; CDirectoryNode::GetDatabaseInfo(items.GetPath(), params); if (params.GetAlbumId() > 0) { std::map<std::string, std::string> artistArt; if (m_musicdatabase.GetArtistArtForItem(params.GetAlbumId(), MediaTypeAlbum, artistArt)) items.AppendArt(artistArt, MediaTypeArtist); std::map<std::string, std::string> albumArt; if (m_musicdatabase.GetArtForItem(params.GetAlbumId(), MediaTypeAlbum, albumArt)) items.AppendArt(albumArt, MediaTypeAlbum); } if (params.GetArtistId() > 0) { std::map<std::string, std::string> artistArt; if (m_musicdatabase.GetArtForItem(params.GetArtistId(), "artist", artistArt)) items.AppendArt(artistArt, MediaTypeArtist); } // add in the "New Playlist" item if we're in the playlists folder if ((items.GetPath() == "special://musicplaylists/") && !items.Contains("newplaylist://")) { CFileItemPtr newPlaylist(new CFileItem(CProfilesManager::GetInstance().GetUserDataItem("PartyMode.xsp"),false)); newPlaylist->SetLabel(g_localizeStrings.Get(16035)); newPlaylist->SetLabelPreformated(true); newPlaylist->m_bIsFolder = true; items.Add(newPlaylist); newPlaylist.reset(new CFileItem("newplaylist://", false)); newPlaylist->SetLabel(g_localizeStrings.Get(525)); newPlaylist->SetIconImage("DefaultPlaylist.png"); newPlaylist->SetLabelPreformated(true); newPlaylist->SetSpecialSort(SortSpecialOnBottom); newPlaylist->SetCanQueue(false); items.Add(newPlaylist); newPlaylist.reset(new CFileItem("newsmartplaylist://music", false)); newPlaylist->SetLabel(g_localizeStrings.Get(21437)); newPlaylist->SetIconImage("DefaultPlaylist.png"); newPlaylist->SetLabelPreformated(true); newPlaylist->SetSpecialSort(SortSpecialOnBottom); newPlaylist->SetCanQueue(false); items.Add(newPlaylist); } // check for .CUE files here. items.FilterCueItems(); std::string label; if (items.GetLabel().empty() && m_rootDir.IsSource(items.GetPath(), CMediaSourceSettings::GetInstance().GetSources("music"), &label)) items.SetLabel(label); } return bResult; }
// Add an "* All ..." folder to the CFileItemList // depending on the child node void CVideoFileItemListModifier::AddQueuingFolder(CFileItemList& items) { if (!items.IsVideoDb()) return; auto directoryNode = CDirectoryNode::ParseURL(items.GetPath()); CFileItemPtr pItem; // always show "all" items by default if (!CServiceBroker::GetSettings().GetBool(CSettings::SETTING_VIDEOLIBRARY_SHOWALLITEMS)) return; // no need for "all" item when only one item if (items.GetObjectCount() <= 1) return; CVideoDbUrl videoUrl; if (!videoUrl.FromString(directoryNode->BuildPath())) return; // hack - as the season node might return episodes std::unique_ptr<CDirectoryNode> pNode(directoryNode); switch (pNode->GetChildType()) { case NODE_TYPE_SEASONS: { std::string strLabel = g_localizeStrings.Get(20366); pItem.reset(new CFileItem(strLabel)); // "All Seasons" videoUrl.AppendPath("-1/"); pItem->SetPath(videoUrl.ToString()); // set the number of watched and unwatched items accordingly int watched = 0; int unwatched = 0; for (int i = 0; i < items.Size(); i++) { CFileItemPtr item = items[i]; watched += static_cast<int>(item->GetProperty("watchedepisodes").asInteger()); unwatched += static_cast<int>(item->GetProperty("unwatchedepisodes").asInteger()); } pItem->SetProperty("totalepisodes", watched + unwatched); pItem->SetProperty("numepisodes", watched + unwatched); // will be changed later to reflect watchmode setting pItem->SetProperty("watchedepisodes", watched); pItem->SetProperty("unwatchedepisodes", unwatched); if (items.Size() && items[0]->GetVideoInfoTag()) { *pItem->GetVideoInfoTag() = *items[0]->GetVideoInfoTag(); pItem->GetVideoInfoTag()->m_iSeason = -1; } pItem->GetVideoInfoTag()->m_strTitle = strLabel; pItem->GetVideoInfoTag()->m_iEpisode = watched + unwatched; pItem->GetVideoInfoTag()->SetPlayCount((unwatched == 0) ? 1 : 0); CVideoDatabase db; if (db.Open()) { pItem->GetVideoInfoTag()->m_iDbId = db.GetSeasonId(pItem->GetVideoInfoTag()->m_iIdShow, -1); db.Close(); } pItem->GetVideoInfoTag()->m_type = MediaTypeSeason; } break; case NODE_TYPE_MUSICVIDEOS_ALBUM: pItem.reset(new CFileItem(g_localizeStrings.Get(15102))); // "All Albums" videoUrl.AppendPath("-1/"); pItem->SetPath(videoUrl.ToString()); break; default: break; } if (pItem) { pItem->m_bIsFolder = true; pItem->SetSpecialSort(g_advancedSettings.m_bVideoLibraryAllItemsOnBottom ? SortSpecialOnBottom : SortSpecialOnTop); pItem->SetCanQueue(false); items.Add(pItem); } }
//! @todo Currently no support for "embedded thumb" as there is no easy way to grab it //! without sending a file that has this as it's album to this class void CGUIDialogSongInfo::OnGetThumb() { CFileItemList items; // Grab the thumbnail from the web /* std::string thumbFromWeb; thumbFromWeb = URIUtils::AddFileToFolder(g_advancedSettings.m_cachePath, "allmusicThumb.jpg"); if (DownloadThumbnail(thumbFromWeb)) { CFileItemPtr item(new CFileItem("thumb://allmusic.com", false)); item->SetArt("thumb", thumbFromWeb); item->SetLabel(g_localizeStrings.Get(20055)); items.Add(item); }*/ // Current thumb if (CFile::Exists(m_song->GetArt("thumb"))) { CFileItemPtr item(new CFileItem("thumb://Current", false)); item->SetArt("thumb", m_song->GetArt("thumb")); item->SetLabel(g_localizeStrings.Get(20016)); items.Add(item); } // local thumb std::string cachedLocalThumb; std::string localThumb(m_song->GetUserMusicThumb(true)); if (m_song->IsMusicDb()) { CFileItem item(m_song->GetMusicInfoTag()->GetURL(), false); localThumb = item.GetUserMusicThumb(true); } if (CFile::Exists(localThumb)) { CFileItemPtr item(new CFileItem("thumb://Local", false)); item->SetArt("thumb", localThumb); item->SetLabel(g_localizeStrings.Get(20017)); items.Add(item); } else { // no local thumb exists, so we are just using the allmusic.com thumb or cached thumb // which is probably the allmusic.com thumb. These could be wrong, so allow the user // to delete the incorrect thumb CFileItemPtr item(new CFileItem("thumb://None", false)); item->SetArt("thumb", "DefaultAlbumCover.png"); item->SetLabel(g_localizeStrings.Get(20018)); items.Add(item); } std::string result; VECSOURCES sources(*CMediaSourceSettings::GetInstance().GetSources("music")); CGUIDialogMusicInfo::AddItemPathToFileBrowserSources(sources, *m_song); g_mediaManager.GetLocalDrives(sources); if (!CGUIDialogFileBrowser::ShowAndGetImage(items, sources, g_localizeStrings.Get(1030), result)) return; // user cancelled if (result == "thumb://Current") return; // user chose the one they have // delete the thumbnail if that's what the user wants, else overwrite with the // new thumbnail std::string newThumb; if (result == "thumb://None") newThumb = "-"; else if (result == "thumb://allmusic.com") newThumb.clear(); else if (result == "thumb://Local") newThumb = localThumb; else newThumb = result; // update thumb in the database CMusicDatabase db; if (db.Open()) { db.SetArtForItem(m_song->GetMusicInfoTag()->GetDatabaseId(), m_song->GetMusicInfoTag()->GetType(), "thumb", newThumb); db.Close(); } m_song->SetArt("thumb", newThumb); // 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); // m_hasUpdatedThumb = true; }
bool CLibraryDirectory::GetDirectory(const CURL& url, CFileItemList &items) { std::string libNode = GetNode(url); if (libNode.empty()) return false; if (URIUtils::HasExtension(libNode, ".xml")) { // a filter or folder node TiXmlElement *node = LoadXML(libNode); if (node) { std::string type = XMLUtils::GetAttribute(node, "type"); if (type == "filter") { CSmartPlaylist playlist; std::string type, label; XMLUtils::GetString(node, "content", type); if (type.empty()) { CLog::Log(LOGERROR, "<content> tag must not be empty for type=\"filter\" node '%s'", libNode.c_str()); return false; } if (XMLUtils::GetString(node, "label", label)) label = CGUIControlFactory::FilterLabel(label); playlist.SetType(type); playlist.SetName(label); if (playlist.LoadFromXML(node) && CSmartPlaylistDirectory::GetDirectory(playlist, items)) { items.SetProperty("library.filter", "true"); items.SetPath(items.GetProperty("path.db").asString()); return true; } } else if (type == "folder") { std::string path; XMLUtils::GetPath(node, "path", path); if (!path.empty()) { URIUtils::AddSlashAtEnd(path); return CDirectory::GetDirectory(path, items, m_strFileMask, m_flags); } } } return false; } // just a plain node - read the folder for XML nodes and other folders CFileItemList nodes; if (!CDirectory::GetDirectory(libNode, nodes, ".xml", DIR_FLAG_NO_FILE_DIRS)) return false; // iterate over our nodes std::string basePath = url.Get(); for (int i = 0; i < nodes.Size(); i++) { const TiXmlElement *node = NULL; std::string xml = nodes[i]->GetPath(); if (nodes[i]->m_bIsFolder) node = LoadXML(URIUtils::AddFileToFolder(xml, "index.xml")); else { node = LoadXML(xml); if (node && URIUtils::GetFileName(xml) == "index.xml") { // set the label on our items std::string label; if (XMLUtils::GetString(node, "label", label)) label = CGUIControlFactory::FilterLabel(label); items.SetLabel(label); continue; } } if (node) { std::string label, icon; if (XMLUtils::GetString(node, "label", label)) label = CGUIControlFactory::FilterLabel(label); XMLUtils::GetString(node, "icon", icon); int order = 0; node->Attribute("order", &order); // create item URIUtils::RemoveSlashAtEnd(xml); std::string folder = URIUtils::GetFileName(xml); CFileItemPtr item(new CFileItem(URIUtils::AddFileToFolder(basePath, folder), true)); item->SetLabel(label); if (!icon.empty() && g_TextureManager.HasTexture(icon)) item->SetIconImage(icon); item->m_iprogramCount = order; items.Add(item); } } items.Sort(SortByPlaylistOrder, SortOrderAscending); return true; }
/** * This method tries to determine what type of disc is located in the given drive and starts to play the content appropriately. */ bool CAutorun::RunDisc(IDirectory* pDir, const CStdString& strDrive, int& nAddedToPlaylist, bool bRoot, bool bypassSettings /* = false */, bool startFromBeginning /* = false */) { bool bPlaying(false); CFileItemList vecItems; if ( !pDir->GetDirectory( strDrive, vecItems ) ) { return false; } bool bAllowVideo = true; // bool bAllowPictures = true; bool bAllowMusic = true; if (!g_passwordManager.IsMasterLockUnlocked(false)) { bAllowVideo = !g_settings.GetCurrentProfile().videoLocked(); // bAllowPictures = !g_settings.GetCurrentProfile().picturesLocked(); bAllowMusic = !g_settings.GetCurrentProfile().musicLocked(); } // is this a root folder we have to check the content to determine a disc type if( bRoot ) { // check root folders next, for normal structured dvd's for (int i = 0; i < vecItems.Size(); i++) { CFileItemPtr pItem = vecItems[i]; // is the current item a (non system) folder? if (pItem->m_bIsFolder && pItem->GetPath() != "." && pItem->GetPath() != "..") { CStdString name = pItem->GetPath(); URIUtils::RemoveSlashAtEnd(name); name = URIUtils::GetFileName(name); // Check if the current foldername indicates a DVD structure (name is "VIDEO_TS") if (name.Equals("VIDEO_TS") && bAllowVideo && (bypassSettings || g_guiSettings.GetBool("dvds.autorun"))) { CStdString path = URIUtils::AddFileToFolder(pItem->GetPath(), "VIDEO_TS.IFO"); if(!CFile::Exists(path)) path = URIUtils::AddFileToFolder(pItem->GetPath(), "video_ts.ifo"); CFileItem item(path, false); item.SetLabel(g_mediaManager.GetDiskLabel(strDrive)); item.GetVideoInfoTag()->m_strFileNameAndPath = g_mediaManager.GetDiskUniqueId(strDrive); if (!startFromBeginning && !item.GetVideoInfoTag()->m_strFileNameAndPath.IsEmpty()) item.m_lStartOffset = STARTOFFSET_RESUME; g_application.PlayFile(item, false); bPlaying = true; return true; } // Check if the current foldername indicates a Blu-Ray structure (default is "BDMV"). // A BR should also include an "AACS" folder for encryption, Sony-BRs can also include update folders for PS3 (PS3_UPDATE / PS3_VPRM). // ToDo: for the time beeing, the DVD autorun settings are used to determine if the BR should be started automatically. if (name.Equals("BDMV") && bAllowVideo && (bypassSettings || g_guiSettings.GetBool("dvds.autorun"))) { CFileItem item(URIUtils::AddFileToFolder(pItem->GetPath(), "index.bdmv"), false); item.SetLabel(g_mediaManager.GetDiskLabel(strDrive)); item.GetVideoInfoTag()->m_strFileNameAndPath = g_mediaManager.GetDiskUniqueId(strDrive); if (!startFromBeginning && !item.GetVideoInfoTag()->m_strFileNameAndPath.IsEmpty()) item.m_lStartOffset = STARTOFFSET_RESUME; g_application.PlayFile(item, false); bPlaying = true; return true; } // Video CDs can have multiple file formats. First we need to determine which one is used on the CD CStdString strExt; if (name.Equals("MPEGAV")) strExt = ".dat"; if (name.Equals("MPEG2")) strExt = ".mpg"; // If a file format was extracted we are sure this is a VCD. Autoplay if settings indicate we should. if (!strExt.IsEmpty() && bAllowVideo && (bypassSettings || g_guiSettings.GetBool("dvds.autorun"))) { CFileItemList items; CDirectory::GetDirectory(pItem->GetPath(), items, strExt); if (items.Size()) { items.Sort(SORT_METHOD_LABEL, SORT_ORDER_ASC); g_playlistPlayer.ClearPlaylist(PLAYLIST_VIDEO); g_playlistPlayer.Add(PLAYLIST_VIDEO, items); g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_VIDEO); g_playlistPlayer.Play(0); bPlaying = true; return true; } } /* Probably want this if/when we add some automedia action dialog... else if (pItem->GetPath().Find("PICTURES") != -1 && bAllowPictures && (bypassSettings)) { bPlaying = true; CStdString strExec; strExec.Format("XBMC.RecursiveSlideShow(%s)", pItem->GetPath().c_str()); CBuiltins::Execute(strExec); return true; } */ } } } // check video first if (!nAddedToPlaylist && !bPlaying && (bypassSettings || g_guiSettings.GetBool("dvds.autorun"))) { // stack video files CFileItemList tempItems; tempItems.Append(vecItems); if (g_settings.m_videoStacking) tempItems.Stack(); CFileItemList itemlist; for (int i = 0; i < tempItems.Size(); i++) { CFileItemPtr pItem = tempItems[i]; if (!pItem->m_bIsFolder && pItem->IsVideo()) { bPlaying = true; if (pItem->IsStack()) { // TODO: remove this once the app/player is capable of handling stacks immediately CStackDirectory dir; CFileItemList items; dir.GetDirectory(pItem->GetPath(), items); itemlist.Append(items); } else itemlist.Add(pItem); } } if (itemlist.Size()) { if (!bAllowVideo) { if (!bypassSettings) return false; if (g_windowManager.GetActiveWindow() != WINDOW_VIDEO_FILES) if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; } g_playlistPlayer.ClearPlaylist(PLAYLIST_VIDEO); g_playlistPlayer.Add(PLAYLIST_VIDEO, itemlist); g_playlistPlayer.SetCurrentPlaylist(PLAYLIST_VIDEO); g_playlistPlayer.Play(0); } } // then music if (!bPlaying && (bypassSettings || g_guiSettings.GetBool("audiocds.autorun")) && bAllowMusic) { for (int i = 0; i < vecItems.Size(); i++) { CFileItemPtr pItem = vecItems[i]; if (!pItem->m_bIsFolder && pItem->IsAudio()) { nAddedToPlaylist++; g_playlistPlayer.Add(PLAYLIST_MUSIC, pItem); } } } /* Probably want this if/when we add some automedia action dialog... // and finally pictures if (!nAddedToPlaylist && !bPlaying && bypassSettings && bAllowPictures) { for (int i = 0; i < vecItems.Size(); i++) { CFileItemPtr pItem = vecItems[i]; if (!pItem->m_bIsFolder && pItem->IsPicture()) { bPlaying = true; CStdString strExec; strExec.Format("XBMC.RecursiveSlideShow(%s)", strDrive.c_str()); CBuiltins::Execute(strExec); break; } } } */ // check subdirs if we are not playing yet if (!bPlaying) { for (int i = 0; i < vecItems.Size(); i++) { CFileItemPtr pItem = vecItems[i]; if (pItem->m_bIsFolder) { if (pItem->GetPath() != "." && pItem->GetPath() != ".." ) { if (RunDisc(pDir, pItem->GetPath(), nAddedToPlaylist, false, bypassSettings, startFromBeginning)) { bPlaying = true; break; } } } // if (non system) folder } // for all items in directory } // if root folder return bPlaying; }
bool CGUIDialogContextMenu::OnContextButton(const CStdString &type, const CFileItemPtr item, CONTEXT_BUTTON button) { // Add Source doesn't require a valid share if (button == CONTEXT_BUTTON_ADD_SOURCE) { if (g_settings.IsMasterUser()) { if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; } else if (!g_settings.GetCurrentProfile().canWriteSources() && !g_passwordManager.IsProfileLockUnlocked()) return false; return CGUIDialogMediaSource::ShowAndAddMediaSource(type); } // buttons that are available on both sources and autosourced items if (!item) return false; switch (button) { case CONTEXT_BUTTON_EJECT_DRIVE: return g_mediaManager.Eject(item->m_strPath); #ifdef HAS_DVD_DRIVE case CONTEXT_BUTTON_PLAY_DISC: return MEDIA_DETECT::CAutorun::PlayDisc(); case CONTEXT_BUTTON_EJECT_DISC: #ifdef _WIN32 CWIN32Util::ToggleTray(g_mediaManager.TranslateDevicePath(item->m_strPath)[0]); #else CIoSupport::ToggleTray(); #endif #endif return true; default: break; } // the rest of the operations require a valid share CMediaSource *share = GetShare(type, item.get()); if (!share) return false; switch (button) { case CONTEXT_BUTTON_EDIT_SOURCE: if (g_settings.IsMasterUser()) { if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; } else if (!g_passwordManager.IsProfileLockUnlocked()) return false; return CGUIDialogMediaSource::ShowAndEditMediaSource(type, *share); case CONTEXT_BUTTON_REMOVE_SOURCE: { if (g_settings.IsMasterUser()) { if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; } else { if (!g_settings.GetCurrentProfile().canWriteSources() && !g_passwordManager.IsMasterLockUnlocked(false)) return false; if (g_settings.GetCurrentProfile().canWriteSources() && !g_passwordManager.IsProfileLockUnlocked()) return false; } // prompt user if they want to really delete the source if (CGUIDialogYesNo::ShowAndGetInput(751, 0, 750, 0)) { // check default before we delete, as deletion will kill the share object CStdString defaultSource(GetDefaultShareNameByType(type)); if (!defaultSource.IsEmpty()) { if (share->strName.Equals(defaultSource)) ClearDefault(type); } g_settings.DeleteSource(type, share->strName, share->strPath); } return true; } case CONTEXT_BUTTON_SET_DEFAULT: if (g_settings.GetCurrentProfile().canWriteSources() && !g_passwordManager.IsProfileLockUnlocked()) return false; else if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; // make share default SetDefault(type, share->strName); return true; case CONTEXT_BUTTON_CLEAR_DEFAULT: if (g_settings.GetCurrentProfile().canWriteSources() && !g_passwordManager.IsProfileLockUnlocked()) return false; else if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; // remove share default ClearDefault(type); return true; case CONTEXT_BUTTON_SET_THUMB: { if (g_settings.GetCurrentProfile().canWriteSources() && !g_passwordManager.IsProfileLockUnlocked()) return false; else if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; // setup our thumb list CFileItemList items; // add the current thumb, if available if (!share->m_strThumbnailImage.IsEmpty()) { CFileItemPtr current(new CFileItem("thumb://Current", false)); current->SetThumbnailImage(share->m_strThumbnailImage); current->SetLabel(g_localizeStrings.Get(20016)); items.Add(current); } else if (item->HasThumbnail()) { // already have a thumb that the share doesn't know about - must be a local one, so we mayaswell reuse it. CFileItemPtr current(new CFileItem("thumb://Current", false)); current->SetThumbnailImage(item->GetThumbnailImage()); current->SetLabel(g_localizeStrings.Get(20016)); items.Add(current); } // see if there's a local thumb for this item CStdString folderThumb = item->GetFolderThumb(); if (XFILE::CFile::Exists(folderThumb)) { CFileItemPtr local(new CFileItem("thumb://Local", false)); local->SetThumbnailImage(folderThumb); local->SetLabel(g_localizeStrings.Get(20017)); items.Add(local); } // and add a "no thumb" entry as well CFileItemPtr nothumb(new CFileItem("thumb://None", false)); nothumb->SetIconImage(item->GetIconImage()); nothumb->SetLabel(g_localizeStrings.Get(20018)); items.Add(nothumb); CStdString strThumb; VECSOURCES shares; g_mediaManager.GetLocalDrives(shares); if (!CGUIDialogFileBrowser::ShowAndGetImage(items, shares, g_localizeStrings.Get(1030), strThumb)) return false; if (strThumb == "thumb://Current") return true; if (strThumb == "thumb://Local") strThumb = folderThumb; if (strThumb == "thumb://None") strThumb = ""; if (!share->m_ignore) { g_settings.UpdateSource(type,share->strName,"thumbnail",strThumb); g_settings.SaveSources(); } else if (!strThumb.IsEmpty()) { // this is some sort of an auto-share, so we have to cache it based on the criteria we use to retrieve them CStdString cachedThumb; if (type == "music") { cachedThumb = item->m_strPath; URIUtils::RemoveSlashAtEnd(cachedThumb); cachedThumb = CUtil::GetCachedMusicThumb(cachedThumb); } else if (type == "video") cachedThumb = item->GetCachedVideoThumb(); else // assume "programs" { // store the thumb for this share CTextureDatabase db; if (db.Open()) { cachedThumb = CTextureCache::GetUniqueImage(item->m_strPath, URIUtils::GetExtension(strThumb)); db.SetTextureForPath(item->m_strPath, cachedThumb); } } XFILE::CFile::Cache(strThumb, cachedThumb); } CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_UPDATE_SOURCES); g_windowManager.SendThreadMessage(msg); return true; } case CONTEXT_BUTTON_ADD_LOCK: { // prompt user for mastercode when changing lock settings) only for default user if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; CStdString strNewPassword = ""; if (!CGUIDialogLockSettings::ShowAndGetLock(share->m_iLockMode,strNewPassword)) return false; // password entry and re-entry succeeded, write out the lock data share->m_iHasLock = 2; g_settings.UpdateSource(type, share->strName, "lockcode", strNewPassword); strNewPassword.Format("%i",share->m_iLockMode); g_settings.UpdateSource(type, share->strName, "lockmode", strNewPassword); g_settings.UpdateSource(type, share->strName, "badpwdcount", "0"); g_settings.SaveSources(); CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_UPDATE_SOURCES); g_windowManager.SendThreadMessage(msg); return true; } case CONTEXT_BUTTON_RESET_LOCK: { // prompt user for profile lock when changing lock settings if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; g_settings.UpdateSource(type, share->strName, "badpwdcount", "0"); g_settings.SaveSources(); CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_UPDATE_SOURCES); g_windowManager.SendThreadMessage(msg); return true; } case CONTEXT_BUTTON_REMOVE_LOCK: { if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; if (!CGUIDialogYesNo::ShowAndGetInput(12335, 0, 750, 0)) return false; share->m_iHasLock = 0; g_settings.UpdateSource(type, share->strName, "lockmode", "0"); g_settings.UpdateSource(type, share->strName, "lockcode", "0"); g_settings.UpdateSource(type, share->strName, "badpwdcount", "0"); g_settings.SaveSources(); CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_UPDATE_SOURCES); g_windowManager.SendThreadMessage(msg); return true; } case CONTEXT_BUTTON_REACTIVATE_LOCK: { bool maxRetryExceeded = false; if (g_guiSettings.GetInt("masterlock.maxretries") != 0) maxRetryExceeded = (share->m_iBadPwdCount >= g_guiSettings.GetInt("masterlock.maxretries")); if (!maxRetryExceeded) { // don't prompt user for mastercode when reactivating a lock g_passwordManager.LockSource(type, share->strName, true); return true; } return false; } case CONTEXT_BUTTON_CHANGE_LOCK: { if (!g_passwordManager.IsMasterLockUnlocked(true)) return false; CStdString strNewPW; CStdString strNewLockMode; if (CGUIDialogLockSettings::ShowAndGetLock(share->m_iLockMode,strNewPW)) strNewLockMode.Format("%i",share->m_iLockMode); else return false; // password ReSet and re-entry succeeded, write out the lock data g_settings.UpdateSource(type, share->strName, "lockcode", strNewPW); g_settings.UpdateSource(type, share->strName, "lockmode", strNewLockMode); g_settings.UpdateSource(type, share->strName, "badpwdcount", "0"); g_settings.SaveSources(); CGUIMessage msg(GUI_MSG_NOTIFY_ALL,0,0,GUI_MSG_UPDATE_SOURCES); g_windowManager.SendThreadMessage(msg); return true; } default: break; } return false; }
// NB: The rar manager expects paths in rars to be terminated with a "\". bool CRarManager::GetFilesInRar(CFileItemList& vecpItems, const std::string& strRarPath, bool bMask, const std::string& strPathInRar) { #ifdef HAS_FILESYSTEM_RAR CSingleLock lock(m_CritSection); ArchiveList_struct* pFileList = NULL; map<std::string,pair<ArchiveList_struct*,vector<CFileInfo> > >::iterator it = m_ExFiles.find(strRarPath); if (it == m_ExFiles.end()) { if( urarlib_list((char*) strRarPath.c_str(), &pFileList, NULL) ) m_ExFiles.insert(make_pair(strRarPath,make_pair(pFileList,vector<CFileInfo>()))); else { if( pFileList ) urarlib_freelist(pFileList); return false; } } else pFileList = it->second.first; CFileItemPtr pFileItem; vector<std::string> vec; set<std::string> dirSet; StringUtils::Tokenize(strPathInRar,vec,"/"); unsigned int iDepth = vec.size(); ArchiveList_struct* pIterator; std::string strCompare = strPathInRar; if (!URIUtils::HasSlashAtEnd(strCompare) && !strCompare.empty()) strCompare += '/'; for( pIterator = pFileList; pIterator ; pIterator ? pIterator = pIterator->next : NULL) { std::string strName; /* convert to utf8 */ if( pIterator->item.NameW && wcslen(pIterator->item.NameW) > 0) g_charsetConverter.wToUTF8(pIterator->item.NameW, strName); else g_charsetConverter.unknownToUTF8(pIterator->item.Name, strName); /* replace back slashes into forward slashes */ /* this could get us into troubles, file could two different files, one with / and one with \ */ StringUtils::Replace(strName, '\\', '/'); if (bMask) { if (!strstr(strName.c_str(),strCompare.c_str())) continue; vec.clear(); StringUtils::Tokenize(strName,vec,"/"); if (vec.size() < iDepth) continue; } unsigned int iMask = (pIterator->item.HostOS==3 ? 0x0040000:16); // win32 or unix attribs? if (((pIterator->item.FileAttr & iMask) == iMask) || (vec.size() > iDepth+1 && bMask)) // we have a directory { if (!bMask) continue; if (vec.size() == iDepth) continue; // remove root of listing if (dirSet.find(vec[iDepth]) == dirSet.end()) { dirSet.insert(vec[iDepth]); pFileItem.reset(new CFileItem(vec[iDepth])); pFileItem->SetPath(vec[iDepth] + '/'); pFileItem->m_bIsFolder = true; pFileItem->m_idepth = pIterator->item.Method; pFileItem->m_iDriveType = pIterator->item.HostOS; //pFileItem->m_lEndOffset = long(pIterator->item.iOffset); } } else { if (vec.size() == iDepth+1 || !bMask) { if (vec.size() == 0) pFileItem.reset(new CFileItem(strName)); else pFileItem.reset(new CFileItem(vec[iDepth])); pFileItem->SetPath(strName.c_str()+strPathInRar.size()); pFileItem->m_dwSize = pIterator->item.UnpSize; pFileItem->m_idepth = pIterator->item.Method; pFileItem->m_iDriveType = pIterator->item.HostOS; //pFileItem->m_lEndOffset = long(pIterator->item.iOffset); } } if (pFileItem) vecpItems.Add(pFileItem); pFileItem.reset(); } return vecpItems.Size() > 0; #else return false; #endif }
bool CZeroconfDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items) { assert(strPath.substr(0, 11) == "zeroconf://"); CStdString path = strPath.substr(11, strPath.length()); URIUtils::RemoveSlashAtEnd(path); if(path.empty()) { std::vector<CZeroconfBrowser::ZeroconfService> found_services = CZeroconfBrowser::GetInstance()->GetFoundServices(); for(std::vector<CZeroconfBrowser::ZeroconfService>::iterator it = found_services.begin(); it != found_services.end(); ++it) { //only use discovered services we can connect to through directory CStdString tmp; if(GetXBMCProtocol(it->GetType(), tmp)) { CFileItemPtr item(new CFileItem("", true)); CURL url; url.SetProtocol("zeroconf"); CStdString service_path = CZeroconfBrowser::ZeroconfService::toPath(*it); CURL::Encode(service_path); url.SetFileName(service_path); item->SetPath(url.Get()); //now do the formatting CStdString protocol = GetHumanReadableProtocol(it->GetType()); item->SetLabel(it->GetName() + " (" + protocol + ")"); item->SetLabelPreformated(true); //just set the default folder icon item->FillInDefaultIcon(); items.Add(item); } } return true; } else { //decode the path first CStdString decoded = path; CURL::Decode(decoded); try { CZeroconfBrowser::ZeroconfService zeroconf_service = CZeroconfBrowser::ZeroconfService::fromPath(decoded); if(!CZeroconfBrowser::GetInstance()->ResolveService(zeroconf_service)) { CLog::Log(LOGINFO, "CZeroconfDirectory::GetDirectory service ( %s ) could not be resolved in time", zeroconf_service.GetName().c_str()); return false; } else { assert(!zeroconf_service.GetIP().empty()); CURL service; service.SetPort(zeroconf_service.GetPort()); service.SetHostName(zeroconf_service.GetIP()); //do protocol conversion (_smb._tcp -> smb) //ToDo: try automatic conversion -> remove leading '_' and '._tcp'? CStdString protocol; if(!GetXBMCProtocol(zeroconf_service.GetType(), protocol)) { CLog::Log(LOGERROR, "CZeroconfDirectory::GetDirectory Unknown service type (%s), skipping; ", zeroconf_service.GetType().c_str()); return false; } service.SetProtocol(protocol); //first try to show the txt-record defined path if any if(GetDirectoryFromTxtRecords(zeroconf_service, service, items)) { return true; } else//no txt record path - so let the CDirectory handler show the folders { return CDirectory::GetDirectory(service.Get(), items, "", DIR_FLAG_ALLOW_PROMPT); } } } catch (std::runtime_error& e) { CLog::Log(LOGERROR, "CZeroconfDirectory::GetDirectory failed getting directory: '%s'. Error: '%s'", decoded.c_str(), e.what()); return false; } } }