1 #include "stdafx.h"
2 #include "ListCache.h"
3 #include "CRecentList.h"
4 #include "Common.h"
5
6
reload()7 bool CListCache::reload()
8 {
9 // 如果m_ver没变则返回false表示CRecentList数据没有变化
10 if (m_ui_ver == CRecentList::m_instance.m_ver)
11 return false;
12 // 加锁后不允许再调用CRecentList的方法防止锁重入 (为保证同步,reload期间只能加这一次锁,不能反复加解锁)
13 std::lock_guard<std::mutex> lock(CRecentList::m_instance.m_mutex);
14
15 // 虽然是CRecentList的友元但此处只应进行只读访问
16 const auto& instance = CRecentList::m_instance;
17 // m_ui_list
18 m_ui_list.clear();
19 vector<const ListItem*> sub_list = BuildSubList();
20 for (const ListItem* pListItem : sub_list)
21 m_ui_list.push_back(*pListItem);
22 // m_ui_current_play_index
23 ASSERT(!instance.m_list.empty()); // CRecentList的m_list在初始化后就从不为空,因为有特殊播放列表不会被删除
24 auto iter = std::find(m_ui_list.begin(), m_ui_list.end(), instance.m_list.front());
25 m_ui_current_play_index = (iter != m_ui_list.end()) ? iter - m_ui_list.begin() : -1;
26 // m_ui_ver
27 m_ui_ver = instance.m_ver;
28
29 return true;
30 }
31
GetItem(size_t index) const32 ListItem CListCache::GetItem(size_t index) const
33 {
34 std::lock_guard<std::mutex> lock(CRecentList::m_instance.m_mutex);
35 vector<const ListItem*> sub_list = BuildSubList();
36 if (index < sub_list.size())
37 return *sub_list[index];
38 return ListItem();
39 }
40
GetIndex(const ListItem & list_item) const41 int CListCache::GetIndex(const ListItem& list_item) const
42 {
43 std::lock_guard<std::mutex> lock(CRecentList::m_instance.m_mutex);
44 vector<const ListItem*> sub_list = BuildSubList();
45 auto it = std::find_if(sub_list.begin(), sub_list.end(), [&](const ListItem* pListItem) { return list_item == *pListItem; });
46 if (it == sub_list.end())
47 return -1;
48 return it - sub_list.begin();
49 }
50
ReadAllListItem(std::function<void (vector<const ListItem * > & sub_list)> func) const51 void CListCache::ReadAllListItem(std::function<void(vector<const ListItem*>& sub_list)> func) const
52 {
53 std::lock_guard<std::mutex> lock(CRecentList::m_instance.m_mutex);
54 vector<const ListItem*> sub_list = BuildSubList();
55 func(sub_list);
56 }
57
BuildSubList() const58 vector<const ListItem*> CListCache::BuildSubList() const
59 {
60 vector<const ListItem*> sub_list;
61 const auto& instance = CRecentList::m_instance;
62
63 if (m_type == LT_CURRENT)
64 {
65 sub_list.push_back(&instance.m_list.front());
66 return sub_list;
67 }
68
69 for (const ListItem& item : instance.m_list)
70 if ((m_type == LT_PLAYLIST_NO_SPEC && item.type == LT_PLAYLIST && !CRecentList::IsSpecPlaylist(item)) ||
71 (m_type == LT_RECENT && item.last_played_time > 0) ||
72 m_type == LT_ALL ||
73 (m_type < LT_MAX && m_type == item.type))
74 sub_list.push_back(&item);
75
76 CRecentList::listSortMode sort_mode{ CRecentList::SM_RECENT_PLAYED };
77 if (m_type == LT_FOLDER)
78 sort_mode = instance.m_sort_mode[LT_FOLDER];
79 if (m_type == LT_PLAYLIST || m_type == LT_PLAYLIST_NO_SPEC)
80 sort_mode = instance.m_sort_mode[LT_PLAYLIST];
81
82 if (sub_list.size() > 1)
83 {
84 // m_list本身是按照最近播放排序的,此时不用再次排序
85 switch (sort_mode)
86 {
87 case CRecentList::SM_RECENT_CREATED:
88 std::stable_sort(sub_list.begin(), sub_list.end(),
89 [](const ListItem* a, const ListItem* b) { return a->create_time > b->create_time; });
90 break;
91 case CRecentList::SM_PATH: // 如果将来LT_MEDIA_LIB需要SM_PATH排序了,这里要注意一下,简单的排path可能不再符合要求
92 std::stable_sort(sub_list.begin(), sub_list.end(),
93 [](const ListItem* a, const ListItem* b) { return CCommon::StringCompareInLocalLanguage(a->path, b->path) < 0; });
94 break;
95 default:
96 break;
97 }
98 // 排序播放列表列表时固定特殊播放列表位置
99 if (m_type == LT_PLAYLIST)
100 {
101 vector<const ListItem*> tmp_list;
102 tmp_list.resize(sub_list.size(), nullptr);
103 int offset{ 2 };
104 for (const ListItem* pListItem : sub_list)
105 {
106 if (CRecentList::IsSpecPlaylist(*pListItem, CRecentList::PT_DEFAULT))
107 tmp_list[0] = pListItem;
108 else if (CRecentList::IsSpecPlaylist(*pListItem, CRecentList::PT_FAVOURITE))
109 tmp_list[1] = pListItem;
110 else if (CRecentList::IsSpecPlaylist(*pListItem, CRecentList::PT_TEMP))
111 tmp_list.back() = pListItem;
112 else
113 tmp_list[offset++] = pListItem;
114 }
115 ASSERT(std::find(tmp_list.begin(), tmp_list.end(), nullptr) == tmp_list.end());
116 std::swap(sub_list, tmp_list);
117 }
118 }
119 return sub_list;
120 }
121