bool CGUIDialogSmartPlaylistEditor::EditPlaylist(const std::string &path, const std::string &type) { CGUIDialogSmartPlaylistEditor *editor = (CGUIDialogSmartPlaylistEditor *)g_windowManager.GetWindow(WINDOW_DIALOG_SMART_PLAYLIST_EDITOR); if (!editor) return false; editor->m_mode = type; if (URIUtils::PathEquals(path, CProfilesManager::GetInstance().GetUserDataItem("PartyMode.xsp"))) editor->m_mode = "partymusic"; if (URIUtils::PathEquals(path, CProfilesManager::GetInstance().GetUserDataItem("PartyMode-Video.xsp"))) editor->m_mode = "partyvideo"; CSmartPlaylist playlist; bool loaded(playlist.Load(path)); if (!loaded) { // failed to load if (!StringUtils::StartsWithNoCase(editor->m_mode, "party")) return false; // only edit normal playlists that exist // party mode playlists can be editted even if they don't exist playlist.SetType(editor->m_mode == "partymusic" ? "songs" : "musicvideos"); } editor->m_playlist = playlist; editor->m_path = path; editor->Initialize(); editor->Open(); return !editor->m_cancelled; }
std::string CSmartPlaylistDirectory::GetPlaylistByName(const std::string& name, const std::string& playlistType) { CFileItemList list; bool filesExist = false; if (CSmartPlaylist::IsMusicType(playlistType)) filesExist = CDirectory::GetDirectory("special://musicplaylists/", list, ".xsp", false); else // all others are video filesExist = CDirectory::GetDirectory("special://videoplaylists/", list, ".xsp", false); if (filesExist) { for (int i = 0; i < list.Size(); i++) { CFileItemPtr item = list[i]; CSmartPlaylist playlist; if (playlist.OpenAndReadName(item->GetURL())) { if (StringUtils::EqualsNoCase(playlist.GetName(), name)) return item->GetPath(); } } for (int i = 0; i < list.Size(); i++) { // check based on filename CFileItemPtr item = list[i]; if (URIUtils::GetFileName(item->GetPath()) == name) { // found :) return item->GetPath(); } } } return ""; }
bool CGUIWindowMusicBase::GetDirectory(const CStdString &strDirectory, CFileItemList &items) { CStdString directory = strDirectory; // check if the path contains a filter and if so load it and // remove it from the path to get proper GUI view states etc CSmartPlaylist filterXsp; CMusicDbUrl musicUrl; if (musicUrl.FromString(strDirectory)) { CVariant filter; if (musicUrl.GetOption("filter", filter)) { // load the filter and if it's type does not match the // path's item type reset it if (filterXsp.LoadFromJson(filter.asString()) && !filterXsp.GetType().Equals(musicUrl.GetType().c_str())) filterXsp.Reset(); // remove the "filter" option from the path musicUrl.AddOption("filter", ""); } directory = musicUrl.ToString(); } items.SetArt("thumb", ""); bool bResult = CGUIMediaWindow::GetDirectory(directory, items); if (bResult) CMusicThumbLoader::FillThumb(items); // (re-)apply the previously retrieved filter // because it was reset in CGUIMediaWindow::GetDirectory() if (!filterXsp.IsEmpty()) m_filter = filterXsp; // 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(g_settings.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->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->SetLabelPreformated(true); newPlaylist->SetSpecialSort(SortSpecialOnBottom); newPlaylist->SetCanQueue(false); items.Add(newPlaylist); } return bResult; }
CStdString CSmartPlaylistDirectory::GetPlaylistByName(const CStdString& name, const CStdString& playlistType) { CFileItemList list; bool filesExist = false; if (playlistType == "songs" || playlistType == "albums") filesExist = CDirectory::GetDirectory("special://musicplaylists/", list, ".xsp", false); else // all others are video filesExist = CDirectory::GetDirectory("special://videoplaylists/", list, ".xsp", false); if (filesExist) { for (int i = 0; i < list.Size(); i++) { CFileItemPtr item = list[i]; CSmartPlaylist playlist; if (playlist.OpenAndReadName(item->GetPath())) { if (playlist.GetName().CompareNoCase(name) == 0) return item->GetPath(); } } for (int i = 0; i < list.Size(); i++) { // check based on filename CFileItemPtr item = list[i]; if (URIUtils::GetFileName(item->GetPath()) == name) { // found :) return item->GetPath(); } } } return ""; }
bool CGUIDialogSmartPlaylistEditor::EditPlaylist(const CStdString &path, const CStdString &type) { CGUIDialogSmartPlaylistEditor *editor = (CGUIDialogSmartPlaylistEditor *)g_windowManager.GetWindow(WINDOW_DIALOG_SMART_PLAYLIST_EDITOR); if (!editor) return false; editor->m_mode = type; if (path.Equals(g_settings.GetUserDataItem("PartyMode.xsp"))) editor->m_mode = "partymusic"; if (path.Equals(g_settings.GetUserDataItem("PartyMode-Video.xsp"))) editor->m_mode = "partyvideo"; CSmartPlaylist playlist; bool loaded(playlist.Load(path)); if (!loaded) { // failed to load if (!editor->m_mode.Left(5).Equals("party")) return false; // only edit normal playlists that exist // party mode playlists can be editted even if they don't exist playlist.m_ruleCombination.m_rules.push_back(CSmartPlaylistRule()); playlist.SetType(editor->m_mode == "partymusic" ? "songs" : "musicvideos"); } editor->m_playlist = playlist; if (editor->m_playlist.m_ruleCombination.m_rules.size() <= 0) editor->m_playlist.m_ruleCombination.m_rules.push_back(CSmartPlaylistRule()); editor->m_path = path; editor->Initialize(); editor->DoModal(g_windowManager.GetActiveWindow()); return !editor->m_cancelled; }
bool CSmartPlaylistDirectory::GetDirectory(const CStdString& strPath, CFileItemList& items) { // Load in the SmartPlaylist and get the WHERE query CSmartPlaylist playlist; if (!playlist.Load(strPath)) return false; return GetDirectory(playlist, items); }
bool CSmartPlaylistDirectory::GetDirectory(const CURL& url, CFileItemList& items) { // Load in the SmartPlaylist and get the WHERE query CSmartPlaylist playlist; if (!playlist.Load(url)) return false; bool result = GetDirectory(playlist, items); if (result) items.SetProperty("library.smartplaylist", true); return result; }
bool CSmartPlaylistFileItemListModifier::Modify(CFileItemList &items) const { if (items.HasProperty(PROPERTY_SORT_ORDER)) return false; std::string xspOption = GetUrlOption(items.GetPath(), URL_OPTION_XSP); if (xspOption.empty()) return false; // check for smartplaylist-specific sorting information CSmartPlaylist xsp; if (!xsp.LoadFromJson(xspOption)) return false; items.SetProperty(PROPERTY_SORT_ORDER, (int)xsp.GetOrder()); items.SetProperty(PROPERTY_SORT_ASCENDING, xsp.GetOrderDirection() == SortOrderAscending); return true; }
bool CMusicDbUrl::validateOption(const std::string &key, const CVariant &value) { if (!CDbUrl::validateOption(key, value)) return false; // if the value is empty it will remove the option which is ok // otherwise we only care about the "filter" option here if (value.empty() || !StringUtils::EqualsNoCase(key, "filter")) return true; if (!value.isString()) return false; CSmartPlaylist xspFilter; if (!xspFilter.LoadFromJson(value.asString())) return false; // check if the filter playlist matches the item type return xspFilter.GetType() == m_type; }
CStdString CSmartPlaylist::GetWhereClause(CDatabase &db, set<CStdString> &referencedPlaylists, bool needWhere /* = true */) { CStdString rule, currentRule; for (vector<CSmartPlaylistRule>::iterator it = m_playlistRules.begin(); it != m_playlistRules.end(); ++it) { if (it != m_playlistRules.begin()) rule += m_matchAllRules ? " AND " : " OR "; else if (needWhere) rule += "WHERE "; rule += "("; CStdString currentRule; if (it->m_field == CSmartPlaylistRule::FIELD_PLAYLIST) { CStdString playlistFile = CSmartPlaylistDirectory::GetPlaylistByName(it->m_parameter, GetType()); if (!playlistFile.IsEmpty() && referencedPlaylists.find(playlistFile) == referencedPlaylists.end()) { referencedPlaylists.insert(playlistFile); CSmartPlaylist playlist; playlist.Load(playlistFile); CStdString playlistQuery; // only playlists of same type will be part of the query if (playlist.GetType().Equals(GetType()) || (playlist.GetType().Equals("mixed") && (GetType() == "songs" || GetType() == "musicvideos")) || playlist.GetType().IsEmpty()) { playlist.SetType(GetType()); playlistQuery = playlist.GetWhereClause(db, referencedPlaylists, false); } if (playlist.GetType().Equals(GetType())) { if (it->m_operator == CSmartPlaylistRule::OPERATOR_DOES_NOT_EQUAL) currentRule.Format("NOT (%s)", playlistQuery.c_str()); else currentRule = playlistQuery; } } } else currentRule = (*it).GetWhereClause(db, GetType()); // if we don't get a rule, we add '1' or '0' so the query is still valid and doesn't fail if (currentRule.IsEmpty()) currentRule = m_matchAllRules ? "'1'" : "'0'"; rule += currentRule; rule += ")"; } return rule; }
void CGUIDialogSmartPlaylistRule::OnBrowse() { CFileItemList items; CMusicDatabase database; database.Open(); CVideoDatabase videodatabase; videodatabase.Open(); VIDEODB_CONTENT_TYPE type = VIDEODB_CONTENT_MOVIES; if (m_type.Equals("tvshows")) type = VIDEODB_CONTENT_TVSHOWS; else if (m_type.Equals("musicvideos")) type = VIDEODB_CONTENT_MUSICVIDEOS; else if (m_type.Equals("episodes")) type = VIDEODB_CONTENT_EPISODES; int iLabel = 0; if (m_rule.m_field == FieldGenre) { if (m_type.Equals("tvshows") || m_type.Equals("episodes") || m_type.Equals("movies")) videodatabase.GetGenresNav("videodb://2/1/",items,type); else if (m_type.Equals("songs") || m_type.Equals("albums") || m_type.Equals("artists") || m_type.Equals("mixed")) database.GetGenresNav("musicdb://1/",items); if (m_type.Equals("musicvideos") || m_type.Equals("mixed")) { CFileItemList items2; videodatabase.GetGenresNav("videodb://3/1/",items2,VIDEODB_CONTENT_MUSICVIDEOS); items.Append(items2); } iLabel = 515; } else if (m_rule.m_field == FieldCountry) { videodatabase.GetCountriesNav("videodb://2/1/",items,type); iLabel = 574; } else if (m_rule.m_field == FieldArtist || m_rule.m_field == FieldAlbumArtist) { if (m_type.Equals("songs") || m_type.Equals("mixed") || m_type.Equals("albums") || m_type.Equals("artists")) database.GetArtistsNav("musicdb://2/", items, m_rule.m_field == FieldAlbumArtist, -1); if (m_type.Equals("musicvideos") || m_type.Equals("mixed")) { CFileItemList items2; videodatabase.GetMusicVideoArtistsByName("",items2); items.Append(items2); } iLabel = 557; } else if (m_rule.m_field == FieldAlbum) { if (m_type.Equals("songs") || m_type.Equals("mixed") || m_type.Equals("albums")) database.GetAlbumsNav("musicdb://3/", items); if (m_type.Equals("musicvideos") || m_type.Equals("mixed")) { CFileItemList items2; videodatabase.GetMusicVideoAlbumsByName("",items2); items.Append(items2); } iLabel = 558; } else if (m_rule.m_field == FieldActor) { videodatabase.GetActorsNav("",items,type); iLabel = 20337; } else if (m_rule.m_field == FieldYear) { if (m_type.Equals("songs") || m_type.Equals("mixed") || m_type.Equals("albums")) database.GetYearsNav("musicdb://9/", items); if (!m_type.Equals("songs") && !m_type.Equals("albums")) { CFileItemList items2; videodatabase.GetYearsNav("", items2, type); items.Append(items2); } iLabel = 562; } else if (m_rule.m_field == FieldDirector) { videodatabase.GetDirectorsNav("",items,type); iLabel = 20339; } else if (m_rule.m_field == FieldStudio) { videodatabase.GetStudiosNav("",items,type); iLabel = 572; } else if (m_rule.m_field == FieldWriter) { videodatabase.GetWritersNav("",items,type); iLabel = 20417; } else if (m_rule.m_field == FieldTvShowTitle) { videodatabase.GetTvShowsNav("videodb://2/2/",items); iLabel = 20343; } else if (m_rule.m_field == FieldPlaylist) { // use filebrowser to grab another smart playlist // Note: This can cause infinite loops (playlist that refers to the same playlist) but I don't // think there's any decent way to deal with this, as the infinite loop may be an arbitrary // number of playlists deep, eg playlist1 -> playlist2 -> playlist3 ... -> playlistn -> playlist1 CStdString path = "special://videoplaylists/"; if (m_type.Equals("songs") || m_type.Equals("albums")) path = "special://musicplaylists/"; XFILE::CDirectory::GetDirectory(path, items, ".xsp", XFILE::DIR_FLAG_NO_FILE_DIRS); for (int i = 0; i < items.Size(); i++) { CFileItemPtr item = items[i]; CSmartPlaylist playlist; if (playlist.OpenAndReadName(item->GetPath())) item->SetLabel(playlist.GetName()); } iLabel = 559; } else if (m_rule.m_field == FieldPath) { VECSOURCES sources; if (m_type == "songs" || m_type == "mixed") sources = *g_settings.GetSourcesFromType("music"); if (m_type != "songs") { VECSOURCES sources2 = *g_settings.GetSourcesFromType("video"); sources.insert(sources.end(),sources2.begin(),sources2.end()); } g_mediaManager.GetLocalDrives(sources); CStdString path = m_rule.GetLocalizedParameter(m_type); CGUIDialogFileBrowser::ShowAndGetDirectory(sources, g_localizeStrings.Get(657), path, false); if (m_rule.m_parameter.size() > 0) m_rule.m_parameter.clear(); if (!path.empty()) m_rule.m_parameter.push_back(path); UpdateButtons(); return; } else if (m_rule.m_field == FieldSet) { videodatabase.GetSetsNav("videodb://1/7/", items, VIDEODB_CONTENT_MOVIES); iLabel = 20434; } else if (m_rule.m_field == FieldTag) { if (m_type == "movies") videodatabase.GetTagsNav("videodb://1/9/", items, VIDEODB_CONTENT_MOVIES); else return; iLabel = 20459; } else { // TODO: Add browseability in here. assert(false); } // sort the items items.Sort(SORT_METHOD_LABEL, SortOrderAscending); CGUIDialogSelect* pDialog = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT); pDialog->Reset(); pDialog->SetItems(&items); CStdString strHeading; strHeading.Format(g_localizeStrings.Get(13401),g_localizeStrings.Get(iLabel)); pDialog->SetHeading(strHeading); pDialog->SetMultiSelection(true); if (!m_rule.m_parameter.empty()) pDialog->SetSelected(m_rule.m_parameter); pDialog->DoModal(); if (pDialog->IsConfirmed()) { const CFileItemList &items = pDialog->GetSelectedItems(); m_rule.m_parameter.clear(); for (int index = 0; index < items.Size(); index++) m_rule.m_parameter.push_back(items[index]->GetLabel()); UpdateButtons(); } pDialog->Reset(); }
void CGUIDialogSmartPlaylistRule::OnBrowse() { CFileItemList items; CMusicDatabase database; database.Open(); CVideoDatabase videodatabase; videodatabase.Open(); std::string basePath; if (CSmartPlaylist::IsMusicType(m_type)) basePath = "musicdb://"; else basePath = "videodb://"; VIDEODB_CONTENT_TYPE type = VIDEODB_CONTENT_MOVIES; if (m_type == "movies") basePath += "movies/"; else if (m_type == "tvshows") { type = VIDEODB_CONTENT_TVSHOWS; basePath += "tvshows/"; } else if (m_type == "musicvideos") { type = VIDEODB_CONTENT_MUSICVIDEOS; basePath += "musicvideos/"; } else if (m_type == "episodes") { if (m_rule.m_field == FieldGenre || m_rule.m_field == FieldYear || m_rule.m_field == FieldStudio) type = VIDEODB_CONTENT_TVSHOWS; else type = VIDEODB_CONTENT_EPISODES; basePath += "tvshows/"; } int iLabel = 0; if (m_rule.m_field == FieldGenre) { if (m_type == "tvshows" || m_type == "episodes" || m_type == "movies") videodatabase.GetGenresNav(basePath + "genres/", items, type); else if (m_type == "songs" || m_type == "albums" || m_type == "artists" || m_type == "mixed") database.GetGenresNav("musicdb://genres/",items); if (m_type == "musicvideos" || m_type == "mixed") { CFileItemList items2; videodatabase.GetGenresNav("videodb://musicvideos/genres/",items2,VIDEODB_CONTENT_MUSICVIDEOS); items.Append(items2); } iLabel = 515; } else if (m_rule.m_field == FieldCountry) { videodatabase.GetCountriesNav(basePath, items, type); iLabel = 574; } else if (m_rule.m_field == FieldArtist || m_rule.m_field == FieldAlbumArtist) { if (CSmartPlaylist::IsMusicType(m_type)) database.GetArtistsNav("musicdb://artists/", items, m_rule.m_field == FieldAlbumArtist, -1); if (m_type == "musicvideos" || m_type == "mixed") { CFileItemList items2; videodatabase.GetMusicVideoArtistsByName("", items2); items.Append(items2); } iLabel = 557; } else if (m_rule.m_field == FieldAlbum) { if (CSmartPlaylist::IsMusicType(m_type)) database.GetAlbumsNav("musicdb://albums/", items); if (m_type == "musicvideos" || m_type == "mixed") { CFileItemList items2; videodatabase.GetMusicVideoAlbumsByName("", items2); items.Append(items2); } iLabel = 558; } else if (m_rule.m_field == FieldActor) { videodatabase.GetActorsNav(basePath + "actors/",items,type); iLabel = 20337; } else if (m_rule.m_field == FieldYear) { if (CSmartPlaylist::IsMusicType(m_type)) database.GetYearsNav("musicdb://years/", items); if (CSmartPlaylist::IsVideoType(m_type)) { CFileItemList items2; videodatabase.GetYearsNav(basePath + "years/", items2, type); items.Append(items2); } iLabel = 562; } else if (m_rule.m_field == FieldDirector) { videodatabase.GetDirectorsNav(basePath + "directors/", items, type); iLabel = 20339; } else if (m_rule.m_field == FieldStudio) { videodatabase.GetStudiosNav(basePath + "studios/", items, type); iLabel = 572; } else if (m_rule.m_field == FieldWriter) { videodatabase.GetWritersNav(basePath, items, type); iLabel = 20417; } else if (m_rule.m_field == FieldTvShowTitle || (m_type == "tvshows" && m_rule.m_field == FieldTitle)) { videodatabase.GetTvShowsNav(basePath + "titles/", items); iLabel = 20343; } else if (m_rule.m_field == FieldTitle) { if (m_type == "songs" || m_type == "mixed") { database.GetSongsNav("musicdb://songs/", items, -1, -1, -1); iLabel = 134; } if (m_type == "movies") { videodatabase.GetMoviesNav(basePath + "titles/", items); iLabel = 20342; } if (m_type == "episodes") { videodatabase.GetEpisodesNav(basePath + "titles/-1/-1/", items); // we need to replace the db label (<season>x<episode> <title>) with the title only CLabelFormatter format("%T", ""); for (int i = 0; i < items.Size(); i++) format.FormatLabel(items[i].get()); iLabel = 20360; } if (m_type == "musicvideos" || m_type == "mixed") { videodatabase.GetMusicVideosNav(basePath + "titles/", items); iLabel = 20389; } } else if (m_rule.m_field == FieldPlaylist || m_rule.m_field == FieldVirtualFolder) { // use filebrowser to grab another smart playlist // Note: This can cause infinite loops (playlist that refers to the same playlist) but I don't // think there's any decent way to deal with this, as the infinite loop may be an arbitrary // number of playlists deep, eg playlist1 -> playlist2 -> playlist3 ... -> playlistn -> playlist1 if (CSmartPlaylist::IsVideoType(m_type)) XFILE::CDirectory::GetDirectory("special://videoplaylists/", items, ".xsp", XFILE::DIR_FLAG_NO_FILE_DIRS); if (CSmartPlaylist::IsMusicType(m_type)) { CFileItemList items2; XFILE::CDirectory::GetDirectory("special://musicplaylists/", items2, ".xsp", XFILE::DIR_FLAG_NO_FILE_DIRS); items.Append(items2); } for (int i = 0; i < items.Size(); i++) { CFileItemPtr item = items[i]; CSmartPlaylist playlist; // don't list unloadable smartplaylists or any referencable smartplaylists // which do not match the type of the current smartplaylist if (!playlist.Load(item->GetPath()) || (m_rule.m_field == FieldPlaylist && (!CSmartPlaylist::CheckTypeCompatibility(m_type, playlist.GetType()) || (!playlist.GetGroup().empty() || playlist.IsGroupMixed())))) { items.Remove(i); i -= 1; continue; } if (!playlist.GetName().empty()) item->SetLabel(playlist.GetName()); } iLabel = 559; } else if (m_rule.m_field == FieldPath) { VECSOURCES sources; if (m_type == "songs" || m_type == "mixed") sources = *CMediaSourceSettings::GetInstance().GetSources("music"); if (CSmartPlaylist::IsVideoType(m_type)) { VECSOURCES sources2 = *CMediaSourceSettings::GetInstance().GetSources("video"); sources.insert(sources.end(),sources2.begin(),sources2.end()); } g_mediaManager.GetLocalDrives(sources); std::string path = m_rule.GetParameter(); CGUIDialogFileBrowser::ShowAndGetDirectory(sources, g_localizeStrings.Get(657), path, false); if (m_rule.m_parameter.size() > 0) m_rule.m_parameter.clear(); if (!path.empty()) m_rule.m_parameter.push_back(path); UpdateButtons(); return; } else if (m_rule.m_field == FieldSet) { videodatabase.GetSetsNav("videodb://movies/sets/", items, VIDEODB_CONTENT_MOVIES); iLabel = 20434; } else if (m_rule.m_field == FieldTag) { VIDEODB_CONTENT_TYPE type = VIDEODB_CONTENT_MOVIES; if (m_type == "tvshows" || m_type == "episodes") type = VIDEODB_CONTENT_TVSHOWS; else if (m_type == "musicvideos") type = VIDEODB_CONTENT_MUSICVIDEOS; else if (m_type != "movies") return; videodatabase.GetTagsNav(basePath + "tags/", items, type); iLabel = 20459; } else { // TODO: Add browseability in here. assert(false); } // sort the items items.Sort(SortByLabel, SortOrderAscending, CSettings::GetInstance().GetBool(CSettings::SETTING_FILELISTS_IGNORETHEWHENSORTING) ? SortAttributeIgnoreArticle : SortAttributeNone); CGUIDialogSelect* pDialog = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT); pDialog->Reset(); pDialog->SetItems(&items); std::string strHeading = StringUtils::Format(g_localizeStrings.Get(13401).c_str(), g_localizeStrings.Get(iLabel).c_str()); pDialog->SetHeading(CVariant{std::move(strHeading)}); pDialog->SetMultiSelection(m_rule.m_field != FieldPlaylist && m_rule.m_field != FieldVirtualFolder); if (!m_rule.m_parameter.empty()) pDialog->SetSelected(m_rule.m_parameter); pDialog->Open(); if (pDialog->IsConfirmed()) { m_rule.m_parameter.clear(); for (int i : pDialog->GetSelectedItems()) m_rule.m_parameter.push_back(items.Get(i)->GetLabel()); UpdateButtons(); } pDialog->Reset(); }
bool CSmartPlaylistDirectory::GetDirectory(const CStdString& strPath, CFileItemList& items) { // Load in the SmartPlaylist and get the WHERE query CSmartPlaylist playlist; if (!playlist.Load(strPath)) return false; bool success = false, success2 = false; if (playlist.GetType().Equals("tvshows")) { CVideoDatabase db; db.Open(); CStdString whereOrder = playlist.GetWhereClause(db) + " " + playlist.GetOrderClause(db); success = db.GetTvShowsByWhere("videodb://2/2/", whereOrder, items); items.SetContent("tvshows"); db.Close(); } else if (playlist.GetType().Equals("episodes")) { CVideoDatabase db; db.Open(); CStdString whereOrder = playlist.GetWhereClause(db) + " " + playlist.GetOrderClause(db); success = db.GetEpisodesByWhere("videodb://2/2/", whereOrder, items); items.SetContent("episodes"); db.Close(); } else if (playlist.GetType().Equals("movies")) { CVideoDatabase db; db.Open(); success = db.GetMoviesByWhere("videodb://1/2/", playlist.GetWhereClause(db), playlist.GetOrderClause(db), items, true); items.SetContent("movies"); db.Close(); } else if (playlist.GetType().Equals("albums")) { CMusicDatabase db; db.Open(); success = db.GetAlbumsByWhere("musicdb://3/", playlist.GetWhereClause(db), playlist.GetOrderClause(db), items); items.SetContent("albums"); db.Close(); } if (playlist.GetType().Equals("songs") || playlist.GetType().Equals("mixed") || playlist.GetType().IsEmpty()) { CMusicDatabase db; db.Open(); CStdString type=playlist.GetType(); if (type.IsEmpty()) type = "songs"; if (playlist.GetType().Equals("mixed")) playlist.SetType("songs"); CStdString whereOrder = playlist.GetWhereClause(db) + " " + playlist.GetOrderClause(db); success = db.GetSongsByWhere("", whereOrder, items); items.SetContent("songs"); db.Close(); playlist.SetType(type); } if (playlist.GetType().Equals("musicvideos") || playlist.GetType().Equals("mixed")) { CVideoDatabase db; db.Open(); CStdString type=playlist.GetType(); if (playlist.GetType().Equals("mixed")) playlist.SetType("musicvideos"); CStdString whereOrder = playlist.GetWhereClause(db) + " " + playlist.GetOrderClause(db); CFileItemList items2; success2 = db.GetMusicVideosByWhere("videodb://3/2/", whereOrder, items2, false); // TODO: SMARTPLAYLISTS Don't check locks??? db.Close(); items.Append(items2); if (items2.Size()) items.SetContent("musicvideos"); playlist.SetType(type); } // go through and set the playlist order for (int i = 0; i < items.Size(); i++) { CFileItemPtr item = items[i]; item->m_iprogramCount = i; // hack for playlist order } if (playlist.GetType().Equals("mixed")) return success || success2; else if (playlist.GetType().Equals("musicvideos")) return success2; else return success; }
bool CPartyModeManager::Enable(PartyModeContext context /*= PARTYMODECONTEXT_MUSIC*/, const CStdString& strXspPath /*= ""*/) { // Filter using our PartyMode xml file CSmartPlaylist playlist; CStdString partyModePath; bool playlistLoaded; m_bIsVideo = context == PARTYMODECONTEXT_VIDEO; if (!strXspPath.IsEmpty()) //if a path to a smartplaylist is supplied use it partyModePath = strXspPath; else if (m_bIsVideo) partyModePath = g_settings.GetUserDataItem("PartyMode-Video.xsp"); else partyModePath = g_settings.GetUserDataItem("PartyMode.xsp"); playlistLoaded=playlist.Load(partyModePath); if ( playlistLoaded ) { m_type = playlist.GetType(); if (context == PARTYMODECONTEXT_UNKNOWN) { //get it from the xsp file m_bIsVideo = (m_type.Equals("video") || m_type.Equals("musicvideos") || m_type.Equals("mixed")); } if (m_type.Equals("mixed")) playlist.SetType("songs"); if (m_type.Equals("mixed")) playlist.SetType("video"); playlist.SetType(m_type); } else { m_strCurrentFilterMusic.Empty(); m_strCurrentFilterVideo.Empty(); m_type = m_bIsVideo ? "musicvideos" : "songs"; } CGUIDialogProgress* pDialog = (CGUIDialogProgress*)g_windowManager.GetWindow(WINDOW_DIALOG_PROGRESS); int iHeading = (m_bIsVideo ? 20250 : 20121); int iLine0 = (m_bIsVideo ? 20251 : 20123); pDialog->SetHeading(iHeading); pDialog->SetLine(0, iLine0); pDialog->SetLine(1, ""); pDialog->SetLine(2, ""); pDialog->StartModal(); ClearState(); unsigned int time = XbmcThreads::SystemClockMillis(); vector< pair<int,int> > songIDs; if (m_type.Equals("songs") || m_type.Equals("mixed")) { CMusicDatabase db; if (db.Open()) { set<CStdString> playlists; if ( playlistLoaded ) m_strCurrentFilterMusic = playlist.GetWhereClause(db, playlists); CLog::Log(LOGINFO, "PARTY MODE MANAGER: Registering filter:[%s]", m_strCurrentFilterMusic.c_str()); m_iMatchingSongs = (int)db.GetSongIDs(m_strCurrentFilterMusic, songIDs); if (m_iMatchingSongs < 1 && m_type.Equals("songs")) { pDialog->Close(); db.Close(); OnError(16031, (CStdString)"Party mode found no matching songs. Aborting."); return false; } } else { pDialog->Close(); OnError(16033, (CStdString)"Party mode could not open database. Aborting."); return false; } db.Close(); } if (m_type.Equals("musicvideos") || m_type.Equals("mixed")) { vector< pair<int,int> > songIDs2; CVideoDatabase db; if (db.Open()) { set<CStdString> playlists; if ( playlistLoaded ) m_strCurrentFilterVideo = playlist.GetWhereClause(db, playlists); CLog::Log(LOGINFO, "PARTY MODE MANAGER: Registering filter:[%s]", m_strCurrentFilterVideo.c_str()); m_iMatchingSongs += (int)db.GetMusicVideoIDs(m_strCurrentFilterVideo, songIDs2); if (m_iMatchingSongs < 1) { pDialog->Close(); db.Close(); OnError(16031, (CStdString)"Party mode found no matching songs. Aborting."); return false; } } else { pDialog->Close(); OnError(16033, (CStdString)"Party mode could not open database. Aborting."); return false; } db.Close(); songIDs.insert(songIDs.end(),songIDs2.begin(),songIDs2.end()); } // calculate history size if (m_iMatchingSongs < 50) m_songsInHistory = 0; else m_songsInHistory = (int)(m_iMatchingSongs/2); if (m_songsInHistory > 200) m_songsInHistory = 200; CLog::Log(LOGINFO,"PARTY MODE MANAGER: Matching songs = %i, History size = %i", m_iMatchingSongs, m_songsInHistory); CLog::Log(LOGINFO,"PARTY MODE MANAGER: Party mode enabled!"); int iPlaylist = m_bIsVideo ? PLAYLIST_VIDEO : PLAYLIST_MUSIC; g_playlistPlayer.ClearPlaylist(iPlaylist); g_playlistPlayer.SetShuffle(iPlaylist, false); g_playlistPlayer.SetRepeat(iPlaylist, PLAYLIST::REPEAT_NONE); pDialog->SetLine(0, (m_bIsVideo ? 20252 : 20124)); pDialog->Progress(); // add initial songs if (!AddInitialSongs(songIDs)) { pDialog->Close(); return false; } CLog::Log(LOGDEBUG, "%s time for song fetch: %u", __FUNCTION__, XbmcThreads::SystemClockMillis() - time); // start playing g_playlistPlayer.SetCurrentPlaylist(iPlaylist); Play(0); pDialog->Close(); // open now playing window if (m_type.Equals("songs")) { if (g_windowManager.GetActiveWindow() != WINDOW_MUSIC_PLAYLIST) g_windowManager.ActivateWindow(WINDOW_MUSIC_PLAYLIST); } // done m_bEnabled = true; Announce(); return true; }
bool CLibraryDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items) { std::string libNode = GetNode(strPath); if (libNode.empty()) return false; if (URIUtils::HasExtension(libNode, ".xml")) { // a filter or folder node TiXmlElement *node = LoadXML(libNode); if (node) { CStdString type = node->Attribute("type"); if (type == "filter") { CSmartPlaylist playlist; CStdString type, label; XMLUtils::GetString(node, "content", type); if (type.IsEmpty()) { 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") { CStdString path; XMLUtils::GetPath(node, "path", path); if (!path.IsEmpty()) { 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 for (int i = 0; i < nodes.Size(); i++) { const TiXmlElement *node = NULL; CStdString 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).Equals("index.xml")) { // set the label on our items CStdString label; if (XMLUtils::GetString(node, "label", label)) label = CGUIControlFactory::FilterLabel(label); items.SetLabel(label); continue; } } if (node) { CStdString 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); CStdString folder = URIUtils::GetFileName(xml); CFileItemPtr item(new CFileItem(URIUtils::AddFileToFolder(strPath, folder), true)); item->SetLabel(label); if (!icon.IsEmpty() && g_TextureManager.HasTexture(icon)) item->SetIconImage(icon); item->m_iprogramCount = order; items.Add(item); } } items.Sort(SortByPlaylistOrder, SortOrderAscending); return true; }
bool CSmartPlaylistDirectory::GetDirectory(const CSmartPlaylist &playlist, CFileItemList& items, const std::string &strBaseDir /* = "" */, bool filter /* = false */) { bool success = false, success2 = false; std::vector<std::string> virtualFolders; SortDescription sorting; sorting.limitEnd = playlist.GetLimit(); sorting.sortBy = playlist.GetOrder(); sorting.sortOrder = playlist.GetOrderAscending() ? SortOrderAscending : SortOrderDescending; sorting.sortAttributes = playlist.GetOrderAttributes(); if (CSettings::Get().GetBool("filelists.ignorethewhensorting")) sorting.sortAttributes = (SortAttribute)(sorting.sortAttributes | SortAttributeIgnoreArticle); items.SetSortIgnoreFolders((sorting.sortAttributes & SortAttributeIgnoreFolders) == SortAttributeIgnoreFolders); std::string option = !filter ? "xsp" : "filter"; const std::string& group = playlist.GetGroup(); bool isGrouped = !group.empty() && !StringUtils::EqualsNoCase(group, "none") && !playlist.IsGroupMixed(); // get all virtual folders and add them to the item list playlist.GetVirtualFolders(virtualFolders); for (std::vector<std::string>::const_iterator virtualFolder = virtualFolders.begin(); virtualFolder != virtualFolders.end(); virtualFolder++) { CFileItemPtr pItem = CFileItemPtr(new CFileItem(*virtualFolder, true)); IFileDirectory *dir = CFileDirectoryFactory::Create(pItem->GetURL(), pItem.get()); if (dir != NULL) { pItem->SetSpecialSort(SortSpecialOnTop); items.Add(pItem); delete dir; } } if (playlist.GetType() == "movies" || playlist.GetType() == "tvshows" || playlist.GetType() == "episodes") { CVideoDatabase db; if (db.Open()) { MediaType mediaType = MediaTypes::FromString(playlist.GetType()); std::string baseDir = strBaseDir; if (strBaseDir.empty()) { if (mediaType == MediaTypeTvShow || mediaType == MediaTypeEpisode) baseDir = "videodb://tvshows/"; else if (mediaType == MediaTypeMovie) baseDir = "videodb://movies/"; else return false; if (!isGrouped) baseDir += "titles"; else baseDir += group; URIUtils::AddSlashAtEnd(baseDir); if (mediaType == MediaTypeEpisode) baseDir += "-1/-1/"; } CVideoDbUrl videoUrl; if (!videoUrl.FromString(baseDir)) return false; // store the smartplaylist as JSON in the URL as well std::string xsp; if (!playlist.IsEmpty(filter)) { if (!playlist.SaveAsJson(xsp, !filter)) return false; } if (!xsp.empty()) videoUrl.AddOption(option, xsp); else videoUrl.RemoveOption(option); CDatabase::Filter dbfilter; success = db.GetItems(videoUrl.ToString(), items, dbfilter, sorting); db.Close(); // if we retrieve a list of episodes and we didn't receive // a pre-defined base path, we need to fix it if (strBaseDir.empty() && mediaType == MediaTypeEpisode && !isGrouped) videoUrl.AppendPath("-1/-1/"); items.SetProperty(PROPERTY_PATH_DB, videoUrl.ToString()); } } else if (playlist.IsMusicType() || playlist.GetType().empty()) { CMusicDatabase db; if (db.Open()) { CSmartPlaylist plist(playlist); if (playlist.GetType() == "mixed" || playlist.GetType().empty()) plist.SetType("songs"); MediaType mediaType = MediaTypes::FromString(plist.GetType()); std::string baseDir = strBaseDir; if (strBaseDir.empty()) { baseDir = "musicdb://"; if (!isGrouped) { if (mediaType == MediaTypeArtist) baseDir += "artists"; else if (mediaType == MediaTypeAlbum) baseDir += "albums"; else if (mediaType == MediaTypeSong) baseDir += "songs"; else return false; } else baseDir += group; URIUtils::AddSlashAtEnd(baseDir); } CMusicDbUrl musicUrl; if (!musicUrl.FromString(baseDir)) return false; // store the smartplaylist as JSON in the URL as well std::string xsp; if (!plist.IsEmpty(filter)) { if (!plist.SaveAsJson(xsp, !filter)) return false; } if (!xsp.empty()) musicUrl.AddOption(option, xsp); else musicUrl.RemoveOption(option); CDatabase::Filter dbfilter; success = db.GetItems(musicUrl.ToString(), items, dbfilter, sorting); db.Close(); items.SetProperty(PROPERTY_PATH_DB, musicUrl.ToString()); } } if (playlist.GetType() == "musicvideos" || playlist.GetType() == "mixed") { CVideoDatabase db; if (db.Open()) { CSmartPlaylist mvidPlaylist(playlist); if (playlist.GetType() == "mixed") mvidPlaylist.SetType("musicvideos"); std::string baseDir = strBaseDir; if (baseDir.empty()) { baseDir = "videodb://musicvideos/"; if (!isGrouped) baseDir += "titles"; else baseDir += group; URIUtils::AddSlashAtEnd(baseDir); } CVideoDbUrl videoUrl; if (!videoUrl.FromString(baseDir)) return false; // store the smartplaylist as JSON in the URL as well std::string xsp; if (!mvidPlaylist.IsEmpty(filter)) { if (!mvidPlaylist.SaveAsJson(xsp, !filter)) return false; } if (!xsp.empty()) videoUrl.AddOption(option, xsp); else videoUrl.RemoveOption(option); CFileItemList items2; CDatabase::Filter dbfilter; success2 = db.GetItems(videoUrl.ToString(), items2, dbfilter, sorting); db.Close(); if (items.Size() <= 0) items.SetPath(videoUrl.ToString()); items.Append(items2); if (items2.Size()) { if (items.Size() > items2.Size()) items.SetContent("mixed"); else items.SetContent("musicvideos"); } items.SetProperty(PROPERTY_PATH_DB, videoUrl.ToString()); } } items.SetLabel(playlist.GetName()); if (isGrouped) items.SetContent(group); else items.SetContent(playlist.GetType()); items.SetProperty(PROPERTY_SORT_ORDER, (int)playlist.GetOrder()); items.SetProperty(PROPERTY_SORT_ASCENDING, playlist.GetOrderDirection() == SortOrderAscending); if (!group.empty()) { items.SetProperty(PROPERTY_GROUP_BY, group); items.SetProperty(PROPERTY_GROUP_MIXED, playlist.IsGroupMixed()); } // sort grouped list by label if (items.Size() > 1 && !group.empty()) items.Sort(SortByLabel, SortOrderAscending, SortAttributeIgnoreArticle); // go through and set the playlist order for (int i = 0; i < items.Size(); i++) { CFileItemPtr item = items[i]; item->m_iprogramCount = i; // hack for playlist order } if (playlist.GetType() == "mixed") return success || success2; else if (playlist.GetType() == "musicvideos") return success2; else return success; }
bool CSmartPlaylistDirectory::GetDirectory(const CSmartPlaylist &playlist, CFileItemList& items) { bool success = false, success2 = false; std::set<CStdString> playlists; if (playlist.GetType().Equals("tvshows")) { CVideoDatabase db; db.Open(); CStdString whereOrder = playlist.GetWhereClause(db, playlists) + " " + playlist.GetOrderClause(db); success = db.GetTvShowsByWhere("videodb://2/2/", whereOrder, items); items.SetContent("tvshows"); db.Close(); } else if (playlist.GetType().Equals("episodes")) { CVideoDatabase db; db.Open(); CStdString whereOrder = playlist.GetWhereClause(db, playlists) + " " + playlist.GetOrderClause(db); success = db.GetEpisodesByWhere("videodb://2/2/", whereOrder, items); items.SetContent("episodes"); db.Close(); } else if (playlist.GetType().Equals("movies")) { CVideoDatabase db; db.Open(); success = db.GetMoviesByWhere("videodb://1/2/", playlist.GetWhereClause(db, playlists), playlist.GetOrderClause(db), items, true); items.SetContent("movies"); db.Close(); } else if (playlist.GetType().Equals("albums")) { CMusicDatabase db; db.Open(); success = db.GetAlbumsByWhere("musicdb://3/", playlist.GetWhereClause(db, playlists), playlist.GetOrderClause(db), items); items.SetContent("albums"); db.Close(); } if (playlist.GetType().Equals("songs") || playlist.GetType().Equals("mixed") || playlist.GetType().IsEmpty()) { CMusicDatabase db; db.Open(); CStdString whereOrder; if (playlist.GetType().IsEmpty() || playlist.GetType().Equals("mixed")) { CSmartPlaylist songPlaylist(playlist); songPlaylist.SetType("songs"); whereOrder = songPlaylist.GetWhereClause(db, playlists) + " " + songPlaylist.GetOrderClause(db); } else whereOrder = playlist.GetWhereClause(db, playlists) + " " + playlist.GetOrderClause(db); success = db.GetSongsByWhere("", whereOrder, items); items.SetContent("songs"); db.Close(); } if (playlist.GetType().Equals("musicvideos") || playlist.GetType().Equals("mixed")) { CVideoDatabase db; db.Open(); CStdString whereOrder; if (playlist.GetType().Equals("mixed")) { CSmartPlaylist mvidPlaylist(playlist); mvidPlaylist.SetType("musicvideos"); whereOrder = mvidPlaylist.GetWhereClause(db, playlists) + " " + mvidPlaylist.GetOrderClause(db); } else whereOrder = playlist.GetWhereClause(db, playlists) + " " + playlist.GetOrderClause(db); CFileItemList items2; success2 = db.GetMusicVideosByWhere("videodb://3/2/", whereOrder, items2, false); // TODO: SMARTPLAYLISTS Don't check locks??? db.Close(); items.Append(items2); if (items2.Size()) items.SetContent("musicvideos"); } items.SetLabel(playlist.GetName()); // go through and set the playlist order for (int i = 0; i < items.Size(); i++) { CFileItemPtr item = items[i]; item->m_iprogramCount = i; // hack for playlist order } if (playlist.GetType().Equals("mixed")) return success || success2; else if (playlist.GetType().Equals("musicvideos")) return success2; else return success; }
// return NULL + set pItem->m_bIsFolder to remove it completely from list. IFileDirectory* CFileDirectoryFactory::Create(const CStdString& strPath, CFileItem* pItem, const CStdString& strMask) { if (URIUtils::IsStack(strPath)) // disqualify stack as we need to work with each of the parts instead return NULL; CStdString strExtension=URIUtils::GetExtension(strPath); StringUtils::ToLower(strExtension); #ifdef HAS_FILESYSTEM if ((strExtension.Equals(".ogg") || strExtension.Equals(".oga")) && CFile::Exists(strPath)) { IFileDirectory* pDir=new COGGFileDirectory; // Has the ogg file more than one bitstream? if (pDir->ContainsFiles(strPath)) { return pDir; // treat as directory } delete pDir; return NULL; } if (strExtension.Equals(".nsf") && CFile::Exists(strPath)) { IFileDirectory* pDir=new CNSFFileDirectory; // Has the nsf file more than one track? if (pDir->ContainsFiles(strPath)) return pDir; // treat as directory delete pDir; return NULL; } if (strExtension.Equals(".sid") && CFile::Exists(strPath)) { IFileDirectory* pDir=new CSIDFileDirectory; // Has the sid file more than one track? if (pDir->ContainsFiles(strPath)) return pDir; // treat as directory delete pDir; return NULL; } #ifdef HAS_ASAP_CODEC if (ASAPCodec::IsSupportedFormat(strExtension) && CFile::Exists(strPath)) { IFileDirectory* pDir=new CASAPFileDirectory; // Has the asap file more than one track? if (pDir->ContainsFiles(strPath)) return pDir; // treat as directory delete pDir; return NULL; } #endif if (pItem->IsRSS()) return new CRSSDirectory(); if (pItem->IsDVDImage()) return new CUDFDirectory(); #endif #if defined(TARGET_ANDROID) if (strExtension.Equals(".apk")) { CStdString strUrl; URIUtils::CreateArchivePath(strUrl, "apk", strPath, ""); CFileItemList items; CDirectory::GetDirectory(strUrl, items, strMask); if (items.Size() == 0) // no files pItem->m_bIsFolder = true; else if (items.Size() == 1 && items[0]->m_idepth == 0) { // one STORED file - collapse it down *pItem = *items[0]; } else { // compressed or more than one file -> create a apk dir pItem->SetPath(strUrl); return new CAPKDirectory; } return NULL; } #endif if (strExtension.Equals(".zip")) { CStdString strUrl; URIUtils::CreateArchivePath(strUrl, "zip", strPath, ""); CFileItemList items; CDirectory::GetDirectory(strUrl, items, strMask); if (items.Size() == 0) // no files pItem->m_bIsFolder = true; else if (items.Size() == 1 && items[0]->m_idepth == 0) { // one STORED file - collapse it down *pItem = *items[0]; } else { // compressed or more than one file -> create a zip dir pItem->SetPath(strUrl); return new CZipDirectory; } return NULL; } if (strExtension.Equals(".rar") || strExtension.Equals(".001")) { CStdString strUrl; URIUtils::CreateArchivePath(strUrl, "rar", strPath, ""); vector<std::string> tokens; StringUtils::Tokenize(strPath,tokens,"."); if (tokens.size() > 2) { if (strExtension.Equals(".001")) { if (StringUtils::EqualsNoCase(tokens[tokens.size()-2], "ts")) // .ts.001 - treat as a movie file to scratch some users itch return NULL; } CStdString token = tokens[tokens.size()-2]; if (StringUtils::StartsWithNoCase(token, "part")) // only list '.part01.rar' { // need this crap to avoid making mistakes - yeyh for the new rar naming scheme :/ struct __stat64 stat; int digits = token.size()-4; CStdString strFormat = StringUtils::Format("part%%0%ii", digits); CStdString strNumber = StringUtils::Format(strFormat.c_str(), 1); CStdString strPath2 = strPath; StringUtils::Replace(strPath2,token,strNumber); if (atoi(token.substr(4).c_str()) > 1 && CFile::Stat(strPath2,&stat) == 0) { pItem->m_bIsFolder = true; return NULL; } } } CFileItemList items; CDirectory::GetDirectory(strUrl, items, strMask); if (items.Size() == 0) // no files - hide this pItem->m_bIsFolder = true; else if (items.Size() == 1 && items[0]->m_idepth == 0x30) { // one STORED file - collapse it down *pItem = *items[0]; } else { #ifdef HAS_FILESYSTEM_RAR // compressed or more than one file -> create a rar dir pItem->SetPath(strUrl); return new CRarDirectory; #else return NULL; #endif } return NULL; } if (strExtension.Equals(".xsp")) { // XBMC Smart playlist - just XML renamed to XSP // read the name of the playlist in CSmartPlaylist playlist; if (playlist.OpenAndReadName(strPath)) { pItem->SetLabel(playlist.GetName()); pItem->SetLabelPreformated(true); } IFileDirectory* pDir=new CSmartPlaylistDirectory; return pDir; // treat as directory } if (CPlayListFactory::IsPlaylist(strPath)) { // Playlist file // currently we only return the directory if it contains // more than one file. Reason is that .pls and .m3u may be used // for links to http streams etc. IFileDirectory *pDir = new CPlaylistFileDirectory(); CFileItemList items; if (pDir->GetDirectory(strPath, items)) { if (items.Size() > 1) return pDir; } delete pDir; return NULL; } return NULL; }
// return NULL + set pItem->m_bIsFolder to remove it completely from list. IFileDirectory* CFileDirectoryFactory::Create(const CURL& url, CFileItem* pItem, const std::string& strMask) { if (url.IsProtocol("stack")) // disqualify stack as we need to work with each of the parts instead return NULL; std::string strExtension=URIUtils::GetExtension(url); StringUtils::ToLower(strExtension); if (!strExtension.empty() && CServiceBroker::IsBinaryAddonCacheUp()) { BinaryAddonBaseList addonInfos; CServiceBroker::GetBinaryAddonManager().GetAddonInfos(addonInfos, true, ADDON_AUDIODECODER); for (const auto& addonInfo : addonInfos) { if (CAudioDecoder::HasTracks(addonInfo) && CAudioDecoder::GetExtensions(addonInfo).find(strExtension) != std::string::npos) { CAudioDecoder* result = new CAudioDecoder(addonInfo); if (!result->CreateDecoder() || !result->ContainsFiles(url)) { delete result; return nullptr; } return result; } } } if (!strExtension.empty() && CServiceBroker::IsBinaryAddonCacheUp()) { for (const auto& vfsAddon : CServiceBroker::GetVFSAddonCache().GetAddonInstances()) { if (vfsAddon->HasFileDirectories() && vfsAddon->GetExtensions().find(strExtension) != std::string::npos) { CVFSEntryIFileDirectoryWrapper* wrap = new CVFSEntryIFileDirectoryWrapper(vfsAddon); if (wrap->ContainsFiles(url)) { if (wrap->m_items.Size() == 1) { // one STORED file - collapse it down *pItem = *wrap->m_items[0]; } else { // compressed or more than one file -> create a dir pItem->SetPath(wrap->m_items.GetPath()); return wrap; } } else pItem->m_bIsFolder = true; delete wrap; return nullptr; } } } if (pItem->IsRSS()) return new CRSSDirectory(); if (pItem->IsDiscImage()) return new CUDFDirectory(); #if defined(TARGET_ANDROID) if (url.IsFileType("apk")) { CURL zipURL = URIUtils::CreateArchivePath("apk", url); CFileItemList items; CDirectory::GetDirectory(zipURL, items, strMask); if (items.Size() == 0) // no files pItem->m_bIsFolder = true; else if (items.Size() == 1 && items[0]->m_idepth == 0 && !items[0]->m_bIsFolder) { // one STORED file - collapse it down *pItem = *items[0]; } else { // compressed or more than one file -> create a apk dir pItem->SetURL(zipURL); return new CAPKDirectory; } return NULL; } #endif if (url.IsFileType("zip")) { CURL zipURL = URIUtils::CreateArchivePath("zip", url); CFileItemList items; CDirectory::GetDirectory(zipURL, items, strMask); if (items.Size() == 0) // no files pItem->m_bIsFolder = true; else if (items.Size() == 1 && items[0]->m_idepth == 0 && !items[0]->m_bIsFolder) { // one STORED file - collapse it down *pItem = *items[0]; } else { // compressed or more than one file -> create a zip dir pItem->SetURL(zipURL); return new CZipDirectory; } return NULL; } if (url.IsFileType("xbt")) { CURL xbtUrl = URIUtils::CreateArchivePath("xbt", url); pItem->SetURL(xbtUrl); return new CXbtDirectory(); } if (url.IsFileType("xsp")) { // XBMC Smart playlist - just XML renamed to XSP // read the name of the playlist in CSmartPlaylist playlist; if (playlist.OpenAndReadName(url)) { pItem->SetLabel(playlist.GetName()); pItem->SetLabelPreformatted(true); } IFileDirectory* pDir=new CSmartPlaylistDirectory; return pDir; // treat as directory } if (CPlayListFactory::IsPlaylist(url)) { // Playlist file // currently we only return the directory if it contains // more than one file. Reason is that .pls and .m3u may be used // for links to http streams etc. IFileDirectory *pDir = new CPlaylistFileDirectory(); CFileItemList items; if (pDir->GetDirectory(url, items)) { if (items.Size() > 1) return pDir; } delete pDir; return NULL; } if (pItem->IsAudioBook()) { if (!pItem->HasMusicInfoTag() || pItem->m_lEndOffset <= 0) { std::unique_ptr<CAudioBookFileDirectory> pDir(new CAudioBookFileDirectory); if (pDir->ContainsFiles(url)) return pDir.release(); } return NULL; } return NULL; }
int CGUIDialogMediaFilter::GetItems(const Filter &filter, std::vector<std::string> &items, bool countOnly /* = false */) { CFileItemList selectItems; // remove the rule for the field of the filter we want to retrieve items for CSmartPlaylist tmpFilter = *m_filter; for (CDatabaseQueryRules::iterator rule = tmpFilter.m_ruleCombination.m_rules.begin(); rule != tmpFilter.m_ruleCombination.m_rules.end(); rule++) { if ((*rule)->m_field == filter.field) { tmpFilter.m_ruleCombination.m_rules.erase(rule); break; } } if (m_mediaType == "movies" || m_mediaType == "tvshows" || m_mediaType == "episodes" || m_mediaType == "musicvideos") { CVideoDatabase videodb; if (!videodb.Open()) return -1; std::set<std::string> playlists; CDatabase::Filter dbfilter; dbfilter.where = tmpFilter.GetWhereClause(videodb, playlists); VIDEODB_CONTENT_TYPE type = VIDEODB_CONTENT_MOVIES; if (m_mediaType == "tvshows") type = VIDEODB_CONTENT_TVSHOWS; else if (m_mediaType == "episodes") type = VIDEODB_CONTENT_EPISODES; else if (m_mediaType == "musicvideos") type = VIDEODB_CONTENT_MUSICVIDEOS; if (filter.field == FieldGenre) videodb.GetGenresNav(m_dbUrl->ToString(), selectItems, type, dbfilter, countOnly); else if (filter.field == FieldActor || filter.field == FieldArtist) videodb.GetActorsNav(m_dbUrl->ToString(), selectItems, type, dbfilter, countOnly); else if (filter.field == FieldDirector) videodb.GetDirectorsNav(m_dbUrl->ToString(), selectItems, type, dbfilter, countOnly); else if (filter.field == FieldStudio) videodb.GetStudiosNav(m_dbUrl->ToString(), selectItems, type, dbfilter, countOnly); else if (filter.field == FieldAlbum) videodb.GetMusicVideoAlbumsNav(m_dbUrl->ToString(), selectItems, -1, dbfilter, countOnly); else if (filter.field == FieldTag) videodb.GetTagsNav(m_dbUrl->ToString(), selectItems, type, dbfilter, countOnly); } else if (m_mediaType == "artists" || m_mediaType == "albums" || m_mediaType == "songs") { CMusicDatabase musicdb; if (!musicdb.Open()) return -1; std::set<std::string> playlists; CDatabase::Filter dbfilter; dbfilter.where = tmpFilter.GetWhereClause(musicdb, playlists); if (filter.field == FieldGenre) musicdb.GetGenresNav(m_dbUrl->ToString(), selectItems, dbfilter, countOnly); else if (filter.field == FieldArtist) musicdb.GetArtistsNav(m_dbUrl->ToString(), selectItems, m_mediaType == "albums", -1, -1, -1, dbfilter, SortDescription(), countOnly); else if (filter.field == FieldAlbum) musicdb.GetAlbumsNav(m_dbUrl->ToString(), selectItems, -1, -1, dbfilter, SortDescription(), countOnly); else if (filter.field == FieldAlbumType) musicdb.GetAlbumTypesNav(m_dbUrl->ToString(), selectItems, dbfilter, countOnly); else if (filter.field == FieldMusicLabel) musicdb.GetMusicLabelsNav(m_dbUrl->ToString(), selectItems, dbfilter, countOnly); } int size = selectItems.Size(); if (size <= 0) return 0; if (countOnly) { if (size == 1 && selectItems.Get(0)->HasProperty("total")) return (int)selectItems.Get(0)->GetProperty("total").asInteger(); return 0; } // sort the items selectItems.Sort(SortByLabel, SortOrderAscending); for (int index = 0; index < size; ++index) items.push_back(selectItems.Get(index)->GetLabel()); return items.size(); }
void CGUIDialogMediaFilter::OnBrowse(const Filter &filter, CFileItemList &items, bool countOnly /* = false */) { CFileItemList selectItems; if (m_mediaType == "movies" || m_mediaType == "tvshows" || m_mediaType == "episodes" || m_mediaType == "musicvideos") { CVideoDatabase videodb; if (!videodb.Open()) return; CSmartPlaylist tmpFilter = *m_filter; for (vector<CSmartPlaylistRule>::iterator rule = tmpFilter.m_ruleCombination.m_rules.begin(); rule != tmpFilter.m_ruleCombination.m_rules.end(); rule++) { if (rule->m_field == filter.field) { tmpFilter.m_ruleCombination.m_rules.erase(rule); break; } } std::set<CStdString> playlists; CDatabase::Filter dbfilter; dbfilter.where = tmpFilter.GetWhereClause(videodb, playlists); VIDEODB_CONTENT_TYPE type = VIDEODB_CONTENT_MOVIES; if (m_mediaType == "tvshows") type = VIDEODB_CONTENT_TVSHOWS; else if (m_mediaType == "episodes") type = VIDEODB_CONTENT_EPISODES; else if (m_mediaType == "musicvideos") type = VIDEODB_CONTENT_MUSICVIDEOS; if (filter.field == FieldGenre) videodb.GetGenresNav(m_dbUrl->ToString(), selectItems, type, dbfilter, countOnly); else if (filter.field == FieldActor || filter.field == FieldArtist) videodb.GetActorsNav(m_dbUrl->ToString(), selectItems, type, dbfilter, countOnly); else if (filter.field == FieldDirector) videodb.GetDirectorsNav(m_dbUrl->ToString(), selectItems, type, dbfilter, countOnly); else if (filter.field == FieldStudio) videodb.GetStudiosNav(m_dbUrl->ToString(), selectItems, type, dbfilter, countOnly); else if (filter.field == FieldAlbum) videodb.GetMusicVideoAlbumsNav(m_dbUrl->ToString(), selectItems, -1, dbfilter, countOnly); else if (filter.field == FieldTag) videodb.GetTagsNav(m_dbUrl->ToString(), selectItems, type, dbfilter, countOnly); } else if (m_mediaType == "artists" || m_mediaType == "albums" || m_mediaType == "songs") { CMusicDatabase musicdb; if (!musicdb.Open()) return; CSmartPlaylist tmpFilter = *m_filter; for (vector<CSmartPlaylistRule>::iterator rule = tmpFilter.m_ruleCombination.m_rules.begin(); rule != tmpFilter.m_ruleCombination.m_rules.end(); rule++) { if (rule->m_field == filter.field) { tmpFilter.m_ruleCombination.m_rules.erase(rule); break; } } std::set<CStdString> playlists; CDatabase::Filter dbfilter; dbfilter.where = tmpFilter.GetWhereClause(musicdb, playlists); if (filter.field == FieldGenre) musicdb.GetGenresNav(m_dbUrl->ToString(), selectItems, dbfilter, countOnly); else if (filter.field == FieldArtist) musicdb.GetArtistsNav(m_dbUrl->ToString(), selectItems, m_mediaType == "albums", -1, -1, -1, dbfilter, SortDescription(), countOnly); else if (filter.field == FieldAlbum) musicdb.GetAlbumsNav(m_dbUrl->ToString(), selectItems, -1, -1, dbfilter, SortDescription(), countOnly); else if (filter.field == FieldAlbumType) musicdb.GetAlbumTypesNav(m_dbUrl->ToString(), selectItems, dbfilter, countOnly); else if (filter.field == FieldMusicLabel) musicdb.GetMusicLabelsNav(m_dbUrl->ToString(), selectItems, dbfilter, countOnly); } if (selectItems.Size() <= 0) return; if (countOnly) { items.Copy(selectItems); return; } // sort the items selectItems.Sort(SORT_METHOD_LABEL, SortOrderAscending); CGUIDialogSelect* pDialog = (CGUIDialogSelect*)g_windowManager.GetWindow(WINDOW_DIALOG_SELECT); pDialog->Reset(); pDialog->SetItems(&selectItems); CStdString strHeading; strHeading.Format(g_localizeStrings.Get(13401), g_localizeStrings.Get(filter.label)); pDialog->SetHeading(strHeading); pDialog->SetMultiSelection(true); if (filter.rule != NULL && !filter.rule->m_parameter.empty()) pDialog->SetSelected(filter.rule->m_parameter); pDialog->DoModal(); if (pDialog->IsConfirmed()) items.Copy(pDialog->GetSelectedItems()); else items.Clear(); pDialog->Reset(); }
bool CSmartPlaylistDirectory::GetDirectory(const CSmartPlaylist &playlist, CFileItemList& items, const CStdString &strBaseDir /* = "" */, bool filter /* = false */) { bool success = false, success2 = false; std::set<CStdString> playlists; SortDescription sorting; sorting.limitEnd = playlist.GetLimit(); sorting.sortBy = playlist.GetOrder(); sorting.sortOrder = playlist.GetOrderAscending() ? SortOrderAscending : SortOrderDescending; if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) sorting.sortAttributes = SortAttributeIgnoreArticle; std::string option = !filter ? "xsp" : "filter"; if (playlist.GetType().Equals("movies") || playlist.GetType().Equals("tvshows") || playlist.GetType().Equals("episodes")) { CVideoDatabase db; if (db.Open()) { MediaType mediaType = DatabaseUtils::MediaTypeFromString(playlist.GetType()); CStdString baseDir = strBaseDir; if (strBaseDir.empty()) { switch (mediaType) { case MediaTypeTvShow: case MediaTypeEpisode: baseDir = "videodb://2/2/"; break; case MediaTypeMovie: baseDir = "videodb://1/2/"; break; default: return false; } } CVideoDbUrl videoUrl; if (!videoUrl.FromString(baseDir)) return false; // store the smartplaylist as JSON in the URL as well CStdString xsp; if (!playlist.IsEmpty(filter)) { if (!playlist.SaveAsJson(xsp, !filter)) return false; } videoUrl.AddOption(option, xsp); CDatabase::Filter dbfilter; success = db.GetSortedVideos(mediaType, videoUrl.ToString(), sorting, items, dbfilter, true); db.Close(); // if we retrieve a list of episodes and we didn't receive // a pre-defined base path, we need to fix it if (strBaseDir.empty() && mediaType == MediaTypeEpisode) videoUrl.AppendPath("-1/-1/"); items.SetProperty(PROPERTY_PATH_DB, videoUrl.ToString()); } } else if (playlist.GetType().Equals("albums")) { CMusicDatabase db; if (db.Open()) { CMusicDbUrl musicUrl; if (!musicUrl.FromString(!strBaseDir.empty() ? strBaseDir : "musicdb://3/")) return false; // store the smartplaylist as JSON in the URL as well CStdString xsp; if (!playlist.IsEmpty(filter)) { if (!playlist.SaveAsJson(xsp, !filter)) return false; } musicUrl.AddOption(option, xsp); CDatabase::Filter dbfilter; success = db.GetAlbumsByWhere(musicUrl.ToString(), dbfilter, items, sorting); db.Close(); items.SetContent("albums"); items.SetProperty(PROPERTY_PATH_DB, musicUrl.ToString()); } } else if (playlist.GetType().Equals("artists")) { CMusicDatabase db; if (db.Open()) { CMusicDbUrl musicUrl; if (!musicUrl.FromString("musicdb://2/")) return false; // store the smartplaylist as JSON in the URL as well CStdString xsp; if (!playlist.IsEmpty(filter)) { if (!playlist.SaveAsJson(xsp, !filter)) return false; } musicUrl.AddOption(option, xsp); CDatabase::Filter dbfilter; success = db.GetArtistsNav(musicUrl.ToString(), items, !g_guiSettings.GetBool("musiclibrary.showcompilationartists"), -1, -1, -1, dbfilter, sorting); db.Close(); items.SetContent("artists"); items.SetProperty(PROPERTY_PATH_DB, musicUrl.ToString()); } } if (playlist.GetType().Equals("songs") || playlist.GetType().Equals("mixed") || playlist.GetType().IsEmpty()) { CMusicDatabase db; if (db.Open()) { CSmartPlaylist songPlaylist(playlist); if (playlist.GetType().IsEmpty() || playlist.GetType().Equals("mixed")) songPlaylist.SetType("songs"); CMusicDbUrl musicUrl; if (!musicUrl.FromString(!strBaseDir.empty() ? strBaseDir : "musicdb://4/")) return false; // store the smartplaylist as JSON in the URL as well CStdString xsp; if (!songPlaylist.IsEmpty(filter)) { if (!songPlaylist.SaveAsJson(xsp, !filter)) return false; } musicUrl.AddOption(option, xsp); CDatabase::Filter dbfilter; success = db.GetSongsByWhere(musicUrl.ToString(), dbfilter, items, sorting); db.Close(); items.SetContent("songs"); items.SetProperty(PROPERTY_PATH_DB, musicUrl.ToString()); } } if (playlist.GetType().Equals("musicvideos") || playlist.GetType().Equals("mixed")) { CVideoDatabase db; if (db.Open()) { CSmartPlaylist mvidPlaylist(playlist); if (playlist.GetType().Equals("mixed")) mvidPlaylist.SetType("musicvideos"); CVideoDbUrl videoUrl; if (!videoUrl.FromString(!strBaseDir.empty() ? strBaseDir : "videodb://3/2/")) return false; // store the smartplaylist as JSON in the URL as well CStdString xsp; if (!mvidPlaylist.IsEmpty(filter)) { if (!mvidPlaylist.SaveAsJson(xsp, !filter)) return false; } videoUrl.AddOption(option, xsp); CFileItemList items2; success2 = db.GetSortedVideos(MediaTypeMusicVideo, videoUrl.ToString(), sorting, items2); db.Close(); items.Append(items2); if (items2.Size()) { if (items.Size() > items2.Size()) items.SetContent("mixed"); else items.SetContent("musicvideos"); } items.SetProperty(PROPERTY_PATH_DB, videoUrl.ToString()); } } items.SetLabel(playlist.GetName()); // go through and set the playlist order for (int i = 0; i < items.Size(); i++) { CFileItemPtr item = items[i]; item->m_iprogramCount = i; // hack for playlist order } if (playlist.GetType().Equals("mixed")) return success || success2; else if (playlist.GetType().Equals("musicvideos")) return success2; else return success; }
// return NULL + set pItem->m_bIsFolder to remove it completely from list. IFileDirectory* CFileDirectoryFactory::Create(const CURL& url, CFileItem* pItem, const std::string& strMask) { if (url.IsProtocol("stack")) // disqualify stack as we need to work with each of the parts instead return NULL; std::string strExtension=URIUtils::GetExtension(url); StringUtils::ToLower(strExtension); if (!strExtension.empty()) { VECADDONS codecs; CBinaryAddonCache &addonCache = CServiceBroker::GetBinaryAddonCache(); addonCache.GetAddons(codecs, ADDON_AUDIODECODER); for (size_t i=0;i<codecs.size();++i) { std::shared_ptr<CAudioDecoder> dec(std::static_pointer_cast<CAudioDecoder>(codecs[i])); if (dec->HasTracks() && dec->GetExtensions().find(strExtension) != std::string::npos) { CAudioDecoder* result = new CAudioDecoder(*dec); result->Create(); if (result->ContainsFiles(url)) return result; delete result; return NULL; } } } if (CServiceBroker::IsBinaryAddonCacheUp()) { VECADDONS vfs; CBinaryAddonCache &addonCache = CServiceBroker::GetBinaryAddonCache(); addonCache.GetAddons(vfs, ADDON_VFS); for (size_t i=0;i<vfs.size();++i) { std::shared_ptr<CVFSEntry> dec(std::static_pointer_cast<CVFSEntry>(vfs[i])); if (!strExtension.empty() && dec->HasFileDirectories() && dec->GetExtensions().find(strExtension) != std::string::npos) { CVFSEntryIFileDirectoryWrapper* wrap = new CVFSEntryIFileDirectoryWrapper(dec); if (wrap->ContainsFiles(url)) { if (wrap->m_items.Size() == 1) { // one STORED file - collapse it down *pItem = *wrap->m_items[0]; } else { // compressed or more than one file -> create a dir pItem->SetPath(wrap->m_items.GetPath()); return wrap; } } else pItem->m_bIsFolder = true; delete wrap; return NULL; } } } if (pItem->IsRSS()) return new CRSSDirectory(); if (pItem->IsDiscImage()) return new CUDFDirectory(); #if defined(TARGET_ANDROID) if (url.IsFileType("apk")) { CURL zipURL = URIUtils::CreateArchivePath("apk", url); CFileItemList items; CDirectory::GetDirectory(zipURL, items, strMask); if (items.Size() == 0) // no files pItem->m_bIsFolder = true; else if (items.Size() == 1 && items[0]->m_idepth == 0 && !items[0]->m_bIsFolder) { // one STORED file - collapse it down *pItem = *items[0]; } else { // compressed or more than one file -> create a apk dir pItem->SetURL(zipURL); return new CAPKDirectory; } return NULL; } #endif if (url.IsFileType("zip")) { CURL zipURL = URIUtils::CreateArchivePath("zip", url); CFileItemList items; CDirectory::GetDirectory(zipURL, items, strMask); if (items.Size() == 0) // no files pItem->m_bIsFolder = true; else if (items.Size() == 1 && items[0]->m_idepth == 0 && !items[0]->m_bIsFolder) { // one STORED file - collapse it down *pItem = *items[0]; } else { // compressed or more than one file -> create a zip dir pItem->SetURL(zipURL); return new CZipDirectory; } return NULL; } if (url.IsFileType("rar") || url.IsFileType("001")) { std::vector<std::string> tokens; const std::string strPath = url.Get(); StringUtils::Tokenize(strPath,tokens,"."); if (tokens.size() > 2) { if (url.IsFileType("001")) { if (StringUtils::EqualsNoCase(tokens[tokens.size()-2], "ts")) // .ts.001 - treat as a movie file to scratch some users itch return NULL; } std::string token = tokens[tokens.size()-2]; if (StringUtils::StartsWith(token, "part")) // only list '.part01.rar' { // need this crap to avoid making mistakes - yeyh for the new rar naming scheme :/ struct __stat64 stat; int digits = token.size()-4; std::string strFormat = StringUtils::Format("part%%0%ii", digits); std::string strNumber = StringUtils::Format(strFormat.c_str(), 1); std::string strPath2 = strPath; StringUtils::Replace(strPath2,token,strNumber); if (atoi(token.substr(4).c_str()) > 1 && CFile::Stat(strPath2,&stat) == 0) { pItem->m_bIsFolder = true; return NULL; } } } CURL rarURL = URIUtils::CreateArchivePath("rar", url); CFileItemList items; CDirectory::GetDirectory(rarURL, items, strMask); if (items.Size() == 0) // no files - hide this pItem->m_bIsFolder = true; else if (items.Size() == 1 && items[0]->m_idepth == 0x30 && !items[0]->m_bIsFolder) { // one STORED file - collapse it down *pItem = *items[0]; } else { #ifdef HAS_FILESYSTEM_RAR // compressed or more than one file -> create a rar dir pItem->SetURL(rarURL); return new CRarDirectory; #else return NULL; #endif } return NULL; } if (url.IsFileType("xbt")) { CURL xbtUrl = URIUtils::CreateArchivePath("xbt", url); pItem->SetURL(xbtUrl); return new CXbtDirectory(); } if (url.IsFileType("xsp")) { // XBMC Smart playlist - just XML renamed to XSP // read the name of the playlist in CSmartPlaylist playlist; if (playlist.OpenAndReadName(url)) { pItem->SetLabel(playlist.GetName()); pItem->SetLabelPreformatted(true); } IFileDirectory* pDir=new CSmartPlaylistDirectory; return pDir; // treat as directory } if (CPlayListFactory::IsPlaylist(url)) { // Playlist file // currently we only return the directory if it contains // more than one file. Reason is that .pls and .m3u may be used // for links to http streams etc. IFileDirectory *pDir = new CPlaylistFileDirectory(); CFileItemList items; if (pDir->GetDirectory(url, items)) { if (items.Size() > 1) return pDir; } delete pDir; return NULL; } if (pItem->IsAudioBook()) { if (!pItem->HasMusicInfoTag() || pItem->m_lEndOffset <= 0) { std::unique_ptr<CAudioBookFileDirectory> pDir(new CAudioBookFileDirectory); if (pDir->ContainsFiles(url)) return pDir.release(); } return NULL; } return NULL; }
bool CSmartPlaylistDirectory::GetDirectory(const CStdString& strPath, CFileItemList& items) { // Load in the SmartPlaylist and get the WHERE query CSmartPlaylist playlist; if (!playlist.Load(strPath)) return false; bool success = false, success2 = false; if (playlist.GetType().Equals("music") || playlist.GetType().Equals("mixed") || playlist.GetType().IsEmpty()) { CMusicDatabase db; db.Open(); CStdString type=playlist.GetType(); if (type.IsEmpty()) type = "music"; if (playlist.GetType().Equals("mixed")) playlist.SetType("music"); CStdString whereOrder = playlist.GetWhereClause() + " " + playlist.GetOrderClause(); success = db.GetSongsByWhere("", whereOrder, items); db.Close(); playlist.SetType(type); } if (playlist.GetType().Equals("video") || playlist.GetType().Equals("mixed")) { CVideoDatabase db; db.Open(); CStdString type=playlist.GetType(); if (playlist.GetType().Equals("mixed")) playlist.SetType("video"); CStdString whereOrder = playlist.GetWhereClause() + " " + playlist.GetOrderClause(); CFileItemList items2; success2 = db.GetMusicVideosByWhere("videodb://3/2/", whereOrder, items2); db.Close(); items.Append(items2); playlist.SetType(type); } if (playlist.GetType().Equals("mixed")) return success || success2; else if (playlist.GetType().Equals("video")) return success2; else return success; }
CStdString CSmartPlaylistRule::GetWhereClause(CDatabase &db, const CStdString& strType) { SEARCH_OPERATOR op = m_operator; if ((strType == "tvshows" || strType == "episodes") && m_field == FIELD_YEAR) { // special case for premiered which is a date rather than a year // TODO: SMARTPLAYLISTS do we really need this, or should we just make this field the premiered date and request a date? if (op == OPERATOR_EQUALS) op = OPERATOR_CONTAINS; else if (op == OPERATOR_DOES_NOT_EQUAL) op = OPERATOR_DOES_NOT_CONTAIN; } CStdString operatorString, negate; CStdString parameter; if (GetFieldType(m_field) == TEXTIN_FIELD) { CStdStringArray split; StringUtils::SplitString(m_parameter, ",", split); for (CStdStringArray::iterator it=split.begin(); it!=split.end(); ++it) { if (!parameter.IsEmpty()) parameter += ","; parameter += db.PrepareSQL("'%s'", (*it).Trim().c_str()); } parameter = " IN (" + parameter + ")"; if (op == OPERATOR_DOES_NOT_EQUAL) negate = " NOT"; } else { // the comparison piece switch (op) { case OPERATOR_CONTAINS: operatorString = " LIKE '%%%s%%'"; break; case OPERATOR_DOES_NOT_CONTAIN: negate = " NOT"; operatorString = " LIKE '%%%s%%'"; break; case OPERATOR_EQUALS: operatorString = " LIKE '%s'"; break; case OPERATOR_DOES_NOT_EQUAL: negate = " NOT"; operatorString = " LIKE '%s'"; break; case OPERATOR_STARTS_WITH: operatorString = " LIKE '%s%%'"; break; case OPERATOR_ENDS_WITH: operatorString = " LIKE '%%%s'"; break; case OPERATOR_AFTER: case OPERATOR_GREATER_THAN: case OPERATOR_IN_THE_LAST: operatorString = " > '%s'"; break; case OPERATOR_BEFORE: case OPERATOR_LESS_THAN: case OPERATOR_NOT_IN_THE_LAST: operatorString = " < '%s'"; break; case OPERATOR_TRUE: operatorString = " = 1"; break; case OPERATOR_FALSE: negate = " NOT "; operatorString = " = 0"; break; default: break; } parameter = db.PrepareSQL(operatorString.c_str(), m_parameter.c_str()); } if (m_field == FIELD_LASTPLAYED || m_field == FIELD_AIRDATE) { if (m_operator == OPERATOR_IN_THE_LAST || m_operator == OPERATOR_NOT_IN_THE_LAST) { // translate time period CDateTime date=CDateTime::GetCurrentDateTime(); CDateTimeSpan span; span.SetFromPeriod(m_parameter); date-=span; parameter = db.PrepareSQL(operatorString.c_str(), date.GetAsDBDate().c_str()); } } else if (m_field == FIELD_TIME) { // translate time to seconds CStdString seconds; seconds.Format("%i", StringUtils::TimeStringToSeconds(m_parameter)); parameter = db.PrepareSQL(operatorString.c_str(), seconds.c_str()); } // now the query parameter CStdString query; if (strType == "songs") { if (m_field == FIELD_GENRE) query = negate + " ((strGenre" + parameter + ") or idSong IN (select idSong from genre,exgenresong where exgenresong.idGenre = genre.idGenre and genre.strGenre" + parameter + "))"; else if (m_field == FIELD_ARTIST) query = negate + " ((strArtist" + parameter + ") or idSong IN (select idSong from artist,exartistsong where exartistsong.idArtist = artist.idArtist and artist.strArtist" + parameter + "))"; else if (m_field == FIELD_ALBUMARTIST) query = negate + " (idalbum in (select idalbum from artist,album where album.idArtist=artist.idArtist and artist.strArtist" + parameter + ") or idalbum in (select idalbum from artist,exartistalbum where exartistalbum.idArtist = artist.idArtist and artist.strArtist" + parameter + "))"; else if (m_field == FIELD_LASTPLAYED && (m_operator == OPERATOR_LESS_THAN || m_operator == OPERATOR_BEFORE || m_operator == OPERATOR_NOT_IN_THE_LAST)) query = "lastPlayed is NULL or lastPlayed" + parameter; } else if (strType == "albums") { if (m_field == FIELD_GENRE) query = negate + " (idAlbum in (select song.idAlbum from song join genre on song.idGenre=genre.idGenre where genre.strGenre" + parameter + ") or " "idAlbum in (select song.idAlbum from song join exgenresong on song.idSong=exgenresong.idSong join genre on exgenresong.idGenre=genre.idGenre where genre.strGenre" + parameter + "))"; else if (m_field == FIELD_ARTIST) query = negate + " (idAlbum in (select song.idAlbum from song join artist on song.idArtist=artist.idArtist where artist.strArtist" + parameter + ") or " "idAlbum in (select song.idAlbum from song join exartistsong on song.idSong=exartistsong.idSong join artist on exartistsong.idArtist=artist.idArtist where artist.strArtist" + parameter + "))"; else if (m_field == FIELD_ALBUMARTIST) query = negate + " (idalbum in (select idalbum from artist,album where album.idArtist=artist.idArtist and artist.strArtist" + parameter + ") or idalbum in (select idalbum from artist,exartistalbum where exartistalbum.idArtist = artist.idArtist and artist.strArtist" + parameter + "))"; } else if (strType == "movies") { if (m_field == FIELD_GENRE) query = "idMovie" + negate + " in (select idMovie from genrelinkmovie join genre on genre.idGenre=genrelinkmovie.idGenre where genre.strGenre" + parameter + ")"; else if (m_field == FIELD_DIRECTOR) query = "idMovie" + negate + " in (select idMovie from directorlinkmovie join actors on actors.idActor=directorlinkmovie.idDirector where actors.strActor" + parameter + ")"; else if (m_field == FIELD_ACTOR) query = "idMovie" + negate + " in (select idMovie from actorlinkmovie join actors on actors.idActor=actorlinkmovie.idActor where actors.strActor" + parameter + ")"; else if (m_field == FIELD_WRITER) query = "idMovie" + negate + " in (select idMovie from writerlinkmovie join actors on actors.idActor=writerlinkmovie.idWriter where actors.strActor" + parameter + ")"; else if (m_field == FIELD_STUDIO) query = "idMovie" + negate + " in (select idMovie from studiolinkmovie join studio on studio.idStudio=studiolinkmovie.idStudio where studio.strStudio" + parameter + ")"; else if (m_field == FIELD_COUNTRY) query = "idMovie" + negate + " in (select idMovie from countrylinkmovie join country on country.idCountry=countrylinkmovie.idCountry where country.strCountry" + parameter + ")"; else if (m_field == FIELD_HASTRAILER) query = negate + GetDatabaseField(m_field, strType) + "!= ''"; else if (m_field == FIELD_LASTPLAYED && (m_operator == OPERATOR_LESS_THAN || m_operator == OPERATOR_BEFORE || m_operator == OPERATOR_NOT_IN_THE_LAST)) query = "lastPlayed is NULL or lastPlayed" + parameter; else if (m_field == FIELD_INPROGRESS) query = "idFile " + negate + " in (select idFile from bookmark where type = 1)"; else if (m_field == FIELD_SET) query = "idMovie" + negate + " in (select idMovie from setlinkmovie join sets on sets.idSet=setlinkmovie.idSet where sets.strSet" + parameter + ")"; } else if (strType == "musicvideos") { if (m_field == FIELD_GENRE) query = "idMVideo" + negate + " in (select idMVideo from genrelinkmusicvideo join genre on genre.idGenre=genrelinkmusicvideo.idGenre where genre.strGenre" + parameter + ")"; else if (m_field == FIELD_ARTIST) query = "idMVideo" + negate + " in (select idMVideo from artistlinkmusicvideo join actors on actors.idActor=artistlinkmusicvideo.idArtist where actors.strActor" + parameter + ")"; else if (m_field == FIELD_STUDIO) query = "idMVideo" + negate + " in (select idMVideo from studiolinkmusicvideo join studio on studio.idStudio=studiolinkmusicvideo.idStudio where studio.strStudio" + parameter + ")"; else if (m_field == FIELD_DIRECTOR) query = "idMVideo" + negate + " in (select idMVideo from directorlinkmusicvideo join actors on actors.idActor=directorlinkmusicvideo.idDirector where actors.strActor" + parameter + ")"; else if (m_field == FIELD_LASTPLAYED && (m_operator == OPERATOR_LESS_THAN || m_operator == OPERATOR_BEFORE || m_operator == OPERATOR_NOT_IN_THE_LAST)) query = "lastPlayed is NULL or lastPlayed" + parameter; } else if (strType == "tvshows") { if (m_field == FIELD_GENRE) query = "idShow" + negate + " in (select idShow from genrelinktvshow join genre on genre.idGenre=genrelinktvshow.idGenre where genre.strGenre" + parameter + ")"; else if (m_field == FIELD_DIRECTOR) query = "idShow" + negate + " in (select idShow from directorlinktvshow join actors on actors.idActor=directorlinktvshow.idDirector where actors.strActor" + parameter + ")"; else if (m_field == FIELD_ACTOR) query = "idShow" + negate + " in (select idShow from actorlinktvshow join actors on actors.idActor=actorlinktvshow.idActor where actors.strActor" + parameter + ")"; else if (m_field == FIELD_STUDIO) query = "idShow" + negate + " IN (SELECT idShow FROM tvshowview WHERE " + GetDatabaseField(m_field, strType) + parameter + ")"; else if (m_field == FIELD_MPAA) query = "idShow" + negate + " IN (SELECT idShow FROM tvshowview WHERE " + GetDatabaseField(m_field, strType) + parameter + ")"; } else if (strType == "episodes") { if (m_field == FIELD_GENRE) query = "idShow" + negate + " in (select idShow from genrelinktvshow join genre on genre.idGenre=genrelinktvshow.idGenre where genre.strGenre" + parameter + ")"; else if (m_field == FIELD_DIRECTOR) query = "idEpisode" + negate + " in (select idEpisode from directorlinkepisode join actors on actors.idActor=directorlinkepisode.idDirector where actors.strActor" + parameter + ")"; else if (m_field == FIELD_ACTOR) query = "idEpisode" + negate + " in (select idEpisode from actorlinkepisode join actors on actors.idActor=actorlinkepisode.idActor where actors.strActor" + parameter + ")"; else if (m_field == FIELD_WRITER) query = "idEpisode" + negate + " in (select idEpisode from writerlinkepisode join actors on actors.idActor=writerlinkepisode.idWriter where actors.strActor" + parameter + ")"; else if (m_field == FIELD_LASTPLAYED && (m_operator == OPERATOR_LESS_THAN || m_operator == OPERATOR_BEFORE || m_operator == OPERATOR_NOT_IN_THE_LAST)) query = "lastPlayed is NULL or lastPlayed" + parameter; else if (m_field == FIELD_INPROGRESS) query = "idFile " + negate + " in (select idFile from bookmark where type = 1)"; else if (m_field == FIELD_STUDIO) query = "idEpisode" + negate + " IN (SELECT idEpisode FROM episodeview WHERE strStudio" + parameter + ")"; else if (m_field == FIELD_MPAA) query = "idEpisode" + negate + " IN (SELECT idEpisode FROM episodeview WHERE mpaa" + parameter + ")"; } if (m_field == FIELD_VIDEORESOLUTION) query = "idFile" + negate + GetVideoResolutionQuery(); else if (m_field == FIELD_AUDIOCHANNELS) query = "idFile" + negate + " in (select distinct idFile from streamdetails where iAudioChannels " + parameter + ")"; else if (m_field == FIELD_VIDEOCODEC) query = "idFile" + negate + " in (select distinct idFile from streamdetails where strVideoCodec " + parameter + ")"; else if (m_field == FIELD_AUDIOCODEC) query = "idFile" + negate + " in (select distinct idFile from streamdetails where strAudioCodec " + parameter + ")"; else if (m_field == FIELD_AUDIOLANGUAGE) query = "idFile" + negate + " in (select distinct idFile from streamdetails where strAudioLanguage " + parameter + ")"; else if (m_field == FIELD_SUBTITLELANGUAGE) query = "idFile" + negate + " in (select distinct idFile from streamdetails where strSubtitleLanguage " + parameter + ")"; else if (m_field == FIELD_VIDEOASPECT) query = "idFile" + negate + " in (select distinct idFile from streamdetails where fVideoAspect " + parameter + ")"; else if (m_field == FIELD_PLAYLIST) { // playlist field - grab our playlist and add to our where clause CStdString playlistFile = CSmartPlaylistDirectory::GetPlaylistByName(m_parameter, strType); if (!playlistFile.IsEmpty()) { CSmartPlaylist playlist; playlist.Load(playlistFile); CStdString playlistQuery; // only playlists of same type will be part of the query if (playlist.GetType().Equals(strType) || (playlist.GetType().Equals("mixed") && (strType == "songs" || strType == "musicvideos")) || playlist.GetType().IsEmpty()) { playlist.SetType(strType); playlistQuery = playlist.GetWhereClause(db, false); } if (m_operator == OPERATOR_DOES_NOT_EQUAL && playlist.GetType().Equals(strType)) query.Format("NOT (%s)", playlistQuery.c_str()); else if (m_operator == OPERATOR_EQUALS && playlist.GetType().Equals(strType)) query = playlistQuery; } } if (m_field == FIELD_PLAYCOUNT && strType != "songs" && strType != "albums") { // playcount is stored as NULL or number in video db if ((m_operator == OPERATOR_EQUALS && m_parameter == "0") || (m_operator == OPERATOR_DOES_NOT_EQUAL && m_parameter != "0") || (m_operator == OPERATOR_LESS_THAN)) { CStdString field = GetDatabaseField(FIELD_PLAYCOUNT, strType); query = field + " is NULL or " + field + parameter; } } if (query.IsEmpty() && m_field != FIELD_NONE) query = GetDatabaseField(m_field,strType) + negate + parameter; // if we fail to get a dbfield, we empty query so it doesn't fail if (query.Equals(negate + parameter)) query = ""; return query; }
bool CSmartPlaylistDirectory::GetDirectory(const CSmartPlaylist &playlist, CFileItemList& items) { bool success = false, success2 = false; std::set<CStdString> playlists; SortDescription sorting; sorting.limitEnd = playlist.GetLimit(); sorting.sortBy = playlist.GetOrder(); sorting.sortOrder = playlist.GetOrderAscending() ? SortOrderAscending : SortOrderDescending; if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) sorting.sortAttributes = SortAttributeIgnoreArticle; if (playlist.GetType().Equals("movies") || playlist.GetType().Equals("tvshows") || playlist.GetType().Equals("episodes")) { CVideoDatabase db; if (db.Open()) { MediaType mediaType = DatabaseUtils::MediaTypeFromString(playlist.GetType()); CStdString strBaseDir; switch (mediaType) { case MediaTypeTvShow: case MediaTypeEpisode: strBaseDir = "videodb://2/2/"; break; case MediaTypeMovie: strBaseDir = "videodb://1/2/"; break; default: return false; } CVideoDbUrl videoUrl; CStdString xsp; if (!videoUrl.FromString(strBaseDir) || !playlist.SaveAsJson(xsp, false)) return false; // store the smartplaylist as JSON in the URL as well videoUrl.AddOption("xsp", xsp); CDatabase::Filter filter; success = db.GetSortedVideos(mediaType, videoUrl.ToString(), sorting, items, filter, true); db.Close(); } } else if (playlist.GetType().Equals("albums")) { CMusicDatabase db; if (db.Open()) { CMusicDbUrl musicUrl; CStdString xsp; if (!musicUrl.FromString("musicdb://3/") || !playlist.SaveAsJson(xsp, false)) return false; // store the smartplaylist as JSON in the URL as well musicUrl.AddOption("xsp", xsp); CDatabase::Filter filter; success = db.GetAlbumsByWhere(musicUrl.ToString(), filter, items, sorting); items.SetContent("albums"); db.Close(); } } if (playlist.GetType().Equals("songs") || playlist.GetType().Equals("mixed") || playlist.GetType().IsEmpty()) { CMusicDatabase db; if (db.Open()) { CSmartPlaylist songPlaylist(playlist); if (playlist.GetType().IsEmpty() || playlist.GetType().Equals("mixed")) songPlaylist.SetType("songs"); CMusicDbUrl musicUrl; CStdString xsp; if (!musicUrl.FromString("musicdb://4/") || !songPlaylist.SaveAsJson(xsp, false)) return false; // store the smartplaylist as JSON in the URL as well musicUrl.AddOption("xsp", xsp); CDatabase::Filter filter; success = db.GetSongsByWhere(musicUrl.ToString(), filter, items, sorting); items.SetContent("songs"); db.Close(); } } if (playlist.GetType().Equals("musicvideos") || playlist.GetType().Equals("mixed")) { CVideoDatabase db; if (db.Open()) { CSmartPlaylist mvidPlaylist(playlist); if (playlist.GetType().Equals("mixed")) mvidPlaylist.SetType("musicvideos"); CVideoDbUrl videoUrl; CStdString xsp; if (!videoUrl.FromString("videodb://3/2/") || !mvidPlaylist.SaveAsJson(xsp, false)) return false; // store the smartplaylist as JSON in the URL as well videoUrl.AddOption("xsp", xsp); CFileItemList items2; success2 = db.GetSortedVideos(MediaTypeMusicVideo, videoUrl.ToString(), sorting, items2); db.Close(); items.Append(items2); if (items2.Size()) { if (items.Size() > items2.Size()) items.SetContent("mixed"); else items.SetContent("musicvideos"); } } } items.SetLabel(playlist.GetName()); // go through and set the playlist order for (int i = 0; i < items.Size(); i++) { CFileItemPtr item = items[i]; item->m_iprogramCount = i; // hack for playlist order } if (playlist.GetType().Equals("mixed")) return success || success2; else if (playlist.GetType().Equals("musicvideos")) return success2; else return success; }