diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2013-09-10 15:41:19 -0400 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2013-09-10 15:41:19 -0400 |
commit | 209e4bdcaed8e0f7d66fa5673f9049948e1f1d53 (patch) | |
tree | bdf1ffca2a5f1f20ac652e6803a77cfcf8278363 /libs/ardour | |
parent | a6815efb86e5091ce82f66ddfb60b2b2cffc587a (diff) |
many changes relating to session construction and audioengine interaction
every session member is now initialized using C++ constructor syntax
session construction reordered to clarify the split(s) between work
where the engine is not relevant and work where is it is. this
split is still not 100% obvious, but is enormously clearer than
previously.
if engine/backend are not running as session is created, and the SR
of the sample rate is known, attempt to force backend to that value.
Diffstat (limited to 'libs/ardour')
-rw-r--r-- | libs/ardour/ardour/session.h | 12 | ||||
-rw-r--r-- | libs/ardour/port.cc | 4 | ||||
-rw-r--r-- | libs/ardour/session.cc | 424 | ||||
-rw-r--r-- | libs/ardour/session_state.cc | 179 |
4 files changed, 343 insertions, 276 deletions
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)); |