Line data Source code
1 : #pragma once
2 :
3 : #include <cstdint>
4 : #include <string>
5 : #include <vector>
6 :
7 : namespace Amplitron {
8 :
9 : class IAudioEngine;
10 :
11 : // Raw MIDI event pushed from the RtMidi callback thread.
12 48640 : struct MidiEvent {
13 : uint8_t status; // e.g. 0xB0 = CC on channel 0
14 : uint8_t data1; // CC number (0-127)
15 : uint8_t data2; // CC value (0-127)
16 24320 : uint8_t pad = 0; // Pad to 4 bytes
17 : };
18 :
19 : enum class MidiMappingMode : uint8_t {
20 : Continuous, // CC 0-127 maps linearly to param [min..max]
21 : Toggle, // CC >= 64 -> on, CC < 64 -> off
22 : };
23 :
24 : enum class MidiTargetType : uint8_t {
25 : EffectParam, // Maps to a specific effect parameter
26 : EffectBypass, // Maps to effect enabled/disabled
27 : InputGain, // Maps to master input gain
28 : OutputGain, // Maps to master output gain
29 : };
30 :
31 595 : struct MidiMapping {
32 92 : int cc_number = 0; // 0-127
33 92 : int midi_channel = -1; // 0-15, or -1 for "any channel"
34 92 : MidiTargetType target_type = MidiTargetType::EffectParam;
35 92 : MidiMappingMode mode = MidiMappingMode::Continuous;
36 :
37 : std::string effect_name; // For EffectParam/EffectBypass targets
38 : std::string param_name; // For EffectParam targets only
39 92 : mutable bool last_state = false; // Tracks pedal state for Toggle mode
40 : };
41 :
42 : /**
43 : * @brief Abstract interface for MIDI port management.
44 : * Satisfies the Interface Segregation Principle (ISP).
45 : */
46 95 : class IMidiPortManager {
47 : public:
48 285 : virtual ~IMidiPortManager() = default;
49 :
50 : virtual std::vector<std::string> get_available_ports() const = 0;
51 : virtual bool open_port(int port_index) = 0;
52 : virtual void close_port() = 0;
53 : virtual int current_port() const = 0;
54 : virtual std::string current_port_name() const = 0;
55 : virtual bool is_port_open() const = 0;
56 : };
57 :
58 : /**
59 : * @brief Abstract interface for managing MIDI CC mapping.
60 : * Satisfies the Interface Segregation Principle (ISP).
61 : */
62 95 : class IMidiMappingService {
63 : public:
64 285 : virtual ~IMidiMappingService() = default;
65 :
66 : virtual void add_mapping(const MidiMapping& mapping) = 0;
67 : virtual void remove_mapping(int index) = 0;
68 : virtual void remove_mapping_for_param(const std::string& effect_name,
69 : const std::string& param_name) = 0;
70 : virtual void clear_mappings() = 0;
71 : virtual const std::vector<MidiMapping>& mappings() const = 0;
72 : virtual void install_default_mappings() = 0;
73 : };
74 :
75 : /**
76 : * @brief Abstract interface for managing interactive MIDI learning.
77 : * Satisfies the Interface Segregation Principle (ISP).
78 : */
79 95 : class IMidiLearnSession {
80 : public:
81 285 : virtual ~IMidiLearnSession() = default;
82 :
83 : virtual void start_learn(MidiTargetType type, const std::string& effect_name,
84 : const std::string& param_name) = 0;
85 : virtual void cancel_learn() = 0;
86 : virtual bool is_learning() const = 0;
87 : virtual std::string learn_status() const = 0;
88 : virtual const std::string& learn_effect_name() const = 0;
89 : virtual const std::string& learn_param_name() const = 0;
90 : };
91 :
92 : /**
93 : * @brief Abstract interface for persistence of MIDI mappings.
94 : * Satisfies the Interface Segregation Principle (ISP).
95 : */
96 95 : class IMidiConfigStore {
97 : public:
98 285 : virtual ~IMidiConfigStore() = default;
99 :
100 : virtual void save_config() const = 0;
101 : virtual void load_config() = 0;
102 : };
103 :
104 : /**
105 : * @brief Abstract interface for the MIDI input manager.
106 : * Satisfies the Dependency Inversion Principle (DIP) and Interface Segregation Principle (ISP).
107 : */
108 95 : class IMidiManager : public IMidiPortManager,
109 : public IMidiMappingService,
110 : public IMidiLearnSession,
111 : public IMidiConfigStore {
112 : public:
113 285 : virtual ~IMidiManager() = default;
114 :
115 : virtual bool initialize() = 0;
116 : virtual void shutdown() = 0;
117 :
118 : virtual void poll(IAudioEngine& engine) = 0;
119 : virtual void inject_event(const MidiEvent& event) = 0;
120 : };
121 :
122 : } // namespace Amplitron
|