xref: /MusicPlayer2/MusicPlayer2/CommonData.h (revision 47cdddcc076af4869ff0138140f620e73e47e8f1)
1 #pragma once
2 #include "ColorConvert.h"
3 #include "DrawCommon.h"
4 #include "Common.h"
5 
6 namespace CONSTVAL
7 {
8     const COLORREF BACKGROUND_COLOR = GRAY(255);		//更改此颜色的值可以修改主窗口背景色
9     const double FULL_SCREEN_ZOOM_FACTOR = 1.5;
10 }
11 
12 struct DeviceInfo	//播放设备的信息
13 {
14     int index;		//设备的索引
15     wstring name;	//设备的名称
16     wstring driver;	//设备的驱动程序
17     DWORD flags;	//设备的状态
18 };
19 
20 
21 struct FontStyle
22 {
23     bool bold{ false };			//粗体
24     bool italic{ false };		//斜体
25     bool underline{ false };	//下划线
26     bool strike_out{ false };	//删除线
27 
ToIntFontStyle28     int ToInt()
29     {
30         int value = 0;
31         if (bold)
32             value |= 0x01;
33         if (italic)
34             value |= 0x02;
35         if (underline)
36             value |= 0x04;
37         if (strike_out)
38             value |= 0x08;
39         return value;
40     }
41 
FromIntFontStyle42     void FromInt(int value)
43     {
44         bold = (value % 2 != 0);
45         italic = ((value >> 1) % 2 != 0);
46         underline = ((value >> 2) % 2 != 0);
47         strike_out = ((value >> 3) % 2 != 0);
48     }
49 };
50 
51 struct FontInfo
52 {
53     wstring name;	//字体名称
54     int size;		//字体大小
55     FontStyle style;	//字体样式
56 };
57 
58 
59 struct UIFont
60 {
61 private:
62     CFont font;
63     CFont font_l;
64 
65 public:
66     CFont& GetFont(bool large = false)
67     {
68         return (large ? font_l : font);
69     }
70 
71     void SetFont(int font_size, LPCTSTR font_name, FontStyle style = FontStyle())
72     {
73         if (font_size < 5)
74             font_size = 5;
75 
76         if (font.m_hObject)
77             font.DeleteObject();
78         CreateFontSimple(font, font_size, font_name, style);
79 
80         if (font_l.m_hObject)
81             font_l.DeleteObject();
82         CreateFontSimple(font_l, static_cast<int>(font_size * CONSTVAL::FULL_SCREEN_ZOOM_FACTOR), font_name, style);
83     }
84 
SetFontUIFont85     void SetFont(FontInfo font_info)
86     {
87         SetFont(font_info.size, font_info.name.c_str(), font_info.style);
88     }
89 
90     static void CreateFontSimple(CFont& font, int font_size, LPCTSTR font_name, FontStyle style = FontStyle())
91     {
92         font.CreateFont(
93             FontSizeToLfHeight(font_size), // nHeight
94             0, // nWidth
95             0, // nEscapement
96             0, // nOrientation
97             (style.bold ? FW_BOLD : FW_NORMAL), // nWeight
98             style.italic, // bItalic
99             style.underline, // bUnderline
100             style.strike_out, // cStrikeOut
101             DEFAULT_CHARSET, // nCharSet
102             OUT_DEFAULT_PRECIS, // nOutPrecision
103             CLIP_DEFAULT_PRECIS, // nClipPrecision
104             DEFAULT_QUALITY, // nQuality
105             DEFAULT_PITCH | FF_SWISS, // nPitchAndFamily
106             font_name);
107     }
108 
109     //将字号转成LOGFONT结构中的lfHeight
FontSizeToLfHeightUIFont110     static int FontSizeToLfHeight(int font_size)
111     {
112         HDC hDC = ::GetDC(HWND_DESKTOP);
113         int lfHeight = -MulDiv(font_size, GetDeviceCaps(hDC, LOGPIXELSY), 72);
114         ::ReleaseDC(HWND_DESKTOP, hDC);
115         return lfHeight;
116     }
117 
118 };
119 
120 struct FontSet
121 {
122     const int FONT_SIZE_MIN{ 8 };
123     const int FONT_SIZE_MAX{ 16 };
124     std::map<int, UIFont> fonts;    //不同大小的默认字体
125 
126     UIFont dlg;                 // 窗口控件字体
127     UIFont lyric;				//歌词字体
128     UIFont lyric_translate;		//歌词翻译的字体
129     UIFont cortana;				//搜索框字体
130     UIFont cortana_translate;	//搜索框翻译字体
131 
132 
133     void Init(LPCTSTR font_name);
134 
135     //获取一个指定大小的字体(目前支持8~16)
136     UIFont& GetFontBySize(int font_size);
137 
138 };
139 
140 
141 //播放列表中项目的显示格式
142 enum DisplayFormat
143 {
144     DF_FILE_NAME,		//文件名
145     DF_TITLE,			//标题
146     DF_ARTIST_TITLE,	//艺术家 - 标题
147     DF_TITLE_ARTIST		//标题 - 艺术家
148 };
149 
150 //最近播放曲目列表显示范围
151 enum RecentPlayedRange
152 {
153     RPR_ALL,			//显示全部
154     RPR_TODAY,          //今天
155     RPR_THREE_DAYS,     //最近三天
156     RPR_WEAK,			//最近一个星期
157     RPR_MONTH,			//最近一个月
158     RPR_HALF_YEAR,		//最近半年
159     RPR_YEAR,			//最近一年
160 };
161 
162 
163 //选项设置数据
164 
165 struct DesktopLyricSettingData		//桌面歌词设置
166 {
167     bool lyric_double_line{ false };
168     FontInfo lyric_font;
169     COLORREF text_color1{};
170     COLORREF text_color2{};
171     int text_gradient{};
172     COLORREF highlight_color1{};
173     COLORREF highlight_color2{};
174     int highlight_gradient{};
175     int opacity{ 100 };
176     bool lock_desktop_lyric{ false };
177     bool hide_lyric_window_without_lyric{ false };	//没有歌词时隐藏歌词窗口
178     bool hide_lyric_window_when_paused{ false };	//暂停时隐藏歌词窗口
179     bool lyric_background_penetrate{ false };
180     bool show_unlock_when_locked{ true };           //桌面歌词锁定时显示解锁图标
181     Alignment lyric_align{ Alignment::AUTO };   //歌词的对齐方式
182 };
183 
184 struct LyricSettingData
185 {
186     bool lyric_karaoke_disp{ true };			//可以是否以卡拉OK样式显示
187     bool lyric_fuzzy_match{ true };				//歌词模糊匹配
188     // bool save_lyric_in_offset{};				//是否将歌词保存在offset标签中,还是保存在每个时间标签中
189     wstring lyric_path;							//歌词文件夹的路径
190     bool use_inner_lyric_first{};				//优先使用内嵌歌词
191     bool show_translate{ true };		        //歌词是否显示翻译
192     bool donot_show_blank_lines{};              //单行和双行显示模式下不显示空白行
193     bool show_song_info_if_lyric_not_exist{};   //是否在没有歌词时显示歌曲信息
194 
195     enum LyricSavePolicy		//歌词保存策略
196     {
197         LS_DO_NOT_SAVE,			//不保存(手动保存)
198         LS_AUTO_SAVE,			//自动保存
199         LS_INQUIRY				//询问
200     };
201 
202     LyricSavePolicy lyric_save_policy{};		//歌词自动保存策略
203 
204     FontInfo lyric_font;						//歌词字体
205     int lyric_line_space{ 2 };					//歌词的行间距
206     Alignment lyric_align{ Alignment::AUTO };   //歌词的对齐方式
207 
208     bool cortana_info_enable{};				    //是否允许在Cortana的搜索框中显示信息
209     bool cortana_show_lyric{ true };            //是否在Cortana搜索框中显示歌词
210     bool cortana_lyric_double_line{ true };		//是否在Cortana搜索中以双行显示歌词
211     int cortana_color{ 0 };						//Cortana搜索框的背景颜色(0:跟随系统,1:黑色,2:白色)
212     bool cortana_show_album_cover{ true };		//是否在Cortana搜索框显示专辑封面
213     bool cortana_icon_beat{ true };				//Cortana图标随音乐节奏跳动
214     bool cortana_lyric_compatible_mode{ false };	//Cortana搜索框歌词显示使用兼容模式
215     FontInfo cortana_font;						//搜索框字体
216     bool cortana_lyric_keep_display{ false };	//搜索框歌词是否在暂停时保持显示
217     bool cortana_show_spectrum{ false };		//是否在搜索框显示频谱
218     bool cortana_opaque{ false };				//搜索框不透明
219     Alignment cortana_lyric_align{ Alignment::AUTO };           //搜索框歌词对齐方式
220     bool show_default_album_icon_in_search_box{ false };      //没有歌词时搜索框显示黑色胶片图标
221     COLORREF cortana_transparent_color{};
222 
223     bool show_desktop_lyric{ false };			//显示桌面歌词
224     DesktopLyricSettingData desktop_lyric_data;
225 };
226 
227 struct ApperanceSettingData
228 {
229     int window_transparency{ 100 };				//窗口透明度
230     ColorTable theme_color;						//主题颜色
231     bool theme_color_follow_system{ true };		//主题颜色跟随系统(仅Win8以上支持)
232     bool show_album_cover;						//显示专辑封面
233     CDrawCommon::StretchMode album_cover_fit{ CDrawCommon::StretchMode::FILL };		//专辑封面契合度(拉伸模式)
234     bool enable_background{ true };
235     bool album_cover_as_background{ false };	//将专辑封面作为背景
236     bool show_spectrum{ true };					//显示频谱分析
237     int sprctrum_height{ 100 };					//频谱分析高度比例(%)
238     bool spectrum_low_freq_in_center{ false };  //频谱分析低频部分显示在中间
239     bool use_old_style_specturm{ false };       //使用旧风格的频谱分析显示
240     int background_transparency{ 80 };			//背景的透明度
241 
242     bool use_out_image{ true };					//使用外部图片作为专辑封面
243     bool use_inner_image_first{ true };			//优先使用内嵌专辑封面
244     wstring album_cover_path;                         // 专辑封面存储路径
245     vector<wstring> default_album_name;			//默认的专辑封面文件名
246 
247     bool background_gauss_blur{ true };			//背景高斯模糊
248     int gauss_blur_radius{ 60 };				//高斯模糊半径*10
249     bool lyric_background{ true };				//歌词界面背景
250     bool dark_mode{ false };					//深色模式
251 
252     bool draw_album_high_quality{ false };      //专辑封面图片使用Gdi+高质量绘图
253     int ui_refresh_interval{ 100 };             //界面刷新的时间间隔
254 
255     int notify_icon_selected{};                 //使用的通知区图标
256     bool notify_icon_auto_adapt{ false }; //通知区图标是否自动适应Win10深浅色模式
257 
258     bool button_round_corners{ false };     //按钮是否使用圆角风格
259 
260     wstring default_background;     //默认的背景图片
261 
262     int playlist_width_percent{ 50 };       //主界面播放列表宽度的百分比
263 
264     bool use_desktop_background{ false };   //使用桌面壁纸作为背景
265 
266     bool always_show_statusbar{ false };    //总是显示状态栏
267     bool show_fps{ true };              //是否在状态栏显示帧率
268     bool show_next_track{ false };      //是否在状态栏显示下一首播放曲目
269 
270     bool show_window_frame{ true };     //显示标准窗口边框
271     bool show_minimize_btn_in_titlebar{ true };     //是否在标题栏显示“最小化”按钮
272     bool show_maximize_btn_in_titlebar{ true };     //是否在标题栏显示“最大化”按钮
273     bool show_minimode_btn_in_titlebar{ true };     //是否在标题栏显示“迷你模式”按钮
274     bool show_fullscreen_btn_in_titlebar{ true };   //是否在标题栏显示“全屏模式”按钮
275     bool show_skin_btn_in_titlebar{ false };        //是否在标题栏显示“切换界面”按钮
276     bool show_settings_btn_in_titlebar{ false };    //是否在标题栏显示“设置”按钮
277     bool show_dark_light_btn_in_titlebar{ false };  //是否在标题栏显示“深色模式/浅色模式”按钮
278     int TitleDisplayItem() const;
279 
280     //如果为true时,当系统为Windows10/11时,如果使用的是自绘标题栏,则去掉标题栏顶部的白边
281     //(目前还存在一些问题,当窗口得到或失去焦点时,窗口会闪烁)
282     bool remove_titlebar_top_frame{ false };
283 };
284 
285 struct GeneralSettingData
286 {
287     bool id3v2_first{ false };					//优先获取ID3V2标签
288     bool auto_download_lyric{ false };			//是否自动下载歌词
289     bool auto_download_album_cover{ true };		//是否自动下载专辑封面
290     bool auto_download_only_tag_full{ true };	//仅在歌曲信息完整时自动下载
291     bool save_lyric_to_song_folder{ true };     // 将自动下载的歌词文件保存在歌曲文件夹
292     bool save_album_to_song_folder{ true };     // 将自动下载的封面文件保存在歌曲文件夹
293     bool download_lyric_text_and_translation_in_same_line{ true };  //下载的歌词原文和翻译在同一行
294     bool check_update_when_start{ true };		//是否在程序启动时检查更新
295     int update_source{};                        //更新源。0: GitHub; 1: Gitee
296     bool minimize_to_notify_icon{ false };		//是否最小到通知区图标
297     bool global_mouse_wheel_volume_adjustment{ true };  //全局鼠标滚轮音量调节
298 
299     wstring language_;                          // 这个是设置状态(空字符串为跟随系统)
300     bool portable_mode{ false };                //如果为true,则程序所有数据都保存到exe所在目录下,否则保存到Appdata\Romaing目录下
301 };
302 
303 struct PlaySettingData
304 {
305     bool stop_when_error{ true };				//出现错误时停止播放
306     bool auto_play_when_start{ false };			//程序启动时自动播放
307     bool continue_when_switch_playlist{ false };//若当前播放歌曲存在于切换到的播放列表则保持播放状态不变
308     bool show_taskbar_progress{ false };		//在任务栏按钮上显示播放进度
309     bool show_playstate_icon{ true };			//在任务栏按钮上显示播放状态的角标
310     wstring output_device;						//播放设备的名称
311     int device_selected{};
312     bool fade_effect{ true };                   //播放淡入淡出效果
313     int fade_time{ 500 };                      //淡入淡出时间(毫秒)
314     bool use_media_trans_control{};             //使用系统MediaTransportControls
315 
316     bool use_mci{ false };              //是否使用MCI内核
317     /// 是否使用ffmpeg内核
318     bool use_ffmpeg{ false };
319     /// ffmpeg内核缓存时长(单位:s)
320     int ffmpeg_core_cache_length { 15 };
321     /// ffmpeg内核最大重试次数
322     int ffmpeg_core_max_retry_count { 3 };
323     /// ffmpeg内核非本地文件重试间隔时间(单位s)
324     int ffmpeg_core_url_retry_interval { 5 };
325     /// ffmpeg内核是否启用WASAPI
326     int ffmpeg_core_enable_WASAPI { false };
327     /// ffmpeg内核是否启用WASAPI独占模式
328     int ffmpeg_core_enable_WASAPI_exclusive_mode { false };
329     /// ffmpeg内核seek等操作最大等待时间
330     int ffmpeg_core_max_wait_time { 3000 };
331 
332     //MIDI设置
333     wstring sf2_path;							//MIDI音色库路径
334     bool midi_use_inner_lyric{ false };			//播放MIDI音乐时显示内嵌歌词
335 };
336 
337 struct GlobalHotKeySettingData
338 {
339     bool hot_key_enable = true;
340     bool global_multimedia_key_enable{ true };	//是否在全局范围内启用多媒体键
341 };
342 
343 enum MediaLibDisplayItem
344 {
345     MLDI_ARTIST = 1,
346     MLDI_ALBUM = (1 << 1),
347     MLDI_GENRE = (1 << 2),
348     MLDI_YEAR = (1 << 3),
349     MLDI_TYPE = (1 << 4),
350     MLDI_BITRATE = (1 << 5),
351     MLDI_RATING = (1 << 6),
352     MLDI_ALL = (1 << 7),
353     MLDI_RECENT = (1 << 8),
354     MLDI_FOLDER_EXPLORE = (1 << 9)
355 };
356 
357 struct MediaLibSettingData
358 {
359     vector<wstring> media_folders;      //媒体库文件夹浏览中显示的文件夹
360     vector<wstring> artist_split_ext;   // 艺术家分割例外,设置名字本身含有分隔符(/;&、)的艺术家(22/7)
361     bool hide_only_one_classification;  //媒体库中将只有一项的分类归到其他类中
362     bool disable_delete_from_disk;      //禁用从磁盘删除
363     bool show_tree_tool_tips;           //树控件显示鼠标提示
364     bool update_media_lib_when_start_up;    //启动时自动更新媒体库
365     bool ignore_too_short_when_update;      // 自动更新/刷新媒体库时忽略时长低于阈值的文件(不影响手动加入)
366     int file_too_short_sec;                 // 音频低时长阈值(清理媒体库功能也使用这个设置)
367     bool remove_file_not_exist_when_update{};   //更新媒体库时移除不存在的音频文件
368     bool disable_drag_sort;				//禁止通过拖放排序
369     DisplayFormat display_format{};		//播放列表中项目的显示样式
370     bool insert_begin_of_playlist{ false };         // 向播放列表添加歌曲时插入开头而不是追加到末尾
371     bool show_playlist_tooltip{};         //显示播放列表工具提示
372     bool float_playlist_follow_main_wnd{};  //浮动播放列表跟随主窗口
373     bool playlist_btn_for_float_playlist{ false };      // 指定主界面中进度条右侧的“显示/隐藏播放列表”按钮的功能是否为显示浮动播放列表
374     int playlist_item_height{ 24 };
375     RecentPlayedRange recent_played_range{};	//最近播放曲目列表的显示范围
376     int display_item{};                 //媒体库显示的项目
377     bool write_id3_v2_3{ false };       //写入的ID3V2版本是否为2.3,否则为2.4
378     bool enable_lastfm { false };       ///是否启用Last.fm相关功能
379     int lastfm_least_perdur { 50 };     ///将记录写入缓存要求播放的百分比
380     int lastfm_least_dur { 60 };        ///将记录写入缓存要求播放的秒数
381     bool lastfm_auto_scrobble { true }; ///是否自动上传缓存里的记录
382     int lastfm_auto_scrobble_min { 1 }; ///自动上传缓存里的记录的下限
383     bool lastfm_enable_https { false }; ///是否使用HTTPS与last.fm服务器通信
384     bool lastfm_enable_nowplaying{ true }; ///是否上传当前播放歌曲
385 };
386 
387 struct NonCategorizedSettingData
388 {
389     int volum_step{ 3 };			//点击主界面中的音量调节时一次调整的步长
390     int mouse_volum_step{ 2 };		//通过鼠标滚轮调节音量时的步长
391     int volume_map{ 100 };			//音量映射(例如:如果将此值从100改为60,则当音量设置为最大(100%)时的音量大小为原来的60%)
392     bool show_cover_tip{ true };	//是否显示专辑封面上的鼠标提示
393     //wstring default_back_image_path{};	//没有专辑封面时的默认背景的路径
394     bool no_sf2_warning{ true };	//是否在没有MIDI音色库时弹出提示信息
395     bool show_hide_menu_bar_tip{ true };	//是隐藏菜单栏是否弹出提示信息
396     bool always_on_top{ false };	//是否总是置顶
397     wstring default_osu_img;
398 
399     bool float_playlist{ false };		//浮动播放列表(不应该用此变量来判断浮动播放列表是否存在)
400     CSize playlist_size{ 320, 530 };		//浮动播放列表的大小
401 
402     int max_album_cover_size{ 800 };
403     bool show_debug_info{ false };
404 
405     int light_mode_default_transparency{ 80 };
406     int dark_mode_default_transparency{ 40 };
407 
408     vector<wstring> default_file_type;
409     vector<wstring> user_defined_type_ffmpeg;   //FFMPEG内核时用户添加的文件格式扩展名
410 
411     enum eLogType
412     {
413         LT_NONE = 0,
414         LT_NORMAL = 1,
415         LT_ERROR = 2
416     };
417 
418     int debug_log{ 0 };     //是否写入日志信息
419 };
420 
421 
422 //界面相关的一些选项
423 struct UIData
424 {
425     bool narrow_mode;					//窄界面模式
426     bool show_playlist{ true };
427     bool show_menu_bar{ true };
428     bool full_screen{ false };
429 
430     int draw_area_width;                //绘图区的宽度
431     int draw_area_height;               //绘图区的高度
432     CImage default_background;			//默认的背景
433     CCriticalSection default_background_sync;
434 
435     bool ShowWindowMenuBar() const ;/* { return show_menu_bar && show_window_frame && !full_screen; }*/
436     bool ShowUiMenuBar() const;/* { return show_menu_bar && !show_window_frame && !full_screen; }*/
437 };
438 
439 
440 struct ImageSet
441 {
442     Gdiplus::Image* default_cover_img{};
443     Gdiplus::Image* default_cover_not_played_img{};
444     string default_cover_img_data;
445     string default_cover_not_played_img_data;
446 
~ImageSetImageSet447     ~ImageSet()
448     {
449         SAFE_DELETE(default_cover_img);
450         SAFE_DELETE(default_cover_not_played_img);
451     }
452 };
453 
454 //通过构造函数传递一个bool变量的引用,在构造时将其置为true,析构时置为false
455 class CFlagLocker
456 {
457 public:
CFlagLocker(bool & flag)458     CFlagLocker(bool& flag)
459         : m_flag(flag)
460     {
461         m_flag = true;
462     }
463 
~CFlagLocker()464     ~CFlagLocker()
465     {
466         m_flag = false;
467     }
468 
469 private:
470     bool& m_flag;
471 };
472 
473 
474 struct MediaUpdateThreadPara
475 {
476     int num_added{};                       //更新媒体库时新增(包括更新)的音频文件数量
477     int process_percent{};                  // 更新媒体库进度%
478     bool thread_exit{};             //如果为true,则线程应该退出
479     bool force;                     // 为true时无视修改时间强制刷新
480 };
481