write session file to alternate name before, then rename; auditioner defaults to...
authorPaul Davis <paul@linuxaudiosystems.com>
Fri, 15 Dec 2006 19:40:10 +0000 (19:40 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Fri, 15 Dec 2006 19:40:10 +0000 (19:40 +0000)
git-svn-id: svn://localhost/ardour2/trunk@1214 d708f5d6-7413-0410-9779-e7cbd77b26cf

15 files changed:
gtk2_ardour/ardour_ui.cc
gtk2_ardour/ardour_ui.h
gtk2_ardour/main.cc
libs/ardour/ardour/audioengine.h
libs/ardour/ardour/configuration_vars.h
libs/ardour/ardour/session.h
libs/ardour/audioengine.cc
libs/ardour/auditioner.cc
libs/ardour/diskstream.cc
libs/ardour/session.cc
libs/ardour/session_butler.cc
libs/ardour/session_events.cc
libs/ardour/session_process.cc
libs/ardour/session_state.cc
libs/ardour/session_transport.cc

index 74eb36a814aa0a1a234897d50cfc385a8174fbc5..de7dce150007246bc0ce9d224ff5adbc1abaeed4 100644 (file)
@@ -353,14 +353,7 @@ ARDOUR_UI::save_ardour_state ()
 void
 ARDOUR_UI::startup ()
 {
-       /* Once the UI is up and running, start the audio engine. Doing
-          this before the UI is up and running can cause problems
-          when not running with SCHED_FIFO, because the amount of
-          CPU and disk work needed to get the UI started can interfere
-          with the scheduling of the audio thread.
-       */
-
-       Glib::signal_idle().connect (mem_fun(*this, &ARDOUR_UI::start_engine));
+       // relax
 }
 
 void
@@ -388,6 +381,8 @@ If you still wish to quit, please use the\n\n\
                        break;
                }
        }
+
+       engine->stop (true);
        Config->save_state();
        quit ();
 }
index 1b7a5572fa9fa8977f643278f48a3995decc70f1..80aad8763c99534aeda5d426b5dbb19c343bf3b2 100644 (file)
@@ -198,6 +198,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI
        void session_add_midi_track ();
 
        void set_engine (ARDOUR::AudioEngine&);
+       gint start_engine ();
 
        gint exit_on_main_window_close (GdkEventAny *);
 
@@ -291,7 +292,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI
        void queue_transport_change ();
        void map_transport_state ();
        int32_t do_engine_start ();
-       gint start_engine ();
        
        void engine_halted ();
        void engine_stopped ();
index adba03b83d8722e6c3edeefb0347ddb259cd8703..21b03f9a63d2c749b5b17055140b4c4ffe90bab6 100644 (file)
@@ -444,7 +444,8 @@ int main (int argc, char *argv[])
                return -1;
        } 
 
