From 1e8b2c521c218b0d7bb938fa6dc36da4e5787b15 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Wed, 2 Oct 2024 13:46:52 -0600 Subject: [PATCH] provide a better method to decide if a trigger(slot) is occupied This is necessary with clip recording because for some short time after recording, a trigger may be playable despite not yet having a region. libs edition. --- libs/ardour/ardour/triggerbox.h | 7 +++- libs/ardour/triggerbox.cc | 32 +++++++++---------- .../control_protocol/basic_ui.cc | 2 +- libs/surfaces/launchkey_4/launchkey_4.cc | 2 +- libs/surfaces/launchpad_pro/lppro.cc | 4 +-- libs/surfaces/launchpad_x/lpx.cc | 4 +-- libs/surfaces/push2/cues.cc | 4 +-- 7 files changed, 30 insertions(+), 25 deletions(-) diff --git a/libs/ardour/ardour/triggerbox.h b/libs/ardour/ardour/triggerbox.h index 94a133742a..938026d51b 100644 --- a/libs/ardour/ardour/triggerbox.h +++ b/libs/ardour/ardour/triggerbox.h @@ -328,7 +328,8 @@ class LIBARDOUR_API Trigger : public PBD::Stateful { void clear_region (); virtual int set_region_in_worker_thread (std::shared_ptr) = 0; virtual int set_region_in_worker_thread_from_capture (std::shared_ptr) = 0; - std::shared_ptr region() const { return _region; } + std::shared_ptr the_region() const { return _region; } + virtual bool playable() const = 0; uint32_t index() const { return _index; } @@ -509,6 +510,8 @@ class LIBARDOUR_API AudioTrigger : public Trigger { return audio_run (bufs, start_sample, end_sample, start, end, nframes, dest_offset, bpm, quantize_offset); } + bool playable() const { return data.length; } + StretchMode stretch_mode() const { return _stretch_mode; } void set_stretch_mode (StretchMode); @@ -600,6 +603,8 @@ class LIBARDOUR_API MIDITrigger : public Trigger { MIDITrigger (uint32_t index, TriggerBox&); ~MIDITrigger (); + bool playable() const { return rt_midibuffer.load(); } + void captured (SlotArmInfo&, BufferSet&); void arm(); void disarm (); diff --git a/libs/ardour/triggerbox.cc b/libs/ardour/triggerbox.cc index 3551e63822..5953a9405b 100644 --- a/libs/ardour/triggerbox.cc +++ b/libs/ardour/triggerbox.cc @@ -3812,7 +3812,7 @@ TriggerBox::fast_forward (CueEvents const & cues, samplepos_t transport_position pos = c->time; cnt = 0; - if (!trig->region()) { + if (!trig->playable()) { fast_forward_nothing_to_do (); return; } @@ -4030,7 +4030,7 @@ TriggerBox::maybe_swap_pending (uint32_t slot) if (p) { if (p == Trigger::MagicClearPointerValue) { - if (all_triggers[slot]->region()) { + if (all_triggers[slot]->playable()) { if (_active_slots) { _active_slots--; } @@ -4040,7 +4040,7 @@ TriggerBox::maybe_swap_pending (uint32_t slot) } all_triggers[slot]->clear_region (); } else { - if (!all_triggers[slot]->region()) { + if (!all_triggers[slot]->playable()) { if (_active_slots == 0) { empty_changed = true; } @@ -4129,7 +4129,7 @@ TriggerBox::deep_sources (std::set >& sources) Glib::Threads::RWLock::ReaderLock lm (trigger_lock); for (uint64_t n = 0; n < all_triggers.size(); ++n) { - std::shared_ptr r (trigger(n)->region ()); + std::shared_ptr r (trigger(n)->the_region ()); if (r) { r->deep_sources (sources); } @@ -4142,7 +4142,7 @@ TriggerBox::used_regions (std::set >& regions) Glib::Threads::RWLock::ReaderLock lm (trigger_lock); for (uint64_t n = 0; n < all_triggers.size(); ++n) { - std::shared_ptr r (trigger(n)->region ()); + std::shared_ptr r (trigger(n)->the_region ()); if (r) { regions.insert (r); } @@ -4322,7 +4322,7 @@ void TriggerBox::bang_trigger_at (Triggers::size_type row, float velocity) { TriggerPtr t = trigger(row); - if (t && t->region()) { + if (t && t->playable()) { t->bang (velocity); } else { /* by convention, an empty slot is effectively a STOP button */ @@ -4334,7 +4334,7 @@ void TriggerBox::unbang_trigger_at (Triggers::size_type row) { TriggerPtr t = trigger(row); - if (t && t->region()) { + if (t && t->playable()) { t->unbang(); } else { /* you shouldn't be able to unbang an empty slot; but if this somehow happens we'll just treat it as a */ @@ -4758,7 +4758,7 @@ TriggerBox::run_cycle (BufferSet& bufs, samplepos_t start_sample, samplepos_t en DEBUG_TRACE (DEBUG::Triggers, string_compose ("tb noticed active scene %1\n", _active_scene)); if (_active_scene < (int32_t) all_triggers.size()) { if (!all_triggers[_active_scene]->cue_isolated()) { - if (all_triggers[_active_scene]->region()) { + if (all_triggers[_active_scene]->playable()) { all_triggers[_active_scene]->bang (); } else { stop_all_quantized (); //empty slot, this should work as a Stop for the running clips @@ -5095,12 +5095,12 @@ TriggerBox::determine_next_trigger (uint32_t current) /* count number of triggers that can actually be run (i.e. they have a region) */ for (uint32_t n = 0; n < all_triggers.size(); ++n) { - if (all_triggers[n]->region()) { + if (all_triggers[n]->playable()) { runnable++; } } - if (runnable == 0 || !all_triggers[current]->region()) { + if (runnable == 0 || !all_triggers[current]->playable()) { return -1; } @@ -5161,7 +5161,7 @@ TriggerBox::determine_next_trigger (uint32_t current) break; } - if (all_triggers[n]->region() && !all_triggers[n]->active()) { + if (all_triggers[n]->playable() && !all_triggers[n]->active()) { return n; } } @@ -5180,7 +5180,7 @@ TriggerBox::determine_next_trigger (uint32_t current) break; } - if (all_triggers[n]->region() && !all_triggers[n]->active ()) { + if (all_triggers[n]->playable() && !all_triggers[n]->active ()) { return n; } } @@ -5188,14 +5188,14 @@ TriggerBox::determine_next_trigger (uint32_t current) case FollowAction::FirstTrigger: for (n = 0; n < all_triggers.size(); ++n) { - if (all_triggers[n]->region() && !all_triggers[n]->active ()) { + if (all_triggers[n]->playable() && !all_triggers[n]->active ()) { return n; } } break; case FollowAction::LastTrigger: for (int i = all_triggers.size() - 1; i >= 0; --i) { - if (all_triggers[i]->region() && !all_triggers[i]->active ()) { + if (all_triggers[i]->playable() && !all_triggers[i]->active ()) { return i; } } @@ -5203,7 +5203,7 @@ TriggerBox::determine_next_trigger (uint32_t current) case FollowAction::JumpTrigger: for (std::size_t n = 0; n < TriggerBox::default_triggers_per_box; ++n) { - if (fa.targets.test (n) && all_triggers[n]->region()) { + if (fa.targets.test (n) && all_triggers[n]->playable()) { possible_targets.push_back (n); } } @@ -5280,7 +5280,7 @@ TriggerBox::set_state (const XMLNode& node, int version) all_triggers.push_back (trig); trig->set_state (**t, version); } - if (trig->region ()) { + if (trig->playable ()) { _active_slots++; } } diff --git a/libs/ctrl-interface/control_protocol/basic_ui.cc b/libs/ctrl-interface/control_protocol/basic_ui.cc index 61d16395e3..8e906da5d8 100644 --- a/libs/ctrl-interface/control_protocol/basic_ui.cc +++ b/libs/ctrl-interface/control_protocol/basic_ui.cc @@ -889,7 +889,7 @@ BasicUI::trigger_display_at (int x, int y) ARDOUR::TriggerPtr current = tb->currently_playing (); TriggerPtr tp = tb->trigger (_tbank_start_row + y); if (tp) { - if (!tp->region()) { + if (!tp->playable()) { disp.state = -1; } else if (tp == current) { disp.state = 1; diff --git a/libs/surfaces/launchkey_4/launchkey_4.cc b/libs/surfaces/launchkey_4/launchkey_4.cc index 9f95a534e7..de1ea9d6e7 100644 --- a/libs/surfaces/launchkey_4/launchkey_4.cc +++ b/libs/surfaces/launchkey_4/launchkey_4.cc @@ -1049,7 +1049,7 @@ LaunchKey4::trigger_property_change (PropertyChange pc, Trigger* t) void LaunchKey4::trigger_pad_light (Pad& pad, std::shared_ptr r, Trigger* t) { - if (!r || !t || !t->region()) { + if (!r || !t || !t->playable()) { unlight_pad (pad.id); return; } diff --git a/libs/surfaces/launchpad_pro/lppro.cc b/libs/surfaces/launchpad_pro/lppro.cc index 3a5f6ad78b..b05f8772aa 100644 --- a/libs/surfaces/launchpad_pro/lppro.cc +++ b/libs/surfaces/launchpad_pro/lppro.cc @@ -1584,7 +1584,7 @@ LaunchPadPro::trigger_property_change (PropertyChange pc, Trigger* t) MidiByteArray msg; std::shared_ptr r = session->get_remote_nth_route (scroll_x_offset + x); - if (!r || !t->region()) { + if (!r || !t->playable()) { msg.push_back (0x90); msg.push_back (pid); msg.push_back (0x0); @@ -1659,7 +1659,7 @@ LaunchPadPro::map_triggerbox (int x) TriggerPtr t = session->trigger_at (xp, yp); - if (!t || !t->region()) { + if (!t || !t->playable()) { msg[2] = 0x0; } else { msg[2] = palette_index; diff --git a/libs/surfaces/launchpad_x/lpx.cc b/libs/surfaces/launchpad_x/lpx.cc index 6121d4957a..18bbf350f1 100644 --- a/libs/surfaces/launchpad_x/lpx.cc +++ b/libs/surfaces/launchpad_x/lpx.cc @@ -1262,7 +1262,7 @@ LaunchPadX::trigger_property_change (PropertyChange pc, Trigger* t) MidiByteArray msg; std::shared_ptr r = session->get_remote_nth_route (scroll_x_offset + x); - if (!r || !t->region()) { + if (!r || !t->playable()) { msg.push_back (0x90); msg.push_back (pid); msg.push_back (0x0); @@ -1337,7 +1337,7 @@ LaunchPadX::map_triggerbox (int x) TriggerPtr t = session->trigger_at (xp, yp); - if (!t || !t->region()) { + if (!t || !t->playable()) { msg[2] = 0x0; } else { msg[2] = palette_index; diff --git a/libs/surfaces/push2/cues.cc b/libs/surfaces/push2/cues.cc index 861f137a7b..f2a228cadf 100644 --- a/libs/surfaces/push2/cues.cc +++ b/libs/surfaces/push2/cues.cc @@ -432,7 +432,7 @@ CueLayout::viewport_changed () std::shared_ptr pad = _p2.pad_by_xy (n, y); if (tb && tb->active()) { TriggerPtr tp = tb->trigger (y); - if (tp && tp->region()) { + if (tp && tp->playable()) { /* trigger in slot */ pad->set_color (color); tp->PropertyChanged.connect (_trig_connections[n * 8 + y], invalidator (*this), boost::bind (&CueLayout::trigger_property_change, this, _1, n, y), &_p2); @@ -780,7 +780,7 @@ CueLayout::set_pad_color_from_trigger_state (int col, std::shared_ptrregion()) { + if (trig->playable()) { if (trig->active()) {