From 4ee709af7b22f0b7e2efa6f1af8efe02f0644d37 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Sat, 5 Apr 2025 17:23:17 -0600 Subject: [PATCH] libardour APIs for Sequence::shift (timepos_t const &) A way to move all MIDI data in a Sequence later in time. This is likely not finished, and may need a new signal for notifications --- libs/ardour/ardour/midi_model.h | 17 ++++++++++- libs/ardour/midi_model.cc | 50 ++++++++++++++++++++++++++++++++ libs/ardour/region.cc | 4 +++ libs/evoral/ControlList.cc | 17 +++++++++++ libs/evoral/Sequence.cc | 20 +++++++++++++ libs/evoral/evoral/ControlList.h | 1 + libs/evoral/evoral/Sequence.h | 2 ++ 7 files changed, 110 insertions(+), 1 deletion(-) diff --git a/libs/ardour/ardour/midi_model.h b/libs/ardour/ardour/midi_model.h index be01e2fb3f..be323e514d 100644 --- a/libs/ardour/ardour/midi_model.h +++ b/libs/ardour/ardour/midi_model.h @@ -83,10 +83,25 @@ public: protected: std::shared_ptr _model; - const std::string _name; + const std::string _name; }; + class LIBARDOUR_API ShiftCommand : public DiffCommand { + public: + ShiftCommand (std::shared_ptr m, std::string const & name, TimeType distance); + ShiftCommand (std::shared_ptr m, const XMLNode& node); + + void operator() (); + void undo (); + + int set_state (const XMLNode&, int version); + XMLNode & get_state () const; + + private: + TimeType _distance; + }; + class LIBARDOUR_API NoteDiffCommand : public DiffCommand { public: diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc index 37890f25f3..baaa41dc37 100644 --- a/libs/ardour/midi_model.cc +++ b/libs/ardour/midi_model.cc @@ -126,6 +126,7 @@ MidiModel::apply_diff_command_only (Command* cmd) /* ************* DIFF COMMAND ********************/ +#define SHIFT_COMMAND_ELEMENT "ShiftCommand" #define NOTE_DIFF_COMMAND_ELEMENT "NoteDiffCommand" #define DIFF_NOTES_ELEMENT "ChangedNotes" #define ADDED_NOTES_ELEMENT "AddedNotes" @@ -146,6 +147,55 @@ MidiModel::DiffCommand::DiffCommand(std::shared_ptr m, const std::str assert(_model); } +MidiModel::ShiftCommand::ShiftCommand (std::shared_ptr m, std::string const & name, MidiModel::TimeType distance) + : DiffCommand (m, name) + , _distance (distance) +{ + assert (_model); +} + +MidiModel::ShiftCommand::ShiftCommand (std::shared_ptr m, const XMLNode& node) + : DiffCommand (m, "") +{ + assert (_model); + set_state (node, Stateful::loading_state_version); + // _name = string_compose (_("Shift MIDI by %1"), _distance.str()); +} + +void +MidiModel::ShiftCommand::operator() () +{ + _model->shift (_distance); + _model->ContentsChanged (); /* EMIT SIGNAL */ +} + +void +MidiModel::ShiftCommand::undo () +{ + _model->shift (-_distance); + _model->ContentsChanged (); /* EMIT SIGNAL */ +} + +int +MidiModel::ShiftCommand::set_state (XMLNode const & diff_command, int /* version */) +{ + if (diff_command.name() != string (SHIFT_COMMAND_ELEMENT)) { + return 1; + } + + diff_command.get_property (X_("distance"), _distance); + + return 0; +} + +XMLNode& +MidiModel::ShiftCommand::get_state () const +{ + XMLNode* node = new XMLNode (SHIFT_COMMAND_ELEMENT); + node->set_property (X_("distance"), _distance); + return *node; +} + MidiModel::NoteDiffCommand::NoteDiffCommand (std::shared_ptr m, const XMLNode& node) : DiffCommand (m, "") { diff --git a/libs/ardour/region.cc b/libs/ardour/region.cc index de8a4de327..10004e00f8 100644 --- a/libs/ardour/region.cc +++ b/libs/ardour/region.cc @@ -1041,6 +1041,8 @@ Region::modify_front_unchecked (timepos_t const & npos, bool reset_fade) source_zero = timepos_t (source_position().time_domain()); // its actually negative, but this will work for us } + std::cerr << "source zero " << source_zero << std::endl; + if (new_position >= last) { /* can't trim it zero or negative length */ return; } @@ -1059,6 +1061,8 @@ Region::modify_front_unchecked (timepos_t const & npos, bool reset_fade) newlen = length() + (np.distance (position())); } + std::cerr << "tti " << np << ", " << newlen << std::endl; + trim_to_internal (np, newlen); if (reset_fade) { diff --git a/libs/evoral/ControlList.cc b/libs/evoral/ControlList.cc index 1d041859c2..b6ec83b3ad 100644 --- a/libs/evoral/ControlList.cc +++ b/libs/evoral/ControlList.cc @@ -1213,6 +1213,23 @@ ControlList::shift (timepos_t const& time, timecnt_t const& distance) maybe_signal_changed (); } +/* Note: timepos_t is used here instead of timecnt_t because there's an + * implicit origin for the magnitude of the distance. + */ +void +ControlList::simple_shift (timepos_t const & distance) +{ + { + Glib::Threads::RWLock::WriterLock lm (_lock); + for (auto & e : _events) { + e->when = e->when + distance; + } + + mark_dirty (); + } + maybe_signal_changed (); +} + void ControlList::modify (iterator iter, timepos_t const& time, double val) { diff --git a/libs/evoral/Sequence.cc b/libs/evoral/Sequence.cc index 263a1040f7..adae676d6c 100644 --- a/libs/evoral/Sequence.cc +++ b/libs/evoral/Sequence.cc @@ -1448,6 +1448,26 @@ Sequence