1 #include "stdafx.h"
2 #include "CRecentList.h"
3 #include "MusicPlayer2.h"
4 #include "FilePathHelper.h"
5
6 CRecentList CRecentList::m_instance;
7
8 std::array<ListItem, CRecentList::PlaylistType::PT_MAX> CRecentList::SP_PLAYLIST;
9
SetSortMode(ListType type,listSortMode sort_mode)10 bool CRecentList::SetSortMode(ListType type, listSortMode sort_mode)
11 {
12 std::lock_guard<std::mutex> lock(m_mutex);
13 ASSERT(type >= 0 && type < ListType::LT_MAX);
14 if (m_sort_mode[type] == sort_mode)
15 return false;
16 m_sort_mode[type] = sort_mode;
17 ++m_ver;
18 return true;
19 }
20
GetSortMode(ListType type) const21 CRecentList::listSortMode CRecentList::GetSortMode(ListType type) const
22 {
23 std::lock_guard<std::mutex> lock(m_mutex);
24 ASSERT(type < ListType::LT_MAX);
25 return m_sort_mode[type];
26 }
27
SetCurrentList(ListItem list_item)28 void CRecentList::SetCurrentList(ListItem list_item)
29 {
30 std::lock_guard<std::mutex> lock(m_mutex);
31 list_item.last_played_time = CCommon::GetCurTimeElapse();
32 auto it = std::find(m_list.begin(), m_list.end(), list_item);
33 if (it != m_list.begin()) // 此次调用会更换当前播放
34 if ((m_list.begin()->type == LT_FOLDER || m_list.begin()->type == LT_MEDIA_LIB) && m_list.begin()->total_num == 0)
35 m_list.erase(m_list.begin()); // 不保存没有歌曲的文件夹/媒体库列表项目
36 if (it != m_list.end()) // 已存在时更新并移动位置到front
37 { // 不要轻易销毁再构造m_list的元素,此处更新,因为链表在更改元素顺序时迭代器不会失效,在程序设计有问题时crash的概率低一些 (虽然正常的程序不应该依赖这点)
38 list_item.create_time = it->create_time; // 继承之前的create_time
39 *it = list_item;
40 if (it != m_list.begin())
41 m_list.splice(m_list.begin(), m_list, it);
42 }
43 else // 不存在时,添加到front
44 {
45 ASSERT(!list_item.empty());
46 // 将当前时间设置为创建时间
47 list_item.create_time = list_item.last_played_time;
48 // 特别的,对于LT_PLAYLIST,重新设置create_time为文件属性“创建时间”
49 if (list_item.type == LT_PLAYLIST)
50 m_list.push_front(CreateNewPlaylistListItem(list_item));
51 else
52 m_list.push_front(list_item);
53 }
54 ++m_ver;
55 }
56
GetCurrentList() const57 ListItem CRecentList::GetCurrentList() const
58 {
59 std::lock_guard<std::mutex> lock(m_mutex);
60 return m_list.front();
61 }
62
IsCurrentList(const ListItem & list_item) const63 bool CRecentList::IsCurrentList(const ListItem& list_item) const
64 {
65 std::lock_guard<std::mutex> lock(m_mutex);
66 if (m_list.empty()) // 未初始化时即未播放当前列表
67 return false;
68 return m_list.front() == list_item;
69 }
70
LoadItem(ListItem & list_item) const71 bool CRecentList::LoadItem(ListItem& list_item) const
72 {
73 std::lock_guard<std::mutex> lock(m_mutex);
74 auto it = std::find(m_list.begin(), m_list.end(), list_item);
75 if (it == m_list.end())
76 return false;
77 list_item = *it;
78 return true;
79 }
80
AddNewItem(ListItem list_item)81 bool CRecentList::AddNewItem(ListItem list_item)
82 {
83 std::lock_guard<std::mutex> lock(m_mutex);
84 auto it = std::find(m_list.begin(), m_list.end(), list_item);
85 if (it != m_list.end())
86 return false;
87 list_item.last_track = SongKey();
88 list_item.last_position = 0;
89 list_item.last_played_time = 0; // 为维持m_list的顺序,此处只能接受加入未播放的项目到末尾
90 list_item.create_time = CCommon::GetCurTimeElapse();
91 if (list_item.type == LT_PLAYLIST) // 对于LT_PLAYLIST,不存在时创建文件并修改create_time为文件属性“创建时间”
92 m_list.push_back(CreateNewPlaylistListItem(list_item));
93 else
94 m_list.push_back(list_item);
95 ++m_ver;
96 return true;
97 }
98
GetSpecPlaylist(PlaylistType playlist_type) const99 ListItem CRecentList::GetSpecPlaylist(PlaylistType playlist_type) const
100 {
101 std::lock_guard<std::mutex> lock(m_mutex);
102 ASSERT(playlist_type >= 0 && playlist_type < PlaylistType::PT_MAX);
103 auto it = std::find(m_list.begin(), m_list.end(), SP_PLAYLIST[playlist_type]);
104 if (it != m_list.end())
105 return *it;
106 ASSERT(playlist_type == PT_TEMP);
107 return SP_PLAYLIST[playlist_type]; // 这行用来在临时播放列表不存在时返回其原型
108 }
109
IsPlayingSpecPlaylist(PlaylistType type)110 bool CRecentList::IsPlayingSpecPlaylist(PlaylistType type)
111 {
112 std::lock_guard<std::mutex> lock(m_mutex);
113 if (m_list.empty()) // 未初始化时即未播放当前列表
114 return false;
115 if (type >= 0 && type < PlaylistType::PT_MAX)
116 return m_list.front() == SP_PLAYLIST[type];
117 for (int i{}; i < PlaylistType::PT_MAX; ++i)
118 if (m_list.front() == SP_PLAYLIST[i])
119 return true;
120 return false;
121 }
122
IsSpecPlaylist(const ListItem & list_item,PlaylistType type)123 bool CRecentList::IsSpecPlaylist(const ListItem& list_item, PlaylistType type)
124 {
125 if (type >= 0 && type < PlaylistType::PT_MAX)
126 return list_item == SP_PLAYLIST[type];
127 for (int i{}; i < PlaylistType::PT_MAX; ++i)
128 if (list_item == SP_PLAYLIST[i])
129 return true;
130 return false;
131 }
132
RemoveItem(const ListItem & list_item)133 bool CRecentList::RemoveItem(const ListItem& list_item)
134 {
135 std::lock_guard<std::mutex> lock(m_mutex);
136 auto it = std::find(m_list.begin(), m_list.end(), list_item);
137 if (it == m_list.begin() || it == m_list.end())
138 return false;
139 if (IsSpecPlaylist(*it, PT_DEFAULT) || IsSpecPlaylist(*it, PT_FAVOURITE))
140 return false;
141 m_list.erase(it);
142 ++m_ver;
143 return true;
144 }
145
RemoveItemIf(std::function<bool (const ListItem & list_item)> func)146 int CRecentList::RemoveItemIf(std::function<bool(const ListItem& list_item)> func)
147 {
148 std::lock_guard<std::mutex> lock(m_mutex);
149 size_t size = m_list.size();
150 ASSERT(!m_list.empty());
151 m_list.remove_if([&](const ListItem& list_item) -> bool
152 { return func(list_item) && list_item != m_list.front() && IsSpecPlaylist(list_item, PT_DEFAULT) && IsSpecPlaylist(list_item, PT_FAVOURITE); });
153 size -= m_list.size();
154 m_ver += size;
155 return size;
156 }
157
ResetLastPlayedTime(const ListItem & list_item)158 bool CRecentList::ResetLastPlayedTime(const ListItem& list_item)
159 {
160 std::lock_guard<std::mutex> lock(m_mutex);
161 auto it = std::find(m_list.begin(), m_list.end(), list_item);
162 if (it == m_list.begin() || it == m_list.end())
163 return false;
164 if (it->type == LT_MEDIA_LIB)
165 m_list.erase(it);
166 else
167 {
168 it->last_played_time = 0;
169 m_list.splice(m_list.end(), m_list, it); // 移动此项到末尾
170 }
171 ++m_ver;
172 return true;
173 }
174
SetContainSubFolder(const ListItem & list_item)175 bool CRecentList::SetContainSubFolder(const ListItem& list_item)
176 {
177 std::lock_guard<std::mutex> lock(m_mutex);
178 auto it = std::find(m_list.begin(), m_list.end(), list_item);
179 if (it == m_list.begin() || it == m_list.end() || list_item.type != LT_FOLDER)
180 return false;
181 it->contain_sub_folder = !it->contain_sub_folder;
182 ++m_ver;
183 return true;
184 }
185
SetPlaylistTotalInfo(const ListItem & list_item,int total_num,int total_time)186 bool CRecentList::SetPlaylistTotalInfo(const ListItem& list_item, int total_num, int total_time)
187 {
188 std::lock_guard<std::mutex> lock(m_mutex);
189 auto it = std::find(m_list.begin(), m_list.end(), list_item);
190 if (it == m_list.begin() || it == m_list.end() || list_item.type != LT_PLAYLIST)
191 return false;
192 if (it->total_num == total_num && it->total_time == total_time)
193 return false;
194 it->total_num = total_num;
195 it->total_time = total_time;
196 ++m_ver;
197 return true;
198 }
199
RenamePlaylist(const ListItem & list_item,const wstring & new_path)200 bool CRecentList::RenamePlaylist(const ListItem& list_item, const wstring& new_path)
201 {
202 std::lock_guard<std::mutex> lock(m_mutex);
203 auto it = std::find(m_list.begin(), m_list.end(), list_item);
204 if (it == m_list.end() || list_item.type != LT_PLAYLIST)
205 return false;
206 it->path = new_path;
207 ++m_ver;
208 return true;
209 }
210
CreateNewPlaylistListItem(ListItem list_item)211 ListItem CRecentList::CreateNewPlaylistListItem(ListItem list_item)
212 {
213 ASSERT(list_item.type == LT_PLAYLIST);
214 if (!CCommon::FileExist(list_item.path)) // 如果播放列表文件不存在则创建一个空文件
215 CCommon::SaveDataToFile(string(), list_item.path);
216 uint64_t file_create_time{};
217 if (CCommon::GetFileCreateTime(list_item.path, file_create_time))
218 list_item.create_time = CCommon::FileTimeToTimeT(file_create_time);
219 return list_item;
220 }
221
SaveData() const222 void CRecentList::SaveData() const
223 {
224 //向主窗口发送通知
225 ::SendMessage(AfxGetMainWnd()->GetSafeHwnd(), WM_RECENT_FOLDER_OR_PLAYLIST_CHANGED, 0, 0); // 重新初始化快捷菜单
226 ::SendMessage(AfxGetMainWnd()->GetSafeHwnd(), WM_INIT_ADD_TO_MENU, 0, 0); // 重新初始化右键菜单中的“添加到播放列表”子菜单
227 std::lock_guard<std::mutex> lock(m_mutex);
228 CFile file;
229 // 打开或者新建文件
230 BOOL bRet = file.Open(theApp.m_recent_list_dat_path.c_str(),
231 CFile::modeCreate | CFile::modeWrite);
232 if (!bRet) // 打开文件失败
233 return;
234 // 构造CArchive对象
235 CArchive ar(&file, CArchive::store);
236 // 写版本号
237 const int version{ 0 };
238 ar << version;
239 // 写数据 (固定全部使用int/uint64_t/CString)
240 ar << static_cast<int>(m_list.size());
241 for (const ListItem& item : m_list)
242 {
243 ar << static_cast<int>(item.type);
244 if (item.type == LT_PLAYLIST)
245 ar << CString(CFilePathHelper(item.path).GetFileNameWithoutExtension().c_str());
246 else
247 ar << CString(item.path.c_str());
248 ar << static_cast<int>(item.sort_mode)
249 << CString(item.last_track.path.c_str())
250 << item.last_track.cue_track
251 << item.last_position
252 << item.total_time
253 << item.total_num
254 << item.last_played_time
255 << item.create_time
256 << static_cast<int>(item.medialib_type)
257 << static_cast<int>(item.contain_sub_folder)
258 ;
259 }
260 // 关闭CArchive对象
261 ar.Close();
262 // 关闭文件
263 file.Close();
264 }
265
LoadData()266 bool CRecentList::LoadData()
267 {
268 std::lock_guard<std::mutex> lock(m_mutex);
269
270 // 初始化特殊播放列表的原型,用来做==比较,总是为空白项目(即初始状态)
271 SP_PLAYLIST[PT_DEFAULT] = { LT_PLAYLIST, theApp.m_playlist_dir + L"default_playlist" PLAYLIST_EXTENSION };
272 SP_PLAYLIST[PT_FAVOURITE] = { LT_PLAYLIST, theApp.m_playlist_dir + L"favourite" PLAYLIST_EXTENSION };
273 SP_PLAYLIST[PT_TEMP] = { LT_PLAYLIST, theApp.m_playlist_dir + L"temp" PLAYLIST_EXTENSION };
274
275 CFile file;
276 // 打开文件
277 if (file.Open(theApp.m_recent_list_dat_path.c_str(), CFile::modeRead))
278 {
279 // 构造CArchive对象
280 CArchive ar(&file, CArchive::load);
281 // 读数据
282 int version{}, size{}, temp_int;
283 CString temp_str;
284 try
285 {
286 ar >> version;
287 ar >> size;
288 for (int i{}; i < size; ++i)
289 {
290 ListItem list_item{};
291 ar >> temp_int;
292 list_item.type = static_cast<ListType>(temp_int);
293 ar >> temp_str;
294 list_item.path = temp_str;
295 ar >> temp_int;
296 list_item.sort_mode = static_cast<SortMode>(temp_int);
297 ar >> temp_str;
298 list_item.last_track.path = temp_str;
299 ar >> list_item.last_track.cue_track;
300 ar >> list_item.last_position;
301 ar >> list_item.total_time;
302 ar >> list_item.total_num;
303 ar >> list_item.last_played_time;
304 ar >> list_item.create_time;
305 ar >> temp_int;
306 list_item.medialib_type = static_cast<CMediaClassifier::ClassificationType>(temp_int);
307 ar >> temp_int;
308 list_item.contain_sub_folder = static_cast<bool>(temp_int);
309
310 if (list_item.type == LT_PLAYLIST)
311 list_item.path = theApp.m_playlist_dir + list_item.path + PLAYLIST_EXTENSION;
312 // 插入m_list
313 m_list.push_back(std::move(list_item));
314 }
315 }
316 catch (CArchiveException* exception)
317 {
318 // 捕获序列化时出现的异常
319 wstring info = theApp.m_str_table.LoadTextFormat(L"MSG_SERIALIZE_ERROR", { theApp.m_recent_list_dat_path, exception->m_cause });
320 theApp.WriteLog(info);
321 }
322 // 关闭对象
323 ar.Close();
324 // 关闭文件
325 file.Close();
326 }
327 else
328 {
329 LoadOldData(); // 文件不存在时试着加载旧版文件
330 }
331
332 AfterLoadData();
333 ++m_ver;
334 return true;
335 }
336
AfterLoadData()337 void CRecentList::AfterLoadData()
338 {
339 // 获取playlist目录下的播放列表文件
340 vector<wstring> file_list;
341 CCommon::GetFiles(theApp.m_playlist_dir + L'*' + PLAYLIST_EXTENSION, file_list);
342 // 移除不符合条件的项目
343 m_list.remove_if([&](const ListItem& list_item) -> bool
344 {
345 switch (list_item.type)
346 {
347 case LT_FOLDER: return list_item.path.size() < 2;
348 case LT_PLAYLIST: return std::find(file_list.begin(), file_list.end(), CFilePathHelper(list_item.path).GetFileName()) == file_list.end();
349 case LT_MEDIA_LIB: return list_item.medialib_type < 0 || list_item.medialib_type >= CMediaClassifier::CT_MAX;
350 default: return true;
351 }
352 });
353 // 检查必须存在的特殊播放列表,不存在时添加 (必须添加在其他播放列表之前,因为对全新程序来说m_list.front()是其当前播放的列表)
354 if (std::find(m_list.begin(), m_list.end(), SP_PLAYLIST[PT_DEFAULT]) == m_list.end())
355 m_list.push_back(CreateNewPlaylistListItem(SP_PLAYLIST[PT_DEFAULT]));
356 if (std::find(m_list.begin(), m_list.end(), SP_PLAYLIST[PT_FAVOURITE]) == m_list.end())
357 m_list.push_back(CreateNewPlaylistListItem(SP_PLAYLIST[PT_FAVOURITE]));
358 // 向m_list添加未记录的播放列表(用户不经程序自行添加的那些)
359 for (const wstring& file : file_list)
360 {
361 ListItem list_item{ LT_PLAYLIST, theApp.m_playlist_dir + file };
362 if (std::find(m_list.begin(), m_list.end(), list_item) == m_list.end())
363 m_list.push_back(CreateNewPlaylistListItem(list_item));
364 }
365 // 校验&旧版兼容
366 uint64_t cur_time = CCommon::GetCurTimeElapse();
367 for (ListItem& item : m_list)
368 {
369 if (item.create_time == 0 && item.type == LT_PLAYLIST) // 对于播放列表,优先尝试文件创建时间
370 {
371 uint64_t file_create_time{};
372 if (CCommon::GetFileCreateTime(item.path, file_create_time))
373 item.create_time = CCommon::FileTimeToTimeT(file_create_time);
374 }
375 if (item.create_time == 0)
376 item.create_time = item.last_played_time;
377 if (item.create_time == 0)
378 item.create_time = cur_time;
379 // 如果读取到的文件夹路径末尾没有斜杠,则在末尾加上一个
380 if (item.type == LT_FOLDER && item.path.back() != L'/' && item.path.back() != L'\\')
381 item.path.push_back(L'\\');
382 }
383 // 按最近播放时间降序排序,链表容器的成员排序方法是stable的
384 m_list.sort();
385 }
386
LoadOldData()387 void CRecentList::LoadOldData()
388 {
389 CFile file;
390 // 打开文件 recent_path.dat
391 if (file.Open(theApp.m_recent_path_dat_path.c_str(), CFile::modeRead))
392 {
393 // 为了保持和以前版本的数据兼容,先读取前8个字节,以判断是否是以前版本
394 char buff[8]{};
395 file.Read(buff, 8);
396 file.SeekToBegin();
397
398 // 构造CArchive对象
399 CArchive ar(&file, CArchive::load);
400 // 读数据
401 unsigned int size{};
402 CString temp;
403 int sort_mode;
404 unsigned int version{};
405 try
406 {
407 ar >> size; //读取映射容器的长度
408 if (buff[4] == '\xff' && buff[5] == '\xfe') //如果第4个字节和第5个字节是FFFE,则说明数据文件是以前版本,此时不读取version
409 version = 0;
410 else
411 ar >> version; //读取数据文件的版本
412 for (unsigned int i{}; i < size; i++)
413 {
414 ListItem list_item{};
415 list_item.type = LT_FOLDER;
416 ar >> temp;
417 list_item.path = temp;
418 // 丢弃PathInfo的track与position,ListItem改为使用SongKey描述,此处无法转换
419 int tmp{};
420 ar >> tmp; // track
421 ar >> tmp; // position
422 ar >> sort_mode;
423 list_item.sort_mode = static_cast<SortMode>(sort_mode);
424 if (version >= 2 && version <= 3) // 在版本4变量descending不再独立存储,功能整合到sort_mode内,这里做读取兼容
425 {
426 BYTE descending;
427 ar >> descending;
428 switch (sort_mode)
429 {
430 case 0: list_item.sort_mode = descending ? SM_D_FILE : SM_U_FILE; break;
431 case 1: list_item.sort_mode = descending ? SM_D_PATH : SM_U_PATH; break;
432 case 2: list_item.sort_mode = descending ? SM_D_TITLE : SM_U_TITLE; break;
433 case 3: list_item.sort_mode = descending ? SM_D_ARTIST : SM_U_ARTIST; break;
434 case 4: list_item.sort_mode = descending ? SM_D_ALBUM : SM_U_ALBUM; break;
435 case 5: list_item.sort_mode = descending ? SM_D_TRACK : SM_U_TRACK; break;
436 case 6: list_item.sort_mode = descending ? SM_D_TIME : SM_U_TIME; break;
437 default: break;
438 }
439 }
440 ar >> list_item.total_num;
441 ar >> list_item.total_time;
442 if (version >= 1)
443 {
444 BYTE contain_sub_folder;
445 ar >> contain_sub_folder;
446 list_item.contain_sub_folder = (contain_sub_folder != 0);
447 }
448 if (version >= 3)
449 ar >> list_item.last_played_time;
450 if (version >= 5)
451 ar >> list_item.create_time;
452
453 m_list.push_back(std::move(list_item));
454 }
455 }
456 catch (CArchiveException* exception)
457 {
458 //捕获序列化时出现的异常
459 wstring info = theApp.m_str_table.LoadTextFormat(L"MSG_SERIALIZE_ERROR", { theApp.m_recent_path_dat_path, exception->m_cause });
460 theApp.WriteLog(info);
461 }
462 // 关闭对象
463 ar.Close();
464 // 关闭文件
465 file.Close();
466 }
467 // 打开文件 recent_path.dat
468 if (file.Open(theApp.m_recent_playlist_data_path.c_str(), CFile::modeRead))
469 {
470 // 构造CArchive对象
471 CArchive ar(&file, CArchive::load);
472 // 读数据
473 unsigned int size{};
474 CString temp;
475 try
476 {
477 int version{};
478 ar >> version;
479 int temp;
480 ar >> temp; // 丢弃m_cur_playlist_type
481 m_list.push_back(SP_PLAYLIST[PT_DEFAULT]);
482 ar >> temp; // 丢弃默认播放列表track
483 ar >> temp; // 丢弃默认播放列表position
484 ar >> m_list.back().total_num;
485 ar >> m_list.back().total_time;
486 if (version >= 4)
487 ar >> m_list.back().last_played_time;
488 if (version >= 2)
489 {
490 m_list.push_back(SP_PLAYLIST[PT_FAVOURITE]);
491 ar >> temp; // 丢弃FAVOURITE播放列表track
492 ar >> temp; // 丢弃FAVOURITE播放列表position
493 ar >> m_list.back().total_num;
494 ar >> m_list.back().total_time;
495 if (version >= 4)
496 ar >> m_list.back().last_played_time;
497 }
498 // 原来temp播放列表以total_num为0表示“已删除”而不是真的删除文件
499 // 这里不再特殊处理,表现为原来“已删除”的temp列表会重新出现(问题不大)
500 if (version >= 3)
501 {
502 m_list.push_back(SP_PLAYLIST[PT_TEMP]);
503 ar >> temp; // 丢弃TEMP播放列表track
504 ar >> temp; // 丢弃TEMP播放列表position
505 ar >> m_list.back().total_num;
506 ar >> m_list.back().total_time;
507 if (version >= 4)
508 ar >> m_list.back().last_played_time;
509 }
510 ar >> size; // 读取映射容器的长度
511 unsigned __int64 not_use{};
512 for (unsigned int i{}; i < size; ++i)
513 {
514 ListItem list_item{};
515 list_item.type = LT_PLAYLIST;
516 CString strTmp;
517 ar >> strTmp;
518 list_item.path = theApp.m_playlist_dir + strTmp.GetString() + PLAYLIST_EXTENSION;
519 ar >> temp; // track
520 ar >> temp; // position;
521 ar >> list_item.total_num;
522 ar >> list_item.total_time;
523 if (version >= 4)
524 ar >> list_item.last_played_time;
525 if (version >= 5)
526 ar >> not_use; // 丢弃原来的create_time,对于播放列表,现已改用文件属性“创建时间”
527
528 m_list.push_back(std::move(list_item));
529 }
530 }
531 catch (CArchiveException* exception)
532 {
533 //捕获序列化时出现的异常
534 wstring info = theApp.m_str_table.LoadTextFormat(L"MSG_SERIALIZE_ERROR", { theApp.m_recent_playlist_data_path, exception->m_cause });
535 theApp.WriteLog(info);
536 }
537 // 关闭对象
538 ar.Close();
539 // 关闭文件
540 file.Close();
541 }
542 // 打开文件 recent_medialib_item.dat
543 if (file.Open(theApp.m_recent_medialib_playlist_path.c_str(), CFile::modeRead))
544 {
545 // 构造CArchive对象
546 CArchive ar(&file, CArchive::load);
547 // 读数据
548 unsigned int size{};
549 try
550 {
551 int version{}, temp{};
552 ar >> version;
553 ar >> size; // 读取长度
554 for (unsigned int i{}; i < size; i++)
555 {
556 ListItem list_item{};
557 list_item.type = LT_MEDIA_LIB;
558 CString strTmp;
559 ar >> strTmp;
560 list_item.path = strTmp.GetString();
561 ar >> temp; // 丢弃track
562 ar >> temp; // 丢弃position
563 ar >> list_item.total_num;
564 ar >> list_item.total_time;
565 ar >> list_item.last_played_time;
566 ar >> temp;
567 list_item.medialib_type = static_cast<CMediaClassifier::ClassificationType>(temp);
568 ar >> temp;
569 list_item.sort_mode = static_cast<SortMode>(temp);
570
571 m_list.push_back(std::move(list_item));
572 }
573 }
574 catch (CArchiveException* exception)
575 {
576 //捕获序列化时出现的异常
577 wstring info = theApp.m_str_table.LoadTextFormat(L"MSG_SERIALIZE_ERROR", { theApp.m_recent_medialib_playlist_path, exception->m_cause });
578 theApp.WriteLog(info);
579 }
580 // 关闭对象
581 ar.Close();
582 // 关闭文件
583 file.Close();
584 }
585 }
586
587