libopenmpt_plugin_gui.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. /*
  2. * libopenmpt_plugin_gui.cpp
  3. * -------------------------
  4. * Purpose: libopenmpt plugin GUI
  5. * Notes : (currently none)
  6. * Authors: OpenMPT Devs
  7. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  8. */
  9. #ifndef _CRT_SECURE_NO_WARNINGS
  10. #define _CRT_SECURE_NO_WARNINGS
  11. #endif
  12. #if !defined(WINVER) && !defined(_WIN32_WINDOWS)
  13. #ifndef _WIN32_WINNT
  14. #define _WIN32_WINNT 0x0501 // _WIN32_WINNT_WINXP
  15. #endif
  16. #endif
  17. #if !defined(MPT_BUILD_RETRO)
  18. #if defined(_MSC_VER)
  19. #define MPT_WITH_MFC
  20. #endif
  21. #else
  22. #if defined(_WIN32_WINNT)
  23. #if (_WIN32_WINNT >= 0x0501)
  24. #if defined(_MSC_VER)
  25. #define MPT_WITH_MFC
  26. #endif
  27. #endif
  28. #endif
  29. #endif
  30. #if defined(MPT_WITH_MFC)
  31. #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS // Avoid binary bloat from linking unused MFC controls
  32. #endif // MPT_WITH_MFC
  33. #ifndef NOMINMAX
  34. #define NOMINMAX
  35. #endif
  36. #if !defined(MPT_WITH_MFC)
  37. #include <fstream>
  38. #include <locale>
  39. #include <sstream>
  40. #include <string>
  41. #include <vector>
  42. #endif
  43. #if !defined(MPT_WITH_MFC)
  44. #include <windows.h>
  45. #endif
  46. #if defined(MPT_WITH_MFC)
  47. #include <afxwin.h>
  48. #include <afxcmn.h>
  49. #endif // MPT_WITH_MFC
  50. #if defined(MPT_WITH_MFC)
  51. #include "resource.h"
  52. #endif // MPT_WITH_MFC
  53. #include "libopenmpt_plugin_gui.hpp"
  54. namespace libopenmpt {
  55. namespace plugin {
  56. #if defined(MPT_WITH_MFC)
  57. class CSettingsApp : public CWinApp {
  58. public:
  59. BOOL InitInstance() override {
  60. if ( !CWinApp::InitInstance() )
  61. {
  62. return FALSE;
  63. }
  64. DllMainAttach();
  65. return TRUE;
  66. }
  67. int ExitInstance() override {
  68. DllMainDetach();
  69. return CWinApp::ExitInstance();
  70. }
  71. };
  72. CSettingsApp theApp;
  73. class CSettingsDialog : public CDialog {
  74. protected:
  75. DECLARE_MESSAGE_MAP()
  76. libopenmpt_settings * s;
  77. CString m_Title;
  78. CComboBox m_ComboBoxSamplerate;
  79. CComboBox m_ComboBoxChannels;
  80. CSliderCtrl m_SliderCtrlGain;
  81. CComboBox m_ComboBoxInterpolation;
  82. CButton m_CheckBoxAmigaResampler;
  83. CComboBox m_ComboBoxAmigaFilter;
  84. CComboBox m_ComboBoxRepeat;
  85. CSliderCtrl m_SliderCtrlStereoSeparation;
  86. CComboBox m_ComboBoxRamping;
  87. public:
  88. CSettingsDialog( libopenmpt_settings * s_, CString title, CWnd * parent = nullptr )
  89. : CDialog( IDD_SETTINGS, parent )
  90. , s( s_ )
  91. , m_Title( title )
  92. {
  93. return;
  94. }
  95. protected:
  96. void DoDataExchange( CDataExchange * pDX ) override
  97. {
  98. CDialog::DoDataExchange( pDX );
  99. DDX_Control( pDX, IDC_COMBO_SAMPLERATE, m_ComboBoxSamplerate );
  100. DDX_Control( pDX, IDC_COMBO_CHANNELS, m_ComboBoxChannels );
  101. DDX_Control( pDX, IDC_SLIDER_GAIN, m_SliderCtrlGain );
  102. DDX_Control( pDX, IDC_COMBO_INTERPOLATION, m_ComboBoxInterpolation );
  103. DDX_Control( pDX, IDC_CHECK_AMIGA_RESAMPLER, m_CheckBoxAmigaResampler );
  104. DDX_Control( pDX, IDC_COMBO_AMIGA_FILTER, m_ComboBoxAmigaFilter );
  105. DDX_Control( pDX, IDC_COMBO_REPEAT, m_ComboBoxRepeat );
  106. DDX_Control( pDX, IDC_SLIDER_STEREOSEPARATION, m_SliderCtrlStereoSeparation );
  107. DDX_Control( pDX, IDC_COMBO_RAMPING, m_ComboBoxRamping );
  108. }
  109. afx_msg BOOL OnInitDialog() override {
  110. CDialog::OnInitDialog();
  111. SetWindowText( m_Title );
  112. EnableToolTips();
  113. bool selected = false;
  114. selected = false;
  115. if ( !s->no_default_format ) {
  116. m_ComboBoxSamplerate.SetItemData( m_ComboBoxSamplerate.AddString( L"Default" ), 0 );
  117. }
  118. m_ComboBoxSamplerate.SetItemData( m_ComboBoxSamplerate.AddString( L"6000" ), 6000 );
  119. m_ComboBoxSamplerate.SetItemData( m_ComboBoxSamplerate.AddString( L"8000" ), 8000 );
  120. m_ComboBoxSamplerate.SetItemData( m_ComboBoxSamplerate.AddString( L"11025" ), 11025 );
  121. m_ComboBoxSamplerate.SetItemData( m_ComboBoxSamplerate.AddString( L"16000" ), 16000 );
  122. m_ComboBoxSamplerate.SetItemData( m_ComboBoxSamplerate.AddString( L"22050" ), 22050 );
  123. m_ComboBoxSamplerate.SetItemData( m_ComboBoxSamplerate.AddString( L"32000" ), 32000 );
  124. m_ComboBoxSamplerate.SetItemData( m_ComboBoxSamplerate.AddString( L"44100" ), 44100 );
  125. m_ComboBoxSamplerate.SetItemData( m_ComboBoxSamplerate.AddString( L"48000" ), 48000 );
  126. m_ComboBoxSamplerate.SetItemData( m_ComboBoxSamplerate.AddString( L"88200" ), 88200 );
  127. m_ComboBoxSamplerate.SetItemData( m_ComboBoxSamplerate.AddString( L"96000" ), 96000 );
  128. if ( !s->no_default_format && s->samplerate == 0 ) {
  129. m_ComboBoxSamplerate.SelectString( 0, L"Default" );
  130. }
  131. for ( int index = 0; index < m_ComboBoxSamplerate.GetCount(); ++index ) {
  132. if ( static_cast<int>( m_ComboBoxSamplerate.GetItemData( index ) ) == s->samplerate ) {
  133. m_ComboBoxSamplerate.SetCurSel( index );
  134. selected = true;
  135. }
  136. }
  137. if ( !selected ) {
  138. m_ComboBoxSamplerate.SelectString( 0, L"48000" );
  139. }
  140. selected = false;
  141. if ( !s->no_default_format ) {
  142. m_ComboBoxChannels.SetItemData( m_ComboBoxChannels.AddString( L"Default" ), 0 );
  143. }
  144. m_ComboBoxChannels.SetItemData( m_ComboBoxChannels.AddString( L"Mono" ), 1 );
  145. m_ComboBoxChannels.SetItemData( m_ComboBoxChannels.AddString( L"Stereo" ), 2 );
  146. m_ComboBoxChannels.SetItemData( m_ComboBoxChannels.AddString( L"Quad" ), 4 );
  147. if ( !s->no_default_format && s->channels == 0 ) {
  148. m_ComboBoxChannels.SelectString( 0, L"Default" );
  149. }
  150. for ( int index = 0; index < m_ComboBoxChannels.GetCount(); ++index ) {
  151. if ( static_cast<int>( m_ComboBoxChannels.GetItemData( index ) ) == s->channels ) {
  152. m_ComboBoxChannels.SetCurSel( index );
  153. selected = true;
  154. }
  155. }
  156. if ( !selected ) {
  157. m_ComboBoxChannels.SelectString( 0, L"Stereo" );
  158. }
  159. m_SliderCtrlGain.SetRange( -1200, 1200 );
  160. m_SliderCtrlGain.SetTicFreq( 100 );
  161. m_SliderCtrlGain.SetPageSize( 300 );
  162. m_SliderCtrlGain.SetLineSize( 100 );
  163. m_SliderCtrlGain.SetPos( s->mastergain_millibel );
  164. selected = false;
  165. m_ComboBoxInterpolation.SetItemData( m_ComboBoxInterpolation.AddString( L"Off / 1 Tap (Nearest)" ), 1 );
  166. m_ComboBoxInterpolation.SetItemData( m_ComboBoxInterpolation.AddString( L"2 Tap (Linear)" ), 2 );
  167. m_ComboBoxInterpolation.SetItemData( m_ComboBoxInterpolation.AddString( L"4 Tap (Cubic)" ), 4 );
  168. m_ComboBoxInterpolation.SetItemData( m_ComboBoxInterpolation.AddString( L"8 Tap (Polyphase FIR)" ), 8 );
  169. for ( int index = 0; index < m_ComboBoxInterpolation.GetCount(); ++index ) {
  170. if ( static_cast<int>( m_ComboBoxInterpolation.GetItemData( index ) ) == s->interpolationfilterlength ) {
  171. m_ComboBoxInterpolation.SetCurSel( index );
  172. selected = true;
  173. }
  174. }
  175. if ( !selected ) {
  176. m_ComboBoxInterpolation.SelectString( 0, L"8 Tap (Polyphase FIR)" );
  177. }
  178. m_CheckBoxAmigaResampler.SetCheck( s->use_amiga_resampler ? BST_CHECKED : BST_UNCHECKED );
  179. selected = false;
  180. m_ComboBoxAmigaFilter.EnableWindow( s->use_amiga_resampler ? TRUE : FALSE );
  181. m_ComboBoxAmigaFilter.SetItemData( m_ComboBoxAmigaFilter.AddString( L"Default" ), 0 );
  182. m_ComboBoxAmigaFilter.SetItemData( m_ComboBoxAmigaFilter.AddString( L"A500 Filter" ), 0xA500 );
  183. m_ComboBoxAmigaFilter.SetItemData( m_ComboBoxAmigaFilter.AddString( L"A1200 Filter" ), 0xA1200 );
  184. m_ComboBoxAmigaFilter.SetItemData( m_ComboBoxAmigaFilter.AddString( L"Unfiltered" ), 1 );
  185. for ( int index = 0; index < m_ComboBoxAmigaFilter.GetCount(); ++index ) {
  186. if ( static_cast<int>( m_ComboBoxAmigaFilter.GetItemData( index ) ) == s->amiga_filter_type ) {
  187. m_ComboBoxAmigaFilter.SetCurSel( index );
  188. selected = true;
  189. }
  190. }
  191. if ( !selected ) {
  192. m_ComboBoxAmigaFilter.SelectString( 0, L"Default" );
  193. }
  194. selected = false;
  195. m_ComboBoxRepeat.SetItemData( m_ComboBoxRepeat.AddString( L"Forever" ), static_cast<unsigned int>( -1 ) );
  196. m_ComboBoxRepeat.SetItemData( m_ComboBoxRepeat.AddString( L"Never" ), 0 );
  197. m_ComboBoxRepeat.SetItemData( m_ComboBoxRepeat.AddString( L"Once" ), 1 );
  198. for ( int index = 0; index < m_ComboBoxRepeat.GetCount(); ++index ) {
  199. if ( static_cast<int>( m_ComboBoxRepeat.GetItemData( index ) ) == s->repeatcount ) {
  200. m_ComboBoxRepeat.SetCurSel( index );
  201. selected = true;
  202. }
  203. }
  204. if ( !selected ) {
  205. m_ComboBoxRepeat.SelectString( 0, L"Never" );
  206. }
  207. m_SliderCtrlStereoSeparation.SetRange( 0, 200 );
  208. m_SliderCtrlStereoSeparation.SetTicFreq( 100 );
  209. m_SliderCtrlStereoSeparation.SetPageSize( 25 );
  210. m_SliderCtrlStereoSeparation.SetLineSize( 5 );
  211. m_SliderCtrlStereoSeparation.SetPos( s->stereoseparation );
  212. selected = false;
  213. m_ComboBoxRamping.SetItemData( m_ComboBoxRamping.AddString( L"Default" ), static_cast<unsigned int>( -1 ) );
  214. m_ComboBoxRamping.SetItemData( m_ComboBoxRamping.AddString( L"Off" ), 0 );
  215. m_ComboBoxRamping.SetItemData( m_ComboBoxRamping.AddString( L"1 ms" ), 1 );
  216. m_ComboBoxRamping.SetItemData( m_ComboBoxRamping.AddString( L"2 ms" ), 2 );
  217. m_ComboBoxRamping.SetItemData( m_ComboBoxRamping.AddString( L"3 ms" ), 3 );
  218. m_ComboBoxRamping.SetItemData( m_ComboBoxRamping.AddString( L"5 ms" ), 5 );
  219. m_ComboBoxRamping.SetItemData( m_ComboBoxRamping.AddString( L"10 ms" ), 10 );
  220. for ( int index = 0; index < m_ComboBoxRamping.GetCount(); ++index ) {
  221. if ( static_cast<int>( m_ComboBoxRamping.GetItemData( index ) ) == s->ramping ) {
  222. m_ComboBoxRamping.SetCurSel( index );
  223. selected = true;
  224. }
  225. }
  226. if ( !selected ) {
  227. m_ComboBoxRamping.SelectString( 0, L"Default" );
  228. }
  229. return TRUE;
  230. }
  231. void OnOK() override {
  232. s->samplerate = m_ComboBoxSamplerate.GetItemData( m_ComboBoxSamplerate.GetCurSel() );
  233. s->channels = m_ComboBoxChannels.GetItemData( m_ComboBoxChannels.GetCurSel() );
  234. s->mastergain_millibel = m_SliderCtrlGain.GetPos();
  235. s->interpolationfilterlength = m_ComboBoxInterpolation.GetItemData( m_ComboBoxInterpolation.GetCurSel() );
  236. s->use_amiga_resampler = ( m_CheckBoxAmigaResampler.GetCheck() != BST_UNCHECKED ) ? 1 : 0;
  237. s->amiga_filter_type = m_ComboBoxAmigaFilter.GetItemData( m_ComboBoxAmigaFilter.GetCurSel() );
  238. s->repeatcount = m_ComboBoxRepeat.GetItemData( m_ComboBoxRepeat.GetCurSel() );
  239. s->stereoseparation = m_SliderCtrlStereoSeparation.GetPos();
  240. s->ramping = m_ComboBoxRamping.GetItemData( m_ComboBoxRamping.GetCurSel() );
  241. s->changed();
  242. CDialog::OnOK();
  243. }
  244. BOOL OnToolTipText( UINT, NMHDR * pNMHDR, LRESULT * pResult ) {
  245. TOOLTIPTEXT * pTTT = reinterpret_cast<TOOLTIPTEXT *>( pNMHDR );
  246. UINT_PTR nID = pNMHDR->idFrom;
  247. if( pTTT->uFlags & TTF_IDISHWND )
  248. {
  249. // idFrom is actually the HWND of the tool
  250. nID = (UINT_PTR)::GetDlgCtrlID((HWND)nID);
  251. }
  252. switch ( nID ) {
  253. case IDC_SLIDER_GAIN:
  254. swprintf( pTTT->szText, _countof(pTTT->szText), L"%.02f dB", m_SliderCtrlGain.GetPos() * 0.01f );
  255. break;
  256. case IDC_SLIDER_STEREOSEPARATION:
  257. swprintf( pTTT->szText, _countof(pTTT->szText), L"%d %%", m_SliderCtrlStereoSeparation.GetPos());
  258. break;
  259. default:
  260. return FALSE;
  261. }
  262. *pResult = 0;
  263. return TRUE;
  264. }
  265. void OnAmigaResamplerChanged() {
  266. m_ComboBoxAmigaFilter.EnableWindow( IsDlgButtonChecked( IDC_CHECK_AMIGA_RESAMPLER ) != BST_UNCHECKED ? TRUE : FALSE );
  267. }
  268. };
  269. BEGIN_MESSAGE_MAP(CSettingsDialog, CDialog)
  270. ON_NOTIFY_EX_RANGE(TTN_NEEDTEXT, 0, 0xFFFF, &CSettingsDialog::OnToolTipText)
  271. ON_COMMAND( IDC_CHECK_AMIGA_RESAMPLER, &CSettingsDialog::OnAmigaResamplerChanged )
  272. END_MESSAGE_MAP()
  273. class CInfoDialog : public CDialog {
  274. protected:
  275. CString m_Title;
  276. CString m_FileInfo;
  277. CEdit m_EditFileInfo;
  278. public:
  279. CInfoDialog( CString title, CString info, CWnd * parent = NULL )
  280. : CDialog( IDD_FILEINFO, parent )
  281. , m_Title( title )
  282. , m_FileInfo( info )
  283. {
  284. return;
  285. }
  286. protected:
  287. void DoDataExchange( CDataExchange * pDX ) override
  288. {
  289. CDialog::DoDataExchange( pDX );
  290. DDX_Control( pDX, IDC_FILEINFO, m_EditFileInfo );
  291. }
  292. afx_msg BOOL OnInitDialog() override {
  293. if ( !CDialog::OnInitDialog() ) {
  294. return false;
  295. }
  296. SetWindowText( m_Title );
  297. m_EditFileInfo.SetWindowText( m_FileInfo );
  298. return TRUE;
  299. }
  300. };
  301. #endif // MPT_WITH_MFC
  302. #if defined(MPT_WITH_MFC)
  303. void gui_edit_settings( libopenmpt_settings * s, HWND parent, std::wstring title ) {
  304. AFX_MANAGE_STATE( AfxGetStaticModuleState() );
  305. CSettingsDialog dlg( s, title.c_str(), parent ? CWnd::FromHandle( parent ) : nullptr );
  306. dlg.DoModal();
  307. }
  308. void gui_show_file_info( HWND parent, std::wstring title, std::wstring info ) {
  309. AFX_MANAGE_STATE( AfxGetStaticModuleState() );
  310. CInfoDialog dlg( title.c_str(), info.c_str(), parent ? CWnd::FromHandle( parent ) : nullptr);
  311. dlg.DoModal();
  312. }
  313. #else // !MPT_WITH_MFC
  314. static std::basic_string<TCHAR> GetTempDirectory() {
  315. DWORD size = GetTempPath(0, nullptr);
  316. if (size) {
  317. std::vector<TCHAR> tempPath(size + 1);
  318. if (GetTempPath(size + 1, tempPath.data())) {
  319. return tempPath.data();
  320. }
  321. }
  322. return {};
  323. }
  324. static std::basic_string<TCHAR> GetTempFilename( std::basic_string<TCHAR> prefix ) {
  325. std::vector<TCHAR> buf(MAX_PATH);
  326. if (GetTempFileName(GetTempDirectory().c_str(), prefix.c_str(), 0, buf.data()) == 0) {
  327. return {};
  328. }
  329. return buf.data();
  330. }
  331. template <typename T>
  332. static std::basic_string<TCHAR> as_string( T x ) {
  333. std::basic_ostringstream<TCHAR> s;
  334. s.imbue(std::locale::classic());
  335. s << x;
  336. return s.str();
  337. }
  338. void gui_edit_settings( libopenmpt_settings * s, HWND /* parent */ , std::basic_string<TCHAR> title ) {
  339. std::basic_string<TCHAR> filename = GetTempFilename( title );
  340. WritePrivateProfileString( title.c_str(), TEXT("Samplerate_Hz"), as_string( s->samplerate ).c_str(), filename.c_str() );
  341. WritePrivateProfileString( title.c_str(), TEXT("Channels"), as_string( s->channels ).c_str(), filename.c_str() );
  342. WritePrivateProfileString( title.c_str(), TEXT("MasterGain_milliBel"), as_string( s->mastergain_millibel ).c_str(), filename.c_str() );
  343. WritePrivateProfileString( title.c_str(), TEXT("StereoSeparation_Percent"), as_string( s->stereoseparation ).c_str(), filename.c_str() );
  344. WritePrivateProfileString( title.c_str(), TEXT("RepeatCount"), as_string( s->repeatcount ).c_str(), filename.c_str() );
  345. WritePrivateProfileString( title.c_str(), TEXT("InterpolationFilterLength"), as_string( s->interpolationfilterlength ).c_str(), filename.c_str() );
  346. WritePrivateProfileString( title.c_str(), TEXT("UseAmigaResampler"), as_string( s->use_amiga_resampler ).c_str(), filename.c_str() );
  347. WritePrivateProfileString( title.c_str(), TEXT("AmigaFilterType"), as_string( s->amiga_filter_type ).c_str(), filename.c_str() );
  348. WritePrivateProfileString( title.c_str(), TEXT("VolumeRampingStrength"), as_string( s->ramping ).c_str(), filename.c_str() );
  349. WritePrivateProfileString( title.c_str(), TEXT("VisAllowScroll"), as_string( s->vis_allow_scroll ).c_str(), filename.c_str() );
  350. STARTUPINFO startupInfo = {};
  351. startupInfo.cb = sizeof(startupInfo);
  352. PROCESS_INFORMATION processInformation = {};
  353. std::basic_string<TCHAR> command = std::basic_string<TCHAR>(TEXT("notepad.exe")) + TEXT(" ") + filename;
  354. std::vector<TCHAR> commandBuf{ command.c_str(), command.c_str() + command.length() + 1 };
  355. if ( CreateProcess( NULL, commandBuf.data(), NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInformation ) == FALSE ) {
  356. MessageBox(NULL, as_string(GetLastError()).c_str(), TEXT("fail"), 0);
  357. return;
  358. }
  359. CloseHandle( processInformation.hThread );
  360. WaitForSingleObject( processInformation.hProcess, INFINITE );
  361. CloseHandle( processInformation.hProcess );
  362. s->samplerate = GetPrivateProfileInt( title.c_str(), TEXT("Samplerate_Hz"), libopenmpt_settings{}.samplerate, filename.c_str() );
  363. s->channels = GetPrivateProfileInt( title.c_str(), TEXT("Channels"), libopenmpt_settings{}.channels, filename.c_str() );
  364. s->mastergain_millibel = GetPrivateProfileInt( title.c_str(), TEXT("MasterGain_milliBel"), libopenmpt_settings{}.mastergain_millibel, filename.c_str() );
  365. s->stereoseparation = GetPrivateProfileInt( title.c_str(), TEXT("StereoSeparation_Percent"), libopenmpt_settings{}.stereoseparation, filename.c_str() );
  366. s->repeatcount = GetPrivateProfileInt( title.c_str(), TEXT("RepeatCount"), libopenmpt_settings{}.repeatcount, filename.c_str() );
  367. s->interpolationfilterlength = GetPrivateProfileInt( title.c_str(), TEXT("InterpolationFilterLength"), libopenmpt_settings{}.interpolationfilterlength, filename.c_str() );
  368. s->use_amiga_resampler = GetPrivateProfileInt( title.c_str(), TEXT("UseAmigaResampler"), libopenmpt_settings{}.use_amiga_resampler, filename.c_str() );
  369. s->amiga_filter_type = GetPrivateProfileInt( title.c_str(), TEXT("AmigaFilterType"), libopenmpt_settings{}.amiga_filter_type, filename.c_str() );
  370. s->ramping = GetPrivateProfileInt( title.c_str(), TEXT("VolumeRampingStrength"), libopenmpt_settings{}.ramping, filename.c_str() );
  371. s->vis_allow_scroll = GetPrivateProfileInt( title.c_str(), TEXT("VisAllowScroll"), libopenmpt_settings{}.vis_allow_scroll, filename.c_str() );
  372. DeleteFile( filename.c_str() );
  373. }
  374. void gui_show_file_info( HWND /* parent */ , std::basic_string<TCHAR> title, std::basic_string<TCHAR> info ) {
  375. std::basic_string<TCHAR> filename = GetTempFilename( title );
  376. {
  377. std::basic_ofstream<TCHAR> f( filename.c_str(), std::ios::out );
  378. f << info;
  379. }
  380. STARTUPINFO startupInfo = {};
  381. startupInfo.cb = sizeof(startupInfo);
  382. PROCESS_INFORMATION processInformation = {};
  383. std::basic_string<TCHAR> command = std::basic_string<TCHAR>(TEXT("notepad.exe")) + TEXT(" ") + filename;
  384. std::vector<TCHAR> commandBuf{ command.c_str(), command.c_str() + command.length() + 1 };
  385. if ( CreateProcess( NULL, commandBuf.data(), NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInformation ) == FALSE ) {
  386. return;
  387. }
  388. CloseHandle( processInformation.hThread );
  389. WaitForSingleObject( processInformation.hProcess, INFINITE );
  390. CloseHandle( processInformation.hProcess );
  391. DeleteFile( filename.c_str() );
  392. }
  393. #endif // MPT_WITH_MFC
  394. } // namespace plugin
  395. } // namespace libopenmpt