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 */
31 #include <sigc++/bind.h>
32 #include <sigc++/retype.h>
34 #include <glibmm/thread.h>
35 #include <glibmm/miscutils.h>
36 #include <glibmm/fileutils.h>
38 #include <pbd/error.h>
39 #include <glibmm/thread.h>
40 #include <pbd/pathscanner.h>
41 #include <pbd/stl_delete.h>
42 #include <pbd/basename.h>
43 #include <pbd/stacktrace.h>
44 #include <pbd/file_utils.h>
46 #include <ardour/analyser.h>
47 #include <ardour/audio_buffer.h>
48 #include <ardour/audio_diskstream.h>
49 #include <ardour/audio_track.h>
50 #include <ardour/audioengine.h>
51 #include <ardour/audiofilesource.h>
52 #include <ardour/audioplaylist.h>
53 #include <ardour/audioregion.h>
54 #include <ardour/auditioner.h>
55 #include <ardour/buffer_set.h>
56 #include <ardour/bundle.h>
57 #include <ardour/click.h>
58 #include <ardour/configuration.h>
59 #include <ardour/crossfade.h>
60 #include <ardour/cycle_timer.h>
61 #include <ardour/data_type.h>
62 #include <ardour/filename_extensions.h>
63 #include <ardour/internal_send.h>
64 #include <ardour/io_processor.h>
65 #include <ardour/midi_diskstream.h>
66 #include <ardour/midi_playlist.h>
67 #include <ardour/midi_region.h>
68 #include <ardour/midi_track.h>
69 #include <ardour/named_selection.h>
70 #include <ardour/playlist.h>
71 #include <ardour/plugin_insert.h>
72 #include <ardour/port_insert.h>
73 #include <ardour/processor.h>
74 #include <ardour/recent_sessions.h>
75 #include <ardour/region_factory.h>
76 #include <ardour/route_group.h>
77 #include <ardour/send.h>
78 #include <ardour/session.h>
79 #include <ardour/session_directory.h>
80 #include <ardour/session_directory.h>
81 #include <ardour/session_metadata.h>
82 #include <ardour/slave.h>
83 #include <ardour/smf_source.h>
84 #include <ardour/source_factory.h>
85 #include <ardour/tape_file_matcher.h>
86 #include <ardour/tempo.h>
87 #include <ardour/utils.h>
92 using namespace ARDOUR;
94 using boost::shared_ptr;
97 static const int CPU_CACHE_ALIGN = 64;
99 static const int CPU_CACHE_ALIGN = 16; /* arguably 32 on most arches, but it matters less */
102 bool Session::_disable_all_loaded_plugins = false;
104 sigc::signal<void,std::string> Session::Dialog;
105 sigc::signal<int> Session::AskAboutPendingState;
106 sigc::signal<int,nframes_t,nframes_t> Session::AskAboutSampleRateMismatch;
107 sigc::signal<void> Session::SendFeedback;
109 sigc::signal<void> Session::SMPTEOffsetChanged;
110 sigc::signal<void> Session::StartTimeChanged;
111 sigc::signal<void> Session::EndTimeChanged;
112 sigc::signal<void> Session::AutoBindingOn;
113 sigc::signal<void> Session::AutoBindingOff;
114 sigc::signal<void, std::string, std::string> Session::Exported;
116 Session::Session (AudioEngine &eng,
117 const string& fullpath,
118 const string& snapshot_name,
122 _requested_return_frame (-1),
123 _scratch_buffers(new BufferSet()),
124 _silent_buffers(new BufferSet()),
125 _mix_buffers(new BufferSet()),
127 _mmc_port (default_mmc_port),
128 _mtc_port (default_mtc_port),
129 _midi_port (default_midi_port),
130 _midi_clock_port (default_midi_clock_port),
131 _session_dir (new SessionDirectory(fullpath)),
132 pending_events (2048),
134 butler_mixdown_buffer (0),
135 butler_gain_buffer (0),
136 post_transport_work((PostTransportWork)0),
137 _send_smpte_update (false),
138 midi_thread (pthread_t (0)),
139 midi_requests (128), // the size of this should match the midi request pool size
140 diskstreams (new DiskstreamList),
141 routes (new RouteList),
142 auditioner ((Auditioner*) 0),
143 _total_free_4k_blocks (0),
144 _bundles (new BundleList),
145 _bundle_xml_node (0),
148 click_emphasis_data (0),
150 _metadata (new SessionMetadata())
155 if (!eng.connected()) {
156 throw failed_constructor();
159 cerr << "Loading session " << fullpath << " using snapshot " << snapshot_name << " (1)" << endl;
161 n_physical_outputs = _engine.n_physical_outputs(DataType::AUDIO);
162 n_physical_inputs = _engine.n_physical_inputs(DataType::AUDIO);
164 first_stage_init (fullpath, snapshot_name);
166 new_session = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
169 if (create (new_session, mix_template, compute_initial_length())) {
171 throw failed_constructor ();
175 if (second_stage_init (new_session)) {
177 throw failed_constructor ();
180 store_recent_sessions(_name, _path);
182 bool was_dirty = dirty();
184 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
186 Config->ParameterChanged.connect (mem_fun (*this, &Session::config_changed));
189 DirtyChanged (); /* EMIT SIGNAL */
193 Session::Session (AudioEngine &eng,
195 string snapshot_name,
196 AutoConnectOption input_ac,
197 AutoConnectOption output_ac,
198 uint32_t control_out_channels,
199 uint32_t master_out_channels,
200 uint32_t requested_physical_in,
201 uint32_t requested_physical_out,
202 nframes_t initial_length)
205 _requested_return_frame (-1),
206 _scratch_buffers(new BufferSet()),
207 _silent_buffers(new BufferSet()),
208 _mix_buffers(new BufferSet()),
210 _mmc_port (default_mmc_port),
211 _mtc_port (default_mtc_port),
212 _midi_port (default_midi_port),
213 _midi_clock_port (default_midi_clock_port),
214 _session_dir ( new SessionDirectory(fullpath)),
215 pending_events (2048),
217 butler_mixdown_buffer (0),
218 butler_gain_buffer (0),
219 post_transport_work((PostTransportWork)0),
220 _send_smpte_update (false),
221 midi_thread (pthread_t (0)),
223 diskstreams (new DiskstreamList),
224 routes (new RouteList),
225 auditioner ((Auditioner *) 0),
226 _total_free_4k_blocks (0),
227 _bundles (new BundleList),
228 _bundle_xml_node (0),
229 _click_io ((IO *) 0),
231 click_emphasis_data (0),
233 _metadata (new SessionMetadata())
237 if (!eng.connected()) {
238 throw failed_constructor();
241 cerr << "Loading session " << fullpath << " using snapshot " << snapshot_name << " (2)" << endl;
243 n_physical_outputs = _engine.n_physical_outputs (DataType::AUDIO);
244 n_physical_inputs = _engine.n_physical_inputs (DataType::AUDIO);
246 if (n_physical_inputs) {
247 n_physical_inputs = max (requested_physical_in, n_physical_inputs);
250 if (n_physical_outputs) {
251 n_physical_outputs = max (requested_physical_out, n_physical_outputs);
254 first_stage_init (fullpath, snapshot_name);
256 new_session = !g_file_test (_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
259 if (create (new_session, string(), initial_length)) {
261 throw failed_constructor ();
266 /* set up Master Out and Control Out if necessary */
271 if (control_out_channels) {
272 shared_ptr<Route> r (new Route (*this, _("monitor"), -1, control_out_channels, -1, control_out_channels, Route::ControlOut));
273 r->set_remote_control_id (control_id++);
278 if (master_out_channels) {
279 shared_ptr<Route> r (new Route (*this, _("master"), -1, master_out_channels, -1, master_out_channels, Route::MasterOut));
280 r->set_remote_control_id (control_id);
284 /* prohibit auto-connect to master, because there isn't one */
285 output_ac = AutoConnectOption (output_ac & ~AutoConnectMaster);
289 add_routes (rl, false);
294 Config->set_input_auto_connect (input_ac);
295 Config->set_output_auto_connect (output_ac);
297 if (second_stage_init (new_session)) {
299 throw failed_constructor ();
302 store_recent_sessions (_name, _path);
304 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
306 Config->ParameterChanged.connect (mem_fun (*this, &Session::config_changed));
317 /* if we got to here, leaving pending capture state around
321 remove_pending_capture_state ();
323 _state_of_the_state = StateOfTheState (CannotSave|Deletion);
325 _engine.remove_session ();
327 GoingAway (); /* EMIT SIGNAL */
333 /* clear history so that no references to objects are held any more */
337 /* clear state tree so that no references to objects are held any more */
341 terminate_butler_thread ();
342 //terminate_midi_thread ();
344 if (click_data != default_click) {
345 delete [] click_data;
348 if (click_emphasis_data != default_click_emphasis) {
349 delete [] click_emphasis_data;
354 delete _scratch_buffers;
355 delete _silent_buffers;
358 AudioDiskstream::free_working_buffers();
360 Route::SyncOrderKeys.clear();
362 #undef TRACK_DESTRUCTION
363 #ifdef TRACK_DESTRUCTION
364 cerr << "delete named selections\n";
365 #endif /* TRACK_DESTRUCTION */
366 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ) {
367 NamedSelectionList::iterator tmp;
376 #ifdef TRACK_DESTRUCTION
377 cerr << "delete playlists\n";
378 #endif /* TRACK_DESTRUCTION */
379 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ) {
380 PlaylistList::iterator tmp;
385 (*i)->drop_references ();
390 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ) {
391 PlaylistList::iterator tmp;
396 (*i)->drop_references ();
402 unused_playlists.clear ();
404 #ifdef TRACK_DESTRUCTION
405 cerr << "delete regions\n";
406 #endif /* TRACK_DESTRUCTION */
408 for (RegionList::iterator i = regions.begin(); i != regions.end(); ) {
409 RegionList::iterator tmp;
414 i->second->drop_references ();
421 #ifdef TRACK_DESTRUCTION
422 cerr << "delete routes\n";
423 #endif /* TRACK_DESTRUCTION */
425 RCUWriter<RouteList> writer (routes);
426 boost::shared_ptr<RouteList> r = writer.get_copy ();
427 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
428 (*i)->drop_references ();
431 /* writer goes out of scope and updates master */
436 #ifdef TRACK_DESTRUCTION
437 cerr << "delete diskstreams\n";
438 #endif /* TRACK_DESTRUCTION */
440 RCUWriter<DiskstreamList> dwriter (diskstreams);
441 boost::shared_ptr<DiskstreamList> dsl = dwriter.get_copy();
442 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
443 (*i)->drop_references ();
447 diskstreams.flush ();
449 #ifdef TRACK_DESTRUCTION
450 cerr << "delete audio sources\n";
451 #endif /* TRACK_DESTRUCTION */
452 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
453 SourceMap::iterator tmp;
458 i->second->drop_references ();
464 #ifdef TRACK_DESTRUCTION
465 cerr << "delete mix groups\n";
466 #endif /* TRACK_DESTRUCTION */
467 for (list<RouteGroup *>::iterator i = mix_groups.begin(); i != mix_groups.end(); ) {
468 list<RouteGroup*>::iterator tmp;
478 #ifdef TRACK_DESTRUCTION
479 cerr << "delete edit groups\n";
480 #endif /* TRACK_DESTRUCTION */
481 for (list<RouteGroup *>::iterator i = edit_groups.begin(); i != edit_groups.end(); ) {
482 list<RouteGroup*>::iterator tmp;
492 delete [] butler_mixdown_buffer;
493 delete [] butler_gain_buffer;
495 Crossfade::set_buffer_size (0);
501 Session::set_worst_io_latencies ()
503 _worst_output_latency = 0;
504 _worst_input_latency = 0;
506 if (!_engine.connected()) {
510 boost::shared_ptr<RouteList> r = routes.reader ();
512 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
513 _worst_output_latency = max (_worst_output_latency, (*i)->output_latency());
514 _worst_input_latency = max (_worst_input_latency, (*i)->input_latency());
519 Session::when_engine_running ()
521 string first_physical_output;
523 /* we don't want to run execute this again */
525 BootMessage (_("Set block size and sample rate"));
527 set_block_size (_engine.frames_per_cycle());
528 set_frame_rate (_engine.frame_rate());
530 BootMessage (_("Using configuration"));
532 Config->map_parameters (mem_fun (*this, &Session::config_changed));
534 /* every time we reconnect, recompute worst case output latencies */
536 _engine.Running.connect (mem_fun (*this, &Session::set_worst_io_latencies));
538 if (synced_to_jack()) {
539 _engine.transport_stop ();
542 if (Config->get_jack_time_master()) {
543 _engine.transport_locate (_transport_frame);
551 _click_io.reset (new ClickIO (*this, "click", 0, 0, -1, -1));
553 if (state_tree && (child = find_named_node (*state_tree->root(), "Click")) != 0) {
555 /* existing state for Click */
557 if (_click_io->set_state (*child->children().front()) == 0) {
559 _clicking = Config->get_clicking ();
563 error << _("could not setup Click I/O") << endmsg;
569 /* default state for Click */
571 first_physical_output = _engine.get_nth_physical_output (DataType::AUDIO, 0);
573 if (first_physical_output.length()) {
574 if (_click_io->add_output_port (first_physical_output, this)) {
575 // relax, even though its an error
577 _clicking = Config->get_clicking ();
583 catch (failed_constructor& err) {
584 error << _("cannot setup Click I/O") << endmsg;
587 BootMessage (_("Compute I/O Latencies"));
589 set_worst_io_latencies ();
592 // XXX HOW TO ALERT UI TO THIS ? DO WE NEED TO?
595 BootMessage (_("Set up standard connections"));
597 /* Create a set of Bundle objects that map
598 to the physical I/O currently available */
600 for (uint32_t np = 0; np < n_physical_outputs; ++np) {
602 snprintf (buf, sizeof (buf), _("out %" PRIu32), np+1);
604 shared_ptr<Bundle> c (new Bundle (buf, true));
605 c->add_channel (_("mono"));
606 c->set_port (0, _engine.get_nth_physical_output (DataType::AUDIO, np));
611 for (uint32_t np = 0; np < n_physical_inputs; ++np) {
613 snprintf (buf, sizeof (buf), _("in %" PRIu32), np+1);
615 shared_ptr<Bundle> c (new Bundle (buf, false));
616 c->add_channel (_("mono"));
617 c->set_port (0, _engine.get_nth_physical_input (DataType::AUDIO, np));
624 /* create master/control ports */
629 /* force the master to ignore any later call to this */
631 if (_master_out->pending_state_node) {
632 _master_out->ports_became_legal();
635 /* no panner resets till we are through */
637 _master_out->defer_pan_reset ();
639 while (_master_out->n_inputs().n_audio()
640 < _master_out->input_maximum().n_audio()) {
641 if (_master_out->add_input_port ("", this, DataType::AUDIO)) {
642 error << _("cannot setup master inputs")
648 while (_master_out->n_outputs().n_audio()
649 < _master_out->output_maximum().n_audio()) {
650 if (_master_out->add_output_port (_engine.get_nth_physical_output (DataType::AUDIO, n), this, DataType::AUDIO)) {
651 error << _("cannot setup master outputs")
658 _master_out->allow_pan_reset ();
663 BootMessage (_("Setup signal flow and plugins"));
667 /* catch up on send+insert cnts */
669 BootMessage (_("Catch up with send/insert state"));
673 for (list<PortInsert*>::iterator i = _port_inserts.begin(); i != _port_inserts.end(); ++i) {
676 if (sscanf ((*i)->name().c_str(), "%*s %u", &id) == 1) {
677 if (id > insert_cnt) {
685 for (list<Send*>::iterator i = _sends.begin(); i != _sends.end(); ++i) {
688 if (sscanf ((*i)->name().c_str(), "%*s %u", &id) == 1) {
696 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
698 /* hook us up to the engine */
700 BootMessage (_("Connect to engine"));
702 _engine.set_session (this);
706 Session::hookup_io ()
708 /* stop graph reordering notifications from
709 causing resorts, etc.
712 _state_of_the_state = StateOfTheState (_state_of_the_state | InitialConnecting);
715 if (auditioner == 0) {
717 /* we delay creating the auditioner till now because
718 it makes its own connections to ports.
719 the engine has to be running for this to work.
723 auditioner.reset (new Auditioner (*this));
726 catch (failed_constructor& err) {
727 warning << _("cannot create Auditioner: no auditioning of regions possible") << endmsg;
731 /* Tell all IO objects to create their ports */
737 vector<string> cports;
739 while (_control_out->n_inputs().n_audio() < _control_out->input_maximum().n_audio()) {
740 if (_control_out->add_input_port ("", this)) {
741 error << _("cannot setup control inputs")
747 while (_control_out->n_outputs().n_audio() < _control_out->output_maximum().n_audio()) {
748 if (_control_out->add_output_port (_engine.get_nth_physical_output (DataType::AUDIO, n), this)) {
749 error << _("cannot set up master outputs")
757 uint32_t ni = _control_out->n_inputs().get (DataType::AUDIO);
759 for (n = 0; n < ni; ++n) {
760 cports.push_back (_control_out->input(n)->name());
763 boost::shared_ptr<RouteList> r = routes.reader ();
765 for (RouteList::iterator x = r->begin(); x != r->end(); ++x) {
766 (*x)->set_control_outs (cports);
770 /* load bundles, which we may have postponed earlier on */
771 if (_bundle_xml_node) {
772 load_bundles (*_bundle_xml_node);
773 delete _bundle_xml_node;
776 /* Tell all IO objects to connect themselves together */
778 IO::enable_connecting ();
780 /* Now reset all panners */
782 IO::reset_panners ();
784 /* Anyone who cares about input state, wake up and do something */
786 IOConnectionsComplete (); /* EMIT SIGNAL */
788 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InitialConnecting);
791 /* now handle the whole enchilada as if it was one
797 /* update mixer solo state */
803 Session::playlist_length_changed ()
805 /* we can't just increase end_location->end() if pl->get_maximum_extent()
806 if larger. if the playlist used to be the longest playlist,
807 and its now shorter, we have to decrease end_location->end(). hence,
808 we have to iterate over all diskstreams and check the
809 playlists currently in use.
815 Session::diskstream_playlist_changed (boost::shared_ptr<Diskstream> dstream)
817 boost::shared_ptr<Playlist> playlist;
819 if ((playlist = dstream->playlist()) != 0) {
820 playlist->LengthChanged.connect (mem_fun (this, &Session::playlist_length_changed));
823 /* see comment in playlist_length_changed () */
828 Session::record_enabling_legal () const
830 /* this used to be in here, but survey says.... we don't need to restrict it */
831 // if (record_status() == Recording) {
835 if (Config->get_all_safe()) {
842 Session::reset_input_monitor_state ()
844 if (transport_rolling()) {
846 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
848 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
849 if ((*i)->record_enabled ()) {
850 //cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
851 (*i)->monitor_input (Config->get_monitoring_model() == HardwareMonitoring && !Config->get_auto_input());
855 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
857 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
858 if ((*i)->record_enabled ()) {
859 //cerr << "switching to input = " << !Config->get_auto_input() << __FILE__ << __LINE__ << endl << endl;
860 (*i)->monitor_input (Config->get_monitoring_model() == HardwareMonitoring);
867 Session::auto_punch_start_changed (Location* location)
869 replace_event (Event::PunchIn, location->start());
871 if (get_record_enabled() && Config->get_punch_in()) {
872 /* capture start has been changed, so save new pending state */
873 save_state ("", true);
878 Session::auto_punch_end_changed (Location* location)
880 nframes_t when_to_stop = location->end();
881 // when_to_stop += _worst_output_latency + _worst_input_latency;
882 replace_event (Event::PunchOut, when_to_stop);
886 Session::auto_punch_changed (Location* location)
888 nframes_t when_to_stop = location->end();
890 replace_event (Event::PunchIn, location->start());
891 //when_to_stop += _worst_output_latency + _worst_input_latency;
892 replace_event (Event::PunchOut, when_to_stop);
896 Session::auto_loop_changed (Location* location)
898 replace_event (Event::AutoLoop, location->end(), location->start());
900 if (transport_rolling() && play_loop) {
902 //if (_transport_frame < location->start() || _transport_frame > location->end()) {
904 if (_transport_frame > location->end()) {
905 // relocate to beginning of loop
906 clear_events (Event::LocateRoll);
908 request_locate (location->start(), true);
911 else if (Config->get_seamless_loop() && !loop_changing) {
913 // schedule a locate-roll to refill the diskstreams at the
915 loop_changing = true;
917 if (location->end() > last_loopend) {
918 clear_events (Event::LocateRoll);
919 Event *ev = new Event (Event::LocateRoll, Event::Add, last_loopend, last_loopend, 0, true);
926 last_loopend = location->end();
930 Session::set_auto_punch_location (Location* location)
934 if ((existing = _locations.auto_punch_location()) != 0 && existing != location) {
935 auto_punch_start_changed_connection.disconnect();
936 auto_punch_end_changed_connection.disconnect();
937 auto_punch_changed_connection.disconnect();
938 existing->set_auto_punch (false, this);
939 remove_event (existing->start(), Event::PunchIn);
940 clear_events (Event::PunchOut);
941 auto_punch_location_changed (0);
950 if (location->end() <= location->start()) {
951 error << _("Session: you can't use that location for auto punch (start <= end)") << endmsg;
955 auto_punch_start_changed_connection.disconnect();
956 auto_punch_end_changed_connection.disconnect();
957 auto_punch_changed_connection.disconnect();
959 auto_punch_start_changed_connection = location->start_changed.connect (mem_fun (this, &Session::auto_punch_start_changed));
960 auto_punch_end_changed_connection = location->end_changed.connect (mem_fun (this, &Session::auto_punch_end_changed));
961 auto_punch_changed_connection = location->changed.connect (mem_fun (this, &Session::auto_punch_changed));
963 location->set_auto_punch (true, this);
966 auto_punch_changed (location);
968 auto_punch_location_changed (location);
972 Session::set_auto_loop_location (Location* location)
976 if ((existing = _locations.auto_loop_location()) != 0 && existing != location) {
977 auto_loop_start_changed_connection.disconnect();
978 auto_loop_end_changed_connection.disconnect();
979 auto_loop_changed_connection.disconnect();
980 existing->set_auto_loop (false, this);
981 remove_event (existing->end(), Event::AutoLoop);
982 auto_loop_location_changed (0);
991 if (location->end() <= location->start()) {
992 error << _("Session: you can't use a mark for auto loop") << endmsg;
996 last_loopend = location->end();
998 auto_loop_start_changed_connection.disconnect();
999 auto_loop_end_changed_connection.disconnect();
1000 auto_loop_changed_connection.disconnect();
1002 auto_loop_start_changed_connection = location->start_changed.connect (mem_fun (this, &Session::auto_loop_changed));
1003 auto_loop_end_changed_connection = location->end_changed.connect (mem_fun (this, &Session::auto_loop_changed));
1004 auto_loop_changed_connection = location->changed.connect (mem_fun (this, &Session::auto_loop_changed));
1006 location->set_auto_loop (true, this);
1008 /* take care of our stuff first */
1010 auto_loop_changed (location);
1012 /* now tell everyone else */
1014 auto_loop_location_changed (location);
1018 Session::locations_added (Location* ignored)
1024 Session::locations_changed ()
1026 _locations.apply (*this, &Session::handle_locations_changed);
1030 Session::handle_locations_changed (Locations::LocationList& locations)
1032 Locations::LocationList::iterator i;
1034 bool set_loop = false;
1035 bool set_punch = false;
1037 for (i = locations.begin(); i != locations.end(); ++i) {
1041 if (location->is_auto_punch()) {
1042 set_auto_punch_location (location);
1045 if (location->is_auto_loop()) {
1046 set_auto_loop_location (location);
1050 if (location->is_start()) {
1051 start_location = location;
1053 if (location->is_end()) {
1054 end_location = location;
1059 set_auto_loop_location (0);
1062 set_auto_punch_location (0);
1069 Session::enable_record ()
1071 /* XXX really atomic compare+swap here */
1072 if (g_atomic_int_get (&_record_status) != Recording) {
1073 g_atomic_int_set (&_record_status, Recording);
1074 _last_record_location = _transport_frame;
1075 deliver_mmc(MIDI::MachineControl::cmdRecordStrobe, _last_record_location);
1077 if (Config->get_monitoring_model() == HardwareMonitoring && Config->get_auto_input()) {
1078 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1079 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1080 if ((*i)->record_enabled ()) {
1081 (*i)->monitor_input (true);
1086 RecordStateChanged ();
1091 Session::disable_record (bool rt_context, bool force)
1095 if ((rs = (RecordState) g_atomic_int_get (&_record_status)) != Disabled) {
1097 if ((!Config->get_latched_record_enable () && !play_loop) || force) {
1098 g_atomic_int_set (&_record_status, Disabled);
1100 if (rs == Recording) {
1101 g_atomic_int_set (&_record_status, Enabled);
1105 // FIXME: timestamp correct? [DR]
1106 // FIXME FIXME FIXME: rt_context? this must be called in the process thread.
1107 // does this /need/ to be sent in all cases?
1109 deliver_mmc (MIDI::MachineControl::cmdRecordExit, _transport_frame);
1111 if (Config->get_monitoring_model() == HardwareMonitoring && Config->get_auto_input()) {
1112 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1114 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1115 if ((*i)->record_enabled ()) {
1116 (*i)->monitor_input (false);
1121 RecordStateChanged (); /* emit signal */
1124 remove_pending_capture_state ();
1130 Session::step_back_from_record ()
1132 /* XXX really atomic compare+swap here */
1133 if (g_atomic_int_get (&_record_status) == Recording) {
1134 g_atomic_int_set (&_record_status, Enabled);
1136 if (Config->get_monitoring_model() == HardwareMonitoring && Config->get_auto_input()) {
1137 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1139 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1140 if ((*i)->record_enabled ()) {
1141 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
1142 (*i)->monitor_input (false);
1150 Session::maybe_enable_record ()
1152 g_atomic_int_set (&_record_status, Enabled);
1154 /* this function is currently called from somewhere other than an RT thread.
1155 this save_state() call therefore doesn't impact anything.
1158 save_state ("", true);
1160 if (_transport_speed) {
1161 if (!Config->get_punch_in()) {
1165 deliver_mmc (MIDI::MachineControl::cmdRecordPause, _transport_frame);
1166 RecordStateChanged (); /* EMIT SIGNAL */
1173 Session::audible_frame () const
1179 if (_transport_speed == 0.0f && non_realtime_work_pending()) {
1180 return last_stop_frame;
1183 /* the first of these two possible settings for "offset"
1184 mean that the audible frame is stationary until
1185 audio emerges from the latency compensation
1188 the second means that the audible frame is stationary
1189 until audio would emerge from a physical port
1190 in the absence of any plugin latency compensation
1193 offset = _worst_output_latency;
1195 if (offset > current_block_size) {
1196 offset -= current_block_size;
1198 /* XXX is this correct? if we have no external
1199 physical connections and everything is internal
1200 then surely this is zero? still, how
1201 likely is that anyway?
1203 offset = current_block_size;
1206 if (synced_to_jack()) {
1207 tf = _engine.transport_frame();
1209 tf = _transport_frame;
1214 if (!non_realtime_work_pending()) {
1218 /* check to see if we have passed the first guaranteed
1219 audible frame past our last start position. if not,
1220 return that last start point because in terms
1221 of audible frames, we have not moved yet.
1224 if (_transport_speed > 0.0f) {
1226 if (!play_loop || !have_looped) {
1227 if (tf < _last_roll_location + offset) {
1228 return _last_roll_location;
1237 } else if (_transport_speed < 0.0f) {
1239 /* XXX wot? no backward looping? */
1241 if (tf > _last_roll_location - offset) {
1242 return _last_roll_location;
1254 Session::set_frame_rate (nframes_t frames_per_second)
1256 /** \fn void Session::set_frame_size(nframes_t)
1257 the AudioEngine object that calls this guarantees
1258 that it will not be called while we are also in
1259 ::process(). Its fine to do things that block
1263 _base_frame_rate = frames_per_second;
1267 Automatable::set_automation_interval ((jack_nframes_t) ceil ((double) frames_per_second * (0.001 * Config->get_automation_interval())));
1271 // XXX we need some equivalent to this, somehow
1272 // SndFileSource::setup_standard_crossfades (frames_per_second);
1276 /* XXX need to reset/reinstantiate all LADSPA plugins */
1280 Session::set_block_size (nframes_t nframes)
1282 /* the AudioEngine guarantees
1283 that it will not be called while we are also in
1284 ::process(). It is therefore fine to do things that block
1290 current_block_size = nframes;
1292 ensure_buffers(_scratch_buffers->available());
1294 delete [] _gain_automation_buffer;
1295 _gain_automation_buffer = new gain_t[nframes];
1297 allocate_pan_automation_buffers (nframes, _npan_buffers, true);
1299 boost::shared_ptr<RouteList> r = routes.reader ();
1301 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1302 (*i)->set_block_size (nframes);
1305 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1306 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1307 (*i)->set_block_size (nframes);
1310 set_worst_io_latencies ();
1315 Session::set_default_fade (float steepness, float fade_msecs)
1318 nframes_t fade_frames;
1320 /* Don't allow fade of less 1 frame */
1322 if (fade_msecs < (1000.0 * (1.0/_current_frame_rate))) {
1329 fade_frames = (nframes_t) floor (fade_msecs * _current_frame_rate * 0.001);
1333 default_fade_msecs = fade_msecs;
1334 default_fade_steepness = steepness;
1337 // jlc, WTF is this!
1338 Glib::RWLock::ReaderLock lm (route_lock);
1339 AudioRegion::set_default_fade (steepness, fade_frames);
1344 /* XXX have to do this at some point */
1345 /* foreach region using default fade, reset, then
1346 refill_all_diskstream_buffers ();
1351 struct RouteSorter {
1352 bool operator() (boost::shared_ptr<Route> r1, boost::shared_ptr<Route> r2) {
1353 if (r1->fed_by.find (r2) != r1->fed_by.end()) {
1355 } else if (r2->fed_by.find (r1) != r2->fed_by.end()) {
1358 if (r1->fed_by.empty()) {
1359 if (r2->fed_by.empty()) {
1360 /* no ardour-based connections inbound to either route. just use signal order */
1361 return r1->order_key(N_("signal")) < r2->order_key(N_("signal"));
1363 /* r2 has connections, r1 does not; run r1 early */
1367 return r1->order_key(N_("signal")) < r2->order_key(N_("signal"));
1374 trace_terminal (shared_ptr<Route> r1, shared_ptr<Route> rbase)
1376 shared_ptr<Route> r2;
1378 if ((r1->fed_by.find (rbase) != r1->fed_by.end()) && (rbase->fed_by.find (r1) != rbase->fed_by.end())) {
1379 info << string_compose(_("feedback loop setup between %1 and %2"), r1->name(), rbase->name()) << endmsg;
1383 /* make a copy of the existing list of routes that feed r1 */
1385 set<shared_ptr<Route> > existing = r1->fed_by;
1387 /* for each route that feeds r1, recurse, marking it as feeding
1391 for (set<shared_ptr<Route> >::iterator i = existing.begin(); i != existing.end(); ++i) {
1394 /* r2 is a route that feeds r1 which somehow feeds base. mark
1395 base as being fed by r2
1398 rbase->fed_by.insert (r2);
1402 /* 2nd level feedback loop detection. if r1 feeds or is fed by r2,
1406 if ((r1->fed_by.find (r2) != r1->fed_by.end()) && (r2->fed_by.find (r1) != r2->fed_by.end())) {
1410 /* now recurse, so that we can mark base as being fed by
1411 all routes that feed r2
1414 trace_terminal (r2, rbase);
1421 Session::resort_routes ()
1423 /* don't do anything here with signals emitted
1424 by Routes while we are being destroyed.
1427 if (_state_of_the_state & Deletion) {
1434 RCUWriter<RouteList> writer (routes);
1435 shared_ptr<RouteList> r = writer.get_copy ();
1436 resort_routes_using (r);
1437 /* writer goes out of scope and forces update */
1442 Session::resort_routes_using (shared_ptr<RouteList> r)
1444 RouteList::iterator i, j;
1446 for (i = r->begin(); i != r->end(); ++i) {
1448 (*i)->fed_by.clear ();
1450 for (j = r->begin(); j != r->end(); ++j) {
1452 /* although routes can feed themselves, it will
1453 cause an endless recursive descent if we
1454 detect it. so don't bother checking for
1462 if ((*j)->feeds (*i)) {
1463 (*i)->fed_by.insert (*j);
1468 for (i = r->begin(); i != r->end(); ++i) {
1469 trace_terminal (*i, *i);
1476 cerr << "finished route resort\n";
1478 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1479 cerr << " " << (*i)->name() << " signal order = " << (*i)->order_key ("signal") << endl;
1486 list<boost::shared_ptr<MidiTrack> >
1487 Session::new_midi_track (TrackMode mode, uint32_t how_many)
1489 char track_name[32];
1490 uint32_t track_id = 0;
1493 RouteList new_routes;
1494 list<boost::shared_ptr<MidiTrack> > ret;
1495 //uint32_t control_id;
1497 // FIXME: need physical I/O and autoconnect stuff for MIDI
1499 /* count existing midi tracks */
1502 shared_ptr<RouteList> r = routes.reader ();
1504 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1505 if (dynamic_cast<MidiTrack*>((*i).get()) != 0) {
1506 if (!(*i)->is_hidden()) {
1508 //channels_used += (*i)->n_inputs().n_midi();
1514 vector<string> physinputs;
1515 vector<string> physoutputs;
1517 _engine.get_physical_outputs (DataType::MIDI, physoutputs);
1518 _engine.get_physical_inputs (DataType::MIDI, physinputs);
1520 // control_id = ntracks() + nbusses();
1524 /* check for duplicate route names, since we might have pre-existing
1525 routes with this name (e.g. create Audio1, Audio2, delete Audio1,
1526 save, close,restart,add new route - first named route is now
1534 snprintf (track_name, sizeof(track_name), "Midi %" PRIu32, track_id);
1536 if (route_by_name (track_name) == 0) {
1540 } while (track_id < (UINT_MAX-1));
1542 shared_ptr<MidiTrack> track;
1545 track = boost::shared_ptr<MidiTrack>((new MidiTrack (*this, track_name, Route::Flag (0), mode)));
1547 if (track->ensure_io (ChanCount(DataType::MIDI, 1), ChanCount(DataType::AUDIO, 1), false, this)) {
1548 error << "cannot configure 1 in/1 out configuration for new midi track" << endmsg;
1554 for (uint32_t x = 0; x < track->n_inputs().n_midi() && x < nphysical_in; ++x) {
1558 if (Config->get_input_auto_connect() & AutoConnectPhysical) {
1559 port = physinputs[(channels_used+x)%nphysical_in];
1562 if (port.length() && track->connect_input (track->input (x), port, this)) {
1568 for (uint32_t x = 0; x < track->n_outputs().n_midi(); ++x) {
1572 if (nphysical_out && (Config->get_output_auto_connect() & AutoConnectPhysical)) {
1573 port = physoutputs[(channels_used+x)%nphysical_out];
1574 } else if (Config->get_output_auto_connect() & AutoConnectMaster) {
1576 port = _master_out->input (x%_master_out->n_inputs().n_midi())->name();
1580 if (port.length() && track->connect_output (track->output (x), port, this)) {
1585 channels_used += track->n_inputs ().n_midi();
1589 track->midi_diskstream()->non_realtime_input_change();
1591 track->DiskstreamChanged.connect (mem_fun (this, &Session::resort_routes));
1592 //track->set_remote_control_id (control_id);
1594 new_routes.push_back (track);
1595 ret.push_back (track);
1598 catch (failed_constructor &err) {
1599 error << _("Session: could not create new midi track.") << endmsg;
1602 /* we need to get rid of this, since the track failed to be created */
1603 /* XXX arguably, AudioTrack::AudioTrack should not do the Session::add_diskstream() */
1606 RCUWriter<DiskstreamList> writer (diskstreams);
1607 boost::shared_ptr<DiskstreamList> ds = writer.get_copy();
1608 ds->remove (track->midi_diskstream());
1615 catch (AudioEngine::PortRegistrationFailure& pfe) {
1617 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;
1620 /* we need to get rid of this, since the track failed to be created */
1621 /* XXX arguably, MidiTrack::MidiTrack should not do the Session::add_diskstream() */
1624 RCUWriter<DiskstreamList> writer (diskstreams);
1625 boost::shared_ptr<DiskstreamList> ds = writer.get_copy();
1626 ds->remove (track->midi_diskstream());
1637 if (!new_routes.empty()) {
1638 add_routes (new_routes, false);
1639 save_state (_current_snapshot_name);
1645 list<boost::shared_ptr<AudioTrack> >
1646 Session::new_audio_track (int input_channels, int output_channels, TrackMode mode, uint32_t how_many)
1648 char track_name[32];
1649 uint32_t track_id = 0;
1651 uint32_t channels_used = 0;
1653 RouteList new_routes;
1654 list<boost::shared_ptr<AudioTrack> > ret;
1655 uint32_t control_id;
1657 /* count existing audio tracks */
1660 shared_ptr<RouteList> r = routes.reader ();
1662 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1663 if (dynamic_cast<AudioTrack*>((*i).get()) != 0) {
1664 if (!(*i)->is_hidden()) {
1666 channels_used += (*i)->n_inputs().n_audio();
1672 vector<string> physinputs;
1673 vector<string> physoutputs;
1675 _engine.get_physical_outputs (DataType::AUDIO, physoutputs);
1676 _engine.get_physical_inputs (DataType::AUDIO, physinputs);
1678 control_id = ntracks() + nbusses() + 1;
1682 /* check for duplicate route names, since we might have pre-existing
1683 routes with this name (e.g. create Audio1, Audio2, delete Audio1,
1684 save, close,restart,add new route - first named route is now
1692 snprintf (track_name, sizeof(track_name), "Audio %" PRIu32, track_id);
1694 if (route_by_name (track_name) == 0) {
1698 } while (track_id < (UINT_MAX-1));
1700 shared_ptr<AudioTrack> track;
1703 track = boost::shared_ptr<AudioTrack>((new AudioTrack (*this, track_name, Route::Flag (0), mode)));
1705 if (track->ensure_io (ChanCount(DataType::AUDIO, input_channels), ChanCount(DataType::AUDIO, output_channels), false, this)) {
1706 error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
1707 input_channels, output_channels)
1712 if (!physinputs.empty()) {
1713 uint32_t nphysical_in = physinputs.size();
1715 for (uint32_t x = 0; x < track->n_inputs().n_audio() && x < nphysical_in; ++x) {
1719 if (Config->get_input_auto_connect() & AutoConnectPhysical) {
1720 port = physinputs[(channels_used+x)%nphysical_in];
1723 if (port.length() && track->connect_input (track->input (x), port, this)) {
1729 if (!physoutputs.empty()) {
1730 uint32_t nphysical_out = physoutputs.size();
1732 for (uint32_t x = 0; x < track->n_outputs().n_audio(); ++x) {
1736 if (Config->get_output_auto_connect() & AutoConnectPhysical) {
1737 port = physoutputs[(channels_used+x)%nphysical_out];
1738 } else if (Config->get_output_auto_connect() & AutoConnectMaster) {
1740 port = _master_out->input (x%_master_out->n_inputs().n_audio())->name();
1744 if (port.length() && track->connect_output (track->output (x), port, this)) {
1750 channels_used += track->n_inputs ().n_audio();
1752 track->audio_diskstream()->non_realtime_input_change();
1754 track->DiskstreamChanged.connect (mem_fun (this, &Session::resort_routes));
1755 track->set_remote_control_id (control_id);
1758 new_routes.push_back (track);
1759 ret.push_back (track);
1762 catch (failed_constructor &err) {
1763 error << _("Session: could not create new audio track.") << endmsg;
1766 /* we need to get rid of this, since the track failed to be created */
1767 /* XXX arguably, AudioTrack::AudioTrack should not do the Session::add_diskstream() */
1770 RCUWriter<DiskstreamList> writer (diskstreams);
1771 boost::shared_ptr<DiskstreamList> ds = writer.get_copy();
1772 ds->remove (track->audio_diskstream());
1779 catch (AudioEngine::PortRegistrationFailure& pfe) {
1781 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;
1784 /* we need to get rid of this, since the track failed to be created */
1785 /* XXX arguably, AudioTrack::AudioTrack should not do the Session::add_diskstream() */
1788 RCUWriter<DiskstreamList> writer (diskstreams);
1789 boost::shared_ptr<DiskstreamList> ds = writer.get_copy();
1790 ds->remove (track->audio_diskstream());
1801 if (!new_routes.empty()) {
1802 add_routes (new_routes, true);
1809 Session::set_remote_control_ids ()
1811 RemoteModel m = Config->get_remote_model();
1813 shared_ptr<RouteList> r = routes.reader ();
1815 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1816 if ( MixerOrdered == m) {
1817 long order = (*i)->order_key(N_("signal"));
1818 (*i)->set_remote_control_id( order+1 );
1819 } else if ( EditorOrdered == m) {
1820 long order = (*i)->order_key(N_("editor"));
1821 (*i)->set_remote_control_id( order+1 );
1822 } else if ( UserOrdered == m) {
1823 //do nothing ... only changes to remote id's are initiated by user
1830 Session::new_audio_route (int input_channels, int output_channels, uint32_t how_many)
1833 uint32_t bus_id = 1;
1835 uint32_t channels_used = 0;
1838 uint32_t control_id;
1840 /* count existing audio busses */
1843 shared_ptr<RouteList> r = routes.reader ();
1845 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1846 if (boost::dynamic_pointer_cast<Track>(*i) == 0) {
1848 if (!(*i)->is_hidden() && (*i)->name() != _("master")) {
1851 channels_used += (*i)->n_inputs().n_audio();
1857 vector<string> physinputs;
1858 vector<string> physoutputs;
1860 _engine.get_physical_outputs (DataType::AUDIO, physoutputs);
1861 _engine.get_physical_inputs (DataType::AUDIO, physinputs);
1863 n_physical_audio_outputs = physoutputs.size();
1864 n_physical_audio_inputs = physinputs.size();
1866 control_id = ntracks() + nbusses() + 1;
1871 snprintf (bus_name, sizeof(bus_name), "Bus %" PRIu32, bus_id);
1875 if (route_by_name (bus_name) == 0) {
1879 } while (bus_id < (UINT_MAX-1));
1882 shared_ptr<Route> bus (new Route (*this, bus_name, -1, -1, -1, -1, Route::Flag(0), DataType::AUDIO));
1884 if (bus->ensure_io (ChanCount(DataType::AUDIO, input_channels), ChanCount(DataType::AUDIO, output_channels), false, this)) {
1885 error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
1886 input_channels, output_channels)
1894 for (uint32_t x = 0; n_physical_audio_inputs && x < bus->n_inputs(); ++x) {
1898 if (Config->get_input_auto_connect() & AutoConnectPhysical) {
1899 port = physinputs[((n+x)%n_physical_audio_inputs)];
1902 if (port.length() && bus->connect_input (bus->input (x), port, this)) {
1908 for (uint32_t x = 0; n_physical_audio_outputs && x < bus->n_outputs().n_audio(); ++x) {
1911 if (Config->get_output_auto_connect() & AutoConnectPhysical) {
1912 port = physoutputs[((n+x)%n_physical_outputs)];
1913 } else if (Config->get_output_auto_connect() & AutoConnectMaster) {
1915 port = _master_out->input (x%_master_out->n_inputs().n_audio())->name();
1919 if (port.length() && bus->connect_output (bus->output (x), port, this)) {
1924 channels_used += bus->n_inputs ().n_audio();
1926 bus->set_remote_control_id (control_id);
1929 ret.push_back (bus);
1933 catch (failed_constructor &err) {
1934 error << _("Session: could not create new audio route.") << endmsg;
1938 catch (AudioEngine::PortRegistrationFailure& pfe) {
1939 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;
1949 add_routes (ret, true);
1957 Session::add_routes (RouteList& new_routes, bool save)
1960 RCUWriter<RouteList> writer (routes);
1961 shared_ptr<RouteList> r = writer.get_copy ();
1962 r->insert (r->end(), new_routes.begin(), new_routes.end());
1963 resort_routes_using (r);
1966 for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) {
1968 boost::weak_ptr<Route> wpr (*x);
1970 (*x)->solo_changed.connect (sigc::bind (mem_fun (*this, &Session::route_solo_changed), wpr));
1971 (*x)->mute_changed.connect (mem_fun (*this, &Session::route_mute_changed));
1972 (*x)->output_changed.connect (mem_fun (*this, &Session::set_worst_io_latencies_x));
1973 (*x)->processors_changed.connect (bind (mem_fun (*this, &Session::update_latency_compensation), false, false));
1975 if ((*x)->is_master()) {
1979 if ((*x)->is_control()) {
1980 _control_out = (*x);
1984 if (_control_out && IO::connecting_legal) {
1986 vector<string> cports;
1987 uint32_t ni = _control_out->n_inputs().n_audio();
1989 for (uint32_t n = 0; n < ni; ++n) {
1990 cports.push_back (_control_out->input(n)->name());
1993 for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) {
1994 (*x)->set_control_outs (cports);
2001 save_state (_current_snapshot_name);
2004 RouteAdded (new_routes); /* EMIT SIGNAL */
2008 Session::add_diskstream (boost::shared_ptr<Diskstream> dstream)
2010 /* need to do this in case we're rolling at the time, to prevent false underruns */
2011 dstream->do_refill_with_alloc ();
2013 dstream->set_block_size (current_block_size);
2016 RCUWriter<DiskstreamList> writer (diskstreams);
2017 boost::shared_ptr<DiskstreamList> ds = writer.get_copy();
2018 ds->push_back (dstream);
2019 /* writer goes out of scope, copies ds back to main */
2022 dstream->PlaylistChanged.connect (sigc::bind (mem_fun (*this, &Session::diskstream_playlist_changed), dstream));
2023 /* this will connect to future changes, and check the current length */
2024 diskstream_playlist_changed (dstream);
2026 dstream->prepare ();
2031 Session::remove_route (shared_ptr<Route> route)
2034 RCUWriter<RouteList> writer (routes);
2035 shared_ptr<RouteList> rs = writer.get_copy ();
2039 /* deleting the master out seems like a dumb
2040 idea, but its more of a UI policy issue
2044 if (route == _master_out) {
2045 _master_out = shared_ptr<Route> ();
2048 if (route == _control_out) {
2049 _control_out = shared_ptr<Route> ();
2051 /* cancel control outs for all routes */
2053 vector<string> empty;
2055 for (RouteList::iterator r = rs->begin(); r != rs->end(); ++r) {
2056 (*r)->set_control_outs (empty);
2060 update_route_solo_state ();
2062 /* writer goes out of scope, forces route list update */
2066 boost::shared_ptr<Diskstream> ds;
2068 if ((t = dynamic_cast<Track*>(route.get())) != 0) {
2069 ds = t->diskstream();
2075 RCUWriter<DiskstreamList> dsl (diskstreams);
2076 boost::shared_ptr<DiskstreamList> d = dsl.get_copy();
2081 find_current_end ();
2083 // We need to disconnect the routes inputs and outputs
2085 route->disconnect_inputs (0);
2086 route->disconnect_outputs (0);
2088 update_latency_compensation (false, false);
2091 /* get rid of it from the dead wood collection in the route list manager */
2093 /* XXX i think this is unsafe as it currently stands, but i am not sure. (pd, october 2nd, 2006) */
2097 /* try to cause everyone to drop their references */
2099 route->drop_references ();
2101 sync_order_keys (N_("session"));
2103 /* save the new state of the world */
2105 if (save_state (_current_snapshot_name)) {
2106 save_history (_current_snapshot_name);
2111 Session::route_mute_changed (void* src)
2117 Session::route_solo_changed (void* src, boost::weak_ptr<Route> wpr)
2119 if (solo_update_disabled) {
2125 boost::shared_ptr<Route> route = wpr.lock ();
2128 /* should not happen */
2129 error << string_compose (_("programming error: %1"), X_("invalid route weak ptr passed to route_solo_changed")) << endmsg;
2133 is_track = (boost::dynamic_pointer_cast<AudioTrack>(route) != 0);
2135 shared_ptr<RouteList> r = routes.reader ();
2137 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2139 /* soloing a track mutes all other tracks, soloing a bus mutes all other busses */
2143 /* don't mess with busses */
2145 if (dynamic_cast<Track*>((*i).get()) == 0) {
2151 /* don't mess with tracks */
2153 if (dynamic_cast<Track*>((*i).get()) != 0) {
2158 if ((*i) != route &&
2159 ((*i)->mix_group () == 0 ||
2160 (*i)->mix_group () != route->mix_group () ||
2161 !route->mix_group ()->is_active())) {
2163 if ((*i)->soloed()) {
2165 /* if its already soloed, and solo latching is enabled,
2166 then leave it as it is.
2169 if (Config->get_solo_latched()) {
2176 solo_update_disabled = true;
2177 (*i)->set_solo (false, src);
2178 solo_update_disabled = false;
2182 bool something_soloed = false;
2183 bool same_thing_soloed = false;
2184 bool signal = false;
2186 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2187 if ((*i)->soloed()) {
2188 something_soloed = true;
2189 if (dynamic_cast<Track*>((*i).get())) {
2191 same_thing_soloed = true;
2196 same_thing_soloed = true;
2204 if (something_soloed != currently_soloing) {
2206 currently_soloing = something_soloed;
2209 modify_solo_mute (is_track, same_thing_soloed);
2212 SoloActive (currently_soloing); /* EMIT SIGNAL */
2215 SoloChanged (); /* EMIT SIGNAL */
2221 Session::update_route_solo_state ()
2224 bool is_track = false;
2225 bool signal = false;
2227 /* this is where we actually implement solo by changing
2228 the solo mute setting of each track.
2231 shared_ptr<RouteList> r = routes.reader ();
2233 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2234 if ((*i)->soloed()) {
2236 if (dynamic_cast<Track*>((*i).get())) {
2243 if (mute != currently_soloing) {
2245 currently_soloing = mute;
2248 if (!is_track && !mute) {
2250 /* nothing is soloed */
2252 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2253 (*i)->set_solo_mute (false);
2263 modify_solo_mute (is_track, mute);
2266 SoloActive (currently_soloing);
2271 Session::modify_solo_mute (bool is_track, bool mute)
2273 shared_ptr<RouteList> r = routes.reader ();
2275 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2279 /* only alter track solo mute */
2281 if (dynamic_cast<Track*>((*i).get())) {
2282 if ((*i)->soloed()) {
2283 (*i)->set_solo_mute (!mute);
2285 (*i)->set_solo_mute (mute);
2291 /* only alter bus solo mute */
2293 if (!dynamic_cast<Track*>((*i).get())) {
2295 if ((*i)->soloed()) {
2297 (*i)->set_solo_mute (false);
2301 /* don't mute master or control outs
2302 in response to another bus solo
2305 if ((*i) != _master_out &&
2306 (*i) != _control_out) {
2307 (*i)->set_solo_mute (mute);
2318 Session::catch_up_on_solo ()
2320 /* this is called after set_state() to catch the full solo
2321 state, which can't be correctly determined on a per-route
2322 basis, but needs the global overview that only the session
2325 update_route_solo_state();
2329 Session::catch_up_on_solo_mute_override ()
2331 if (Config->get_solo_model() != InverseMute) {
2335 /* this is called whenever the param solo-mute-override is
2338 shared_ptr<RouteList> r = routes.reader ();
2340 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2341 (*i)->catch_up_on_solo_mute_override ();
2346 Session::route_by_name (string name)
2348 shared_ptr<RouteList> r = routes.reader ();
2350 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2351 if ((*i)->name() == name) {
2356 return shared_ptr<Route> ((Route*) 0);
2360 Session::route_by_id (PBD::ID id)
2362 shared_ptr<RouteList> r = routes.reader ();
2364 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2365 if ((*i)->id() == id) {
2370 return shared_ptr<Route> ((Route*) 0);
2374 Session::route_by_remote_id (uint32_t id)
2376 shared_ptr<RouteList> r = routes.reader ();
2378 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2379 if ((*i)->remote_control_id() == id) {
2384 return shared_ptr<Route> ((Route*) 0);
2388 Session::find_current_end ()
2390 if (_state_of_the_state & Loading) {
2394 nframes_t max = get_maximum_extent ();
2396 if (max > end_location->end()) {
2397 end_location->set_end (max);
2399 DurationChanged(); /* EMIT SIGNAL */
2404 Session::get_maximum_extent () const
2409 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
2411 for (DiskstreamList::const_iterator i = dsl->begin(); i != dsl->end(); ++i) {
2412 if ((*i)->destructive()) //ignore tape tracks when getting max extents
2414 boost::shared_ptr<Playlist> pl = (*i)->playlist();
2415 if ((me = pl->get_maximum_extent()) > max) {
2423 boost::shared_ptr<Diskstream>
2424 Session::diskstream_by_name (string name)
2426 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
2428 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
2429 if ((*i)->name() == name) {
2434 return boost::shared_ptr<Diskstream>((Diskstream*) 0);
2437 boost::shared_ptr<Diskstream>
2438 Session::diskstream_by_id (const PBD::ID& id)
2440 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
2442 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
2443 if ((*i)->id() == id) {
2448 return boost::shared_ptr<Diskstream>((Diskstream*) 0);
2451 /* Region management */
2454 Session::new_region_name (string old)
2456 string::size_type last_period;
2458 string::size_type len = old.length() + 64;
2461 if ((last_period = old.find_last_of ('.')) == string::npos) {
2463 /* no period present - add one explicitly */
2466 last_period = old.length() - 1;
2471 number = atoi (old.substr (last_period+1).c_str());
2475 while (number < (UINT_MAX-1)) {
2477 RegionList::const_iterator i;
2482 snprintf (buf, len, "%s%" PRIu32, old.substr (0, last_period + 1).c_str(), number);
2485 for (i = regions.begin(); i != regions.end(); ++i) {
2486 if (i->second->name() == sbuf) {
2491 if (i == regions.end()) {
2496 if (number != (UINT_MAX-1)) {
2500 error << string_compose (_("cannot create new name for region \"%1\""), old) << endmsg;
2505 Session::region_name (string& result, string base, bool newlevel)
2510 assert(base.find("/") == string::npos);
2514 Glib::Mutex::Lock lm (region_lock);
2516 snprintf (buf, sizeof (buf), "%d", (int)regions.size() + 1);
2525 string::size_type pos;
2527 pos = base.find_last_of ('.');
2529 /* pos may be npos, but then we just use entire base */
2531 subbase = base.substr (0, pos);
2536 Glib::Mutex::Lock lm (region_lock);
2538 map<string,uint32_t>::iterator x;
2542 if ((x = region_name_map.find (subbase)) == region_name_map.end()) {
2544 region_name_map[subbase] = 1;
2547 snprintf (buf, sizeof (buf), ".%d", x->second);
2558 Session::add_region (boost::shared_ptr<Region> region)
2560 vector<boost::shared_ptr<Region> > v;
2561 v.push_back (region);
2566 Session::add_regions (vector<boost::shared_ptr<Region> >& new_regions)
2571 Glib::Mutex::Lock lm (region_lock);
2573 for (vector<boost::shared_ptr<Region> >::iterator ii = new_regions.begin(); ii != new_regions.end(); ++ii) {
2575 boost::shared_ptr<Region> region = *ii;
2579 error << _("Session::add_region() ignored a null region. Warning: you might have lost a region.") << endmsg;
2583 RegionList::iterator x;
2585 for (x = regions.begin(); x != regions.end(); ++x) {
2587 if (region->region_list_equivalent (x->second)) {
2592 if (x == regions.end()) {
2594 pair<RegionList::key_type,RegionList::mapped_type> entry;
2596 entry.first = region->id();
2597 entry.second = region;
2599 pair<RegionList::iterator,bool> x = regions.insert (entry);
2611 /* mark dirty because something has changed even if we didn't
2612 add the region to the region list.
2619 vector<boost::weak_ptr<Region> > v;
2620 boost::shared_ptr<Region> first_r;
2622 for (vector<boost::shared_ptr<Region> >::iterator ii = new_regions.begin(); ii != new_regions.end(); ++ii) {
2624 boost::shared_ptr<Region> region = *ii;
2628 error << _("Session::add_region() ignored a null region. Warning: you might have lost a region.") << endmsg;
2631 v.push_back (region);
2638 region->StateChanged.connect (sigc::bind (mem_fun (*this, &Session::region_changed), boost::weak_ptr<Region>(region)));
2639 region->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_region), boost::weak_ptr<Region>(region)));
2641 update_region_name_map (region);
2645 RegionsAdded (v); /* EMIT SIGNAL */
2651 Session::update_region_name_map (boost::shared_ptr<Region> region)
2653 string::size_type last_period = region->name().find_last_of ('.');
2655 if (last_period != string::npos && last_period < region->name().length() - 1) {
2657 string base = region->name().substr (0, last_period);
2658 string number = region->name().substr (last_period+1);
2659 map<string,uint32_t>::iterator x;
2661 /* note that if there is no number, we get zero from atoi,
2665 region_name_map[base] = atoi (number);
2670 Session::region_changed (Change what_changed, boost::weak_ptr<Region> weak_region)
2672 boost::shared_ptr<Region> region (weak_region.lock ());
2678 if (what_changed & Region::HiddenChanged) {
2679 /* relay hidden changes */
2680 RegionHiddenChange (region);
2683 if (what_changed & NameChanged) {
2684 update_region_name_map (region);
2689 Session::remove_region (boost::weak_ptr<Region> weak_region)
2691 RegionList::iterator i;
2692 boost::shared_ptr<Region> region (weak_region.lock ());
2698 bool removed = false;
2701 Glib::Mutex::Lock lm (region_lock);
2703 if ((i = regions.find (region->id())) != regions.end()) {
2709 /* mark dirty because something has changed even if we didn't
2710 remove the region from the region list.
2716 RegionRemoved(region); /* EMIT SIGNAL */
2720 boost::shared_ptr<Region>
2721 Session::find_whole_file_parent (boost::shared_ptr<Region const> child)
2723 RegionList::iterator i;
2724 boost::shared_ptr<Region> region;
2726 Glib::Mutex::Lock lm (region_lock);
2728 for (i = regions.begin(); i != regions.end(); ++i) {
2732 if (region->whole_file()) {
2734 if (child->source_equivalent (region)) {
2740 return boost::shared_ptr<Region> ();
2744 Session::find_equivalent_playlist_regions (boost::shared_ptr<Region> region, vector<boost::shared_ptr<Region> >& result)
2746 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i)
2747 (*i)->get_region_list_equivalent_regions (region, result);
2751 Session::destroy_region (boost::shared_ptr<Region> region)
2753 vector<boost::shared_ptr<Source> > srcs;
2756 if (region->playlist()) {
2757 region->playlist()->destroy_region (region);
2760 for (uint32_t n = 0; n < region->n_channels(); ++n) {
2761 srcs.push_back (region->source (n));
2765 region->drop_references ();
2767 for (vector<boost::shared_ptr<Source> >::iterator i = srcs.begin(); i != srcs.end(); ++i) {
2769 (*i)->mark_for_remove ();
2770 (*i)->drop_references ();
2772 cerr << "source was not used by any playlist\n";
2779 Session::destroy_regions (list<boost::shared_ptr<Region> > regions)
2781 for (list<boost::shared_ptr<Region> >::iterator i = regions.begin(); i != regions.end(); ++i) {
2782 destroy_region (*i);
2788 Session::remove_last_capture ()
2790 list<boost::shared_ptr<Region> > r;
2792 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
2794 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
2795 list<boost::shared_ptr<Region> >& l = (*i)->last_capture_regions();
2798 r.insert (r.end(), l.begin(), l.end());
2803 destroy_regions (r);
2805 save_state (_current_snapshot_name);
2811 Session::remove_region_from_region_list (boost::shared_ptr<Region> r)
2817 /* Source Management */
2819 Session::add_source (boost::shared_ptr<Source> source)
2821 pair<SourceMap::key_type, SourceMap::mapped_type> entry;
2822 pair<SourceMap::iterator,bool> result;
2824 entry.first = source->id();
2825 entry.second = source;
2828 Glib::Mutex::Lock lm (source_lock);
2829 result = sources.insert (entry);
2832 if (result.second) {
2833 source->GoingAway.connect (sigc::bind (mem_fun (this, &Session::remove_source), boost::weak_ptr<Source> (source)));
2837 boost::shared_ptr<AudioFileSource> afs;
2839 if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(source)) != 0) {
2840 if (Config->get_auto_analyse_audio()) {
2841 Analyser::queue_source_for_analysis (source, false);
2847 Session::remove_source (boost::weak_ptr<Source> src)
2849 SourceMap::iterator i;
2850 boost::shared_ptr<Source> source = src.lock();
2857 Glib::Mutex::Lock lm (source_lock);
2859 if ((i = sources.find (source->id())) != sources.end()) {
2864 if (!_state_of_the_state & InCleanup) {
2866 /* save state so we don't end up with a session file
2867 referring to non-existent sources.
2870 save_state (_current_snapshot_name);
2874 boost::shared_ptr<Source>
2875 Session::source_by_id (const PBD::ID& id)
2877 Glib::Mutex::Lock lm (source_lock);
2878 SourceMap::iterator i;
2879 boost::shared_ptr<Source> source;
2881 if ((i = sources.find (id)) != sources.end()) {
2889 boost::shared_ptr<Source>
2890 Session::source_by_path_and_channel (const Glib::ustring& path, uint16_t chn)
2892 Glib::Mutex::Lock lm (source_lock);
2894 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2895 cerr << "comparing " << path << " with " << i->second->name() << endl;
2896 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(i->second);
2898 if (afs && afs->path() == path && chn == afs->channel()) {
2903 return boost::shared_ptr<Source>();
2907 Session::peak_path (Glib::ustring base) const
2909 sys::path peakfile_path(_session_dir->peak_path());
2910 peakfile_path /= basename_nosuffix (base) + peakfile_suffix;
2911 return peakfile_path.to_string();
2915 Session::change_audio_path_by_name (string path, string oldname, string newname, bool destructive)
2918 string old_basename = PBD::basename_nosuffix (oldname);
2919 string new_legalized = legalize_for_path (newname);
2921 /* note: we know (or assume) the old path is already valid */
2925 /* destructive file sources have a name of the form:
2927 /path/to/Tnnnn-NAME(%[LR])?.wav
2929 the task here is to replace NAME with the new name.
2932 /* find last slash */
2936 string::size_type slash;
2937 string::size_type dash;
2939 if ((slash = path.find_last_of ('/')) == string::npos) {
2943 dir = path.substr (0, slash+1);
2945 /* '-' is not a legal character for the NAME part of the path */
2947 if ((dash = path.find_last_of ('-')) == string::npos) {
2951 prefix = path.substr (slash+1, dash-(slash+1));
2956 path += new_legalized;
2957 path += ".wav"; /* XXX gag me with a spoon */
2961 /* non-destructive file sources have a name of the form:
2963 /path/to/NAME-nnnnn(%[LR])?.wav
2965 the task here is to replace NAME with the new name.
2970 string::size_type slash;
2971 string::size_type dash;
2972 string::size_type postfix;
2974 /* find last slash */
2976 if ((slash = path.find_last_of ('/')) == string::npos) {
2980 dir = path.substr (0, slash+1);
2982 /* '-' is not a legal character for the NAME part of the path */
2984 if ((dash = path.find_last_of ('-')) == string::npos) {
2988 suffix = path.substr (dash+1);
2990 // Suffix is now everything after the dash. Now we need to eliminate
2991 // the nnnnn part, which is done by either finding a '%' or a '.'
2993 postfix = suffix.find_last_of ("%");
2994 if (postfix == string::npos) {
2995 postfix = suffix.find_last_of ('.');
2998 if (postfix != string::npos) {
2999 suffix = suffix.substr (postfix);
3001 error << "Logic error in Session::change_audio_path_by_name(), please report to the developers" << endl;
3005 const uint32_t limit = 10000;
3006 char buf[PATH_MAX+1];
3008 for (uint32_t cnt = 1; cnt <= limit; ++cnt) {
3010 snprintf (buf, sizeof(buf), "%s%s-%u%s", dir.c_str(), newname.c_str(), cnt, suffix.c_str());
3012 if (access (buf, F_OK) != 0) {
3020 error << "FATAL ERROR! Could not find a " << endl;
3029 Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool destructive)
3033 char buf[PATH_MAX+1];
3034 const uint32_t limit = 10000;
3038 legalized = legalize_for_path (name);
3040 /* find a "version" of the file name that doesn't exist in
3041 any of the possible directories.
3044 for (cnt = (destructive ? ++destructive_index : 1); cnt <= limit; ++cnt) {
3046 vector<space_and_path>::iterator i;
3047 uint32_t existing = 0;
3049 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3051 SessionDirectory sdir((*i).path);
3053 spath = sdir.sound_path().to_string();
3057 snprintf (buf, sizeof(buf), "%s/T%04d-%s.wav", spath.c_str(), cnt, legalized.c_str());
3058 } else if (nchan == 2) {
3060 snprintf (buf, sizeof(buf), "%s/T%04d-%s%%L.wav", spath.c_str(), cnt, legalized.c_str());
3062 snprintf (buf, sizeof(buf), "%s/T%04d-%s%%R.wav", spath.c_str(), cnt, legalized.c_str());
3064 } else if (nchan < 26) {
3065 snprintf (buf, sizeof(buf), "%s/T%04d-%s%%%c.wav", spath.c_str(), cnt, legalized.c_str(), 'a' + chan);
3067 snprintf (buf, sizeof(buf), "%s/T%04d-%s.wav", spath.c_str(), cnt, legalized.c_str());
3076 snprintf (buf, sizeof(buf), "%s-%u.wav", spath.c_str(), cnt);
3077 } else if (nchan == 2) {
3079 snprintf (buf, sizeof(buf), "%s-%u%%L.wav", spath.c_str(), cnt);
3081 snprintf (buf, sizeof(buf), "%s-%u%%R.wav", spath.c_str(), cnt);
3083 } else if (nchan < 26) {
3084 snprintf (buf, sizeof(buf), "%s-%u%%%c.wav", spath.c_str(), cnt, 'a' + chan);
3086 snprintf (buf, sizeof(buf), "%s-%u.wav", spath.c_str(), cnt);
3090 if (sys::exists(buf)) {
3096 if (existing == 0) {
3101 error << string_compose(_("There are already %1 recordings for %2, which I consider too many."), limit, name) << endmsg;
3103 throw failed_constructor();
3107 /* we now have a unique name for the file, but figure out where to
3113 SessionDirectory sdir(get_best_session_directory_for_new_source ());
3115 spath = sdir.sound_path().to_string();
3118 string::size_type pos = foo.find_last_of ('/');
3120 if (pos == string::npos) {
3123 spath += foo.substr (pos + 1);
3129 boost::shared_ptr<AudioFileSource>
3130 Session::create_audio_source_for_session (AudioDiskstream& ds, uint32_t chan, bool destructive)
3132 string spath = audio_path_from_name (ds.name(), ds.n_channels().n_audio(), chan, destructive);
3133 return boost::dynamic_pointer_cast<AudioFileSource> (
3134 SourceFactory::createWritable (DataType::AUDIO, *this, spath, destructive, frame_rate()));
3137 // FIXME: _terrible_ code duplication
3139 Session::change_midi_path_by_name (string path, string oldname, string newname, bool destructive)
3142 string old_basename = PBD::basename_nosuffix (oldname);
3143 string new_legalized = legalize_for_path (newname);
3145 /* note: we know (or assume) the old path is already valid */
3149 /* destructive file sources have a name of the form:
3151 /path/to/Tnnnn-NAME(%[LR])?.wav
3153 the task here is to replace NAME with the new name.
3156 /* find last slash */
3160 string::size_type slash;
3161 string::size_type dash;
3163 if ((slash = path.find_last_of ('/')) == string::npos) {
3167 dir = path.substr (0, slash+1);
3169 /* '-' is not a legal character for the NAME part of the path */
3171 if ((dash = path.find_last_of ('-')) == string::npos) {
3175 prefix = path.substr (slash+1, dash-(slash+1));
3180 path += new_legalized;
3181 path += ".mid"; /* XXX gag me with a spoon */
3185 /* non-destructive file sources have a name of the form:
3187 /path/to/NAME-nnnnn(%[LR])?.wav
3189 the task here is to replace NAME with the new name.
3194 string::size_type slash;
3195 string::size_type dash;
3196 string::size_type postfix;
3198 /* find last slash */
3200 if ((slash = path.find_last_of ('/')) == string::npos) {
3204 dir = path.substr (0, slash+1);
3206 /* '-' is not a legal character for the NAME part of the path */
3208 if ((dash = path.find_last_of ('-')) == string::npos) {
3212 suffix = path.substr (dash+1);
3214 // Suffix is now everything after the dash. Now we need to eliminate
3215 // the nnnnn part, which is done by either finding a '%' or a '.'
3217 postfix = suffix.find_last_of ("%");
3218 if (postfix == string::npos) {
3219 postfix = suffix.find_last_of ('.');
3222 if (postfix != string::npos) {
3223 suffix = suffix.substr (postfix);
3225 error << "Logic error in Session::change_midi_path_by_name(), please report to the developers" << endl;
3229 const uint32_t limit = 10000;
3230 char buf[PATH_MAX+1];
3232 for (uint32_t cnt = 1; cnt <= limit; ++cnt) {
3234 snprintf (buf, sizeof(buf), "%s%s-%u%s", dir.c_str(), newname.c_str(), cnt, suffix.c_str());
3236 if (access (buf, F_OK) != 0) {
3244 error << "FATAL ERROR! Could not find a " << endl;
3253 Session::midi_path_from_name (string name)
3257 char buf[PATH_MAX+1];
3258 const uint32_t limit = 10000;
3262 legalized = legalize_for_path (name);
3264 /* find a "version" of the file name that doesn't exist in
3265 any of the possible directories.
3268 for (cnt = 1; cnt <= limit; ++cnt) {
3270 vector<space_and_path>::iterator i;
3271 uint32_t existing = 0;
3273 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3275 SessionDirectory sdir((*i).path);
3277 sys::path p = sdir.midi_path();
3281 spath = p.to_string();
3283 snprintf (buf, sizeof(buf), "%s-%u.mid", spath.c_str(), cnt);
3285 if (sys::exists (buf)) {
3290 if (existing == 0) {
3295 error << string_compose(_("There are already %1 recordings for %2, which I consider too many."), limit, name) << endmsg;
3296 throw failed_constructor();
3300 /* we now have a unique name for the file, but figure out where to
3306 SessionDirectory sdir(get_best_session_directory_for_new_source ());
3308 spath = sdir.midi_path().to_string();
3311 string::size_type pos = foo.find_last_of ('/');
3313 if (pos == string::npos) {
3316 spath += foo.substr (pos + 1);
3322 boost::shared_ptr<MidiSource>
3323 Session::create_midi_source_for_session (MidiDiskstream& ds)
3325 string mpath = midi_path_from_name (ds.name());
3327 return boost::dynamic_pointer_cast<SMFSource> (SourceFactory::createWritable (DataType::MIDI, *this, mpath, false, frame_rate()));
3331 /* Playlist management */
3333 boost::shared_ptr<Playlist>
3334 Session::playlist_by_name (string name)
3336 Glib::Mutex::Lock lm (playlist_lock);
3337 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
3338 if ((*i)->name() == name) {
3342 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
3343 if ((*i)->name() == name) {
3348 return boost::shared_ptr<Playlist>();
3352 Session::unassigned_playlists (std::list<boost::shared_ptr<Playlist> > & list)
3354 Glib::Mutex::Lock lm (playlist_lock);
3355 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
3356 if (!(*i)->get_orig_diskstream_id().to_s().compare ("0")) {
3357 list.push_back (*i);
3360 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
3361 if (!(*i)->get_orig_diskstream_id().to_s().compare ("0")) {
3362 list.push_back (*i);
3368 Session::add_playlist (boost::shared_ptr<Playlist> playlist, bool unused)
3370 if (playlist->hidden()) {
3375 Glib::Mutex::Lock lm (playlist_lock);
3376 if (find (playlists.begin(), playlists.end(), playlist) == playlists.end()) {
3377 playlists.insert (playlists.begin(), playlist);
3378 playlist->InUse.connect (sigc::bind (mem_fun (*this, &Session::track_playlist), boost::weak_ptr<Playlist>(playlist)));
3379 playlist->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_playlist), boost::weak_ptr<Playlist>(playlist)));
3384 playlist->release();
3389 PlaylistAdded (playlist); /* EMIT SIGNAL */
3393 Session::get_playlists (vector<boost::shared_ptr<Playlist> >& s)
3396 Glib::Mutex::Lock lm (playlist_lock);
3397 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
3400 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
3407 Session::track_playlist (bool inuse, boost::weak_ptr<Playlist> wpl)
3409 boost::shared_ptr<Playlist> pl(wpl.lock());
3415 PlaylistList::iterator x;
3418 /* its not supposed to be visible */
3423 Glib::Mutex::Lock lm (playlist_lock);
3427 unused_playlists.insert (pl);
3429 if ((x = playlists.find (pl)) != playlists.end()) {
3430 playlists.erase (x);
3436 playlists.insert (pl);
3438 if ((x = unused_playlists.find (pl)) != unused_playlists.end()) {
3439 unused_playlists.erase (x);
3446 Session::remove_playlist (boost::weak_ptr<Playlist> weak_playlist)
3448 if (_state_of_the_state & Deletion) {
3452 boost::shared_ptr<Playlist> playlist (weak_playlist.lock());
3459 Glib::Mutex::Lock lm (playlist_lock);
3461 PlaylistList::iterator i;
3463 i = find (playlists.begin(), playlists.end(), playlist);
3464 if (i != playlists.end()) {
3465 playlists.erase (i);
3468 i = find (unused_playlists.begin(), unused_playlists.end(), playlist);
3469 if (i != unused_playlists.end()) {
3470 unused_playlists.erase (i);
3477 PlaylistRemoved (playlist); /* EMIT SIGNAL */
3481 Session::set_audition (boost::shared_ptr<Region> r)
3483 pending_audition_region = r;
3484 post_transport_work = PostTransportWork (post_transport_work | PostTransportAudition);
3485 schedule_butler_transport_work ();
3489 Session::audition_playlist ()
3491 Event* ev = new Event (Event::Audition, Event::Add, Event::Immediate, 0, 0.0);
3492 ev->region.reset ();
3497 Session::non_realtime_set_audition ()
3499 if (!pending_audition_region) {
3500 auditioner->audition_current_playlist ();
3502 auditioner->audition_region (pending_audition_region);
3503 pending_audition_region.reset ();
3505 AuditionActive (true); /* EMIT SIGNAL */
3509 Session::audition_region (boost::shared_ptr<Region> r)
3511 Event* ev = new Event (Event::Audition, Event::Add, Event::Immediate, 0, 0.0);
3517 Session::cancel_audition ()
3519 if (auditioner->active()) {
3520 auditioner->cancel_audition ();
3521 AuditionActive (false); /* EMIT SIGNAL */
3526 Session::RoutePublicOrderSorter::operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b)
3528 return a->order_key(N_("signal")) < b->order_key(N_("signal"));
3532 Session::remove_empty_sounds ()
3534 vector<string> audio_filenames;
3536 get_files_in_directory (_session_dir->sound_path(), audio_filenames);
3538 Glib::Mutex::Lock lm (source_lock);
3540 TapeFileMatcher tape_file_matcher;
3542 remove_if (audio_filenames.begin(), audio_filenames.end(),
3543 sigc::mem_fun (tape_file_matcher, &TapeFileMatcher::matches));
3545 for (vector<string>::iterator i = audio_filenames.begin(); i != audio_filenames.end(); ++i) {
3547 sys::path audio_file_path (_session_dir->sound_path());
3549 audio_file_path /= *i;
3551 if (AudioFileSource::is_empty (*this, audio_file_path.to_string())) {
3555 sys::remove (audio_file_path);
3556 const string peakfile = peak_path (audio_file_path.to_string());
3557 sys::remove (peakfile);
3559 catch (const sys::filesystem_error& err)
3561 error << err.what() << endmsg;
3568 Session::is_auditioning () const
3570 /* can be called before we have an auditioner object */
3572 return auditioner->active();
3579 Session::set_all_solo (bool yn)
3581 shared_ptr<RouteList> r = routes.reader ();
3583 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
3584 if (!(*i)->is_hidden()) {
3585 (*i)->set_solo (yn, this);
3593 Session::set_all_mute (bool yn)
3595 shared_ptr<RouteList> r = routes.reader ();
3597 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
3598 if (!(*i)->is_hidden()) {
3599 (*i)->set_mute (yn, this);
3607 Session::n_diskstreams () const
3611 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
3613 for (DiskstreamList::const_iterator i = dsl->begin(); i != dsl->end(); ++i) {
3614 if (!(*i)->hidden()) {
3622 Session::graph_reordered ()
3624 /* don't do this stuff if we are setting up connections
3625 from a set_state() call or creating new tracks.
3628 if (_state_of_the_state & InitialConnecting) {
3632 /* every track/bus asked for this to be handled but it was deferred because
3633 we were connecting. do it now.
3636 request_input_change_handling ();
3640 /* force all diskstreams to update their capture offset values to
3641 reflect any changes in latencies within the graph.
3644 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
3646 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
3647 (*i)->set_capture_offset ();
3652 Session::record_disenable_all ()
3654 record_enable_change_all (false);
3658 Session::record_enable_all ()
3660 record_enable_change_all (true);
3664 Session::record_enable_change_all (bool yn)
3666 shared_ptr<RouteList> r = routes.reader ();
3668 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
3671 if ((at = dynamic_cast<Track*>((*i).get())) != 0) {
3672 at->set_record_enable (yn, this);
3676 /* since we don't keep rec-enable state, don't mark session dirty */
3680 Session::add_processor (Processor* processor)
3683 PortInsert* port_insert;
3684 PluginInsert* plugin_insert;
3686 if ((port_insert = dynamic_cast<PortInsert *> (processor)) != 0) {
3687 _port_inserts.insert (_port_inserts.begin(), port_insert);
3688 } else if ((plugin_insert = dynamic_cast<PluginInsert *> (processor)) != 0) {
3689 _plugin_inserts.insert (_plugin_inserts.begin(), plugin_insert);
3690 } else if ((send = dynamic_cast<Send *> (processor)) != 0) {
3691 _sends.insert (_sends.begin(), send);
3692 } else if (dynamic_cast<InternalSend *> (processor) != 0) {
3695 fatal << _("programming error: unknown type of Insert created!") << endmsg;
3699 processor->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_processor), processor));
3705 Session::remove_processor (Processor* processor)
3708 PortInsert* port_insert;
3709 PluginInsert* plugin_insert;
3711 if ((port_insert = dynamic_cast<PortInsert *> (processor)) != 0) {
3712 list<PortInsert*>::iterator x = find (_port_inserts.begin(), _port_inserts.end(), port_insert);
3713 if (x != _port_inserts.end()) {
3714 insert_bitset[port_insert->bit_slot()] = false;
3715 _port_inserts.erase (x);
3717 } else if ((plugin_insert = dynamic_cast<PluginInsert *> (processor)) != 0) {
3718 _plugin_inserts.remove (plugin_insert);
3719 } else if (dynamic_cast<InternalSend *> (processor) != 0) {
3721 } else if ((send = dynamic_cast<Send *> (processor)) != 0) {
3722 list<Send*>::iterator x = find (_sends.begin(), _sends.end(), send);
3723 if (x != _sends.end()) {
3724 send_bitset[send->bit_slot()] = false;
3728 fatal << _("programming error: unknown type of Insert deleted!") << endmsg;
3736 Session::available_capture_duration ()
3738 float sample_bytes_on_disk = 4.0; // keep gcc happy
3740 switch (Config->get_native_file_data_format()) {
3742 sample_bytes_on_disk = 4.0;
3746 sample_bytes_on_disk = 3.0;
3750 sample_bytes_on_disk = 2.0;
3754 /* impossible, but keep some gcc versions happy */
3755 fatal << string_compose (_("programming error: %1"),
3756 X_("illegal native file data format"))
3761 double scale = 4096.0 / sample_bytes_on_disk;
3763 if (_total_free_4k_blocks * scale > (double) max_frames) {
3767 return (nframes_t) floor (_total_free_4k_blocks * scale);
3771 Session::add_bundle (shared_ptr<Bundle> bundle)
3774 RCUWriter<BundleList> writer (_bundles);
3775 boost::shared_ptr<BundleList> b = writer.get_copy ();
3776 b->push_back (bundle);
3779 BundleAdded (bundle); /* EMIT SIGNAL */
3785 Session::remove_bundle (shared_ptr<Bundle> bundle)
3787 bool removed = false;
3790 RCUWriter<BundleList> writer (_bundles);
3791 boost::shared_ptr<BundleList> b = writer.get_copy ();
3792 BundleList::iterator i = find (b->begin(), b->end(), bundle);
3794 if (i != b->end()) {
3801 BundleRemoved (bundle); /* EMIT SIGNAL */
3808 Session::bundle_by_name (string name) const
3810 boost::shared_ptr<BundleList> b = _bundles.reader ();
3812 for (BundleList::const_iterator i = b->begin(); i != b->end(); ++i) {
3813 if ((*i)->name() == name) {
3818 return boost::shared_ptr<Bundle> ();
3822 Session::tempo_map_changed (Change ignored)
3826 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
3827 (*i)->update_after_tempo_map_change ();
3830 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
3831 (*i)->update_after_tempo_map_change ();
3837 /** Ensures that all buffers (scratch, send, silent, etc) are allocated for
3838 * the given count with the current block size.
3841 Session::ensure_buffers (ChanCount howmany)
3843 if (current_block_size == 0)
3844 return; // too early? (is this ok?)
3846 // We need at least 2 MIDI scratch buffers to mix/merge
3847 if (howmany.n_midi() < 2)
3848 howmany.set_midi(2);
3850 // FIXME: JACK needs to tell us maximum MIDI buffer size
3851 // Using nasty assumption (max # events == nframes) for now
3852 _scratch_buffers->ensure_buffers(howmany, current_block_size);
3853 _mix_buffers->ensure_buffers(howmany, current_block_size);
3854 _silent_buffers->ensure_buffers(howmany, current_block_size);
3856 allocate_pan_automation_buffers (current_block_size, howmany.n_audio(), false);
3860 Session::next_insert_id ()
3862 /* this doesn't really loop forever. just think about it */
3865 for (boost::dynamic_bitset<uint32_t>::size_type n = 0; n < insert_bitset.size(); ++n) {
3866 if (!insert_bitset[n]) {
3867 insert_bitset[n] = true;
3873 /* none available, so resize and try again */
3875 insert_bitset.resize (insert_bitset.size() + 16, false);
3880 Session::next_send_id ()
3882 /* this doesn't really loop forever. just think about it */
3885 for (boost::dynamic_bitset<uint32_t>::size_type n = 0; n < send_bitset.size(); ++n) {
3886 if (!send_bitset[n]) {
3887 send_bitset[n] = true;
3893 /* none available, so resize and try again */
3895 send_bitset.resize (send_bitset.size() + 16, false);
3900 Session::mark_send_id (uint32_t id)
3902 if (id >= send_bitset.size()) {
3903 send_bitset.resize (id+16, false);
3905 if (send_bitset[id]) {
3906 warning << string_compose (_("send ID %1 appears to be in use already"), id) << endmsg;
3908 send_bitset[id] = true;
3912 Session::mark_insert_id (uint32_t id)
3914 if (id >= insert_bitset.size()) {
3915 insert_bitset.resize (id+16, false);
3917 if (insert_bitset[id]) {
3918 warning << string_compose (_("insert ID %1 appears to be in use already"), id) << endmsg;
3920 insert_bitset[id] = true;
3923 /* Named Selection management */
3926 Session::named_selection_by_name (string name)
3928 Glib::Mutex::Lock lm (named_selection_lock);
3929 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
3930 if ((*i)->name == name) {
3938 Session::add_named_selection (NamedSelection* named_selection)
3941 Glib::Mutex::Lock lm (named_selection_lock);
3942 named_selections.insert (named_selections.begin(), named_selection);
3945 for (list<boost::shared_ptr<Playlist> >::iterator i = named_selection->playlists.begin(); i != named_selection->playlists.end(); ++i) {
3951 NamedSelectionAdded (); /* EMIT SIGNAL */
3955 Session::remove_named_selection (NamedSelection* named_selection)
3957 bool removed = false;
3960 Glib::Mutex::Lock lm (named_selection_lock);
3962 NamedSelectionList::iterator i = find (named_selections.begin(), named_selections.end(), named_selection);
3964 if (i != named_selections.end()) {
3966 named_selections.erase (i);
3973 NamedSelectionRemoved (); /* EMIT SIGNAL */
3978 Session::reset_native_file_format ()
3980 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
3982 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
3983 (*i)->reset_write_sources (false);
3988 Session::route_name_unique (string n) const
3990 shared_ptr<RouteList> r = routes.reader ();
3992 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
3993 if ((*i)->name() == n) {
4002 Session::n_playlists () const
4004 Glib::Mutex::Lock lm (playlist_lock);
4005 return playlists.size();
4009 Session::allocate_pan_automation_buffers (nframes_t nframes, uint32_t howmany, bool force)
4011 if (!force && howmany <= _npan_buffers) {
4015 if (_pan_automation_buffer) {
4017 for (uint32_t i = 0; i < _npan_buffers; ++i) {
4018 delete [] _pan_automation_buffer[i];
4021 delete [] _pan_automation_buffer;
4024 _pan_automation_buffer = new pan_t*[howmany];
4026 for (uint32_t i = 0; i < howmany; ++i) {
4027 _pan_automation_buffer[i] = new pan_t[nframes];
4030 _npan_buffers = howmany;
4034 Session::freeze (InterThreadInfo& itt)
4036 shared_ptr<RouteList> r = routes.reader ();
4038 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
4042 if ((at = dynamic_cast<Track*>((*i).get())) != 0) {
4043 /* XXX this is wrong because itt.progress will keep returning to zero at the start
4053 boost::shared_ptr<Region>
4054 Session::write_one_track (AudioTrack& track, nframes_t start, nframes_t end,
4055 bool overwrite, vector<boost::shared_ptr<Source> >& srcs, InterThreadInfo& itt)
4057 boost::shared_ptr<Region> result;
4058 boost::shared_ptr<Playlist> playlist;
4059 boost::shared_ptr<AudioFileSource> fsource;
4061 char buf[PATH_MAX+1];
4062 ChanCount nchans(track.audio_diskstream()->n_channels());
4064 nframes_t this_chunk;
4067 SessionDirectory sdir(get_best_session_directory_for_new_source ());
4068 const string sound_dir = sdir.sound_path().to_string();
4069 nframes_t len = end - start;
4072 error << string_compose (_("Cannot write a range where end <= start (e.g. %1 <= %2)"),
4073 end, start) << endmsg;
4077 // any bigger than this seems to cause stack overflows in called functions
4078 const nframes_t chunk_size = (128 * 1024)/4;
4080 g_atomic_int_set (&processing_prohibited, 1);
4082 /* call tree *MUST* hold route_lock */
4084 if ((playlist = track.diskstream()->playlist()) == 0) {
4088 /* external redirects will be a problem */
4090 if (track.has_external_redirects()) {
4094 for (uint32_t chan_n=0; chan_n < nchans.n_audio(); ++chan_n) {
4096 for (x = 0; x < 99999; ++x) {
4097 snprintf (buf, sizeof(buf), "%s/%s-%d-bounce-%" PRIu32 ".wav", sound_dir.c_str(), playlist->name().c_str(), chan_n, x+1);
4098 if (access (buf, F_OK) != 0) {
4104 error << string_compose (_("too many bounced versions of playlist \"%1\""), playlist->name()) << endmsg;
4109 fsource = boost::dynamic_pointer_cast<AudioFileSource> (
4110 SourceFactory::createWritable (DataType::AUDIO, *this, buf, false, frame_rate()));
4113 catch (failed_constructor& err) {
4114 error << string_compose (_("cannot create new audio file \"%1\" for %2"), buf, track.name()) << endmsg;
4118 srcs.push_back (fsource);
4121 /* XXX need to flush all redirects */
4126 /* create a set of reasonably-sized buffers */
4127 buffers.ensure_buffers(nchans, chunk_size);
4128 buffers.set_count(nchans);
4130 for (vector<boost::shared_ptr<Source> >::iterator src=srcs.begin(); src != srcs.end(); ++src) {
4131 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
4133 afs->prepare_for_peakfile_writes ();
4136 while (to_do && !itt.cancel) {
4138 this_chunk = min (to_do, chunk_size);
4140 if (track.export_stuff (buffers, start, this_chunk)) {
4145 for (vector<boost::shared_ptr<Source> >::iterator src=srcs.begin(); src != srcs.end(); ++src, ++n) {
4146 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
4149 if (afs->write (buffers.get_audio(n).data(), this_chunk) != this_chunk) {
4155 start += this_chunk;
4156 to_do -= this_chunk;
4158 itt.progress = (float) (1.0 - ((double) to_do / len));
4167 xnow = localtime (&now);
4169 for (vector<boost::shared_ptr<Source> >::iterator src=srcs.begin(); src != srcs.end(); ++src) {
4170 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
4173 afs->update_header (position, *xnow, now);
4174 afs->flush_header ();
4178 /* construct a region to represent the bounced material */
4180 result = RegionFactory::create (srcs, 0, srcs.front()->length(),
4181 region_name_from_path (srcs.front()->name(), true));
4186 for (vector<boost::shared_ptr<Source> >::iterator src = srcs.begin(); src != srcs.end(); ++src) {
4187 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
4190 afs->mark_for_remove ();
4193 (*src)->drop_references ();
4197 for (vector<boost::shared_ptr<Source> >::iterator src = srcs.begin(); src != srcs.end(); ++src) {
4198 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
4201 afs->done_with_peakfile_writes ();
4205 g_atomic_int_set (&processing_prohibited, 0);
4211 Session::get_silent_buffers (ChanCount count)
4213 assert(_silent_buffers->available() >= count);
4214 _silent_buffers->set_count(count);
4216 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
4217 for (size_t i= 0; i < count.get(*t); ++i) {
4218 _silent_buffers->get(*t, i).clear();
4222 return *_silent_buffers;
4226 Session::get_scratch_buffers (ChanCount count)
4228 if (count != ChanCount::ZERO) {
4229 assert(_scratch_buffers->available() >= count);
4230 _scratch_buffers->set_count(count);
4232 _scratch_buffers->set_count (_scratch_buffers->available());
4235 return *_scratch_buffers;
4239 Session::get_mix_buffers (ChanCount count)
4241 assert(_mix_buffers->available() >= count);
4242 _mix_buffers->set_count(count);
4243 return *_mix_buffers;
4247 Session::ntracks () const
4250 shared_ptr<RouteList> r = routes.reader ();
4252 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
4253 if (dynamic_cast<Track*> ((*i).get())) {
4262 Session::nbusses () const
4265 shared_ptr<RouteList> r = routes.reader ();
4267 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
4268 if (dynamic_cast<Track*> ((*i).get()) == 0) {
4277 Session::add_automation_list(AutomationList *al)
4279 automation_lists[al->id()] = al;
4283 Session::compute_initial_length ()
4285 return _engine.frame_rate() * 60 * 5;
4289 Session::sync_order_keys (const char* base)
4291 if (!Config->get_sync_all_route_ordering()) {
4292 /* leave order keys as they are */
4296 boost::shared_ptr<RouteList> r = routes.reader ();
4298 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
4299 (*i)->sync_order_keys (base);
4302 Route::SyncOrderKeys (base); // EMIT SIGNAL