fix crash when copy'ing latent plugins
[ardour.git] / libs / ardour / session.cc
index fb73ecbd3662bc8fbae70f53b40cbfa61e9b90a1..61bfce14b6bfc995f0203b44e42bdf17652e60d8 100644 (file)
 
 #include "LuaBridge/LuaBridge.h"
 
-#include "i18n.h"
+#include "pbd/i18n.h"
 
 #include <glibmm/checksum.h>
 
@@ -178,6 +178,7 @@ Session::Session (AudioEngine &eng,
        , _record_status (Disabled)
        , _transport_frame (0)
        , _session_range_location (0)
+       , _session_range_end_is_free (true)
        , _slave (0)
        , _silent (false)
        , _transport_speed (0)
@@ -212,6 +213,7 @@ Session::Session (AudioEngine &eng,
        , post_export_position (0)
        , _exporting (false)
        , _export_rolling (false)
+       , _realtime_export (false)
        , _export_preroll (0)
        , _export_latency (0)
        , _pre_export_mmc_enabled (false)
@@ -2028,59 +2030,55 @@ framepos_t
 Session::audible_frame () const
 {
        framepos_t ret;
-       framepos_t tf;
-       framecnt_t offset;
 
-       offset = worst_playback_latency ();
+       frameoffset_t offset = worst_playback_latency (); // - _engine.samples_since_cycle_start ();
+       offset *= transport_speed ();
 
        if (synced_to_engine()) {
                /* Note: this is basically just sync-to-JACK */
-               tf = _engine.transport_frame();
+               ret = _engine.transport_frame();
        } else {
-               tf = _transport_frame;
+               ret = _transport_frame;
        }
 
-       ret = tf;
-
-       if (!non_realtime_work_pending()) {
-
-               /* MOVING */
+       if (transport_rolling()) {
+               ret -= offset;
 
                /* Check to see if we have passed the first guaranteed
-                  audible frame past our last start position. if not,
-                  return that last start point because in terms
-                  of audible frames, we have not moved yet.
-
-                  `Start position' in this context means the time we last
-                  either started, located, or changed transport direction.
-               */
+                * audible frame past our last start position. if not,
+                * return that last start point because in terms
+                * of audible frames, we have not moved yet.
+                *
+                * `Start position' in this context means the time we last
+                * either started, located, or changed transport direction.
+                */
 
                if (_transport_speed > 0.0f) {
 
                        if (!play_loop || !have_looped) {
-                               if (tf < _last_roll_or_reversal_location + offset) {
+                               if (ret < _last_roll_or_reversal_location) {
                                        return _last_roll_or_reversal_location;
                                }
+                       } else {
+                               // latent loops
+                               Location *location = _locations->auto_loop_location();
+                               frameoffset_t lo = location->start() - ret;
+                               if (lo > 0) {
+                                       ret = location->end () - lo;
+                               }
                        }
 
-
-                       /* forwards */
-                       ret -= offset;
-
                } else if (_transport_speed < 0.0f) {
 
                        /* XXX wot? no backward looping? */
 
-                       if (tf > _last_roll_or_reversal_location - offset) {
+                       if (ret > _last_roll_or_reversal_location) {
                                return _last_roll_or_reversal_location;
-                       } else {
-                               /* backwards */
-                               ret += offset;
                        }
                }
        }
 
-       return ret;
+       return std::max ((framepos_t)0, ret);
 }
 
 void
@@ -3453,7 +3451,7 @@ Session::add_routes_inner (RouteList& new_routes, bool input_auto_connect, bool
 
                                if (order == PresentationInfo::max_order) {
                                        /* just add to the end */
-                                       r->set_presentation_order_explicit (n_routes + added);
+                                       r->set_presentation_order (n_routes + added, false);
                                        DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("group order not set, set to NR %1 + %2 = %3\n", n_routes, added, n_routes + added));
                                } else {
                                        r->set_presentation_order (order + added);
@@ -3901,6 +3899,8 @@ Session::route_solo_changed (bool self_solo_changed, Controllable::GroupControlD
 
                if ((*i)->solo_isolate_control()->solo_isolated() || !(*i)->can_solo()) {
                        /* route does not get solo propagated to it */
+                       DEBUG_TRACE (DEBUG::Solo, string_compose ("%1 excluded from solo because iso = %2 can_solo = %3\n", (*i)->name(), (*i)->solo_isolate_control()->solo_isolated(),
+                                                                 (*i)->can_solo()));
                        continue;
                }
 
@@ -4244,6 +4244,24 @@ Session::get_remote_nth_stripable (PresentationInfo::order_t n, PresentationInfo
        sl.sort (Stripable::PresentationOrderSorter());
 
        for (StripableList::const_iterator s = sl.begin(); s != sl.end(); ++s) {
+
+               if ((*s)->presentation_info().hidden()) {
+                       /* if the caller didn't explicitly ask for hidden
+                          stripables, ignore hidden ones. This matches
+                          the semantics of the pre-PresentationOrder
+                          "get by RID" logic of Ardour 4.x and earlier.
+
+                          XXX at some point we should likely reverse
+                          the logic of the flags, because asking for "the
+                          hidden stripables" is not going to be common,
+                          whereas asking for visible ones is normal.
+                       */
+
+                       if (! (flags & PresentationInfo::Hidden)) {
+                               continue;
+                       }
+               }
+
                if ((*s)->presentation_info().flag_match (flags)) {
                        if (match_cnt++ == n) {
                                return *s;
@@ -4389,12 +4407,18 @@ Session::maybe_update_session_range (framepos_t a, framepos_t b)
                        _session_range_location->set_start (a);
                }
 
-               if (b > _session_range_location->end()) {
+               if (_session_range_end_is_free && (b > _session_range_location->end())) {
                        _session_range_location->set_end (b);
                }
        }
 }
 
+void
+Session::set_end_is_free (bool yn)
+{
+       _session_range_end_is_free = yn;
+}
+
 void
 Session::playlist_ranges_moved (list<Evoral::RangeMove<framepos_t> > const & ranges)
 {
@@ -7034,3 +7058,14 @@ Session::auto_connect_thread_run ()
        }
        pthread_mutex_unlock (&_auto_connect_mutex);
 }
+
+void
+Session::cancel_all_solo ()
+{
+       StripableList sl;
+
+       get_stripables (sl);
+
+       set_controls (stripable_list_to_control_list (sl, &Stripable::solo_control), 0.0, Controllable::NoGroup);
+       clear_all_solo_state (routes.reader());
+}