Add an API to query if the audible frame is latent pending a locate
authorRobin Gareus <robin@gareus.org>
Fri, 31 Mar 2017 10:59:44 +0000 (12:59 +0200)
committerRobin Gareus <robin@gareus.org>
Fri, 31 Mar 2017 12:01:50 +0000 (14:01 +0200)
eg. at the end of a loop, the session may already be playing the
beginning of the loop. The TransportLooped signal was emitted.
Yet due to playback latency, the audible frame is still at the end of
the loop.

To interpolate the playhead position the UI needs to be able to know:
Relying on the TransportLooped signal is not sufficient because it
does not take playback latency into account.

libs/ardour/ardour/session.h
libs/ardour/session.cc
libs/ardour/session_state.cc

index ad2e69d0837b07840bfff574db8eff1d5fbd87a7..8088858917ec5f146673d232c7d34c31b245a39e 100644 (file)
@@ -681,7 +681,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
 
        framepos_t transport_frame () const {return _transport_frame; }
        framepos_t record_location () const {return _last_record_location; }
-       framepos_t audible_frame () const;
+       framepos_t audible_frame (bool* latent_locate = NULL) const;
        framepos_t requested_return_frame() const { return _requested_return_frame; }
        void set_requested_return_frame(framepos_t return_to);
 
index 2c3e1d2ef2f1b3c522583eab56d37d3526c2cd8b..f55e95486ef8c74735a6234fee273147c68bc2dd 100644 (file)
@@ -2067,12 +2067,15 @@ Session::maybe_enable_record (bool rt_context)
 }
 
 framepos_t
-Session::audible_frame () const
+Session::audible_frame (bool* latent_locate) const
 {
        framepos_t ret;
 
        frameoffset_t offset = worst_playback_latency (); // - _engine.samples_since_cycle_start ();
        offset *= transport_speed ();
+       if (latent_locate) {
+               *latent_locate = false;
+       }
 
        if (synced_to_engine()) {
                /* Note: this is basically just sync-to-JACK */
@@ -2097,14 +2100,24 @@ Session::audible_frame () const
 
                        if (!play_loop || !have_looped) {
                                if (ret < _last_roll_or_reversal_location) {
+                                       if (latent_locate) {
+                                               *latent_locate = true;
+                                       }
                                        return _last_roll_or_reversal_location;
                                }
                        } else {
-                               // latent loops
+                               /* the play-position wrapped at the loop-point
+                                * ardour is already playing the beginning of the loop,
+                                * but due to playback latency, the "audible frame"
+                                * is still at the end of the loop.
+                                */
                                Location *location = _locations->auto_loop_location();
                                frameoffset_t lo = location->start() - ret;
                                if (lo > 0) {
                                        ret = location->end () - lo;
+                                       if (latent_locate) {
+                                               *latent_locate = true;
+                                       }
                                }
                        }
 
index 1b93e41c3cd96fcf9f3c62fb0e218ab6bbe8da0f..72da3e6788f2e245eaa877a42055d4898266dfe1 100644 (file)
@@ -233,7 +233,7 @@ Session::post_engine_init ()
        msc->set_input_port (boost::dynamic_pointer_cast<MidiPort>(scene_input_port()));
        msc->set_output_port (boost::dynamic_pointer_cast<MidiPort>(scene_output_port()));
 
-       boost::function<framecnt_t(void)> timer_func (boost::bind (&Session::audible_frame, this));
+       boost::function<framecnt_t(void)> timer_func (boost::bind (&Session::audible_frame, this, (bool*)(0)));
        boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_input_port())->set_timer (timer_func);
 
        setup_midi_machine_control ();