diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2006-12-15 19:40:10 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2006-12-15 19:40:10 +0000 |
commit | 7e845c53ab95f4fd33c8327bf3dff9bdb82a7a18 (patch) | |
tree | 21948926eb794efa7bb48111deccb64291899883 /libs | |
parent | e80214b71d9e38be55290cb594616a42d1e8c5e7 (diff) |
write session file to alternate name before, then rename; auditioner defaults to first 2 physical outputs; engine started before loading session, always; clean up handling off input connections and so forth during startup (faster! a bitcd ..); notice new locates while doing older ones; stop engine at shutdown first, not later
git-svn-id: svn://localhost/ardour2/trunk@1214 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
-rw-r--r-- | libs/ardour/ardour/audioengine.h | 2 | ||||
-rw-r--r-- | libs/ardour/ardour/configuration_vars.h | 9 | ||||
-rw-r--r-- | libs/ardour/ardour/session.h | 8 | ||||
-rw-r--r-- | libs/ardour/audioengine.cc | 27 | ||||
-rw-r--r-- | libs/ardour/auditioner.cc | 30 | ||||
-rw-r--r-- | libs/ardour/diskstream.cc | 7 | ||||
-rw-r--r-- | libs/ardour/session.cc | 43 | ||||
-rw-r--r-- | libs/ardour/session_butler.cc | 2 | ||||
-rw-r--r-- | libs/ardour/session_events.cc | 11 | ||||
-rw-r--r-- | libs/ardour/session_process.cc | 2 | ||||
-rw-r--r-- | libs/ardour/session_state.cc | 69 | ||||
-rw-r--r-- | libs/ardour/session_transport.cc | 69 |
12 files changed, 190 insertions, 89 deletions
diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h index 7f42aff40c..7274f5646e 100644 --- a/libs/ardour/ardour/audioengine.h +++ b/libs/ardour/ardour/audioengine.h @@ -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; } diff --git a/libs/ardour/ardour/configuration_vars.h b/libs/ardour/ardour/configuration_vars.h index 89857ac9f5..b0e79af388 100644 --- a/libs/ardour/ardour/configuration_vars.h +++ b/libs/ardour/ardour/configuration_vars.h @@ -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 */ diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 6ce7f75832..253cd28b7f 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -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 (); diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 4ea9cd66f8..e68dc718d9 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -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; diff --git a/libs/ardour/auditioner.cc b/libs/ardour/auditioner.cc index ce6bcd4143..84f6f13f1d 100644 --- a/libs/ardour/auditioner.cc +++ b/libs/ardour/auditioner.cc @@ -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 (""); } } } diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc index 62c3fffeb6..420dd20fcb 100644 --- a/libs/ardour/diskstream.cc +++ b/libs/ardour/diskstream.cc @@ -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; } diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index caea881383..86770939da 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -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 diff --git a/libs/ardour/session_butler.cc b/libs/ardour/session_butler.cc index 832284901c..bb02eede91 100644 --- a/libs/ardour/session_butler.cc +++ b/libs/ardour/session_butler.cc @@ -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 () { diff --git a/libs/ardour/session_events.cc b/libs/ardour/session_events.cc index 6367eaaf17..4a2800dcb1 100644 --- a/libs/ardour/session_events.cc +++ b/libs/ardour/session_events.cc @@ -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) { diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc index 9b051252b1..06ba4e304e 100644 --- a/libs/ardour/session_process.cc +++ b/libs/ardour/session_process.cc @@ -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 (); } } diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index 2ae8a833e1..a34b3ec52b 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -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(); diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index bbdf3a073f..19380c57c0 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -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 */ |