-
+       ui->start_engine ();
+       
        if (maybe_load_session ()) {
                ui->run (text_receiver);
                ui = 0;
index 7f42aff40cfade02a2a0dc84e28a9b7605d889ca..7274f5646e451e4153222bf89ca1504d328f0a76 100644 (file)
@@ -61,7 +61,7 @@ class AudioEngine : public sigc::trackable
        bool will_reconnect_at_halt ();
        void set_reconnect_at_halt (bool);
 
-       int stop ();
+       int stop (bool forever = false);
        int start ();
        bool running() const { return _running; }
 
index 89857ac9f57dcf96ea52c2fb860f43b9c329141d..b0e79af38893a0b5057910154dffca3306d60e6b 100644 (file)
@@ -3,13 +3,8 @@
 CONFIG_VARIABLE (AutoConnectOption, output_auto_connect, "output-auto-connect", AutoConnectOption (0))
 CONFIG_VARIABLE (AutoConnectOption, input_auto_connect, "input-auto-connect", AutoConnectOption (0))
 
-#ifdef __APPLE__
-CONFIG_VARIABLE (std::string, auditioner_output_left, "auditioner-output-left",  "coreaudio:Built-in Audio:in1")
-CONFIG_VARIABLE (std::string, auditioner_output_right, "auditioner-output-right", "coreaudio:Built-in Audio:in2")
-#else
-CONFIG_VARIABLE (std::string, auditioner_output_left, "auditioner-output-left", "alsa_pcm:playback_1")
-CONFIG_VARIABLE (std::string, auditioner_output_right, "auditioner-output-right", "alsa_pcm:playback_2")
-#endif
+CONFIG_VARIABLE (std::string, auditioner_output_left, "auditioner-output-left", "default")
+CONFIG_VARIABLE (std::string, auditioner_output_right, "auditioner-output-right", "default")
 
 /* MIDI and MIDI related */
 
index 6ce7f75832195016104836477fc3335ddc1a5578..253cd28b7f8f87b87be4c39a760ba075a6aac0fd 100644 (file)
@@ -1078,7 +1078,6 @@ class Session : public PBD::StatefulDestructible
 
        void hookup_io ();
        void when_engine_running ();
-       sigc::connection first_time_running;
        void graph_reordered ();
 
        string _current_snapshot_name;
@@ -1110,6 +1109,8 @@ class Session : public PBD::StatefulDestructible
        bool              butler_should_run;
        mutable gint      butler_should_do_transport_work;
        int               butler_request_pipe[2];
+
+       inline bool transport_work_requested() const { return g_atomic_int_get(&butler_should_do_transport_work); }
        
        struct ButlerRequest {
            enum Type {
@@ -1383,9 +1384,8 @@ class Session : public PBD::StatefulDestructible
        void realtime_stop (bool abort);
        void non_realtime_start_scrub ();
        void non_realtime_set_speed ();
-       void non_realtime_stop (bool abort);
-       void non_realtime_overwrite ();
-       void non_realtime_buffer_fill ();
+       void non_realtime_stop (bool abort, int entry_request_count, bool& finished);
+       void non_realtime_overwrite (int entry_request_count, bool& finished);
        void butler_transport_work ();
        void post_transport ();
        void engine_halted ();
index 4ea9cd66f8effc6bb91e3360508e62229236dc54..e68dc718d9d352527e558a5c9383cf30ef3b1772 100644 (file)
@@ -148,11 +148,17 @@ AudioEngine::start ()
 }
 
 int
-AudioEngine::stop ()
+AudioEngine::stop (bool forever)
 {
        if (_running) {
                _running = false;
-               jack_deactivate (_jack);
+               if (forever) {
+                       jack_client_t* foo = _jack;
+                       _jack = 0;
+                       jack_client_close (foo);
+               } else {
+                       jack_deactivate (_jack);
+               }
                Stopped(); /* EMIT SIGNAL */
        }
 
@@ -192,7 +198,7 @@ void
 AudioEngine::jack_timebase_callback (jack_transport_state_t state, nframes_t nframes,
                                     jack_position_t* pos, int new_position)
 {
-       if (session && session->synced_to_jack()) {
+       if (_jack && session && session->synced_to_jack()) {
                session->jack_timebase_callback (state, nframes, pos, new_position);
        }
 }
@@ -206,7 +212,7 @@ AudioEngine::_jack_sync_callback (jack_transport_state_t state, jack_position_t*
 int
 AudioEngine::jack_sync_callback (jack_transport_state_t state, jack_position_t* pos)
 {
-       if (session) {
+       if (_jack && session) {
                return session->jack_sync_callback (state, pos);
        } else {
                return true;
@@ -216,14 +222,20 @@ AudioEngine::jack_sync_callback (jack_transport_state_t state, jack_position_t*
 int
 AudioEngine::_xrun_callback (void *arg)
 {
-        static_cast<AudioEngine *>(arg)->Xrun (); /* EMIT SIGNAL */
+       AudioEngine* ae = static_cast<AudioEngine*> (arg);
+       if (ae->jack()) {
+               ae->Xrun (); /* EMIT SIGNAL */
+       }
        return 0;
 }
 
 int
 AudioEngine::_graph_order_callback (void *arg)
 {
-       static_cast<AudioEngine *>(arg)->GraphReordered (); /* EMIT SIGNAL */
+       AudioEngine* ae = static_cast<AudioEngine*> (arg);
+       if (ae->jack()) {
+               ae->GraphReordered (); /* EMIT SIGNAL */
+       }
        return 0;
 }
 
@@ -416,7 +428,6 @@ AudioEngine::remove_session ()
        }
        
        remove_all_ports ();
-
 }
 
 Port *
@@ -718,7 +729,7 @@ AudioEngine::get_ports (const string& port_name_pattern, const string& type_name
 void
 AudioEngine::halted (void *arg)
 {
-       AudioEngine *ae = reinterpret_cast<AudioEngine *> (arg);
+       AudioEngine* ae = static_cast<AudioEngine *> (arg);
 
        ae->_running = false;
        ae->_jack = 0;
index ce6bcd41430f598a25dbc8e981f04daec551f374..84f6f13f1d115f5f8bfb3a3638fb72b8e7eef4f2 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <ardour/audio_diskstream.h>
 #include <ardour/audioregion.h>
+#include <ardour/audioengine.h>
 #include <ardour/route.h>
 #include <ardour/session.h>
 #include <ardour/auditioner.h>
@@ -43,8 +44,17 @@ Auditioner::Auditioner (Session& s)
 {
        string left = Config->get_auditioner_output_left();
        string right = Config->get_auditioner_output_right();
+
+       if (left == "default") {
+               left = _session.engine().get_nth_physical_output (0);   
+       }
+
+       if (right == "default") {
+               right = _session.engine().get_nth_physical_output (1);
+       }
        
        if ((left.length() == 0) && (right.length() == 0)) {
+               warning << _("no outputs available for auditioner - manual connection required") << endmsg;
                return;
        }
 
@@ -182,18 +192,34 @@ Auditioner::play_audition (nframes_t nframes)
 void
 Auditioner::output_changed (IOChange change, void* src)
 {
+       string phys;
+
        if (change & ConnectionsChanged) {
                const char ** connections;
                connections =  output (0)->get_connections ();
                if (connections) {
-                       Config->set_auditioner_output_left (connections[0]);
+                       phys = _session.engine().get_nth_physical_output (0);
+                       if (phys != connections[0]) {
+                               Config->set_auditioner_output_left (connections[0]);
+                       } else {
+                               Config->set_auditioner_output_left ("default");
+                       }
                        free (connections);
+               } else {
+                       Config->set_auditioner_output_left ("");
                }
                
                connections = output (1)->get_connections ();
                if (connections) {
-                       Config->set_auditioner_output_right (connections[0]);
+                       phys = _session.engine().get_nth_physical_output (1);
+                       if (phys != connections[0]) {
+                               Config->set_auditioner_output_right (connections[0]);
+                       } else {
+                               Config->set_auditioner_output_right ("default");
+                       }
                        free (connections);
+               } else {
+                       Config->set_auditioner_output_right ("");
                }
        }
 }
index 62c3fffeb6c01ba23c5aeef7b3a4197c24f368cb..420dd20fcbe918c5add84fc92b1d74ae600df7b5 100644 (file)
@@ -332,7 +332,12 @@ Diskstream::use_playlist (boost::shared_ptr<Playlist> playlist)
                plgone_connection = _playlist->GoingAway.connect (bind (mem_fun (*this, &Diskstream::playlist_deleted), boost::weak_ptr<Playlist>(_playlist)));
        }
 
-       if (!overwrite_queued) {
+       /* don't do this if we've already asked for it *or* if we are setting up
+          the diskstream for the very first time - the input changed handling will
+          take care of the buffer refill.
+       */
+
+       if (!overwrite_queued && !(_session.state_of_the_state() & Session::CannotSave)) {
                _session.request_overwrite_buffer (this);
                overwrite_queued = true;
        }
index caea88138339c5e6f047fa0c95ee67b07476a39e..86770939da36727472ad1ced0e982677f2923d7e 100644 (file)
@@ -630,8 +630,6 @@ Session::when_engine_running ()
 
        /* we don't want to run execute this again */
 
-       first_time_running.disconnect ();
-
        set_block_size (_engine.frames_per_cycle());
        set_frame_rate (_engine.frame_rate());
 
@@ -696,23 +694,6 @@ Session::when_engine_running ()
                // XXX HOW TO ALERT UI TO THIS ? DO WE NEED TO?
        }
 
-       if (auditioner == 0) {
-
-               /* we delay creating the auditioner till now because
-                  it makes its own connections to ports named
-                  in the ARDOUR_RC config file. the engine has
-                  to be running for this to work.
-               */
-
-               try {
-                       auditioner.reset (new Auditioner (*this));
-               }
-
-               catch (failed_constructor& err) {
-                       warning << _("cannot create Auditioner: no auditioning of regions possible") << endmsg;
-               }
-       }
-
        /* Create a set of Connection objects that map
           to the physical outputs currently available
        */
@@ -880,6 +861,23 @@ Session::hookup_io ()
        */
 
        _state_of_the_state = StateOfTheState (_state_of_the_state | InitialConnecting);
+       cerr << "InitialConnecting set\n";
+
+       if (auditioner == 0) {
+               
+               /* we delay creating the auditioner till now because
+                  it makes its own connections to ports.
+                  the engine has to be running for this to work.
+               */
+               
+               try {
+                       auditioner.reset (new Auditioner (*this));
+               }
+               
+               catch (failed_constructor& err) {
+                       warning << _("cannot create Auditioner: no auditioning of regions possible") << endmsg;
+               }
+       }
 
        /* Tell all IO objects to create their ports */
 
@@ -919,6 +917,7 @@ Session::hookup_io ()
        IOConnectionsComplete (); /* EMIT SIGNAL */
 
        _state_of_the_state = StateOfTheState (_state_of_the_state & ~InitialConnecting);
+       cerr << "InitialConnectingUN set\n";
 
        /* now handle the whole enchilada as if it was one
           graph reorder event.
@@ -3260,6 +3259,12 @@ Session::graph_reordered ()
                return;
        }
 
+       /* every track/bus asked for this to be handled but it was deferred because
+          we were connecting. do it now.
+       */
+
+       request_input_change_handling ();
+
        resort_routes ();
 
        /* force all diskstreams to update their capture offset values to 
index 832284901c12580fd0e8e5a406206429733c4ae2..bb02eede91cb7677917feea4e919f19e95fe1774 100644 (file)
@@ -157,8 +157,6 @@ Session::_butler_thread_work (void* arg)
        return 0;
 }
 
-#define transport_work_requested() g_atomic_int_get(&butler_should_do_transport_work)
-
 void *
 Session::butler_thread_work ()
 {
index 6367eaaf1733f028bb2bcf829775ed3bf0edb355..4a2800dcb1bd1db8e0def1fd4dda4b302863084e 100644 (file)
@@ -305,9 +305,14 @@ Session::process_event (Event* ev)
        */
 
        if (non_realtime_work_pending()) {
-               immediate_events.insert (immediate_events.end(), ev);
-               _remove_event (ev);
-               return;
+               
+               /* except locates, which we have the capability to handle */
+
+               if (ev->type != Event::Locate) {
+                       immediate_events.insert (immediate_events.end(), ev);
+                       _remove_event (ev);
+                       return;
+               }
        }
 
        switch (ev->type) {
index 9b051252b19c26606de96e7626275af92064b6eb..06ba4e304ec5ba67cc3c8b5e39ecad4a6c5438d3 100644 (file)
@@ -53,7 +53,7 @@ Session::process (nframes_t nframes)
        }
 
        if (non_realtime_work_pending()) {
-               if (g_atomic_int_get (&butler_should_do_transport_work) == 0) {
+               if (!transport_work_requested ()) {
                        post_transport ();
                } 
        } 
index 2ae8a833e13f2bd3c2ed3f8a8a31d12ef76264a2..a34b3ec52b0a49c9a5841bf9123b9dcda4d86289 100644 (file)
@@ -54,6 +54,7 @@
 #include <pbd/pathscanner.h>
 #include <pbd/pthread_utils.h>
 #include <pbd/strsplit.h>
+#include <pbd/stacktrace.h>
 
 #include <ardour/audioengine.h>
 #include <ardour/configuration.h>
@@ -306,11 +307,7 @@ Session::second_stage_init (bool new_session)
        _engine.Halted.connect (mem_fun (*this, &Session::engine_halted));
        _engine.Xrun.connect (mem_fun (*this, &Session::xrun_recovery));
 
-       if (_engine.running()) {
-               when_engine_running();
-       } else {
-               first_time_running = _engine.Running.connect (mem_fun (*this, &Session::when_engine_running));
-       }
+       when_engine_running();
 
        send_full_time_code ();
        _engine.transport_locate (0);
@@ -586,15 +583,34 @@ Session::save_state (string snapshot_name, bool pending)
                xml_path = _path;
                xml_path += snapshot_name;
                xml_path += _statefile_suffix;
+
                bak_path = xml_path;
                bak_path += ".bak";
                
-               // Make backup of state file
+               if (g_file_test (xml_path.c_str(), G_FILE_TEST_EXISTS)) {
+
+                       // Make backup of state file
                
-               if ((access (xml_path.c_str(), F_OK) == 0) &&
-                   (rename(xml_path.c_str(), bak_path.c_str()))) {
-                       error << _("could not backup old state file, current state not saved.") << endmsg;
-                       return -1;
+                       ifstream in (xml_path.c_str());
+                       ofstream out (bak_path.c_str());
+
+                       if (!in) {
+                               error << string_compose (_("Could not open existing session file %1 for backup"), xml_path) << endmsg;
+                               return -1;
+                       }
+
+                       if (!out) {
+                               error << string_compose (_("Could not open backup session file %1"), bak_path) << endmsg;
+                               return -1;
+                       }
+
+                       out << in.rdbuf();
+
+                       if (!in || !out) {
+                               error << string_compose (_("Could not copy existing session file %1 to %2 for backup"), xml_path, bak_path) << endmsg;
+                               unlink (bak_path.c_str());
+                               return -1;
+                       }
                }
 
        } else {
@@ -605,30 +621,31 @@ Session::save_state (string snapshot_name, bool pending)
 
        }
 
+       string tmp_path;
+
+       tmp_path = _path;
+       tmp_path += snapshot_name;
+       tmp_path += ".tmp";
+
        cerr << "actually writing state\n";
 
-       if (!tree.write (xml_path)) {
-               error << string_compose (_("state could not be saved to %1"), xml_path) << endmsg;
+       if (!tree.write (tmp_path)) {
+               error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
+               unlink (tmp_path.c_str());
+               return -1;
 
-               /* don't leave a corrupt file lying around if it is
-                  possible to fix.
-               */
+       } else {
 
-               if (unlink (xml_path.c_str())) {
-                       error << string_compose (_("could not remove corrupt state file %1"), xml_path) << endmsg;
-               } else {
-                       if (!pending) {
-                               if (rename (bak_path.c_str(), xml_path.c_str())) {
-                                       error << string_compose (_("could not restore state file from backup %1"), bak_path) << endmsg;
-                               }
-                       }
+               if (rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
+                       error << string_compose (_("could not rename temporary session file %1 to %2"), tmp_path, xml_path) << endmsg;
+                       unlink (tmp_path.c_str());
+                       return -1;
                }
-
-               return -1;
        }
 
        if (!pending) {
-                save_history(snapshot_name);
+
+                save_history (snapshot_name);
 
                bool was_dirty = dirty();
 
index bbdf3a073f52f3469b8609446bfe0582909a49d8..19380c57c0e1b6fc984d9cd3091baec3e48f6b2a 100644 (file)
@@ -30,6 +30,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>
@@ -52,8 +53,11 @@ using namespace PBD;
 void
 Session::request_input_change_handling ()
 {
-       Event* ev = new Event (Event::InputConfigurationChange, Event::Add, Event::Immediate, 0, 0.0);
-       queue_event (ev);
+       if (!(_state_of_the_state & (InitialConnecting|Deletion))) {
+               stacktrace (cerr);
+               Event* ev = new Event (Event::InputConfigurationChange, Event::Add, Event::Immediate, 0, 0.0);
+               queue_event (ev);
+       }
 }
 
 void
@@ -180,9 +184,14 @@ Session::realtime_stop (bool abort)
 void
 Session::butler_transport_work ()
 {
+  restart:
+       bool finished;
        boost::shared_ptr<RouteList> r = routes.reader ();
        boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
 
+       int on_entry = g_atomic_int_get (&butler_should_do_transport_work);
+       finished = true;
+
        if (post_transport_work & PostTransportCurveRealloc) {
                for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                        (*i)->curve_reallocate();
@@ -206,30 +215,48 @@ Session::butler_transport_work ()
                cumulative_rf_motion = 0;
                reset_rf_scale (0);
 
-               for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
-                       if (!(*i)->hidden()) {
-                               if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
-                                       (*i)->seek ((nframes_t) (_transport_frame * (double) (*i)->speed()));
+               /* don't seek if locate will take care of that in non_realtime_stop() */
+
+               if (!(post_transport_work & PostTransportLocate)) {
+                       
+                       for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
+                               if (!(*i)->hidden()) {
+                                       if ((*i)->speed() != 1.0f || (*i)->speed() != -1.0f) {
+                                               (*i)->seek ((nframes_t) (_transport_frame * (double) (*i)->speed()));
+                                       }
+                                       else {
+                                               (*i)->seek (_transport_frame);
+                                       }
                                }
-                               else {
-                                       (*i)->seek (_transport_frame);
+                               if (on_entry != g_atomic_int_get (&butler_should_do_transport_work)) {
+                                       /* new request, stop seeking, and start again */
+                                       g_atomic_int_dec_and_test (&butler_should_do_transport_work);
+                                       goto restart;
                                }
                        }
                }
        }
 
        if (post_transport_work & (PostTransportStop|PostTransportLocate)) {
-               non_realtime_stop (post_transport_work & PostTransportAbort);
+               non_realtime_stop (post_transport_work & PostTransportAbort, on_entry, finished);
+               if (!finished) {
+                       g_atomic_int_dec_and_test (&butler_should_do_transport_work);
+                       goto restart;
+               }
        }
 
        if (post_transport_work & PostTransportOverWrite) {
-               non_realtime_overwrite ();
+               non_realtime_overwrite (on_entry, finished);
+               if (!finished) {
+                       g_atomic_int_dec_and_test (&butler_should_do_transport_work);
+                       goto restart;
+               }
        }
 
        if (post_transport_work & PostTransportAudition) {
                non_realtime_set_audition ();
        }
-
+       
        g_atomic_int_dec_and_test (&butler_should_do_transport_work);
 }
 
@@ -244,7 +271,7 @@ Session::non_realtime_set_speed ()
 }
 
 void
-Session::non_realtime_overwrite ()
+Session::non_realtime_overwrite (int on_entry, bool& finished)
 {
        boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
 
@@ -252,11 +279,15 @@ Session::non_realtime_overwrite ()
                if ((*i)->pending_overwrite) {
                        (*i)->overwrite_existing_buffers ();
                }
+               if (on_entry != g_atomic_int_get (&butler_should_do_transport_work)) {
+                       finished = false;
+                       return;
+               }
        }
 }
 
 void
-Session::non_realtime_stop (bool abort)
+Session::non_realtime_stop (bool abort, int on_entry, bool& finished)
 {
        struct tm* now;
        time_t     xnow;
@@ -371,6 +402,11 @@ Session::non_realtime_stop (bool abort)
                                        (*i)->seek (_transport_frame);
                                }
                        }
+                       if (on_entry != g_atomic_int_get (&butler_should_do_transport_work)) {
+                               finished = false;
+                               /* we will be back */
+                               return;
+                       }
                }
 #ifdef LEAVE_TRANSPORT_UNADJUSTED
        }
@@ -622,6 +658,8 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w
 
        } else {
 
+               cerr << "butler not requested\n";
+
                /* this is functionally what clear_clicks() does but with a tentative lock */
 
                Glib::RWLock::WriterLock clickm (click_lock, Glib::TRY_LOCK);
@@ -892,7 +930,6 @@ Session::post_transport ()
        if (post_transport_work & PostTransportLocate) {
 
                if ((Config->get_auto_play() && !_exporting) || (post_transport_work & PostTransportRoll)) {
-                       
                        start_transport ();
                        
                } else {
@@ -1123,6 +1160,8 @@ Session::request_bounded_roll (nframes_t start, nframes_t end)
 void
 Session::engine_halted ()
 {
+       bool ignored;
+
        /* there will be no more calls to process(), so
           we'd better clean up for ourselves, right now.
 
@@ -1135,7 +1174,7 @@ Session::engine_halted ()
        stop_butler ();
        
        realtime_stop (false);
-       non_realtime_stop (false);
+       non_realtime_stop (false, 0, ignored);
        transport_sub_state = 0;
 
        TransportStateChange (); /* EMIT SIGNAL */