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