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