LCOV - code coverage report
Current view: top level - src/gui/commands - command_param.h (source / functions) Coverage Total Hit
Test: merged.info Lines: 97.7 % 43 42
Test Date: 2026-06-03 09:13:19 Functions: 85.7 % 7 6

            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 <chrono>
       7              : 
       8              : namespace Amplitron {
       9              : 
      10              : /**
      11              :  * @brief Command that records a single parameter value change on an effect.
      12              :  *
      13              :  * Supports coalescing: rapid changes to the same parameter within 500 ms are
      14              :  * merged into one undo step. Uses shared_ptr<Effect> directly so it is robust
      15              :  * against effect chain reordering.
      16              :  */
      17            6 : class ParameterChangeCommand : public Command {
      18              : public:
      19              :     /**
      20              :      * @brief Construct a ParameterChangeCommand.
      21              :      * @param engine      Reference to the AudioEngine.
      22              :      * @param effect      Shared pointer to the target effect.
      23              :      * @param param_index Index of the parameter within the effect's param list.
      24              :      * @param old_value   Value before the change (used by undo).
      25              :      * @param new_value   Value after the change (used by execute).
      26              :      */
      27           68 :     ParameterChangeCommand(AudioEngine& engine, std::shared_ptr<Effect> effect,
      28              :                            int param_index, float old_value, float new_value)
      29           68 :         : engine_(engine), effect_(std::move(effect)),
      30           83 :           param_index_(param_index), old_value_(old_value), new_value_(new_value) {}
      31              : 
      32              :     /** @brief Set the parameter to new_value_. */
      33           18 :     bool execute() override {
      34           18 :         auto& params = effect_->params();
      35           18 :         if (param_index_ >= 0 && param_index_ < static_cast<int>(params.size())) {
      36            6 :             params[param_index_].value = new_value_;
      37            6 :             int idx = -1;
      38            6 :             auto& fx = engine_.effects();
      39           24 :             for (int i = 0; i < static_cast<int>(fx.size()); ++i) {
      40           18 :                 if (fx[i] == effect_) { idx = i; break; }
      41            6 :             }
      42            6 :             if (idx >= 0) engine_.push_param_change(idx, param_index_, new_value_);
      43            2 :         }
      44           18 :         return true;
      45              :     }
      46              : 
      47              :     /** @brief Restore the parameter to old_value_. */
      48           18 :     void undo() override {
      49           18 :         auto& params = effect_->params();
      50           18 :         if (param_index_ >= 0 && param_index_ < static_cast<int>(params.size())) {
      51            6 :             params[param_index_].value = old_value_;
      52            6 :             int idx = -1;
      53            6 :             auto& fx = engine_.effects();
      54           24 :             for (int i = 0; i < static_cast<int>(fx.size()); ++i) {
      55           18 :                 if (fx[i] == effect_) { idx = i; break; }
      56            6 :             }
      57            6 :             if (idx >= 0) engine_.push_param_change(idx, param_index_, old_value_);
      58            2 :         }
      59           18 :     }
      60              : 
      61              :     /** @brief Return "Change Parameter". */
      62            0 :     const char* description() const override { return "Change Parameter"; }
      63              : 
      64              :     /**
      65              :      * @brief Attempt to coalesce @p other into this command.
      66              :      *
      67              :      * Merges if @p other is a ParameterChangeCommand targeting the same
      68              :      * effect and parameter index within 500 ms. On success, this command's
      69              :      * new_value_ and timestamp are updated; old_value_ is preserved.
      70              :      *
      71              :      * @return true if @p other was absorbed.
      72              :      */
      73           24 :     bool merge_with(const Command& other) override {
      74           24 :         auto* pc = dynamic_cast<const ParameterChangeCommand*>(&other);
      75           24 :         if (!pc) return false;
      76           21 :         if (pc->effect_.get() != effect_.get() || pc->param_index_ != param_index_)
      77            6 :             return false;
      78              : 
      79           12 :         auto dt = std::chrono::duration_cast<std::chrono::milliseconds>(
      80           12 :             pc->timestamp_ - timestamp_);
      81           12 :         if (dt.count() > 500) return false;
      82              : 
      83            9 :         new_value_ = pc->new_value_;
      84            9 :         timestamp_ = pc->timestamp_;
      85            9 :         return true;
      86            8 :     }
      87              : 
      88              :     /** @brief Accessor for the target effect. */
      89            3 :     std::shared_ptr<Effect> effect() const { return effect_; }
      90              : 
      91              :     /** @brief Index of the parameter being changed. */
      92           10 :     int param_index() const { return param_index_; }
      93              : 
      94              :     /** @brief Value before the change. */
      95              :     float old_value() const { return old_value_; }
      96              : 
      97              :     /** @brief Value after the change. */
      98              :     float new_value() const { return new_value_; }
      99              : 
     100              : private:
     101              :     AudioEngine& engine_;
     102              :     std::shared_ptr<Effect> effect_;
     103              :     int param_index_;
     104              :     float old_value_;
     105              :     float new_value_;
     106              : };
     107              : 
     108              : } // namespace Amplitron
        

Generated by: LCOV version 2.0-1