xref: /MusicPlayer2/MusicPlayer2/COSUPlayerHelper.cpp (revision 30eb58cf938f2dced2d7fddc283cd0d36a2d3364)
1 #include "stdafx.h"
2 #include "COSUPlayerHelper.h"
3 #include "FilePathHelper.h"
4 #include "AudioCommon.h"
5 #include "Common.h"
6 
7 
COSUPlayerHelper()8 COSUPlayerHelper::COSUPlayerHelper()
9 {
10 }
11 
12 
~COSUPlayerHelper()13 COSUPlayerHelper::~COSUPlayerHelper()
14 {
15 }
16 
IsOsuFolder(const std::wstring & strPath)17 bool COSUPlayerHelper::IsOsuFolder(const std::wstring & strPath)
18 {
19     if (strPath.empty())
20         return false;
21 
22     wstring folder_path{ strPath };
23     if (folder_path.back() != L'\\' && folder_path.back() != L'/')
24         folder_path.push_back(L'\\');
25 
26     CFilePathHelper path_helper(folder_path);
27     wstring parent_dir = path_helper.GetParentDir();
28 
29     //判断一个文件是否为osu的Songs目录:它的父级目录有osu!.exe文件且文件夹是Songs
30     return folder_path.size() > 7 && folder_path.substr(folder_path.size() - 6, 5) == L"Songs" && CCommon::FileExist(parent_dir + L"osu!.exe");
31 }
32 
IsOsuFile(const std::wstring & strPath)33 bool COSUPlayerHelper::IsOsuFile(const std::wstring& strPath)
34 {
35     if (strPath.empty())
36         return false;
37 
38     CFilePathHelper path_helper(strPath);
39     return IsOsuFolder(path_helper.GetParentDir());
40 }
41 
GetOSUAudioFiles(wstring path,vector<SongInfo> & song_list)42 void COSUPlayerHelper::GetOSUAudioFiles(wstring path, vector<SongInfo>& song_list)
43 {
44     vector<wstring> files;
45     GetOSUAudioFiles(path, files);
46     for (const auto& file : files)
47     {
48         SongInfo song_info;
49         song_info.file_path = file;
50         song_list.push_back(song_info);
51     }
52 }
53 
GetOSUAudioFiles(wstring path,vector<wstring> & files)54 void COSUPlayerHelper::GetOSUAudioFiles(wstring path, vector<wstring>& files)
55 {
56     if (path.back() != L'\\' && path.back() != L'/')
57         path.push_back(L'\\');
58 
59     vector<wstring> folder_list;
60     CCommon::GetFiles(path + L"*", folder_list);
61     for (const auto& folder_name : folder_list)
62     {
63         if(folder_name == L"." || folder_name == L"..")
64             continue;
65 
66         std::vector<wstring> osu_list;
67         CCommon::GetFiles(path + folder_name + L"\\*.osu", osu_list);
68         if(!osu_list.empty())
69         {
70             COSUFile osu_file{ (path + folder_name + L'\\' + osu_list.front()).c_str() };
71             wstring file_name = path + folder_name + L'\\' + osu_file.GetAudioFileName();
72             // 这里的file_name大小写可能与实际文件不同会导致自动更新/播放时媒体库出现大小写各一份,这里统一以音频文件为准
73             if (CCommon::CheckAndFixFile(file_name))
74                 files.push_back(file_name);
75         }
76     }
77 }
78 
GetOSUAudioTitleArtist(SongInfo & song_info)79 void COSUPlayerHelper::GetOSUAudioTitleArtist(SongInfo & song_info)
80 {
81     CFilePathHelper file_path{ song_info.file_path };
82     wstring song_folder = file_path.GetDir();
83 
84     std::vector<wstring> osu_list;
85     CCommon::GetFiles(song_folder + L"*.osu", osu_list);
86     if (!osu_list.empty())
87     {
88         COSUFile osu_file{ (song_folder + osu_list.front()).c_str() };
89         song_info.artist = osu_file.GetArtist();
90         song_info.title = osu_file.GetTitle();
91         song_info.album = osu_file.GetAlbum();
92 
93         wstring id = osu_file.GetBeatampSetId();
94         wstring folder_name = file_path.GetFolderName();
95         if (id.empty())
96         {
97             size_t index = folder_name.find(L' ');
98             id = folder_name.substr(0, index);
99         }
100         song_info.track = _wtoi(id.c_str());
101         song_info.comment = folder_name;
102     }
103 }
104 
GetAlbumCover(wstring file_path)105 wstring COSUPlayerHelper::GetAlbumCover(wstring file_path)
106 {
107     wstring dir;
108     CFilePathHelper path_helper(file_path);
109     dir = path_helper.GetDir();
110 
111     wstring album_cover_file_name;
112     std::vector<wstring> osu_list;
113     CCommon::GetFiles(dir + L"*.osu", osu_list);
114     std::sort(osu_list.begin(), osu_list.end());       // 不存在BeatampId标签时使用此次排序后第一个osu文件的封面
115     int beatmap_id{};
116     for (const wstring& osu_item : osu_list)
117     {
118         COSUFile osu_file{ (dir + osu_item).c_str() };
119         wstring id_s{ osu_file.GetBeatampId() };
120         if (!id_s.empty())
121         {
122             int id_i{ std::stoi(id_s) };
123             if (beatmap_id == 0 || beatmap_id > id_i)  // 取得beatmap_id最小的osu文件对应封面
124             {
125                 beatmap_id = id_i;
126                 album_cover_file_name = osu_file.GetAlbumCoverFileName();
127             }
128         }
129         else  // 如果出现id_s为空说明osu文件版本较旧,获取osu_list[0]的封面后退出循环
130         {
131             album_cover_file_name = osu_file.GetAlbumCoverFileName();
132             break;
133         }
134     }
135 
136     if (!CCommon::FileExist(dir + album_cover_file_name))
137     {
138         vector<wstring> image_list;
139         CCommon::GetFiles(dir + L"*.jpg", image_list);
140         if (!image_list.empty())
141 	    {
142             album_cover_file_name = image_list[0];
143 	    }
144     }
145 
146     //没有找到封面时查找osu目录下Data\bg里面的图片,并随机选择一张作为封面
147     if (!CCommon::FileExist(dir + album_cover_file_name))
148     {
149         static std::map<wstring, wstring> bg_map;       //每次为一首没有封面的文件随机选择一张封面后保存起来,下次则直接返回上次获取的封面
150         auto iter = bg_map.find(file_path);
151         if (iter != bg_map.end())
152         {
153             return iter->second;
154         }
155         else
156         {
157             wstring songs_dir = path_helper.GetParentDir();
158             wstring osu_dir = CFilePathHelper(songs_dir).GetParentDir();
159             wstring bg_dir = osu_dir + L"Data\\bg\\";
160             std::vector<wstring> bg_files;
161             CCommon::GetImageFiles(bg_dir + L"*.*", bg_files);
162             if (!bg_files.empty())
163             {
164                 wstring cover_path;
165                 //有多个图片时随机选择一张
166                 if (bg_files.size() > 1)
167                 {
168                     SYSTEMTIME current_time;
169                     GetLocalTime(&current_time);			//获取当前时间
170                     srand(current_time.wMilliseconds);		//用当前时间的毫秒数设置产生随机数的种子
171                     int index = rand() % static_cast<int>(bg_files.size());
172                     cover_path = bg_dir + bg_files[index];
173                 }
174                 else
175                 {
176                     cover_path = bg_dir + bg_files[0];
177                 }
178                 bg_map[file_path] = cover_path;
179                 return cover_path;
180             }
181         }
182     }
183 
184     if (album_cover_file_name.empty())
185         return wstring();
186     else
187         return dir + album_cover_file_name;
188 }
189 
GetOSUFile(wstring folder_path)190 void COSUPlayerHelper::GetOSUFile(wstring folder_path)
191 {
192 }
193 
194 
195 ////////////////////////////////////////////////////////////////////////////
COSUFile(const wchar_t * file_path)196 COSUFile::COSUFile(const wchar_t * file_path)
197 {
198     CFilePathHelper file_path_helper{ file_path };
199     wstring ext = file_path_helper.GetFileExtension();
200     if (ext != L"osu")
201         return;
202 
203     CCommon::GetFileContent(file_path, m_data);
204     if (m_data.empty())
205         return;
206 
207     GetTag("[General]", m_general_seg);
208     GetTag("[Metadata]", m_metadata_seg);
209     GetTag("[Events]", m_events_seg);
210 }
211 
GetAudioFileName()212 wstring COSUFile::GetAudioFileName()
213 {
214     return GetTagItem("AudioFilename:", m_general_seg);
215 }
216 
GetArtist()217 wstring COSUFile::GetArtist()
218 {
219     wstring artist = GetTagItem("ArtistUnicode:", m_metadata_seg);
220     if(artist.empty())
221         artist = GetTagItem("Artist:", m_metadata_seg);
222     return artist;
223 }
224 
GetTitle()225 wstring COSUFile::GetTitle()
226 {
227     wstring artist = GetTagItem("TitleUnicode:", m_metadata_seg);
228     if (artist.empty())
229         artist = GetTagItem("Title:", m_metadata_seg);
230     return artist;
231 }
232 
GetAlbum()233 wstring COSUFile::GetAlbum()
234 {
235     return GetTagItem("Source:", m_metadata_seg);
236 }
237 
GetBeatampId()238 wstring COSUFile::GetBeatampId()
239 {
240     return GetTagItem("BeatmapID:", m_metadata_seg);
241 }
242 
GetBeatampSetId()243 wstring COSUFile::GetBeatampSetId()
244 {
245     return GetTagItem("BeatmapSetID:", m_metadata_seg);
246 }
247 
GetAlbumCoverFileName()248 wstring COSUFile::GetAlbumCoverFileName()
249 {
250     size_t index1{}, index2{};
251     string album_cover_name;
252     while (true)
253     {
254         //查找,"到"之间的字符串
255         index1 = m_events_seg.find(",\"", index1);
256         if (index1 == string::npos)
257             return wstring();
258         index2 = m_events_seg.find("\"", index1 + 2);
259         album_cover_name = m_events_seg.substr(index1 + 2, index2 - index1 - 2);
260         index1 = index2 + 1;
261         size_t index0 = album_cover_name.rfind('.');
262         string ext;
263         if (index0 != string::npos)
264             ext = album_cover_name.substr(index0 + 1);
265         //如果获取到的文件名是图片文件,则将其返回
266         if(CCommon::StringCompareNoCase(ext, string("jpg")) || CCommon::StringCompareNoCase(ext, string("png")) || CCommon::StringCompareNoCase(ext, string("jpeg")))
267             return CCommon::StrToUnicode(album_cover_name, CodeType::UTF8);
268     }
269 }
270 
GetTag(const string & tag,string & tag_content)271 void COSUFile::GetTag(const string & tag, string & tag_content)
272 {
273     size_t start{}, end{};
274     start = m_data.find(tag);
275     if (start != string::npos)
276         end = m_data.find("\n[", start + tag.size());
277 
278     tag_content = m_data.substr(start, end - start);
279 
280 }
281 
GetTagItem(const string & tag,const string & tag_content)282 wstring COSUFile::GetTagItem(const string & tag, const string & tag_content)
283 {
284     size_t start = tag_content.find(tag);
285     if (start != string::npos)
286     {
287         size_t end = tag_content.find('\n', start + 1);
288         string file_name = tag_content.substr(start + tag.size(), end - start - tag.size());
289         CCommon::StringNormalize(file_name);
290         return CCommon::StrToUnicode(file_name, CodeType::UTF8);
291     }
292     return wstring();
293 }
294