From bc2cbfc7ec044692e959d5d1e55f5ea4fc76fe85 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Thu, 27 Feb 2020 02:36:16 +0100 Subject: [PATCH] Prevent concurrent loop and punch recording (backend) This also prevents switching between punch-in/out record and looping without transport-stop. --- libs/ardour/ardour/session.h | 16 ++++++++ libs/ardour/session.cc | 68 ++++++++++++++++++++++++++++++++ libs/ardour/session_state.cc | 18 ++++++++- libs/ardour/session_transport.cc | 9 +++++ 4 files changed, 109 insertions(+), 2 deletions(-) diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 6ab67fbd25..221a5ab6cc 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -1694,6 +1694,22 @@ private: void flush_all_inserts (); int micro_locate (samplecnt_t distance); + enum PunchLoopLock { + NoConstraint, + OnlyPunch, + OnlyLoop, + }; + + volatile guint _punch_or_loop; // enum PunchLoopLock + + bool punch_is_possible () const; + bool loop_is_possible () const; + + bool punch_active () const; + void unset_punch (); + bool maybe_allow_only_loop (bool play_loop = false); + bool maybe_allow_only_punch (); + void force_locate (samplepos_t sample, LocateTransportDisposition); void realtime_stop (bool abort, bool clear_state); void realtime_locate (bool); diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index af02a33605..a2c61c8bb8 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -271,6 +271,7 @@ Session::Session (AudioEngine &eng, , ltc_timecode_offset (0) , ltc_timecode_negative_offset (false) , midi_control_ui (0) + , _punch_or_loop (NoConstraint) , _tempo_map (0) , _all_route_group (new RouteGroup (*this, "all")) , routes (new RouteList) @@ -1397,6 +1398,72 @@ Session::auto_punch_start_changed (Location* location) } } +bool +Session::punch_active () const +{ + if (!get_record_enabled ()) { + return false; + } + if (!_locations->auto_punch_location ()) { + return false; + } + return config.get_punch_in () || config.get_punch_out (); +} + +bool +Session::punch_is_possible () const +{ + return g_atomic_int_get (&_punch_or_loop) != OnlyLoop; +} + +bool +Session::loop_is_possible () const +{ +#if 0 /* maybe prevent looping even when not rolling ? */ + if (get_record_enabled () && punch_active ()) { + return false; + } + } +#endif + return g_atomic_int_get(&_punch_or_loop) != OnlyPunch; +} + +bool +Session::maybe_allow_only_loop (bool play_loop) { + if (!(get_play_loop () || play_loop)) { + return false; + } + bool rv = g_atomic_int_compare_and_exchange (&_punch_or_loop, NoConstraint, OnlyLoop); + if (rv || loop_is_possible ()) { + unset_punch (); + return true; + } + return false; +} + +bool +Session::maybe_allow_only_punch () { + if (!punch_active ()) { + return false; + } + bool rv = g_atomic_int_compare_and_exchange (&_punch_or_loop, NoConstraint, OnlyPunch); + return rv || punch_is_possible (); +} + +void +Session::unset_punch () +{ + /* used when enabling looping + * -> _punch_or_loop = OnlyLoop; + */ + if (config.get_punch_in ()) { + config.set_punch_in (false); + } + if (config.get_punch_out ()) { + config.set_punch_out (false); + } +} + void Session::auto_punch_end_changed (Location* location) { @@ -1871,6 +1938,7 @@ Session::maybe_enable_record (bool rt_context) } if (_transport_speed) { + maybe_allow_only_punch (); if (!config.get_punch_in()) { enable_record (); } diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 0e0f5eb109..a7de032375 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -4006,8 +4006,15 @@ Session::config_changed (std::string p, bool ours) } else if (p == "punch-in") { - Location* location; + if (!punch_is_possible ()) { + if (config.get_punch_in ()) { + /* force off */ + config.set_punch_in (false); + return; + } + } + Location* location; if ((location = _locations->auto_punch_location()) != 0) { if (config.get_punch_in ()) { @@ -4019,8 +4026,15 @@ Session::config_changed (std::string p, bool ours) } else if (p == "punch-out") { - Location* location; + if (!punch_is_possible ()) { + if (config.get_punch_out ()) { + /* force off */ + config.set_punch_out (false); + return; + } + } + Location* location; if ((location = _locations->auto_punch_location()) != 0) { if (config.get_punch_out()) { diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index 8cdca5d79e..a79e39a4c2 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -145,6 +145,8 @@ Session::realtime_stop (bool abort, bool clear_state) reset_slave_state (); + g_atomic_int_set (&_punch_or_loop, NoConstraint); + _transport_speed = 0; _target_transport_speed = 0; _engine_speed = 1.0; @@ -604,6 +606,9 @@ Session::start_transport () break; } + maybe_allow_only_loop (); + maybe_allow_only_punch (); + _transport_speed = _default_transport_speed; _target_transport_speed = _transport_speed; @@ -1575,6 +1580,10 @@ Session::set_play_loop (bool yn, bool change_transport_state) return; } + if (yn && !maybe_allow_only_loop (true)) { + return; + } + if (yn) { play_loop = true;