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