xref: /MusicPlayer2/MusicPlayer2/CRecentList.h (revision 965ce478a79b0d21e8a6e2ade0490efa175855dd)
1 #pragma once
2 #include "ListItem.h"
3 
4 // 维护程序所有的列表对象即实际持有&管理所有“ListItem”
5 // 此类不直接提供面向UI的接口,因为UI不应从这里直接读数据,同步有问题
6 // 请构造一个CListCache对象来为UI创建只读数据副本
7 // 需要修改时仍然使用CRecentList的接口,CListCache成员方法reload能够刷新其持有的显示缓存
8 
9 class CListCache;
10 
11 class CRecentList
12 {
13     friend class CListCache;
14 public:
~CRecentList()15     ~CRecentList() {};
Instance()16     static CRecentList& Instance() { return m_instance; }
17 
18     // 列表排序方式
19     enum listSortMode
20     {
21         SM_UNSORTED,        // 未排序
22         SM_RECENT_PLAYED,   // 最近播放
23         SM_RECENT_CREATED,  // 最近创建/添加
24         SM_PATH,            // 路径/名称
25     };
26     bool SetSortMode(ListType type, listSortMode sort_mode);
27     listSortMode GetSortMode(ListType type) const;
28 
29     // 更新(不存在时添加)当前正在播放的列表的信息(列表进入/播放曲目/列表退出 时使用这个)
30     // 约定只有此方法能够变动m_list.front(),因为第一项即程序的“当前播放”列表
31     void SetCurrentList(ListItem list_item);
32     // 获取当前播放的列表的信息副本
33     ListItem GetCurrentList() const;
34     // 判断list_item是否为正在播放的列表
35     bool IsCurrentList(const ListItem& list_item) const;
36     // 如果list_item不存在则将其加入m_list末尾并返回true,否则返回false
37     // 对LT_PLAYLIST,文件不存在时会负责创建空播放列表文件
38     bool AddNewItem(ListItem list_item);
39     // 从m_list加载指定list_item的信息,不存在时返回false
40     bool LoadItem(ListItem& list_item) const;
41 
42     // 实际存储时不再区分播放列表类型,此处枚举仅用作接下来的接口的参数
43     enum PlaylistType
44     {
45         PT_DEFAULT,
46         PT_FAVOURITE,
47         PT_TEMP,
48         PT_MAX,
49     };
50     // 获取指定的特殊播放列表信息副本
51     ListItem GetSpecPlaylist(PlaylistType type) const;
52     // 判断是否正在播放指定类型的特殊播放列表 (type为PT_MAX时对任意特殊播放列表返回true)
53     bool IsPlayingSpecPlaylist(PlaylistType type = PlaylistType::PT_MAX);
54     // 判断ListItem是否是指定类型的特殊播放列表 (type为PT_MAX时对任意特殊播放列表返回true)
55     static bool IsSpecPlaylist(const ListItem& list_item, PlaylistType type = PlaylistType::PT_MAX);
56 
57     // 移除指定的列表信息(不存在时返回false)
58     // 特别的,当前播放的列表 & 默认播放列表 & 我喜欢的播放列表 禁止移除
59     // 对于LT_PLAYLIST,请先成功删除播放列表文件再调用此方法(因为不应在持有锁期间打开模态窗口)
60     bool RemoveItem(const ListItem& list_item);
61     // 遍历m_list,移除func返回true的项目
62     // 特别的,当前播放的列表 & 默认播放列表 & 我喜欢的播放列表 禁止移除
63     // 对于LT_PLAYLIST,请先成功删除播放列表文件再调用此方法(因为不应在持有锁期间打开模态窗口)
64     int RemoveItemIf(std::function<bool(const ListItem& list_item)> func);
65 
66     // 将上次播放时间清空,使它从“最近播放”中移除 (不会对当前播放生效)
67     // 特别的,对于LT_MEDIA_LIB实际执行的是RemoveItem
68     bool ResetLastPlayedTime(const ListItem& list_item);
69 
70     // 翻转m_list中指定项目的contain_sub_folder成员
71     // ListItem的type必须为LT_FOLDER,不会对当前播放生效
72     bool SetContainSubFolder(const ListItem& list_item);
73     // 将m_list内对应项目的 total_time & total_num 修改为参数的值
74     // ListItem的type必须为LT_PLAYLIST,不会对当前播放生效,有修改发生时返回true
75     bool SetPlaylistTotalInfo(const ListItem& list_item, int total_num, int total_time);
76     // 重命名播放列表 (之后要改成不会对当前播放生效)
77     bool RenamePlaylist(const ListItem& list_item, const wstring& new_path);
78 
79 private:
80     // 不存在时创建&读取对应playlist文件的创建时间(CRecentList内部使用)
81     ListItem CreateNewPlaylistListItem(ListItem list_item);
82 
83 public:
84     // 将数据写入文件
85     void SaveData() const;
86     // 从文件读取数据
87     bool LoadData();
88 private:
89     // 读取数据后调用一次
90     void AfterLoadData();
91     // 读取旧版未整合数据
92     void LoadOldData();
93 
94 private:
CRecentList()95     CRecentList() {};
96     static CRecentList m_instance;                  // 此类唯一的对象
97 
98     std::atomic<int> m_ver{};                       // 每次m_list/m_sort_mode变化时加一,即数据的修改标记
99     std::array<listSortMode, LT_MAX> m_sort_mode{}; // 列表的列表的排序方式,此类不直接使用,由友元CListCache读取使用
100     std::list<ListItem> m_list;                     // 列表的列表,总是保持按最近播放时间降序排序
101 
102     mutable std::mutex m_mutex;                     // 此类的成员变量读/写时先锁定此互斥量
103     // 特殊播放列表的原型,用来做==比较,初始化之后只读
104     static std::array<ListItem, CRecentList::PlaylistType::PT_MAX> SP_PLAYLIST;
105 };
106 
107