1 #include "stdafx.h"
2 #include "MediaLibHelper.h"
3 #include "MusicPlayer2.h"
4 #include "SongDataManager.h"
5 #include "FilePathHelper.h"
6
7
operator ()(const std::wstring & a,const std::wstring & b) const8 bool StringComparerNoCase::operator()(const std::wstring& a, const std::wstring& b) const
9 {
10 return CCommon::StringCompareInLocalLanguage(a, b, true) < 0;
11 }
12
CMediaClassifier(ClassificationType type,bool hide_only_one_classification)13 CMediaClassifier::CMediaClassifier(ClassificationType type, bool hide_only_one_classification)
14 : m_type(type), m_hide_only_one_classification(hide_only_one_classification)
15 {
16 }
17
18
~CMediaClassifier()19 CMediaClassifier::~CMediaClassifier()
20 {
21 }
22
GetMeidaList() const23 const CMediaClassifier::MediaList& CMediaClassifier::GetMeidaList() const
24 {
25 return m_media_list;
26 }
27
GetMeidaList()28 CMediaClassifier::MediaList& CMediaClassifier::GetMeidaList()
29 {
30 return m_media_list;
31 }
32
ClassifyMedia()33 void CMediaClassifier::ClassifyMedia()
34 {
35 m_media_list.clear();
36 CSongDataManager::GetInstance().GetSongData([&](const CSongDataManager::SongDataMap& song_data_map)
37 {
38 for (const auto& song_info : song_data_map)
39 {
40 std::vector<std::wstring> item_names;
41 switch (m_type)
42 {
43 case CMediaClassifier::CT_ARTIST:
44 {
45 static const wstring& default_artist = theApp.m_str_table.LoadText(L"TXT_EMPTY_ARTIST");
46 song_info.second.GetArtistList(item_names); // 有的歌曲可能有多个艺术家,将解析到的艺术家保存到vector里
47 for (auto& item_name : item_names)
48 CCommon::StringNormalize(item_name);
49 if (item_names.empty() || (item_names.size() == 1 && default_artist == item_names[0]))
50 {
51 item_names.clear();
52 item_names.push_back(std::wstring());
53 }
54 }
55 break;
56 case CMediaClassifier::CT_ALBUM:
57 {
58 static const wstring& default_album = theApp.m_str_table.LoadText(L"TXT_EMPTY_ALBUM");
59 wstring str_album = song_info.second.album;
60 if (default_album == str_album)
61 str_album.clear();
62 item_names.push_back(str_album);
63 }
64 break;
65 case CMediaClassifier::CT_GENRE:
66 {
67 static const wstring& default_genre = theApp.m_str_table.LoadText(L"TXT_EMPTY_GENRE");
68 wstring str_genre = song_info.second.genre;
69 if (default_genre == str_genre)
70 str_genre.clear();
71 item_names.push_back(str_genre);
72 }
73 break;
74 case CMediaClassifier::CT_YEAR:
75 {
76 static const wstring& default_year = theApp.m_str_table.LoadText(L"TXT_EMPTY_YEAR");
77 wstring str_year = song_info.second.get_year();
78 if (default_year == str_year)
79 str_year.clear();
80 if (str_year.size() > 4)
81 str_year.resize(4);
82 item_names.push_back(str_year);
83 }
84 break;
85 case CMediaClassifier::CT_TYPE:
86 {
87 wstring str_type = CFilePathHelper(song_info.first.path).GetFileExtension();
88 item_names.push_back(str_type);
89 }
90 break;
91 case CMediaClassifier::CT_BITRATE:
92 {
93 wstring str_type;
94 if (song_info.second.bitrate == 0)
95 str_type = L"-";
96 else if (song_info.second.bitrate < 32)
97 str_type = L"<32";
98 else if (song_info.second.bitrate < 64)
99 str_type = L"32+";
100 else if (song_info.second.bitrate < 128)
101 str_type = L"64+";
102 else if (song_info.second.bitrate < 192)
103 str_type = L"128+";
104 else if (song_info.second.bitrate < 300)
105 str_type = L"192+";
106 else if (song_info.second.bitrate < 512)
107 str_type = L"300+";
108 else if (song_info.second.bitrate < 1024)
109 str_type = L"512+";
110 else
111 str_type = L"1024+";
112 item_names.push_back(str_type);
113 }
114 break;
115 case CT_RATING:
116 {
117 wstring str_type;
118 if (song_info.second.rating >= 1 && song_info.second.rating <= 5)
119 str_type = std::to_wstring(song_info.second.rating);
120 else
121 str_type = theApp.m_str_table.LoadText(L"TXT_EMPTY_RATED");
122 item_names.push_back(str_type);
123 break;
124 }
125 default:
126 break;
127 }
128
129 for (const auto& item_name : item_names)
130 {
131 auto iter = m_media_list.find(item_name);
132 if (iter != m_media_list.end())
133 iter->second.push_back(song_info.second);
134 else
135 m_media_list[item_name].push_back(song_info.second);
136 }
137 }
138 });
139
140 std::vector<SongInfo> other_list;
141
142 //查找只有一个项目的分类,将其归到“其他”类里
143 if (m_hide_only_one_classification && (m_type == CT_ARTIST || m_type == CT_ALBUM || m_type == CT_GENRE))
144 {
145 for (auto iter{ m_media_list.begin() }; iter != m_media_list.end();)
146 {
147 if (iter->second.size() == 1)
148 {
149 //确保其他类列表里的项目不会重复
150 if (!CCommon::IsItemInVector(other_list, [&](const SongInfo& item) {
151 return item.file_path == iter->second[0].file_path;
152 }))
153 {
154 other_list.push_back(iter->second[0]);
155 }
156 iter = m_media_list.erase(iter);
157 }
158 else
159 {
160 ++iter;
161 }
162 }
163 if (m_type == CT_ARTIST)
164 std::sort(other_list.begin(), other_list.end(), SongInfo::GetSortFunc(SM_U_ARTIST));
165 else if (m_type == CT_ALBUM)
166 std::sort(other_list.begin(), other_list.end(), SongInfo::GetSortFunc(SM_U_ALBUM));
167 else if (m_type == CT_GENRE)
168 std::sort(other_list.begin(), other_list.end(), SongInfo::GetSortFunc(SM_U_GENRE));
169 //else if (m_type == CT_YEAR)
170 // std::sort(other_list.begin(), other_list.end(), SongInfo::GetSortFunc(SM_U_YEAR));
171 if (!other_list.empty())
172 m_media_list[STR_OTHER_CLASSIFY_TYPE] = other_list;
173 }
174
175 //将年份不是4位数字的归到“其他”类里
176 if (m_type == CT_YEAR)
177 {
178 for (auto iter{ m_media_list.begin() }; iter != m_media_list.end();)
179 {
180 if (!iter->first.empty() && !IsStringYear(iter->first)) //如果年份不是4位数字,则添加到其他列表里
181 {
182 other_list.insert(other_list.end(), iter->second.begin(), iter->second.end());
183 iter = m_media_list.erase(iter);
184 }
185 else
186 {
187 ++iter;
188 }
189 }
190 if (!other_list.empty())
191 m_media_list[STR_OTHER_CLASSIFY_TYPE] = other_list;
192 }
193
194 for (auto& item : m_media_list)
195 {
196 if (item.first != STR_OTHER_CLASSIFY_TYPE)
197 {
198 if (m_type == CT_ALBUM) //“唱片集”类别中,默认按音轨序号排序
199 std::sort(item.second.begin(), item.second.end(), SongInfo::GetSortFunc(SM_U_TRACK));
200 else //其他类别默认按文件路径排序
201 std::sort(item.second.begin(), item.second.end(), SongInfo::GetSortFunc(SM_U_PATH));
202 }
203 }
204 }
205
IsStringYear(std::wstring str)206 bool CMediaClassifier::IsStringYear(std::wstring str)
207 {
208 if (str.size() < 4)
209 return false;
210 str.resize(4);
211
212 for (size_t i = 0; i < 4; i++)
213 {
214 if (str[i] < L'0' || str[i] > L'9')
215 return false;
216 }
217
218 return str > L"1000" && str < L"3000";
219 }
220
ClearResult()221 void CMediaClassifier::ClearResult()
222 {
223 m_media_list.clear();
224 }
225
RemoveFiles(std::vector<SongInfo> songs)226 void CMediaClassifier::RemoveFiles(std::vector<SongInfo> songs)
227 {
228 auto isRemoved = [&](const SongInfo& song)
229 {
230 for (const auto& item : songs)
231 {
232 if (item.IsSameSong(song))
233 return true;
234 }
235 return false;
236 };
237 for (auto& item : m_media_list)
238 {
239 auto iter_removed = std::remove_if(item.second.begin(), item.second.end(), isRemoved);
240 item.second.erase(iter_removed, item.second.end());
241 }
242 }
243
SetHideOnlyOneClassification(bool hide_only_one_classification)244 void CMediaClassifier::SetHideOnlyOneClassification(bool hide_only_one_classification)
245 {
246 m_hide_only_one_classification = hide_only_one_classification;
247 }
248