Mptrack.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. /*
  2. * MPTrack.h
  3. * ---------
  4. * Purpose: OpenMPT core application class.
  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. #pragma once
  10. #include "openmpt/all/BuildSettings.hpp"
  11. #include "resource.h" // main symbols
  12. #include "Settings.h"
  13. #include "MPTrackUtil.h"
  14. #include "Reporting.h"
  15. #include "../soundlib/MIDIMacros.h"
  16. #include "../soundlib/modcommand.h"
  17. #include "../common/ComponentManager.h"
  18. #include "../misc/mptMutex.h"
  19. #include "../common/mptRandom.h"
  20. #include <future>
  21. OPENMPT_NAMESPACE_BEGIN
  22. class CModDoc;
  23. class CModDocTemplate;
  24. class CVstPluginManager;
  25. namespace SoundDevice
  26. {
  27. class Manager;
  28. } // namespace SoundDevice
  29. struct AllSoundDeviceComponents;
  30. class CDLSBank;
  31. class DebugSettings;
  32. class TrackerSettings;
  33. class ComponentManagerSettings;
  34. namespace mpt
  35. {
  36. namespace Wine
  37. {
  38. class VersionContext;
  39. class Context;
  40. } // namespace Wine
  41. } // namespace mpt
  42. class GdiplusRAII;
  43. /////////////////////////////////////////////////////////////////////////////
  44. // 16-colors DIB
  45. struct MODPLUGDIB
  46. {
  47. BITMAPINFOHEADER bmiHeader;
  48. RGBQUAD bmiColors[16];
  49. LPBYTE lpDibBits;
  50. };
  51. /////////////////////////////////////////////////////////////////////////////
  52. // Midi Library
  53. using MidiLibrary = std::array<mpt::PathString, 128 * 2>; // 128 instruments + 128 percussions
  54. //////////////////////////////////////////////////////////////////////////
  55. // Dragon Droppings
  56. enum DragonDropType
  57. {
  58. DRAGONDROP_NOTHING = 0, // |------< Drop Type >-------------|---< dropItem >----|---< dropParam >---|
  59. DRAGONDROP_DLS, // | Instrument from a DLS bank | DLS Bank # | DLS Instrument |
  60. DRAGONDROP_SAMPLE, // | Sample from a song | Sample # | NULL |
  61. DRAGONDROP_INSTRUMENT, // | Instrument from a song | Instrument # | NULL |
  62. DRAGONDROP_SOUNDFILE, // | File from instrument library | ? | File Name |
  63. DRAGONDROP_MIDIINSTR, // | File from midi library | Midi Program/Perc | File Name |
  64. DRAGONDROP_PATTERN, // | Pattern from a song | Pattern # | NULL |
  65. DRAGONDROP_ORDER, // | Pattern index in a song | Order # | NULL |
  66. DRAGONDROP_SONG, // | Song file (mod/s3m/xm/it) | 0 | File Name |
  67. DRAGONDROP_SEQUENCE // | Sequence (a set of orders) | Sequence # | NULL |
  68. };
  69. struct DRAGONDROP
  70. {
  71. const CSoundFile *sndFile = nullptr;
  72. DragonDropType dropType = DRAGONDROP_NOTHING;
  73. uint32 dropItem = 0;
  74. LPARAM dropParam = 0;
  75. mpt::PathString GetPath() const
  76. {
  77. const mpt::PathString *const path = reinterpret_cast<const mpt::PathString *>(dropParam);
  78. MPT_ASSERT(path);
  79. return path ? *path : mpt::PathString();
  80. }
  81. };
  82. /////////////////////////////////////////////////////////////////////////////
  83. // CTrackApp:
  84. // See mptrack.cpp for the implementation of this class
  85. //
  86. class CMPTCommandLineInfo;
  87. class CTrackApp : public CWinApp
  88. {
  89. friend class CMainFrame;
  90. // static data
  91. protected:
  92. static MODTYPE m_nDefaultDocType;
  93. static MidiLibrary midiLibrary;
  94. public:
  95. static std::vector<std::unique_ptr<CDLSBank>> gpDLSBanks;
  96. protected:
  97. mpt::recursive_mutex_with_lock_count m_GlobalMutex;
  98. DWORD m_GuiThreadId = 0;
  99. std::future<std::vector<std::unique_ptr<CDLSBank>>> m_scannedDlsBanks;
  100. std::atomic<bool> m_scannedDlsBanksAvailable = false;
  101. std::unique_ptr<mpt::random_device> m_RD;
  102. std::unique_ptr<mpt::thread_safe_prng<mpt::default_prng>> m_PRNG;
  103. std::unique_ptr<GdiplusRAII> m_Gdiplus;
  104. std::shared_ptr<mpt::OS::Wine::VersionContext> m_WineVersion;
  105. IniFileSettingsBackend *m_pSettingsIniFile;
  106. SettingsContainer *m_pSettings = nullptr;
  107. DebugSettings *m_pDebugSettings = nullptr;
  108. TrackerSettings *m_pTrackerSettings = nullptr;
  109. IniFileSettingsBackend *m_pSongSettingsIniFile = nullptr;
  110. SettingsContainer *m_pSongSettings = nullptr;
  111. ComponentManagerSettings *m_pComponentManagerSettings = nullptr;
  112. IniFileSettingsContainer *m_pPluginCache = nullptr;
  113. CModDocTemplate *m_pModTemplate = nullptr;
  114. CVstPluginManager *m_pPluginManager = nullptr;
  115. mpt::log::GlobalLogger m_GlobalLogger{};
  116. std::unique_ptr<AllSoundDeviceComponents> m_pAllSoundDeviceComponents;
  117. std::unique_ptr<SoundDevice::Manager> m_pSoundDevicesManager;
  118. mpt::PathString m_InstallPath; // i.e. "C:\Program Files\OpenMPT\" (installer mode) or "G:\OpenMPT\" (portable mode)
  119. mpt::PathString m_InstallBinPath; // i.e. "C:\Program Files\OpenMPT\bin\" (multi-arch mode) or InstallPath (legacy mode)
  120. mpt::PathString m_InstallBinArchPath; // i.e. "C:\Program Files\OpenMPT\bin\amd64\" (multi-arch mode) or InstallPath (legacy mode)
  121. mpt::PathString m_InstallPkgPath; // i.e. "C:\Program Files\OpenMPT\" (installer mode) or "G:\OpenMPT\" (portable mode)
  122. mpt::PathString m_ConfigPath; // InstallPath (portable mode) or "%AppData%\OpenMPT\"
  123. mpt::PathString m_szConfigFileName;
  124. mpt::PathString m_szPluginCacheFileName;
  125. std::shared_ptr<mpt::Wine::Context> m_Wine;
  126. mpt::PathString m_WineWrapperDllName;
  127. // Default macro configuration
  128. MIDIMacroConfig m_MidiCfg;
  129. DWORD m_dwLastPluginIdleCall = 0;
  130. bool m_bInstallerMode = false;
  131. bool m_bPortableMode = false;
  132. bool m_bSourceTreeMode = false;
  133. public:
  134. CTrackApp();
  135. CDataRecoveryHandler *GetDataRecoveryHandler() override;
  136. void AddToRecentFileList(LPCTSTR lpszPathName) override;
  137. void AddToRecentFileList(const mpt::PathString &path);
  138. /// Removes item from MRU-list; most recent item has index zero.
  139. void RemoveMruItem(const size_t item);
  140. void RemoveMruItem(const mpt::PathString &path);
  141. public:
  142. bool IsMultiArchInstall() const { return m_InstallPath == m_InstallBinArchPath; }
  143. mpt::PathString GetInstallPath() const { return m_InstallPath; } // i.e. "C:\Program Files\OpenMPT\" (installer mode) or "G:\OpenMPT\" (portable mode)
  144. mpt::PathString GetInstallBinPath() const { return m_InstallBinPath; } // i.e. "C:\Program Files\OpenMPT\bin\" (multi-arch mode) or InstallPath (legacy mode)
  145. mpt::PathString GetInstallBinArchPath() const { return m_InstallBinArchPath; } // i.e. "C:\Program Files\OpenMPT\bin\amd64\" (multi-arch mode) or InstallPath (legacy mode)
  146. mpt::PathString GetInstallPkgPath() const { return m_InstallPkgPath; } // i.e. "C:\Program Files\OpenMPT\" (installer mode) or "G:\OpenMPT\" (portable mode)
  147. static MODTYPE GetDefaultDocType() { return m_nDefaultDocType; }
  148. static void SetDefaultDocType(MODTYPE n) { m_nDefaultDocType = n; }
  149. static MidiLibrary &GetMidiLibrary() { return midiLibrary; }
  150. static void ImportMidiConfig(const mpt::PathString &filename, bool hideWarning = false);
  151. static void ExportMidiConfig(const mpt::PathString &filename);
  152. static void ImportMidiConfig(SettingsContainer &file, const mpt::PathString &path, bool forgetSettings = false);
  153. static void ExportMidiConfig(SettingsContainer &file);
  154. static std::future<std::vector<std::unique_ptr<CDLSBank>>> LoadDefaultDLSBanks();
  155. static void SaveDefaultDLSBanks();
  156. static void RemoveDLSBank(UINT nBank);
  157. static bool AddDLSBank(const mpt::PathString &filename);
  158. static bool OpenURL(const char *url); // UTF8
  159. static bool OpenURL(const std::string &url); // UTF8
  160. static bool OpenURL(const CString &url);
  161. static bool OpenURL(const mpt::ustring &url);
  162. static bool OpenURL(const mpt::PathString &lpszURL);
  163. static bool OpenFile(const mpt::PathString &file) { return OpenURL(file); };
  164. static bool OpenDirectory(const mpt::PathString &directory) { return OpenURL(directory); };
  165. // Retrieve the user-supplied MIDI port name for a MIDI input or output port.
  166. mpt::ustring GetFriendlyMIDIPortName(const mpt::ustring &deviceName, bool isInputPort, bool addDeviceName = true);
  167. CString GetFriendlyMIDIPortName(const CString &deviceName, bool isInputPort, bool addDeviceName = true);
  168. int GetOpenDocumentCount() const;
  169. std::vector<CModDoc *> GetOpenDocuments() const;
  170. public:
  171. inline mpt::recursive_mutex_with_lock_count &GetGlobalMutexRef() { return m_GlobalMutex; }
  172. bool InGuiThread() const { return GetCurrentThreadId() == m_GuiThreadId; }
  173. mpt::random_device &RandomDevice() { return *m_RD; }
  174. mpt::thread_safe_prng<mpt::default_prng> &PRNG() { return *m_PRNG; }
  175. CModDocTemplate *GetModDocTemplate() const { return m_pModTemplate; }
  176. CVstPluginManager *GetPluginManager() const { return m_pPluginManager; }
  177. SoundDevice::Manager *GetSoundDevicesManager() const { return m_pSoundDevicesManager.get(); }
  178. void GetDefaultMidiMacro(MIDIMacroConfig &cfg) const { cfg = m_MidiCfg; }
  179. void SetDefaultMidiMacro(const MIDIMacroConfig &cfg) { m_MidiCfg = cfg; }
  180. mpt::PathString GetConfigFileName() const { return m_szConfigFileName; }
  181. SettingsContainer *GetpSettings()
  182. {
  183. return m_pSettings;
  184. }
  185. SettingsContainer &GetSettings()
  186. {
  187. ASSERT(m_pSettings);
  188. return *m_pSettings;
  189. }
  190. TrackerSettings &GetTrackerSettings()
  191. {
  192. ASSERT(m_pTrackerSettings);
  193. return *m_pTrackerSettings;
  194. }
  195. bool IsInstallerMode() const
  196. {
  197. return m_bInstallerMode;
  198. }
  199. bool IsPortableMode() const
  200. {
  201. return m_bPortableMode;
  202. }
  203. bool IsSourceTreeMode() const
  204. {
  205. return m_bSourceTreeMode;
  206. }
  207. SettingsContainer &GetPluginCache()
  208. {
  209. ASSERT(m_pPluginCache);
  210. return *m_pPluginCache;
  211. }
  212. SettingsContainer &GetSongSettings()
  213. {
  214. ASSERT(m_pSongSettings);
  215. return *m_pSongSettings;
  216. }
  217. const mpt::PathString &GetSongSettingsFilename() const
  218. {
  219. return m_pSongSettingsIniFile->GetFilename();
  220. }
  221. void SetWineVersion(std::shared_ptr<mpt::OS::Wine::VersionContext> wineVersion)
  222. {
  223. MPT_ASSERT_ALWAYS(mpt::OS::Windows::IsWine());
  224. m_WineVersion = wineVersion;
  225. }
  226. std::shared_ptr<mpt::OS::Wine::VersionContext> GetWineVersion() const
  227. {
  228. MPT_ASSERT_ALWAYS(mpt::OS::Windows::IsWine());
  229. MPT_ASSERT_ALWAYS(m_WineVersion); // Verify initialization order. We should not should reach this until after Wine is detected.
  230. return m_WineVersion;
  231. }
  232. void SetWine(std::shared_ptr<mpt::Wine::Context> wine)
  233. {
  234. m_Wine = wine;
  235. }
  236. std::shared_ptr<mpt::Wine::Context> GetWine() const
  237. {
  238. return m_Wine;
  239. }
  240. void SetWineWrapperDllFilename(mpt::PathString filename)
  241. {
  242. m_WineWrapperDllName = filename;
  243. }
  244. mpt::PathString GetWineWrapperDllFilename() const
  245. {
  246. return m_WineWrapperDllName;
  247. }
  248. /// Returns path to config folder including trailing '\'.
  249. mpt::PathString GetConfigPath() const { return m_ConfigPath; }
  250. void SetupPaths(bool overridePortable);
  251. void CreatePaths();
  252. #if !defined(MPT_BUILD_RETRO)
  253. bool CheckSystemSupport();
  254. #endif // !MPT_BUILD_RETRO
  255. // Relative / absolute paths conversion
  256. mpt::PathString PathAbsoluteToInstallRelative(const mpt::PathString &path) { return path.AbsolutePathToRelative(GetInstallPath()); }
  257. mpt::PathString PathInstallRelativeToAbsolute(const mpt::PathString &path) { return path.RelativePathToAbsolute(GetInstallPath()); }
  258. mpt::PathString PathAbsoluteToInstallBinArchRelative(const mpt::PathString &path) { return path.AbsolutePathToRelative(GetInstallBinArchPath()); }
  259. mpt::PathString PathInstallBinArchRelativeToAbsolute(const mpt::PathString &path) { return path.RelativePathToAbsolute(GetInstallBinArchPath()); }
  260. static void OpenModulesDialog(std::vector<mpt::PathString> &files, const mpt::PathString &overridePath = mpt::PathString());
  261. public:
  262. // Get name of resampling mode. addTaps = true also adds the number of taps the filter uses.
  263. static CString GetResamplingModeName(ResamplingMode mode, int length, bool addTaps);
  264. // Overrides
  265. public:
  266. // ClassWizard generated virtual function overrides
  267. //{{AFX_VIRTUAL(CTrackApp)
  268. public:
  269. BOOL InitInstance() override;
  270. BOOL InitInstanceEarly(CMPTCommandLineInfo &cmdInfo);
  271. BOOL InitInstanceLate(CMPTCommandLineInfo &cmdInfo);
  272. BOOL InitInstanceImpl(CMPTCommandLineInfo &cmdInfo);
  273. int Run() override;
  274. LRESULT ProcessWndProcException(CException *e, const MSG *pMsg) override;
  275. int ExitInstance() override;
  276. int ExitInstanceImpl();
  277. BOOL OnIdle(LONG lCount) override;
  278. //}}AFX_VIRTUAL
  279. // Implementation
  280. //{{AFX_MSG(CTrackApp)
  281. CModDoc *NewDocument(MODTYPE newType = MOD_TYPE_NONE);
  282. afx_msg void OnFileNew() { NewDocument(); }
  283. afx_msg void OnFileNewMOD() { NewDocument(MOD_TYPE_MOD); }
  284. afx_msg void OnFileNewS3M() { NewDocument(MOD_TYPE_S3M); }
  285. afx_msg void OnFileNewXM() { NewDocument(MOD_TYPE_XM); }
  286. afx_msg void OnFileNewIT() { NewDocument(MOD_TYPE_IT); }
  287. afx_msg void OnFileNewMPT() { NewDocument(MOD_TYPE_MPT); }
  288. afx_msg void OnFileOpen();
  289. afx_msg void OnAppAbout();
  290. afx_msg void OnFileCloseAll();
  291. afx_msg void OnUpdateAnyDocsOpen(CCmdUI *cmd);
  292. //}}AFX_MSG
  293. DECLARE_MESSAGE_MAP()
  294. protected:
  295. size_t AddScannedDLSBanks();
  296. void InitializeDXPlugins();
  297. void UninitializeDXPlugins();
  298. bool MoveConfigFile(const mpt::PathString &fileName, mpt::PathString subDir = {}, mpt::PathString newFileName = {});
  299. };
  300. extern CTrackApp theApp;
  301. //////////////////////////////////////////////////////////////////
  302. // More Bitmap Helpers
  303. class CFastBitmap
  304. {
  305. protected:
  306. static constexpr uint8 BLEND_OFFSET = 0x80;
  307. struct MODPLUGFASTDIB
  308. {
  309. BITMAPINFOHEADER bmiHeader;
  310. RGBQUAD bmiColors[256];
  311. std::vector<uint8> DibBits;
  312. };
  313. MODPLUGFASTDIB m_Dib;
  314. UINT m_nTextColor, m_nBkColor;
  315. MODPLUGDIB *m_pTextDib;
  316. uint8 m_nBlendOffset;
  317. uint8 m_n4BitPalette[16];
  318. uint8 m_nXShiftFactor;
  319. public:
  320. CFastBitmap() {}
  321. public:
  322. void Init(MODPLUGDIB *lpTextDib = nullptr);
  323. void Blit(HDC hdc, int x, int y, int cx, int cy);
  324. void Blit(HDC hdc, LPCRECT lprc) { Blit(hdc, lprc->left, lprc->top, lprc->right - lprc->left, lprc->bottom - lprc->top); }
  325. void SetTextColor(int nText, int nBk = -1)
  326. {
  327. m_nTextColor = nText;
  328. if(nBk >= 0)
  329. m_nBkColor = nBk;
  330. }
  331. void SetTextBkColor(UINT nBk) { m_nBkColor = nBk; }
  332. void SetColor(UINT nIndex, COLORREF cr);
  333. void SetAllColors(UINT nBaseIndex, UINT nColors, COLORREF *pcr);
  334. void TextBlt(int x, int y, int cx, int cy, int srcx, int srcy, MODPLUGDIB *lpdib = nullptr);
  335. void SetBlendMode(bool enable) { m_nBlendOffset = enable ? BLEND_OFFSET : 0; }
  336. bool GetBlendMode() const { return m_nBlendOffset != 0; }
  337. void SetBlendColor(COLORREF cr);
  338. void SetSize(int x, int y);
  339. int GetWidth() const { return m_Dib.bmiHeader.biWidth; }
  340. };
  341. ///////////////////////////////////////////////////
  342. // 4-bit DIB Drawing functions
  343. void DibBlt(HDC hdc, int x, int y, int sizex, int sizey, int srcx, int srcy, MODPLUGDIB *lpdib);
  344. MODPLUGDIB *LoadDib(LPCTSTR lpszName);
  345. RGBQUAD rgb2quad(COLORREF c);
  346. // Other bitmap functions
  347. int DrawTextT(HDC hdc, const wchar_t *lpchText, int cchText, LPRECT lprc, UINT format);
  348. int DrawTextT(HDC hdc, const char *lpchText, int cchText, LPRECT lprc, UINT format);
  349. void DrawButtonRect(HDC hdc, const RECT *lpRect, LPCSTR lpszText = nullptr, BOOL bDisabled = FALSE, BOOL bPushed = FALSE, DWORD dwFlags = (DT_CENTER | DT_VCENTER), uint32 topMargin = 0);
  350. void DrawButtonRect(HDC hdc, const RECT *lpRect, LPCWSTR lpszText = nullptr, BOOL bDisabled = FALSE, BOOL bPushed = FALSE, DWORD dwFlags = (DT_CENTER | DT_VCENTER), uint32 topMargin = 0);
  351. // Misc functions
  352. void ErrorBox(UINT nStringID, CWnd *p = nullptr);
  353. // Helper function declarations.
  354. struct SNDMIXPLUGIN;
  355. class IMixPlugin;
  356. void AddPluginNamesToCombobox(CComboBox &CBox, const SNDMIXPLUGIN *plugarray, const bool libraryName = false, const PLUGINDEX updatePlug = PLUGINDEX_INVALID);
  357. void AddPluginParameternamesToCombobox(CComboBox &CBox, SNDMIXPLUGIN &plugarray);
  358. void AddPluginParameternamesToCombobox(CComboBox &CBox, IMixPlugin &plug);
  359. // Append note names in range [noteStart, noteEnd] to given combobox. Index starts from 0.
  360. void AppendNotesToControl(CComboBox &combobox, ModCommand::NOTE noteStart, ModCommand::NOTE noteEnd);
  361. // Append note names to combo box.
  362. // If nInstr is given, instrument-specific note names are used instead of default note names.
  363. // A custom note range may also be specified using the noteStart and noteEnd parameters.
  364. // If they are left out, only notes that are available in the module type, plus any supported "special notes" are added.
  365. void AppendNotesToControlEx(CComboBox &combobox, const CSoundFile &sndFile, INSTRUMENTINDEX nInstr = MAX_INSTRUMENTS, ModCommand::NOTE noteStart = 0, ModCommand::NOTE noteEnd = 0);
  366. // Get window text (e.g. edit box content) as a CString
  367. CString GetWindowTextString(const CWnd &wnd);
  368. // Get window text (e.g. edit box content) as a unicode string
  369. mpt::ustring GetWindowTextUnicode(const CWnd &wnd);
  370. ///////////////////////////////////////////////////
  371. // Tables
  372. extern const TCHAR *szSpecialNoteNamesMPT[];
  373. extern const TCHAR *szSpecialNoteShortDesc[];
  374. extern const char *szHexChar;
  375. // Defined in load_mid.cpp
  376. extern const char *szMidiProgramNames[128];
  377. extern const char *szMidiPercussionNames[61]; // notes 25..85
  378. extern const char *szMidiGroupNames[17]; // 16 groups + Percussions
  379. /////////////////////////////////////////////////////////////////////////////
  380. //{{AFX_INSERT_LOCATION}}
  381. // Microsoft Developer Studio will insert additional declarations immediately before the previous line.
  382. OPENMPT_NAMESPACE_END