summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/ardour_ui.cc6
-rw-r--r--gtk2_ardour/ardour_ui.h2
-rw-r--r--gtk2_ardour/engine_dialog.cc24
-rw-r--r--gtk2_ardour/engine_dialog.h19
-rw-r--r--libs/ardour/ardour/session.h12
-rw-r--r--libs/ardour/port.cc4
-rw-r--r--libs/ardour/session.cc424
-rw-r--r--libs/ardour/session_state.cc179
8 files changed, 380 insertions, 290 deletions
diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc
index d6c6863b14..4992e0a14b 100644
--- a/gtk2_ardour/ardour_ui.cc
+++ b/gtk2_ardour/ardour_ui.cc
@@ -268,7 +268,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
/* handle Audio/MIDI setup when session requires it */
- ARDOUR::Session::AudioEngineSetupRequired.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::do_audio_midi_setup, this));
+ ARDOUR::Session::AudioEngineSetupRequired.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::do_audio_midi_setup, this, _1));
/* handle sr mismatch with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
@@ -4159,10 +4159,12 @@ ARDOUR_UI::launch_audio_midi_setup ()
}
int
-ARDOUR_UI::do_audio_midi_setup ()
+ARDOUR_UI::do_audio_midi_setup (uint32_t desired_sample_rate)
{
launch_audio_midi_setup ();
+ _audio_midi_setup->set_desired_sample_rate (desired_sample_rate);
+
int r = _audio_midi_setup->run ();
switch (r) {
diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h
index 77e81fd23a..fa8eb18f01 100644
--- a/gtk2_ardour/ardour_ui.h
+++ b/gtk2_ardour/ardour_ui.h
@@ -750,7 +750,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
EngineControl* _audio_midi_setup;
void launch_audio_midi_setup ();
- int do_audio_midi_setup ();
+ int do_audio_midi_setup (uint32_t);
};
#endif /* __ardour_gui_h__ */
diff --git a/gtk2_ardour/engine_dialog.cc b/gtk2_ardour/engine_dialog.cc
index b03dc9a304..b97a7133e6 100644
--- a/gtk2_ardour/engine_dialog.cc
+++ b/gtk2_ardour/engine_dialog.cc
@@ -65,6 +65,7 @@ EngineControl::EngineControl ()
, control_app_button (_("Launch Control App"))
, basic_packer (9, 3)
, ignore_changes (0)
+ , _desired_sample_rate (0)
{
build_notebook ();
@@ -340,6 +341,8 @@ EngineControl::device_changed ()
ignore_changes++;
/* sample rates */
+
+ string desired;
vector<float> sr = backend->available_sample_rates (device_name);
for (vector<float>::const_iterator x = sr.begin(); x != sr.end(); ++x) {
@@ -350,11 +353,17 @@ EngineControl::device_changed ()
snprintf (buf, sizeof (buf), "%.0f kHz", (*x)/1000.0);
}
s.push_back (buf);
+ if (*x == _desired_sample_rate) {
+ desired = buf;
+ }
}
set_popdown_strings (sample_rate_combo, s);
- sample_rate_combo.set_active_text (s.front());
-
+ if (desired.empty()) {
+ sample_rate_combo.set_active_text (s.front());
+ } else {
+ sample_rate_combo.set_active_text (desired);
+ }
vector<uint32_t> bs = backend->available_buffer_sizes(device_name);
s.clear ();
@@ -514,7 +523,9 @@ EngineControl::maybe_display_saved_state ()
if (state) {
ignore_changes++;
- sample_rate_combo.set_active_text (state->sample_rate);
+ if (!_desired_sample_rate) {
+ sample_rate_combo.set_active_text (state->sample_rate);
+ }
buffer_size_combo.set_active_text (state->buffer_size);
input_latency.set_value (state->input_latency);
output_latency.set_value (state->output_latency);
@@ -843,3 +854,10 @@ EngineControl::manage_control_app_sensitivity ()
control_app_button.set_sensitive (true);
}
}
+
+void
+EngineControl::set_desired_sample_rate (uint32_t sr)
+{
+ _desired_sample_rate = sr;
+ device_changed ();
+}
diff --git a/gtk2_ardour/engine_dialog.h b/gtk2_ardour/engine_dialog.h
index cdeb18a2c7..a92d0629f2 100644
--- a/gtk2_ardour/engine_dialog.h
+++ b/gtk2_ardour/engine_dialog.h
@@ -37,14 +37,16 @@
class EngineControl : public ArdourDialog {
public:
- EngineControl ();
- ~EngineControl ();
-
- static bool need_setup ();
-
- XMLNode& get_state ();
- void set_state (const XMLNode&);
-
+ EngineControl ();
+ ~EngineControl ();
+
+ static bool need_setup ();
+
+ XMLNode& get_state ();
+ void set_state (const XMLNode&);
+
+ void set_desired_sample_rate (uint32_t);
+
private:
Gtk::Notebook notebook;
@@ -153,6 +155,7 @@ class EngineControl : public ArdourDialog {
void control_app_button_clicked ();
void manage_control_app_sensitivity ();
int push_state_to_backend (bool start);
+ uint32_t _desired_sample_rate;
};
#endif /* __gtk2_ardour_engine_dialog_h__ */
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index 7ef7fde07a..09bf75276d 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -558,7 +558,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
/** handlers should return 0 for "everything OK", and any other value for
* "cannot setup audioengine".
*/
- static PBD::Signal0<int> AudioEngineSetupRequired;
+ static PBD::Signal1<int,uint32_t> AudioEngineSetupRequired;
/** handlers should return -1 for "stop cleanup",
0 for "yes, delete this playlist",
@@ -1071,7 +1071,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
boost::scoped_ptr<SessionDirectory> _session_dir;
void hookup_io ();
- void when_engine_running ();
+ int when_engine_running ();
void graph_reordered ();
/** current snapshot name, without the .ardour suffix */
@@ -1137,8 +1137,8 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
void auto_loop_changed (Location *);
void auto_loop_declick_range (Location *, framepos_t &, framepos_t &);
- void first_stage_init (std::string path, std::string snapshot_name);
- int second_stage_init ();
+ void pre_engine_init (std::string path);
+ int post_engine_init ();
void remove_empty_sounds ();
void setup_midi_control ();
@@ -1620,6 +1620,10 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
/* persistent, non-track related MIDI ports */
MidiPortManager* _midi_ports;
MIDI::MachineControl* _mmc;
+
+ void setup_ltc ();
+ void setup_click ();
+ void setup_bundles ();
};
} // namespace ARDOUR
diff --git a/libs/ardour/port.cc b/libs/ardour/port.cc
index 8fadad4fcc..e8629cbf14 100644
--- a/libs/ardour/port.cc
+++ b/libs/ardour/port.cc
@@ -153,8 +153,10 @@ Port::connect (std::string const & other)
}
if (sends_output ()) {
+ DEBUG_TRACE (DEBUG::Ports, string_compose ("Connect %1 to %2\n", our_name, other_name));
r = port_engine.connect (our_name, other_name);
} else {
+ DEBUG_TRACE (DEBUG::Ports, string_compose ("Connect %1 to %2\n", other_name, our_name));
r = port_engine.connect (other_name, our_name);
}
@@ -420,6 +422,8 @@ Port::reconnect ()
{
/* caller must hold process lock; intended to be used only after reestablish() */
+ DEBUG_TRACE (DEBUG::Ports, string_compose ("Connect %1 to %2 destinations\n",name(), _connections.size()));
+
for (std::set<string>::iterator i = _connections.begin(); i != _connections.end(); ++i) {
if (connect (*i)) {
return -1;
diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
index 687469e5a5..9934d5a095 100644
--- a/libs/ardour/session.cc
+++ b/libs/ardour/session.cc
@@ -107,7 +107,7 @@ using namespace PBD;
bool Session::_disable_all_loaded_plugins = false;
-PBD::Signal0<int> Session::AudioEngineSetupRequired;
+PBD::Signal1<int,uint32_t> Session::AudioEngineSetupRequired;
PBD::Signal1<void,std::string> Session::Dialog;
PBD::Signal0<int> Session::AskAboutPendingState;
PBD::Signal2<int, framecnt_t, framecnt_t> Session::AskAboutSampleRateMismatch;
@@ -132,106 +132,137 @@ Session::Session (AudioEngine &eng,
const string& snapshot_name,
BusProfile* bus_profile,
string mix_template)
- : _engine (eng)
+ : playlists (new SessionPlaylists)
+ , _engine (eng)
+ , process_function (&Session::process_with_events)
+ , waiting_for_sync_offset (false)
+ , _base_frame_rate (0)
+ , _current_frame_rate (0)
+ , _nominal_frame_rate (0)
+ , transport_sub_state (0)
+ , _record_status (Disabled)
+ , _transport_frame (0)
+ , _session_range_location (0)
+ , _slave (0)
+ , _silent (false)
+ , _transport_speed (0)
+ , _default_transport_speed (1.0)
+ , _last_transport_speed (0)
, _target_transport_speed (0.0)
+ , auto_play_legal (false)
+ , _last_slave_transport_frame (0)
+ , maximum_output_latency (0)
, _requested_return_frame (-1)
+ , current_block_size (0)
+ , _worst_output_latency (0)
+ , _worst_input_latency (0)
+ , _worst_track_latency (0)
+ , _have_captured (false)
+ , _meter_hold (0)
+ , _meter_falloff (0)
+ , _non_soloed_outs_muted (false)
+ , _listen_cnt (0)
+ , _solo_isolated_cnt (0)
+ , _writable (false)
+ , _was_seamless (Config->get_seamless_loop ())
, _under_nsm_control (false)
+ , delta_accumulator_cnt (0)
+ , average_slave_delta (1800) // !!! why 1800 ???
+ , average_dir (0)
+ , have_first_delta_accumulator (false)
+ , _slave_state (Stopped)
+ , post_export_sync (false)
+ , post_export_position (0)
+ , _exporting (false)
+ , _export_started (false)
+ , _export_rolling (false)
+ , _pre_export_mmc_enabled (false)
+ , _name (snapshot_name)
+ , _is_new (true)
+ , _send_qf_mtc (false)
+ , _pframes_since_last_mtc (0)
+ , session_midi_feedback (0)
+ , play_loop (false)
+ , loop_changing (false)
+ , last_loopend (0)
, _session_dir (new SessionDirectory (fullpath))
+ , _current_snapshot_name (snapshot_name)
, state_tree (0)
+ , state_was_pending (false)
, _state_of_the_state (StateOfTheState(CannotSave|InitialConnecting|Loading))
+ , _last_roll_location (0)
+ , _last_roll_or_reversal_location (0)
+ , _last_record_location (0)
+ , pending_locate_roll (false)
+ , pending_locate_frame (0)
+ , pending_locate_flush (false)
+ , pending_abort (false)
+ , pending_auto_loop (false)
, _butler (new Butler (*this))
, _post_transport_work (0)
+ , cumulative_rf_motion (0)
+ , rf_scale (1.0)
+ , _locations (new Locations (*this))
+ , step_speed (0)
+ , outbound_mtc_timecode_frame (0)
+ , next_quarter_frame_to_send (-1)
+ , _frames_per_timecode_frame (0)
+ , _frames_per_hour (0)
+ , _timecode_frames_per_hour (0)
+ , last_timecode_valid (false)
+ , last_timecode_when (0)
, _send_timecode_update (false)
+ , ltc_encoder (0)
, ltc_enc_buf(0)
+ , ltc_buf_off (0)
+ , ltc_buf_len (0)
+ , ltc_speed (0)
+ , ltc_enc_byte (0)
+ , ltc_enc_pos (0)
+ , ltc_enc_cnt (0)
+ , ltc_enc_off (0)
+ , restarting (false)
+ , ltc_prev_cycle (0)
+ , ltc_timecode_offset (0)
+ , ltc_timecode_negative_offset (false)
+ , midi_control_ui (0)
+ , _tempo_map (0)
, _all_route_group (new RouteGroup (*this, "all"))
, routes (new RouteList)
+ , _adding_routes_in_progress (false)
+ , destructive_index (0)
+ , solo_update_disabled (false)
+ , default_fade_steepness (0)
+ , default_fade_msecs (0)
, _total_free_4k_blocks (0)
, _total_free_4k_blocks_uncertain (false)
+ , no_questions_about_missing_files (false)
+ , _playback_load (0)
+ , _capture_load (0)
, _bundles (new BundleList)
, _bundle_xml_node (0)
, _current_trans (0)
+ , _clicking (false)
, click_data (0)
, click_emphasis_data (0)
- , main_outs (0)
- , _have_rec_enabled_track (false)
- , _suspend_timecode_transmission (0)
- , _non_soloed_outs_muted (false)
- , _listen_cnt (0)
- , _solo_isolated_cnt (0)
- , _transport_speed (0)
- , _default_transport_speed (1.0)
- , _last_transport_speed (0)
- , auto_play_legal (false)
- , transport_sub_state (0)
- , _transport_frame (0)
- , _session_range_location (0)
- , loop_changing (false)
- , play_loop (false)
- , have_looped (false)
- , _last_roll_location (0)
- , _last_roll_or_reversal_location (0)
- , _last_record_location (0)
- , pending_locate_frame (0)
- , pending_locate_roll (false)
- , pending_locate_flush (false)
- , state_was_pending (false)
- , outbound_mtc_timecode_frame (0)
- , next_quarter_frame_to_send (-1)
- , current_block_size (0)
- , solo_update_disabled (false)
- , _have_captured (false)
- , _worst_output_latency (0)
- , _worst_input_latency (0)
- , _worst_track_latency (0)
- , _was_seamless (Config->get_seamless_loop ())
- , _slave (0)
- , _send_qf_mtc (false)
- , _pframes_since_last_mtc (0)
+ , click_length (0)
+ , click_emphasis_length (0)
+ , _clicks_cleared (0)
, _play_range (false)
- , _exporting (false)
- , pending_abort (false)
- , _adding_routes_in_progress (false)
- , destructive_index (0)
+ , main_outs (0)
, first_file_data_format_reset (true)
, first_file_header_format_reset (true)
- , post_export_sync (false)
- , midi_control_ui (0)
+ , have_looped (false)
+ , _have_rec_enabled_track (false)
, _step_editors (0)
- , no_questions_about_missing_files (false)
+ , _suspend_timecode_transmission (0)
, _speakers (new Speakers)
- , _clicks_cleared (0)
, ignore_route_processor_changes (false)
- , _pre_export_mmc_enabled (false)
- , _locations (new Locations (*this))
- , ltc_encoder (0)
- , playlists (new SessionPlaylists)
- , _name (snapshot_name)
- , _current_snapshot_name (snapshot_name)
- , step_speed (0.0)
- , click_length (0)
- , click_emphasis_length (0)
- , _clicking (false)
- , process_function (&Session::process_with_events)
- , last_timecode_when (0)
- , last_timecode_valid (false)
- , average_slave_delta (1800) // !!! why 1800 ???
- , have_first_delta_accumulator (false)
- , delta_accumulator_cnt (0)
- , _slave_state (Stopped)
{
- if (_engine.current_backend() == 0 || _engine.setup_required()) {
- boost::optional<int> r = AudioEngineSetupRequired ();
- if (r.get_value_or (-1) != 0) {
- throw failed_constructor();
- }
- }
-
- if (!_engine.connected()) {
- throw failed_constructor();
- }
-
- first_stage_init (fullpath, snapshot_name);
+ uint32_t sr = 0;
+ pre_engine_init (fullpath);
+
if (_is_new) {
if (create (mix_template, bus_profile)) {
destroy ();
@@ -241,14 +272,44 @@ Session::Session (AudioEngine &eng,
if (load_state (_current_snapshot_name)) {
throw failed_constructor ();
}
+
+ /* try to get sample rate from XML state so that we
+ * can influence the SR if we set up the audio
+ * engine.
+ */
+
+ if (state_tree) {
+ const XMLProperty* prop;
+ if ((prop = state_tree->root()->property (X_("sample-rate"))) != 0) {
+ sr = atoi (prop->value());
+ }
+ }
+ }
+
+ if (_engine.current_backend() == 0 || _engine.setup_required()) {
+ boost::optional<int> r = AudioEngineSetupRequired (sr);
+ if (r.get_value_or (-1) != 0) {
+ destroy ();
+ throw failed_constructor();
+ }
}
- if (second_stage_init ()) {
+ /* at this point the engine should be connected (i.e. interacting
+ with a backend device (or psuedo-device) and available to us
+ for determinining sample rates and other settings.
+ */
+
+ if (!_engine.connected()) {
+ destroy ();
+ throw failed_constructor();
+ }
+
+ if (post_engine_init ()) {
destroy ();
throw failed_constructor ();
}
- store_recent_sessions(_name, _path);
+ store_recent_sessions (_name, _path);
bool was_dirty = dirty();
@@ -397,135 +458,103 @@ Session::destroy ()
}
void
-Session::when_engine_running ()
+Session::setup_ltc ()
{
- string first_physical_output;
-
- BootMessage (_("Set block size and sample rate"));
-
- set_block_size (_engine.samples_per_cycle());
- set_frame_rate (_engine.sample_rate());
-
- BootMessage (_("Using configuration"));
-
- boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
- boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
-
- Config->map_parameters (ff);
- config.map_parameters (ft);
-
- /* every time we reconnect, recompute worst case output latencies */
-
- _engine.Running.connect_same_thread (*this, boost::bind (&Session::initialize_latencies, this));
-
- if (synced_to_jack()) {
- _engine.transport_stop ();
+ XMLNode* child = 0;
+
+ _ltc_input.reset (new IO (*this, _("LTC In"), IO::Input));
+ _ltc_output.reset (new IO (*this, _("LTC Out"), IO::Output));
+
+ if (state_tree && (child = find_named_node (*state_tree->root(), "LTC-In")) != 0) {
+ _ltc_input->set_state (*(child->children().front()), Stateful::loading_state_version);
+ } else {
+ {
+ Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+ _ltc_input->ensure_io (ChanCount (DataType::AUDIO, 1), true, this);
+ }
+ reconnect_ltc_input ();
}
-
- if (config.get_jack_time_master()) {
- _engine.transport_locate (_transport_frame);
+
+ if (state_tree && (child = find_named_node (*state_tree->root(), "LTC-Out")) != 0) {
+ _ltc_output->set_state (*(child->children().front()), Stateful::loading_state_version);
+ } else {
+ {
+ Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+ _ltc_output->ensure_io (ChanCount (DataType::AUDIO, 1), true, this);
+ }
+ reconnect_ltc_output ();
}
+
+ /* fix up names of LTC ports because we don't want the normal
+ * IO style of NAME/TYPE-{in,out}N
+ */
+
+ _ltc_input->nth (0)->set_name (_("LTC-in"));
+ _ltc_output->nth (0)->set_name (_("LTC-out"));
+}
- _clicking = false;
+void
+Session::setup_click ()
+{
+ XMLNode* child = 0;
- try {
- XMLNode* child = 0;
+ _clicking = false;
+ _click_io.reset (new ClickIO (*this, "click"));
+ _click_gain.reset (new Amp (*this));
+ _click_gain->activate ();
+
+ if (state_tree && (child = find_named_node (*state_tree->root(), "Click")) != 0) {
- _ltc_input.reset (new IO (*this, _("LTC In"), IO::Input));
- _ltc_output.reset (new IO (*this, _("LTC Out"), IO::Output));
+ /* existing state for Click */
+ int c = 0;
- if (state_tree && (child = find_named_node (*state_tree->root(), "LTC-In")) != 0) {
- _ltc_input->set_state (*(child->children().front()), Stateful::loading_state_version);
+ if (Stateful::loading_state_version < 3000) {
+ c = _click_io->set_state_2X (*child->children().front(), Stateful::loading_state_version, false);
} else {
- {
- Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
- _ltc_input->ensure_io (ChanCount (DataType::AUDIO, 1), true, this);
- }
- reconnect_ltc_input ();
- }
-
- if (state_tree && (child = find_named_node (*state_tree->root(), "LTC-Out")) != 0) {
- _ltc_output->set_state (*(child->children().front()), Stateful::loading_state_version);
- } else {
- {
- Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
- _ltc_output->ensure_io (ChanCount (DataType::AUDIO, 1), true, this);
- }
- reconnect_ltc_output ();
- }
-
- /* fix up names of LTC ports because we don't want the normal
- * IO style of NAME/TYPE-{in,out}N
- */
-
- _ltc_input->nth (0)->set_name (_("LTC-in"));
- _ltc_output->nth (0)->set_name (_("LTC-out"));
-
- _click_io.reset (new ClickIO (*this, "click"));
- _click_gain.reset (new Amp (*this));
- _click_gain->activate ();
-
- if (state_tree && (child = find_named_node (*state_tree->root(), "Click")) != 0) {
-
- /* existing state for Click */
- int c = 0;
-
- if (Stateful::loading_state_version < 3000) {
- c = _click_io->set_state_2X (*child->children().front(), Stateful::loading_state_version, false);
- } else {
- const XMLNodeList& children (child->children());
- XMLNodeList::const_iterator i = children.begin();
- if ((c = _click_io->set_state (**i, Stateful::loading_state_version)) == 0) {
- ++i;
- if (i != children.end()) {
- c = _click_gain->set_state (**i, Stateful::loading_state_version);
- }
+ const XMLNodeList& children (child->children());
+ XMLNodeList::const_iterator i = children.begin();
+ if ((c = _click_io->set_state (**i, Stateful::loading_state_version)) == 0) {
+ ++i;
+ if (i != children.end()) {
+ c = _click_gain->set_state (**i, Stateful::loading_state_version);
}
}
+ }
- if (c == 0) {
- _clicking = Config->get_clicking ();
+ if (c == 0) {
+ _clicking = Config->get_clicking ();
- } else {
+ } else {
- error << _("could not setup Click I/O") << endmsg;
- _clicking = false;
- }
+ error << _("could not setup Click I/O") << endmsg;
+ _clicking = false;
+ }
- } else {
+ } else {
- /* default state for Click: dual-mono to first 2 physical outputs */
+ /* default state for Click: dual-mono to first 2 physical outputs */
- vector<string> outs;
- _engine.get_physical_outputs (DataType::AUDIO, outs);
+ vector<string> outs;
+ _engine.get_physical_outputs (DataType::AUDIO, outs);
- for (uint32_t physport = 0; physport < 2; ++physport) {
- if (outs.size() > physport) {
- if (_click_io->add_port (outs[physport], this)) {
- // relax, even though its an error
- }
+ for (uint32_t physport = 0; physport < 2; ++physport) {
+ if (outs.size() > physport) {
+ if (_click_io->add_port (outs[physport], this)) {
+ // relax, even though its an error
}
}
-
- if (_click_io->n_ports () > ChanCount::ZERO) {
- _clicking = Config->get_clicking ();
- }
}
- }
- catch (failed_constructor& err) {
- error << _("cannot setup Click I/O") << endmsg;
- }
-
- BootMessage (_("Compute I/O Latencies"));
-
- if (_clicking) {
- // XXX HOW TO ALERT UI TO THIS ? DO WE NEED TO?
+ if (_click_io->n_ports () > ChanCount::ZERO) {
+ _clicking = Config->get_clicking ();
+ }
}
+}
- BootMessage (_("Set up standard connections"));
-
+void
+Session::setup_bundles ()
+{
vector<string> inputs[DataType::num_types];
vector<string> outputs[DataType::num_types];
for (uint32_t i = 0; i < DataType::num_types; ++i) {
@@ -624,6 +653,37 @@ Session::when_engine_running ()
add_bundle (c);
}
+}
+
+int
+Session::when_engine_running ()
+{
+ /* every time we reconnect, recompute worst case output latencies */
+
+ _engine.Running.connect_same_thread (*this, boost::bind (&Session::initialize_latencies, this));
+
+ if (synced_to_jack()) {
+ _engine.transport_stop ();
+ }
+
+ if (config.get_jack_time_master()) {
+ _engine.transport_locate (_transport_frame);
+ }
+
+
+ try {
+ BootMessage (_("Set up LTC"));
+ setup_ltc ();
+ BootMessage (_("Set up Click"));
+ setup_click ();
+ BootMessage (_("Set up standard connections"));
+ setup_bundles ();
+ }
+
+ catch (failed_constructor& err) {
+ return -1;
+ }
+
BootMessage (_("Setup signal flow and plugins"));
/* Reset all panners */
@@ -672,6 +732,8 @@ Session::when_engine_running ()
BootMessage (_("Connect to engine"));
_engine.set_session (this);
_engine.reset_timebase ();
+
+ return 0;
}
void
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index 2491712c49..b4364f4c13 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -125,10 +125,35 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
-/** @param snapshot_name Snapshot name, without the .ardour prefix */
void
-Session::first_stage_init (string fullpath, string /*snapshot_name*/)
+Session::pre_engine_init (string fullpath)
{
+ if (fullpath.empty()) {
+ destroy ();
+ throw failed_constructor();
+ }
+
+ /* discover canonical fullpath */
+
+ char buf[PATH_MAX+1];
+ if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
+ error << string_compose(_("Could not use path %1 (%2)"), buf, strerror(errno)) << endmsg;
+ destroy ();
+ throw failed_constructor();
+ }
+
+ _path = string(buf);
+
+ /* we require _path to end with a dir separator */
+
+ if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
+ _path += G_DIR_SEPARATOR;
+ }
+
+ /* is it new ? */
+
+ _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
+
/* finish initialization that can't be done in a normal C++ constructor
definition.
*/
@@ -168,32 +193,6 @@ Session::first_stage_init (string fullpath, string /*snapshot_name*/)
boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
add_controllable (_solo_cut_control);
- /* discover canonical fullpath */
-
- if (fullpath.length() == 0) {
- destroy ();
- throw failed_constructor();
- }
-
- char buf[PATH_MAX+1];
- if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
- error << string_compose(_("Could not use path %1 (%2)"), buf, strerror(errno)) << endmsg;
- destroy ();
- throw failed_constructor();
- }
-
- _path = string(buf);
-
- /* we require _path to end with a dir separator */
-
- if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
- _path += G_DIR_SEPARATOR;
- }
-
- /* is it new ? */
-
- _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
-
/* These are all static "per-class" signals */
SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
@@ -207,95 +206,90 @@ Session::first_stage_init (string fullpath, string /*snapshot_name*/)
Delivery::disable_panners ();
IO::disable_connecting ();
- /* ENGINE */
+ AudioFileSource::set_peak_dir (_session_dir->peak_path());
+}
+
+int
+Session::post_engine_init ()
+{
+ BootMessage (_("Set block size and sample rate"));
+
+ set_block_size (_engine.samples_per_cycle());
+ set_frame_rate (_engine.sample_rate());
n_physical_outputs = _engine.n_physical_outputs ();
n_physical_inputs = _engine.n_physical_inputs ();
- _current_frame_rate = _engine.sample_rate ();
- _nominal_frame_rate = _current_frame_rate;
- _base_frame_rate = _current_frame_rate;
+ BootMessage (_("Using configuration"));
_midi_ports = new MidiPortManager;
- _mmc = new MIDI::MachineControl;
-
- _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
+ setup_midi_machine_control ();
- _tempo_map = new TempoMap (_current_frame_rate);
- _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
-
- AudioDiskstream::allocate_working_buffers();
-
- SndFileSource::setup_standard_crossfades (*this, frame_rate());
- _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
-
- refresh_disk_space ();
- sync_time_vars ();
-}
-
-int
-Session::second_stage_init ()
-{
- AudioFileSource::set_peak_dir (_session_dir->peak_path());
-
if (_butler->start_thread()) {
return -1;
}
-
+
if (start_midi_thread ()) {
return -1;
}
+
+ setup_click_sounds (0);
+ setup_midi_control ();
- setup_midi_machine_control ();
-
- // set_state() will call setup_raid_path(), but if it's a new session we need
- // to call setup_raid_path() here.
-
- if (state_tree) {
- if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
- return -1;
- }
- } else {
- setup_raid_path(_path);
- }
+ _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
+ _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
- /* we can't save till after ::when_engine_running() is called,
- because otherwise we save state with no connections made.
- therefore, we reset _state_of_the_state because ::set_state()
- will have cleared it.
+ try {
+ /* tempo map requires sample rate knowledge */
- we also have to include Loading so that any events that get
- generated between here and the end of ::when_engine_running()
- will be processed directly rather than queued.
- */
+ _tempo_map = new TempoMap (_current_frame_rate);
+ _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
+
+ /* MidiClock requires a tempo map */
- _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
+ midi_clock = new MidiClockTicker ();
+ midi_clock->set_session (this);
- _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
- _locations->added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
- setup_click_sounds (0);
- setup_midi_control ();
+ /* crossfades require sample rate knowledge */
- /* Pay attention ... */
+ SndFileSource::setup_standard_crossfades (*this, frame_rate());
+ _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
+
+ AudioDiskstream::allocate_working_buffers();
+ refresh_disk_space ();
+
+ /* we're finally ready to call set_state() ... all objects have
+ * been created, the engine is running.
+ */
+
+ if (state_tree) {
+ if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
+ return -1;
+ }
+ } else {
+ // set_state() will call setup_raid_path(), but if it's a new session we need
+ // to call setup_raid_path() here.
+ setup_raid_path (_path);
+ }
- _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
- _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
+ /* ENGINE */
- midi_clock = new MidiClockTicker ();
- midi_clock->set_session (this);
+ boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
+ boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
+
+ Config->map_parameters (ff);
+ config.map_parameters (ft);
- try {
when_engine_running ();
- }
-
- /* handle this one in a different way than all others, so that its clear what happened */
- catch (AudioEngine::PortRegistrationFailure& err) {
+ _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
+ _locations->added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
+
+ } catch (AudioEngine::PortRegistrationFailure& err) {
+ /* handle this one in a different way than all others, so that its clear what happened */
error << err.what() << endmsg;
return -1;
- }
-
- catch (...) {
+ } catch (...) {
return -1;
}
@@ -3516,6 +3510,9 @@ Session::load_diskstreams_2X (XMLNode const & node, int)
void
Session::setup_midi_machine_control ()
{
+ _mmc = new MIDI::MachineControl;
+ _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
+
_mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
_mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
_mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));