xref: /MusicPlayer2/MusicPlayer2/FormatConvertDlg.cpp (revision b4360c210d93887ae47e27aca2e2f711b9b3d0f0)
1 // FormatConvertDlg.cpp: 实现文件
2 //
3 
4 #include "stdafx.h"
5 #include "MusicPlayer2.h"
6 #include "Player.h"
7 #include "FormatConvertDlg.h"
8 #include "BassCore.h"
9 #include "MusicPlayerCmdHelper.h"
10 #include "SongDataManager.h"
11 #include "FileNameFormDlg.h"
12 #include "MP3EncodeCfgDlg.h"
13 #include "WmaEncodeCfgDlg.h"
14 #include "OggEncodeCfgDlg.h"
15 #include "FlacEncodeCfgDlg.h"
16 #include "FilterHelper.h"
17 #include "IniHelper.h"
18 #include "TagEditDlg.h"
19 
20 #define MAX_ALBUM_COVER_SIZE (128 * 1024)                           //编码器支持的最大专辑封面大小
21 #define CONVERT_TEMP_ALBUM_COVER_NAME L"cover_R1hdyFy6CoEK7Gu8"     //临时的专辑封面文件名
22 #define COMPRESSED_ALBUM_COVER_PIXEL 512                            //要将专辑封面图片压缩的尺寸
23 
24 
GetCueDisplayFileName(const wstring & title,const wstring & artist)25 static wstring GetCueDisplayFileName(const wstring& title, const wstring& artist)
26 {
27     wstring str;
28     if (!artist.empty() && !title.empty())
29         str = artist + L" - " + title;
30     else
31         str = artist + title;
32     return str;
33 }
34 
35 //////////////////////////////////////////////////////////////////////////
36 
37 // CFormatConvertDlg 对话框
38 
IMPLEMENT_DYNAMIC(CFormatConvertDlg,CBaseDialog)39 IMPLEMENT_DYNAMIC(CFormatConvertDlg, CBaseDialog)
40 
41 CFormatConvertDlg::CFormatConvertDlg(CWnd* pParent /*=nullptr*/)
42     : CBaseDialog(IDD_FORMAT_CONVERT_DIALOG, pParent)
43 {
44 }
45 
CFormatConvertDlg(const vector<SongInfo> & items,CWnd * pParent)46 CFormatConvertDlg::CFormatConvertDlg(const vector<SongInfo>& items, CWnd* pParent /*=nullptr*/)
47     : CBaseDialog(IDD_FORMAT_CONVERT_DIALOG, pParent)
48 {
49     //获取文件列表
50     for (SongInfo item : items)
51     {
52         item.Normalize();
53         m_file_list.push_back(std::move(item));
54     }
55     // 确保音频文件信息更新到媒体库,并解析cue,(对于大量不存在于媒体库的新文件此方法很慢)
56     int cnt{}, percent{};
57     bool exit_flag{ false };
58     CAudioCommon::GetAudioInfo(m_file_list, cnt, exit_flag, percent, MR_MIN_REQUIRED, false);
59     // 去重
60     std::unordered_set<SongKey> song_key;
61     song_key.reserve(m_file_list.size());
62     auto new_end = std::remove_if(m_file_list.begin(), m_file_list.end(),
63         [&](const SongInfo& song) { return !song_key.emplace(song).second; }); // emplace失败说明此项目已存在,返回true移除当前项目
64     m_file_list.erase(new_end, m_file_list.end());
65     // 加载歌曲信息(与播放列表一致)
66     CSongDataManager::GetInstance().LoadSongsInfo(m_file_list);
67 
68     //如果文件是 MIDI 音乐,则把SF2音色库信息添加到注释信息
69     wstring midi_comment = L"Converted from MIDI by MusicPlayer2. SF2: " + CPlayer::GetInstance().GetSoundFontName();
70     for (auto& song : m_file_list)
71     {
72         if (CAudioCommon::GetAudioTypeByFileName(song.file_path) == AU_MIDI)
73             song.comment = midi_comment;
74     }
75 
76     m_freq_map.emplace_back(L"8 kHz", 8000);
77     m_freq_map.emplace_back(L"16 kHz", 16000);
78     m_freq_map.emplace_back(L"22 kHz", 22050);
79     m_freq_map.emplace_back(L"24 kHz", 24000);
80     m_freq_map.emplace_back(L"32 kHz", 32000);
81     m_freq_map.emplace_back(L"44.1 kHz", 44100);
82     m_freq_map.emplace_back(L"48 kHz", 48000);
83 }
84 
~CFormatConvertDlg()85 CFormatConvertDlg::~CFormatConvertDlg()
86 {
87     CPlayer::GetInstance().GetPlayerCore()->UnInitEncoder();
88 }
89 
GetDialogName() const90 CString CFormatConvertDlg::GetDialogName() const
91 {
92     return _T("FormatConvertDlg");
93 
94 }
95 
InitializeControls()96 bool CFormatConvertDlg::InitializeControls()
97 {
98     wstring temp;
99     temp = theApp.m_str_table.LoadText(L"TITLE_FORMAT_CONVERT");
100     SetWindowTextW(temp.c_str());
101     temp = theApp.m_str_table.LoadText(L"TXT_FORMAT_CONVERT_OUT_FORMAT_SEL");
102     SetDlgItemTextW(IDC_TXT_FORMAT_CONVERT_OUT_FORMAT_SEL_STATIC, temp.c_str());
103     // IDC_OUT_FORMAT_COMBO
104     temp = theApp.m_str_table.LoadText(L"TXT_FORMAT_CONVERT_SETTING");
105     SetDlgItemTextW(IDC_ENCODER_CONFIG_BUTTON, temp.c_str());
106     temp = theApp.m_str_table.LoadText(L"TXT_FORMAT_CONVERT_FILE_LIST");
107     SetDlgItemTextW(IDC_TXT_FORMAT_CONVERT_FILE_LIST_STATIC, temp.c_str());
108     // IDC_SONG_LIST1
109     temp = theApp.m_str_table.LoadText(L"TXT_FORMAT_CONVERT_OPT");
110     SetDlgItemTextW(IDC_TXT_FORMAT_CONVERT_OPT_STATIC, temp.c_str());
111     temp = theApp.m_str_table.LoadText(L"TXT_FORMAT_CONVERT_CHANGE_FREQ");
112     SetDlgItemTextW(IDC_CHANGE_FREQ_CHECK, temp.c_str());
113     // IDC_FREQ_COMBO
114     temp = theApp.m_str_table.LoadText(L"TXT_FORMAT_CONVERT_COPY_TAG");
115     SetDlgItemTextW(IDC_COPY_TAG_CHECK, temp.c_str());
116     temp = theApp.m_str_table.LoadText(L"TXT_FORMAT_CONVERT_COPY_COVER");
117     SetDlgItemTextW(IDC_COPY_ALBUM_COVER_CHECK, temp.c_str());
118     temp = theApp.m_str_table.LoadText(L"TXT_FORMAT_CONVERT_OUT_FILE_NAME");
119     SetDlgItemTextW(IDC_TXT_FORMAT_CONVERT_OUT_FILE_NAME_STATIC, temp.c_str());
120     // IDC_OUT_NAME_EDIT
121     temp = theApp.m_str_table.LoadText(L"TXT_FORMAT_CONVERT_ADD_SERIAL_NUMBER");
122     SetDlgItemTextW(IDC_ADD_NUMBER_CHECK, temp.c_str());
123     temp = theApp.m_str_table.LoadText(L"TXT_FORMAT_CONVERT_FILE_EXIST_SEL");
124     SetDlgItemTextW(IDC_TXT_FORMAT_CONVERT_FILE_EXIST_SEL_STATIC, temp.c_str());
125     // IDC_TARGET_FILE_EXIST_COMBO
126     temp = theApp.m_str_table.LoadText(L"TXT_FORMAT_CONVERT_OUT_DIR");
127     SetDlgItemTextW(IDC_TXT_FORMAT_CONVERT_OUT_DIR_STATIC, temp.c_str());
128     // IDC_OUT_DIR_EDIT
129     temp = theApp.m_str_table.LoadText(L"TXT_FORMAT_CONVERT_OUT_DIR_OPEN_WHEN_COMPLETE");
130     SetDlgItemTextW(IDC_OPEN_TARGET_DIR_CHECK, temp.c_str());
131     temp = L"";
132     SetDlgItemTextW(IDC_PROGRESS_BAR, temp.c_str());    // 此控件持有的文本会影响接下来的重排,需要先清空
133     SetDlgItemTextW(IDC_PROGRESS_TEXT, temp.c_str());
134     temp = theApp.m_str_table.LoadText(L"TXT_FORMAT_CONVERT_START_CONVERT");
135     SetDlgItemTextW(IDC_START_CONVERT_BUTTON, temp.c_str());
136     // IDCANCEL
137 
138     RepositionTextBasedControls({
139         { CtrlTextInfo::L1, IDC_TXT_FORMAT_CONVERT_OUT_FORMAT_SEL_STATIC },
140         { CtrlTextInfo::C0, IDC_OUT_FORMAT_COMBO },
141         { CtrlTextInfo::R1, IDC_ENCODER_CONFIG_BUTTON, CtrlTextInfo::W32 }
142         }, CtrlTextInfo::W128);
143     RepositionTextBasedControls({
144         { CtrlTextInfo::L2, IDC_CHANGE_FREQ_CHECK, CtrlTextInfo::W32 },
145         { CtrlTextInfo::L1, IDC_FREQ_COMBO }
146         });
147     RepositionTextBasedControls({
148         { CtrlTextInfo::L1, IDC_TXT_FORMAT_CONVERT_OUT_FILE_NAME_STATIC },
149         { CtrlTextInfo::C0, IDC_OUT_NAME_EDIT },
150         { CtrlTextInfo::L1, IDC_TXT_FORMAT_CONVERT_OUT_DIR_STATIC },
151         { CtrlTextInfo::C0, IDC_OUT_DIR_EDIT }
152         }, CtrlTextInfo::W128);
153     RepositionTextBasedControls({
154         { CtrlTextInfo::L1, IDC_PROGRESS_BAR },
155         { CtrlTextInfo::C0, IDC_PROGRESS_TEXT },
156         { CtrlTextInfo::R1, IDC_START_CONVERT_BUTTON, CtrlTextInfo::W32 },
157         { CtrlTextInfo::R2, IDCANCEL, CtrlTextInfo::W32 }
158         }, CtrlTextInfo::W128);
159     return true;
160 }
161 
DoDataExchange(CDataExchange * pDX)162 void CFormatConvertDlg::DoDataExchange(CDataExchange* pDX)
163 {
164     CBaseDialog::DoDataExchange(pDX);
165     DDX_Control(pDX, IDC_SONG_LIST1, m_file_list_ctrl);
166     DDX_Control(pDX, IDC_OUT_FORMAT_COMBO, m_encode_format_combo);
167     DDX_Control(pDX, IDC_PROGRESS_BAR, m_progress_bar);
168     DDX_Control(pDX, IDC_FREQ_COMBO, m_freq_comb);
169     DDX_Control(pDX, IDC_OUT_DIR_EDIT, m_out_dir_edit);
170     DDX_Control(pDX, IDC_OUT_NAME_EDIT, m_out_name_edit);
171 }
172 
LoadConfig()173 void CFormatConvertDlg::LoadConfig()
174 {
175     CIniHelper ini(theApp.m_config_path);
176     m_encode_format = static_cast<EncodeFormat>(ini.GetInt(L"format_convert", L"encode_format", 1));
177     m_write_tag = ini.GetBool(L"format_convert", L"write_tag", true);
178     m_write_album_cover = ini.GetBool(L"format_convert", L"write_album_cover", true);
179     m_file_exist_action = ini.GetInt(L"format_convert", L"file_exist_action", 0);
180     m_add_file_serial_num = ini.GetBool(L"format_convert", L"add_file_serial_num", false);
181     m_out_dir = ini.GetString(L"format_convert", L"out_dir", L"");
182     if (!CCommon::FolderExist(m_out_dir))		//如果读取到的目录不存在,则设置为“我的文档”目录
183     {
184         m_out_dir = CCommon::GetSpecialDir(CSIDL_MYDOCUMENTS);
185     }
186     m_out_name = ini.GetString(L"format_convert", L"out_name_formular", CFileNameFormDlg::FORMULAR_ORIGINAL.c_str());
187     m_convert_freq = ini.GetBool(L"format_convert", L"convert_freq", false);
188     m_freq_sel = ini.GetString(L"format_convert", L"freq_sel", L"");
189     m_open_output_dir = ini.GetBool(L"format_convert", L"open_output_dir", false);
190 }
191 
SaveConfig() const192 void CFormatConvertDlg::SaveConfig() const
193 {
194     CIniHelper ini(theApp.m_config_path);
195     ini.WriteInt(L"format_convert", L"encode_format", static_cast<int>(m_encode_format));
196     ini.WriteBool(L"format_convert", L"write_tag", m_write_tag);
197     ini.WriteBool(L"format_convert", L"write_album_cover", m_write_album_cover);
198     ini.WriteInt(L"format_convert", L"file_exist_action", m_file_exist_action);
199     ini.WriteBool(L"format_convert", L"add_file_serial_num", m_add_file_serial_num);
200     ini.WriteString(L"format_convert", L"out_dir", m_out_dir);
201     ini.WriteString(L"format_convert", L"out_name_formular", m_out_name);
202     ini.WriteBool(L"format_convert", L"convert_freq", m_convert_freq);
203     ini.WriteString(L"format_convert", L"freq_sel", m_freq_sel);
204     ini.WriteBool(L"format_convert", L"open_output_dir", m_open_output_dir);
205     ini.Save();
206 }
207 
LoadEncoderConfig()208 void CFormatConvertDlg::LoadEncoderConfig()
209 {
210     CIniHelper ini(theApp.m_config_dir + L"Encoder\\encoder.ini");
211 
212     m_mp3_encode_para.encode_type = ini.GetInt(L"mp3_encoder", L"encode_type", 0);
213     m_mp3_encode_para.cbr_bitrate = ini.GetInt(L"mp3_encoder", L"cbr_bitrate", 128);
214     m_mp3_encode_para.abr_bitrate = ini.GetInt(L"mp3_encoder", L"abr_bitrate", 128);
215     m_mp3_encode_para.vbr_quality = ini.GetInt(L"mp3_encoder", L"vbr_quality", 4);
216     m_mp3_encode_para.cmd_para = ini.GetString(L"mp3_encoder", L"cmd_para", L"");
217     m_mp3_encode_para.joint_stereo = ini.GetBool(L"mp3_encoder", L"joint_stereo", true);
218     if (m_mp3_encode_para.encode_type == 3)    // 旧版兼容
219     {
220         m_mp3_encode_para.encode_type = 0;
221         m_mp3_encode_para.cmd_para.clear();
222     }
223     if (!m_mp3_encode_para.cmd_para.empty())
224     {
225         m_mp3_encode_para.user_define_para = true;
226     }
227     CMP3EncodeCfgDlg::EncodeParaToCmdline(m_mp3_encode_para);
228 
229     m_wma_encode_para.cbr = ini.GetBool(L"wma_encoder", L"cbr", true);
230     m_wma_encode_para.cbr_bitrate = ini.GetInt(L"wma_encoder", L"cbr_bitrate", 64);
231     m_wma_encode_para.vbr_quality = ini.GetInt(L"wma_encoder", L"vbr_quality", 75);
232 
233     m_ogg_encode_para.encode_quality = ini.GetInt(L"ogg_encoder", L"quality", 4);
234 
235     m_flac_encode_para.compression_level = ini.GetInt(L"flac_encoder", L"compression_level", 8);
236     m_flac_encode_para.user_define_para = ini.GetBool(L"flac_encoder", L"user_define_para", false);
237     m_flac_encode_para.cmd_para = ini.GetString(L"flac_encoder", L"cmd_para", L"");
238 }
239 
SaveEncoderConfig() const240 void CFormatConvertDlg::SaveEncoderConfig() const
241 {
242     std::wstring encoder_dir = theApp.m_config_dir + L"Encoder\\";
243     CCommon::CreateDir(encoder_dir);
244     CIniHelper ini(encoder_dir + L"encoder.ini");
245 
246     ini.WriteInt(L"mp3_encoder", L"encode_type", m_mp3_encode_para.encode_type);
247     ini.WriteInt(L"mp3_encoder", L"cbr_bitrate", m_mp3_encode_para.cbr_bitrate);
248     ini.WriteInt(L"mp3_encoder", L"abr_bitrate", m_mp3_encode_para.abr_bitrate);
249     ini.WriteInt(L"mp3_encoder", L"vbr_quality", m_mp3_encode_para.vbr_quality);
250     ini.WriteString(L"mp3_encoder", L"cmd_para", m_mp3_encode_para.user_define_para ? m_mp3_encode_para.cmd_para : L"");
251     ini.WriteBool(L"mp3_encoder", L"joint_stereo", m_mp3_encode_para.joint_stereo);
252 
253     ini.WriteBool(L"wma_encoder", L"cbr", m_wma_encode_para.cbr);
254     ini.WriteInt(L"wma_encoder", L"cbr_bitrate", m_wma_encode_para.cbr_bitrate);
255     ini.WriteInt(L"wma_encoder", L"vbr_quality", m_wma_encode_para.vbr_quality);
256 
257     ini.WriteInt(L"ogg_encoder", L"quality", m_ogg_encode_para.encode_quality);
258 
259     ini.WriteInt(L"flac_encoder", L"compression_level", m_flac_encode_para.compression_level);
260     ini.WriteBool(L"flac_encoder", L"user_define_para", m_flac_encode_para.user_define_para);
261     ini.WriteString(L"flac_encoder", L"cmd_para", m_flac_encode_para.cmd_para);
262 
263     ini.Save();
264 }
265 
266 
BEGIN_MESSAGE_MAP(CFormatConvertDlg,CBaseDialog)267 BEGIN_MESSAGE_MAP(CFormatConvertDlg, CBaseDialog)
268     ON_CBN_SELCHANGE(IDC_OUT_FORMAT_COMBO, &CFormatConvertDlg::OnCbnSelchangeOutFormatCombo)
269     ON_BN_CLICKED(IDC_START_CONVERT_BUTTON, &CFormatConvertDlg::OnBnClickedStartConvertButton)
270     //ON_BN_CLICKED(IDC_BROWSE_BUTTON, &CFormatConvertDlg::OnBnClickedBrowseButton)
271     ON_MESSAGE(WM_CONVERT_PROGRESS, &CFormatConvertDlg::OnConvertProgress)
272     ON_MESSAGE(WM_CONVERT_COMPLETE, &CFormatConvertDlg::OnConvertComplete)
273     ON_WM_CLOSE()
274     ON_BN_CLICKED(IDC_ENCODER_CONFIG_BUTTON, &CFormatConvertDlg::OnBnClickedEncoderConfigButton)
275     ON_WM_GETMINMAXINFO()
276     ON_BN_CLICKED(IDC_COPY_TAG_CHECK, &CFormatConvertDlg::OnBnClickedCopyTagCheck)
277     ON_BN_CLICKED(IDC_COPY_ALBUM_COVER_CHECK, &CFormatConvertDlg::OnBnClickedCopyAlbumCoverCheck)
278     ON_CBN_SELCHANGE(IDC_TARGET_FILE_EXIST_COMBO, &CFormatConvertDlg::OnCbnSelchangeTargetFileExistCombo)
279     ON_BN_CLICKED(IDC_ADD_NUMBER_CHECK, &CFormatConvertDlg::OnBnClickedAddNumberCheck)
280     ON_NOTIFY(NM_RCLICK, IDC_SONG_LIST1, &CFormatConvertDlg::OnNMRClickSongList1)
281     ON_COMMAND(ID_ADD_FILE, &CFormatConvertDlg::OnAddFile)
282     ON_COMMAND(ID_DELETE_SELECT, &CFormatConvertDlg::OnDeleteSelect)
283     ON_COMMAND(ID_CLEAR_LIST, &CFormatConvertDlg::OnClearList)
284     ON_COMMAND(ID_MOVE_UP, &CFormatConvertDlg::OnMoveUp)
285     ON_COMMAND(ID_MOVE_DOWN, &CFormatConvertDlg::OnMoveDown)
286     ON_COMMAND(ID_EDIT_TAG_INFO, &CFormatConvertDlg::OnEditTagInfo)
287     ON_WM_INITMENU()
288     ON_NOTIFY(NM_DBLCLK, IDC_SONG_LIST1, &CFormatConvertDlg::OnNMDblclkSongList1)
289     ON_BN_CLICKED(IDC_CHANGE_FREQ_CHECK, &CFormatConvertDlg::OnBnClickedChangeFreqCheck)
290     ON_CBN_SELCHANGE(IDC_FREQ_COMBO, &CFormatConvertDlg::OnCbnSelchangeFreqCombo)
291     ON_MESSAGE(WM_EDIT_BROWSE_CHANGED, &CFormatConvertDlg::OnEditBrowseChanged)
292     ON_BN_CLICKED(IDC_OPEN_TARGET_DIR_CHECK, &CFormatConvertDlg::OnBnClickedOpenTargetDirCheck)
293 END_MESSAGE_MAP()
294 
295 
296 // CFormatConvertDlg 消息处理程序
297 
298 
299 BOOL CFormatConvertDlg::OnInitDialog()
300 {
301     CBaseDialog::OnInitDialog();
302 
303     // TODO:  在此添加额外的初始化
304     CenterWindow();
305 
306     SetIcon(IconMgr::IconType::IT_Convert, FALSE);
307     SetIcon(IconMgr::IconType::IT_Convert, TRUE);
308     SetButtonIcon(IDC_ENCODER_CONFIG_BUTTON, IconMgr::IconType::IT_Setting);
309     SetButtonIcon(IDC_START_CONVERT_BUTTON, IconMgr::IconType::IT_Convert);
310 
311     LoadConfig();
312     LoadEncoderConfig();
313 
314     m_encoder_succeed = InitEncoder();
315     if (!CPlayer::GetInstance().GetPlayerCore()->IsFreqConvertAvailable())
316         m_convert_freq = false;
317 
318     //初始化文件列表
319     CRect rect;
320     m_file_list_ctrl.GetWindowRect(rect);
321     int width0{ theApp.DPI(40) }, width1, width2{ theApp.DPI(65) };
322     width1 = rect.Width() - width0 - width2 - theApp.DPI(20) - 1;
323     //插入列
324     m_file_list_ctrl.SetExtendedStyle(m_file_list_ctrl.GetExtendedStyle() | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_LABELTIP);
325     m_file_list_ctrl.InsertColumn(0, theApp.m_str_table.LoadText(L"TXT_SERIAL_NUMBER").c_str(), LVCFMT_LEFT, width0);
326     m_file_list_ctrl.InsertColumn(1, theApp.m_str_table.LoadText(L"TXT_FILE_NAME").c_str(), LVCFMT_LEFT, width1);
327     m_file_list_ctrl.InsertColumn(2, theApp.m_str_table.LoadText(L"TXT_FORMAT_CONVERT_STAUS").c_str(), LVCFMT_LEFT, width2);
328     //插入项目
329     ShowFileList();
330     //设置主题颜色
331     //m_file_list_ctrl.SetColor(theApp.m_app_setting_data.theme_color);
332 
333     //初始化转换格式的下拉列表
334     m_encode_format_combo.AddString(_T("WAV"));
335     m_encode_format_combo.AddString(theApp.m_str_table.LoadText(L"TXT_FORMAT_CONVERT_ENCODER_NAME_MP3_LAME").c_str());
336     m_encode_format_combo.AddString(_T("WMA"));
337     m_encode_format_combo.AddString(_T("OGG"));
338     m_encode_format_combo.AddString(_T("FLAC"));
339     m_encode_format_combo.SetCurSel(static_cast<int>(m_encode_format));
340 
341     //初始化选项控件的状态
342     ((CButton*)GetDlgItem(IDC_COPY_TAG_CHECK))->SetCheck(m_write_tag);
343     ((CButton*)GetDlgItem(IDC_COPY_ALBUM_COVER_CHECK))->SetCheck(m_write_album_cover);
344     ((CButton*)GetDlgItem(IDC_ADD_NUMBER_CHECK))->SetCheck(m_add_file_serial_num);
345     CComboBox* file_exist_combo = (CComboBox*)GetDlgItem(IDC_TARGET_FILE_EXIST_COMBO);
346     file_exist_combo->AddString(theApp.m_str_table.LoadText(L"TXT_FORMAT_CONVERT_FILE_EXIST_AUTO_RENAME").c_str());
347     file_exist_combo->AddString(theApp.m_str_table.LoadText(L"TXT_FORMAT_CONVERT_FILE_EXIST_IGNORE").c_str());
348     file_exist_combo->AddString(theApp.m_str_table.LoadText(L"TXT_FORMAT_CONVERT_FILE_EXIST_OVERWRITE").c_str());
349     file_exist_combo->SetCurSel(m_file_exist_action);
350     ((CButton*)GetDlgItem(IDC_OPEN_TARGET_DIR_CHECK))->SetCheck(m_open_output_dir);
351 
352     int freq_comb_sel{ -1 };
353     for (size_t i{}; i < m_freq_map.size(); ++i)
354     {
355         m_freq_comb.AddString(m_freq_map[i].first.c_str());
356         if (m_freq_map[i].first == m_freq_sel)
357             freq_comb_sel = i;
358         if (m_freq_map[i].second == 44100)          // 默认值
359             m_freq_comb.SetCurSel(i);
360     }
361     if (freq_comb_sel != -1)
362         m_freq_comb.SetCurSel(freq_comb_sel);
363     m_freq_comb.EnableWindow(m_convert_freq);
364     ((CButton*)GetDlgItem(IDC_CHANGE_FREQ_CHECK))->SetCheck(m_convert_freq);
365 
366     m_out_name_edit.SetWindowText(m_out_name.c_str());
367     m_out_name_edit.SetEditBrowseMode(CBrowseEdit::EditBrowseMode::RENAME);
368 
369     if (!m_out_dir.empty() && m_out_dir.back() != L'\\')
370         m_out_dir.push_back(L'\\');
371     m_out_dir_edit.SetWindowText(m_out_dir.c_str());
372     m_out_dir_edit.EnableFolderBrowseButton(theApp.m_str_table.LoadText(L"TITLE_FOLDER_BROWSER_OUTPUT_FOLDER").c_str());
373     m_progress_bar.SetBackgroundColor(GetSysColor(COLOR_BTNFACE));
374     m_progress_bar.ShowWindow(SW_HIDE);
375 
376     SetEncodeConfigBtnState();
377 
378     //#ifndef COMPILE_IN_WIN_XP
379     //	if (CWinVersionHelper::IsWindows7OrLater())
380     //		CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_pTaskbar));	//创建ITaskbarList3的实例
381     //#endif
382 
383     return TRUE;  // return TRUE unless you set the focus to a control
384                   // 异常: OCX 属性页应返回 FALSE
385 }
386 
387 
EnableControls(bool enable)388 void CFormatConvertDlg::EnableControls(bool enable)
389 {
390     GetDlgItem(IDC_OUT_FORMAT_COMBO)->EnableWindow(enable);
391     GetDlgItem(IDC_START_CONVERT_BUTTON)->EnableWindow(enable);
392     GetDlgItem(IDC_ENCODER_CONFIG_BUTTON)->EnableWindow(enable);
393     GetDlgItem(IDC_COPY_TAG_CHECK)->EnableWindow(enable);
394     GetDlgItem(IDC_TARGET_FILE_EXIST_COMBO)->EnableWindow(enable);
395     GetDlgItem(IDC_COPY_ALBUM_COVER_CHECK)->EnableWindow(enable);
396     GetDlgItem(IDC_ADD_NUMBER_CHECK)->EnableWindow(enable);
397     GetDlgItem(IDC_CHANGE_FREQ_CHECK)->EnableWindow(enable);
398     m_freq_comb.EnableWindow(enable && m_convert_freq);
399     GetDlgItem(IDC_OUT_DIR_EDIT)->EnableWindow(enable);
400     GetDlgItem(IDC_OUT_NAME_EDIT)->EnableWindow(enable);
401 }
402 
SetEncodeConfigBtnState()403 void CFormatConvertDlg::SetEncodeConfigBtnState()
404 {
405     GetDlgItem(IDC_ENCODER_CONFIG_BUTTON)->EnableWindow(m_encode_format != EncodeFormat::WAV);
406 }
407 
ShowFileList()408 void CFormatConvertDlg::ShowFileList()
409 {
410     m_file_list_ctrl.DeleteAllItems();
411     for (size_t i{}; i < m_file_list.size(); i++)
412     {
413         CString tmp;
414         tmp.Format(_T("%d"), i + 1);
415         m_file_list_ctrl.InsertItem(i, tmp);
416         if (!m_file_list[i].is_cue)
417         {
418             CFilePathHelper file_path(m_file_list[i].file_path);
419             m_file_list_ctrl.SetItemText(i, 1, file_path.GetFileName().c_str());
420         }
421         else
422         {
423             m_file_list_ctrl.SetItemText(i, 1, GetCueDisplayFileName(m_file_list[i].title, m_file_list[i].artist).c_str());
424         }
425     }
426 }
427 
InitEncoder()428 bool CFormatConvertDlg::InitEncoder()
429 {
430     return CPlayer::GetInstance().GetPlayerCore()->InitEncoder();
431 }
432 
EncodeSingleFile(CFormatConvertDlg * pthis,int file_index)433 bool CFormatConvertDlg::EncodeSingleFile(CFormatConvertDlg* pthis, int file_index)
434 {
435     //设置输出文件路径
436     SongInfo& song_info{ pthis->m_file_list[file_index] };
437 
438     // 输出文件路径
439     wstring out_file_path{ pthis->m_out_dir };
440 
441     // 为目标文件添加序号
442     if (pthis->m_add_file_serial_num)
443     {
444         CString index_str;
445         if (pthis->m_file_list.size() < 10)
446             index_str.Format(_T("%d."), file_index + 1);
447         else if (pthis->m_file_list.size() < 100)
448             index_str.Format(_T("%02d."), file_index + 1);
449         else
450             index_str.Format(_T("%03d."), file_index + 1);
451         out_file_path += index_str;
452     }
453 
454     // 按照格式字符串生成输出文件名(这里缺少长度检查)
455     out_file_path += CFileNameFormDlg::FileNameFromTag(pthis->m_out_name, song_info);
456 
457     // 按照输出格式添加后缀
458     switch (pthis->m_encode_format)
459     {
460     case EncodeFormat::WAV:
461         out_file_path += L".wav";
462         break;
463     case EncodeFormat::MP3:
464         out_file_path += L".mp3";
465         break;
466     case EncodeFormat::WMA:
467         out_file_path += L".wma";
468         break;
469     case EncodeFormat::OGG:
470         out_file_path += L".ogg";
471         break;
472     case EncodeFormat::FLAC:
473         out_file_path += L".flac";
474         break;
475     }
476 
477     //判断目标文件是否存在
478     if (pthis->m_file_exist_action == 0)		//如果设置了“目标文件存在时自动重命名”,自动在文件名后面添加形如“ (数字)”的编号
479     {
480         CCommon::FileAutoRename(out_file_path);
481     }
482     else if (pthis->m_file_exist_action == 1)		//如果设置了“目标文件存在时忽略”
483     {
484         if (CCommon::FileExist(out_file_path))
485         {
486             ::PostMessage(pthis->GetSafeHwnd(), WM_CONVERT_PROGRESS, file_index, 102);
487             return false;
488         }
489     }
490 
491     void* para{};
492     switch (pthis->m_encode_format)
493     {
494     case EncodeFormat::MP3:
495         para = &pthis->m_mp3_encode_para;
496         break;
497     case EncodeFormat::WMA:
498         para = &pthis->m_wma_encode_para;
499         break;
500     case EncodeFormat::OGG:
501         para = &pthis->m_ogg_encode_para;
502         break;
503     case EncodeFormat::FLAC:
504         para = &pthis->m_flac_encode_para;
505     default:
506         break;
507 
508     }
509 
510     int freq{};
511     if (CPlayer::GetInstance().GetPlayerCore()->IsFreqConvertAvailable() && pthis->m_convert_freq)
512         freq = pthis->GetFreq();
513 
514     static int _file_index{};
515     _file_index = file_index;
516     static CFormatConvertDlg* _pthis{};
517     _pthis = pthis;
518     //执行转换格式
519     if (!CPlayer::GetInstance().GetPlayerCore()->EncodeAudio(song_info, out_file_path, pthis->m_encode_format, para, freq, [](int progress)
520         {
521             ::PostMessage(_pthis->GetSafeHwnd(), WM_CONVERT_PROGRESS, _file_index, progress);
522         }))
523         return false;
524 
525     //转换完成后向目标文件写入标签信息和专辑封面
526     SongInfo song_info_out{ song_info };
527     song_info_out.file_path = out_file_path;
528     song_info_out.is_cue = false;
529     //写入标签信息
530     if (pthis->m_write_tag)
531     {
532         CAudioTag audio_tag_out(song_info_out);
533         audio_tag_out.WriteAudioTag();
534     }
535     //写入专辑封面
536     if (pthis->m_write_album_cover)
537     {
538         //获取原始文件的专辑封面
539         SongInfo song_info_tmp;
540         song_info_tmp.file_path = song_info.file_path;
541         CAudioTag audio_tag(song_info_tmp);
542         int cover_type;
543         wstring album_cover_path = audio_tag.GetAlbumCover(cover_type, ALBUM_COVER_NAME_ENCODE);
544         CImage image;
545         image.Load(album_cover_path.c_str());
546         if (image.IsNull())		//如果没有内嵌的专辑封面,则获取外部封面
547         {
548             CMusicPlayerCmdHelper helper;
549             album_cover_path = helper.SearchAlbumCover(song_info);
550         }
551         else
552             image.Destroy();
553         //将专辑封面写入目标文件
554         if (!album_cover_path.empty())
555         {
556             CAudioTag audio_tag_out(song_info_out);
557             audio_tag_out.WriteAlbumCover(album_cover_path);
558         }
559     }
560 
561     return true;
562 }
563 
564 
SetProgressInfo(int progress)565 void CFormatConvertDlg::SetProgressInfo(int progress)
566 {
567     wstring info;
568     if (progress >= 100)
569         info = theApp.m_str_table.LoadText(L"TXT_FORMAT_CONVERT_PROGRESS_INFO_COMPLETE");
570     else
571         info = theApp.m_str_table.LoadTextFormat(L"TXT_FORMAT_CONVERT_PROGRESS_INFO", { progress });
572     SetDlgItemText(IDC_PROGRESS_TEXT, info.c_str());
573 }
574 
GetFreq()575 int CFormatConvertDlg::GetFreq()
576 {
577     int sel_index = m_freq_comb.GetCurSel();
578     return m_freq_map[sel_index].second;
579 }
580 
ThreadFunc(LPVOID lpParam)581 UINT CFormatConvertDlg::ThreadFunc(LPVOID lpParam)
582 {
583     CCommon::SetThreadLanguageList(theApp.m_str_table.GetLanguageTag());
584     CFormatConvertDlg* pThis{ (CFormatConvertDlg*)lpParam };
585     for (size_t i{}; i < pThis->m_file_list.size(); i++)
586     {
587         if (theApp.m_format_convert_dialog_exit)
588             return 0;
589         //编码文件
590         if (EncodeSingleFile(pThis, i))
591             ::PostMessage(pThis->GetSafeHwnd(), WM_CONVERT_PROGRESS, i, 101);
592     }
593     ::PostMessage(pThis->GetSafeHwnd(), WM_CONVERT_COMPLETE, 0, 0);
594     return 0;
595 }
596 
597 
OnCbnSelchangeOutFormatCombo()598 void CFormatConvertDlg::OnCbnSelchangeOutFormatCombo()
599 {
600     // TODO: 在此添加控件通知处理程序代码
601     m_encode_format = static_cast<EncodeFormat>(m_encode_format_combo.GetCurSel());
602     SetEncodeConfigBtnState();
603 }
604 
605 
OnBnClickedStartConvertButton()606 void CFormatConvertDlg::OnBnClickedStartConvertButton()
607 {
608     // TODO: 在此添加控件通知处理程序代码
609     m_progress_bar.ShowWindow(SW_SHOW);
610     m_progress_bar.SetProgress(0);
611     SetProgressInfo(0);
612     if (!m_encoder_succeed)
613     {
614         CBassCore* bass_core = dynamic_cast<CBassCore*>(CPlayer::GetInstance().GetPlayerCore());
615         wstring info;
616         if (bass_core != nullptr)
617             info = theApp.m_str_table.LoadTextFormat(L"MSG_FORMAT_CONVERT_BASS_LOAD_ERROR", { bass_core->GetEncoderDir() + L"bassenc.dll" });
618         else
619             info = theApp.m_str_table.LoadText(L"MSG_FORMAT_CONVERT_INIT_ERROR");
620         MessageBox(info.c_str(), NULL, MB_ICONERROR | MB_OK);
621         return;
622     }
623 
624     if (m_out_dir.empty())
625     {
626         const wstring& info = theApp.m_str_table.LoadText(L"MSG_FORMAT_CONVERT_SET_OUTPUT_DIR");
627         MessageBox(info.c_str(), NULL, MB_ICONWARNING | MB_OK);
628         return;
629     }
630     else if (!CCommon::FolderExist(m_out_dir))
631     {
632         wstring info = theApp.m_str_table.LoadTextFormat(L"MSG_FORMAT_CONVERT_OUTPUT_DIR_NOT_EXIST", { m_out_dir });
633         MessageBox(info.c_str(), NULL, MB_ICONWARNING | MB_OK);
634     }
635 
636     //先清除“状态”一列的内容
637     for (size_t i{}; i < m_file_list.size(); i++)
638     {
639         m_file_list_ctrl.SetItemText(i, 2, _T(""));
640     }
641 
642     EnableControls(false);
643     theApp.m_format_convert_dialog_exit = false;
644     //创建格式转换的工作线程
645     m_pThread = AfxBeginThread(ThreadFunc, this);
646     m_thread_runing = true;
647     if (theApp.IsTaskbarInteractionEnabled())
648         theApp.GetITaskbarList3()->SetProgressState(this->GetSafeHwnd(), TBPF_INDETERMINATE);
649 }
650 
651 
OnConvertProgress(WPARAM wParam,LPARAM lParam)652 afx_msg LRESULT CFormatConvertDlg::OnConvertProgress(WPARAM wParam, LPARAM lParam)
653 {
654     wstring status_str;
655     int percent = (int)lParam;
656     if (percent == 0)
657         m_file_list_ctrl.EnsureVisible(wParam, FALSE);		//转换开始时,确保当前列表项可见
658     if (percent < 0)
659     {
660         //显示错误信息
661         if (percent == CONVERT_ERROR_FILE_CANNOT_OPEN)
662             status_str = theApp.m_str_table.LoadText(L"TXT_FORMAT_CONVERT_STAUS_ERROR_FILE_CANNOT_OPEN");
663         else if (percent == CONVERT_ERROR_ENCODE_CHANNEL_FAILED)
664             status_str = theApp.m_str_table.LoadText(L"TXT_FORMAT_CONVERT_STAUS_ERROR_ENCODE_CHANNEL_FAILED");
665         else if (percent == CONVERT_ERROR_ENCODE_PARA_ERROR)
666             status_str = theApp.m_str_table.LoadText(L"TXT_FORMAT_CONVERT_STAUS_ERROR_ENCODE_PARA_ERROR");
667         else if (percent == CONVERT_ERROR_MIDI_NO_SF2)
668             status_str = theApp.m_str_table.LoadText(L"TXT_FORMAT_CONVERT_STAUS_ERROR_MIDI_NO_SF2");
669         else if (percent == CONVERT_ERROR_WMA_NO_WMP9_OR_LATER)
670             status_str = theApp.m_str_table.LoadText(L"TXT_FORMAT_CONVERT_STAUS_ERROR_NO_WMP9_OR_LATER");
671         else if (percent == CONVERT_ERROR_WMA_NO_SUPPORTED_ENCODER)
672             status_str = theApp.m_str_table.LoadText(L"TXT_FORMAT_CONVERT_STAUS_ERROR_NO_SUPPORTED_ENCODER");
673         else
674             status_str = theApp.m_str_table.LoadTextFormat(L"TXT_FORMAT_CONVERT_STAUS_ERROR_OTHER", { percent });
675     }
676     else if (percent == 101)
677     {
678         status_str = theApp.m_str_table.LoadText(L"TXT_FORMAT_CONVERT_STAUS_COMPLETE");
679     }
680     else if (percent == 102)
681     {
682         status_str = theApp.m_str_table.LoadText(L"TXT_FORMAT_CONVERT_STAUS_SKIPPED");
683     }
684     else
685     {
686         status_str = std::to_wstring(static_cast<int>(lParam)) + L'%';
687     }
688     m_file_list_ctrl.SetItemText(wParam, 2, status_str.c_str());
689 
690     //总体的进度
691     int position, length;
692     length = m_file_list.size() * 100;
693     position = wParam * 100 + percent;
694     if (theApp.IsTaskbarInteractionEnabled())
695         theApp.GetITaskbarList3()->SetProgressValue(this->GetSafeHwnd(), position, length);
696     int total_percent = position * 100 / length;
697     static int last_percent = -1;
698     if (last_percent != total_percent)
699     {
700         m_progress_bar.SetProgress(total_percent);
701         SetProgressInfo(total_percent);
702         last_percent = total_percent;
703     }
704 
705     return 0;
706 }
707 
708 
OnConvertComplete(WPARAM wParam,LPARAM lParam)709 afx_msg LRESULT CFormatConvertDlg::OnConvertComplete(WPARAM wParam, LPARAM lParam)
710 {
711     EnableControls(true);
712     m_thread_runing = false;
713     m_progress_bar.SetProgress(100);
714     SetProgressInfo(100);
715 
716     if (m_open_output_dir)
717     {
718         ShellExecute(NULL, _T("open"), _T("explorer"), m_out_dir.c_str(), NULL, SW_SHOWNORMAL);
719     }
720 
721     return 0;
722 }
723 
724 
OnCancel()725 void CFormatConvertDlg::OnCancel()
726 {
727     // TODO: 在此添加专用代码和/或调用基类
728     theApp.m_format_convert_dialog_exit = true;
729     if (m_pThread != nullptr)
730         WaitForSingleObject(m_pThread->m_hThread, 2000);	//等待线程退出
731 
732     SaveConfig();
733     SaveEncoderConfig();
734 
735     DestroyWindow();
736 
737     //CBaseDialog::OnCancel();
738 }
739 
740 
OnOK()741 void CFormatConvertDlg::OnOK()
742 {
743     // TODO: 在此添加专用代码和/或调用基类
744     //theApp.m_format_convert_dialog_exit = true;
745     //if (m_pThread != nullptr)
746     //	WaitForSingleObject(m_pThread->m_hThread, 2000);	//等待线程退出
747 
748     CBaseDialog::OnOK();
749 }
750 
751 
OnClose()752 void CFormatConvertDlg::OnClose()
753 {
754     // TODO: 在此添加消息处理程序代码和/或调用默认值
755 
756     CBaseDialog::OnClose();
757 }
758 
759 
OnBnClickedEncoderConfigButton()760 void CFormatConvertDlg::OnBnClickedEncoderConfigButton()
761 {
762     // TODO: 在此添加控件通知处理程序代码
763     switch (m_encode_format)
764     {
765     case EncodeFormat::WAV:
766         break;
767     case EncodeFormat::MP3:
768     {
769         CMP3EncodeCfgDlg dlg;
770         dlg.m_encode_para = m_mp3_encode_para;
771         if (dlg.DoModal() == IDOK)
772             m_mp3_encode_para = dlg.m_encode_para;
773     }
774     break;
775     case EncodeFormat::WMA:
776     {
777         CWmaEncodeCfgDlg dlg;
778         dlg.m_encode_para = m_wma_encode_para;
779         if (dlg.DoModal() == IDOK)
780             m_wma_encode_para = dlg.m_encode_para;
781     }
782     break;
783     case EncodeFormat::OGG:
784     {
785         COggEncodeCfgDlg dlg;
786         dlg.m_encode_para = m_ogg_encode_para;
787         if (dlg.DoModal() == IDOK)
788             m_ogg_encode_para = dlg.m_encode_para;
789     }
790     break;
791     case EncodeFormat::FLAC:
792     {
793         CFlacEncodeCfgDlg dlg;
794         dlg.m_encode_para = m_flac_encode_para;
795         if (dlg.DoModal() == IDOK)
796             m_flac_encode_para = dlg.m_encode_para;
797     }
798     break;
799     default:
800         break;
801     }
802 }
803 
804 
OnBnClickedCopyTagCheck()805 void CFormatConvertDlg::OnBnClickedCopyTagCheck()
806 {
807     // TODO: 在此添加控件通知处理程序代码
808     m_write_tag = (((CButton*)GetDlgItem(IDC_COPY_TAG_CHECK))->GetCheck() != 0);
809 }
810 
811 
OnBnClickedCopyAlbumCoverCheck()812 void CFormatConvertDlg::OnBnClickedCopyAlbumCoverCheck()
813 {
814     // TODO: 在此添加控件通知处理程序代码
815     m_write_album_cover = (((CButton*)GetDlgItem(IDC_COPY_ALBUM_COVER_CHECK))->GetCheck() != 0);
816 }
817 
818 
OnCbnSelchangeTargetFileExistCombo()819 void CFormatConvertDlg::OnCbnSelchangeTargetFileExistCombo()
820 {
821     // TODO: 在此添加控件通知处理程序代码
822     m_file_exist_action = ((CComboBox*)GetDlgItem(IDC_TARGET_FILE_EXIST_COMBO))->GetCurSel();
823 }
824 
825 
OnBnClickedAddNumberCheck()826 void CFormatConvertDlg::OnBnClickedAddNumberCheck()
827 {
828     // TODO: 在此添加控件通知处理程序代码
829     m_add_file_serial_num = (((CButton*)GetDlgItem(IDC_ADD_NUMBER_CHECK))->GetCheck() != 0);
830 }
831 
832 
OnNMRClickSongList1(NMHDR * pNMHDR,LRESULT * pResult)833 void CFormatConvertDlg::OnNMRClickSongList1(NMHDR* pNMHDR, LRESULT* pResult)
834 {
835     LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
836     // TODO: 在此添加控件通知处理程序代码
837     m_item_selected = pNMItemActivate->iItem;	//获取鼠标选中的项目
838     CMenu* pContextMenu = theApp.m_menu_mgr.GetMenu(MenuMgr::FcListMenu);
839     m_file_list_ctrl.ShowPopupMenu(pContextMenu, pNMItemActivate->iItem, this);
840 
841     *pResult = 0;
842 }
843 
844 
OnAddFile()845 void CFormatConvertDlg::OnAddFile()
846 {
847     // TODO: 在此添加命令处理程序代码
848     if (m_thread_runing)
849         return;
850     //设置过滤器
851     wstring filter = FilterHelper::GetAudioFileFilter();
852     //构造打开文件对话框
853     CFileDialog fileDlg(TRUE, NULL, NULL, OFN_ALLOWMULTISELECT, filter.c_str(), this);
854     //设置保存文件名的字符缓冲的大小为128kB(如果以平均一个文件名长度为32字节计算,最多可以打开大约4096个文件)
855     fileDlg.m_ofn.nMaxFile = 128 * 1024;
856     std::vector<wchar_t> buffer(fileDlg.m_ofn.nMaxFile);
857     fileDlg.m_ofn.lpstrFile = buffer.data();
858     //显示打开文件对话框
859     if (IDOK == fileDlg.DoModal())
860     {
861         POSITION posFile = fileDlg.GetStartPosition();
862         while (posFile != NULL)
863         {
864             CString file_path = fileDlg.GetNextPathName(posFile);
865             m_file_list.push_back(SongInfo(file_path.GetString()));
866         }
867         // 音频文件信息更新到媒体库,并解析cue,(对于大量不存在于媒体库的新文件此方法很慢)
868         int cnt{}, percent{};
869         bool exit_flag{ false };
870         CAudioCommon::GetAudioInfo(m_file_list, cnt, exit_flag, percent, MR_MIN_REQUIRED, false);
871         // 去重
872         std::unordered_set<SongKey> song_key;
873         song_key.reserve(m_file_list.size());
874         auto new_end = std::remove_if(m_file_list.begin(), m_file_list.end(),
875             [&](const SongInfo& song) { return !song_key.emplace(song).second; }); // emplace失败说明此项目已存在,返回true移除当前项目
876         m_file_list.erase(new_end, m_file_list.end());
877         // 加载歌曲信息(与播放列表一致)
878         CSongDataManager::GetInstance().LoadSongsInfo(m_file_list);
879         //如果文件是 MIDI 音乐,则把SF2音色库信息添加到注释信息
880         wstring midi_comment = L"Converted from MIDI by MusicPlayer2. SF2: " + CPlayer::GetInstance().GetSoundFontName();
881         for (auto& song : m_file_list)
882         {
883             if (CAudioCommon::GetAudioTypeByFileName(song.file_path) == AU_MIDI)
884                 song.comment = midi_comment;
885         }
886         // 刷新显示
887         ShowFileList();
888     }
889 }
890 
891 
OnDeleteSelect()892 void CFormatConvertDlg::OnDeleteSelect()
893 {
894     // TODO: 在此添加命令处理程序代码
895     if (m_thread_runing)
896         return;
897     int select;
898     select = m_file_list_ctrl.GetCurSel();		//获取当前选中项序号
899     if (select >= 0 && select < static_cast<int>(m_file_list.size()))
900     {
901         m_file_list.erase(m_file_list.begin() + select);	//删除选中项
902         ShowFileList();
903     }
904 }
905 
906 
OnClearList()907 void CFormatConvertDlg::OnClearList()
908 {
909     // TODO: 在此添加命令处理程序代码
910     if (m_thread_runing)
911         return;
912     m_file_list.clear();
913     m_file_list_ctrl.DeleteAllItems();
914 }
915 
916 
OnMoveUp()917 void CFormatConvertDlg::OnMoveUp()
918 {
919     // TODO: 在此添加命令处理程序代码
920     if (m_thread_runing)
921         return;
922     int select;
923     select = m_file_list_ctrl.GetCurSel();		//获取当前选中项序号
924     if (select < 0 || select >= static_cast<int>(m_file_list.size()))	//当前选中项在索引以外
925     {
926         return;
927     }
928     else if (select > 0)
929     {
930         //交换文件列表中的选中项和前一项
931         auto temp = m_file_list[select];
932         m_file_list[select] = m_file_list[select - 1];
933         m_file_list[select - 1] = temp;
934         ShowFileList();		//上移操作完毕重新显示列表
935         m_file_list_ctrl.SetCurSel(select - 1);	//设置选中项为前一项
936     }
937 }
938 
939 
OnMoveDown()940 void CFormatConvertDlg::OnMoveDown()
941 {
942     // TODO: 在此添加命令处理程序代码
943     if (m_thread_runing)
944         return;
945     int select;
946     select = m_file_list_ctrl.GetCurSel();		//获取当前选中项序号
947     if (select < 0 || select >= static_cast<int>(m_file_list.size()))	//当前选中项在索引以外
948     {
949         return;
950     }
951     else if (select < static_cast<int>(m_file_list.size()) - 1)
952     {
953         //交换文件列表中的选中项和后一项
954         auto temp = m_file_list[select];
955         m_file_list[select] = m_file_list[select + 1];
956         m_file_list[select + 1] = temp;
957         ShowFileList();		//下移操作完毕重新显示列表
958         m_file_list_ctrl.SetCurSel(select + 1);	//设置选中项为前一项
959     }
960 }
961 
962 
PreTranslateMessage(MSG * pMsg)963 BOOL CFormatConvertDlg::PreTranslateMessage(MSG* pMsg)
964 {
965     // TODO: 在此添加专用代码和/或调用基类
966     if (pMsg->message == WM_KEYDOWN)
967     {
968         //按下Ctrl键时
969         if (GetKeyState(VK_CONTROL) & 0x80)
970         {
971             if (pMsg->wParam == VK_UP)		//按Ctr+↑上移
972             {
973                 OnMoveUp();
974                 return TRUE;
975             }
976             if (pMsg->wParam == VK_DOWN)	//按Ctr+↓下移
977             {
978                 OnMoveDown();
979                 return TRUE;
980             }
981         }
982     }
983     return CBaseDialog::PreTranslateMessage(pMsg);
984 }
985 
986 
OnEditTagInfo()987 void CFormatConvertDlg::OnEditTagInfo()
988 {
989     // TODO: 在此添加命令处理程序代码
990     if (m_thread_runing)
991         return;
992 
993     CTagEditDlg dlg(m_file_list, m_item_selected);
994     dlg.DoModal();
995 }
996 
997 
OnInitMenu(CMenu * pMenu)998 void CFormatConvertDlg::OnInitMenu(CMenu* pMenu)
999 {
1000     CBaseDialog::OnInitMenu(pMenu);
1001 
1002     // TODO: 在此处添加消息处理程序代码
1003     bool item_selected_valid{ m_item_selected >= 0 && m_item_selected < static_cast<int>(m_file_list.size()) };
1004     pMenu->EnableMenuItem(ID_ADD_FILE, MF_BYCOMMAND | (!m_thread_runing ? MF_ENABLED : MF_GRAYED));
1005     pMenu->EnableMenuItem(ID_CLEAR_LIST, MF_BYCOMMAND | (!m_thread_runing ? MF_ENABLED : MF_GRAYED));
1006     pMenu->EnableMenuItem(ID_EDIT_TAG_INFO, MF_BYCOMMAND | ((!m_thread_runing && item_selected_valid) ? MF_ENABLED : MF_GRAYED));
1007     pMenu->EnableMenuItem(ID_DELETE_SELECT, MF_BYCOMMAND | ((!m_thread_runing && item_selected_valid) ? MF_ENABLED : MF_GRAYED));
1008     pMenu->EnableMenuItem(ID_MOVE_UP, MF_BYCOMMAND | ((!m_thread_runing && item_selected_valid) ? MF_ENABLED : MF_GRAYED));
1009     pMenu->EnableMenuItem(ID_MOVE_DOWN, MF_BYCOMMAND | ((!m_thread_runing && item_selected_valid) ? MF_ENABLED : MF_GRAYED));
1010 
1011     pMenu->SetDefaultItem(ID_EDIT_TAG_INFO);
1012 }
1013 
1014 
OnNMDblclkSongList1(NMHDR * pNMHDR,LRESULT * pResult)1015 void CFormatConvertDlg::OnNMDblclkSongList1(NMHDR* pNMHDR, LRESULT* pResult)
1016 {
1017     LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
1018     // TODO: 在此添加控件通知处理程序代码
1019     m_item_selected = pNMItemActivate->iItem;	//获取鼠标选中的项目
1020     if (m_item_selected >= 0 && m_item_selected < static_cast<int>(m_file_list.size()))
1021         OnEditTagInfo();		//双击打开“编辑标签信息”
1022 
1023     *pResult = 0;
1024 }
1025 
1026 
OnBnClickedChangeFreqCheck()1027 void CFormatConvertDlg::OnBnClickedChangeFreqCheck()
1028 {
1029     // TODO: 在此添加控件通知处理程序代码
1030     CButton* pBtn = (CButton*)GetDlgItem(IDC_CHANGE_FREQ_CHECK);
1031     m_convert_freq = pBtn->GetCheck() != 0;
1032     if (m_convert_freq && !CPlayer::GetInstance().GetPlayerCore()->IsFreqConvertAvailable())
1033     {
1034         m_convert_freq = false;
1035         CBassCore* bass_core = dynamic_cast<CBassCore*>(CPlayer::GetInstance().GetPlayerCore());
1036         if (bass_core != nullptr)
1037         {
1038             wstring info = theApp.m_str_table.LoadTextFormat(L"MSG_FORMAT_CONVERT_BASS_MIX_LOAD_ERROR", { bass_core->GetEncoderDir() + L"bassmix.dll" });
1039             MessageBox(info.c_str(), NULL, MB_ICONWARNING | MB_OK);
1040         }
1041         pBtn->SetCheck(FALSE);
1042     }
1043 
1044     m_freq_comb.EnableWindow(m_convert_freq);
1045 }
1046 
1047 
OnCbnSelchangeFreqCombo()1048 void CFormatConvertDlg::OnCbnSelchangeFreqCombo()
1049 {
1050     // TODO: 在此添加控件通知处理程序代码
1051     CString str;
1052     m_freq_comb.GetWindowText(str);
1053     m_freq_sel = str.GetString();
1054 }
1055 
1056 
OnEditBrowseChanged(WPARAM wParam,LPARAM lParam)1057 afx_msg LRESULT CFormatConvertDlg::OnEditBrowseChanged(WPARAM wParam, LPARAM lParam)
1058 {
1059     CBrowseEdit* pEdit = (CBrowseEdit*)lParam;
1060     CString str;
1061     if (pEdit == &m_out_dir_edit)
1062     {
1063         GetDlgItemText(IDC_OUT_DIR_EDIT, str);
1064         m_out_dir = str.GetString();
1065     }
1066     if (pEdit == &m_out_name_edit)
1067     {
1068         GetDlgItemText(IDC_OUT_NAME_EDIT, str);
1069         m_out_name = str.GetString();
1070     }
1071     return 0;
1072 }
1073 
1074 
OnBnClickedOpenTargetDirCheck()1075 void CFormatConvertDlg::OnBnClickedOpenTargetDirCheck()
1076 {
1077     // TODO: 在此添加控件通知处理程序代码
1078     m_open_output_dir = (((CButton*)GetDlgItem(IDC_OPEN_TARGET_DIR_CHECK))->GetCheck() != 0);
1079 }
1080