Line data Source code
1 : #include <imgui.h>
2 :
3 : #include <cstdio>
4 :
5 : #include "audio/effects/amp_cab/amp_simulator.h"
6 : #include "audio/effects/amp_cab/cabinet_sim.h"
7 : #include "audio/effects/delay_reverb/delay.h"
8 : #include "audio/effects/delay_reverb/reverb.h"
9 : #include "audio/effects/distortion/distortion.h"
10 : #include "audio/effects/distortion/overdrive.h"
11 : #include "audio/effects/dynamics/compressor.h"
12 : #include "audio/effects/dynamics/multiband_compressor.h"
13 : #include "audio/effects/dynamics/noise_gate.h"
14 : #include "audio/effects/eq_filter/equalizer.h"
15 : #include "audio/effects/eq_filter/wah.h"
16 : #include "audio/effects/modulation/chorus.h"
17 : #include "audio/effects/modulation/flanger.h"
18 : #include "audio/effects/modulation/phaser.h"
19 : #include "audio/effects/pitch/octaver.h"
20 : #include "audio/effects/pitch/pitch_shifter.h"
21 : #include "audio/effects/utility/looper.h"
22 : #include "gui/pedalboard/pedal_board.h"
23 : #include "gui/theme/theme.h"
24 : #include "gui/views/gui_midi.h"
25 : #include "midi/midi_manager.h"
26 :
27 : namespace Amplitron {
28 :
29 15 : void PedalBoard::render_add_pedal_menu() {
30 15 : if (ImGui::Button("+ Add Pedal")) {
31 0 : ImGui::OpenPopup("AddPedalPopup");
32 0 : }
33 :
34 15 : if (ImGui::BeginPopup("AddPedalPopup")) {
35 3 : ImGui::TextColored(Theme::Gold(), "DRIVE");
36 3 : if (ImGui::MenuItem("Overdrive")) {
37 0 : add_effect_and_show(std::make_shared<Overdrive>());
38 0 : }
39 3 : if (ImGui::MenuItem("Distortion")) {
40 0 : add_effect_and_show(std::make_shared<Distortion>());
41 0 : }
42 :
43 3 : ImGui::Separator();
44 3 : ImGui::TextColored(Theme::Live(), "DYNAMICS");
45 3 : if (ImGui::MenuItem("Noise Gate")) {
46 0 : add_effect_and_show(std::make_shared<NoiseGate>());
47 0 : }
48 3 : if (ImGui::MenuItem("Compressor")) {
49 0 : add_effect_and_show(std::make_shared<Compressor>());
50 0 : }
51 3 : if (ImGui::MenuItem("MultiBand Compressor")) {
52 0 : add_effect_and_show(std::make_shared<MultiBandCompressor>());
53 0 : }
54 :
55 3 : ImGui::Separator();
56 3 : ImGui::TextColored(ImVec4(0.35f, 0.60f, 0.95f, 1.0f), "MODULATION");
57 3 : if (ImGui::MenuItem("Chorus")) {
58 0 : add_effect_and_show(std::make_shared<Chorus>());
59 0 : }
60 3 : if (ImGui::MenuItem("Phaser")) {
61 0 : add_effect_and_show(std::make_shared<Phaser>());
62 0 : }
63 3 : if (ImGui::MenuItem("Flanger")) {
64 0 : add_effect_and_show(std::make_shared<Flanger>());
65 0 : }
66 :
67 3 : ImGui::Separator();
68 3 : ImGui::TextColored(ImVec4(0.65f, 0.35f, 0.95f, 1.0f), "TIME");
69 3 : if (ImGui::MenuItem("Delay")) {
70 0 : add_effect_and_show(std::make_shared<Delay>());
71 0 : }
72 3 : if (ImGui::MenuItem("Reverb")) {
73 0 : add_effect_and_show(std::make_shared<Reverb>());
74 0 : }
75 3 : if (ImGui::MenuItem("Looper")) {
76 0 : add_effect_and_show(std::make_shared<Looper>());
77 0 : }
78 :
79 3 : ImGui::Separator();
80 3 : ImGui::TextColored(ImVec4(0.30f, 0.75f, 0.60f, 1.0f), "FILTER");
81 3 : if (ImGui::MenuItem("Wah")) {
82 0 : add_effect_and_show(std::make_shared<WahPedal>());
83 0 : }
84 :
85 3 : ImGui::Separator();
86 3 : ImGui::TextColored(ImVec4(0.85f, 0.40f, 0.55f, 1.0f), "PITCH");
87 3 : if (ImGui::MenuItem("Octaver")) {
88 0 : add_effect_and_show(std::make_shared<Octaver>());
89 0 : }
90 3 : if (ImGui::MenuItem("Pitch Shifter")) {
91 0 : add_effect_and_show(std::make_shared<PitchShifter>());
92 0 : }
93 :
94 3 : ImGui::Separator();
95 3 : ImGui::TextColored(Theme::GoldDim(), "TONE");
96 3 : if (ImGui::MenuItem("Equalizer")) {
97 0 : add_effect_and_show(std::make_shared<Equalizer>());
98 0 : }
99 3 : if (ImGui::MenuItem("Cabinet Sim")) {
100 0 : add_effect_and_show(std::make_shared<CabinetSim>());
101 0 : }
102 :
103 3 : ImGui::Separator();
104 3 : ImGui::TextDisabled("Routing Utility Blocks");
105 :
106 : // --- NEW MODULAR DAG INSTANTIATION ENTRIES ---
107 3 : if (ImGui::MenuItem("+ Signal Splitter Node (1 In -> N-Out)")) {
108 0 : history_.execute(std::make_unique<AddGraphNodeCommand>(
109 0 : engine_, "Splitter", NodeRoutingType::Splitter, nullptr, ImVec2(0, 0)));
110 0 : }
111 3 : if (ImGui::MenuItem("+ Signal Mixer Node (N-In -> 1 Out)")) {
112 0 : history_.execute(std::make_unique<AddGraphNodeCommand>(
113 0 : engine_, "Mixer", NodeRoutingType::Mixer, nullptr, ImVec2(0, 0), 2));
114 0 : }
115 :
116 3 : ImGui::EndPopup();
117 1 : }
118 15 : }
119 :
120 15 : void PedalBoard::render_amp_selector() {
121 15 : const auto &models = get_amp_models();
122 15 : int amp_idx = find_amp_index();
123 :
124 15 : if (amp_idx < 0) {
125 9 : auto amp = std::make_shared<AmpSimulator>();
126 9 : amp->params()[0].value = 0.0f;
127 9 : engine_.add_effect(amp);
128 9 : rebuild_widgets();
129 9 : amp_idx = find_amp_index();
130 9 : }
131 :
132 18 : const char *current_label = "Amp";
133 18 : int current_model = 0;
134 13 : if (amp_idx >= 0) {
135 15 : auto &_fx = engine_.effects()[amp_idx];
136 15 : current_model = static_cast<int>(amp_fx->params()[0].value);
137 20 : if (current_model >= 0 && current_model < static_cast<int>(models.size())) {
138 15 : current_label = models[current_model].name;
139 5 : }
140 5 : }
141 :
142 15 : ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.35f, 0.18f, 0.08f, 1.0f));
143 15 : ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.50f, 0.25f, 0.10f, 1.0f));
144 5 : char amp_label[64];
145 15 : std::snprintf(amp_label, sizeof(amp_label), "Amp: %s", current_label);
146 15 : if (ImGui::Button(amp_label)) {
147 0 : ImGui::OpenPopup("AmpSelectorPopup");
148 0 : }
149 15 : ImGui::PopStyleColor(2);
150 :
151 15 : if (ImGui::BeginPopup("AmpSelectorPopup")) {
152 3 : ImGui::TextColored(ImVec4(0.95f, 0.55f, 0.20f, 1.0f), "AMP MODEL");
153 15 : for (int m = 0; m < static_cast<int>(models.size()); ++m) {
154 12 : bool is_selected = (current_model == m);
155 12 : if (ImGui::MenuItem(models[m].name, models[m].inspiration, is_selected)) {
156 0 : if (amp_idx >= 0) {
157 0 : engine_.effects()[amp_idx]->params()[0].value = static_cast<float>(m);
158 0 : }
159 0 : }
160 4 : }
161 3 : ImGui::EndPopup();
162 1 : }
163 15 : }
164 :
165 : // ============================================================
166 : // MIDI MENU — QUICK STATUS AND ACTIONS
167 : // ============================================================
168 18 : void PedalBoard::render_midi_menu() {
169 18 : if (!gui_midi_) return;
170 15 : auto &midi = gui_midi_->manager();
171 :
172 15 : if (ImGui::Button("MIDI")) {
173 0 : ImGui::OpenPopup("MidiMenuPopup");
174 0 : }
175 :
176 15 : if (ImGui::BeginPopup("MidiMenuPopup")) {
177 : // Device status
178 6 : if (midi.is_port_open()) {
179 6 : ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f), "● Connected");
180 6 : ImGui::SameLine();
181 8 : ImGui::TextDisabled("(%s)", midi.current_port_name().c_str());
182 2 : } else {
183 0 : ImGui::TextColored(ImVec4(1.0f, 0.4f, 0.4f, 1.0f), "● Disconnected");
184 : }
185 :
186 6 : ImGui::Separator();
187 :
188 : // Learn mode status
189 6 : if (midi.is_learning()) {
190 3 : ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.0f, 1.0f), "⚡ Learn Mode Active");
191 3 : if (ImGui::MenuItem("Cancel Learn Mode", "Esc")) {
192 0 : midi.cancel_learn();
193 0 : }
194 1 : } else {
195 3 : ImGui::TextDisabled("Right-click any knob to MIDI learn");
196 : }
197 :
198 6 : ImGui::Separator();
199 :
200 : // Quick actions
201 6 : if (ImGui::MenuItem("Clear All Mappings")) {
202 0 : show_confirm_midi_clear_ = true;
203 0 : }
204 :
205 6 : if (ImGui::MenuItem("Save Config")) {
206 0 : midi.save_config();
207 0 : }
208 :
209 6 : if (ImGui::MenuItem("Load Config")) {
210 0 : midi.load_config();
211 0 : }
212 :
213 6 : ImGui::Separator();
214 :
215 : // Show active mappings count
216 6 : auto &mappings = midi.mappings();
217 6 : ImGui::TextDisabled("%zu active mappings", mappings.size());
218 :
219 6 : ImGui::EndPopup();
220 2 : }
221 6 : }
222 :
223 : } // namespace Amplitron
|