1
0

Moddoc.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. /*
  2. * ModDoc.h
  3. * --------
  4. * Purpose: Converting between various module formats.
  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 "Sndfile.h"
  12. #include "../common/misc_util.h"
  13. #include "Undo.h"
  14. #include "Notification.h"
  15. #include "UpdateHints.h"
  16. #include <time.h>
  17. OPENMPT_NAMESPACE_BEGIN
  18. class EncoderFactoryBase;
  19. class CChildFrame;
  20. /////////////////////////////////////////////////////////////////////////
  21. // Split Keyboard Settings (pattern editor)
  22. struct SplitKeyboardSettings
  23. {
  24. enum
  25. {
  26. splitOctaveRange = 9,
  27. };
  28. bool IsSplitActive() const { return (octaveLink && (octaveModifier != 0)) || (splitInstrument != 0) || (splitVolume != 0); }
  29. int octaveModifier = 0; // determines by how many octaves the notes should be transposed up or down
  30. ModCommand::NOTE splitNote = NOTE_MIDDLEC - 1;
  31. ModCommand::INSTR splitInstrument = 0;
  32. ModCommand::VOL splitVolume = 0;
  33. bool octaveLink = false; // apply octaveModifier
  34. };
  35. enum InputTargetContext : int8;
  36. struct LogEntry
  37. {
  38. LogLevel level;
  39. mpt::ustring message;
  40. LogEntry() : level(LogInformation) {}
  41. LogEntry(LogLevel l, const mpt::ustring &m) : level(l), message(m) {}
  42. };
  43. enum LogMode
  44. {
  45. LogModeInstantReporting,
  46. LogModeGather,
  47. };
  48. class ScopedLogCapturer
  49. {
  50. private:
  51. CModDoc &m_modDoc;
  52. LogMode m_oldLogMode;
  53. CString m_title;
  54. CWnd *m_pParent;
  55. bool m_showLog;
  56. public:
  57. ScopedLogCapturer(CModDoc &modDoc, const CString &title = {}, CWnd *parent = nullptr, bool showLog = true);
  58. ~ScopedLogCapturer();
  59. void ShowLog(bool force = false);
  60. void ShowLog(const CString &preamble, bool force = false);
  61. [[deprecated]] void ShowLog(const std::string &preamble, bool force = false);
  62. void ShowLog(const mpt::ustring &preamble, bool force = false);
  63. };
  64. struct PlayNoteParam
  65. {
  66. std::bitset<128> *m_notesPlaying = nullptr;
  67. SmpLength m_loopStart = 0, m_loopEnd = 0, m_sampleOffset = 0;
  68. int32 m_volume = -1;
  69. SAMPLEINDEX m_sample = 0;
  70. INSTRUMENTINDEX m_instr = 0;
  71. CHANNELINDEX m_currentChannel = CHANNELINDEX_INVALID;
  72. ModCommand::NOTE m_note;
  73. PlayNoteParam(ModCommand::NOTE note) : m_note(note) { }
  74. PlayNoteParam& LoopStart(SmpLength loopStart) { m_loopStart = loopStart; return *this; }
  75. PlayNoteParam& LoopEnd(SmpLength loopEnd) { m_loopEnd = loopEnd; return *this; }
  76. PlayNoteParam& Offset(SmpLength sampleOffset) { m_sampleOffset = sampleOffset; return *this; }
  77. PlayNoteParam& Volume(int32 volume) { m_volume = volume; return *this; }
  78. PlayNoteParam& Sample(SAMPLEINDEX sample) { m_sample = sample; return *this; }
  79. PlayNoteParam& Instrument(INSTRUMENTINDEX instr) { m_instr = instr; return *this; }
  80. PlayNoteParam& Channel(CHANNELINDEX channel) { m_currentChannel = channel; return *this; }
  81. PlayNoteParam& CheckNNA(std::bitset<128> &notesPlaying) { m_notesPlaying = &notesPlaying; return *this; }
  82. };
  83. enum class RecordGroup : uint8
  84. {
  85. NoGroup = 0,
  86. Group1 = 1,
  87. Group2 = 2,
  88. };
  89. class CModDoc final : public CDocument
  90. {
  91. protected:
  92. friend ScopedLogCapturer;
  93. mutable std::vector<LogEntry> m_Log;
  94. LogMode m_LogMode = LogModeInstantReporting;
  95. CSoundFile m_SndFile;
  96. HWND m_hWndFollow = nullptr;
  97. FlagSet<Notification::Type, uint16> m_notifyType;
  98. Notification::Item m_notifyItem = 0;
  99. CSize m_szOldPatternScrollbarsPos = { -10, -10 };
  100. CPatternUndo m_PatternUndo;
  101. CSampleUndo m_SampleUndo;
  102. CInstrumentUndo m_InstrumentUndo;
  103. SplitKeyboardSettings m_SplitKeyboardSettings; // this is maybe not the best place to keep them, but it should do the job
  104. time_t m_creationTime;
  105. std::atomic<bool> m_modifiedAutosave = false; // Modified since last autosave?
  106. public:
  107. class NoteToChannelMap : public std::array<CHANNELINDEX, NOTE_MAX - NOTE_MIN + 1>
  108. {
  109. public:
  110. NoteToChannelMap() { fill(CHANNELINDEX_INVALID); }
  111. };
  112. NoteToChannelMap m_noteChannel; // Note -> Preview channel assignment
  113. bool m_ShowSavedialog = false;
  114. bool m_bHasValidPath = false; //becomes true if document is loaded or saved.
  115. protected:
  116. // Note-off event buffer for MIDI sustain pedal
  117. std::array<std::vector<uint32>, 16> m_midiSustainBuffer;
  118. std::array<std::bitset<128>, 16> m_midiPlayingNotes;
  119. std::bitset<16> m_midiSustainActive;
  120. std::bitset<MAX_BASECHANNELS> m_bsMultiRecordMask;
  121. std::bitset<MAX_BASECHANNELS> m_bsMultiSplitRecordMask;
  122. protected: // create from serialization only
  123. CModDoc();
  124. DECLARE_DYNCREATE(CModDoc)
  125. // public members
  126. public:
  127. CSoundFile &GetSoundFile() { return m_SndFile; }
  128. const CSoundFile &GetSoundFile() const { return m_SndFile; }
  129. #if MPT_COMPILER_CLANG
  130. #pragma clang diagnostic push
  131. #pragma clang diagnostic ignored "-Woverloaded-virtual"
  132. #endif // MPT_COMPILER_CLANG
  133. bool IsModified() const { return m_bModified != FALSE; } // Work-around: CDocument::IsModified() is not const...
  134. #if MPT_COMPILER_CLANG
  135. #pragma clang diagnostic pop
  136. #endif // MPT_COMPILER_CLANG
  137. void SetModified(bool modified = true);
  138. bool ModifiedSinceLastAutosave();
  139. void SetShowSaveDialog(bool b) { m_ShowSavedialog = b; }
  140. void PostMessageToAllViews(UINT uMsg, WPARAM wParam = 0, LPARAM lParam = 0);
  141. void SendNotifyMessageToAllViews(UINT uMsg, WPARAM wParam = 0, LPARAM lParam = 0);
  142. void SendMessageToActiveView(UINT uMsg, WPARAM wParam = 0, LPARAM lParam = 0);
  143. MODTYPE GetModType() const { return m_SndFile.m_nType; }
  144. INSTRUMENTINDEX GetNumInstruments() const { return m_SndFile.m_nInstruments; }
  145. SAMPLEINDEX GetNumSamples() const { return m_SndFile.m_nSamples; }
  146. // Logging for general progress and error events.
  147. void AddToLog(LogLevel level, const mpt::ustring &text) const;
  148. /*[[deprecated]]*/ void AddToLog(const CString &text) const { AddToLog(LogInformation, mpt::ToUnicode(text)); }
  149. /*[[deprecated]]*/ void AddToLog(const std::string &text) const { AddToLog(LogInformation, mpt::ToUnicode(mpt::Charset::Locale, text)); }
  150. /*[[deprecated]]*/ void AddToLog(const char *text) const { AddToLog(LogInformation, mpt::ToUnicode(mpt::Charset::Locale, text ? text : "")); }
  151. const std::vector<LogEntry> & GetLog() const { return m_Log; }
  152. mpt::ustring GetLogString() const;
  153. LogLevel GetMaxLogLevel() const;
  154. protected:
  155. LogMode GetLogMode() const { return m_LogMode; }
  156. void SetLogMode(LogMode mode) { m_LogMode = mode; }
  157. void ClearLog();
  158. UINT ShowLog(const CString &preamble, const CString &title = {}, CWnd *parent = nullptr);
  159. UINT ShowLog(const CString &title = {}, CWnd *parent = nullptr) { return ShowLog(_T(""), title, parent); }
  160. public:
  161. void ClearFilePath() { m_strPathName.Empty(); }
  162. void ViewPattern(UINT nPat, UINT nOrd);
  163. void ViewSample(UINT nSmp);
  164. void ViewInstrument(UINT nIns);
  165. HWND GetFollowWnd() const { return m_hWndFollow; }
  166. void SetFollowWnd(HWND hwnd);
  167. void SetNotifications(FlagSet<Notification::Type> type, Notification::Item item = 0) { m_notifyType = type; m_notifyItem = item; }
  168. FlagSet<Notification::Type, uint16> GetNotificationType() const { return m_notifyType; }
  169. Notification::Item GetNotificationItem() const { return m_notifyItem; }
  170. void ActivateWindow();
  171. void OnSongProperties();
  172. void PrepareUndoForAllPatterns(bool storeChannelInfo = false, const char *description = "");
  173. CPatternUndo &GetPatternUndo() { return m_PatternUndo; }
  174. CSampleUndo &GetSampleUndo() { return m_SampleUndo; }
  175. CInstrumentUndo &GetInstrumentUndo() { return m_InstrumentUndo; }
  176. SplitKeyboardSettings &GetSplitKeyboardSettings() { return m_SplitKeyboardSettings; }
  177. time_t GetCreationTime() const { return m_creationTime; }
  178. // operations
  179. public:
  180. bool ChangeModType(MODTYPE wType);
  181. bool ChangeNumChannels(CHANNELINDEX nNewChannels, const bool showCancelInRemoveDlg = true);
  182. bool RemoveChannels(const std::vector<bool> &keepMask, bool verbose = false);
  183. void CheckUsedChannels(std::vector<bool> &usedMask, CHANNELINDEX maxRemoveCount = MAX_BASECHANNELS) const;
  184. CHANNELINDEX ReArrangeChannels(const std::vector<CHANNELINDEX> &fromToArray, const bool createUndoPoint = true);
  185. SAMPLEINDEX ReArrangeSamples(const std::vector<SAMPLEINDEX> &newOrder);
  186. INSTRUMENTINDEX ReArrangeInstruments(const std::vector<INSTRUMENTINDEX> &newOrder, deleteInstrumentSamples removeSamples = doNoDeleteAssociatedSamples);
  187. SEQUENCEINDEX ReArrangeSequences(const std::vector<SEQUENCEINDEX> &newOrder);
  188. bool ConvertInstrumentsToSamples();
  189. bool ConvertSamplesToInstruments();
  190. PLUGINDEX RemovePlugs(const std::vector<bool> &keepMask);
  191. bool RemovePlugin(PLUGINDEX plugin);
  192. void ClonePlugin(SNDMIXPLUGIN &target, const SNDMIXPLUGIN &source);
  193. void AppendModule(const CSoundFile &source);
  194. // Create a new pattern and, if order position is specified, inserts it into the order list.
  195. PATTERNINDEX InsertPattern(ROWINDEX rows, ORDERINDEX ord = ORDERINDEX_INVALID);
  196. SAMPLEINDEX InsertSample();
  197. INSTRUMENTINDEX InsertInstrument(SAMPLEINDEX sample = SAMPLEINDEX_INVALID, INSTRUMENTINDEX duplicateSource = INSTRUMENTINDEX_INVALID, bool silent = false);
  198. INSTRUMENTINDEX InsertInstrumentForPlugin(PLUGINDEX plug);
  199. INSTRUMENTINDEX HasInstrumentForPlugin(PLUGINDEX plug) const;
  200. void InitializeInstrument(ModInstrument *pIns);
  201. bool RemoveOrder(SEQUENCEINDEX nSeq, ORDERINDEX nOrd);
  202. bool RemovePattern(PATTERNINDEX nPat);
  203. bool RemoveSample(SAMPLEINDEX nSmp);
  204. bool RemoveInstrument(INSTRUMENTINDEX nIns);
  205. void ProcessMIDI(uint32 midiData, INSTRUMENTINDEX ins, IMixPlugin *plugin, InputTargetContext ctx);
  206. CHANNELINDEX PlayNote(PlayNoteParam &params, NoteToChannelMap *noteChannel = nullptr);
  207. bool NoteOff(UINT note, bool fade = false, INSTRUMENTINDEX ins = INSTRUMENTINDEX_INVALID, CHANNELINDEX currentChn = CHANNELINDEX_INVALID);
  208. void CheckNNA(ModCommand::NOTE note, INSTRUMENTINDEX ins, std::bitset<128> &playingNotes);
  209. void UpdateOPLInstrument(SAMPLEINDEX smp);
  210. bool IsNotePlaying(UINT note, SAMPLEINDEX nsmp = 0, INSTRUMENTINDEX nins = 0);
  211. bool MuteChannel(CHANNELINDEX nChn, bool bMute);
  212. bool UpdateChannelMuteStatus(CHANNELINDEX nChn);
  213. bool MuteSample(SAMPLEINDEX nSample, bool bMute);
  214. bool MuteInstrument(INSTRUMENTINDEX nInstr, bool bMute);
  215. // Returns true if toggling the mute status of a channel should set the document as modified given the current module format and settings.
  216. bool MuteToggleModifiesDocument() const;
  217. bool SoloChannel(CHANNELINDEX nChn, bool bSolo);
  218. bool IsChannelSolo(CHANNELINDEX nChn) const;
  219. bool SurroundChannel(CHANNELINDEX nChn, bool bSurround);
  220. bool SetChannelGlobalVolume(CHANNELINDEX nChn, uint16 nVolume);
  221. bool SetChannelDefaultPan(CHANNELINDEX nChn, uint16 nPan);
  222. bool IsChannelMuted(CHANNELINDEX nChn) const;
  223. bool IsSampleMuted(SAMPLEINDEX nSample) const;
  224. bool IsInstrumentMuted(INSTRUMENTINDEX nInstr) const;
  225. bool NoFxChannel(CHANNELINDEX nChn, bool bNoFx, bool updateMix = true);
  226. bool IsChannelNoFx(CHANNELINDEX nChn) const;
  227. RecordGroup GetChannelRecordGroup(CHANNELINDEX channel) const;
  228. void SetChannelRecordGroup(CHANNELINDEX channel, RecordGroup recordGroup);
  229. void ToggleChannelRecordGroup(CHANNELINDEX channel, RecordGroup recordGroup);
  230. void ReinitRecordState(bool unselect = true);
  231. CHANNELINDEX GetNumChannels() const { return m_SndFile.m_nChannels; }
  232. UINT GetPatternSize(PATTERNINDEX nPat) const;
  233. bool IsChildSample(INSTRUMENTINDEX nIns, SAMPLEINDEX nSmp) const;
  234. INSTRUMENTINDEX FindSampleParent(SAMPLEINDEX sample) const;
  235. SAMPLEINDEX FindInstrumentChild(INSTRUMENTINDEX nIns) const;
  236. bool MoveOrder(ORDERINDEX nSourceNdx, ORDERINDEX nDestNdx, bool bUpdate = true, bool bCopy = false, SEQUENCEINDEX nSourceSeq = SEQUENCEINDEX_INVALID, SEQUENCEINDEX nDestSeq = SEQUENCEINDEX_INVALID);
  237. BOOL ExpandPattern(PATTERNINDEX nPattern);
  238. BOOL ShrinkPattern(PATTERNINDEX nPattern);
  239. bool SetDefaultChannelColors() { return SetDefaultChannelColors(0, GetNumChannels()); }
  240. bool SetDefaultChannelColors(CHANNELINDEX channel) { return SetDefaultChannelColors(channel, channel + 1u); }
  241. bool SetDefaultChannelColors(CHANNELINDEX minChannel, CHANNELINDEX maxChannel);
  242. bool SupportsChannelColors() const { return GetModType() & (MOD_TYPE_XM | MOD_TYPE_IT | MOD_TYPE_MPT); }
  243. bool CopyEnvelope(INSTRUMENTINDEX nIns, EnvelopeType nEnv);
  244. bool SaveEnvelope(INSTRUMENTINDEX nIns, EnvelopeType nEnv, const mpt::PathString &fileName);
  245. bool PasteEnvelope(INSTRUMENTINDEX nIns, EnvelopeType nEnv);
  246. bool LoadEnvelope(INSTRUMENTINDEX nIns, EnvelopeType nEnv, const mpt::PathString &fileName);
  247. LRESULT ActivateView(UINT nIdView, DWORD dwParam);
  248. // Notify all views of document updates (GUI thread only)
  249. void UpdateAllViews(CView *pSender, UpdateHint hint, CObject *pHint=NULL);
  250. // Notify all views of document updates (for non-GUI threads)
  251. void UpdateAllViews(UpdateHint hint);
  252. void GetEditPosition(ROWINDEX &row, PATTERNINDEX &pat, ORDERINDEX &ord);
  253. LRESULT OnCustomKeyMsg(WPARAM, LPARAM);
  254. void TogglePluginEditor(UINT m_nCurrentPlugin, bool onlyThisEditor = false);
  255. void RecordParamChange(PLUGINDEX slot, PlugParamIndex param);
  256. void LearnMacro(int macro, PlugParamIndex param);
  257. void SetElapsedTime(ORDERINDEX nOrd, ROWINDEX nRow, bool setSamplePos);
  258. void SetLoopSong(bool loop);
  259. // Global settings to pattern effect conversion
  260. bool GlobalVolumeToPattern();
  261. bool HasMPTHacks(const bool autofix = false);
  262. void FixNullStrings();
  263. // Fix: save pattern scrollbar position when switching to other tab
  264. CSize GetOldPatternScrollbarsPos() const { return m_szOldPatternScrollbarsPos; };
  265. void SetOldPatternScrollbarsPos( CSize s ){ m_szOldPatternScrollbarsPos = s; };
  266. void OnFileWaveConvert(ORDERINDEX nMinOrder, ORDERINDEX nMaxOrder);
  267. void OnFileWaveConvert(ORDERINDEX nMinOrder, ORDERINDEX nMaxOrder, const std::vector<EncoderFactoryBase*> &encFactories);
  268. // Returns formatted ModInstrument name.
  269. // [in] bEmptyInsteadOfNoName: In case of unnamed instrument string, "(no name)" is returned unless this
  270. // parameter is true is case which an empty name is returned.
  271. // [in] bIncludeIndex: True to include instrument index in front of the instrument name, false otherwise.
  272. CString GetPatternViewInstrumentName(INSTRUMENTINDEX nInstr, bool bEmptyInsteadOfNoName = false, bool bIncludeIndex = true) const;
  273. // Check if a given channel contains data.
  274. bool IsChannelUnused(CHANNELINDEX nChn) const;
  275. // Check whether a sample is used.
  276. // In sample mode, the sample numbers in all patterns are checked.
  277. // In instrument mode, it is only checked if a sample is referenced by an instrument (but not if the sample is actually played anywhere)
  278. bool IsSampleUsed(SAMPLEINDEX sample, bool searchInMutedChannels = true) const;
  279. // Check whether an instrument is used (only for instrument mode).
  280. bool IsInstrumentUsed(INSTRUMENTINDEX instr, bool searchInMutedChannels = true) const;
  281. // protected members
  282. protected:
  283. void InitializeMod();
  284. CChildFrame *GetChildFrame(); //rewbs.customKeys
  285. // Overrides
  286. // ClassWizard generated virtual function overrides
  287. //{{AFX_VIRTUAL(CModDoc)
  288. public:
  289. BOOL OnNewDocument() override;
  290. BOOL OnOpenDocument(LPCTSTR lpszPathName) override;
  291. BOOL OnSaveDocument(LPCTSTR lpszPathName) override
  292. {
  293. return OnSaveDocument(lpszPathName ? mpt::PathString::FromCString(lpszPathName) : mpt::PathString()) ? TRUE : FALSE;
  294. }
  295. void OnCloseDocument() override;
  296. void SafeFileClose();
  297. bool OnSaveDocument(const mpt::PathString &filename, const bool setPath = true);
  298. #if MPT_COMPILER_CLANG
  299. #pragma clang diagnostic push
  300. #pragma clang diagnostic ignored "-Woverloaded-virtual"
  301. #endif // MPT_COMPILER_CLANG
  302. void SetPathName(const mpt::PathString &filename, BOOL bAddToMRU = TRUE)
  303. {
  304. CDocument::SetPathName(filename.ToCString(), bAddToMRU);
  305. }
  306. #if MPT_COMPILER_CLANG
  307. #pragma clang diagnostic pop
  308. #endif // MPT_COMPILER_CLANG
  309. mpt::PathString GetPathNameMpt() const
  310. {
  311. return mpt::PathString::FromCString(GetPathName());
  312. }
  313. BOOL SaveModified() override;
  314. bool SaveAllSamples(bool showPrompt = true);
  315. bool SaveSample(SAMPLEINDEX smp);
  316. BOOL DoSave(LPCTSTR lpszPathName, BOOL /*bSaveAs*/ = TRUE) override
  317. {
  318. return DoSave(lpszPathName ? mpt::PathString::FromCString(lpszPathName) : mpt::PathString());
  319. }
  320. BOOL DoSave(const mpt::PathString &filename, bool setPath = true);
  321. void DeleteContents() override;
  322. //}}AFX_VIRTUAL
  323. // Get the sample index for the current pattern cell (resolves instrument note maps, etc)
  324. SAMPLEINDEX GetSampleIndex(const ModCommand &m, ModCommand::INSTR lastInstr = 0) const;
  325. // Get group (octave) size from given instrument (or sample in sample mode)
  326. int GetInstrumentGroupSize(INSTRUMENTINDEX instr) const;
  327. int GetBaseNote(INSTRUMENTINDEX instr) const;
  328. ModCommand::NOTE GetNoteWithBaseOctave(int noteOffset, INSTRUMENTINDEX instr) const;
  329. // Convert a linear volume property to decibels
  330. static CString LinearToDecibels(double value, double valueAtZeroDB);
  331. // Convert a panning value to a more readable string
  332. static CString PanningToString(int32 value, int32 valueAtCenter);
  333. void SerializeViews() const;
  334. void DeserializeViews();
  335. // View MIDI Mapping dialog for given plugin and parameter combination.
  336. void ViewMIDIMapping(PLUGINDEX plugin = PLUGINDEX_INVALID, PlugParamIndex param = 0);
  337. // Implementation
  338. public:
  339. virtual ~CModDoc();
  340. // Generated message map functions
  341. public:
  342. //{{AFX_MSG(CModDoc)
  343. afx_msg void OnFileWaveConvert();
  344. afx_msg void OnFileMidiConvert();
  345. afx_msg void OnFileOPLExport();
  346. afx_msg void OnFileCompatibilitySave();
  347. afx_msg void OnPlayerPlay();
  348. afx_msg void OnPlayerStop();
  349. afx_msg void OnPlayerPause();
  350. afx_msg void OnPlayerPlayFromStart();
  351. afx_msg void OnPanic();
  352. afx_msg void OnEditGlobals();
  353. afx_msg void OnEditPatterns();
  354. afx_msg void OnEditSamples();
  355. afx_msg void OnEditInstruments();
  356. afx_msg void OnEditComments();
  357. afx_msg void OnShowCleanup();
  358. afx_msg void OnShowSampleTrimmer();
  359. afx_msg void OnSetupZxxMacros();
  360. afx_msg void OnEstimateSongLength();
  361. afx_msg void OnApproximateBPM();
  362. afx_msg void OnUpdateXMITMPTOnly(CCmdUI *p);
  363. afx_msg void OnUpdateHasEditHistory(CCmdUI *p);
  364. afx_msg void OnUpdateHasMIDIMappings(CCmdUI *p);
  365. afx_msg void OnUpdateCompatExportableOnly(CCmdUI *p);
  366. afx_msg void OnPatternRestart() { OnPatternRestart(true); } //rewbs.customKeys
  367. afx_msg void OnPatternRestart(bool loop); //rewbs.customKeys
  368. afx_msg void OnPatternPlay(); //rewbs.customKeys
  369. afx_msg void OnPatternPlayNoLoop(); //rewbs.customKeys
  370. afx_msg void OnViewEditHistory();
  371. afx_msg void OnViewMPTHacks();
  372. afx_msg void OnViewTempoSwingSettings();
  373. afx_msg void OnSaveCopy();
  374. afx_msg void OnSaveTemplateModule();
  375. afx_msg void OnAppendModule();
  376. afx_msg void OnViewMIDIMapping() { ViewMIDIMapping(); }
  377. afx_msg void OnChannelManager();
  378. //}}AFX_MSG
  379. DECLARE_MESSAGE_MAP()
  380. private:
  381. void ChangeFileExtension(MODTYPE nNewType);
  382. CHANNELINDEX FindAvailableChannel() const;
  383. };
  384. /////////////////////////////////////////////////////////////////////////////
  385. //{{AFX_INSERT_LOCATION}}
  386. // Microsoft Developer Studio will insert additional declarations immediately before the previous line.
  387. OPENMPT_NAMESPACE_END