Line data Source code
1 : #pragma once
2 :
3 : #include "gui/commands/command_base.h"
4 : #include "audio/engine/audio_engine.h"
5 : #include "audio/effects/effect.h"
6 : #include <cstring>
7 : #include <algorithm>
8 :
9 : namespace Amplitron {
10 :
11 : /**
12 : * @brief Command that appends an effect to the engine's signal chain.
13 : *
14 : * execute() adds the effect; undo() finds and removes it.
15 : */
16 3 : class AddEffectCommand : public Command {
17 : public:
18 : /**
19 : * @brief Construct an AddEffectCommand.
20 : * @param engine Reference to the audio engine that owns the effect chain.
21 : * @param effect Shared pointer to the effect to add.
22 : */
23 96 : AddEffectCommand(AudioEngine& engine, std::shared_ptr<Effect> effect)
24 96 : : engine_(engine), effect_(std::move(effect)) {}
25 :
26 : /** @brief Append the effect to the engine's chain (before the amp if present). */
27 81 : bool execute() override {
28 81 : int amp_idx = -1;
29 81 : auto& fx = engine_.effects();
30 243 : for (int i = 0; i < static_cast<int>(fx.size()); ++i) {
31 162 : if (std::strcmp(fx[i]->name(), "Amp Sim") == 0) {
32 0 : amp_idx = i;
33 0 : break;
34 : }
35 54 : }
36 81 : if (amp_idx >= 0) {
37 0 : engine_.insert_effect(amp_idx, effect_);
38 0 : } else {
39 108 : engine_.add_effect(effect_);
40 : }
41 81 : return true;
42 0 : }
43 :
44 : /** @brief Remove the previously added effect from the chain. */
45 21 : void undo() override {
46 21 : auto& fx = engine_.effects();
47 21 : for (int i = static_cast<int>(fx.size()) - 1; i >= 0; --i) {
48 21 : if (fx[i] == effect_) {
49 21 : engine_.remove_effect(i);
50 21 : return;
51 : }
52 0 : }
53 7 : }
54 :
55 : /** @brief Return "Add Effect". */
56 12 : const char* description() const override { return "Add Effect"; }
57 :
58 : /** @brief Accessor for the wrapped effect. */
59 : std::shared_ptr<Effect> effect() const { return effect_; }
60 :
61 : private:
62 : AudioEngine& engine_;
63 : std::shared_ptr<Effect> effect_;
64 : };
65 :
66 : /**
67 : * @brief Command that removes an effect from the engine's signal chain.
68 : *
69 : * The constructor captures the effect pointer before removal so undo() can
70 : * re-insert it at its original position.
71 : */
72 : class RemoveEffectCommand : public Command {
73 : public:
74 : /**
75 : * @brief Construct a RemoveEffectCommand.
76 : * @param engine Reference to the audio engine.
77 : * @param index Chain index of the effect to remove (captured at construction).
78 : */
79 25 : RemoveEffectCommand(AudioEngine& engine, int index)
80 20 : : engine_(engine), index_(index) {
81 15 : auto& fx = engine_.effects();
82 19 : if (index >= 0 && index < static_cast<int>(fx.size())) {
83 9 : effect_ = fx[index];
84 3 : }
85 20 : }
86 :
87 : /** @brief Remove the effect at the stored index. */
88 18 : bool execute() override {
89 18 : engine_.remove_effect(index_);
90 18 : return true;
91 : }
92 :
93 : /** @brief Re-insert the captured effect at its original chain position. */
94 12 : void undo() override {
95 12 : if (effect_) {
96 6 : auto& fx = engine_.effects();
97 6 : int pos = std::min(index_, static_cast<int>(fx.size()));
98 6 : engine_.add_effect(effect_);
99 6 : int last = static_cast<int>(engine_.effects().size()) - 1;
100 6 : if (last != pos) {
101 3 : engine_.move_effect(last, pos);
102 1 : }
103 2 : }
104 12 : }
105 :
106 : /** @brief Return "Remove Effect". */
107 0 : const char* description() const override { return "Remove Effect"; }
108 :
109 : /** @brief Original chain index of the removed effect. */
110 6 : int index() const { return index_; }
111 :
112 : /** @brief Accessor for the captured effect pointer. */
113 6 : std::shared_ptr<Effect> effect() const { return effect_; }
114 :
115 : private:
116 : AudioEngine& engine_;
117 : int index_;
118 : std::shared_ptr<Effect> effect_;
119 : };
120 :
121 : } // namespace Amplitron
|