MIDIMacros.h 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /*
  2. * MIDIMacros.h
  3. * ------------
  4. * Purpose: Helper functions / classes for MIDI Macro functionality.
  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 "openmpt/base/Endian.hpp"
  12. OPENMPT_NAMESPACE_BEGIN
  13. enum
  14. {
  15. kGlobalMacros = 9, // Number of global macros
  16. kSFxMacros = 16, // Number of parametered macros
  17. kZxxMacros = 128, // Number of fixed macros
  18. kMacroLength = 32, // Max number of chars per macro
  19. };
  20. OPENMPT_NAMESPACE_END
  21. #ifdef MODPLUG_TRACKER
  22. #include "plugins/PluginStructs.h"
  23. #endif // MODPLUG_TRACKER
  24. OPENMPT_NAMESPACE_BEGIN
  25. // Parametered macro presets
  26. enum ParameteredMacro
  27. {
  28. kSFxUnused = 0,
  29. kSFxCutoff, // Z00 - Z7F controls resonant filter cutoff
  30. kSFxReso, // Z00 - Z7F controls resonant filter resonance
  31. kSFxFltMode, // Z00 - Z7F controls resonant filter mode (lowpass / highpass)
  32. kSFxDryWet, // Z00 - Z7F controls plugin Dry / Wet ratio
  33. kSFxPlugParam, // Z00 - Z7F controls a plugin parameter
  34. kSFxCC, // Z00 - Z7F controls MIDI CC
  35. kSFxChannelAT, // Z00 - Z7F controls Channel Aftertouch
  36. kSFxPolyAT, // Z00 - Z7F controls Poly Aftertouch
  37. kSFxPitch, // Z00 - Z7F controls Pitch Bend
  38. kSFxProgChange, // Z00 - Z7F controls MIDI Program Change
  39. kSFxCustom,
  40. kSFxMax
  41. };
  42. // Fixed macro presets
  43. enum FixedMacro
  44. {
  45. kZxxUnused = 0,
  46. kZxxReso4Bit, // Z80 - Z8F controls resonant filter resonance
  47. kZxxReso7Bit, // Z80 - ZFF controls resonant filter resonance
  48. kZxxCutoff, // Z80 - ZFF controls resonant filter cutoff
  49. kZxxFltMode, // Z80 - ZFF controls resonant filter mode (lowpass / highpass)
  50. kZxxResoFltMode, // Z80 - Z9F controls resonance + filter mode
  51. kZxxChannelAT, // Z80 - ZFF controls Channel Aftertouch
  52. kZxxPolyAT, // Z80 - ZFF controls Poly Aftertouch
  53. kZxxPitch, // Z80 - ZFF controls Pitch Bend
  54. kZxxProgChange, // Z80 - ZFF controls MIDI Program Change
  55. kZxxCustom,
  56. kZxxMax
  57. };
  58. // Global macro types
  59. enum GlobalMacro
  60. {
  61. MIDIOUT_START = 0,
  62. MIDIOUT_STOP,
  63. MIDIOUT_TICK,
  64. MIDIOUT_NOTEON,
  65. MIDIOUT_NOTEOFF,
  66. MIDIOUT_VOLUME,
  67. MIDIOUT_PAN,
  68. MIDIOUT_BANKSEL,
  69. MIDIOUT_PROGRAM,
  70. };
  71. struct MIDIMacroConfigData
  72. {
  73. struct Macro
  74. {
  75. public:
  76. Macro &operator=(const Macro &other) = default;
  77. Macro &operator=(const std::string_view other) noexcept
  78. {
  79. const size_t copyLength = std::min({m_data.size() - 1u, other.size(), other.find('\0')});
  80. std::copy(other.begin(), other.begin() + copyLength, m_data.begin());
  81. m_data[copyLength] = '\0';
  82. Sanitize();
  83. return *this;
  84. }
  85. bool operator==(const Macro &other) const noexcept
  86. {
  87. return m_data == other.m_data; // Don't care about data past null-terminator as operator= and Sanitize() ensure there is no data behind it.
  88. }
  89. bool operator!=(const Macro &other) const noexcept
  90. {
  91. return !(*this == other);
  92. }
  93. operator mpt::span<const char>() const noexcept
  94. {
  95. return {m_data.data(), Length()};
  96. }
  97. operator std::string_view() const noexcept
  98. {
  99. return {m_data.data(), Length()};
  100. }
  101. operator std::string() const
  102. {
  103. return {m_data.data(), Length()};
  104. }
  105. MPT_CONSTEXPR20_FUN size_t Length() const noexcept
  106. {
  107. return static_cast<size_t>(std::distance(m_data.begin(), std::find(m_data.begin(), m_data.end(), '\0')));
  108. }
  109. MPT_CONSTEXPR20_FUN void Clear() noexcept
  110. {
  111. m_data.fill('\0');
  112. }
  113. // Remove blanks and other unwanted characters from macro strings for internal usage.
  114. std::string NormalizedString() const;
  115. void Sanitize() noexcept;
  116. void UpgradeLegacyMacro() noexcept;
  117. private:
  118. std::array<char, kMacroLength> m_data;
  119. };
  120. std::array<Macro, kGlobalMacros> Global;
  121. std::array<Macro, kSFxMacros> SFx; // Parametered macros for Z00...Z7F
  122. std::array<Macro, kZxxMacros> Zxx; // Fixed macros Z80...ZFF
  123. constexpr Macro *begin() noexcept {return Global.data(); }
  124. constexpr const Macro *begin() const noexcept { return Global.data(); }
  125. constexpr Macro *end() noexcept { return Zxx.data() + Zxx.size(); }
  126. constexpr const Macro *end() const noexcept { return Zxx.data() + Zxx.size(); }
  127. };
  128. // This is directly written to files, so the size must be correct!
  129. MPT_BINARY_STRUCT(MIDIMacroConfigData::Macro, 32)
  130. MPT_BINARY_STRUCT(MIDIMacroConfigData, 4896)
  131. class MIDIMacroConfig : public MIDIMacroConfigData
  132. {
  133. public:
  134. MIDIMacroConfig() { Reset(); }
  135. // Get macro type from a macro string
  136. ParameteredMacro GetParameteredMacroType(uint32 macroIndex) const;
  137. FixedMacro GetFixedMacroType() const;
  138. // Create a new macro
  139. protected:
  140. void CreateParameteredMacro(Macro &parameteredMacro, ParameteredMacro macroType, int subType) const;
  141. public:
  142. void CreateParameteredMacro(uint32 macroIndex, ParameteredMacro macroType, int subType = 0)
  143. {
  144. if(macroIndex < std::size(SFx))
  145. CreateParameteredMacro(SFx[macroIndex], macroType, subType);
  146. }
  147. std::string CreateParameteredMacro(ParameteredMacro macroType, int subType = 0) const;
  148. protected:
  149. void CreateFixedMacro(std::array<Macro, kZxxMacros> &fixedMacros, FixedMacro macroType) const;
  150. public:
  151. void CreateFixedMacro(FixedMacro macroType)
  152. {
  153. CreateFixedMacro(Zxx, macroType);
  154. }
  155. bool operator==(const MIDIMacroConfig &other) const;
  156. bool operator!=(const MIDIMacroConfig &other) const { return !(*this == other); }
  157. #ifdef MODPLUG_TRACKER
  158. // Translate macro type or macro string to macro name
  159. CString GetParameteredMacroName(uint32 macroIndex, IMixPlugin *plugin = nullptr) const;
  160. CString GetParameteredMacroName(ParameteredMacro macroType) const;
  161. CString GetFixedMacroName(FixedMacro macroType) const;
  162. // Extract information from a parametered macro string.
  163. PlugParamIndex MacroToPlugParam(uint32 macroIndex) const;
  164. int MacroToMidiCC(uint32 macroIndex) const;
  165. // Check if any macro can automate a given plugin parameter
  166. int FindMacroForParam(PlugParamIndex param) const;
  167. #endif // MODPLUG_TRACKER
  168. // Check if a given set of macros is the default IT macro set.
  169. bool IsMacroDefaultSetupUsed() const;
  170. // Reset MIDI macro config to default values.
  171. void Reset();
  172. // Clear all Zxx macros so that they do nothing.
  173. void ClearZxxMacros();
  174. // Sanitize all macro config strings.
  175. void Sanitize();
  176. // Fix old-format (not conforming to IT's MIDI macro definitions) MIDI config strings.
  177. void UpgradeMacros();
  178. };
  179. static_assert(sizeof(MIDIMacroConfig) == sizeof(MIDIMacroConfigData)); // this is directly written to files, so the size must be correct!
  180. OPENMPT_NAMESPACE_END