1 #include "stdafx.h"
2 #include "UiMediaLibItemMgr.h"
3 #include "MusicPlayer2.h"
4 #include "Playlist.h"
5 #include "SongDataManager.h"
6 #include "SongInfoHelper.h"
7 #include "CRecentList.h"
8 #include "Player.h"
9
10 CUiMediaLibItemMgr CUiMediaLibItemMgr::m_instance;
11
~CUiMediaLibItemMgr()12 CUiMediaLibItemMgr::~CUiMediaLibItemMgr()
13 {
14 }
15
Instance()16 CUiMediaLibItemMgr& CUiMediaLibItemMgr::Instance()
17 {
18 return m_instance;
19 }
20
GetClassifiedMeidaLibItemList(CMediaClassifier::ClassificationType type)21 void CUiMediaLibItemMgr::GetClassifiedMeidaLibItemList(CMediaClassifier::ClassificationType type)
22 {
23 auto& item_list{ m_item_map[type] };
24 item_list.clear();
25 CMediaClassifier classifier(type, theApp.m_media_lib_setting_data.hide_only_one_classification);
26 classifier.ClassifyMedia();
27 for (const auto& item : classifier.GetMeidaList())
28 {
29 if (item.first != STR_OTHER_CLASSIFY_TYPE)
30 {
31 ItemInfo info;
32 info.name = item.first;
33 info.count = item.second.size();
34 item_list.push_back(info);
35 }
36 }
37 }
38
Init()39 void CUiMediaLibItemMgr::Init()
40 {
41 m_loading = true;
42 std::shared_lock<std::shared_mutex> lock(m_shared_mutex);
43
44 GetClassifiedMeidaLibItemList(CMediaClassifier::CT_ARTIST);
45 GetClassifiedMeidaLibItemList(CMediaClassifier::CT_ALBUM);
46 GetClassifiedMeidaLibItemList(CMediaClassifier::CT_GENRE);
47 GetClassifiedMeidaLibItemList(CMediaClassifier::CT_YEAR);
48 GetClassifiedMeidaLibItemList(CMediaClassifier::CT_TYPE);
49 GetClassifiedMeidaLibItemList(CMediaClassifier::CT_BITRATE);
50 GetClassifiedMeidaLibItemList(CMediaClassifier::CT_RATING);
51
52 m_loading = false;
53 m_inited = true;
54 }
55
GetItemCount(CMediaClassifier::ClassificationType type) const56 int CUiMediaLibItemMgr::GetItemCount(CMediaClassifier::ClassificationType type) const
57 {
58 if (!m_loading)
59 {
60 auto iter = m_item_map.find(type);
61 if (iter != m_item_map.end())
62 return static_cast<int>(iter->second.size());
63 }
64 return 0;
65 }
66
GetItemDisplayName(CMediaClassifier::ClassificationType type,int index) const67 std::wstring CUiMediaLibItemMgr::GetItemDisplayName(CMediaClassifier::ClassificationType type, int index) const
68 {
69 if (!m_loading)
70 {
71 const std::wstring& name{ GetItemName(type, index) };
72 ListItem list_item{ LT_MEDIA_LIB, name };
73 list_item.medialib_type = type;
74 return list_item.GetDisplayName();
75 }
76 return std::wstring();
77 }
78
GetItemInfo(CMediaClassifier::ClassificationType type,int index) const79 const CUiMediaLibItemMgr::ItemInfo& CUiMediaLibItemMgr::GetItemInfo(CMediaClassifier::ClassificationType type, int index) const
80 {
81 if (!m_loading)
82 {
83 auto iter = m_item_map.find(type);
84 if (iter != m_item_map.end())
85 {
86 const auto& item_list{ iter->second };
87 if (index >= 0 && index < static_cast<int>(item_list.size()))
88 {
89 return item_list[index];
90 }
91 }
92 }
93 static ItemInfo empty_info{};
94 return empty_info;
95 }
96
GetItemName(CMediaClassifier::ClassificationType type,int index) const97 const std::wstring& CUiMediaLibItemMgr::GetItemName(CMediaClassifier::ClassificationType type, int index) const
98 {
99 return GetItemInfo(type, index).name;
100 }
101
GetItemSongCount(CMediaClassifier::ClassificationType type,int index) const102 int CUiMediaLibItemMgr::GetItemSongCount(CMediaClassifier::ClassificationType type, int index) const
103 {
104 return GetItemInfo(type, index).count;
105 }
106
SetCurrentName(CMediaClassifier::ClassificationType type,const std::wstring & name)107 void CUiMediaLibItemMgr::SetCurrentName(CMediaClassifier::ClassificationType type, const std::wstring& name)
108 {
109 m_current_name_map[type] = name;
110 m_current_index_map.erase(type);
111 }
112
GetCurrentIndex(CMediaClassifier::ClassificationType type)113 int CUiMediaLibItemMgr::GetCurrentIndex(CMediaClassifier::ClassificationType type)
114 {
115 if (!m_loading)
116 {
117 auto index_iter = m_current_index_map.find(type);
118 if (index_iter == m_current_index_map.end())
119 {
120 //根据名称查找所在的序号
121 auto name_iter = m_current_name_map.find(type);
122 if (name_iter != m_current_name_map.end())
123 {
124 const auto& name_list{ m_item_map[type] };
125 auto iter = std::find_if(name_list.begin(), name_list.end(), [&](const ItemInfo& item) {
126 return item.name == name_iter->second;
127 });
128 if (iter != name_list.end())
129 {
130 int index = iter - name_list.begin();
131 //设置当前项目的序号
132 m_current_index_map[type] = index;
133 return index;
134 }
135 }
136 }
137 else
138 {
139 return index_iter->second;
140 }
141 }
142
143 return -1;
144 }
145
CUiMediaLibItemMgr()146 CUiMediaLibItemMgr::CUiMediaLibItemMgr()
147 {
148 }
149
150
151 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
152 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
153 CUiMyFavouriteItemMgr CUiMyFavouriteItemMgr::m_instance;
154
~CUiMyFavouriteItemMgr()155 CUiMyFavouriteItemMgr::~CUiMyFavouriteItemMgr()
156 {
157 }
158
Instance()159 CUiMyFavouriteItemMgr& CUiMyFavouriteItemMgr::Instance()
160 {
161 return m_instance;
162 }
163
GetSongCount() const164 int CUiMyFavouriteItemMgr::GetSongCount() const
165 {
166 if (!m_loading)
167 return static_cast<int>(m_may_favourite_song_list.size());
168 else
169 return 0;
170 }
171
GetSongInfo(int index) const172 const SongInfo& CUiMyFavouriteItemMgr::GetSongInfo(int index) const
173 {
174 if (!m_loading)
175 {
176 if (index >= 0 && index < GetSongCount())
177 return m_may_favourite_song_list[index];
178 }
179 static SongInfo empty_song;
180 return empty_song;
181 }
182
UpdateMyFavourite()183 void CUiMyFavouriteItemMgr::UpdateMyFavourite()
184 {
185 m_loading = true;
186 std::shared_lock<std::shared_mutex> lock(m_shared_mutex);
187
188 ListItem list_item = CRecentList::Instance().GetSpecPlaylist(CRecentList::PT_FAVOURITE);
189 CPlaylistFile playlist_file;
190 playlist_file.LoadFromFile(list_item.path);
191 playlist_file.MoveToSongList(m_may_favourite_song_list);
192 CSongDataManager::GetInstance().LoadSongsInfo(m_may_favourite_song_list); // 从媒体库加载歌曲属性
193
194 m_loading = false;
195 m_inited = true;
196 }
197
GetSongList(std::vector<SongInfo> & song_list) const198 void CUiMyFavouriteItemMgr::GetSongList(std::vector<SongInfo>& song_list) const
199 {
200 std::copy(m_may_favourite_song_list.begin(), m_may_favourite_song_list.end(), std::back_inserter(song_list));
201 }
202
Contains(const SongInfo & song) const203 bool CUiMyFavouriteItemMgr::Contains(const SongInfo& song) const
204 {
205 auto iter = std::find_if(m_may_favourite_song_list.begin(), m_may_favourite_song_list.end(), [&](const SongInfo& a) {
206 return a.IsSameSong(song);
207 });
208 return iter != m_may_favourite_song_list.end();
209 }
210
CUiMyFavouriteItemMgr()211 CUiMyFavouriteItemMgr::CUiMyFavouriteItemMgr()
212 {
213 }
214
215 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
216 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
217 CUiAllTracksMgr CUiAllTracksMgr::m_instance;
218
~CUiAllTracksMgr()219 CUiAllTracksMgr::~CUiAllTracksMgr()
220 {
221 }
222
Instance()223 CUiAllTracksMgr& CUiAllTracksMgr::Instance()
224 {
225 return m_instance;
226 }
227
GetSongCount() const228 int CUiAllTracksMgr::GetSongCount() const
229 {
230 if (!m_loading)
231 return static_cast<int>(m_all_tracks_list.size());
232 else
233 return 0;
234 }
235
GetSongInfo(int index) const236 SongInfo CUiAllTracksMgr::GetSongInfo(int index) const
237 {
238 if (!m_loading)
239 {
240 if (index >= 0 && index < GetSongCount())
241 return CSongDataManager::GetInstance().GetSongInfo(m_all_tracks_list[index].song_key);
242 }
243 static SongInfo empty_song;
244 return empty_song;
245 }
246
GetItem(int index) const247 const CUiAllTracksMgr::UTrackInfo& CUiAllTracksMgr::GetItem(int index) const
248 {
249 if (!m_loading)
250 {
251 if (index >= 0 && index < GetSongCount())
252 return m_all_tracks_list[index];
253 }
254 static UTrackInfo empty_item;
255 return empty_item;
256 }
257
GetCurrentIndex() const258 int CUiAllTracksMgr::GetCurrentIndex() const
259 {
260 return m_current_index;
261 }
262
SetCurrentSong(const SongInfo & song)263 void CUiAllTracksMgr::SetCurrentSong(const SongInfo& song)
264 {
265 if (!m_loading && m_inited && !song.IsEmpty())
266 {
267 int index{};
268 for (const auto& item : m_all_tracks_list)
269 {
270 if (std::equal_to<SongKey>()(SongKey(song), item.song_key))
271 {
272 m_current_index = index;
273 break;
274 }
275 index++;
276 }
277 }
278 }
279
UpdateAllTracks()280 void CUiAllTracksMgr::UpdateAllTracks()
281 {
282 m_loading = true;
283 std::shared_lock<std::shared_mutex> lock(m_shared_mutex);
284
285 m_all_tracks_list.clear();
286 vector<SongInfo> tmp_song_list;
287 //从song data中读取
288 CSongDataManager::GetInstance().GetSongData([&](const CSongDataManager::SongDataMap& song_data_map) {
289 tmp_song_list.reserve(song_data_map.size());
290 std::transform(song_data_map.begin(), song_data_map.end(), std::back_inserter(tmp_song_list), [](const auto& item) { return item.second; });
291 });
292
293 //从CRecentList中查找“所有曲目”,并获取排序方式
294 ListItem list_item{ LT_MEDIA_LIB, L"" };
295 list_item.medialib_type = CMediaClassifier::CT_NONE;
296 CRecentList::Instance().LoadItem(list_item);
297 //对所有曲目排序
298 auto sort_fun = SongInfo::GetSortFunc(list_item.GetDefaultSortMode());
299 std::stable_sort(tmp_song_list.begin(), tmp_song_list.end(), sort_fun);
300 std::transform(tmp_song_list.begin(), tmp_song_list.end(), std::back_inserter(m_all_tracks_list), [](const SongInfo& song_info) {
301 UTrackInfo item;
302 item.song_key = song_info;
303 item.name = CSongInfoHelper::GetDisplayStr(song_info, theApp.m_media_lib_setting_data.display_format);
304 item.length = song_info.length();
305 item.is_favourite = CUiMyFavouriteItemMgr::Instance().Contains(song_info);
306 return item;
307 });
308 m_loading = false;
309 m_inited = true;
310 }
311
GetSongList(std::vector<SongInfo> & song_list) const312 void CUiAllTracksMgr::GetSongList(std::vector<SongInfo>& song_list) const
313 {
314 for (const auto& item : m_all_tracks_list)
315 {
316 SongInfo song{ CSongDataManager::GetInstance().GetSongInfo(item.song_key) };
317 song_list.push_back(song);
318 }
319 }
320
AddOrRemoveMyFavourite(int index)321 void CUiAllTracksMgr::AddOrRemoveMyFavourite(int index)
322 {
323 if (!m_loading && m_inited && index >= 0 && index < GetSongCount())
324 {
325 m_all_tracks_list[index].is_favourite = !m_all_tracks_list[index].is_favourite;
326 }
327 }
328
CUiAllTracksMgr()329 CUiAllTracksMgr::CUiAllTracksMgr()
330 {
331 }
332
333 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
334 //////////////////////////////////////////////////////////////////////////////////////////////////////////////
335 CUiFolderExploreMgr CUiFolderExploreMgr::m_instance;
336
Instance()337 CUiFolderExploreMgr& CUiFolderExploreMgr::Instance()
338 {
339 return m_instance;
340 }
341
GetRootNodes()342 std::vector<std::shared_ptr<UiElement::TreeElement::Node>>& CUiFolderExploreMgr::GetRootNodes()
343 {
344 if (m_loading)
345 {
346 static std::vector<std::shared_ptr<UiElement::TreeElement::Node>> empty_nodes;
347 return empty_nodes;
348 }
349 else
350 {
351 return m_root_nodes;
352 }
353 }
354
UpdateFolders()355 void CUiFolderExploreMgr::UpdateFolders()
356 {
357 m_loading = true;
358
359 m_root_nodes.clear();
360
361 //这里等待播放内核加载完成,否则无法判断文件夹内音频文件数量
362 while (!CPlayer::GetInstance().IsPlayerCoreInited())
363 {
364 Sleep(20);
365 }
366
367 //获取媒体库目录
368 for (const auto& default_folder : theApp.m_media_lib_setting_data.media_folders)
369 {
370 int audo_file_count = GetAudioFilesNum(default_folder);
371 auto root_node = UiElement::FolderExploreTree::CreateNode(default_folder, audo_file_count, nullptr);
372 root_node->collapsed = false; //默认展开顶级节点
373 m_root_nodes.push_back(root_node);
374 CreateFolderNodeByPath(default_folder, root_node);
375 }
376
377 m_loading = false;
378 }
379
CUiFolderExploreMgr()380 CUiFolderExploreMgr::CUiFolderExploreMgr()
381 {
382 }
383
CreateFolderNodeByPath(std::wstring path,std::shared_ptr<UiElement::TreeElement::Node> parent)384 void CUiFolderExploreMgr::CreateFolderNodeByPath(std::wstring path, std::shared_ptr<UiElement::TreeElement::Node> parent)
385 {
386 //文件句柄
387 intptr_t hFile = 0;
388 //文件信息
389 _wfinddata_t fileinfo;
390 if (path.back() != '\\' && path.back() != '/')
391 path.push_back('\\');
392 if ((hFile = _wfindfirst((path + L"*").c_str(), &fileinfo)) != -1)
393 {
394 do
395 {
396 std::wstring file_name = fileinfo.name;
397 if (file_name == L"." || file_name == L"..")
398 continue;
399
400 std::wstring sub_file_path = path + file_name;
401 int audo_file_count = GetAudioFilesNum(sub_file_path);
402 if (CCommon::IsFolder(sub_file_path) && audo_file_count > 0) //当前是文件夹且包含音频文件,则递归调用
403 {
404 auto sub_node = UiElement::FolderExploreTree::CreateNode(file_name, audo_file_count, parent);
405 CreateFolderNodeByPath(sub_file_path, sub_node);
406 }
407 } while (_wfindnext(hFile, &fileinfo) == 0);
408 }
409 _findclose(hFile);
410 }
411
GetAudioFilesNum(std::wstring path)412 int CUiFolderExploreMgr::GetAudioFilesNum(std::wstring path)
413 {
414 if (path.back() != '\\' && path.back() != '/')
415 path.push_back('\\');
416
417 auto iter = m_folder_audio_files_num.find(path);
418 if (iter != m_folder_audio_files_num.end())
419 {
420 return iter->second;
421 }
422 else
423 {
424 int audio_file_count = 0;
425 //文件句柄
426 intptr_t hFile = 0;
427 //文件信息
428 _wfinddata_t fileinfo;
429 if ((hFile = _wfindfirst((path + L"*").c_str(), &fileinfo)) != -1)
430 {
431 do
432 {
433 wstring file_name = fileinfo.name;
434 if (file_name == L"." || file_name == L"..")
435 continue;
436
437 if (CCommon::IsFolder(path + file_name)) //是文件夹,则递归调用
438 {
439 audio_file_count += GetAudioFilesNum(path + file_name);
440 }
441 else
442 {
443 if (CAudioCommon::FileIsAudio(path + file_name)) //找到了音频文件
444 audio_file_count++;
445 }
446 } while (_wfindnext(hFile, &fileinfo) == 0);
447 }
448 _findclose(hFile);
449
450 m_folder_audio_files_num[path] = audio_file_count;
451 return audio_file_count;
452 }
453 }
454