[PVR][Estuary] Timer settings dialog: Show client name in timer type selection dialog...
[xbmc.git] / xbmc / filesystem / SmartPlaylistDirectory.cpp
blob9e05599a20d600280b2c6c6ee2843e98f2974985
1 /*
2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "SmartPlaylistDirectory.h"
11 #include "FileItem.h"
12 #include "ServiceBroker.h"
13 #include "filesystem/Directory.h"
14 #include "filesystem/File.h"
15 #include "filesystem/FileDirectoryFactory.h"
16 #include "music/MusicDatabase.h"
17 #include "music/MusicDbUrl.h"
18 #include "playlists/PlayListTypes.h"
19 #include "playlists/SmartPlayList.h"
20 #include "settings/Settings.h"
21 #include "settings/SettingsComponent.h"
22 #include "utils/SortUtils.h"
23 #include "utils/StringUtils.h"
24 #include "utils/URIUtils.h"
25 #include "video/VideoDatabase.h"
26 #include "video/VideoDbUrl.h"
28 #include <math.h>
30 #define PROPERTY_PATH_DB "path.db"
31 #define PROPERTY_SORT_ORDER "sort.order"
32 #define PROPERTY_SORT_ASCENDING "sort.ascending"
33 #define PROPERTY_GROUP_BY "group.by"
34 #define PROPERTY_GROUP_MIXED "group.mixed"
36 namespace XFILE
38 CSmartPlaylistDirectory::CSmartPlaylistDirectory() = default;
40 CSmartPlaylistDirectory::~CSmartPlaylistDirectory() = default;
42 bool CSmartPlaylistDirectory::GetDirectory(const CURL& url, CFileItemList& items)
44 // Load in the SmartPlaylist and get the WHERE query
45 CSmartPlaylist playlist;
46 if (!playlist.Load(url))
47 return false;
48 bool result = GetDirectory(playlist, items);
49 if (result)
50 items.SetProperty("library.smartplaylist", true);
52 return result;
55 bool CSmartPlaylistDirectory::GetDirectory(const CSmartPlaylist &playlist, CFileItemList& items, const std::string &strBaseDir /* = "" */, bool filter /* = false */)
57 bool success = false, success2 = false;
58 std::vector<std::string> virtualFolders;
60 SortDescription sorting;
61 if (playlist.GetLimit() > 0)
62 sorting.limitEnd = playlist.GetLimit();
63 sorting.sortBy = playlist.GetOrder();
64 sorting.sortOrder = playlist.GetOrderAscending() ? SortOrderAscending : SortOrderDescending;
65 sorting.sortAttributes = playlist.GetOrderAttributes();
66 if (CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_FILELISTS_IGNORETHEWHENSORTING))
67 sorting.sortAttributes = (SortAttribute)(sorting.sortAttributes | SortAttributeIgnoreArticle);
68 if (playlist.IsMusicType() && CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(
69 CSettings::SETTING_MUSICLIBRARY_USEARTISTSORTNAME))
70 sorting.sortAttributes =
71 static_cast<SortAttribute>(sorting.sortAttributes | SortAttributeUseArtistSortName);
72 items.SetSortIgnoreFolders((sorting.sortAttributes & SortAttributeIgnoreFolders) ==
73 SortAttributeIgnoreFolders);
75 std::string option = !filter ? "xsp" : "filter";
76 std::string group = playlist.GetGroup();
77 bool isGrouped = !group.empty() && !StringUtils::EqualsNoCase(group, "none") && !playlist.IsGroupMixed();
78 // Hint for playlist files like STRM
79 PLAYLIST::Id playlistTypeHint = PLAYLIST::TYPE_NONE;
81 // get all virtual folders and add them to the item list
82 playlist.GetVirtualFolders(virtualFolders);
83 for (const std::string& virtualFolder : virtualFolders)
85 CFileItemPtr pItem = CFileItemPtr(new CFileItem(virtualFolder, true));
86 IFileDirectory *dir = CFileDirectoryFactory::Create(pItem->GetURL(), pItem.get());
88 if (dir != NULL)
90 pItem->SetSpecialSort(SortSpecialOnTop);
91 items.Add(pItem);
92 delete dir;
96 if (playlist.GetType() == "movies" ||
97 playlist.GetType() == "tvshows" ||
98 playlist.GetType() == "episodes")
100 playlistTypeHint = PLAYLIST::TYPE_VIDEO;
101 CVideoDatabase db;
102 if (db.Open())
104 MediaType mediaType = CMediaTypes::FromString(playlist.GetType());
106 std::string baseDir = strBaseDir;
107 if (strBaseDir.empty())
109 if (mediaType == MediaTypeTvShow || mediaType == MediaTypeEpisode)
110 baseDir = "videodb://tvshows/";
111 else if (mediaType == MediaTypeMovie)
112 baseDir = "videodb://movies/";
113 else
114 return false;
116 if (!isGrouped)
117 baseDir += "titles";
118 else
119 baseDir += group;
120 URIUtils::AddSlashAtEnd(baseDir);
122 if (mediaType == MediaTypeEpisode)
123 baseDir += "-1/-1/";
126 CVideoDbUrl videoUrl;
127 if (!videoUrl.FromString(baseDir))
128 return false;
130 // store the smartplaylist as JSON in the URL as well
131 std::string xsp;
132 if (!playlist.IsEmpty(filter))
134 if (!playlist.SaveAsJson(xsp, !filter))
135 return false;
138 if (!xsp.empty())
139 videoUrl.AddOption(option, xsp);
140 else
141 videoUrl.RemoveOption(option);
143 CDatabase::Filter dbfilter;
144 success = db.GetItems(videoUrl.ToString(), items, dbfilter, sorting);
145 db.Close();
147 // if we retrieve a list of episodes and we didn't receive
148 // a pre-defined base path, we need to fix it
149 if (strBaseDir.empty() && mediaType == MediaTypeEpisode && !isGrouped)
150 videoUrl.AppendPath("-1/-1/");
151 items.SetProperty(PROPERTY_PATH_DB, videoUrl.ToString());
154 else if (playlist.IsMusicType() || playlist.GetType().empty())
156 playlistTypeHint = PLAYLIST::TYPE_MUSIC;
157 CMusicDatabase db;
158 if (db.Open())
160 CSmartPlaylist plist(playlist);
161 if (playlist.GetType() == "mixed" || playlist.GetType().empty())
162 plist.SetType("songs");
164 MediaType mediaType = CMediaTypes::FromString(plist.GetType());
166 std::string baseDir = strBaseDir;
167 if (strBaseDir.empty())
169 baseDir = "musicdb://";
170 if (!isGrouped)
172 if (mediaType == MediaTypeArtist)
173 baseDir += "artists";
174 else if (mediaType == MediaTypeAlbum)
175 baseDir += "albums";
176 else if (mediaType == MediaTypeSong)
177 baseDir += "songs";
178 else
179 return false;
181 else
182 baseDir += group;
184 URIUtils::AddSlashAtEnd(baseDir);
187 CMusicDbUrl musicUrl;
188 if (!musicUrl.FromString(baseDir))
189 return false;
191 // store the smartplaylist as JSON in the URL as well
192 std::string xsp;
193 if (!plist.IsEmpty(filter))
195 if (!plist.SaveAsJson(xsp, !filter))
196 return false;
199 if (!xsp.empty())
200 musicUrl.AddOption(option, xsp);
201 else
202 musicUrl.RemoveOption(option);
204 CDatabase::Filter dbfilter;
205 success = db.GetItems(musicUrl.ToString(), items, dbfilter, sorting);
206 db.Close();
208 items.SetProperty(PROPERTY_PATH_DB, musicUrl.ToString());
212 if (playlist.GetType() == "musicvideos" || playlist.GetType() == "mixed")
214 playlistTypeHint = PLAYLIST::TYPE_VIDEO;
215 CVideoDatabase db;
216 if (db.Open())
218 CSmartPlaylist mvidPlaylist(playlist);
219 if (playlist.GetType() == "mixed")
220 mvidPlaylist.SetType("musicvideos");
222 std::string baseDir = strBaseDir;
223 if (baseDir.empty())
225 baseDir = "videodb://musicvideos/";
227 if (!isGrouped)
228 baseDir += "titles";
229 else
230 baseDir += group;
231 URIUtils::AddSlashAtEnd(baseDir);
234 CVideoDbUrl videoUrl;
235 if (!videoUrl.FromString(baseDir))
236 return false;
238 // adjust the group in case we're retrieving a grouped playlist
239 // based on artists. This is needed because the video library
240 // is using the actorslink table for artists.
241 if (isGrouped && group == "artists")
243 group = "actors";
244 mvidPlaylist.SetGroup(group);
247 // store the smartplaylist as JSON in the URL as well
248 std::string xsp;
249 if (!mvidPlaylist.IsEmpty(filter))
251 if (!mvidPlaylist.SaveAsJson(xsp, !filter))
252 return false;
255 if (!xsp.empty())
256 videoUrl.AddOption(option, xsp);
257 else
258 videoUrl.RemoveOption(option);
260 CFileItemList items2;
261 CDatabase::Filter dbfilter;
262 success2 = db.GetItems(videoUrl.ToString(), items2, dbfilter, sorting);
264 db.Close();
265 if (items.Size() <= 0)
266 items.SetPath(videoUrl.ToString());
268 items.Append(items2);
269 if (items2.Size())
271 if (items.Size() > items2.Size())
272 items.SetContent("mixed");
273 else
274 items.SetContent("musicvideos");
276 items.SetProperty(PROPERTY_PATH_DB, videoUrl.ToString());
280 items.SetLabel(playlist.GetName());
281 if (isGrouped)
282 items.SetContent(group);
283 else
284 items.SetContent(playlist.GetType());
286 items.SetProperty(PROPERTY_SORT_ORDER, (int)playlist.GetOrder());
287 items.SetProperty(PROPERTY_SORT_ASCENDING, playlist.GetOrderDirection() == SortOrderAscending);
288 if (!group.empty())
290 items.SetProperty(PROPERTY_GROUP_BY, group);
291 items.SetProperty(PROPERTY_GROUP_MIXED, playlist.IsGroupMixed());
294 // sort grouped list by label
295 if (items.Size() > 1 && !group.empty())
296 items.Sort(SortByLabel, SortOrderAscending, CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(CSettings::SETTING_FILELISTS_IGNORETHEWHENSORTING) ? SortAttributeIgnoreArticle : SortAttributeNone);
298 // go through and set the playlist order
299 for (int i = 0; i < items.Size(); i++)
301 CFileItemPtr item = items[i];
302 item->m_iprogramCount = i; // hack for playlist order
303 item->SetProperty("playlist_type_hint", playlistTypeHint);
306 if (playlist.GetType() == "mixed")
307 return success || success2;
308 else if (playlist.GetType() == "musicvideos")
309 return success2;
310 else
311 return success;
314 bool CSmartPlaylistDirectory::ContainsFiles(const CURL& url)
316 // smart playlists always have files??
317 return true;
320 std::string CSmartPlaylistDirectory::GetPlaylistByName(const std::string& name, const std::string& playlistType)
322 CFileItemList list;
323 bool filesExist = false;
324 if (CSmartPlaylist::IsMusicType(playlistType))
325 filesExist = CDirectory::GetDirectory("special://musicplaylists/", list, ".xsp", DIR_FLAG_DEFAULTS);
326 else // all others are video
327 filesExist = CDirectory::GetDirectory("special://videoplaylists/", list, ".xsp", DIR_FLAG_DEFAULTS);
328 if (filesExist)
330 for (int i = 0; i < list.Size(); i++)
332 CFileItemPtr item = list[i];
333 CSmartPlaylist playlist;
334 if (playlist.OpenAndReadName(item->GetURL()))
336 if (StringUtils::EqualsNoCase(playlist.GetName(), name))
337 return item->GetPath();
340 for (int i = 0; i < list.Size(); i++)
341 { // check based on filename
342 CFileItemPtr item = list[i];
343 if (URIUtils::GetFileName(item->GetPath()) == name)
344 { // found :)
345 return item->GetPath();
349 return "";
352 bool CSmartPlaylistDirectory::Remove(const CURL& url)
354 return XFILE::CFile::Delete(url);