1 #include "stdafx.h"
2 #include "SongDataManager.h"
3 #include "MusicPlayer2.h"
4 #include "FilePathHelper.h"
5
6 CSongDataManager CSongDataManager::m_instance;
7
CSongDataManager()8 CSongDataManager::CSongDataManager()
9 {
10 }
11
~CSongDataManager()12 CSongDataManager::~CSongDataManager()
13 {
14 }
15
GetInstance()16 CSongDataManager& CSongDataManager::GetInstance()
17 {
18 return m_instance;
19 }
20
SaveSongData(std::wstring path)21 void CSongDataManager::SaveSongData(std::wstring path)
22 {
23 // 打开或者新建文件
24 CFile file;
25 BOOL bRet = file.Open(path.c_str(),
26 CFile::modeCreate | CFile::modeWrite);
27 if (!bRet) //打开文件失败
28 {
29 return;
30 }
31 std::shared_lock<std::shared_mutex> readLock(m_shared_mutex);
32 // 构造CArchive对象
33 CArchive ar(&file, CArchive::store);
34 // 写数据
35 ar << CString(_T("2.751")); //写入数据版本
36 ar << static_cast<int>(m_song_data.size()); //写入映射容器的大小
37 for (const auto& song_data : m_song_data)
38 {
39 ar << CString(song_data.first.path.c_str())
40 << song_data.second.start_pos.toInt()
41 << song_data.second.end_pos.toInt()
42 << song_data.second.bitrate
43 << CString(song_data.second.title.c_str())
44 << CString(song_data.second.artist.c_str())
45 << CString(song_data.second.album.c_str())
46 << CString(song_data.second.get_year().c_str())
47 << CString(song_data.second.comment.c_str())
48 << CString(song_data.second.genre.c_str())
49 << song_data.second.genre_idx
50 << song_data.second.track
51 << song_data.second.tag_type
52 << CString(song_data.second.GetSongId().c_str())
53 << song_data.second.listen_time
54 << song_data.second.info_acquired
55 << song_data.second.is_cue
56 //<< song_data.second.is_favourite
57
58 //<< song_data.second.no_online_album_cover
59 //<< song_data.second.no_online_lyric
60 << song_data.second.flags
61 << song_data.second.last_played_time
62 << CString(song_data.second.lyric_file.c_str())
63 << song_data.second.modified_time
64 << song_data.second.rating
65 << song_data.second.freq
66 << song_data.second.bits
67 << song_data.second.channels
68 << CString(song_data.second.cue_file_path.c_str())
69 << CString(song_data.second.album_artist.c_str())
70 << song_data.second.total_tracks
71 << song_data.second.disc_num
72 << song_data.second.total_discs
73 ;
74 }
75 // 关闭CArchive对象
76 ar.Close();
77 // 关闭文件
78 file.Close();
79
80 m_song_data_modified = false;
81 }
82
LoadSongData(std::wstring path)83 void CSongDataManager::LoadSongData(std::wstring path)
84 {
85 // 打开文件
86 CFile file;
87 BOOL bRet = file.Open(path.c_str(), CFile::modeRead);
88 if (!bRet) return;
89 // LoadSongData执行时主窗口还未启动应该没有其他线程,不过还是加上
90 std::unique_lock<std::shared_mutex> writeLock(m_shared_mutex);
91 // 构造CArchive对象
92 CArchive ar(&file, CArchive::load);
93 // 读数据
94 int size{};
95 SongInfo song_info;
96 CString temp;
97 try
98 {
99 //读取版本
100 ar >> m_data_version;
101 //if (!CCommon::StringIsVersion(m_data_version))
102 // m_data_version = _T("0.00");
103 if (m_data_version >= _T("2.664"))
104 {
105 ar >> size; //读取映射容器的长度
106 }
107 else
108 {
109 size_t size_1;
110 ar >> size_1;
111 size = static_cast<int>(size_1);
112 }
113 m_song_data.reserve(size);
114 for (int i{}; i < size; i++)
115 {
116 ar >> temp;
117 song_info.file_path = temp;
118 int song_start_pos{}, song_end_pos{};
119 if (m_data_version >= _T("2.731"))
120 {
121 ar >> song_start_pos;
122 }
123 ar >> song_end_pos;
124 song_info.start_pos.fromInt(song_start_pos);
125 song_info.end_pos.fromInt(song_end_pos);
126 if (m_data_version >= _T("2.691"))
127 {
128 ar >> song_info.bitrate;
129 }
130 else
131 {
132 int bitrate;
133 ar >> bitrate;
134 song_info.bitrate = bitrate;
135 }
136 ar >> temp;
137 song_info.title = temp;
138 ar >> temp;
139 song_info.artist = temp;
140 ar >> temp;
141 song_info.album = temp;
142 ar >> temp;
143 song_info.SetYear(temp);
144 ar >> temp;
145 song_info.comment = temp;
146 ar >> temp;
147 song_info.genre = temp;
148 ar >> song_info.genre_idx;
149 if (m_data_version >= _T("2.66"))
150 {
151 ar >> song_info.track;
152 }
153 else
154 {
155 BYTE track;
156 ar >> track;
157 song_info.track = track;
158 }
159
160 if (m_data_version >= _T("2.691"))
161 {
162 ar >> song_info.tag_type;
163 }
164 else
165 {
166 int tag_type;
167 ar >> tag_type;
168 song_info.tag_type = tag_type;
169 }
170 ar >> temp;
171 song_info.SetSongId(temp.GetString());
172
173 if (m_data_version >= _T("2.64")) //版本号大于等于2.64
174 {
175 ar >> song_info.listen_time;
176 ar >> song_info.info_acquired;
177 }
178
179 if (m_data_version >= _T("2.731"))
180 {
181 ar >> song_info.is_cue;
182 }
183
184 if (m_data_version == _T("2.661"))
185 {
186 ar >> song_info.is_favourite;
187 }
188
189 if (m_data_version >= _T("2.663") && m_data_version < _T("2.690"))
190 {
191 bool no_online_album_cover{ song_info.NoOnlineAlbumCover() };
192 bool no_online_lyric{ song_info.NoOnlineLyric() };
193 ar >> no_online_album_cover;
194 ar >> no_online_lyric;
195 }
196
197 if (m_data_version >= _T("2.690"))
198 {
199 ar >> song_info.flags;
200 }
201
202 if (m_data_version >= _T("2.680"))
203 {
204 ar >> song_info.last_played_time;
205 }
206
207 if (m_data_version >= _T("2.692"))
208 {
209 ar >> temp;
210 song_info.lyric_file = temp;
211 }
212
213 if (m_data_version >= _T("2.700"))
214 {
215 ar >> song_info.modified_time;
216 }
217
218 if (m_data_version >= _T("2.720"))
219 {
220 ar >> song_info.rating;
221 }
222
223 if (m_data_version >= _T("2.730"))
224 {
225 ar >> song_info.freq;
226 ar >> song_info.bits;
227 ar >> song_info.channels;
228 }
229 if (m_data_version >= _T("2.75"))
230 {
231 ar >> temp;
232 song_info.cue_file_path = temp;
233 }
234 if (m_data_version >= _T("2.751"))
235 {
236 ar >> temp;
237 song_info.album_artist = temp;
238 ar >> song_info.total_tracks;
239 ar >> song_info.disc_num;
240 ar >> song_info.total_discs;
241 }
242 m_song_data[song_info] = song_info; // 将读取到的一首歌曲信息添加到映射容器中
243 }
244 }
245 catch (CArchiveException* exception)
246 {
247 wstring info = theApp.m_str_table.LoadTextFormat(L"MSG_SERIALIZE_ERROR", { path, exception->m_cause });
248 theApp.WriteLog(info);
249 }
250 // 关闭对象
251 ar.Close();
252 // 关闭文件
253 file.Close();
254 }
255
IsSongDataModified() const256 bool CSongDataManager::IsSongDataModified() const
257 {
258 return m_song_data_modified;
259 }
260
GetDataVersion() const261 CString CSongDataManager::GetDataVersion() const
262 {
263 return m_data_version;
264 }
265
SetSongID(const SongKey & key,const unsigned __int64 id)266 bool CSongDataManager::SetSongID(const SongKey& key, const unsigned __int64 id)
267 {
268 std::unique_lock<std::shared_mutex> writeLock(m_shared_mutex);
269 ASSERT(!key.path.empty());
270 auto iter = m_song_data.find(key);
271 if (iter == m_song_data.end())
272 return false; // 为避免问题,仅能为媒体库已存在的条目设置id
273 iter->second.song_id = id;
274
275 m_song_data_modified = true;
276 return true;
277 }
278
GetSongID(const SongKey & key,unsigned __int64 & id) const279 bool CSongDataManager::GetSongID(const SongKey& key, unsigned __int64& id) const
280 {
281 std::shared_lock<std::shared_mutex> readLock(m_shared_mutex);
282 ASSERT(!key.path.empty());
283 id = 0;
284 auto iter = m_song_data.find(key);
285 if (iter == m_song_data.end())
286 return false;
287 id = iter->second.song_id;
288 return true;
289 }
290
SaveCueSongInfo(const vector<SongInfo> & songs_info)291 void CSongDataManager::SaveCueSongInfo(const vector<SongInfo>& songs_info)
292 {
293 std::unique_lock<std::shared_mutex> writeLock(m_shared_mutex);
294 for (const auto& song_info : songs_info)
295 {
296 SongInfo& song = m_song_data[song_info];
297 song.file_path = song_info.file_path;
298 song.cue_file_path = song_info.cue_file_path;
299 song.modified_time = song_info.modified_time;
300 song.CopyAudioTag(song_info);
301 song.start_pos = song_info.start_pos;
302 song.end_pos = song_info.end_pos;
303 song.bitrate = song_info.bitrate;
304 song.freq = song_info.freq;
305 song.bits = song_info.bits;
306 song.channels = song_info.channels;
307 song.is_cue = true;
308 song.info_acquired = true;
309 song.SetChannelInfoAcquired(true);
310 }
311 m_song_data_modified = true;
312 }
313
LoadSongInfo(SongInfo & song_info) const314 void CSongDataManager::LoadSongInfo(SongInfo& song_info) const
315 {
316 std::shared_lock<std::shared_mutex> readLock(m_shared_mutex);
317 auto iter = m_song_data.find(song_info);
318 if (iter != m_song_data.end())
319 {
320 const SongInfo& temp = iter->second;
321 song_info.CopyAudioTag(temp);
322 song_info.cue_file_path = temp.cue_file_path;
323 song_info.start_pos = temp.start_pos;
324 song_info.end_pos = temp.end_pos;
325 song_info.bitrate = temp.bitrate;
326 song_info.modified_time = temp.modified_time;
327 song_info.listen_time = temp.listen_time;
328 song_info.freq = temp.freq;
329 song_info.channels = temp.channels;
330 song_info.bits = temp.bits;
331 }
332 }
333
LoadSongsInfo(vector<SongInfo> & songs_info) const334 void CSongDataManager::LoadSongsInfo(vector<SongInfo>& songs_info) const
335 {
336 std::shared_lock<std::shared_mutex> readLock(m_shared_mutex);
337 for (SongInfo& song_info : songs_info)
338 {
339 auto iter = m_song_data.find(song_info);
340 if (iter != m_song_data.end())
341 {
342 const SongInfo& temp = iter->second;
343 song_info.CopyAudioTag(temp);
344 song_info.cue_file_path = temp.cue_file_path;
345 song_info.start_pos = temp.start_pos;
346 song_info.end_pos = temp.end_pos;
347 song_info.bitrate = temp.bitrate;
348 song_info.modified_time = temp.modified_time;
349 song_info.listen_time = temp.listen_time;
350 song_info.freq = temp.freq;
351 song_info.channels = temp.channels;
352 song_info.bits = temp.bits;
353 }
354 }
355 }
356
GetSongInfo3(const SongInfo & song) const357 SongInfo CSongDataManager::GetSongInfo3(const SongInfo& song) const
358 {
359 std::shared_lock<std::shared_mutex> readLock(m_shared_mutex);
360 if (song.IsEmpty())
361 return song;
362 ASSERT(!song.file_path.empty());
363 SongInfo tmp;
364 auto iter = m_song_data.find(song);
365 if (iter != m_song_data.end())
366 tmp = iter->second;
367 else
368 tmp = song;
369 return tmp;
370 }
371
GetSongInfo(const SongKey & key) const372 SongInfo CSongDataManager::GetSongInfo(const SongKey& key) const
373 {
374 std::shared_lock<std::shared_mutex> readLock(m_shared_mutex);
375 ASSERT(!key.path.empty());
376 SongInfo tmp;
377 auto iter = m_song_data.find(key);
378 if (iter != m_song_data.end())
379 tmp = iter->second;
380 return tmp;
381 }
382
GetSongData(const std::function<void (const CSongDataManager::SongDataMap &)> & func) const383 void CSongDataManager::GetSongData(const std::function<void(const CSongDataManager::SongDataMap&)>& func) const
384 {
385 std::shared_lock<std::shared_mutex> readLock(m_shared_mutex);
386 func(m_song_data);
387 }
388
IsItemExist(const SongKey & key) const389 bool CSongDataManager::IsItemExist(const SongKey& key) const
390 {
391 std::shared_lock<std::shared_mutex> readLock(m_shared_mutex);
392 auto iter = m_song_data.find(key);
393 return iter != m_song_data.end();
394 }
395
AddItem(const SongInfo & song)396 void CSongDataManager::AddItem(const SongInfo& song)
397 {
398 std::unique_lock<std::shared_mutex> writeLock(m_shared_mutex);
399 ASSERT(!song.file_path.empty());
400 m_song_data[song] = song;
401 m_song_data_modified = true;
402 }
403
RemoveItem(const SongKey & key)404 bool CSongDataManager::RemoveItem(const SongKey& key)
405 {
406 std::unique_lock<std::shared_mutex> writeLock(m_shared_mutex);
407 auto iter = m_song_data.find(key);
408 if (iter != m_song_data.end())
409 {
410 m_song_data.erase(iter);
411 m_song_data_modified = true;
412 return true;
413 }
414 return false;
415 }
416
RemoveItemIf(std::function<bool (const SongInfo &)> fun_condition)417 int CSongDataManager::RemoveItemIf(std::function<bool(const SongInfo&)> fun_condition)
418 {
419 std::unique_lock<std::shared_mutex> writeLock(m_shared_mutex);
420 // 遍历映射容器,删除不必要的条目。
421 int removedCount{};
422 auto iter = m_song_data.begin();
423 while (iter != m_song_data.end())
424 {
425 if (fun_condition(iter->second))
426 {
427 iter = m_song_data.erase(iter);
428 ++removedCount;
429 }
430 else
431 ++iter;
432 }
433 if (removedCount > 0)
434 m_song_data_modified = true;
435 return removedCount;
436 }
437
ClearPlayTime()438 void CSongDataManager::ClearPlayTime()
439 {
440 std::unique_lock<std::shared_mutex> writeLock(m_shared_mutex);
441 for (auto& data : m_song_data)
442 {
443 data.second.listen_time = 0;
444 }
445 m_song_data_modified = true;
446 }
447
ClearLastPlayedTime()448 void CSongDataManager::ClearLastPlayedTime()
449 {
450 std::unique_lock<std::shared_mutex> writeLock(m_shared_mutex);
451 for (auto& item : m_song_data)
452 {
453 item.second.last_played_time = 0;
454 }
455 m_song_data_modified = true;
456 }
457
ChangeFilePath(const wstring & file_path,const wstring & new_path)458 void CSongDataManager::ChangeFilePath(const wstring& file_path, const wstring& new_path)
459 {
460 std::unique_lock<std::shared_mutex> writeLock(m_shared_mutex);
461 auto iter = m_song_data.find(file_path);
462 if (iter != m_song_data.end())
463 {
464 SongInfo song = iter->second;
465 if (!song.file_path.empty())
466 song.file_path = new_path;
467 m_song_data[new_path] = song;
468 }
469 }
470