From fd6afb30e6ecfc6aa79f0bfe35a05344ec9dd152 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Thu, 27 Jun 2024 16:22:11 -0600 Subject: [PATCH] use MidiModel::ContentsChanged to drive MIDI cue edit swaps No need for a special method called post-edit --- libs/ardour/ardour/triggerbox.h | 6 ++-- libs/ardour/triggerbox.cc | 64 +++++++++++++++++++-------------- 2 files changed, 41 insertions(+), 29 deletions(-) diff --git a/libs/ardour/ardour/triggerbox.h b/libs/ardour/ardour/triggerbox.h index 55d841c3e4..5b6c4a2b74 100644 --- a/libs/ardour/ardour/triggerbox.h +++ b/libs/ardour/ardour/triggerbox.h @@ -580,8 +580,6 @@ class LIBARDOUR_API MIDITrigger : public Trigger { return midi_run (bufs, start_sample, end_sample, start, end, nframes, dest_offset, bpm, quantize_offset); } - void edited (); - void set_start (timepos_t const &); void set_end (timepos_t const &); void set_legato_offset (timepos_t const &); @@ -636,7 +634,6 @@ class LIBARDOUR_API MIDITrigger : public Trigger { private: PBD::ID data_source; - PBD::ScopedConnection content_connection; Temporal::Beats final_beat; @@ -648,6 +645,9 @@ class LIBARDOUR_API MIDITrigger : public Trigger { Temporal::BBT_Offset _legato_offset; std::shared_ptr _model; + PBD::ScopedConnection content_connection; + void model_contents_changed(); + Temporal::Beats loop_start; Temporal::Beats loop_end; uint32_t first_event_index; diff --git a/libs/ardour/triggerbox.cc b/libs/ardour/triggerbox.cc index 5aa94186d0..04ae931f7e 100644 --- a/libs/ardour/triggerbox.cc +++ b/libs/ardour/triggerbox.cc @@ -675,7 +675,7 @@ Trigger::set_region_internal (std::shared_ptr r) * them in playlists either. */ - if (r->whole_file ()) { + if (r && r->whole_file ()) { _region = RegionFactory::create (r, r->derive_properties ()); } else { _region = r; @@ -1281,29 +1281,31 @@ MIDITrigger::check_edit_swap (timepos_t const & time, bool playing, BufferSet& b return; } -// if (playing) { - MidiBuffer& mbuf (bufs.get_midi (0)); - MidiStateTracker post_edit_state; + if (playing) { + MidiBuffer& mbuf (bufs.get_midi (0)); + MidiStateTracker post_edit_state; - const timepos_t region_start_time = _region->start(); - const Temporal::Beats region_start = region_start_time.beats(); - pending->track_state (transition_beats + (time.beats() - region_start), post_edit_state); - _box.tracker->resolve_diff (post_edit_state, mbuf, time.samples()); -// } + /* Get the new MIDI state at the current time, and resolve any + * differences with the MIDI state held by the triggerbox we're + * in. + */ - std::cerr << "OLD\n"; - RTMidiBufferBeats* ort = rt_midibuffer.load(); - if (ort) { - ort->dump (99); + /* note: transition_beats is the time of the most recent + * transition (e.g. loop point) + */ + + Temporal::Beats p = time.beats() - transition_beats; + + pending->track_state (p - loop_start, post_edit_state); + _box.tracker->resolve_diff (post_edit_state, mbuf, time.samples()); } old_rt_midibuffer = rt_midibuffer.exchange (pending); - std::cerr << "old after exch " << old_rt_midibuffer << std::endl; if (iter < rt_midibuffer.load()->size()) { /* shutdown */ } - ort = rt_midibuffer.load (); + RTMidiBufferBeats* ort = rt_midibuffer.load (); first_event_index = std::numeric_limits::min(); last_event_index = std::numeric_limits::max(); @@ -1327,8 +1329,6 @@ MIDITrigger::check_edit_swap (timepos_t const & time, bool playing, BufferSet& b } } - std::cerr << "Swapped in new pending RT MB, events " << first_event_index << " .. " << last_event_index << "\n"; - rt_midibuffer.load()->dump (99); pending_rt_midibuffer = nullptr; } @@ -2719,6 +2719,13 @@ MIDITrigger::estimate_midi_patches () int MIDITrigger::set_region_in_worker_thread (std::shared_ptr r) { + if (!r) { + set_region_internal (r); + content_connection.disconnect (); + _model.reset (); + return 0; + } + std::shared_ptr mr = std::dynamic_pointer_cast (r); if (!mr) { @@ -2727,19 +2734,25 @@ MIDITrigger::set_region_in_worker_thread (std::shared_ptr r) set_region_internal (r); set_name (mr->name()); - data_length = mr->length().beats(); - _follow_length = Temporal::BBT_Offset (0, data_length.get_beats(), 0); - set_length (mr->length()); _model = mr->model(); + _model->ContentsChanged.connect_same_thread (content_connection, boost::bind (&MIDITrigger::model_contents_changed, this)); loop_start = r->start ().beats(); - loop_end = r->end ().beats(); + loop_end = r->length ().beats(); + + data_length = loop_end - loop_start; + + + std::cerr << "Have a MIDI loop that is " << data_length << " long\n"; + + _follow_length = Temporal::BBT_Offset (0, data_length.get_beats(), 0); + set_length (timecnt_t (data_length)); RTMidiBufferBeats* rtmb = new RTMidiBufferBeats; { - Source::ReaderLock lm (mr->midi_source()->mutex()); - mr->midi_source()->render (lm, *rtmb); + MidiModel::ReadLock lm (_model->read_lock()); + _model->render (lm, *rtmb); } pending_rt_midibuffer = rtmb; @@ -2822,10 +2835,9 @@ MIDITrigger::tempo_map_changed () } void -MIDITrigger::edited () +MIDITrigger::model_contents_changed () { RTMidiBufferBeats * rtmb (new RTMidiBufferBeats); - std::shared_ptr mr = std::dynamic_pointer_cast (_region); _model->render (_model->read_lock(), *rtmb); @@ -2839,7 +2851,7 @@ MIDITrigger::edited () /* And set it. RT thread will find this and do what needs to be done */ - pending_rt_midibuffer = rtmb; + pending_rt_midibuffer.store (rtmb); } template