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