1 #pragma once 2 #include "Time.h" 3 4 enum eTagType 5 { 6 T_OTHER_TAG = 0, 7 T_ID3V1 = 1, 8 T_ID3V2 = 1 << 1, 9 T_APE = 1 << 2, 10 T_RIFF = 1 << 3, 11 T_MP4 = 1 << 4, 12 }; 13 14 //排序方式 15 enum SortMode 16 { 17 SM_U_FILE = 0, // 文件名 升序 18 SM_D_FILE, // 文件名 降序 19 SM_U_PATH, // 路径 升序 20 SM_D_PATH, // 路径 降序 21 SM_U_TITLE, // 标题 升序 22 SM_D_TITLE, // 标题 降序 23 SM_U_ARTIST, // 艺术家 升序 24 SM_D_ARTIST, // 艺术家 降序 25 SM_U_ALBUM, // 专辑 升序 26 SM_D_ALBUM, // 专辑 降序 27 SM_U_TRACK, // 音轨号 升序 28 SM_D_TRACK, // 音轨号 降序 29 SM_U_LISTEN, // 累计播放时间 升序 30 SM_D_LISTEN, // 累计播放时间 降序 31 SM_U_TIME, // 修改日期 升序 32 SM_D_TIME, // 修改日期 降序 33 SM_U_GENRE, // 流派 升序 34 SM_D_GENRE, // 流派 降序 35 SM_U_YEAR, // 年份 升序 36 SM_D_YEAR, // 年份 降序 37 SM_U_BITRATE, // 比特率 升序 38 SM_D_BITRATE, // 比特率 降序 39 40 SM_UNSORT = 100, // 未排序(进入播放列表模式时总是设置为此排序方式,且不进行持久化) 41 }; 42 43 //一首歌曲的信息 44 struct SongInfo 45 { 46 wstring file_path{}; // 歌曲的路径 47 wstring lyric_file{}; // 匹配的歌词文件的路径 48 wstring title; // 标题 49 wstring artist; // 艺术家 50 wstring album; // 唱片集 51 wstring comment; // 注释 52 wstring genre; // 流派 53 wstring cue_file_path; // cue文件的路径 54 wstring album_artist; // 唱片集艺术家 55 unsigned __int64 song_id{}; // 歌曲对应的网易云音乐中的歌曲ID<仅在媒体库内使用> 56 __int64 last_played_time{}; // 上次播放的时间<仅在媒体库内使用> 57 unsigned __int64 modified_time{}; // 修改时间 58 int track{}; // 音轨序号 59 int listen_time{}; // 歌曲累计听的时间(单位为秒)<仅在媒体库内使用> 60 int freq{}; // 采样频率 61 Time start_pos{}; // 音频的起始位置 62 Time end_pos{}; // 音频的结束位置 63 unsigned short year{}; // 年份 64 short bitrate{}; // 比特率 65 WORD flags{}; // 保存一些标志<仅在媒体库内使用> 66 BYTE tag_type{}; // 标签的类型(0:其他;1:ID3v1;2:ID3v2;3:APE) 67 BYTE genre_idx{ 255 }; // 以字节表示的流派号 68 bool info_acquired{ false }; // 如果已经获取到了信息,则为ture (实际上已完全没有作用,可以被modified_time==0和ChannelInfoAcquired代替,考虑移除) 69 bool is_favourite{ false }; // 是否在我喜欢的音乐列表内<仅在播放列表内使用> 70 bool is_cue{ false }; // 如果曲目是cue分轨,则为true 71 BYTE rating{ 255 }; // 歌曲分级<仅在媒体库内使用> 72 BYTE bits{}; // 位深度 73 BYTE channels{}; // 声道数 74 BYTE total_tracks{}; // 曲目总数 75 BYTE disc_num{}; // CD序号 76 BYTE total_discs{}; // CD总数 77 78 // 如果为true,则不在线下载歌词<flags bit0> 79 bool NoOnlineLyric() const; 80 // 如果为true,则不在线下载歌词<flags bit0> 81 void SetNoOnlineLyric(bool val); 82 // 如果为true,则不在线下载专辑封面<flags bit1> 83 bool NoOnlineAlbumCover() const; 84 // 如果为true,则不在线下载专辑封面<flags bit1> 85 void SetNoOnlineAlbumCover(bool val); 86 // 如果为true,则总是使用外部封面<flags bit2> 87 bool AlwaysUseExternalAlbumCover() const; 88 // 如果为true,则总是使用外部封面<flags bit2> 89 void SetAlwaysUseExternalAlbumCover(bool val); 90 // 采样率、位深度、声道数信息是否已获取<flags bit3> 91 bool ChannelInfoAcquired() const; 92 // 采样率、位深度、声道数信息是否已获取<flags bit3> 93 void SetChannelInfoAcquired(bool val); 94 95 //从另一个SongInfo对象复制标签信息 96 void CopyAudioTag(const SongInfo& song_info); 97 98 bool IsTitleEmpty() const; 99 bool IsArtistEmpty() const; 100 bool IsAlbumEmpty() const; 101 bool IsYearEmpty() const; 102 bool IsGenreEmpty() const; 103 104 // 获取艺术家列表(可能存在多个艺术家) 105 void GetArtistList(vector<wstring>& artist_list) const; 106 // TODO: 迁移所有用于文件名的艺术家字符串从这里获取 107 // 获取首个艺术家(作为文件名时请从这里获取以限制长度) 108 wstring GetFirstArtist() const; 109 110 wstring GetTitle() const; 111 wstring GetArtist() const; 112 wstring GetAlbum() const; 113 wstring GetYear() const; 114 wstring get_year() const; 115 wstring GetGenre() const; 116 wstring GetFileName() const; 117 wstring GetSongId() const; 118 119 void SetYear(const wchar_t* str_year); 120 void SetSongId(const wstring& id); 121 122 bool IsEmpty() const; 123 Time length() const; 124 // 判断是否为相同歌曲,原比较代码有漏洞,请迁移所有比较到使用此方法 125 bool IsSameSong(const SongInfo& song) const; 126 // 清除歌曲信息中的<>内的默认字符串 127 void Normalize(); 128 129 // 获取SongInfo的排序谓词方法 130 static std::function<bool(const SongInfo& a, const SongInfo& b)> GetSortFunc(SortMode sort_mode); 131 // 获取排序方式的显示名称 132 static wstring GetSortModeDisplayName(SortMode sort_mode); 133 }; 134 135 struct SongKey 136 { 137 wstring path; 138 int cue_track{}; // 当存储cue时用来保存音轨号,其他情况为0 139 SongKeySongKey140 SongKey() {} SongKeySongKey141 SongKey(const wstring& path) : path(path) 142 { 143 ASSERT(!path.empty()); 144 } SongKeySongKey145 SongKey(const wstring& path, const int& cue_track) : path(path), cue_track(cue_track) 146 { 147 ASSERT(!path.empty()); 148 } SongKeySongKey149 SongKey(const SongInfo& song_info) 150 { 151 ASSERT(!song_info.file_path.empty()); 152 path = song_info.file_path; 153 if (song_info.is_cue) 154 cue_track = song_info.track; 155 } 156 bool operator<(const SongKey& key) const 157 { 158 if (int pathComparison = path.compare(key.path)) 159 return pathComparison < 0; 160 return cue_track < key.cue_track; 161 } 162 bool operator==(const SongInfo& other) const 163 { 164 if ((cue_track > 0) != other.is_cue) // is_cue不同 165 return false; 166 if (path != other.file_path) // 路径不同 167 return false; 168 if ((cue_track > 0) && cue_track != other.track) // is_cue为true时音轨号不同 169 return false; 170 return true; 171 } 172 }; 173 174 namespace std { 175 template <> 176 struct hash<SongKey> { 177 std::size_t operator()(const SongKey& key) const { 178 return std::hash<wstring>()(key.path) ^ std::hash<int>()(key.cue_track); 179 } 180 }; 181 template <> 182 struct equal_to<SongKey> { 183 bool operator()(const SongKey& lhs, const SongKey& rhs) const { 184 return lhs.path == rhs.path && lhs.cue_track == rhs.cue_track; 185 } 186 }; 187 } 188