Back-port tim mayberry's fixes for import; fix JACK slaving to never pay attention...
[ardour.git] / libs / ardour / session_transport.cc
index 59a6bce785308ad80aa41911cf2caaee5caf66f1..d55c217bf5d22a3247c24b3c3cd13eef20424c93 100644 (file)
@@ -15,7 +15,6 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-    $Id$
 */
 
 #include <cmath>
@@ -30,6 +29,7 @@
 #include <glibmm/thread.h>
 #include <pbd/pthread_utils.h>
 #include <pbd/memento_command.h>
+#include <pbd/stacktrace.h>
 
 #include <midi++/mmc.h>
 #include <midi++/port.h>
@@ -176,7 +176,7 @@ Session::realtime_stop (bool abort)
                waiting_for_sync_offset = true;
        }
 
-       transport_sub_state = (Config->get_auto_return() ? AutoReturning : 0);
+       transport_sub_state = ((Config->get_slave_source() == None && Config->get_auto_return()) ? AutoReturning : 0);
 }
 
 void
@@ -372,17 +372,36 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
                update_latency_compensation (true, abort);
        }
 
-       if (Config->get_auto_return() || (post_transport_work & PostTransportLocate) || synced_to_jack()) {
+       if ((Config->get_slave_source() == None && Config->get_auto_return()) || 
+           (post_transport_work & PostTransportLocate) || 
+           (_requested_return_frame >= 0) ||
+           synced_to_jack()) {
                
                if (pending_locate_flush) {
                        flush_all_redirects ();
                }
+               
+               if (((Config->get_slave_source() == None && Config->get_auto_return()) || 
+                    synced_to_jack() ||
+                    _requested_return_frame >= 0) &&
+                   !(post_transport_work & PostTransportLocate)) {
 
-               if ((Config->get_auto_return() || synced_to_jack()) && !(post_transport_work & PostTransportLocate)) {
+                       bool do_locate = false;
 
-                       _transport_frame = last_stop_frame;
+                       if (_requested_return_frame >= 0) {
+                               _transport_frame = _requested_return_frame;
+                               _requested_return_frame = -1;
+                               do_locate = true;
+                       } else {
+                               _transport_frame = last_stop_frame;
+                       }
 
-                       if (synced_to_jack()) {
+                       if (synced_to_jack() && !play_loop) {
+                               do_locate = true;
+                       }
+                       
+                       if (do_locate) {
+                               // cerr << "non-realtimestop: transport locate to " << _transport_frame << endl;
                                _engine.transport_locate (_transport_frame);
                        }
                } 
@@ -421,14 +440,16 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
                /* XXX its a little odd that we're doing this here
                   when realtime_stop(), which has already executed,
                   will have done this.
+                  JLC - so let's not because it seems unnecessary and breaks loop record
                */
-               
+#if 0
                if (!Config->get_latched_record_enable()) {
                        g_atomic_int_set (&_record_status, Disabled);
                } else {
                        g_atomic_int_set (&_record_status, Enabled);
                }
                RecordStateChanged (); /* emit signal */
+#endif
        }
        
        if ((post_transport_work & PostTransportLocate) && get_record_enabled()) {
@@ -458,7 +479,9 @@ Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
                
        }
 
-       PositionChanged (_transport_frame); /* EMIT SIGNAL */
+        nframes_t tf = _transport_frame;
+
+        PositionChanged (tf); /* EMIT SIGNAL */
        TransportStateChange (); /* EMIT SIGNAL */
 
        /* and start it up again if relevant */
@@ -614,7 +637,7 @@ Session::start_locate (nframes_t target_frame, bool with_roll, bool with_flush,
 void
 Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool with_loop)
 {
-       if (actively_recording()) {
+       if (actively_recording() && !with_loop) {
                return;
        }
 
@@ -640,7 +663,7 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w
                } 
        }
 
-       if (transport_rolling() && !Config->get_auto_play() && !with_roll && !(synced_to_jack() && play_loop)) {
+       if (transport_rolling() && (!auto_play_legal || !Config->get_auto_play()) && !with_roll && !(synced_to_jack() && play_loop)) {
                realtime_stop (false);
        } 
 
@@ -705,6 +728,22 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w
                        // cancel looping directly, this is called from event handling context
                        set_play_loop (false);
                }
+               else if (al && _transport_frame == al->start()) {
+                       if (with_loop) {
+                               // this is only necessary for seamless looping
+
+                               boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
+                               
+                               for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
+                                       if ((*i)->record_enabled ()) {
+                                               // tell it we've looped, so it can deal with the record state
+                                               (*i)->transport_looped(_transport_frame);
+                                       }
+                               }
+                       }
+
+                       TransportLooped(); // EMIT SIGNAL
+               }
        }
        
        loop_changing = false;
@@ -875,7 +914,9 @@ Session::start_transport ()
                break;
 
        case Recording:
-               disable_record (false);
+               if (!play_loop) {
+                       disable_record (false);
+               }
                break;
 
        default:
@@ -925,7 +966,7 @@ Session::post_transport ()
 
        if (post_transport_work & PostTransportLocate) {
 
-               if ((Config->get_auto_play() && !_exporting) || (post_transport_work & PostTransportRoll)) {
+               if (((Config->get_slave_source() == None && (auto_play_legal && Config->get_auto_play())) && !_exporting) || (post_transport_work & PostTransportRoll)) {
                        start_transport ();
                        
                } else {
@@ -1144,6 +1185,14 @@ Session::setup_auto_play ()
        merge_event (ev);
 }
 
+void
+Session::request_roll_at_and_return (nframes_t start, nframes_t return_to)
+{
+       request_locate (start, false);
+       Event *ev = new Event (Event::LocateRollLocate, Event::Add, Event::Immediate, return_to, 1.0);
+       queue_event (ev);
+}
+
 void
 Session::request_bounded_roll (nframes_t start, nframes_t end)
 {
@@ -1250,3 +1299,19 @@ Session::update_latency_compensation_proxy (void* ignored)
 {
        update_latency_compensation (false, false);
 }
+
+void
+Session::allow_auto_play (bool yn)
+{
+       auto_play_legal = yn;
+}
+
+void
+Session::reset_jack_connection (jack_client_t* jack)
+{
+       JACK_Slave* js;
+
+       if (_slave && ((js = dynamic_cast<JACK_Slave*> (_slave)) != 0)) {
+               js->reset_client (jack);
+       }
+}