xref: /MusicPlayer2/MusicPlayer2/SongDataManager.cpp (revision d116564c7d2fbe11e6f90b13943d206ca3e2cd40)
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