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.
9 #include "MusicDatabaseDirectory.h"
12 #include "MusicDatabaseDirectory/QueryParams.h"
13 #include "ServiceBroker.h"
14 #include "filesystem/File.h"
15 #include "guilib/LocalizeStrings.h"
16 #include "guilib/TextureManager.h"
17 #include "music/MusicDatabase.h"
18 #include "music/MusicDbUrl.h"
19 #include "settings/Settings.h"
20 #include "settings/SettingsComponent.h"
21 #include "utils/Crc32.h"
22 #include "utils/LegacyPathTranslation.h"
23 #include "utils/StringUtils.h"
24 #include "utils/URIUtils.h"
26 using namespace XFILE
;
27 using namespace MUSICDATABASEDIRECTORY
;
29 CMusicDatabaseDirectory::CMusicDatabaseDirectory(void) = default;
31 CMusicDatabaseDirectory::~CMusicDatabaseDirectory(void) = default;
33 bool CMusicDatabaseDirectory::GetDirectory(const CURL
& url
, CFileItemList
&items
)
35 std::string path
= CLegacyPathTranslation::TranslateMusicDbPath(url
);
37 // Adjust path to control navigation from albums to discs or directly to songs
41 GetDirectoryNodeInfo(path
, type
, childtype
, params
);
42 if (childtype
== NODE_TYPE_DISC
)
44 bool bFlatten
= false;
45 if (params
.GetAlbumId() < 0)
46 bFlatten
= true; // Showing *all albums next always songs
49 // Option to show discs for ordinary albums (not just boxed sets)
50 bFlatten
= !CServiceBroker::GetSettingsComponent()->GetSettings()->GetBool(
51 CSettings::SETTING_MUSICLIBRARY_SHOWDISCS
);
52 CMusicDatabase musicdatabase
;
53 if (musicdatabase
.Open())
55 if (bFlatten
) // Check for boxed set
56 bFlatten
= !musicdatabase
.IsAlbumBoxset(params
.GetAlbumId());
58 { // Check we will get more than 1 disc when path filter options applied
59 int iDiscTotal
= musicdatabase
.GetDiscsCount(path
);
60 bFlatten
= iDiscTotal
<= 1;
63 musicdatabase
.Close();
66 { // Skip discs level and go directly to songs
68 if (!musicUrl
.FromString(path
))
70 musicUrl
.AppendPath("-2/"); // Flattened so adjust list label etc.
71 path
= musicUrl
.ToString();
76 items
.m_dwSize
= -1; // No size
78 std::unique_ptr
<CDirectoryNode
> pNode(CDirectoryNode::ParseURL(path
));
83 bool bResult
= pNode
->GetChilds(items
);
84 for (int i
=0;i
<items
.Size();++i
)
86 CFileItemPtr item
= items
[i
];
87 if (item
->m_bIsFolder
&& !item
->HasArt("icon") && !item
->HasArt("thumb"))
89 std::string strImage
= GetIcon(item
->GetPath());
90 if (!strImage
.empty() && CServiceBroker::GetGUI()->GetTextureManager().HasTexture(strImage
))
91 item
->SetArt("icon", strImage
);
94 if (items
.GetLabel().empty())
95 items
.SetLabel(pNode
->GetLocalizedName());
100 NODE_TYPE
CMusicDatabaseDirectory::GetDirectoryChildType(const std::string
& strPath
)
102 std::string path
= CLegacyPathTranslation::TranslateMusicDbPath(strPath
);
103 std::unique_ptr
<CDirectoryNode
> pNode(CDirectoryNode::ParseURL(path
));
106 return NODE_TYPE_NONE
;
108 return pNode
->GetChildType();
111 NODE_TYPE
CMusicDatabaseDirectory::GetDirectoryType(const std::string
& strPath
)
113 std::string path
= CLegacyPathTranslation::TranslateMusicDbPath(strPath
);
114 std::unique_ptr
<CDirectoryNode
> pNode(CDirectoryNode::ParseURL(path
));
117 return NODE_TYPE_NONE
;
119 return pNode
->GetType();
122 NODE_TYPE
CMusicDatabaseDirectory::GetDirectoryParentType(const std::string
& strPath
)
124 std::string path
= CLegacyPathTranslation::TranslateMusicDbPath(strPath
);
125 std::unique_ptr
<CDirectoryNode
> pNode(CDirectoryNode::ParseURL(path
));
128 return NODE_TYPE_NONE
;
130 CDirectoryNode
* pParentNode
=pNode
->GetParent();
133 return NODE_TYPE_NONE
;
135 return pParentNode
->GetChildType();
138 bool CMusicDatabaseDirectory::GetDirectoryNodeInfo(const std::string
& strPath
,
139 MUSICDATABASEDIRECTORY::NODE_TYPE
& type
,
140 MUSICDATABASEDIRECTORY::NODE_TYPE
& childtype
,
141 MUSICDATABASEDIRECTORY::CQueryParams
& params
)
143 std::string path
= CLegacyPathTranslation::TranslateMusicDbPath(strPath
);
144 if (!CDirectoryNode::GetNodeInfo(path
, type
, childtype
, params
))
150 bool CMusicDatabaseDirectory::IsArtistDir(const std::string
& strDirectory
)
152 NODE_TYPE node
=GetDirectoryType(strDirectory
);
153 return (node
==NODE_TYPE_ARTIST
);
156 void CMusicDatabaseDirectory::ClearDirectoryCache(const std::string
& strDirectory
)
158 std::string path
= CLegacyPathTranslation::TranslateMusicDbPath(strDirectory
);
159 URIUtils::RemoveSlashAtEnd(path
);
161 uint32_t crc
= Crc32::ComputeFromLowerCase(path
);
163 std::string strFileName
= StringUtils::Format("special://temp/archive_cache/{:08x}.fi", crc
);
164 CFile::Delete(strFileName
);
167 bool CMusicDatabaseDirectory::IsAllItem(const std::string
& strDirectory
)
169 //Last query parameter, ignoring any appended options, is -1 or -2
170 CURL
url(strDirectory
);
171 if (StringUtils::EndsWith(url
.GetWithoutOptions(), "/-1/") || // any albumid
172 StringUtils::EndsWith(url
.GetWithoutOptions(), "/-1/-2/")) // any albumid + flattened
177 bool CMusicDatabaseDirectory::GetLabel(const std::string
& strDirectory
, std::string
& strLabel
)
181 std::string path
= CLegacyPathTranslation::TranslateMusicDbPath(strDirectory
);
182 std::unique_ptr
<CDirectoryNode
> pNode(CDirectoryNode::ParseURL(path
));
186 // first see if there's any filter criteria
188 CDirectoryNode::GetDatabaseInfo(path
, params
);
190 CMusicDatabase musicdatabase
;
191 if (!musicdatabase
.Open())
195 if (params
.GetGenreId() >= 0)
196 strLabel
+= musicdatabase
.GetGenreById(params
.GetGenreId());
199 if (params
.GetArtistId() >= 0)
201 if (!strLabel
.empty())
203 strLabel
+= musicdatabase
.GetArtistById(params
.GetArtistId());
207 if (params
.GetAlbumId() >= 0)
209 if (!strLabel
.empty())
211 strLabel
+= musicdatabase
.GetAlbumById(params
.GetAlbumId());
214 if (strLabel
.empty())
216 switch (pNode
->GetChildType())
218 case NODE_TYPE_TOP100
:
219 strLabel
= g_localizeStrings
.Get(271); // Top 100
221 case NODE_TYPE_GENRE
:
222 strLabel
= g_localizeStrings
.Get(135); // Genres
224 case NODE_TYPE_SOURCE
:
225 strLabel
= g_localizeStrings
.Get(39030); // Sources
228 strLabel
= g_localizeStrings
.Get(38033); // Roles
230 case NODE_TYPE_ARTIST
:
231 strLabel
= g_localizeStrings
.Get(133); // Artists
233 case NODE_TYPE_ALBUM
:
234 strLabel
= g_localizeStrings
.Get(132); // Albums
236 case NODE_TYPE_ALBUM_RECENTLY_ADDED
:
237 case NODE_TYPE_ALBUM_RECENTLY_ADDED_SONGS
:
238 strLabel
= g_localizeStrings
.Get(359); // Recently Added Albums
240 case NODE_TYPE_ALBUM_RECENTLY_PLAYED
:
241 case NODE_TYPE_ALBUM_RECENTLY_PLAYED_SONGS
:
242 strLabel
= g_localizeStrings
.Get(517); // Recently Played Albums
244 case NODE_TYPE_ALBUM_TOP100
:
245 case NODE_TYPE_ALBUM_TOP100_SONGS
:
246 strLabel
= g_localizeStrings
.Get(10505); // Top 100 Albums
248 case NODE_TYPE_SINGLES
:
249 strLabel
= g_localizeStrings
.Get(1050); // Singles
252 strLabel
= g_localizeStrings
.Get(134); // Songs
254 case NODE_TYPE_SONG_TOP100
:
255 strLabel
= g_localizeStrings
.Get(10504); // Top 100 Songs
258 strLabel
= g_localizeStrings
.Get(652); // Years
260 case NODE_TYPE_OVERVIEW
:
271 bool CMusicDatabaseDirectory::ContainsSongs(const std::string
&path
)
273 MUSICDATABASEDIRECTORY::NODE_TYPE type
= GetDirectoryChildType(path
);
274 if (type
== MUSICDATABASEDIRECTORY::NODE_TYPE_SONG
) return true;
275 if (type
== MUSICDATABASEDIRECTORY::NODE_TYPE_SINGLES
) return true;
276 if (type
== MUSICDATABASEDIRECTORY::NODE_TYPE_ALBUM_RECENTLY_ADDED_SONGS
) return true;
277 if (type
== MUSICDATABASEDIRECTORY::NODE_TYPE_ALBUM_RECENTLY_PLAYED_SONGS
) return true;
278 if (type
== MUSICDATABASEDIRECTORY::NODE_TYPE_ALBUM_TOP100_SONGS
) return true;
279 if (type
== MUSICDATABASEDIRECTORY::NODE_TYPE_SONG_TOP100
) return true;
280 if (type
== MUSICDATABASEDIRECTORY::NODE_TYPE_DISC
) return true;
284 bool CMusicDatabaseDirectory::Exists(const CURL
& url
)
286 std::string path
= CLegacyPathTranslation::TranslateMusicDbPath(url
);
287 std::unique_ptr
<CDirectoryNode
> pNode(CDirectoryNode::ParseURL(path
));
292 if (pNode
->GetChildType() == MUSICDATABASEDIRECTORY::NODE_TYPE_NONE
)
298 bool CMusicDatabaseDirectory::CanCache(const std::string
& strPath
)
300 std::string path
= CLegacyPathTranslation::TranslateMusicDbPath(strPath
);
301 std::unique_ptr
<CDirectoryNode
> pNode(CDirectoryNode::ParseURL(path
));
304 return pNode
->CanCache();
307 std::string
CMusicDatabaseDirectory::GetIcon(const std::string
&strDirectory
)
309 switch (GetDirectoryChildType(strDirectory
))
311 case NODE_TYPE_ARTIST
:
312 return "DefaultMusicArtists.png";
313 case NODE_TYPE_GENRE
:
314 return "DefaultMusicGenres.png";
315 case NODE_TYPE_SOURCE
:
316 return "DefaultMusicSources.png";
318 return "DefaultMusicRoles.png";
319 case NODE_TYPE_TOP100
:
320 return "DefaultMusicTop100.png";
321 case NODE_TYPE_ALBUM
:
322 return "DefaultMusicAlbums.png";
323 case NODE_TYPE_ALBUM_RECENTLY_ADDED
:
324 case NODE_TYPE_ALBUM_RECENTLY_ADDED_SONGS
:
325 return "DefaultMusicRecentlyAdded.png";
326 case NODE_TYPE_ALBUM_RECENTLY_PLAYED
:
327 case NODE_TYPE_ALBUM_RECENTLY_PLAYED_SONGS
:
328 return "DefaultMusicRecentlyPlayed.png";
329 case NODE_TYPE_SINGLES
:
331 return "DefaultMusicSongs.png";
332 case NODE_TYPE_ALBUM_TOP100
:
333 case NODE_TYPE_ALBUM_TOP100_SONGS
:
334 return "DefaultMusicTop100Albums.png";
335 case NODE_TYPE_SONG_TOP100
:
336 return "DefaultMusicTop100Songs.png";
338 return "DefaultMusicYears.png";