From 7dee98279abc93f63ad6b7e90627e09b15aed5ad Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Fri, 21 Jun 2024 22:18:52 -0600 Subject: [PATCH] extend MidiModel and MIDITrigger in preparation for edit-change handling --- libs/ardour/ardour/midi_model.h | 4 ++++ libs/ardour/ardour/triggerbox.h | 12 ++++++++++++ libs/ardour/midi_model.cc | 18 +++++++++++++++++- libs/ardour/midi_source.cc | 1 + libs/ardour/triggerbox.cc | 27 +++++++++++++++++++++++++-- 5 files changed, 59 insertions(+), 3 deletions(-) diff --git a/libs/ardour/ardour/midi_model.h b/libs/ardour/ardour/midi_model.h index 89ac2c4a88..12d3e218ee 100644 --- a/libs/ardour/ardour/midi_model.h +++ b/libs/ardour/ardour/midi_model.h @@ -48,6 +48,7 @@ namespace ARDOUR { class Session; class MidiSource; +class MidiStateTracker; /** This is a higher level (than MidiBuffer) model of MIDI data, with separate * representations for notes (instead of just unassociated note on/off events) @@ -61,6 +62,7 @@ public: typedef Temporal::Beats TimeType; MidiModel (MidiSource&); + MidiModel (MidiModel const & other, MidiSource&); class LIBARDOUR_API DiffCommand : public PBD::Command { public: @@ -324,6 +326,8 @@ public: void insert_silence_at_start (TimeType); void transpose (NoteDiffCommand *, const NotePtr, int); + void track_state (timepos_t const & when, MidiStateTracker&) const; + protected: int resolve_overlaps_unlocked (const NotePtr, void* arg = 0); diff --git a/libs/ardour/ardour/triggerbox.h b/libs/ardour/ardour/triggerbox.h index 02f1cabafa..a3f5d0e4d4 100644 --- a/libs/ardour/ardour/triggerbox.h +++ b/libs/ardour/ardour/triggerbox.h @@ -580,6 +580,8 @@ class LIBARDOUR_API MIDITrigger : public Trigger { return midi_run (bufs, start_sample, end_sample, start, end, nframes, dest_offset, bpm, quantize_offset); } + void swap_model (std::shared_ptr, ARDOUR::MidiModel::DiffCommand*); + void set_start (timepos_t const &); void set_end (timepos_t const &); void set_legato_offset (timepos_t const &); @@ -657,6 +659,16 @@ class LIBARDOUR_API MIDITrigger : public Trigger { int load_data (std::shared_ptr); void compute_and_set_length (); void _startup (BufferSet&, pframes_t dest_offset, Temporal::BBT_Offset const &); + + struct ModelSwap { + std::shared_ptr model; + ARDOUR::MidiModel::DiffCommand* cmd; + + ModelSwap (std::shared_ptr m, ARDOUR::MidiModel::DiffCommand* c) + : model (m), cmd (c) {} + }; + + std::atomic model_swap; }; class LIBARDOUR_API TriggerBoxThread diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc index fb31114ed1..1387841c18 100644 --- a/libs/ardour/midi_model.cc +++ b/libs/ardour/midi_model.cc @@ -66,6 +66,14 @@ MidiModel::MidiModel (MidiSource& s) _midi_source.AutomationStateChanged.connect_same_thread (_midi_source_connections, boost::bind (&MidiModel::source_automation_state_changed, this, _1, _2)); } +MidiModel::MidiModel (MidiModel const & other, MidiSource & s) + : AutomatableSequence (other) + , _midi_source (s) +{ + _midi_source.InterpolationChanged.connect_same_thread (_midi_source_connections, boost::bind (&MidiModel::source_interpolation_changed, this, _1, _2)); + _midi_source.AutomationStateChanged.connect_same_thread (_midi_source_connections, boost::bind (&MidiModel::source_automation_state_changed, this, _1, _2)); +} + MidiModel::NoteDiffCommand* MidiModel::new_note_diff_command (const string& name) { @@ -1424,7 +1432,7 @@ MidiModel::find_sysex (Evoral::event_id_t sysex_id) MidiModel::WriteLock MidiModel::edit_lock() { - Source::WriterLock* source_lock = 0; + Source::WriterLock* source_lock = nullptr; /* Take source lock and invalidate iterator to release its lock on model. * Add currently active notes to _active_notes so we can restore them @@ -1866,3 +1874,11 @@ MidiModel::rebuild_from_mapping_stash (Temporal::Beats const & src_pos_offset) tempo_mapping_stash.clear (); } + +void +MidiModel::track_state (timepos_t const & when, MidiStateTracker& mst) const +{ + for (auto const & ev : *this) { + mst.track (ev.buffer()); + } +} diff --git a/libs/ardour/midi_source.cc b/libs/ardour/midi_source.cc index d3fe5bc2a6..a899b1396b 100644 --- a/libs/ardour/midi_source.cc +++ b/libs/ardour/midi_source.cc @@ -497,6 +497,7 @@ void MidiSource::set_model (const WriterLock& lock, std::shared_ptr m) { _model = m; + std::cerr << "Source " << name() << " switched to model " << _model << std::endl; invalidate(lock); ModelChanged (); /* EMIT SIGNAL */ } diff --git a/libs/ardour/triggerbox.cc b/libs/ardour/triggerbox.cc index 219cfa7e64..e7db6c027b 100644 --- a/libs/ardour/triggerbox.cc +++ b/libs/ardour/triggerbox.cc @@ -2205,6 +2205,7 @@ MIDITrigger::MIDITrigger (uint32_t n, TriggerBox& b) , pending_rt_midibuffer (nullptr) , old_rt_midibuffer (nullptr) , map_change (false) + , model_swap (nullptr) { _channel_map.assign (16, -1); } @@ -2213,6 +2214,14 @@ MIDITrigger::~MIDITrigger () { } +void +MIDITrigger::check_edit_swap (bool playing) +{ + if (model_swap != nullptr) { + std::cerr << "EDIT!\n"; + } +} + void MIDITrigger::set_used_channels (Evoral::SMF::UsedChannels used) { @@ -2779,6 +2788,13 @@ MIDITrigger::tempo_map_changed () map_change = true; } +void +MIDITrigger::swap_model (std::shared_ptr model, ARDOUR::MidiModel::DiffCommand* cmd) +{ + ModelSwap* ms = new ModelSwap (model, cmd); + model_swap = ms; +} + template pframes_t MIDITrigger::midi_run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample, @@ -2787,12 +2803,15 @@ MIDITrigger::midi_run (BufferSet& bufs, samplepos_t start_sample, samplepos_t en { assert (rt_midibuffer); - MidiBuffer* mb (in_process_context? &bufs.get_midi (0) : 0); + MidiBuffer* mb (in_process_context? &bufs.get_midi (0) : nullptr); typedef Evoral::Event MidiEvent; const timepos_t region_start_time = _region->start(); const Temporal::Beats region_start = region_start_time.beats(); Temporal::TempoMap::SharedPtr tmap (Temporal::TempoMap::use()); + std::shared_ptr mr = std::dynamic_pointer_cast (_region); + assert (mr); + last_event_samples = end_sample; /* see if we're going to start or stop or retrigger in this run() call */ @@ -3145,7 +3164,7 @@ TriggerBox::send_property_change (PBD::PropertyChange pc) TriggerBox::TriggerBox (Session& s, DataType dt) : Processor (s, _("TriggerBox"), Temporal::TimeDomainProvider (Temporal::BeatTime)) - , tracker (dt == DataType::MIDI ? new MidiStateTracker : 0) + , tracker (dt == DataType::MIDI ? new MidiStateTracker : nullptr) , _data_type (dt) , _order (-1) , explicit_queue (64) @@ -4830,6 +4849,10 @@ TriggerBox::process_requests (BufferSet& bufs) { Request* r; + for (uint64_t n = 0; n < all_triggers.size(); ++n) { + all_triggers[n]->check_edit_swap (_currently_playing == all_triggers[n]); + } + while (requests.read (&r, 1) == 1) { process_request (bufs, r); }