X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fsession.cc;h=5b8d2f850677abea63df09685b996c7960d0e8f7;hb=803b502bf176c417a70498a98173fb09691a80b7;hp=0af1272c0acf60cd70b9a4a875cea064762ad47e;hpb=c0529df1a354d51911921b15acdb771707c44287;p=ardour.git diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 0af1272c0a..5b8d2f8506 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -27,12 +27,14 @@ #include #include #include +#include #include #include #include #include +#include #include #include @@ -44,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -94,19 +97,29 @@ const char* Session::dead_sound_dir_name = X_("dead_sounds"); const char* Session::interchange_dir_name = X_("interchange"); const char* Session::export_dir_name = X_("export"); +bool Session::_disable_all_loaded_plugins = false; + Session::compute_peak_t Session::compute_peak = 0; Session::find_peaks_t Session::find_peaks = 0; Session::apply_gain_to_buffer_t Session::apply_gain_to_buffer = 0; Session::mix_buffers_with_gain_t Session::mix_buffers_with_gain = 0; Session::mix_buffers_no_gain_t Session::mix_buffers_no_gain = 0; +sigc::signal Session::Dialog; sigc::signal Session::AskAboutPendingState; +sigc::signal Session::AskAboutSampleRateMismatch; sigc::signal Session::SendFeedback; sigc::signal Session::SMPTEOffsetChanged; sigc::signal Session::StartTimeChanged; sigc::signal Session::EndTimeChanged; +sigc::signal Session::AutoBindingOn; +sigc::signal Session::AutoBindingOff; + + +sigc::signal Session::Exported; + int Session::find_session (string str, string& path, string& snapshot, bool& isnew) { @@ -258,9 +271,9 @@ Session::find_session (string str, string& path, string& snapshot, bool& isnew) } Session::Session (AudioEngine &eng, - string fullpath, - string snapshot_name, - string* mix_template) + const string& fullpath, + const string& snapshot_name, + string mix_template) : _engine (eng), _mmc_port (default_mmc_port), @@ -282,15 +295,15 @@ Session::Session (AudioEngine &eng, cerr << "Loading session " << fullpath << " using snapshot " << snapshot_name << " (1)" << endl; - n_physical_outputs = _engine.n_physical_outputs(); - n_physical_inputs = _engine.n_physical_inputs(); + n_physical_audio_outputs = _engine.n_physical_audio_outputs(); + n_physical_audio_inputs = _engine.n_physical_audio_inputs(); first_stage_init (fullpath, snapshot_name); - new_session = !g_file_test (_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)); + new_session = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)); + if (new_session) { if (create (new_session, mix_template, compute_initial_length())) { - cerr << "create failed\n"; destroy (); throw failed_constructor (); } @@ -344,15 +357,15 @@ Session::Session (AudioEngine &eng, cerr << "Loading session " << fullpath << " using snapshot " << snapshot_name << " (2)" << endl; - n_physical_outputs = _engine.n_physical_outputs(); - n_physical_inputs = _engine.n_physical_inputs(); + n_physical_audio_outputs = _engine.n_physical_audio_outputs(); + n_physical_audio_inputs = _engine.n_physical_audio_inputs(); - if (n_physical_inputs) { - n_physical_inputs = max (requested_physical_in, n_physical_inputs); + if (n_physical_audio_inputs) { + n_physical_audio_inputs = max (requested_physical_in, n_physical_audio_inputs); } - if (n_physical_outputs) { - n_physical_outputs = max (requested_physical_out, n_physical_outputs); + if (n_physical_audio_outputs) { + n_physical_audio_outputs = max (requested_physical_out, n_physical_audio_outputs); } first_stage_init (fullpath, snapshot_name); @@ -360,7 +373,7 @@ Session::Session (AudioEngine &eng, new_session = !g_file_test (_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)); if (new_session) { - if (create (new_session, 0, initial_length)) { + if (create (new_session, string(), initial_length)) { destroy (); throw failed_constructor (); } @@ -390,7 +403,7 @@ Session::Session (AudioEngine &eng, } if (!rl.empty()) { - add_routes (rl); + add_routes (rl, false); } } @@ -403,17 +416,12 @@ Session::Session (AudioEngine &eng, throw failed_constructor (); } - store_recent_sessions(_name, _path); + store_recent_sessions (_name, _path); - bool was_dirty = dirty (); - _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty); - Config->ParameterChanged.connect (mem_fun (*this, &Session::config_changed)); - if (was_dirty) { - DirtyChanged (); /* EMIT SIGNAL */ - } + Config->ParameterChanged.connect (mem_fun (*this, &Session::config_changed)); } Session::~Session () @@ -431,6 +439,7 @@ Session::destroy () remove_pending_capture_state (); _state_of_the_state = StateOfTheState (CannotSave|Deletion); + _engine.remove_session (); GoingAway (); /* EMIT SIGNAL */ @@ -575,14 +584,13 @@ Session::destroy () tmp = i; ++tmp; - + i->second->drop_references (); - + i = tmp; } - audio_sources.clear (); - + #ifdef TRACK_DESTRUCTION cerr << "delete mix groups\n"; #endif /* TRACK_DESTRUCTION */ @@ -665,9 +673,13 @@ Session::when_engine_running () /* we don't want to run execute this again */ + BootMessage (_("Set block size and sample rate")); + set_block_size (_engine.frames_per_cycle()); set_frame_rate (_engine.frame_rate()); + BootMessage (_("Using configuration")); + Config->map_parameters (mem_fun (*this, &Session::config_changed)); /* every time we reconnect, recompute worst case output latencies */ @@ -707,7 +719,7 @@ Session::when_engine_running () /* default state for Click */ - first_physical_output = _engine.get_nth_physical_output (0); + first_physical_output = _engine.get_nth_physical_audio_output (0); if (first_physical_output.length()) { if (_click_io->add_output_port (first_physical_output, this)) { @@ -723,6 +735,8 @@ Session::when_engine_running () error << _("cannot setup Click I/O") << endmsg; } + BootMessage (_("Compute I/O Latencies")); + set_worst_io_latencies (); if (_clicking) { @@ -733,35 +747,37 @@ Session::when_engine_running () to the physical outputs currently available */ + BootMessage (_("Set up standard connections")); + /* ONE: MONO */ - for (uint32_t np = 0; np < n_physical_outputs; ++np) { + for (uint32_t np = 0; np < n_physical_audio_outputs; ++np) { char buf[32]; snprintf (buf, sizeof (buf), _("out %" PRIu32), np+1); Connection* c = new OutputConnection (buf, true); c->add_port (); - c->add_connection (0, _engine.get_nth_physical_output (np)); + c->add_connection (0, _engine.get_nth_physical_audio_output (np)); add_connection (c); } - for (uint32_t np = 0; np < n_physical_inputs; ++np) { + for (uint32_t np = 0; np < n_physical_audio_inputs; ++np) { char buf[32]; snprintf (buf, sizeof (buf), _("in %" PRIu32), np+1); Connection* c = new InputConnection (buf, true); c->add_port (); - c->add_connection (0, _engine.get_nth_physical_input (np)); + c->add_connection (0, _engine.get_nth_physical_audio_input (np)); add_connection (c); } /* TWO: STEREO */ - for (uint32_t np = 0; np < n_physical_outputs; np +=2) { + for (uint32_t np = 0; np < n_physical_audio_outputs; np +=2) { char buf[32]; snprintf (buf, sizeof (buf), _("out %" PRIu32 "+%" PRIu32), np+1, np+2); @@ -769,13 +785,13 @@ Session::when_engine_running () c->add_port (); c->add_port (); - c->add_connection (0, _engine.get_nth_physical_output (np)); - c->add_connection (1, _engine.get_nth_physical_output (np+1)); + c->add_connection (0, _engine.get_nth_physical_audio_output (np)); + c->add_connection (1, _engine.get_nth_physical_audio_output (np+1)); add_connection (c); } - for (uint32_t np = 0; np < n_physical_inputs; np +=2) { + for (uint32_t np = 0; np < n_physical_audio_inputs; np +=2) { char buf[32]; snprintf (buf, sizeof (buf), _("in %" PRIu32 "+%" PRIu32), np+1, np+2); @@ -783,8 +799,8 @@ Session::when_engine_running () c->add_port (); c->add_port (); - c->add_connection (0, _engine.get_nth_physical_input (np)); - c->add_connection (1, _engine.get_nth_physical_input (np+1)); + c->add_connection (0, _engine.get_nth_physical_audio_input (np)); + c->add_connection (1, _engine.get_nth_physical_audio_input (np+1)); add_connection (c); } @@ -817,7 +833,7 @@ Session::when_engine_running () } n = 0; while ((int) _master_out->n_outputs() < _master_out->output_maximum()) { - if (_master_out->add_output_port (_engine.get_nth_physical_output (n), this)) { + if (_master_out->add_output_port (_engine.get_nth_physical_audio_output (n), this)) { error << _("cannot setup master outputs") << endmsg; break; @@ -837,11 +853,15 @@ Session::when_engine_running () } add_connection (c); } + + BootMessage (_("Setup signal flow and plugins")); hookup_io (); /* catch up on send+insert cnts */ + BootMessage (_("Catch up with send/insert state")); + insert_cnt = 0; for (list::iterator i = _port_inserts.begin(); i != _port_inserts.end(); ++i) { @@ -871,17 +891,18 @@ Session::when_engine_running () /* hook us up to the engine */ + BootMessage (_("Connect to engine")); + _engine.set_session (this); #ifdef HAVE_LIBLO /* and to OSC */ + BootMessage (_("OSC startup")); + osc->set_session (*this); #endif - _state_of_the_state = Clean; - - DirtyChanged (); /* EMIT SIGNAL */ } void @@ -893,6 +914,7 @@ Session::hookup_io () _state_of_the_state = StateOfTheState (_state_of_the_state | InitialConnecting); + if (auditioner == 0) { /* we delay creating the auditioner till now because @@ -926,7 +948,7 @@ Session::hookup_io () } n = 0; while ((int) _control_out->n_outputs() < _control_out->output_maximum()) { - if (_control_out->add_output_port (_engine.get_nth_physical_output (n), this)) { + if (_control_out->add_output_port (_engine.get_nth_physical_audio_output (n), this)) { error << _("cannot set up master outputs") << endmsg; break; @@ -962,6 +984,7 @@ Session::hookup_io () _state_of_the_state = StateOfTheState (_state_of_the_state & ~InitialConnecting); + /* now handle the whole enchilada as if it was one graph reorder event. */ @@ -1105,7 +1128,6 @@ Session::auto_loop_changed (Location* location) } last_loopend = location->end(); - } void @@ -1143,6 +1165,10 @@ Session::set_auto_punch_location (Location* location) auto_punch_changed_connection = location->changed.connect (mem_fun (this, &Session::auto_punch_changed)); location->set_auto_punch (true, this); + + + auto_punch_changed (location); + auto_punch_location_changed (location); } @@ -1182,6 +1208,13 @@ Session::set_auto_loop_location (Location* location) auto_loop_changed_connection = location->changed.connect (mem_fun (this, &Session::auto_loop_changed)); location->set_auto_loop (true, this); + + /* take care of our stuff first */ + + auto_loop_changed (location); + + /* now tell everyone else */ + auto_loop_location_changed (location); } @@ -1294,11 +1327,11 @@ Session::step_back_from_record () if (g_atomic_int_get (&_record_status) == Recording) { g_atomic_int_set (&_record_status, Enabled); - if (Config->get_monitoring_model() == HardwareMonitoring) { + if (Config->get_monitoring_model() == HardwareMonitoring && Config->get_auto_input()) { boost::shared_ptr dsl = diskstreams.reader(); for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) { - if (Config->get_auto_input() && (*i)->record_enabled ()) { + if ((*i)->record_enabled ()) { //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl; (*i)->monitor_input (false); } @@ -1404,6 +1437,8 @@ Session::set_frame_rate (nframes_t frames_per_second) IO::set_automation_interval ((jack_nframes_t) ceil ((double) frames_per_second * (0.001 * Config->get_automation_interval()))); + clear_clicks (); + // XXX we need some equivalent to this, somehow // SndFileSource::setup_standard_crossfades (frames_per_second); @@ -1687,8 +1722,8 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod uint32_t nphysical_in; uint32_t nphysical_out; - _engine.get_physical_outputs (physoutputs); - _engine.get_physical_inputs (physinputs); + _engine.get_physical_audio_outputs (physoutputs); + _engine.get_physical_audio_inputs (physinputs); control_id = ntracks() + nbusses() + 1; while (how_many) { @@ -1712,13 +1747,13 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod } while (track_id < (UINT_MAX-1)); if (Config->get_input_auto_connect() & AutoConnectPhysical) { - nphysical_in = min (n_physical_inputs, (uint32_t) physinputs.size()); + nphysical_in = min (n_physical_audio_inputs, (uint32_t) physinputs.size()); } else { nphysical_in = 0; } if (Config->get_output_auto_connect() & AutoConnectPhysical) { - nphysical_out = min (n_physical_outputs, (uint32_t) physinputs.size()); + nphysical_out = min (n_physical_audio_outputs, (uint32_t) physinputs.size()); } else { nphysical_out = 0; } @@ -1734,7 +1769,7 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod << endmsg; goto failed; } - + if (nphysical_in) { for (uint32_t x = 0; x < track->n_inputs() && x < nphysical_in; ++x) { @@ -1777,6 +1812,7 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod new_routes.push_back (track); ret.push_back (track); + } catch (failed_constructor &err) { @@ -1819,8 +1855,7 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod failed: if (!new_routes.empty()) { - add_routes (new_routes, false); - save_state (_current_snapshot_name); + add_routes (new_routes, true); } return ret; @@ -1874,8 +1909,8 @@ Session::new_audio_route (int input_channels, int output_channels, uint32_t how_ vector physinputs; vector physoutputs; - _engine.get_physical_outputs (physoutputs); - _engine.get_physical_inputs (physinputs); + _engine.get_physical_audio_outputs (physoutputs); + _engine.get_physical_audio_inputs (physinputs); control_id = ntracks() + nbusses() + 1; while (how_many) { @@ -1901,12 +1936,12 @@ Session::new_audio_route (int input_channels, int output_channels, uint32_t how_ goto failure; } - for (uint32_t x = 0; n_physical_inputs && x < bus->n_inputs(); ++x) { + for (uint32_t x = 0; n_physical_audio_inputs && x < bus->n_inputs(); ++x) { port = ""; if (Config->get_input_auto_connect() & AutoConnectPhysical) { - port = physinputs[((n+x)%n_physical_inputs)]; + port = physinputs[((n+x)%n_physical_audio_inputs)]; } if (port.length() && bus->connect_input (bus->input (x), port, this)) { @@ -1914,12 +1949,12 @@ Session::new_audio_route (int input_channels, int output_channels, uint32_t how_ } } - for (uint32_t x = 0; n_physical_outputs && x < bus->n_outputs(); ++x) { + for (uint32_t x = 0; n_physical_audio_outputs && x < bus->n_outputs(); ++x) { port = ""; if (Config->get_output_auto_connect() & AutoConnectPhysical) { - port = physoutputs[((n+x)%n_physical_outputs)]; + port = physoutputs[((n+x)%n_physical_audio_outputs)]; } else if (Config->get_output_auto_connect() & AutoConnectMaster) { if (_master_out) { port = _master_out->input (x%_master_out->n_inputs())->name(); @@ -1954,8 +1989,7 @@ Session::new_audio_route (int input_channels, int output_channels, uint32_t how_ failure: if (!ret.empty()) { - add_routes (ret, false); - save_state (_current_snapshot_name); + add_routes (ret, true); } return ret; @@ -2093,14 +2127,14 @@ Session::remove_route (shared_ptr route) find_current_end (); - update_latency_compensation (false, false); - set_dirty(); - // We need to disconnect the routes inputs and outputs route->disconnect_inputs (0); route->disconnect_outputs (0); + update_latency_compensation (false, false); + set_dirty(); + /* get rid of it from the dead wood collection in the route list manager */ /* XXX i think this is unsafe as it currently stands, but i am not sure. (pd, october 2nd, 2006) */ @@ -2564,6 +2598,14 @@ Session::region_name (string& result, string base, bool newlevel) const void Session::add_region (boost::shared_ptr region) +{ + vector > v; + v.push_back (region); + add_regions (v); +} + +void +Session::add_regions (vector >& new_regions) { boost::shared_ptr ar; boost::shared_ptr oar; @@ -2572,43 +2614,52 @@ Session::add_region (boost::shared_ptr region) { Glib::Mutex::Lock lm (region_lock); - if ((ar = boost::dynamic_pointer_cast (region)) != 0) { - - AudioRegionList::iterator x; - - for (x = audio_regions.begin(); x != audio_regions.end(); ++x) { - - oar = boost::dynamic_pointer_cast (x->second); - - if (ar->region_list_equivalent (oar)) { - break; - } - } - - if (x == audio_regions.end()) { - - pair entry; - - entry.first = region->id(); - entry.second = ar; + for (vector >::iterator ii = new_regions.begin(); ii != new_regions.end(); ++ii) { + + boost::shared_ptr region = *ii; + + if (region == 0) { - pair x = audio_regions.insert (entry); + error << _("Session::add_region() ignored a null region. Warning: you might have lost a region.") << endmsg; + } else if ((ar = boost::dynamic_pointer_cast (region)) != 0) { - if (!x.second) { - return; + AudioRegionList::iterator x; + + for (x = audio_regions.begin(); x != audio_regions.end(); ++x) { + + oar = boost::dynamic_pointer_cast (x->second); + + if (ar->region_list_equivalent (oar)) { + break; + } } + + if (x == audio_regions.end()) { + + pair entry; + + entry.first = region->id(); + entry.second = ar; + + pair x = audio_regions.insert (entry); + + + if (!x.second) { + return; + } + + added = true; + } - added = true; - } - - } else { - - fatal << _("programming error: ") - << X_("unknown region type passed to Session::add_region()") - << endmsg; - /*NOTREACHED*/ - + } else { + + fatal << _("programming error: ") + << X_("unknown region type passed to Session::add_region()") + << endmsg; + /*NOTREACHED*/ + + } } } @@ -2619,9 +2670,34 @@ Session::add_region (boost::shared_ptr region) set_dirty(); if (added) { - region->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_region), boost::weak_ptr(region))); - region->StateChanged.connect (sigc::bind (mem_fun (*this, &Session::region_changed), boost::weak_ptr(region))); - AudioRegionAdded (ar); /* EMIT SIGNAL */ + + vector > v; + boost::shared_ptr first_ar; + + for (vector >::iterator ii = new_regions.begin(); ii != new_regions.end(); ++ii) { + + boost::shared_ptr region = *ii; + boost::shared_ptr ar; + + if (region == 0) { + + error << _("Session::add_region() ignored a null region. Warning: you might have lost a region.") << endmsg; + + } else if ((ar = boost::dynamic_pointer_cast (region)) != 0) { + v.push_back (ar); + + if (!first_ar) { + first_ar = ar; + } + } + + region->StateChanged.connect (sigc::bind (mem_fun (*this, &Session::region_changed), boost::weak_ptr(region))); + region->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_region), boost::weak_ptr(region))); + } + + if (!v.empty()) { + AudioRegionsAdded (v); /* EMIT SIGNAL */ + } } } @@ -2816,6 +2892,9 @@ Session::add_source (boost::shared_ptr source) set_dirty(); } + if (Config->get_auto_analyse_audio()) { + Analyser::queue_source_for_analysis (source, false); + } } } @@ -2880,13 +2959,13 @@ Session::source_by_path_and_channel (const Glib::ustring& path, uint16_t chn) return boost::shared_ptr(); } -string -Session::peak_path_from_audio_path (string audio_path) const +Glib::ustring +Session::peak_path (Glib::ustring base) const { - string res; - + Glib::ustring res; + res = peak_dir (); - res += PBD::basename_nosuffix (audio_path); + res += base; res += ".peak"; return res; @@ -3323,12 +3402,12 @@ Session::remove_empty_sounds () continue; } - if (AudioFileSource::is_empty (*this, *(*i))) { + if (AudioFileSource::is_empty (*this, **i)) { unlink ((*i)->c_str()); - string peak_path = peak_path_from_audio_path (**i); - unlink (peak_path.c_str()); + Glib::ustring peakpath = peak_path (PBD::basename_nosuffix (**i)); + unlink (peakpath.c_str()); } delete* i; @@ -3603,18 +3682,36 @@ void Session::tempo_map_changed (Change ignored) { clear_clicks (); + + for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) { + (*i)->update_after_tempo_map_change (); + } + + for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) { + (*i)->update_after_tempo_map_change (); + } + set_dirty (); } void Session::ensure_passthru_buffers (uint32_t howmany) { + if (current_block_size == 0) { + return; + } + while (howmany > _passthru_buffers.size()) { Sample *p; #ifdef NO_POSIX_MEMALIGN p = (Sample *) malloc(current_block_size * sizeof(Sample)); #else - posix_memalign((void **)&p,CPU_CACHE_ALIGN,current_block_size * sizeof(Sample)); + if (posix_memalign((void **)&p,CPU_CACHE_ALIGN,current_block_size * sizeof(Sample)) != 0) { + fatal << string_compose (_("Memory allocation error: posix_memalign (%1 * %2) failed (%3)"), + current_block_size, sizeof (Sample), strerror (errno)) + << endmsg; + /*NOTREACHED*/ + } #endif _passthru_buffers.push_back (p); @@ -3623,7 +3720,12 @@ Session::ensure_passthru_buffers (uint32_t howmany) #ifdef NO_POSIX_MEMALIGN p = (Sample *) malloc(current_block_size * sizeof(Sample)); #else - posix_memalign((void **)&p,CPU_CACHE_ALIGN,current_block_size * 4); + if (posix_memalign((void **)&p,CPU_CACHE_ALIGN,current_block_size * 4) != 0) { + fatal << string_compose (_("Memory allocation error: posix_memalign (%1 * %2) failed (%3)"), + current_block_size, sizeof (Sample), strerror (errno)) + << endmsg; + /*NOTREACHED*/ + } #endif memset (p, 0, sizeof (Sample) * current_block_size); _silent_buffers.push_back (p); @@ -4002,9 +4104,37 @@ Session::write_one_audio_track (AudioTrack& track, nframes_t start, nframes_t le vector& Session::get_silent_buffers (uint32_t howmany) { + if (howmany > _silent_buffers.size()) { + + error << string_compose (_("Programming error: get_silent_buffers() called for %1 buffers but only %2 exist"), + howmany, _silent_buffers.size()) << endmsg; + + if (howmany > 1000) { + cerr << "ABSURD: more than 1000 silent buffers requested!\n"; + abort (); + } + + while (howmany > _silent_buffers.size()) { + Sample *p = 0; + +#ifdef NO_POSIX_MEMALIGN + p = (Sample *) malloc(current_block_size * sizeof(Sample)); +#else + if (posix_memalign((void **)&p,CPU_CACHE_ALIGN,current_block_size * 4) != 0) { + fatal << string_compose (_("Memory allocation error: posix_memalign (%1 * %2) failed (%3)"), + current_block_size, sizeof (Sample), strerror (errno)) + << endmsg; + /*NOTREACHED*/ + } +#endif + _silent_buffers.push_back (p); + } + } + for (uint32_t i = 0; i < howmany; ++i) { memset (_silent_buffers[i], 0, sizeof (Sample) * current_block_size); } + return _silent_buffers; } @@ -4050,3 +4180,19 @@ Session::compute_initial_length () return _engine.frame_rate() * 60 * 5; } +void +Session::sync_order_keys () +{ + if (!Config->get_sync_all_route_ordering()) { + /* leave order keys as they are */ + return; + } + + boost::shared_ptr r = routes.reader (); + + for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { + (*i)->sync_order_keys (); + } + + Route::SyncOrderKeys (); // EMIT SIGNAL +}