2 Copyright (C) 1999-2004 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include <cstdio> /* sprintf(3) ... grrr */
32 #include <sigc++/bind.h>
33 #include <sigc++/retype.h>
35 #include <glibmm/thread.h>
36 #include <glibmm/miscutils.h>
37 #include <glibmm/fileutils.h>
39 #include <pbd/error.h>
40 #include <glibmm/thread.h>
41 #include <pbd/pathscanner.h>
42 #include <pbd/stl_delete.h>
43 #include <pbd/basename.h>
44 #include <pbd/stacktrace.h>
46 #include <ardour/audioengine.h>
47 #include <ardour/configuration.h>
48 #include <ardour/session.h>
49 #include <ardour/analyser.h>
50 #include <ardour/audio_diskstream.h>
51 #include <ardour/utils.h>
52 #include <ardour/audioplaylist.h>
53 #include <ardour/audioregion.h>
54 #include <ardour/audiofilesource.h>
55 #include <ardour/auditioner.h>
56 #include <ardour/recent_sessions.h>
57 #include <ardour/redirect.h>
58 #include <ardour/send.h>
59 #include <ardour/insert.h>
60 #include <ardour/connection.h>
61 #include <ardour/slave.h>
62 #include <ardour/tempo.h>
63 #include <ardour/audio_track.h>
64 #include <ardour/cycle_timer.h>
65 #include <ardour/named_selection.h>
66 #include <ardour/crossfade.h>
67 #include <ardour/playlist.h>
68 #include <ardour/click.h>
69 #include <ardour/data_type.h>
70 #include <ardour/source_factory.h>
71 #include <ardour/region_factory.h>
74 #include <ardour/osc.h>
80 using namespace ARDOUR;
82 using boost::shared_ptr;
85 static const int CPU_CACHE_ALIGN = 64;
87 static const int CPU_CACHE_ALIGN = 16; /* arguably 32 on most arches, but it matters less */
90 const char* Session::_template_suffix = X_(".template");
91 const char* Session::_statefile_suffix = X_(".ardour");
92 const char* Session::_pending_suffix = X_(".pending");
93 const char* Session::old_sound_dir_name = X_("sounds");
94 const char* Session::sound_dir_name = X_("audiofiles");
95 const char* Session::peak_dir_name = X_("peaks");
96 const char* Session::dead_sound_dir_name = X_("dead_sounds");
97 const char* Session::interchange_dir_name = X_("interchange");
98 const char* Session::export_dir_name = X_("export");
100 bool Session::_disable_all_loaded_plugins = false;
102 Session::compute_peak_t Session::compute_peak = 0;
103 Session::find_peaks_t Session::find_peaks = 0;
104 Session::apply_gain_to_buffer_t Session::apply_gain_to_buffer = 0;
105 Session::mix_buffers_with_gain_t Session::mix_buffers_with_gain = 0;
106 Session::mix_buffers_no_gain_t Session::mix_buffers_no_gain = 0;
108 sigc::signal<void,std::string> Session::Dialog;
109 sigc::signal<int> Session::AskAboutPendingState;
110 sigc::signal<int,nframes_t,nframes_t> Session::AskAboutSampleRateMismatch;
111 sigc::signal<void> Session::SendFeedback;
113 sigc::signal<void> Session::SMPTEOffsetChanged;
114 sigc::signal<void> Session::StartTimeChanged;
115 sigc::signal<void> Session::EndTimeChanged;
117 sigc::signal<void> Session::AutoBindingOn;
118 sigc::signal<void> Session::AutoBindingOff;
121 sigc::signal<void, std::string, std::string> Session::Exported;
124 Session::find_session (string str, string& path, string& snapshot, bool& isnew)
127 char buf[PATH_MAX+1];
131 if (!realpath (str.c_str(), buf) && (errno != ENOENT && errno != ENOTDIR)) {
132 error << string_compose (_("Could not resolve path: %1 (%2)"), buf, strerror(errno)) << endmsg;
138 /* check to see if it exists, and what it is */
140 if (stat (str.c_str(), &statbuf)) {
141 if (errno == ENOENT) {
144 error << string_compose (_("cannot check session path %1 (%2)"), str, strerror (errno))
152 /* it exists, so it must either be the name
153 of the directory, or the name of the statefile
157 if (S_ISDIR (statbuf.st_mode)) {
159 string::size_type slash = str.find_last_of ('/');
161 if (slash == string::npos) {
163 /* a subdirectory of cwd, so statefile should be ... */
169 tmp += _statefile_suffix;
173 if (stat (tmp.c_str(), &statbuf)) {
174 error << string_compose (_("cannot check statefile %1 (%2)"), tmp, strerror (errno))
184 /* some directory someplace in the filesystem.
185 the snapshot name is the directory name
190 snapshot = str.substr (slash+1);
194 } else if (S_ISREG (statbuf.st_mode)) {
196 string::size_type slash = str.find_last_of ('/');
197 string::size_type suffix;
199 /* remove the suffix */
201 if (slash != string::npos) {
202 snapshot = str.substr (slash+1);
207 suffix = snapshot.find (_statefile_suffix);
209 if (suffix == string::npos) {
210 error << string_compose (_("%1 is not an Ardour snapshot file"), str) << endmsg;
216 snapshot = snapshot.substr (0, suffix);
218 if (slash == string::npos) {
220 /* we must be in the directory where the
221 statefile lives. get it using cwd().
224 char cwd[PATH_MAX+1];
226 if (getcwd (cwd, sizeof (cwd)) == 0) {
227 error << string_compose (_("cannot determine current working directory (%1)"), strerror (errno))
236 /* full path to the statefile */
238 path = str.substr (0, slash);
243 /* what type of file is it? */
244 error << string_compose (_("unknown file type for session %1"), str) << endmsg;
250 /* its the name of a new directory. get the name
254 string::size_type slash = str.find_last_of ('/');
256 if (slash == string::npos) {
258 /* no slash, just use the name, but clean it up */
260 path = legalize_for_path (str);
266 snapshot = str.substr (slash+1);
273 Session::Session (AudioEngine &eng,
274 const string& fullpath,
275 const string& snapshot_name,
280 _mmc_port (default_mmc_port),
281 _mtc_port (default_mtc_port),
282 _midi_port (default_midi_port),
283 pending_events (2048),
285 butler_mixdown_buffer (0),
286 butler_gain_buffer (0),
287 midi_thread (pthread_t (0)),
288 midi_requests (128), // the size of this should match the midi request pool size
289 diskstreams (new DiskstreamList),
290 routes (new RouteList),
291 auditioner ((Auditioner*) 0),
292 _total_free_4k_blocks (0),
295 click_emphasis_data (0),
300 if (!eng.connected()) {
301 throw failed_constructor();
304 cerr << "Loading session " << fullpath << " using snapshot " << snapshot_name << " (1)" << endl;
306 n_physical_audio_outputs = _engine.n_physical_audio_outputs();
307 n_physical_audio_inputs = _engine.n_physical_audio_inputs();
309 first_stage_init (fullpath, snapshot_name);
311 new_session = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
314 if (create (new_session, mix_template, compute_initial_length())) {
316 throw failed_constructor ();
320 if (second_stage_init (new_session)) {
322 throw failed_constructor ();
325 store_recent_sessions(_name, _path);
327 bool was_dirty = dirty();
329 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
331 Config->ParameterChanged.connect (mem_fun (*this, &Session::config_changed));
334 DirtyChanged (); /* EMIT SIGNAL */
338 Session::Session (AudioEngine &eng,
340 string snapshot_name,
341 AutoConnectOption input_ac,
342 AutoConnectOption output_ac,
343 uint32_t control_out_channels,
344 uint32_t master_out_channels,
345 uint32_t requested_physical_in,
346 uint32_t requested_physical_out,
347 nframes_t initial_length)
351 _mmc_port (default_mmc_port),
352 _mtc_port (default_mtc_port),
353 _midi_port (default_midi_port),
354 pending_events (2048),
356 butler_mixdown_buffer (0),
357 butler_gain_buffer (0),
358 midi_thread (pthread_t (0)),
360 diskstreams (new DiskstreamList),
361 routes (new RouteList),
362 auditioner ((Auditioner *) 0),
363 _total_free_4k_blocks (0),
364 _click_io ((IO *) 0),
366 click_emphasis_data (0),
372 if (!eng.connected()) {
373 throw failed_constructor();
376 cerr << "Loading session " << fullpath << " using snapshot " << snapshot_name << " (2)" << endl;
378 n_physical_audio_outputs = _engine.n_physical_audio_outputs();
379 n_physical_audio_inputs = _engine.n_physical_audio_inputs();
381 if (n_physical_audio_inputs) {
382 n_physical_audio_inputs = max (requested_physical_in, n_physical_audio_inputs);
385 if (n_physical_audio_outputs) {
386 n_physical_audio_outputs = max (requested_physical_out, n_physical_audio_outputs);
389 first_stage_init (fullpath, snapshot_name);
391 new_session = !g_file_test (_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
394 if (create (new_session, string(), initial_length)) {
396 throw failed_constructor ();
401 /* set up Master Out and Control Out if necessary */
406 if (control_out_channels) {
407 shared_ptr<Route> r (new Route (*this, _("monitor"), -1, control_out_channels, -1, control_out_channels, Route::ControlOut));
408 r->set_remote_control_id (control_id++);
413 if (master_out_channels) {
414 shared_ptr<Route> r (new Route (*this, _("master"), -1, master_out_channels, -1, master_out_channels, Route::MasterOut));
415 r->set_remote_control_id (control_id);
419 /* prohibit auto-connect to master, because there isn't one */
420 output_ac = AutoConnectOption (output_ac & ~AutoConnectMaster);
424 add_routes (rl, false);
429 Config->set_input_auto_connect (input_ac);
430 Config->set_output_auto_connect (output_ac);
432 if (second_stage_init (new_session)) {
434 throw failed_constructor ();
437 store_recent_sessions (_name, _path);
439 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
442 Config->ParameterChanged.connect (mem_fun (*this, &Session::config_changed));
453 /* if we got to here, leaving pending capture state around
457 remove_pending_capture_state ();
459 _state_of_the_state = StateOfTheState (CannotSave|Deletion);
461 _engine.remove_session ();
463 GoingAway (); /* EMIT SIGNAL */
469 /* clear history so that no references to objects are held any more */
473 /* clear state tree so that no references to objects are held any more */
476 terminate_butler_thread ();
477 terminate_midi_thread ();
479 if (click_data != default_click) {
480 delete [] click_data;
483 if (click_emphasis_data != default_click_emphasis) {
484 delete [] click_emphasis_data;
489 for (vector<Sample*>::iterator i = _passthru_buffers.begin(); i != _passthru_buffers.end(); ++i) {
493 for (vector<Sample*>::iterator i = _silent_buffers.begin(); i != _silent_buffers.end(); ++i) {
497 for (vector<Sample*>::iterator i = _send_buffers.begin(); i != _send_buffers.end(); ++i) {
501 AudioDiskstream::free_working_buffers();
503 /* this should cause deletion of the auditioner */
505 // auditioner.reset ();
507 #undef TRACK_DESTRUCTION
508 #ifdef TRACK_DESTRUCTION
509 cerr << "delete named selections\n";
510 #endif /* TRACK_DESTRUCTION */
511 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ) {
512 NamedSelectionList::iterator tmp;
521 #ifdef TRACK_DESTRUCTION
522 cerr << "delete playlists\n";
523 #endif /* TRACK_DESTRUCTION */
524 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ) {
525 PlaylistList::iterator tmp;
530 (*i)->drop_references ();
535 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ) {
536 PlaylistList::iterator tmp;
541 (*i)->drop_references ();
547 unused_playlists.clear ();
549 #ifdef TRACK_DESTRUCTION
550 cerr << "delete audio regions\n";
551 #endif /* TRACK_DESTRUCTION */
553 for (AudioRegionList::iterator i = audio_regions.begin(); i != audio_regions.end(); ) {
554 AudioRegionList::iterator tmp;
559 i->second->drop_references ();
564 audio_regions.clear ();
566 #ifdef TRACK_DESTRUCTION
567 cerr << "delete routes\n";
568 #endif /* TRACK_DESTRUCTION */
570 RCUWriter<RouteList> writer (routes);
571 boost::shared_ptr<RouteList> r = writer.get_copy ();
572 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
573 (*i)->drop_references ();
576 /* writer goes out of scope and updates master */
581 #ifdef TRACK_DESTRUCTION
582 cerr << "delete diskstreams\n";
583 #endif /* TRACK_DESTRUCTION */
585 RCUWriter<DiskstreamList> dwriter (diskstreams);
586 boost::shared_ptr<DiskstreamList> dsl = dwriter.get_copy();
587 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
588 (*i)->drop_references ();
592 diskstreams.flush ();
594 #ifdef TRACK_DESTRUCTION
595 cerr << "delete audio sources\n";
596 #endif /* TRACK_DESTRUCTION */
597 for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ) {
598 AudioSourceList::iterator tmp;
603 i->second->drop_references ();
607 audio_sources.clear ();
609 #ifdef TRACK_DESTRUCTION
610 cerr << "delete mix groups\n";
611 #endif /* TRACK_DESTRUCTION */
612 for (list<RouteGroup *>::iterator i = mix_groups.begin(); i != mix_groups.end(); ) {
613 list<RouteGroup*>::iterator tmp;
623 #ifdef TRACK_DESTRUCTION
624 cerr << "delete edit groups\n";
625 #endif /* TRACK_DESTRUCTION */
626 for (list<RouteGroup *>::iterator i = edit_groups.begin(); i != edit_groups.end(); ) {
627 list<RouteGroup*>::iterator tmp;
637 #ifdef TRACK_DESTRUCTION
638 cerr << "delete connections\n";
639 #endif /* TRACK_DESTRUCTION */
640 for (ConnectionList::iterator i = _connections.begin(); i != _connections.end(); ) {
641 ConnectionList::iterator tmp;
651 delete [] butler_mixdown_buffer;
652 delete [] butler_gain_buffer;
654 Crossfade::set_buffer_size (0);
660 Session::set_worst_io_latencies ()
662 _worst_output_latency = 0;
663 _worst_input_latency = 0;
665 if (!_engine.connected()) {
669 boost::shared_ptr<RouteList> r = routes.reader ();
671 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
672 _worst_output_latency = max (_worst_output_latency, (*i)->output_latency());
673 _worst_input_latency = max (_worst_input_latency, (*i)->input_latency());
678 Session::when_engine_running ()
680 string first_physical_output;
682 /* we don't want to run execute this again */
684 BootMessage (_("Set block size and sample rate"));
686 set_block_size (_engine.frames_per_cycle());
687 set_frame_rate (_engine.frame_rate());
689 BootMessage (_("Using configuration"));
691 Config->map_parameters (mem_fun (*this, &Session::config_changed));
693 /* every time we reconnect, recompute worst case output latencies */
695 _engine.Running.connect (mem_fun (*this, &Session::set_worst_io_latencies));
697 if (synced_to_jack()) {
698 _engine.transport_stop ();
701 if (Config->get_jack_time_master()) {
702 _engine.transport_locate (_transport_frame);
710 _click_io.reset (new ClickIO (*this, "click", 0, 0, -1, -1));
712 if (state_tree && (child = find_named_node (*state_tree->root(), "Click")) != 0) {
714 /* existing state for Click */
716 if (_click_io->set_state (*child->children().front()) == 0) {
718 _clicking = Config->get_clicking ();
722 error << _("could not setup Click I/O") << endmsg;
728 /* default state for Click */
730 first_physical_output = _engine.get_nth_physical_audio_output (0);
732 if (first_physical_output.length()) {
733 if (_click_io->add_output_port (first_physical_output, this)) {
734 // relax, even though its an error
736 _clicking = Config->get_clicking ();
742 catch (failed_constructor& err) {
743 error << _("cannot setup Click I/O") << endmsg;
746 BootMessage (_("Compute I/O Latencies"));
748 set_worst_io_latencies ();
751 // XXX HOW TO ALERT UI TO THIS ? DO WE NEED TO?
754 /* Create a set of Connection objects that map
755 to the physical outputs currently available
758 BootMessage (_("Set up standard connections"));
762 for (uint32_t np = 0; np < n_physical_audio_outputs; ++np) {
764 snprintf (buf, sizeof (buf), _("out %" PRIu32), np+1);
766 Connection* c = new OutputConnection (buf, true);
769 c->add_connection (0, _engine.get_nth_physical_audio_output (np));
774 for (uint32_t np = 0; np < n_physical_audio_inputs; ++np) {
776 snprintf (buf, sizeof (buf), _("in %" PRIu32), np+1);
778 Connection* c = new InputConnection (buf, true);
781 c->add_connection (0, _engine.get_nth_physical_audio_input (np));
788 for (uint32_t np = 0; np < n_physical_audio_outputs; np +=2) {
790 snprintf (buf, sizeof (buf), _("out %" PRIu32 "+%" PRIu32), np+1, np+2);
792 Connection* c = new OutputConnection (buf, true);
796 c->add_connection (0, _engine.get_nth_physical_audio_output (np));
797 c->add_connection (1, _engine.get_nth_physical_audio_output (np+1));
802 for (uint32_t np = 0; np < n_physical_audio_inputs; np +=2) {
804 snprintf (buf, sizeof (buf), _("in %" PRIu32 "+%" PRIu32), np+1, np+2);
806 Connection* c = new InputConnection (buf, true);
810 c->add_connection (0, _engine.get_nth_physical_audio_input (np));
811 c->add_connection (1, _engine.get_nth_physical_audio_input (np+1));
820 /* create master/control ports */
825 /* force the master to ignore any later call to this */
827 if (_master_out->pending_state_node) {
828 _master_out->ports_became_legal();
831 /* no panner resets till we are through */
833 _master_out->defer_pan_reset ();
835 while ((int) _master_out->n_inputs() < _master_out->input_maximum()) {
836 if (_master_out->add_input_port ("", this)) {
837 error << _("cannot setup master inputs")
843 while ((int) _master_out->n_outputs() < _master_out->output_maximum()) {
844 if (_master_out->add_output_port (_engine.get_nth_physical_audio_output (n), this)) {
845 error << _("cannot setup master outputs")
852 _master_out->allow_pan_reset ();
856 Connection* c = new OutputConnection (_("Master Out"), true);
858 for (uint32_t n = 0; n < _master_out->n_inputs (); ++n) {
860 c->add_connection ((int) n, _master_out->input(n)->name());
865 BootMessage (_("Setup signal flow and plugins"));
869 /* catch up on send+insert cnts */
871 BootMessage (_("Catch up with send/insert state"));
875 for (list<PortInsert*>::iterator i = _port_inserts.begin(); i != _port_inserts.end(); ++i) {
878 if (sscanf ((*i)->name().c_str(), "%*s %u", &id) == 1) {
879 if (id > insert_cnt) {
887 for (list<Send*>::iterator i = _sends.begin(); i != _sends.end(); ++i) {
890 if (sscanf ((*i)->name().c_str(), "%*s %u", &id) == 1) {
898 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
900 /* hook us up to the engine */
902 BootMessage (_("Connect to engine"));
904 _engine.set_session (this);
909 BootMessage (_("OSC startup"));
911 osc->set_session (*this);
917 Session::hookup_io ()
919 /* stop graph reordering notifications from
920 causing resorts, etc.
923 _state_of_the_state = StateOfTheState (_state_of_the_state | InitialConnecting);
926 if (auditioner == 0) {
928 /* we delay creating the auditioner till now because
929 it makes its own connections to ports.
930 the engine has to be running for this to work.
934 auditioner.reset (new Auditioner (*this));
937 catch (failed_constructor& err) {
938 warning << _("cannot create Auditioner: no auditioning of regions possible") << endmsg;
942 /* Tell all IO objects to create their ports */
948 vector<string> cports;
950 while ((int) _control_out->n_inputs() < _control_out->input_maximum()) {
951 if (_control_out->add_input_port ("", this)) {
952 error << _("cannot setup control inputs")
958 while ((int) _control_out->n_outputs() < _control_out->output_maximum()) {
959 if (_control_out->add_output_port (_engine.get_nth_physical_audio_output (n), this)) {
960 error << _("cannot set up master outputs")
968 uint32_t ni = _control_out->n_inputs();
970 for (n = 0; n < ni; ++n) {
971 cports.push_back (_control_out->input(n)->name());
974 boost::shared_ptr<RouteList> r = routes.reader ();
976 for (RouteList::iterator x = r->begin(); x != r->end(); ++x) {
977 (*x)->set_control_outs (cports);
981 /* Tell all IO objects to connect themselves together */
983 IO::enable_connecting ();
985 /* Now reset all panners */
987 IO::reset_panners ();
989 /* Anyone who cares about input state, wake up and do something */
991 IOConnectionsComplete (); /* EMIT SIGNAL */
993 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InitialConnecting);
996 /* now handle the whole enchilada as if it was one
1002 /* update mixer solo state */
1008 Session::playlist_length_changed ()
1010 /* we can't just increase end_location->end() if pl->get_maximum_extent()
1011 if larger. if the playlist used to be the longest playlist,
1012 and its now shorter, we have to decrease end_location->end(). hence,
1013 we have to iterate over all diskstreams and check the
1014 playlists currently in use.
1016 find_current_end ();
1020 Session::diskstream_playlist_changed (boost::weak_ptr<Diskstream> wptr)
1022 boost::shared_ptr<Diskstream> dstream = wptr.lock();
1029 boost::shared_ptr<Playlist> playlist;
1031 if ((playlist = dstream->playlist()) != 0) {
1032 playlist->LengthChanged.connect (mem_fun (this, &Session::playlist_length_changed));
1035 /* see comment in playlist_length_changed () */
1036 find_current_end ();
1040 Session::record_enabling_legal () const
1042 /* this used to be in here, but survey says.... we don't need to restrict it */
1043 // if (record_status() == Recording) {
1047 if (Config->get_all_safe()) {
1054 Session::reset_input_monitor_state ()
1056 if (transport_rolling()) {
1058 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1060 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1061 if ((*i)->record_enabled ()) {
1062 //cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
1063 (*i)->monitor_input (Config->get_monitoring_model() == HardwareMonitoring && !Config->get_auto_input());
1067 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1069 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1070 if ((*i)->record_enabled ()) {
1071 //cerr << "switching to input = " << !Config->get_auto_input() << __FILE__ << __LINE__ << endl << endl;
1072 (*i)->monitor_input (Config->get_monitoring_model() == HardwareMonitoring);
1079 Session::auto_punch_start_changed (Location* location)
1081 replace_event (Event::PunchIn, location->start());
1083 if (get_record_enabled() && Config->get_punch_in()) {
1084 /* capture start has been changed, so save new pending state */
1085 save_state ("", true);
1090 Session::auto_punch_end_changed (Location* location)
1092 nframes_t when_to_stop = location->end();
1093 // when_to_stop += _worst_output_latency + _worst_input_latency;
1094 replace_event (Event::PunchOut, when_to_stop);
1098 Session::auto_punch_changed (Location* location)
1100 nframes_t when_to_stop = location->end();
1102 replace_event (Event::PunchIn, location->start());
1103 //when_to_stop += _worst_output_latency + _worst_input_latency;
1104 replace_event (Event::PunchOut, when_to_stop);
1108 Session::auto_loop_changed (Location* location)
1110 replace_event (Event::AutoLoop, location->end(), location->start());
1112 if (transport_rolling() && play_loop) {
1114 //if (_transport_frame < location->start() || _transport_frame > location->end()) {
1116 if (_transport_frame > location->end()) {
1117 // relocate to beginning of loop
1118 clear_events (Event::LocateRoll);
1120 request_locate (location->start(), true);
1123 else if (Config->get_seamless_loop() && !loop_changing) {
1125 // schedule a locate-roll to refill the diskstreams at the
1126 // previous loop end
1127 loop_changing = true;
1129 if (location->end() > last_loopend) {
1130 clear_events (Event::LocateRoll);
1131 Event *ev = new Event (Event::LocateRoll, Event::Add, last_loopend, last_loopend, 0, true);
1138 last_loopend = location->end();
1142 Session::set_auto_punch_location (Location* location)
1146 if ((existing = _locations.auto_punch_location()) != 0 && existing != location) {
1147 auto_punch_start_changed_connection.disconnect();
1148 auto_punch_end_changed_connection.disconnect();
1149 auto_punch_changed_connection.disconnect();
1150 existing->set_auto_punch (false, this);
1151 remove_event (existing->start(), Event::PunchIn);
1152 clear_events (Event::PunchOut);
1153 auto_punch_location_changed (0);
1158 if (location == 0) {
1162 if (location->end() <= location->start()) {
1163 error << _("Session: you can't use that location for auto punch (start <= end)") << endmsg;
1167 auto_punch_start_changed_connection.disconnect();
1168 auto_punch_end_changed_connection.disconnect();
1169 auto_punch_changed_connection.disconnect();
1171 auto_punch_start_changed_connection = location->start_changed.connect (mem_fun (this, &Session::auto_punch_start_changed));
1172 auto_punch_end_changed_connection = location->end_changed.connect (mem_fun (this, &Session::auto_punch_end_changed));
1173 auto_punch_changed_connection = location->changed.connect (mem_fun (this, &Session::auto_punch_changed));
1175 location->set_auto_punch (true, this);
1178 auto_punch_changed (location);
1180 auto_punch_location_changed (location);
1184 Session::set_auto_loop_location (Location* location)
1188 if ((existing = _locations.auto_loop_location()) != 0 && existing != location) {
1189 auto_loop_start_changed_connection.disconnect();
1190 auto_loop_end_changed_connection.disconnect();
1191 auto_loop_changed_connection.disconnect();
1192 existing->set_auto_loop (false, this);
1193 remove_event (existing->end(), Event::AutoLoop);
1194 auto_loop_location_changed (0);
1199 if (location == 0) {
1203 if (location->end() <= location->start()) {
1204 error << _("Session: you can't use a mark for auto loop") << endmsg;
1208 last_loopend = location->end();
1210 auto_loop_start_changed_connection.disconnect();
1211 auto_loop_end_changed_connection.disconnect();
1212 auto_loop_changed_connection.disconnect();
1214 auto_loop_start_changed_connection = location->start_changed.connect (mem_fun (this, &Session::auto_loop_changed));
1215 auto_loop_end_changed_connection = location->end_changed.connect (mem_fun (this, &Session::auto_loop_changed));
1216 auto_loop_changed_connection = location->changed.connect (mem_fun (this, &Session::auto_loop_changed));
1218 location->set_auto_loop (true, this);
1220 /* take care of our stuff first */
1222 auto_loop_changed (location);
1224 /* now tell everyone else */
1226 auto_loop_location_changed (location);
1230 Session::locations_added (Location* ignored)
1236 Session::locations_changed ()
1238 _locations.apply (*this, &Session::handle_locations_changed);
1242 Session::handle_locations_changed (Locations::LocationList& locations)
1244 Locations::LocationList::iterator i;
1246 bool set_loop = false;
1247 bool set_punch = false;
1249 for (i = locations.begin(); i != locations.end(); ++i) {
1253 if (location->is_auto_punch()) {
1254 set_auto_punch_location (location);
1257 if (location->is_auto_loop()) {
1258 set_auto_loop_location (location);
1262 if (location->is_start()) {
1263 start_location = location;
1265 if (location->is_end()) {
1266 end_location = location;
1271 set_auto_loop_location (0);
1274 set_auto_punch_location (0);
1281 Session::enable_record ()
1283 /* XXX really atomic compare+swap here */
1284 if (g_atomic_int_get (&_record_status) != Recording) {
1285 g_atomic_int_set (&_record_status, Recording);
1286 _last_record_location = _transport_frame;
1287 send_mmc_in_another_thread (MIDI::MachineControl::cmdRecordStrobe);
1289 if (Config->get_monitoring_model() == HardwareMonitoring && Config->get_auto_input()) {
1290 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1291 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1292 if ((*i)->record_enabled ()) {
1293 (*i)->monitor_input (true);
1298 RecordStateChanged ();
1303 Session::disable_record (bool rt_context, bool force)
1307 if ((rs = (RecordState) g_atomic_int_get (&_record_status)) != Disabled) {
1309 if ((!Config->get_latched_record_enable () && !play_loop) || force) {
1310 g_atomic_int_set (&_record_status, Disabled);
1312 if (rs == Recording) {
1313 g_atomic_int_set (&_record_status, Enabled);
1317 send_mmc_in_another_thread (MIDI::MachineControl::cmdRecordExit);
1319 if (Config->get_monitoring_model() == HardwareMonitoring && Config->get_auto_input()) {
1320 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1322 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1323 if ((*i)->record_enabled ()) {
1324 (*i)->monitor_input (false);
1329 RecordStateChanged (); /* emit signal */
1332 remove_pending_capture_state ();
1338 Session::step_back_from_record ()
1340 /* XXX really atomic compare+swap here */
1341 if (g_atomic_int_get (&_record_status) == Recording) {
1342 g_atomic_int_set (&_record_status, Enabled);
1344 if (Config->get_monitoring_model() == HardwareMonitoring && Config->get_auto_input()) {
1345 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1347 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1348 if ((*i)->record_enabled ()) {
1349 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
1350 (*i)->monitor_input (false);
1358 Session::maybe_enable_record ()
1360 g_atomic_int_set (&_record_status, Enabled);
1362 /* this function is currently called from somewhere other than an RT thread.
1363 this save_state() call therefore doesn't impact anything.
1366 save_state ("", true);
1368 if (_transport_speed) {
1369 if (!Config->get_punch_in()) {
1373 send_mmc_in_another_thread (MIDI::MachineControl::cmdRecordPause);
1374 RecordStateChanged (); /* EMIT SIGNAL */
1381 Session::audible_frame () const
1387 if (_transport_speed == 0.0f && non_realtime_work_pending()) {
1388 return last_stop_frame;
1391 /* the first of these two possible settings for "offset"
1392 mean that the audible frame is stationary until
1393 audio emerges from the latency compensation
1396 the second means that the audible frame is stationary
1397 until audio would emerge from a physical port
1398 in the absence of any plugin latency compensation
1401 offset = _worst_output_latency;
1403 if (offset > current_block_size) {
1404 offset -= current_block_size;
1406 /* XXX is this correct? if we have no external
1407 physical connections and everything is internal
1408 then surely this is zero? still, how
1409 likely is that anyway?
1411 offset = current_block_size;
1414 if (synced_to_jack()) {
1415 tf = _engine.transport_frame();
1417 tf = _transport_frame;
1422 if (!non_realtime_work_pending()) {
1426 /* check to see if we have passed the first guaranteed
1427 audible frame past our last stopping position. if not,
1428 the return that last stopping point because in terms
1429 of audible frames, we have not moved yet.
1432 if (_transport_speed > 0.0f) {
1434 if (!play_loop || !have_looped) {
1435 if (tf < last_stop_frame + offset) {
1436 return last_stop_frame;
1445 } else if (_transport_speed < 0.0f) {
1447 /* XXX wot? no backward looping? */
1449 if (tf > last_stop_frame - offset) {
1450 return last_stop_frame;
1462 Session::set_frame_rate (nframes_t frames_per_second)
1464 /** \fn void Session::set_frame_size(nframes_t)
1465 the AudioEngine object that calls this guarantees
1466 that it will not be called while we are also in
1467 ::process(). Its fine to do things that block
1471 _base_frame_rate = frames_per_second;
1475 IO::set_automation_interval ((jack_nframes_t) ceil ((double) frames_per_second * (0.001 * Config->get_automation_interval())));
1479 // XXX we need some equivalent to this, somehow
1480 // SndFileSource::setup_standard_crossfades (frames_per_second);
1484 /* XXX need to reset/reinstantiate all LADSPA plugins */
1488 Session::set_block_size (nframes_t nframes)
1490 /* the AudioEngine guarantees
1491 that it will not be called while we are also in
1492 ::process(). It is therefore fine to do things that block
1497 vector<Sample*>::iterator i;
1500 current_block_size = nframes;
1502 for (np = 0, i = _passthru_buffers.begin(); i != _passthru_buffers.end(); ++i, ++np) {
1506 for (vector<Sample*>::iterator i = _silent_buffers.begin(); i != _silent_buffers.end(); ++i) {
1510 _passthru_buffers.clear ();
1511 _silent_buffers.clear ();
1513 ensure_passthru_buffers (np);
1515 for (vector<Sample*>::iterator i = _send_buffers.begin(); i != _send_buffers.end(); ++i) {
1519 #ifdef NO_POSIX_MEMALIGN
1520 buf = (Sample *) malloc(current_block_size * sizeof(Sample));
1522 posix_memalign((void **)&buf,CPU_CACHE_ALIGN,current_block_size * sizeof(Sample));
1526 memset (*i, 0, sizeof (Sample) * current_block_size);
1530 if (_gain_automation_buffer) {
1531 delete [] _gain_automation_buffer;
1533 _gain_automation_buffer = new gain_t[nframes];
1535 allocate_pan_automation_buffers (nframes, _npan_buffers, true);
1537 boost::shared_ptr<RouteList> r = routes.reader ();
1539 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1540 (*i)->set_block_size (nframes);
1543 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1544 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1545 (*i)->set_block_size (nframes);
1548 set_worst_io_latencies ();
1553 Session::set_default_fade (float steepness, float fade_msecs)
1556 nframes_t fade_frames;
1558 /* Don't allow fade of less 1 frame */
1560 if (fade_msecs < (1000.0 * (1.0/_current_frame_rate))) {
1567 fade_frames = (nframes_t) floor (fade_msecs * _current_frame_rate * 0.001);
1571 default_fade_msecs = fade_msecs;
1572 default_fade_steepness = steepness;
1575 // jlc, WTF is this!
1576 Glib::RWLock::ReaderLock lm (route_lock);
1577 AudioRegion::set_default_fade (steepness, fade_frames);
1582 /* XXX have to do this at some point */
1583 /* foreach region using default fade, reset, then
1584 refill_all_diskstream_buffers ();
1589 struct RouteSorter {
1590 bool operator() (boost::shared_ptr<Route> r1, boost::shared_ptr<Route> r2) {
1591 if (r1->fed_by.find (r2) != r1->fed_by.end()) {
1593 } else if (r2->fed_by.find (r1) != r2->fed_by.end()) {
1596 if (r1->fed_by.empty()) {
1597 if (r2->fed_by.empty()) {
1598 /* no ardour-based connections inbound to either route. just use signal order */
1599 return r1->order_key(N_("signal")) < r2->order_key(N_("signal"));
1601 /* r2 has connections, r1 does not; run r1 early */
1605 return r1->order_key(N_("signal")) < r2->order_key(N_("signal"));
1612 trace_terminal (shared_ptr<Route> r1, shared_ptr<Route> rbase)
1614 shared_ptr<Route> r2;
1616 if ((r1->fed_by.find (rbase) != r1->fed_by.end()) && (rbase->fed_by.find (r1) != rbase->fed_by.end())) {
1617 info << string_compose(_("feedback loop setup between %1 and %2"), r1->name(), rbase->name()) << endmsg;
1621 /* make a copy of the existing list of routes that feed r1 */
1623 set<shared_ptr<Route> > existing = r1->fed_by;
1625 /* for each route that feeds r1, recurse, marking it as feeding
1629 for (set<shared_ptr<Route> >::iterator i = existing.begin(); i != existing.end(); ++i) {
1632 /* r2 is a route that feeds r1 which somehow feeds base. mark
1633 base as being fed by r2
1636 rbase->fed_by.insert (r2);
1640 /* 2nd level feedback loop detection. if r1 feeds or is fed by r2,
1644 if ((r1->fed_by.find (r2) != r1->fed_by.end()) && (r2->fed_by.find (r1) != r2->fed_by.end())) {
1648 /* now recurse, so that we can mark base as being fed by
1649 all routes that feed r2
1652 trace_terminal (r2, rbase);
1659 Session::resort_routes ()
1661 /* don't do anything here with signals emitted
1662 by Routes while we are being destroyed.
1665 if (_state_of_the_state & Deletion) {
1672 RCUWriter<RouteList> writer (routes);
1673 shared_ptr<RouteList> r = writer.get_copy ();
1674 resort_routes_using (r);
1675 /* writer goes out of scope and forces update */
1680 Session::resort_routes_using (shared_ptr<RouteList> r)
1682 RouteList::iterator i, j;
1684 for (i = r->begin(); i != r->end(); ++i) {
1686 (*i)->fed_by.clear ();
1688 for (j = r->begin(); j != r->end(); ++j) {
1690 /* although routes can feed themselves, it will
1691 cause an endless recursive descent if we
1692 detect it. so don't bother checking for
1700 if ((*j)->feeds (*i)) {
1701 (*i)->fed_by.insert (*j);
1706 for (i = r->begin(); i != r->end(); ++i) {
1707 trace_terminal (*i, *i);
1713 /* don't leave dangling references to routes in Route::fed_by */
1715 for (i = r->begin(); i != r->end(); ++i) {
1716 (*i)->fed_by.clear ();
1720 cerr << "finished route resort\n";
1722 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1723 cerr << " " << (*i)->name() << " signal order = " << (*i)->order_key ("signal") << endl;
1730 list<boost::shared_ptr<AudioTrack> >
1731 Session::new_audio_track (int input_channels, int output_channels, TrackMode mode, uint32_t how_many)
1733 char track_name[32];
1734 uint32_t track_id = 0;
1736 uint32_t channels_used = 0;
1738 RouteList new_routes;
1739 list<boost::shared_ptr<AudioTrack> > ret;
1740 uint32_t control_id;
1742 /* count existing audio tracks */
1745 shared_ptr<RouteList> r = routes.reader ();
1747 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1748 if (dynamic_cast<AudioTrack*>((*i).get()) != 0) {
1749 if (!(*i)->hidden()) {
1751 channels_used += (*i)->n_inputs();
1757 vector<string> physinputs;
1758 vector<string> physoutputs;
1759 uint32_t nphysical_in;
1760 uint32_t nphysical_out;
1762 _engine.get_physical_audio_outputs (physoutputs);
1763 _engine.get_physical_audio_inputs (physinputs);
1764 control_id = ntracks() + nbusses() + 1;
1768 /* check for duplicate route names, since we might have pre-existing
1769 routes with this name (e.g. create Audio1, Audio2, delete Audio1,
1770 save, close,restart,add new route - first named route is now
1778 snprintf (track_name, sizeof(track_name), "Audio %" PRIu32, track_id);
1780 if (route_by_name (track_name) == 0) {
1784 } while (track_id < (UINT_MAX-1));
1786 if (Config->get_input_auto_connect() & AutoConnectPhysical) {
1787 nphysical_in = min (n_physical_audio_inputs, (uint32_t) physinputs.size());
1792 if (Config->get_output_auto_connect() & AutoConnectPhysical) {
1793 nphysical_out = min (n_physical_audio_outputs, (uint32_t) physinputs.size());
1798 shared_ptr<AudioTrack> track;
1801 track = boost::shared_ptr<AudioTrack>((new AudioTrack (*this, track_name, Route::Flag (0), mode)));
1803 if (track->ensure_io (input_channels, output_channels, false, this)) {
1804 error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
1805 input_channels, output_channels)
1811 for (uint32_t x = 0; x < track->n_inputs() && x < nphysical_in; ++x) {
1815 if (Config->get_input_auto_connect() & AutoConnectPhysical) {
1816 port = physinputs[(channels_used+x)%nphysical_in];
1819 if (port.length() && track->connect_input (track->input (x), port, this)) {
1825 for (uint32_t x = 0; x < track->n_outputs(); ++x) {
1829 if (nphysical_out && (Config->get_output_auto_connect() & AutoConnectPhysical)) {
1830 port = physoutputs[(channels_used+x)%nphysical_out];
1831 } else if (Config->get_output_auto_connect() & AutoConnectMaster) {
1833 port = _master_out->input (x%_master_out->n_inputs())->name();
1837 if (port.length() && track->connect_output (track->output (x), port, this)) {
1842 channels_used += track->n_inputs ();
1844 track->audio_diskstream()->non_realtime_input_change();
1846 track->DiskstreamChanged.connect (mem_fun (this, &Session::resort_routes));
1847 track->set_remote_control_id (control_id);
1850 new_routes.push_back (track);
1851 ret.push_back (track);
1855 catch (failed_constructor &err) {
1856 error << _("Session: could not create new audio track.") << endmsg;
1859 /* we need to get rid of this, since the track failed to be created */
1860 /* XXX arguably, AudioTrack::AudioTrack should not do the Session::add_diskstream() */
1863 RCUWriter<DiskstreamList> writer (diskstreams);
1864 boost::shared_ptr<DiskstreamList> ds = writer.get_copy();
1865 ds->remove (track->audio_diskstream());
1872 catch (AudioEngine::PortRegistrationFailure& pfe) {
1874 error << _("No more JACK ports are available. You will need to stop Ardour and restart JACK with ports if you need this many tracks.") << endmsg;
1877 /* we need to get rid of this, since the track failed to be created */
1878 /* XXX arguably, AudioTrack::AudioTrack should not do the Session::add_diskstream() */
1881 RCUWriter<DiskstreamList> writer (diskstreams);
1882 boost::shared_ptr<DiskstreamList> ds = writer.get_copy();
1883 ds->remove (track->audio_diskstream());
1894 if (!new_routes.empty()) {
1895 add_routes (new_routes, true);
1902 Session::set_remote_control_ids ()
1904 RemoteModel m = Config->get_remote_model();
1906 shared_ptr<RouteList> r = routes.reader ();
1908 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1909 if ( MixerOrdered == m) {
1910 long order = (*i)->order_key(N_("signal"));
1911 (*i)->set_remote_control_id( order+1 );
1912 } else if ( EditorOrdered == m) {
1913 long order = (*i)->order_key(N_("editor"));
1914 (*i)->set_remote_control_id( order+1 );
1915 } else if ( UserOrdered == m) {
1916 //do nothing ... only changes to remote id's are initiated by user
1923 Session::new_audio_route (int input_channels, int output_channels, uint32_t how_many)
1926 uint32_t bus_id = 1;
1930 uint32_t control_id;
1932 /* count existing audio busses */
1935 shared_ptr<RouteList> r = routes.reader ();
1937 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1938 if (dynamic_cast<AudioTrack*>((*i).get()) == 0) {
1939 if (!(*i)->hidden() && (*i)->name() != _("master")) {
1946 vector<string> physinputs;
1947 vector<string> physoutputs;
1949 _engine.get_physical_audio_outputs (physoutputs);
1950 _engine.get_physical_audio_inputs (physinputs);
1951 control_id = ntracks() + nbusses() + 1;
1956 snprintf (bus_name, sizeof(bus_name), "Bus %" PRIu32, bus_id);
1960 if (route_by_name (bus_name) == 0) {
1964 } while (bus_id < (UINT_MAX-1));
1967 shared_ptr<Route> bus (new Route (*this, bus_name, -1, -1, -1, -1, Route::Flag(0), DataType::AUDIO));
1969 if (bus->ensure_io (input_channels, output_channels, false, this)) {
1970 error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
1971 input_channels, output_channels)
1976 for (uint32_t x = 0; n_physical_audio_inputs && x < bus->n_inputs(); ++x) {
1980 if (Config->get_input_auto_connect() & AutoConnectPhysical) {
1981 port = physinputs[((n+x)%n_physical_audio_inputs)];
1984 if (port.length() && bus->connect_input (bus->input (x), port, this)) {
1989 for (uint32_t x = 0; n_physical_audio_outputs && x < bus->n_outputs(); ++x) {
1993 if (Config->get_output_auto_connect() & AutoConnectPhysical) {
1994 port = physoutputs[((n+x)%n_physical_audio_outputs)];
1995 } else if (Config->get_output_auto_connect() & AutoConnectMaster) {
1997 port = _master_out->input (x%_master_out->n_inputs())->name();
2001 if (port.length() && bus->connect_output (bus->output (x), port, this)) {
2006 bus->set_remote_control_id (control_id);
2009 ret.push_back (bus);
2013 catch (failed_constructor &err) {
2014 error << _("Session: could not create new audio route.") << endmsg;
2018 catch (AudioEngine::PortRegistrationFailure& pfe) {
2019 error << _("No more JACK ports are available. You will need to stop Ardour and restart JACK with ports if you need this many tracks.") << endmsg;
2029 add_routes (ret, true);
2037 Session::new_route_from_template (uint32_t how_many, const std::string& template_path)
2041 uint32_t control_id;
2044 if (!tree.read (template_path.c_str())) {
2048 XMLNode* node = tree.root();
2050 control_id = ntracks() + nbusses() + 1;
2054 XMLNode node_copy (*node); // make a copy so we can change the name if we need to
2056 std::string node_name = IO::name_from_state (*node_copy.children().front());
2058 if (route_by_name (node_name) != 0) {
2060 /* generate a new name by adding a number to the end of the template name */
2062 uint32_t number = 1;
2065 snprintf (name, sizeof (name), "%s %" PRIu32, node_name.c_str(), number);
2069 if (route_by_name (name) == 0) {
2073 } while (number < (UINT_MAX-1));
2075 IO::set_name_in_state (node_copy, name);
2079 shared_ptr<Route> route (new Route (*this, node_copy, DataType::AUDIO));
2081 route->set_remote_control_id (control_id);
2084 ret.push_back (route);
2087 catch (failed_constructor &err) {
2088 error << _("Session: could not create new route from template") << endmsg;
2092 catch (AudioEngine::PortRegistrationFailure& pfe) {
2093 error << _("No more JACK ports are available. You will need to stop Ardour and restart JACK with ports if you need this many tracks.") << endmsg;
2102 add_routes (ret, true);
2109 Session::add_routes (RouteList& new_routes, bool save)
2112 RCUWriter<RouteList> writer (routes);
2113 shared_ptr<RouteList> r = writer.get_copy ();
2114 r->insert (r->end(), new_routes.begin(), new_routes.end());
2115 resort_routes_using (r);
2118 for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) {
2120 boost::weak_ptr<Route> wpr (*x);
2122 (*x)->solo_changed.connect (sigc::bind (mem_fun (*this, &Session::route_solo_changed), wpr));
2123 (*x)->mute_changed.connect (mem_fun (*this, &Session::route_mute_changed));
2124 (*x)->output_changed.connect (mem_fun (*this, &Session::set_worst_io_latencies_x));
2125 (*x)->redirects_changed.connect (mem_fun (*this, &Session::update_latency_compensation_proxy));
2127 if ((*x)->master()) {
2131 if ((*x)->control()) {
2132 _control_out = (*x);
2136 if (_control_out && IO::connecting_legal) {
2138 vector<string> cports;
2139 uint32_t ni = _control_out->n_inputs();
2142 for (n = 0; n < ni; ++n) {
2143 cports.push_back (_control_out->input(n)->name());
2146 for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) {
2147 (*x)->set_control_outs (cports);
2154 save_state (_current_snapshot_name);
2157 RouteAdded (new_routes); /* EMIT SIGNAL */
2161 Session::add_diskstream (boost::shared_ptr<Diskstream> dstream)
2163 /* need to do this in case we're rolling at the time, to prevent false underruns */
2164 dstream->do_refill_with_alloc ();
2166 dstream->set_block_size (current_block_size);
2169 RCUWriter<DiskstreamList> writer (diskstreams);
2170 boost::shared_ptr<DiskstreamList> ds = writer.get_copy();
2171 ds->push_back (dstream);
2172 /* writer goes out of scope, copies ds back to main */
2175 dstream->PlaylistChanged.connect (sigc::bind (mem_fun (*this, &Session::diskstream_playlist_changed),
2176 boost::weak_ptr<Diskstream> (dstream)));
2177 /* this will connect to future changes, and check the current length */
2178 diskstream_playlist_changed (dstream);
2180 dstream->prepare ();
2184 Session::remove_route (shared_ptr<Route> route)
2187 RCUWriter<RouteList> writer (routes);
2188 shared_ptr<RouteList> rs = writer.get_copy ();
2192 /* deleting the master out seems like a dumb
2193 idea, but its more of a UI policy issue
2197 if (route == _master_out) {
2198 _master_out = shared_ptr<Route> ();
2201 if (route == _control_out) {
2202 _control_out = shared_ptr<Route> ();
2204 /* cancel control outs for all routes */
2206 vector<string> empty;
2208 for (RouteList::iterator r = rs->begin(); r != rs->end(); ++r) {
2209 (*r)->set_control_outs (empty);
2213 update_route_solo_state ();
2215 /* writer goes out of scope, forces route list update */
2218 // FIXME: audio specific
2220 boost::shared_ptr<AudioDiskstream> ds;
2222 if ((at = dynamic_cast<AudioTrack*>(route.get())) != 0) {
2223 ds = at->audio_diskstream();
2229 RCUWriter<DiskstreamList> dsl (diskstreams);
2230 boost::shared_ptr<DiskstreamList> d = dsl.get_copy();
2234 diskstreams.flush ();
2237 find_current_end ();
2239 // We need to disconnect the routes inputs and outputs
2241 route->disconnect_inputs (0);
2242 route->disconnect_outputs (0);
2244 update_latency_compensation (false, false);
2247 /* get rid of it from the dead wood collection in the route list manager */
2249 /* XXX i think this is unsafe as it currently stands, but i am not sure. (pd, october 2nd, 2006) */
2253 /* try to cause everyone to drop their references */
2255 route->drop_references ();
2257 sync_order_keys (N_("session"));
2259 /* save the new state of the world */
2261 if (save_state (_current_snapshot_name)) {
2262 save_history (_current_snapshot_name);
2267 Session::route_mute_changed (void* src)
2273 Session::route_solo_changed (void* src, boost::weak_ptr<Route> wpr)
2275 if (solo_update_disabled) {
2281 boost::shared_ptr<Route> route = wpr.lock ();
2284 /* should not happen */
2285 error << string_compose (_("programming error: %1"), X_("invalid route weak ptr passed to route_solo_changed")) << endmsg;
2289 is_track = (boost::dynamic_pointer_cast<AudioTrack>(route) != 0);
2291 shared_ptr<RouteList> r = routes.reader ();
2293 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2295 /* soloing a track mutes all other tracks, soloing a bus mutes all other busses */
2299 /* don't mess with busses */
2301 if (dynamic_cast<AudioTrack*>((*i).get()) == 0) {
2307 /* don't mess with tracks */
2309 if (dynamic_cast<AudioTrack*>((*i).get()) != 0) {
2314 if ((*i) != route &&
2315 ((*i)->mix_group () == 0 ||
2316 (*i)->mix_group () != route->mix_group () ||
2317 !route->mix_group ()->is_active())) {
2319 if ((*i)->soloed()) {
2321 /* if its already soloed, and solo latching is enabled,
2322 then leave it as it is.
2325 if (Config->get_solo_latched()) {
2332 solo_update_disabled = true;
2333 (*i)->set_solo (false, src);
2334 solo_update_disabled = false;
2338 bool something_soloed = false;
2339 bool same_thing_soloed = false;
2340 bool signal = false;
2342 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2343 if ((*i)->soloed()) {
2344 something_soloed = true;
2345 if (dynamic_cast<AudioTrack*>((*i).get())) {
2347 same_thing_soloed = true;
2352 same_thing_soloed = true;
2360 if (something_soloed != currently_soloing) {
2362 currently_soloing = something_soloed;
2365 modify_solo_mute (is_track, same_thing_soloed);
2368 SoloActive (currently_soloing); /* EMIT SIGNAL */
2371 SoloChanged (); /* EMIT SIGNAL */
2377 Session::update_route_solo_state ()
2380 bool is_track = false;
2381 bool signal = false;
2383 /* this is where we actually implement solo by changing
2384 the solo mute setting of each track.
2387 shared_ptr<RouteList> r = routes.reader ();
2389 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2390 if ((*i)->soloed()) {
2392 if (dynamic_cast<AudioTrack*>((*i).get())) {
2399 if (mute != currently_soloing) {
2401 currently_soloing = mute;
2404 if (!is_track && !mute) {
2406 /* nothing is soloed */
2408 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2409 (*i)->set_solo_mute (false);
2419 modify_solo_mute (is_track, mute);
2422 SoloActive (currently_soloing);
2427 Session::modify_solo_mute (bool is_track, bool mute)
2429 shared_ptr<RouteList> r = routes.reader ();
2431 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2435 /* only alter track solo mute */
2437 if (dynamic_cast<AudioTrack*>((*i).get())) {
2438 if ((*i)->soloed()) {
2439 (*i)->set_solo_mute (!mute);
2441 (*i)->set_solo_mute (mute);
2447 /* only alter bus solo mute */
2449 if (!dynamic_cast<AudioTrack*>((*i).get())) {
2451 if ((*i)->soloed()) {
2453 (*i)->set_solo_mute (false);
2457 /* don't mute master or control outs
2458 in response to another bus solo
2461 if ((*i) != _master_out &&
2462 (*i) != _control_out) {
2463 (*i)->set_solo_mute (mute);
2474 Session::catch_up_on_solo ()
2476 /* this is called after set_state() to catch the full solo
2477 state, which can't be correctly determined on a per-route
2478 basis, but needs the global overview that only the session
2481 update_route_solo_state();
2485 Session::catch_up_on_solo_mute_override ()
2487 if (Config->get_solo_model() != InverseMute) {
2491 /* this is called whenever the param solo-mute-override is
2494 shared_ptr<RouteList> r = routes.reader ();
2496 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2497 (*i)->catch_up_on_solo_mute_override ();
2502 Session::route_by_name (string name)
2504 shared_ptr<RouteList> r = routes.reader ();
2506 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2507 if ((*i)->name() == name) {
2512 return shared_ptr<Route> ((Route*) 0);
2516 Session::route_by_id (PBD::ID id)
2518 shared_ptr<RouteList> r = routes.reader ();
2520 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2521 if ((*i)->id() == id) {
2526 return shared_ptr<Route> ((Route*) 0);
2530 Session::route_by_remote_id (uint32_t id)
2532 shared_ptr<RouteList> r = routes.reader ();
2534 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2535 if ((*i)->remote_control_id() == id) {
2540 return shared_ptr<Route> ((Route*) 0);
2544 Session::find_current_end ()
2546 if (_state_of_the_state & Loading) {
2550 nframes_t max = get_maximum_extent ();
2552 if (max > end_location->end()) {
2553 end_location->set_end (max);
2555 DurationChanged(); /* EMIT SIGNAL */
2560 Session::get_maximum_extent () const
2565 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
2567 for (DiskstreamList::const_iterator i = dsl->begin(); i != dsl->end(); ++i) {
2568 if ((*i)->destructive()) //ignore tape tracks when getting max extents
2570 boost::shared_ptr<Playlist> pl = (*i)->playlist();
2571 if ((me = pl->get_maximum_extent()) > max) {
2579 boost::shared_ptr<Diskstream>
2580 Session::diskstream_by_name (string name)
2582 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
2584 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
2585 if ((*i)->name() == name) {
2590 return boost::shared_ptr<Diskstream>((Diskstream*) 0);
2593 boost::shared_ptr<Diskstream>
2594 Session::diskstream_by_id (const PBD::ID& id)
2596 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
2598 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
2599 if ((*i)->id() == id) {
2604 return boost::shared_ptr<Diskstream>((Diskstream*) 0);
2607 /* AudioRegion management */
2610 Session::new_region_name (string old)
2612 string::size_type last_period;
2614 string::size_type len = old.length() + 64;
2617 if ((last_period = old.find_last_of ('.')) == string::npos) {
2619 /* no period present - add one explicitly */
2622 last_period = old.length() - 1;
2627 number = atoi (old.substr (last_period+1).c_str());
2631 while (number < (UINT_MAX-1)) {
2633 AudioRegionList::const_iterator i;
2638 snprintf (buf, len, "%s%" PRIu32, old.substr (0, last_period + 1).c_str(), number);
2641 for (i = audio_regions.begin(); i != audio_regions.end(); ++i) {
2642 if (i->second->name() == sbuf) {
2647 if (i == audio_regions.end()) {
2652 if (number != (UINT_MAX-1)) {
2656 error << string_compose (_("cannot create new name for region \"%1\""), old) << endmsg;
2661 Session::region_name (string& result, string base, bool newlevel)
2668 Glib::Mutex::Lock lm (region_lock);
2670 snprintf (buf, sizeof (buf), "%d", (int)audio_regions.size() + 1);
2679 string::size_type pos;
2681 pos = base.find_last_of ('.');
2683 /* pos may be npos, but then we just use entire base */
2685 subbase = base.substr (0, pos);
2690 Glib::Mutex::Lock lm (region_lock);
2692 map<string,uint32_t>::iterator x;
2696 if ((x = region_name_map.find (subbase)) == region_name_map.end()) {
2698 region_name_map[subbase] = 1;
2701 snprintf (buf, sizeof (buf), ".%d", x->second);
2711 Session::add_region (boost::shared_ptr<Region> region)
2713 vector<boost::shared_ptr<Region> > v;
2714 v.push_back (region);
2719 Session::add_regions (vector<boost::shared_ptr<Region> >& new_regions)
2721 boost::shared_ptr<AudioRegion> ar;
2722 boost::shared_ptr<AudioRegion> oar;
2726 Glib::Mutex::Lock lm (region_lock);
2728 for (vector<boost::shared_ptr<Region> >::iterator ii = new_regions.begin(); ii != new_regions.end(); ++ii) {
2730 boost::shared_ptr<Region> region = *ii;
2734 error << _("Session::add_region() ignored a null region. Warning: you might have lost a region.") << endmsg;
2736 } else if ((ar = boost::dynamic_pointer_cast<AudioRegion> (region)) != 0) {
2738 AudioRegionList::iterator x;
2740 for (x = audio_regions.begin(); x != audio_regions.end(); ++x) {
2742 oar = boost::dynamic_pointer_cast<AudioRegion> (x->second);
2744 if (ar->region_list_equivalent (oar)) {
2749 if (x == audio_regions.end()) {
2751 pair<AudioRegionList::key_type,AudioRegionList::mapped_type> entry;
2753 entry.first = region->id();
2756 pair<AudioRegionList::iterator,bool> x = audio_regions.insert (entry);
2767 fatal << _("programming error: ")
2768 << X_("unknown region type passed to Session::add_region()")
2776 /* mark dirty because something has changed even if we didn't
2777 add the region to the region list.
2784 vector<boost::weak_ptr<AudioRegion> > v;
2785 boost::shared_ptr<AudioRegion> first_ar;
2787 for (vector<boost::shared_ptr<Region> >::iterator ii = new_regions.begin(); ii != new_regions.end(); ++ii) {
2789 boost::shared_ptr<Region> region = *ii;
2790 boost::shared_ptr<AudioRegion> ar;
2794 error << _("Session::add_region() ignored a null region. Warning: you might have lost a region.") << endmsg;
2796 } else if ((ar = boost::dynamic_pointer_cast<AudioRegion> (region)) != 0) {
2804 region->StateChanged.connect (sigc::bind (mem_fun (*this, &Session::region_changed), boost::weak_ptr<Region>(region)));
2805 region->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_region), boost::weak_ptr<Region>(region)));
2807 update_region_name_map (region);
2811 AudioRegionsAdded (v); /* EMIT SIGNAL */
2817 Session::update_region_name_map (boost::shared_ptr<Region> region)
2819 string::size_type last_period = region->name().find_last_of ('.');
2821 if (last_period != string::npos && last_period < region->name().length() - 1) {
2823 string base = region->name().substr (0, last_period);
2824 string number = region->name().substr (last_period+1);
2825 map<string,uint32_t>::iterator x;
2827 /* note that if there is no number, we get zero from atoi,
2831 region_name_map[base] = atoi (number);
2836 Session::region_changed (Change what_changed, boost::weak_ptr<Region> weak_region)
2838 boost::shared_ptr<Region> region (weak_region.lock ());
2844 if (what_changed & Region::HiddenChanged) {
2845 /* relay hidden changes */
2846 RegionHiddenChange (region);
2849 if (what_changed & NameChanged) {
2850 update_region_name_map (region);
2855 Session::remove_region (boost::weak_ptr<Region> weak_region)
2857 AudioRegionList::iterator i;
2858 boost::shared_ptr<Region> region (weak_region.lock ());
2864 boost::shared_ptr<AudioRegion> ar;
2865 bool removed = false;
2868 Glib::Mutex::Lock lm (region_lock);
2870 if ((ar = boost::dynamic_pointer_cast<AudioRegion> (region)) != 0) {
2871 if ((i = audio_regions.find (region->id())) != audio_regions.end()) {
2872 audio_regions.erase (i);
2878 fatal << _("programming error: ")
2879 << X_("unknown region type passed to Session::remove_region()")
2885 /* mark dirty because something has changed even if we didn't
2886 remove the region from the region list.
2892 AudioRegionRemoved (ar); /* EMIT SIGNAL */
2896 boost::shared_ptr<AudioRegion>
2897 Session::find_whole_file_parent (boost::shared_ptr<AudioRegion const> child)
2899 AudioRegionList::iterator i;
2900 boost::shared_ptr<AudioRegion> region;
2901 Glib::Mutex::Lock lm (region_lock);
2903 for (i = audio_regions.begin(); i != audio_regions.end(); ++i) {
2907 if (region->whole_file()) {
2909 if (child->source_equivalent (region)) {
2915 return boost::shared_ptr<AudioRegion> ();
2919 Session::find_equivalent_playlist_regions (boost::shared_ptr<Region> region, vector<boost::shared_ptr<Region> >& result)
2921 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i)
2922 (*i)->get_region_list_equivalent_regions (region, result);
2926 Session::destroy_region (boost::shared_ptr<Region> region)
2928 vector<boost::shared_ptr<Source> > srcs;
2931 boost::shared_ptr<AudioRegion> aregion;
2933 if ((aregion = boost::dynamic_pointer_cast<AudioRegion> (region)) == 0) {
2937 if (aregion->playlist()) {
2938 aregion->playlist()->destroy_region (region);
2941 for (uint32_t n = 0; n < aregion->n_channels(); ++n) {
2942 srcs.push_back (aregion->source (n));
2946 region->drop_references ();
2948 for (vector<boost::shared_ptr<Source> >::iterator i = srcs.begin(); i != srcs.end(); ++i) {
2950 if (!(*i)->used()) {
2951 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*i);
2954 (afs)->mark_for_remove ();
2957 (*i)->drop_references ();
2959 cerr << "source was not used by any playlist\n";
2967 Session::destroy_regions (list<boost::shared_ptr<Region> > regions)
2969 for (list<boost::shared_ptr<Region> >::iterator i = regions.begin(); i != regions.end(); ++i) {
2970 destroy_region (*i);
2976 Session::remove_last_capture ()
2978 list<boost::shared_ptr<Region> > r;
2980 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
2982 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
2983 list<boost::shared_ptr<Region> >& l = (*i)->last_capture_regions();
2986 r.insert (r.end(), l.begin(), l.end());
2991 destroy_regions (r);
2993 save_state (_current_snapshot_name);
2999 Session::remove_region_from_region_list (boost::shared_ptr<Region> r)
3005 /* Source Management */
3008 Session::add_source (boost::shared_ptr<Source> source)
3010 boost::shared_ptr<AudioFileSource> afs;
3012 if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(source)) != 0) {
3014 pair<AudioSourceList::key_type, AudioSourceList::mapped_type> entry;
3015 pair<AudioSourceList::iterator,bool> result;
3017 entry.first = source->id();
3021 Glib::Mutex::Lock lm (audio_source_lock);
3022 result = audio_sources.insert (entry);
3025 if (result.second) {
3026 source->GoingAway.connect (sigc::bind (mem_fun (this, &Session::remove_source), boost::weak_ptr<Source> (source)));
3030 if (Config->get_auto_analyse_audio()) {
3031 Analyser::queue_source_for_analysis (source, false);
3037 Session::remove_source (boost::weak_ptr<Source> src)
3039 AudioSourceList::iterator i;
3040 boost::shared_ptr<Source> source = src.lock();
3047 Glib::Mutex::Lock lm (audio_source_lock);
3049 if ((i = audio_sources.find (source->id())) != audio_sources.end()) {
3050 audio_sources.erase (i);
3054 if (!_state_of_the_state & InCleanup) {
3056 /* save state so we don't end up with a session file
3057 referring to non-existent sources.
3060 save_state (_current_snapshot_name);
3064 boost::shared_ptr<Source>
3065 Session::source_by_id (const PBD::ID& id)
3067 Glib::Mutex::Lock lm (audio_source_lock);
3068 AudioSourceList::iterator i;
3069 boost::shared_ptr<Source> source;
3071 if ((i = audio_sources.find (id)) != audio_sources.end()) {
3075 /* XXX search MIDI or other searches here */
3081 boost::shared_ptr<Source>
3082 Session::source_by_path_and_channel (const Glib::ustring& path, uint16_t chn)
3084 Glib::Mutex::Lock lm (audio_source_lock);
3086 for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ++i) {
3087 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(i->second);
3089 if (afs && afs->path() == path && chn == afs->channel()) {
3094 return boost::shared_ptr<Source>();
3098 Session::peak_path (Glib::ustring base) const
3100 return Glib::build_filename(peak_dir (), base + ".peak");
3104 Session::change_audio_path_by_name (string path, string oldname, string newname, bool destructive)
3107 string old_basename = PBD::basename_nosuffix (oldname);
3108 string new_legalized = legalize_for_path (newname);
3110 /* note: we know (or assume) the old path is already valid */
3114 /* destructive file sources have a name of the form:
3116 /path/to/Tnnnn-NAME(%[LR])?.wav
3118 the task here is to replace NAME with the new name.
3121 /* find last slash */
3125 string::size_type slash;
3126 string::size_type dash;
3128 if ((slash = path.find_last_of ('/')) == string::npos) {
3132 dir = path.substr (0, slash+1);
3134 /* '-' is not a legal character for the NAME part of the path */
3136 if ((dash = path.find_last_of ('-')) == string::npos) {
3140 prefix = path.substr (slash+1, dash-(slash+1));
3145 path += new_legalized;
3146 path += ".wav"; /* XXX gag me with a spoon */
3150 /* non-destructive file sources have a name of the form:
3152 /path/to/NAME-nnnnn(%[LR])?.wav
3154 the task here is to replace NAME with the new name.
3159 string::size_type slash;
3160 string::size_type dash;
3161 string::size_type postfix;
3163 /* find last slash */
3165 if ((slash = path.find_last_of ('/')) == string::npos) {
3169 dir = path.substr (0, slash+1);
3171 /* '-' is not a legal character for the NAME part of the path */
3173 if ((dash = path.find_last_of ('-')) == string::npos) {
3177 suffix = path.substr (dash+1);
3179 // Suffix is now everything after the dash. Now we need to eliminate
3180 // the nnnnn part, which is done by either finding a '%' or a '.'
3182 postfix = suffix.find_last_of ("%");
3183 if (postfix == string::npos) {
3184 postfix = suffix.find_last_of ('.');
3187 if (postfix != string::npos) {
3188 suffix = suffix.substr (postfix);
3190 error << "Logic error in Session::change_audio_path_by_name(), please report to the developers" << endl;
3194 const uint32_t limit = 10000;
3195 char buf[PATH_MAX+1];
3197 for (uint32_t cnt = 1; cnt <= limit; ++cnt) {
3199 snprintf (buf, sizeof(buf), "%s%s-%u%s", dir.c_str(), newname.c_str(), cnt, suffix.c_str());
3201 if (access (buf, F_OK) != 0) {
3209 error << "FATAL ERROR! Could not find a " << endl;
3218 Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool destructive)
3222 char buf[PATH_MAX+1];
3223 const uint32_t limit = 10000;
3227 legalized = legalize_for_path (name);
3229 /* find a "version" of the file name that doesn't exist in
3230 any of the possible directories.
3233 for (cnt = (destructive ? ++destructive_index : 1); cnt <= limit; ++cnt) {
3235 vector<space_and_path>::iterator i;
3236 uint32_t existing = 0;
3238 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3242 spath += sound_dir (false);
3246 snprintf (buf, sizeof(buf), "%s/T%04d-%s.wav", spath.c_str(), cnt, legalized.c_str());
3247 } else if (nchan == 2) {
3249 snprintf (buf, sizeof(buf), "%s/T%04d-%s%%L.wav", spath.c_str(), cnt, legalized.c_str());
3251 snprintf (buf, sizeof(buf), "%s/T%04d-%s%%R.wav", spath.c_str(), cnt, legalized.c_str());
3253 } else if (nchan < 26) {
3254 snprintf (buf, sizeof(buf), "%s/T%04d-%s%%%c.wav", spath.c_str(), cnt, legalized.c_str(), 'a' + chan);
3256 snprintf (buf, sizeof(buf), "%s/T%04d-%s.wav", spath.c_str(), cnt, legalized.c_str());
3265 snprintf (buf, sizeof(buf), "%s-%u.wav", spath.c_str(), cnt);
3266 } else if (nchan == 2) {
3268 snprintf (buf, sizeof(buf), "%s-%u%%L.wav", spath.c_str(), cnt);
3270 snprintf (buf, sizeof(buf), "%s-%u%%R.wav", spath.c_str(), cnt);
3272 } else if (nchan < 26) {
3273 snprintf (buf, sizeof(buf), "%s-%u%%%c.wav", spath.c_str(), cnt, 'a' + chan);
3275 snprintf (buf, sizeof(buf), "%s-%u.wav", spath.c_str(), cnt);
3279 if (g_file_test (buf, G_FILE_TEST_EXISTS)) {
3285 if (existing == 0) {
3290 error << string_compose(_("There are already %1 recordings for %2, which I consider too many."), limit, name) << endmsg;
3292 throw failed_constructor();
3296 /* we now have a unique name for the file, but figure out where to
3302 spath = discover_best_sound_dir ();
3305 string::size_type pos = foo.find_last_of ('/');
3307 if (pos == string::npos) {
3310 spath += foo.substr (pos + 1);
3316 boost::shared_ptr<AudioFileSource>
3317 Session::create_audio_source_for_session (AudioDiskstream& ds, uint32_t chan, bool destructive)
3319 string spath = audio_path_from_name (ds.name(), ds.n_channels(), chan, destructive);
3320 return boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (*this, spath, destructive, frame_rate()));
3323 /* Playlist management */
3325 boost::shared_ptr<Playlist>
3326 Session::playlist_by_name (string name)
3328 Glib::Mutex::Lock lm (playlist_lock);
3329 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
3330 if ((*i)->name() == name) {
3334 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
3335 if ((*i)->name() == name) {
3340 return boost::shared_ptr<Playlist>();
3344 Session::add_playlist (boost::shared_ptr<Playlist> playlist)
3346 if (playlist->hidden()) {
3351 Glib::Mutex::Lock lm (playlist_lock);
3352 if (find (playlists.begin(), playlists.end(), playlist) == playlists.end()) {
3353 playlists.insert (playlists.begin(), playlist);
3354 playlist->InUse.connect (sigc::bind (mem_fun (*this, &Session::track_playlist), boost::weak_ptr<Playlist>(playlist)));
3355 playlist->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_playlist), boost::weak_ptr<Playlist>(playlist)));
3361 PlaylistAdded (playlist); /* EMIT SIGNAL */
3365 Session::get_playlists (vector<boost::shared_ptr<Playlist> >& s)
3368 Glib::Mutex::Lock lm (playlist_lock);
3369 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
3372 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
3379 Session::track_playlist (bool inuse, boost::weak_ptr<Playlist> wpl)
3381 boost::shared_ptr<Playlist> pl(wpl.lock());
3387 PlaylistList::iterator x;
3390 /* its not supposed to be visible */
3395 Glib::Mutex::Lock lm (playlist_lock);
3399 unused_playlists.insert (pl);
3401 if ((x = playlists.find (pl)) != playlists.end()) {
3402 playlists.erase (x);
3408 playlists.insert (pl);
3410 if ((x = unused_playlists.find (pl)) != unused_playlists.end()) {
3411 unused_playlists.erase (x);
3418 Session::remove_playlist (boost::weak_ptr<Playlist> weak_playlist)
3420 if (_state_of_the_state & Deletion) {
3424 boost::shared_ptr<Playlist> playlist (weak_playlist.lock());
3431 Glib::Mutex::Lock lm (playlist_lock);
3433 PlaylistList::iterator i;
3435 i = find (playlists.begin(), playlists.end(), playlist);
3436 if (i != playlists.end()) {
3437 playlists.erase (i);
3440 i = find (unused_playlists.begin(), unused_playlists.end(), playlist);
3441 if (i != unused_playlists.end()) {
3442 unused_playlists.erase (i);
3449 PlaylistRemoved (playlist); /* EMIT SIGNAL */
3453 Session::set_audition (boost::shared_ptr<Region> r)
3455 pending_audition_region = r;
3456 post_transport_work = PostTransportWork (post_transport_work | PostTransportAudition);
3457 schedule_butler_transport_work ();
3461 Session::audition_playlist ()
3463 Event* ev = new Event (Event::Audition, Event::Add, Event::Immediate, 0, 0.0);
3464 ev->region.reset ();
3469 Session::non_realtime_set_audition ()
3471 if (!pending_audition_region) {
3472 auditioner->audition_current_playlist ();
3474 auditioner->audition_region (pending_audition_region);
3475 pending_audition_region.reset ();
3477 AuditionActive (true); /* EMIT SIGNAL */
3481 Session::audition_region (boost::shared_ptr<Region> r)
3483 Event* ev = new Event (Event::Audition, Event::Add, Event::Immediate, 0, 0.0);
3489 Session::cancel_audition ()
3491 if (auditioner->active()) {
3492 auditioner->cancel_audition ();
3493 AuditionActive (false); /* EMIT SIGNAL */
3498 Session::RoutePublicOrderSorter::operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b)
3500 return a->order_key(N_("signal")) < b->order_key(N_("signal"));
3504 Session::remove_empty_sounds ()
3506 PathScanner scanner;
3508 vector<string *>* possible_audiofiles = scanner (sound_dir(), "\\.(wav|aiff|caf|w64|L|R)$", false, true);
3510 Glib::Mutex::Lock lm (audio_source_lock);
3512 regex_t compiled_tape_track_pattern;
3515 if ((err = regcomp (&compiled_tape_track_pattern, "/T[0-9][0-9][0-9][0-9]-", REG_EXTENDED|REG_NOSUB))) {
3519 regerror (err, &compiled_tape_track_pattern, msg, sizeof (msg));
3521 error << string_compose (_("Cannot compile tape track regexp for use (%1)"), msg) << endmsg;
3525 for (vector<string *>::iterator i = possible_audiofiles->begin(); i != possible_audiofiles->end(); ++i) {
3527 /* never remove files that appear to be a tape track */
3529 if (regexec (&compiled_tape_track_pattern, (*i)->c_str(), 0, 0, 0) == 0) {
3534 if (AudioFileSource::is_empty (*this, **i)) {
3536 unlink ((*i)->c_str());
3538 Glib::ustring peakpath = peak_path (PBD::basename_nosuffix (**i));
3539 unlink (peakpath.c_str());
3545 delete possible_audiofiles;
3549 Session::is_auditioning () const
3551 /* can be called before we have an auditioner object */
3553 return auditioner->active();
3560 Session::set_all_solo (bool yn)
3562 shared_ptr<RouteList> r = routes.reader ();
3564 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
3565 if (!(*i)->hidden()) {
3566 (*i)->set_solo (yn, this);
3574 Session::set_all_mute (bool yn)
3576 shared_ptr<RouteList> r = routes.reader ();
3578 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
3579 if (!(*i)->hidden()) {
3580 (*i)->set_mute (yn, this);
3588 Session::n_diskstreams () const
3592 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
3594 for (DiskstreamList::const_iterator i = dsl->begin(); i != dsl->end(); ++i) {
3595 if (!(*i)->hidden()) {
3603 Session::graph_reordered ()
3605 /* don't do this stuff if we are setting up connections
3606 from a set_state() call or creating new tracks.
3609 if (_state_of_the_state & InitialConnecting) {
3613 /* every track/bus asked for this to be handled but it was deferred because
3614 we were connecting. do it now.
3617 request_input_change_handling ();
3621 /* force all diskstreams to update their capture offset values to
3622 reflect any changes in latencies within the graph.
3625 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
3627 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
3628 (*i)->set_capture_offset ();
3633 Session::record_disenable_all ()
3635 record_enable_change_all (false);
3639 Session::record_enable_all ()
3641 record_enable_change_all (true);
3645 Session::record_enable_change_all (bool yn)
3647 shared_ptr<RouteList> r = routes.reader ();
3649 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
3652 if ((at = dynamic_cast<AudioTrack*>((*i).get())) != 0) {
3653 at->set_record_enable (yn, this);
3657 /* since we don't keep rec-enable state, don't mark session dirty */
3661 Session::add_redirect (Redirect* redirect)
3665 PortInsert* port_insert;
3666 PluginInsert* plugin_insert;
3668 if ((insert = dynamic_cast<Insert *> (redirect)) != 0) {
3669 if ((port_insert = dynamic_cast<PortInsert *> (insert)) != 0) {
3670 _port_inserts.insert (_port_inserts.begin(), port_insert);
3671 } else if ((plugin_insert = dynamic_cast<PluginInsert *> (insert)) != 0) {
3672 _plugin_inserts.insert (_plugin_inserts.begin(), plugin_insert);
3674 fatal << _("programming error: unknown type of Insert created!") << endmsg;
3677 } else if ((send = dynamic_cast<Send *> (redirect)) != 0) {
3678 _sends.insert (_sends.begin(), send);
3680 fatal << _("programming error: unknown type of Redirect created!") << endmsg;
3684 redirect->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_redirect), redirect));
3690 Session::remove_redirect (Redirect* redirect)
3694 PortInsert* port_insert;
3695 PluginInsert* plugin_insert;
3697 if ((insert = dynamic_cast<Insert *> (redirect)) != 0) {
3698 if ((port_insert = dynamic_cast<PortInsert *> (insert)) != 0) {
3699 list<PortInsert*>::iterator x = find (_port_inserts.begin(), _port_inserts.end(), port_insert);
3700 if (x != _port_inserts.end()) {
3701 insert_bitset[port_insert->bit_slot()] = false;
3702 _port_inserts.erase (x);
3704 } else if ((plugin_insert = dynamic_cast<PluginInsert *> (insert)) != 0) {
3705 _plugin_inserts.remove (plugin_insert);
3707 fatal << string_compose (_("programming error: %1"),
3708 X_("unknown type of Insert deleted!"))
3712 } else if ((send = dynamic_cast<Send *> (redirect)) != 0) {
3713 list<Send*>::iterator x = find (_sends.begin(), _sends.end(), send);
3714 if (x != _sends.end()) {
3715 send_bitset[send->bit_slot()] = false;
3719 fatal << _("programming error: unknown type of Redirect deleted!") << endmsg;
3727 Session::available_capture_duration ()
3729 float sample_bytes_on_disk = 4.0; // keep gcc happy
3731 switch (Config->get_native_file_data_format()) {
3733 sample_bytes_on_disk = 4.0;
3737 sample_bytes_on_disk = 3.0;
3741 sample_bytes_on_disk = 2.0;
3745 /* impossible, but keep some gcc versions happy */
3746 fatal << string_compose (_("programming error: %1"),
3747 X_("illegal native file data format"))
3752 double scale = 4096.0 / sample_bytes_on_disk;
3754 if (_total_free_4k_blocks * scale > (double) max_frames) {
3758 return (nframes_t) floor (_total_free_4k_blocks * scale);
3762 Session::add_connection (ARDOUR::Connection* connection)
3765 Glib::Mutex::Lock guard (connection_lock);
3766 _connections.push_back (connection);
3769 ConnectionAdded (connection); /* EMIT SIGNAL */
3775 Session::remove_connection (ARDOUR::Connection* connection)
3777 bool removed = false;
3780 Glib::Mutex::Lock guard (connection_lock);
3781 ConnectionList::iterator i = find (_connections.begin(), _connections.end(), connection);
3783 if (i != _connections.end()) {
3784 _connections.erase (i);
3790 ConnectionRemoved (connection); /* EMIT SIGNAL */
3796 ARDOUR::Connection *
3797 Session::connection_by_name (string name) const
3799 Glib::Mutex::Lock lm (connection_lock);
3801 for (ConnectionList::const_iterator i = _connections.begin(); i != _connections.end(); ++i) {
3802 if ((*i)->name() == name) {
3811 Session::tempo_map_changed (Change ignored)
3815 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
3816 (*i)->update_after_tempo_map_change ();
3819 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
3820 (*i)->update_after_tempo_map_change ();
3827 Session::ensure_passthru_buffers (uint32_t howmany)
3829 if (current_block_size == 0) {
3833 while (howmany > _passthru_buffers.size()) {
3835 #ifdef NO_POSIX_MEMALIGN
3836 p = (Sample *) malloc(current_block_size * sizeof(Sample));
3838 if (posix_memalign((void **)&p,CPU_CACHE_ALIGN,current_block_size * sizeof(Sample)) != 0) {
3839 fatal << string_compose (_("Memory allocation error: posix_memalign (%1 * %2) failed (%3)"),
3840 current_block_size, sizeof (Sample), strerror (errno))
3845 _passthru_buffers.push_back (p);
3849 #ifdef NO_POSIX_MEMALIGN
3850 p = (Sample *) malloc(current_block_size * sizeof(Sample));
3852 if (posix_memalign((void **)&p,CPU_CACHE_ALIGN,current_block_size * sizeof(Sample)) != 0) {
3853 fatal << string_compose (_("Memory allocation error: posix_memalign (%1 * %2) failed (%3)"),
3854 current_block_size, sizeof (Sample), strerror (errno))
3859 memset (p, 0, sizeof (Sample) * current_block_size);
3860 _silent_buffers.push_back (p);
3864 #ifdef NO_POSIX_MEMALIGN
3865 p = (Sample *) malloc(current_block_size * sizeof(Sample));
3867 posix_memalign((void **)&p,CPU_CACHE_ALIGN,current_block_size * sizeof(Sample));
3869 memset (p, 0, sizeof (Sample) * current_block_size);
3870 _send_buffers.push_back (p);
3873 allocate_pan_automation_buffers (current_block_size, howmany, false);
3877 Session::next_insert_id ()
3879 /* this doesn't really loop forever. just think about it */
3882 for (boost::dynamic_bitset<uint32_t>::size_type n = 0; n < insert_bitset.size(); ++n) {
3883 if (!insert_bitset[n]) {
3884 insert_bitset[n] = true;
3890 /* none available, so resize and try again */
3892 insert_bitset.resize (insert_bitset.size() + 16, false);
3897 Session::next_send_id ()
3899 /* this doesn't really loop forever. just think about it */
3902 for (boost::dynamic_bitset<uint32_t>::size_type n = 0; n < send_bitset.size(); ++n) {
3903 if (!send_bitset[n]) {
3904 send_bitset[n] = true;
3910 /* none available, so resize and try again */
3912 send_bitset.resize (send_bitset.size() + 16, false);
3917 Session::mark_send_id (uint32_t id)
3919 if (id >= send_bitset.size()) {
3920 send_bitset.resize (id+16, false);
3922 if (send_bitset[id]) {
3923 warning << string_compose (_("send ID %1 appears to be in use already"), id) << endmsg;
3925 send_bitset[id] = true;
3929 Session::mark_insert_id (uint32_t id)
3931 if (id >= insert_bitset.size()) {
3932 insert_bitset.resize (id+16, false);
3934 if (insert_bitset[id]) {
3935 warning << string_compose (_("insert ID %1 appears to be in use already"), id) << endmsg;
3937 insert_bitset[id] = true;
3940 /* Named Selection management */
3943 Session::named_selection_by_name (string name)
3945 Glib::Mutex::Lock lm (named_selection_lock);
3946 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
3947 if ((*i)->name == name) {
3955 Session::add_named_selection (NamedSelection* named_selection)
3958 Glib::Mutex::Lock lm (named_selection_lock);
3959 named_selections.insert (named_selections.begin(), named_selection);
3962 for (list<boost::shared_ptr<Playlist> >::iterator i = named_selection->playlists.begin(); i != named_selection->playlists.end(); ++i) {
3968 NamedSelectionAdded (); /* EMIT SIGNAL */
3972 Session::remove_named_selection (NamedSelection* named_selection)
3974 bool removed = false;
3977 Glib::Mutex::Lock lm (named_selection_lock);
3979 NamedSelectionList::iterator i = find (named_selections.begin(), named_selections.end(), named_selection);
3981 if (i != named_selections.end()) {
3983 named_selections.erase (i);
3990 NamedSelectionRemoved (); /* EMIT SIGNAL */
3995 Session::reset_native_file_format ()
3997 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
3999 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
4000 (*i)->reset_write_sources (false);
4005 Session::route_name_unique (string n) const
4007 shared_ptr<RouteList> r = routes.reader ();
4009 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
4010 if ((*i)->name() == n) {
4019 Session::n_playlists () const
4021 Glib::Mutex::Lock lm (playlist_lock);
4022 return playlists.size();
4026 Session::allocate_pan_automation_buffers (nframes_t nframes, uint32_t howmany, bool force)
4028 if (!force && howmany <= _npan_buffers) {
4032 if (_pan_automation_buffer) {
4034 for (uint32_t i = 0; i < _npan_buffers; ++i) {
4035 delete [] _pan_automation_buffer[i];
4038 delete [] _pan_automation_buffer;
4041 _pan_automation_buffer = new pan_t*[howmany];
4043 for (uint32_t i = 0; i < howmany; ++i) {
4044 _pan_automation_buffer[i] = new pan_t[nframes];
4047 _npan_buffers = howmany;
4051 Session::freeze (InterThreadInfo& itt)
4053 shared_ptr<RouteList> r = routes.reader ();
4055 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
4059 if ((at = dynamic_cast<AudioTrack*>((*i).get())) != 0) {
4060 /* XXX this is wrong because itt.progress will keep returning to zero at the start
4070 boost::shared_ptr<Region>
4071 Session::write_one_audio_track (AudioTrack& track, nframes_t start, nframes_t end,
4072 bool overwrite, vector<boost::shared_ptr<AudioSource> >& srcs, InterThreadInfo& itt)
4074 boost::shared_ptr<Region> result;
4075 boost::shared_ptr<Playlist> playlist;
4076 boost::shared_ptr<AudioFileSource> fsource;
4078 char buf[PATH_MAX+1];
4082 nframes_t this_chunk;
4084 nframes_t len = end - start;
4085 vector<Sample*> buffers;
4088 error << string_compose (_("Cannot write a range where end <= start (e.g. %1 <= %2)"),
4089 end, start) << endmsg;
4093 // any bigger than this seems to cause stack overflows in called functions
4094 const nframes_t chunk_size = (128 * 1024)/4;
4096 g_atomic_int_set (&processing_prohibited, 1);
4098 /* call tree *MUST* hold route_lock */
4100 if ((playlist = track.diskstream()->playlist()) == 0) {
4104 /* external redirects will be a problem */
4106 if (track.has_external_redirects()) {
4110 nchans = track.audio_diskstream()->n_channels();
4112 dir = discover_best_sound_dir ();
4114 for (uint32_t chan_n=0; chan_n < nchans; ++chan_n) {
4116 for (x = 0; x < 99999; ++x) {
4117 snprintf (buf, sizeof(buf), "%s/%s-%d-bounce-%" PRIu32 ".wav", dir.c_str(), playlist->name().c_str(), chan_n, x+1);
4118 if (access (buf, F_OK) != 0) {
4124 error << string_compose (_("too many bounced versions of playlist \"%1\""), playlist->name()) << endmsg;
4129 fsource = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (*this, buf, false, frame_rate()));
4132 catch (failed_constructor& err) {
4133 error << string_compose (_("cannot create new audio file \"%1\" for %2"), buf, track.name()) << endmsg;
4137 srcs.push_back (fsource);
4140 /* XXX need to flush all redirects */
4145 /* create a set of reasonably-sized buffers */
4147 for (vector<Sample*>::iterator i = _passthru_buffers.begin(); i != _passthru_buffers.end(); ++i) {
4149 #ifdef NO_POSIX_MEMALIGN
4150 b = (Sample *) malloc(chunk_size * sizeof(Sample));
4152 posix_memalign((void **)&b,4096,chunk_size * sizeof(Sample));
4154 buffers.push_back (b);
4157 for (vector<boost::shared_ptr<AudioSource> >::iterator src=srcs.begin(); src != srcs.end(); ++src) {
4158 (*src)->prepare_for_peakfile_writes ();
4161 while (to_do && !itt.cancel) {
4163 this_chunk = min (to_do, chunk_size);
4165 if (track.export_stuff (buffers, nchans, start, this_chunk)) {
4170 for (vector<boost::shared_ptr<AudioSource> >::iterator src=srcs.begin(); src != srcs.end(); ++src, ++n) {
4171 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
4174 if (afs->write (buffers[n], this_chunk) != this_chunk) {
4180 start += this_chunk;
4181 to_do -= this_chunk;
4183 itt.progress = (float) (1.0 - ((double) to_do / len));
4192 xnow = localtime (&now);
4194 for (vector<boost::shared_ptr<AudioSource> >::iterator src=srcs.begin(); src != srcs.end(); ++src) {
4195 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
4198 afs->update_header (position, *xnow, now);
4199 afs->flush_header ();
4203 /* construct a region to represent the bounced material */
4205 result = RegionFactory::create (srcs, 0, srcs.front()->length(),
4206 region_name_from_path (srcs.front()->name(), true));
4211 for (vector<boost::shared_ptr<AudioSource> >::iterator src = srcs.begin(); src != srcs.end(); ++src) {
4212 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
4215 afs->mark_for_remove ();
4218 (*src)->drop_references ();
4222 for (vector<boost::shared_ptr<AudioSource> >::iterator src = srcs.begin(); src != srcs.end(); ++src) {
4223 (*src)->done_with_peakfile_writes ();
4227 for (vector<Sample*>::iterator i = buffers.begin(); i != buffers.end(); ++i) {
4231 g_atomic_int_set (&processing_prohibited, 0);
4239 Session::get_silent_buffers (uint32_t howmany)
4241 if (howmany > _silent_buffers.size()) {
4243 error << string_compose (_("Programming error: get_silent_buffers() called for %1 buffers but only %2 exist"),
4244 howmany, _silent_buffers.size()) << endmsg;
4246 if (howmany > 1000) {
4247 cerr << "ABSURD: more than 1000 silent buffers requested!\n";
4251 while (howmany > _silent_buffers.size()) {
4254 #ifdef NO_POSIX_MEMALIGN
4255 p = (Sample *) malloc(current_block_size * sizeof(Sample));
4257 if (posix_memalign((void **)&p,CPU_CACHE_ALIGN,current_block_size * sizeof(Sample)) != 0) {
4258 fatal << string_compose (_("Memory allocation error: posix_memalign (%1 * %2) failed (%3)"),
4259 current_block_size, sizeof (Sample), strerror (errno))
4264 _silent_buffers.push_back (p);
4268 for (uint32_t i = 0; i < howmany; ++i) {
4269 memset (_silent_buffers[i], 0, sizeof (Sample) * current_block_size);
4272 return _silent_buffers;
4276 Session::ntracks () const
4279 shared_ptr<RouteList> r = routes.reader ();
4281 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
4282 if (dynamic_cast<AudioTrack*> ((*i).get())) {
4291 Session::nbusses () const
4294 shared_ptr<RouteList> r = routes.reader ();
4296 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
4297 if (dynamic_cast<AudioTrack*> ((*i).get()) == 0) {
4306 Session::add_automation_list(AutomationList *al)
4308 automation_lists[al->id()] = al;
4312 Session::compute_initial_length ()
4314 return _engine.frame_rate() * 60 * 5;
4318 Session::sync_order_keys (const char* base)
4320 if (!Config->get_sync_all_route_ordering()) {
4321 /* leave order keys as they are */
4325 boost::shared_ptr<RouteList> r = routes.reader ();
4327 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
4328 (*i)->sync_order_keys (base);
4331 Route::SyncOrderKeys (base); // EMIT SIGNAL