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.
26 #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>
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>
45 #include <ardour/audioengine.h>
46 #include <ardour/configuration.h>
47 #include <ardour/session.h>
48 #include <ardour/audio_diskstream.h>
49 #include <ardour/utils.h>
50 #include <ardour/audioplaylist.h>
51 #include <ardour/audioregion.h>
52 #include <ardour/audiofilesource.h>
53 #include <ardour/destructive_filesource.h>
54 #include <ardour/auditioner.h>
55 #include <ardour/recent_sessions.h>
56 #include <ardour/redirect.h>
57 #include <ardour/send.h>
58 #include <ardour/insert.h>
59 #include <ardour/connection.h>
60 #include <ardour/slave.h>
61 #include <ardour/tempo.h>
62 #include <ardour/audio_track.h>
63 #include <ardour/cycle_timer.h>
64 #include <ardour/named_selection.h>
65 #include <ardour/crossfade.h>
66 #include <ardour/playlist.h>
67 #include <ardour/click.h>
68 #include <ardour/data_type.h>
69 #include <ardour/source_factory.h>
70 #include <ardour/region_factory.h>
73 #include <ardour/osc.h>
79 using namespace ARDOUR;
81 using boost::shared_ptr;
83 const char* Session::_template_suffix = X_(".template");
84 const char* Session::_statefile_suffix = X_(".ardour");
85 const char* Session::_pending_suffix = X_(".pending");
86 const char* Session::old_sound_dir_name = X_("sounds");
87 const char* Session::sound_dir_name = X_("audiofiles");
88 const char* Session::peak_dir_name = X_("peaks");
89 const char* Session::dead_sound_dir_name = X_("dead_sounds");
90 const char* Session::interchange_dir_name = X_("interchange");
92 Session::compute_peak_t Session::compute_peak = 0;
93 Session::apply_gain_to_buffer_t Session::apply_gain_to_buffer = 0;
94 Session::mix_buffers_with_gain_t Session::mix_buffers_with_gain = 0;
95 Session::mix_buffers_no_gain_t Session::mix_buffers_no_gain = 0;
97 sigc::signal<int> Session::AskAboutPendingState;
98 sigc::signal<void> Session::SendFeedback;
100 sigc::signal<void> Session::SMPTEOffsetChanged;
101 sigc::signal<void> Session::StartTimeChanged;
102 sigc::signal<void> Session::EndTimeChanged;
105 Session::find_session (string str, string& path, string& snapshot, bool& isnew)
108 char buf[PATH_MAX+1];
112 if (!realpath (str.c_str(), buf) && (errno != ENOENT && errno != ENOTDIR)) {
113 error << string_compose (_("Could not resolve path: %1 (%2)"), buf, strerror(errno)) << endmsg;
119 /* check to see if it exists, and what it is */
121 if (stat (str.c_str(), &statbuf)) {
122 if (errno == ENOENT) {
125 error << string_compose (_("cannot check session path %1 (%2)"), str, strerror (errno))
133 /* it exists, so it must either be the name
134 of the directory, or the name of the statefile
138 if (S_ISDIR (statbuf.st_mode)) {
140 string::size_type slash = str.find_last_of ('/');
142 if (slash == string::npos) {
144 /* a subdirectory of cwd, so statefile should be ... */
150 tmp += _statefile_suffix;
154 if (stat (tmp.c_str(), &statbuf)) {
155 error << string_compose (_("cannot check statefile %1 (%2)"), tmp, strerror (errno))
165 /* some directory someplace in the filesystem.
166 the snapshot name is the directory name
171 snapshot = str.substr (slash+1);
175 } else if (S_ISREG (statbuf.st_mode)) {
177 string::size_type slash = str.find_last_of ('/');
178 string::size_type suffix;
180 /* remove the suffix */
182 if (slash != string::npos) {
183 snapshot = str.substr (slash+1);
188 suffix = snapshot.find (_statefile_suffix);
190 if (suffix == string::npos) {
191 error << string_compose (_("%1 is not an Ardour snapshot file"), str) << endmsg;
197 snapshot = snapshot.substr (0, suffix);
199 if (slash == string::npos) {
201 /* we must be in the directory where the
202 statefile lives. get it using cwd().
205 char cwd[PATH_MAX+1];
207 if (getcwd (cwd, sizeof (cwd)) == 0) {
208 error << string_compose (_("cannot determine current working directory (%1)"), strerror (errno))
217 /* full path to the statefile */
219 path = str.substr (0, slash);
224 /* what type of file is it? */
225 error << string_compose (_("unknown file type for session %1"), str) << endmsg;
231 /* its the name of a new directory. get the name
235 string::size_type slash = str.find_last_of ('/');
237 if (slash == string::npos) {
239 /* no slash, just use the name, but clean it up */
241 path = legalize_for_path (str);
247 snapshot = str.substr (slash+1);
254 Session::Session (AudioEngine &eng,
256 string snapshot_name,
257 string* mix_template)
260 _mmc_port (default_mmc_port),
261 _mtc_port (default_mtc_port),
262 _midi_port (default_midi_port),
263 pending_events (2048),
264 midi_requests (128), // the size of this should match the midi request pool size
265 diskstreams (new DiskstreamList),
266 routes (new RouteList),
267 auditioner ((Auditioner*) 0),
273 cerr << "Loading session " << fullpath << " using snapshot " << snapshot_name << " (1)" << endl;
275 n_physical_outputs = _engine.n_physical_outputs();
276 n_physical_inputs = _engine.n_physical_inputs();
278 first_stage_init (fullpath, snapshot_name);
280 new_session = !g_file_test (_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
282 if (create (new_session, mix_template, compute_initial_length())) {
283 cerr << "create failed\n";
285 throw failed_constructor ();
289 if (second_stage_init (new_session)) {
291 throw failed_constructor ();
294 store_recent_sessions(_name, _path);
296 bool was_dirty = dirty();
298 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
300 Config->ParameterChanged.connect (mem_fun (*this, &Session::config_changed));
303 DirtyChanged (); /* EMIT SIGNAL */
307 Session::Session (AudioEngine &eng,
309 string snapshot_name,
310 AutoConnectOption input_ac,
311 AutoConnectOption output_ac,
312 uint32_t control_out_channels,
313 uint32_t master_out_channels,
314 uint32_t requested_physical_in,
315 uint32_t requested_physical_out,
316 nframes_t initial_length)
319 _mmc_port (default_mmc_port),
320 _mtc_port (default_mtc_port),
321 _midi_port (default_midi_port),
322 pending_events (2048),
324 diskstreams (new DiskstreamList),
325 routes (new RouteList),
331 cerr << "Loading session " << fullpath << " using snapshot " << snapshot_name << " (2)" << endl;
333 n_physical_outputs = _engine.n_physical_outputs();
334 n_physical_inputs = _engine.n_physical_inputs();
336 if (n_physical_inputs) {
337 n_physical_inputs = max (requested_physical_in, n_physical_inputs);
340 if (n_physical_outputs) {
341 n_physical_outputs = max (requested_physical_out, n_physical_outputs);
344 first_stage_init (fullpath, snapshot_name);
346 new_session = !g_file_test (_path.c_str(), GFileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
349 if (create (new_session, 0, initial_length)) {
351 throw failed_constructor ();
355 if (control_out_channels) {
356 shared_ptr<Route> r (new Route (*this, _("monitor"), -1, control_out_channels, -1, control_out_channels, Route::ControlOut));
363 if (master_out_channels) {
364 shared_ptr<Route> r (new Route (*this, _("master"), -1, master_out_channels, -1, master_out_channels, Route::MasterOut));
370 /* prohibit auto-connect to master, because there isn't one */
371 output_ac = AutoConnectOption (output_ac & ~AutoConnectMaster);
374 Config->set_input_auto_connect (input_ac);
375 Config->set_output_auto_connect (output_ac);
377 if (second_stage_init (new_session)) {
379 throw failed_constructor ();
382 store_recent_sessions(_name, _path);
384 bool was_dirty = dirty ();
386 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
389 DirtyChanged (); /* EMIT SIGNAL */
401 /* if we got to here, leaving pending capture state around
405 remove_pending_capture_state ();
407 _state_of_the_state = StateOfTheState (CannotSave|Deletion);
408 _engine.remove_session ();
410 GoingAway (); /* EMIT SIGNAL */
416 /* clear history so that no references to objects are held any more */
420 /* clear state tree so that no references to objects are held any more */
426 terminate_butler_thread ();
427 terminate_midi_thread ();
429 if (click_data && click_data != default_click) {
430 delete [] click_data;
433 if (click_emphasis_data && click_emphasis_data != default_click_emphasis) {
434 delete [] click_emphasis_data;
439 for (vector<Sample*>::iterator i = _passthru_buffers.begin(); i != _passthru_buffers.end(); ++i) {
443 for (vector<Sample*>::iterator i = _silent_buffers.begin(); i != _silent_buffers.end(); ++i) {
447 for (vector<Sample*>::iterator i = _send_buffers.begin(); i != _send_buffers.end(); ++i) {
451 AudioDiskstream::free_working_buffers();
453 /* this should cause deletion of the auditioner */
455 // auditioner.reset ();
457 #undef TRACK_DESTRUCTION
458 #ifdef TRACK_DESTRUCTION
459 cerr << "delete named selections\n";
460 #endif /* TRACK_DESTRUCTION */
461 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ) {
462 NamedSelectionList::iterator tmp;
471 #ifdef TRACK_DESTRUCTION
472 cerr << "delete playlists\n";
473 #endif /* TRACK_DESTRUCTION */
474 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ) {
475 PlaylistList::iterator tmp;
480 (*i)->drop_references ();
485 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ) {
486 PlaylistList::iterator tmp;
491 (*i)->drop_references ();
497 unused_playlists.clear ();
499 #ifdef TRACK_DESTRUCTION
500 cerr << "delete audio regions\n";
501 #endif /* TRACK_DESTRUCTION */
503 for (AudioRegionList::iterator i = audio_regions.begin(); i != audio_regions.end(); ) {
504 AudioRegionList::iterator tmp;
509 i->second->drop_references ();
514 audio_regions.clear ();
516 #ifdef TRACK_DESTRUCTION
517 cerr << "delete routes\n";
518 #endif /* TRACK_DESTRUCTION */
520 RCUWriter<RouteList> writer (routes);
521 boost::shared_ptr<RouteList> r = writer.get_copy ();
522 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
523 (*i)->drop_references ();
526 /* writer goes out of scope and updates master */
531 #ifdef TRACK_DESTRUCTION
532 cerr << "delete diskstreams\n";
533 #endif /* TRACK_DESTRUCTION */
535 RCUWriter<DiskstreamList> dwriter (diskstreams);
536 boost::shared_ptr<DiskstreamList> dsl = dwriter.get_copy();
537 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
538 (*i)->drop_references ();
542 diskstreams.flush ();
544 #ifdef TRACK_DESTRUCTION
545 cerr << "delete audio sources\n";
546 #endif /* TRACK_DESTRUCTION */
547 for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ) {
548 AudioSourceList::iterator tmp;
553 i->second->drop_references ();
558 audio_sources.clear ();
560 #ifdef TRACK_DESTRUCTION
561 cerr << "delete mix groups\n";
562 #endif /* TRACK_DESTRUCTION */
563 for (list<RouteGroup *>::iterator i = mix_groups.begin(); i != mix_groups.end(); ) {
564 list<RouteGroup*>::iterator tmp;
574 #ifdef TRACK_DESTRUCTION
575 cerr << "delete edit groups\n";
576 #endif /* TRACK_DESTRUCTION */
577 for (list<RouteGroup *>::iterator i = edit_groups.begin(); i != edit_groups.end(); ) {
578 list<RouteGroup*>::iterator tmp;
588 #ifdef TRACK_DESTRUCTION
589 cerr << "delete connections\n";
590 #endif /* TRACK_DESTRUCTION */
591 for (ConnectionList::iterator i = _connections.begin(); i != _connections.end(); ) {
592 ConnectionList::iterator tmp;
602 if (butler_mixdown_buffer) {
603 delete [] butler_mixdown_buffer;
606 if (butler_gain_buffer) {
607 delete [] butler_gain_buffer;
610 Crossfade::set_buffer_size (0);
618 Session::set_worst_io_latencies ()
620 _worst_output_latency = 0;
621 _worst_input_latency = 0;
623 if (!_engine.connected()) {
627 boost::shared_ptr<RouteList> r = routes.reader ();
629 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
630 _worst_output_latency = max (_worst_output_latency, (*i)->output_latency());
631 _worst_input_latency = max (_worst_input_latency, (*i)->input_latency());
636 Session::when_engine_running ()
638 string first_physical_output;
640 /* we don't want to run execute this again */
642 set_block_size (_engine.frames_per_cycle());
643 set_frame_rate (_engine.frame_rate());
645 Config->map_parameters (mem_fun (*this, &Session::config_changed));
647 /* every time we reconnect, recompute worst case output latencies */
649 _engine.Running.connect (mem_fun (*this, &Session::set_worst_io_latencies));
651 if (synced_to_jack()) {
652 _engine.transport_stop ();
655 if (Config->get_jack_time_master()) {
656 _engine.transport_locate (_transport_frame);
664 _click_io.reset (new ClickIO (*this, "click", 0, 0, -1, -1));
666 if (state_tree && (child = find_named_node (*state_tree->root(), "Click")) != 0) {
668 /* existing state for Click */
670 if (_click_io->set_state (*child->children().front()) == 0) {
672 _clicking = Config->get_clicking ();
676 error << _("could not setup Click I/O") << endmsg;
682 /* default state for Click */
684 first_physical_output = _engine.get_nth_physical_output (0);
686 if (first_physical_output.length()) {
687 if (_click_io->add_output_port (first_physical_output, this)) {
688 // relax, even though its an error
690 _clicking = Config->get_clicking ();
696 catch (failed_constructor& err) {
697 error << _("cannot setup Click I/O") << endmsg;
700 set_worst_io_latencies ();
703 // XXX HOW TO ALERT UI TO THIS ? DO WE NEED TO?
706 /* Create a set of Connection objects that map
707 to the physical outputs currently available
712 for (uint32_t np = 0; np < n_physical_outputs; ++np) {
714 snprintf (buf, sizeof (buf), _("out %" PRIu32), np+1);
716 Connection* c = new OutputConnection (buf, true);
719 c->add_connection (0, _engine.get_nth_physical_output (np));
724 for (uint32_t np = 0; np < n_physical_inputs; ++np) {
726 snprintf (buf, sizeof (buf), _("in %" PRIu32), np+1);
728 Connection* c = new InputConnection (buf, true);
731 c->add_connection (0, _engine.get_nth_physical_input (np));
738 for (uint32_t np = 0; np < n_physical_outputs; np +=2) {
740 snprintf (buf, sizeof (buf), _("out %" PRIu32 "+%" PRIu32), np+1, np+2);
742 Connection* c = new OutputConnection (buf, true);
746 c->add_connection (0, _engine.get_nth_physical_output (np));
747 c->add_connection (1, _engine.get_nth_physical_output (np+1));
752 for (uint32_t np = 0; np < n_physical_inputs; np +=2) {
754 snprintf (buf, sizeof (buf), _("in %" PRIu32 "+%" PRIu32), np+1, np+2);
756 Connection* c = new InputConnection (buf, true);
760 c->add_connection (0, _engine.get_nth_physical_input (np));
761 c->add_connection (1, _engine.get_nth_physical_input (np+1));
770 /* create master/control ports */
775 /* force the master to ignore any later call to this */
777 if (_master_out->pending_state_node) {
778 _master_out->ports_became_legal();
781 /* no panner resets till we are through */
783 _master_out->defer_pan_reset ();
785 while ((int) _master_out->n_inputs() < _master_out->input_maximum()) {
786 if (_master_out->add_input_port ("", this)) {
787 error << _("cannot setup master inputs")
793 while ((int) _master_out->n_outputs() < _master_out->output_maximum()) {
794 if (_master_out->add_output_port (_engine.get_nth_physical_output (n), this)) {
795 error << _("cannot setup master outputs")
802 _master_out->allow_pan_reset ();
806 Connection* c = new OutputConnection (_("Master Out"), true);
808 for (uint32_t n = 0; n < _master_out->n_inputs (); ++n) {
810 c->add_connection ((int) n, _master_out->input(n)->name());
817 /* catch up on send+insert cnts */
821 for (list<PortInsert*>::iterator i = _port_inserts.begin(); i != _port_inserts.end(); ++i) {
824 if (sscanf ((*i)->name().c_str(), "%*s %u", &id) == 1) {
825 if (id > insert_cnt) {
833 for (list<Send*>::iterator i = _sends.begin(); i != _sends.end(); ++i) {
836 if (sscanf ((*i)->name().c_str(), "%*s %u", &id) == 1) {
844 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
846 /* hook us up to the engine */
848 _engine.set_session (this);
853 osc->set_session (*this);
856 _state_of_the_state = Clean;
858 DirtyChanged (); /* EMIT SIGNAL */
862 Session::hookup_io ()
864 /* stop graph reordering notifications from
865 causing resorts, etc.
868 _state_of_the_state = StateOfTheState (_state_of_the_state | InitialConnecting);
870 if (auditioner == 0) {
872 /* we delay creating the auditioner till now because
873 it makes its own connections to ports.
874 the engine has to be running for this to work.
878 auditioner.reset (new Auditioner (*this));
881 catch (failed_constructor& err) {
882 warning << _("cannot create Auditioner: no auditioning of regions possible") << endmsg;
886 /* Tell all IO objects to create their ports */
893 while ((int) _control_out->n_inputs() < _control_out->input_maximum()) {
894 if (_control_out->add_input_port ("", this)) {
895 error << _("cannot setup control inputs")
901 while ((int) _control_out->n_outputs() < _control_out->output_maximum()) {
902 if (_control_out->add_output_port (_engine.get_nth_physical_output (n), this)) {
903 error << _("cannot set up master outputs")
911 /* Tell all IO objects to connect themselves together */
913 IO::enable_connecting ();
915 /* Now reset all panners */
917 IO::reset_panners ();
919 /* Anyone who cares about input state, wake up and do something */
921 IOConnectionsComplete (); /* EMIT SIGNAL */
923 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InitialConnecting);
925 /* now handle the whole enchilada as if it was one
931 /* update mixer solo state */
937 Session::playlist_length_changed ()
939 /* we can't just increase end_location->end() if pl->get_maximum_extent()
940 if larger. if the playlist used to be the longest playlist,
941 and its now shorter, we have to decrease end_location->end(). hence,
942 we have to iterate over all diskstreams and check the
943 playlists currently in use.
949 Session::diskstream_playlist_changed (boost::shared_ptr<Diskstream> dstream)
951 boost::shared_ptr<Playlist> playlist;
953 if ((playlist = dstream->playlist()) != 0) {
954 playlist->LengthChanged.connect (mem_fun (this, &Session::playlist_length_changed));
957 /* see comment in playlist_length_changed () */
962 Session::record_enabling_legal () const
964 /* this used to be in here, but survey says.... we don't need to restrict it */
965 // if (record_status() == Recording) {
969 if (Config->get_all_safe()) {
976 Session::reset_input_monitor_state ()
978 if (transport_rolling()) {
980 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
982 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
983 if ((*i)->record_enabled ()) {
984 //cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
985 (*i)->monitor_input (Config->get_monitoring_model() == HardwareMonitoring && !Config->get_auto_input());
989 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
991 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
992 if ((*i)->record_enabled ()) {
993 //cerr << "switching to input = " << !Config->get_auto_input() << __FILE__ << __LINE__ << endl << endl;
994 (*i)->monitor_input (Config->get_monitoring_model() == HardwareMonitoring);
1001 Session::auto_punch_start_changed (Location* location)
1003 replace_event (Event::PunchIn, location->start());
1005 if (get_record_enabled() && Config->get_punch_in()) {
1006 /* capture start has been changed, so save new pending state */
1007 save_state ("", true);
1012 Session::auto_punch_end_changed (Location* location)
1014 nframes_t when_to_stop = location->end();
1015 // when_to_stop += _worst_output_latency + _worst_input_latency;
1016 replace_event (Event::PunchOut, when_to_stop);
1020 Session::auto_punch_changed (Location* location)
1022 nframes_t when_to_stop = location->end();
1024 replace_event (Event::PunchIn, location->start());
1025 //when_to_stop += _worst_output_latency + _worst_input_latency;
1026 replace_event (Event::PunchOut, when_to_stop);
1030 Session::auto_loop_changed (Location* location)
1032 replace_event (Event::AutoLoop, location->end(), location->start());
1034 if (transport_rolling() && play_loop) {
1036 //if (_transport_frame < location->start() || _transport_frame > location->end()) {
1038 if (_transport_frame > location->end()) {
1039 // relocate to beginning of loop
1040 clear_events (Event::LocateRoll);
1042 request_locate (location->start(), true);
1045 else if (Config->get_seamless_loop() && !loop_changing) {
1047 // schedule a locate-roll to refill the diskstreams at the
1048 // previous loop end
1049 loop_changing = true;
1051 if (location->end() > last_loopend) {
1052 clear_events (Event::LocateRoll);
1053 Event *ev = new Event (Event::LocateRoll, Event::Add, last_loopend, last_loopend, 0, true);
1060 last_loopend = location->end();
1065 Session::set_auto_punch_location (Location* location)
1069 if ((existing = _locations.auto_punch_location()) != 0 && existing != location) {
1070 auto_punch_start_changed_connection.disconnect();
1071 auto_punch_end_changed_connection.disconnect();
1072 auto_punch_changed_connection.disconnect();
1073 existing->set_auto_punch (false, this);
1074 remove_event (existing->start(), Event::PunchIn);
1075 clear_events (Event::PunchOut);
1076 auto_punch_location_changed (0);
1081 if (location == 0) {
1085 if (location->end() <= location->start()) {
1086 error << _("Session: you can't use that location for auto punch (start <= end)") << endmsg;
1090 auto_punch_start_changed_connection.disconnect();
1091 auto_punch_end_changed_connection.disconnect();
1092 auto_punch_changed_connection.disconnect();
1094 auto_punch_start_changed_connection = location->start_changed.connect (mem_fun (this, &Session::auto_punch_start_changed));
1095 auto_punch_end_changed_connection = location->end_changed.connect (mem_fun (this, &Session::auto_punch_end_changed));
1096 auto_punch_changed_connection = location->changed.connect (mem_fun (this, &Session::auto_punch_changed));
1098 location->set_auto_punch (true, this);
1099 auto_punch_location_changed (location);
1103 Session::set_auto_loop_location (Location* location)
1107 if ((existing = _locations.auto_loop_location()) != 0 && existing != location) {
1108 auto_loop_start_changed_connection.disconnect();
1109 auto_loop_end_changed_connection.disconnect();
1110 auto_loop_changed_connection.disconnect();
1111 existing->set_auto_loop (false, this);
1112 remove_event (existing->end(), Event::AutoLoop);
1113 auto_loop_location_changed (0);
1118 if (location == 0) {
1122 if (location->end() <= location->start()) {
1123 error << _("Session: you can't use a mark for auto loop") << endmsg;
1127 last_loopend = location->end();
1129 auto_loop_start_changed_connection.disconnect();
1130 auto_loop_end_changed_connection.disconnect();
1131 auto_loop_changed_connection.disconnect();
1133 auto_loop_start_changed_connection = location->start_changed.connect (mem_fun (this, &Session::auto_loop_changed));
1134 auto_loop_end_changed_connection = location->end_changed.connect (mem_fun (this, &Session::auto_loop_changed));
1135 auto_loop_changed_connection = location->changed.connect (mem_fun (this, &Session::auto_loop_changed));
1137 location->set_auto_loop (true, this);
1138 auto_loop_location_changed (location);
1142 Session::locations_added (Location* ignored)
1148 Session::locations_changed ()
1150 _locations.apply (*this, &Session::handle_locations_changed);
1154 Session::handle_locations_changed (Locations::LocationList& locations)
1156 Locations::LocationList::iterator i;
1158 bool set_loop = false;
1159 bool set_punch = false;
1161 for (i = locations.begin(); i != locations.end(); ++i) {
1165 if (location->is_auto_punch()) {
1166 set_auto_punch_location (location);
1169 if (location->is_auto_loop()) {
1170 set_auto_loop_location (location);
1177 set_auto_loop_location (0);
1180 set_auto_punch_location (0);
1187 Session::enable_record ()
1189 /* XXX really atomic compare+swap here */
1190 if (g_atomic_int_get (&_record_status) != Recording) {
1191 g_atomic_int_set (&_record_status, Recording);
1192 _last_record_location = _transport_frame;
1193 send_mmc_in_another_thread (MIDI::MachineControl::cmdRecordStrobe);
1195 if (Config->get_monitoring_model() == HardwareMonitoring && Config->get_auto_input()) {
1196 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1197 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1198 if ((*i)->record_enabled ()) {
1199 (*i)->monitor_input (true);
1204 RecordStateChanged ();
1209 Session::disable_record (bool rt_context, bool force)
1213 if ((rs = (RecordState) g_atomic_int_get (&_record_status)) != Disabled) {
1215 if (!Config->get_latched_record_enable () || force) {
1216 g_atomic_int_set (&_record_status, Disabled);
1218 if (rs == Recording) {
1219 g_atomic_int_set (&_record_status, Enabled);
1223 send_mmc_in_another_thread (MIDI::MachineControl::cmdRecordExit);
1225 if (Config->get_monitoring_model() == HardwareMonitoring && Config->get_auto_input()) {
1226 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1228 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1229 if ((*i)->record_enabled ()) {
1230 (*i)->monitor_input (false);
1235 RecordStateChanged (); /* emit signal */
1238 remove_pending_capture_state ();
1244 Session::step_back_from_record ()
1246 g_atomic_int_set (&_record_status, Enabled);
1248 if (Config->get_monitoring_model() == HardwareMonitoring) {
1249 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1251 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1252 if (Config->get_auto_input() && (*i)->record_enabled ()) {
1253 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
1254 (*i)->monitor_input (false);
1261 Session::maybe_enable_record ()
1263 g_atomic_int_set (&_record_status, Enabled);
1265 /* this function is currently called from somewhere other than an RT thread.
1266 this save_state() call therefore doesn't impact anything.
1269 save_state ("", true);
1271 if (_transport_speed) {
1272 if (!Config->get_punch_in()) {
1276 send_mmc_in_another_thread (MIDI::MachineControl::cmdRecordPause);
1277 RecordStateChanged (); /* EMIT SIGNAL */
1284 Session::audible_frame () const
1290 /* the first of these two possible settings for "offset"
1291 mean that the audible frame is stationary until
1292 audio emerges from the latency compensation
1295 the second means that the audible frame is stationary
1296 until audio would emerge from a physical port
1297 in the absence of any plugin latency compensation
1300 offset = _worst_output_latency;
1302 if (offset > current_block_size) {
1303 offset -= current_block_size;
1305 /* XXX is this correct? if we have no external
1306 physical connections and everything is internal
1307 then surely this is zero? still, how
1308 likely is that anyway?
1310 offset = current_block_size;
1313 if (synced_to_jack()) {
1314 tf = _engine.transport_frame();
1316 tf = _transport_frame;
1319 if (_transport_speed == 0) {
1329 if (!non_realtime_work_pending()) {
1333 /* take latency into account */
1342 Session::set_frame_rate (nframes_t frames_per_second)
1344 /** \fn void Session::set_frame_size(nframes_t)
1345 the AudioEngine object that calls this guarantees
1346 that it will not be called while we are also in
1347 ::process(). Its fine to do things that block
1351 _base_frame_rate = frames_per_second;
1355 Route::set_automation_interval ((jack_nframes_t) ceil ((double) frames_per_second * 0.25));
1357 // XXX we need some equivalent to this, somehow
1358 // SndFileSource::setup_standard_crossfades (frames_per_second);
1362 /* XXX need to reset/reinstantiate all LADSPA plugins */
1366 Session::set_block_size (nframes_t nframes)
1368 /* the AudioEngine guarantees
1369 that it will not be called while we are also in
1370 ::process(). It is therefore fine to do things that block
1375 vector<Sample*>::iterator i;
1378 current_block_size = nframes;
1380 for (np = 0, i = _passthru_buffers.begin(); i != _passthru_buffers.end(); ++i, ++np) {
1384 for (vector<Sample*>::iterator i = _silent_buffers.begin(); i != _silent_buffers.end(); ++i) {
1388 _passthru_buffers.clear ();
1389 _silent_buffers.clear ();
1391 ensure_passthru_buffers (np);
1393 for (vector<Sample*>::iterator i = _send_buffers.begin(); i != _send_buffers.end(); ++i) {
1397 #ifdef NO_POSIX_MEMALIGN
1398 buf = (Sample *) malloc(current_block_size * sizeof(Sample));
1400 posix_memalign((void **)&buf,16,current_block_size * 4);
1404 memset (*i, 0, sizeof (Sample) * current_block_size);
1408 if (_gain_automation_buffer) {
1409 delete [] _gain_automation_buffer;
1411 _gain_automation_buffer = new gain_t[nframes];
1413 allocate_pan_automation_buffers (nframes, _npan_buffers, true);
1415 boost::shared_ptr<RouteList> r = routes.reader ();
1417 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1418 (*i)->set_block_size (nframes);
1421 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1422 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1423 (*i)->set_block_size (nframes);
1426 set_worst_io_latencies ();
1431 Session::set_default_fade (float steepness, float fade_msecs)
1434 nframes_t fade_frames;
1436 /* Don't allow fade of less 1 frame */
1438 if (fade_msecs < (1000.0 * (1.0/_current_frame_rate))) {
1445 fade_frames = (nframes_t) floor (fade_msecs * _current_frame_rate * 0.001);
1449 default_fade_msecs = fade_msecs;
1450 default_fade_steepness = steepness;
1453 // jlc, WTF is this!
1454 Glib::RWLock::ReaderLock lm (route_lock);
1455 AudioRegion::set_default_fade (steepness, fade_frames);
1460 /* XXX have to do this at some point */
1461 /* foreach region using default fade, reset, then
1462 refill_all_diskstream_buffers ();
1467 struct RouteSorter {
1468 bool operator() (boost::shared_ptr<Route> r1, boost::shared_ptr<Route> r2) {
1469 if (r1->fed_by.find (r2) != r1->fed_by.end()) {
1471 } else if (r2->fed_by.find (r1) != r2->fed_by.end()) {
1474 if (r1->fed_by.empty()) {
1475 if (r2->fed_by.empty()) {
1476 /* no ardour-based connections inbound to either route. just use signal order */
1477 return r1->order_key(N_("signal")) < r2->order_key(N_("signal"));
1479 /* r2 has connections, r1 does not; run r1 early */
1483 return r1->order_key(N_("signal")) < r2->order_key(N_("signal"));
1490 trace_terminal (shared_ptr<Route> r1, shared_ptr<Route> rbase)
1492 shared_ptr<Route> r2;
1494 if ((r1->fed_by.find (rbase) != r1->fed_by.end()) && (rbase->fed_by.find (r1) != rbase->fed_by.end())) {
1495 info << string_compose(_("feedback loop setup between %1 and %2"), r1->name(), rbase->name()) << endmsg;
1499 /* make a copy of the existing list of routes that feed r1 */
1501 set<shared_ptr<Route> > existing = r1->fed_by;
1503 /* for each route that feeds r1, recurse, marking it as feeding
1507 for (set<shared_ptr<Route> >::iterator i = existing.begin(); i != existing.end(); ++i) {
1510 /* r2 is a route that feeds r1 which somehow feeds base. mark
1511 base as being fed by r2
1514 rbase->fed_by.insert (r2);
1518 /* 2nd level feedback loop detection. if r1 feeds or is fed by r2,
1522 if ((r1->fed_by.find (r2) != r1->fed_by.end()) && (r2->fed_by.find (r1) != r2->fed_by.end())) {
1526 /* now recurse, so that we can mark base as being fed by
1527 all routes that feed r2
1530 trace_terminal (r2, rbase);
1537 Session::resort_routes ()
1539 /* don't do anything here with signals emitted
1540 by Routes while we are being destroyed.
1543 if (_state_of_the_state & Deletion) {
1550 RCUWriter<RouteList> writer (routes);
1551 shared_ptr<RouteList> r = writer.get_copy ();
1552 resort_routes_using (r);
1553 /* writer goes out of scope and forces update */
1558 Session::resort_routes_using (shared_ptr<RouteList> r)
1560 RouteList::iterator i, j;
1562 for (i = r->begin(); i != r->end(); ++i) {
1564 (*i)->fed_by.clear ();
1566 for (j = r->begin(); j != r->end(); ++j) {
1568 /* although routes can feed themselves, it will
1569 cause an endless recursive descent if we
1570 detect it. so don't bother checking for
1578 if ((*j)->feeds (*i)) {
1579 (*i)->fed_by.insert (*j);
1584 for (i = r->begin(); i != r->end(); ++i) {
1585 trace_terminal (*i, *i);
1591 /* don't leave dangling references to routes in Route::fed_by */
1593 for (i = r->begin(); i != r->end(); ++i) {
1594 (*i)->fed_by.clear ();
1598 cerr << "finished route resort\n";
1600 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1601 cerr << " " << (*i)->name() << " signal order = " << (*i)->order_key ("signal") << endl;
1608 list<boost::shared_ptr<AudioTrack> >
1609 Session::new_audio_track (int input_channels, int output_channels, TrackMode mode, uint32_t how_many)
1611 char track_name[32];
1612 uint32_t track_id = 0;
1614 uint32_t channels_used = 0;
1616 RouteList new_routes;
1617 list<boost::shared_ptr<AudioTrack> > ret;
1618 uint32_t control_id;
1620 /* count existing audio tracks */
1623 shared_ptr<RouteList> r = routes.reader ();
1625 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1626 if (dynamic_cast<AudioTrack*>((*i).get()) != 0) {
1627 if (!(*i)->hidden()) {
1629 channels_used += (*i)->n_inputs();
1635 vector<string> physinputs;
1636 vector<string> physoutputs;
1637 uint32_t nphysical_in;
1638 uint32_t nphysical_out;
1640 _engine.get_physical_outputs (physoutputs);
1641 _engine.get_physical_inputs (physinputs);
1646 /* check for duplicate route names, since we might have pre-existing
1647 routes with this name (e.g. create Audio1, Audio2, delete Audio1,
1648 save, close,restart,add new route - first named route is now
1656 snprintf (track_name, sizeof(track_name), "Audio %" PRIu32, track_id);
1658 if (route_by_name (track_name) == 0) {
1662 } while (track_id < (UINT_MAX-1));
1664 if (Config->get_input_auto_connect() & AutoConnectPhysical) {
1665 nphysical_in = min (n_physical_inputs, (uint32_t) physinputs.size());
1670 if (Config->get_output_auto_connect() & AutoConnectPhysical) {
1671 nphysical_out = min (n_physical_outputs, (uint32_t) physinputs.size());
1677 shared_ptr<AudioTrack> track (new AudioTrack (*this, track_name, Route::Flag (0), mode));
1679 if (track->ensure_io (input_channels, output_channels, false, this)) {
1680 error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
1681 input_channels, output_channels)
1686 for (uint32_t x = 0; x < track->n_inputs() && x < nphysical_in; ++x) {
1690 if (Config->get_input_auto_connect() & AutoConnectPhysical) {
1691 port = physinputs[(channels_used+x)%nphysical_in];
1694 if (port.length() && track->connect_input (track->input (x), port, this)) {
1700 for (uint32_t x = 0; x < track->n_outputs(); ++x) {
1704 if (nphysical_out && (Config->get_output_auto_connect() & AutoConnectPhysical)) {
1705 port = physoutputs[(channels_used+x)%nphysical_out];
1706 } else if (Config->get_output_auto_connect() & AutoConnectMaster) {
1708 port = _master_out->input (x%_master_out->n_inputs())->name();
1712 if (port.length() && track->connect_output (track->output (x), port, this)) {
1717 channels_used += track->n_inputs ();
1720 vector<string> cports;
1721 uint32_t ni = _control_out->n_inputs();
1723 for (n = 0; n < ni; ++n) {
1724 cports.push_back (_control_out->input(n)->name());
1727 track->set_control_outs (cports);
1730 track->DiskstreamChanged.connect (mem_fun (this, &Session::resort_routes));
1731 track->set_remote_control_id (ntracks() + control_id + 1);
1734 new_routes.push_back (track);
1735 ret.push_back (track);
1738 catch (failed_constructor &err) {
1739 error << _("Session: could not create new audio track.") << endmsg;
1740 // XXX should we delete the tracks already created?
1748 if (!new_routes.empty()) {
1749 add_routes (new_routes, false);
1750 save_state (_current_snapshot_name);
1757 Session::new_audio_route (int input_channels, int output_channels, uint32_t how_many)
1760 uint32_t bus_id = 1;
1765 /* count existing audio busses */
1768 shared_ptr<RouteList> r = routes.reader ();
1770 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1771 if (dynamic_cast<AudioTrack*>((*i).get()) == 0) {
1772 if (!(*i)->hidden()) {
1779 vector<string> physinputs;
1780 vector<string> physoutputs;
1782 _engine.get_physical_outputs (physoutputs);
1783 _engine.get_physical_inputs (physinputs);
1790 snprintf (bus_name, sizeof(bus_name), "Bus %" PRIu32, bus_id);
1792 if (route_by_name (bus_name) == 0) {
1796 } while (bus_id < (UINT_MAX-1));
1799 shared_ptr<Route> bus (new Route (*this, bus_name, -1, -1, -1, -1, Route::Flag(0), DataType::AUDIO));
1801 if (bus->ensure_io (input_channels, output_channels, false, this)) {
1802 error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
1803 input_channels, output_channels)
1807 for (uint32_t x = 0; n_physical_inputs && x < bus->n_inputs(); ++x) {
1811 if (Config->get_input_auto_connect() & AutoConnectPhysical) {
1812 port = physinputs[((n+x)%n_physical_inputs)];
1815 if (port.length() && bus->connect_input (bus->input (x), port, this)) {
1820 for (uint32_t x = 0; n_physical_outputs && x < bus->n_outputs(); ++x) {
1824 if (Config->get_output_auto_connect() & AutoConnectPhysical) {
1825 port = physoutputs[((n+x)%n_physical_outputs)];
1826 } else if (Config->get_output_auto_connect() & AutoConnectMaster) {
1828 port = _master_out->input (x%_master_out->n_inputs())->name();
1832 if (port.length() && bus->connect_output (bus->output (x), port, this)) {
1838 vector<string> cports;
1839 uint32_t ni = _control_out->n_inputs();
1841 for (uint32_t n = 0; n < ni; ++n) {
1842 cports.push_back (_control_out->input(n)->name());
1844 bus->set_control_outs (cports);
1847 ret.push_back (bus);
1851 catch (failed_constructor &err) {
1852 error << _("Session: could not create new audio route.") << endmsg;
1861 add_routes (ret, false);
1862 save_state (_current_snapshot_name);
1870 Session::add_routes (RouteList& new_routes, bool save)
1873 RCUWriter<RouteList> writer (routes);
1874 shared_ptr<RouteList> r = writer.get_copy ();
1875 r->insert (r->end(), new_routes.begin(), new_routes.end());
1876 resort_routes_using (r);
1879 for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) {
1881 boost::weak_ptr<Route> wpr (*x);
1883 (*x)->solo_changed.connect (sigc::bind (mem_fun (*this, &Session::route_solo_changed), wpr));
1884 (*x)->mute_changed.connect (mem_fun (*this, &Session::route_mute_changed));
1885 (*x)->output_changed.connect (mem_fun (*this, &Session::set_worst_io_latencies_x));
1886 (*x)->redirects_changed.connect (mem_fun (*this, &Session::update_latency_compensation_proxy));
1888 if ((*x)->master()) {
1892 if ((*x)->control()) {
1893 _control_out = (*x);
1900 save_state (_current_snapshot_name);
1903 RouteAdded (new_routes); /* EMIT SIGNAL */
1907 Session::add_diskstream (boost::shared_ptr<Diskstream> dstream)
1909 /* need to do this in case we're rolling at the time, to prevent false underruns */
1910 dstream->do_refill_with_alloc();
1913 RCUWriter<DiskstreamList> writer (diskstreams);
1914 boost::shared_ptr<DiskstreamList> ds = writer.get_copy();
1915 ds->push_back (dstream);
1918 dstream->set_block_size (current_block_size);
1920 dstream->PlaylistChanged.connect (sigc::bind (mem_fun (*this, &Session::diskstream_playlist_changed), dstream));
1921 /* this will connect to future changes, and check the current length */
1922 diskstream_playlist_changed (dstream);
1924 dstream->prepare ();
1928 Session::remove_route (shared_ptr<Route> route)
1931 RCUWriter<RouteList> writer (routes);
1932 shared_ptr<RouteList> rs = writer.get_copy ();
1936 /* deleting the master out seems like a dumb
1937 idea, but its more of a UI policy issue
1941 if (route == _master_out) {
1942 _master_out = shared_ptr<Route> ();
1945 if (route == _control_out) {
1946 _control_out = shared_ptr<Route> ();
1948 /* cancel control outs for all routes */
1950 vector<string> empty;
1952 for (RouteList::iterator r = rs->begin(); r != rs->end(); ++r) {
1953 (*r)->set_control_outs (empty);
1957 update_route_solo_state ();
1959 /* writer goes out of scope, forces route list update */
1962 // FIXME: audio specific
1964 boost::shared_ptr<AudioDiskstream> ds;
1966 if ((at = dynamic_cast<AudioTrack*>(route.get())) != 0) {
1967 ds = at->audio_diskstream();
1973 RCUWriter<DiskstreamList> dsl (diskstreams);
1974 boost::shared_ptr<DiskstreamList> d = dsl.get_copy();
1979 find_current_end ();
1981 update_latency_compensation (false, false);
1984 // We need to disconnect the routes inputs and outputs
1985 route->disconnect_inputs(NULL);
1986 route->disconnect_outputs(NULL);
1988 /* get rid of it from the dead wood collection in the route list manager */
1990 /* XXX i think this is unsafe as it currently stands, but i am not sure. (pd, october 2nd, 2006) */
1994 /* try to cause everyone to drop their references */
1996 route->drop_references ();
1998 /* save the new state of the world */
2000 if (save_state (_current_snapshot_name)) {
2001 save_history (_current_snapshot_name);
2006 Session::route_mute_changed (void* src)
2012 Session::route_solo_changed (void* src, boost::weak_ptr<Route> wpr)
2014 if (solo_update_disabled) {
2020 boost::shared_ptr<Route> route = wpr.lock ();
2023 /* should not happen */
2024 error << string_compose (_("programming error: %1"), X_("invalid route weak ptr passed to route_solo_changed")) << endmsg;
2028 is_track = (boost::dynamic_pointer_cast<AudioTrack>(route) != 0);
2030 shared_ptr<RouteList> r = routes.reader ();
2032 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2034 /* soloing a track mutes all other tracks, soloing a bus mutes all other busses */
2038 /* don't mess with busses */
2040 if (dynamic_cast<AudioTrack*>((*i).get()) == 0) {
2046 /* don't mess with tracks */
2048 if (dynamic_cast<AudioTrack*>((*i).get()) != 0) {
2053 if ((*i) != route &&
2054 ((*i)->mix_group () == 0 ||
2055 (*i)->mix_group () != route->mix_group () ||
2056 !route->mix_group ()->is_active())) {
2058 if ((*i)->soloed()) {
2060 /* if its already soloed, and solo latching is enabled,
2061 then leave it as it is.
2064 if (Config->get_solo_latched()) {
2071 solo_update_disabled = true;
2072 (*i)->set_solo (false, src);
2073 solo_update_disabled = false;
2077 bool something_soloed = false;
2078 bool same_thing_soloed = false;
2079 bool signal = false;
2081 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2082 if ((*i)->soloed()) {
2083 something_soloed = true;
2084 if (dynamic_cast<AudioTrack*>((*i).get())) {
2086 same_thing_soloed = true;
2091 same_thing_soloed = true;
2099 if (something_soloed != currently_soloing) {
2101 currently_soloing = something_soloed;
2104 modify_solo_mute (is_track, same_thing_soloed);
2107 SoloActive (currently_soloing);
2114 Session::update_route_solo_state ()
2117 bool is_track = false;
2118 bool signal = false;
2120 /* caller must hold RouteLock */
2122 /* this is where we actually implement solo by changing
2123 the solo mute setting of each track.
2126 shared_ptr<RouteList> r = routes.reader ();
2128 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2129 if ((*i)->soloed()) {
2131 if (dynamic_cast<AudioTrack*>((*i).get())) {
2138 if (mute != currently_soloing) {
2140 currently_soloing = mute;
2143 if (!is_track && !mute) {
2145 /* nothing is soloed */
2147 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2148 (*i)->set_solo_mute (false);
2158 modify_solo_mute (is_track, mute);
2161 SoloActive (currently_soloing);
2166 Session::modify_solo_mute (bool is_track, bool mute)
2168 shared_ptr<RouteList> r = routes.reader ();
2170 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2174 /* only alter track solo mute */
2176 if (dynamic_cast<AudioTrack*>((*i).get())) {
2177 if ((*i)->soloed()) {
2178 (*i)->set_solo_mute (!mute);
2180 (*i)->set_solo_mute (mute);
2186 /* only alter bus solo mute */
2188 if (!dynamic_cast<AudioTrack*>((*i).get())) {
2190 if ((*i)->soloed()) {
2192 (*i)->set_solo_mute (false);
2196 /* don't mute master or control outs
2197 in response to another bus solo
2200 if ((*i) != _master_out &&
2201 (*i) != _control_out) {
2202 (*i)->set_solo_mute (mute);
2213 Session::catch_up_on_solo ()
2215 /* this is called after set_state() to catch the full solo
2216 state, which can't be correctly determined on a per-route
2217 basis, but needs the global overview that only the session
2220 update_route_solo_state();
2224 Session::route_by_name (string name)
2226 shared_ptr<RouteList> r = routes.reader ();
2228 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2229 if ((*i)->name() == name) {
2234 return shared_ptr<Route> ((Route*) 0);
2238 Session::route_by_id (PBD::ID id)
2240 shared_ptr<RouteList> r = routes.reader ();
2242 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2243 if ((*i)->id() == id) {
2248 return shared_ptr<Route> ((Route*) 0);
2252 Session::route_by_remote_id (uint32_t id)
2254 shared_ptr<RouteList> r = routes.reader ();
2256 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2257 if ((*i)->remote_control_id() == id) {
2262 return shared_ptr<Route> ((Route*) 0);
2266 Session::find_current_end ()
2268 if (_state_of_the_state & Loading) {
2272 nframes_t max = get_maximum_extent ();
2274 if (max > end_location->end()) {
2275 end_location->set_end (max);
2277 DurationChanged(); /* EMIT SIGNAL */
2282 Session::get_maximum_extent () const
2287 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
2289 for (DiskstreamList::const_iterator i = dsl->begin(); i != dsl->end(); ++i) {
2290 boost::shared_ptr<Playlist> pl = (*i)->playlist();
2291 if ((me = pl->get_maximum_extent()) > max) {
2299 boost::shared_ptr<Diskstream>
2300 Session::diskstream_by_name (string name)
2302 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
2304 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
2305 if ((*i)->name() == name) {
2310 return boost::shared_ptr<Diskstream>((Diskstream*) 0);
2313 boost::shared_ptr<Diskstream>
2314 Session::diskstream_by_id (const PBD::ID& id)
2316 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
2318 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
2319 if ((*i)->id() == id) {
2324 return boost::shared_ptr<Diskstream>((Diskstream*) 0);
2327 /* AudioRegion management */
2330 Session::new_region_name (string old)
2332 string::size_type last_period;
2334 string::size_type len = old.length() + 64;
2337 if ((last_period = old.find_last_of ('.')) == string::npos) {
2339 /* no period present - add one explicitly */
2342 last_period = old.length() - 1;
2347 number = atoi (old.substr (last_period+1).c_str());
2351 while (number < (UINT_MAX-1)) {
2353 AudioRegionList::const_iterator i;
2358 snprintf (buf, len, "%s%" PRIu32, old.substr (0, last_period + 1).c_str(), number);
2361 for (i = audio_regions.begin(); i != audio_regions.end(); ++i) {
2362 if (i->second->name() == sbuf) {
2367 if (i == audio_regions.end()) {
2372 if (number != (UINT_MAX-1)) {
2376 error << string_compose (_("cannot create new name for region \"%1\""), old) << endmsg;
2381 Session::region_name (string& result, string base, bool newlevel) const
2388 Glib::Mutex::Lock lm (region_lock);
2390 snprintf (buf, sizeof (buf), "%d", (int)audio_regions.size() + 1);
2398 /* XXX this is going to be slow. optimize me later */
2403 string::size_type pos;
2405 pos = base.find_last_of ('.');
2407 /* pos may be npos, but then we just use entire base */
2409 subbase = base.substr (0, pos);
2413 bool name_taken = true;
2416 Glib::Mutex::Lock lm (region_lock);
2418 for (int n = 1; n < 5000; ++n) {
2421 snprintf (buf, sizeof (buf), ".%d", n);
2426 for (AudioRegionList::const_iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) {
2427 if (i->second->name() == result) {
2440 fatal << string_compose(_("too many regions with names like %1"), base) << endmsg;
2448 Session::add_region (boost::shared_ptr<Region> region)
2450 boost::shared_ptr<AudioRegion> ar;
2451 boost::shared_ptr<AudioRegion> oar;
2455 Glib::Mutex::Lock lm (region_lock);
2457 if ((ar = boost::dynamic_pointer_cast<AudioRegion> (region)) != 0) {
2459 AudioRegionList::iterator x;
2461 for (x = audio_regions.begin(); x != audio_regions.end(); ++x) {
2463 oar = boost::dynamic_pointer_cast<AudioRegion> (x->second);
2465 if (ar->region_list_equivalent (oar)) {
2470 if (x == audio_regions.end()) {
2472 pair<AudioRegionList::key_type,AudioRegionList::mapped_type> entry;
2474 entry.first = region->id();
2477 pair<AudioRegionList::iterator,bool> x = audio_regions.insert (entry);
2489 fatal << _("programming error: ")
2490 << X_("unknown region type passed to Session::add_region()")
2497 /* mark dirty because something has changed even if we didn't
2498 add the region to the region list.
2504 region->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_region), boost::weak_ptr<Region>(region)));
2505 region->StateChanged.connect (sigc::bind (mem_fun (*this, &Session::region_changed), boost::weak_ptr<Region>(region)));
2506 AudioRegionAdded (ar); /* EMIT SIGNAL */
2511 Session::region_changed (Change what_changed, boost::weak_ptr<Region> weak_region)
2513 boost::shared_ptr<Region> region (weak_region.lock ());
2519 if (what_changed & Region::HiddenChanged) {
2520 /* relay hidden changes */
2521 RegionHiddenChange (region);
2526 Session::remove_region (boost::weak_ptr<Region> weak_region)
2528 AudioRegionList::iterator i;
2529 boost::shared_ptr<Region> region (weak_region.lock ());
2535 boost::shared_ptr<AudioRegion> ar;
2536 bool removed = false;
2539 Glib::Mutex::Lock lm (region_lock);
2541 if ((ar = boost::dynamic_pointer_cast<AudioRegion> (region)) != 0) {
2542 if ((i = audio_regions.find (region->id())) != audio_regions.end()) {
2543 audio_regions.erase (i);
2549 fatal << _("programming error: ")
2550 << X_("unknown region type passed to Session::remove_region()")
2556 /* mark dirty because something has changed even if we didn't
2557 remove the region from the region list.
2563 AudioRegionRemoved (ar); /* EMIT SIGNAL */
2567 boost::shared_ptr<AudioRegion>
2568 Session::find_whole_file_parent (boost::shared_ptr<AudioRegion const> child)
2570 AudioRegionList::iterator i;
2571 boost::shared_ptr<AudioRegion> region;
2572 Glib::Mutex::Lock lm (region_lock);
2574 for (i = audio_regions.begin(); i != audio_regions.end(); ++i) {
2578 if (region->whole_file()) {
2580 if (child->source_equivalent (region)) {
2586 return boost::shared_ptr<AudioRegion> ();
2590 Session::find_equivalent_playlist_regions (boost::shared_ptr<Region> region, vector<boost::shared_ptr<Region> >& result)
2592 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i)
2593 (*i)->get_region_list_equivalent_regions (region, result);
2597 Session::destroy_region (boost::shared_ptr<Region> region)
2599 vector<boost::shared_ptr<Source> > srcs;
2602 boost::shared_ptr<AudioRegion> aregion;
2604 if ((aregion = boost::dynamic_pointer_cast<AudioRegion> (region)) == 0) {
2608 if (aregion->playlist()) {
2609 aregion->playlist()->destroy_region (region);
2612 for (uint32_t n = 0; n < aregion->n_channels(); ++n) {
2613 srcs.push_back (aregion->source (n));
2617 region->drop_references ();
2619 for (vector<boost::shared_ptr<Source> >::iterator i = srcs.begin(); i != srcs.end(); ++i) {
2621 if (!(*i)->used()) {
2622 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*i);
2625 (afs)->mark_for_remove ();
2628 (*i)->drop_references ();
2630 cerr << "source was not used by any playlist\n";
2638 Session::destroy_regions (list<boost::shared_ptr<Region> > regions)
2640 for (list<boost::shared_ptr<Region> >::iterator i = regions.begin(); i != regions.end(); ++i) {
2641 destroy_region (*i);
2647 Session::remove_last_capture ()
2649 list<boost::shared_ptr<Region> > r;
2651 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
2653 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
2654 list<boost::shared_ptr<Region> >& l = (*i)->last_capture_regions();
2657 r.insert (r.end(), l.begin(), l.end());
2662 destroy_regions (r);
2667 Session::remove_region_from_region_list (boost::shared_ptr<Region> r)
2673 /* Source Management */
2676 Session::add_source (boost::shared_ptr<Source> source)
2678 boost::shared_ptr<AudioFileSource> afs;
2680 if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(source)) != 0) {
2682 pair<AudioSourceList::key_type, AudioSourceList::mapped_type> entry;
2683 pair<AudioSourceList::iterator,bool> result;
2685 entry.first = source->id();
2689 Glib::Mutex::Lock lm (audio_source_lock);
2690 result = audio_sources.insert (entry);
2693 if (result.second) {
2694 source->GoingAway.connect (sigc::bind (mem_fun (this, &Session::remove_source), boost::weak_ptr<Source> (source)));
2702 Session::remove_source (boost::weak_ptr<Source> src)
2704 AudioSourceList::iterator i;
2705 boost::shared_ptr<Source> source = src.lock();
2712 Glib::Mutex::Lock lm (audio_source_lock);
2714 if ((i = audio_sources.find (source->id())) != audio_sources.end()) {
2715 audio_sources.erase (i);
2719 if (!_state_of_the_state & InCleanup) {
2721 /* save state so we don't end up with a session file
2722 referring to non-existent sources.
2725 save_state (_current_snapshot_name);
2729 boost::shared_ptr<Source>
2730 Session::source_by_id (const PBD::ID& id)
2732 Glib::Mutex::Lock lm (audio_source_lock);
2733 AudioSourceList::iterator i;
2734 boost::shared_ptr<Source> source;
2736 if ((i = audio_sources.find (id)) != audio_sources.end()) {
2740 /* XXX search MIDI or other searches here */
2746 Session::peak_path_from_audio_path (string audio_path) const
2751 res += PBD::basename_nosuffix (audio_path);
2758 Session::change_audio_path_by_name (string path, string oldname, string newname, bool destructive)
2761 string old_basename = PBD::basename_nosuffix (oldname);
2762 string new_legalized = legalize_for_path (newname);
2764 /* note: we know (or assume) the old path is already valid */
2768 /* destructive file sources have a name of the form:
2770 /path/to/Tnnnn-NAME(%[LR])?.wav
2772 the task here is to replace NAME with the new name.
2775 /* find last slash */
2779 string::size_type slash;
2780 string::size_type dash;
2782 if ((slash = path.find_last_of ('/')) == string::npos) {
2786 dir = path.substr (0, slash+1);
2788 /* '-' is not a legal character for the NAME part of the path */
2790 if ((dash = path.find_last_of ('-')) == string::npos) {
2794 prefix = path.substr (slash+1, dash-(slash+1));
2799 path += new_legalized;
2800 path += ".wav"; /* XXX gag me with a spoon */
2804 /* non-destructive file sources have a name of the form:
2806 /path/to/NAME-nnnnn(%[LR])?.wav
2808 the task here is to replace NAME with the new name.
2813 string::size_type slash;
2814 string::size_type dash;
2815 string::size_type postfix;
2817 /* find last slash */
2819 if ((slash = path.find_last_of ('/')) == string::npos) {
2823 dir = path.substr (0, slash+1);
2825 /* '-' is not a legal character for the NAME part of the path */
2827 if ((dash = path.find_last_of ('-')) == string::npos) {
2831 suffix = path.substr (dash+1);
2833 // Suffix is now everything after the dash. Now we need to eliminate
2834 // the nnnnn part, which is done by either finding a '%' or a '.'
2836 postfix = suffix.find_last_of ("%");
2837 if (postfix == string::npos) {
2838 postfix = suffix.find_last_of ('.');
2841 if (postfix != string::npos) {
2842 suffix = suffix.substr (postfix);
2844 error << "Logic error in Session::change_audio_path_by_name(), please report to the developers" << endl;
2848 const uint32_t limit = 10000;
2849 char buf[PATH_MAX+1];
2851 for (uint32_t cnt = 1; cnt <= limit; ++cnt) {
2853 snprintf (buf, sizeof(buf), "%s%s-%u%s", dir.c_str(), newname.c_str(), cnt, suffix.c_str());
2855 if (access (buf, F_OK) != 0) {
2863 error << "FATAL ERROR! Could not find a " << endl;
2872 Session::audio_path_from_name (string name, uint32_t nchan, uint32_t chan, bool destructive)
2876 char buf[PATH_MAX+1];
2877 const uint32_t limit = 10000;
2881 legalized = legalize_for_path (name);
2883 /* find a "version" of the file name that doesn't exist in
2884 any of the possible directories.
2887 for (cnt = (destructive ? ++destructive_index : 1); cnt <= limit; ++cnt) {
2889 vector<space_and_path>::iterator i;
2890 uint32_t existing = 0;
2892 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2896 spath += sound_dir (false);
2900 snprintf (buf, sizeof(buf), "%s/T%04d-%s.wav", spath.c_str(), cnt, legalized.c_str());
2901 } else if (nchan == 2) {
2903 snprintf (buf, sizeof(buf), "%s/T%04d-%s%%L.wav", spath.c_str(), cnt, legalized.c_str());
2905 snprintf (buf, sizeof(buf), "%s/T%04d-%s%%R.wav", spath.c_str(), cnt, legalized.c_str());
2907 } else if (nchan < 26) {
2908 snprintf (buf, sizeof(buf), "%s/T%04d-%s%%%c.wav", spath.c_str(), cnt, legalized.c_str(), 'a' + chan);
2910 snprintf (buf, sizeof(buf), "%s/T%04d-%s.wav", spath.c_str(), cnt, legalized.c_str());
2919 snprintf (buf, sizeof(buf), "%s-%u.wav", spath.c_str(), cnt);
2920 } else if (nchan == 2) {
2922 snprintf (buf, sizeof(buf), "%s-%u%%L.wav", spath.c_str(), cnt);
2924 snprintf (buf, sizeof(buf), "%s-%u%%R.wav", spath.c_str(), cnt);
2926 } else if (nchan < 26) {
2927 snprintf (buf, sizeof(buf), "%s-%u%%%c.wav", spath.c_str(), cnt, 'a' + chan);
2929 snprintf (buf, sizeof(buf), "%s-%u.wav", spath.c_str(), cnt);
2933 if (g_file_test (buf, G_FILE_TEST_EXISTS)) {
2939 if (existing == 0) {
2944 error << string_compose(_("There are already %1 recordings for %2, which I consider too many."), limit, name) << endmsg;
2946 throw failed_constructor();
2950 /* we now have a unique name for the file, but figure out where to
2956 spath = discover_best_sound_dir ();
2959 string::size_type pos = foo.find_last_of ('/');
2961 if (pos == string::npos) {
2964 spath += foo.substr (pos + 1);
2970 boost::shared_ptr<AudioFileSource>
2971 Session::create_audio_source_for_session (AudioDiskstream& ds, uint32_t chan, bool destructive)
2973 string spath = audio_path_from_name (ds.name(), ds.n_channels(), chan, destructive);
2974 return boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (*this, spath, destructive, frame_rate()));
2977 /* Playlist management */
2979 boost::shared_ptr<Playlist>
2980 Session::playlist_by_name (string name)
2982 Glib::Mutex::Lock lm (playlist_lock);
2983 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
2984 if ((*i)->name() == name) {
2988 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
2989 if ((*i)->name() == name) {
2994 return boost::shared_ptr<Playlist>();
2998 Session::add_playlist (boost::shared_ptr<Playlist> playlist)
3000 if (playlist->hidden()) {
3005 Glib::Mutex::Lock lm (playlist_lock);
3006 if (find (playlists.begin(), playlists.end(), playlist) == playlists.end()) {
3007 playlists.insert (playlists.begin(), playlist);
3008 playlist->InUse.connect (sigc::bind (mem_fun (*this, &Session::track_playlist), boost::weak_ptr<Playlist>(playlist)));
3009 playlist->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_playlist), boost::weak_ptr<Playlist>(playlist)));
3015 PlaylistAdded (playlist); /* EMIT SIGNAL */
3019 Session::get_playlists (vector<boost::shared_ptr<Playlist> >& s)
3022 Glib::Mutex::Lock lm (playlist_lock);
3023 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
3026 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
3033 Session::track_playlist (bool inuse, boost::weak_ptr<Playlist> wpl)
3035 boost::shared_ptr<Playlist> pl(wpl.lock());
3041 PlaylistList::iterator x;
3044 /* its not supposed to be visible */
3049 Glib::Mutex::Lock lm (playlist_lock);
3053 unused_playlists.insert (pl);
3055 if ((x = playlists.find (pl)) != playlists.end()) {
3056 playlists.erase (x);
3062 playlists.insert (pl);
3064 if ((x = unused_playlists.find (pl)) != unused_playlists.end()) {
3065 unused_playlists.erase (x);
3072 Session::remove_playlist (boost::weak_ptr<Playlist> weak_playlist)
3074 if (_state_of_the_state & Deletion) {
3078 boost::shared_ptr<Playlist> playlist (weak_playlist.lock());
3085 Glib::Mutex::Lock lm (playlist_lock);
3087 PlaylistList::iterator i;
3089 i = find (playlists.begin(), playlists.end(), playlist);
3090 if (i != playlists.end()) {
3091 playlists.erase (i);
3094 i = find (unused_playlists.begin(), unused_playlists.end(), playlist);
3095 if (i != unused_playlists.end()) {
3096 unused_playlists.erase (i);
3103 PlaylistRemoved (playlist); /* EMIT SIGNAL */
3107 Session::set_audition (boost::shared_ptr<Region> r)
3109 pending_audition_region = r;
3110 post_transport_work = PostTransportWork (post_transport_work | PostTransportAudition);
3111 schedule_butler_transport_work ();
3115 Session::audition_playlist ()
3117 Event* ev = new Event (Event::Audition, Event::Add, Event::Immediate, 0, 0.0);
3118 ev->region.reset ();
3123 Session::non_realtime_set_audition ()
3125 if (!pending_audition_region) {
3126 auditioner->audition_current_playlist ();
3128 auditioner->audition_region (pending_audition_region);
3129 pending_audition_region.reset ();
3131 AuditionActive (true); /* EMIT SIGNAL */
3135 Session::audition_region (boost::shared_ptr<Region> r)
3137 Event* ev = new Event (Event::Audition, Event::Add, Event::Immediate, 0, 0.0);
3143 Session::cancel_audition ()
3145 if (auditioner->active()) {
3146 auditioner->cancel_audition ();
3147 AuditionActive (false); /* EMIT SIGNAL */
3152 Session::RoutePublicOrderSorter::operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b)
3154 return a->order_key(N_("signal")) < b->order_key(N_("signal"));
3158 Session::remove_empty_sounds ()
3160 PathScanner scanner;
3162 vector<string *>* possible_audiofiles = scanner (sound_dir(), "\\.(wav|aiff|caf|w64)$", false, true);
3164 Glib::Mutex::Lock lm (audio_source_lock);
3166 regex_t compiled_tape_track_pattern;
3169 if ((err = regcomp (&compiled_tape_track_pattern, "/T[0-9][0-9][0-9][0-9]-", REG_EXTENDED|REG_NOSUB))) {
3173 regerror (err, &compiled_tape_track_pattern, msg, sizeof (msg));
3175 error << string_compose (_("Cannot compile tape track regexp for use (%1)"), msg) << endmsg;
3179 for (vector<string *>::iterator i = possible_audiofiles->begin(); i != possible_audiofiles->end(); ++i) {
3181 /* never remove files that appear to be a tape track */
3183 if (regexec (&compiled_tape_track_pattern, (*i)->c_str(), 0, 0, 0) == 0) {
3188 if (AudioFileSource::is_empty (*this, *(*i))) {
3190 unlink ((*i)->c_str());
3192 string peak_path = peak_path_from_audio_path (**i);
3193 unlink (peak_path.c_str());
3199 delete possible_audiofiles;
3203 Session::is_auditioning () const
3205 /* can be called before we have an auditioner object */
3207 return auditioner->active();
3214 Session::set_all_solo (bool yn)
3216 shared_ptr<RouteList> r = routes.reader ();
3218 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
3219 if (!(*i)->hidden()) {
3220 (*i)->set_solo (yn, this);
3228 Session::set_all_mute (bool yn)
3230 shared_ptr<RouteList> r = routes.reader ();
3232 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
3233 if (!(*i)->hidden()) {
3234 (*i)->set_mute (yn, this);
3242 Session::n_diskstreams () const
3246 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
3248 for (DiskstreamList::const_iterator i = dsl->begin(); i != dsl->end(); ++i) {
3249 if (!(*i)->hidden()) {
3257 Session::graph_reordered ()
3259 /* don't do this stuff if we are setting up connections
3260 from a set_state() call.
3263 if (_state_of_the_state & InitialConnecting) {
3267 /* every track/bus asked for this to be handled but it was deferred because
3268 we were connecting. do it now.
3271 request_input_change_handling ();
3275 /* force all diskstreams to update their capture offset values to
3276 reflect any changes in latencies within the graph.
3279 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
3281 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
3282 (*i)->set_capture_offset ();
3287 Session::record_disenable_all ()
3289 record_enable_change_all (false);
3293 Session::record_enable_all ()
3295 record_enable_change_all (true);
3299 Session::record_enable_change_all (bool yn)
3301 shared_ptr<RouteList> r = routes.reader ();
3303 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
3306 if ((at = dynamic_cast<AudioTrack*>((*i).get())) != 0) {
3307 at->set_record_enable (yn, this);
3311 /* since we don't keep rec-enable state, don't mark session dirty */
3315 Session::add_redirect (Redirect* redirect)
3319 PortInsert* port_insert;
3320 PluginInsert* plugin_insert;
3322 if ((insert = dynamic_cast<Insert *> (redirect)) != 0) {
3323 if ((port_insert = dynamic_cast<PortInsert *> (insert)) != 0) {
3324 _port_inserts.insert (_port_inserts.begin(), port_insert);
3325 } else if ((plugin_insert = dynamic_cast<PluginInsert *> (insert)) != 0) {
3326 _plugin_inserts.insert (_plugin_inserts.begin(), plugin_insert);
3328 fatal << _("programming error: unknown type of Insert created!") << endmsg;
3331 } else if ((send = dynamic_cast<Send *> (redirect)) != 0) {
3332 _sends.insert (_sends.begin(), send);
3334 fatal << _("programming error: unknown type of Redirect created!") << endmsg;
3338 redirect->GoingAway.connect (sigc::bind (mem_fun (*this, &Session::remove_redirect), redirect));
3344 Session::remove_redirect (Redirect* redirect)
3348 PortInsert* port_insert;
3349 PluginInsert* plugin_insert;
3351 if ((insert = dynamic_cast<Insert *> (redirect)) != 0) {
3352 if ((port_insert = dynamic_cast<PortInsert *> (insert)) != 0) {
3353 list<PortInsert*>::iterator x = find (_port_inserts.begin(), _port_inserts.end(), port_insert);
3354 if (x != _port_inserts.end()) {
3355 insert_bitset[port_insert->bit_slot()] = false;
3356 _port_inserts.erase (x);
3358 } else if ((plugin_insert = dynamic_cast<PluginInsert *> (insert)) != 0) {
3359 _plugin_inserts.remove (plugin_insert);
3361 fatal << string_compose (_("programming error: %1"),
3362 X_("unknown type of Insert deleted!"))
3366 } else if ((send = dynamic_cast<Send *> (redirect)) != 0) {
3367 list<Send*>::iterator x = find (_sends.begin(), _sends.end(), send);
3368 if (x != _sends.end()) {
3369 send_bitset[send->bit_slot()] = false;
3373 fatal << _("programming error: unknown type of Redirect deleted!") << endmsg;
3381 Session::available_capture_duration ()
3383 float sample_bytes_on_disk;
3385 switch (Config->get_native_file_data_format()) {
3387 sample_bytes_on_disk = 4;
3391 sample_bytes_on_disk = 3;
3395 /* impossible, but keep some gcc versions happy */
3396 fatal << string_compose (_("programming error: %1"),
3397 X_("illegal native file data format"))
3402 double scale = 4096.0 / sample_bytes_on_disk;
3404 if (_total_free_4k_blocks * scale > (double) max_frames) {
3408 return (nframes_t) floor (_total_free_4k_blocks * scale);
3412 Session::add_connection (ARDOUR::Connection* connection)
3415 Glib::Mutex::Lock guard (connection_lock);
3416 _connections.push_back (connection);
3419 ConnectionAdded (connection); /* EMIT SIGNAL */
3425 Session::remove_connection (ARDOUR::Connection* connection)
3427 bool removed = false;
3430 Glib::Mutex::Lock guard (connection_lock);
3431 ConnectionList::iterator i = find (_connections.begin(), _connections.end(), connection);
3433 if (i != _connections.end()) {
3434 _connections.erase (i);
3440 ConnectionRemoved (connection); /* EMIT SIGNAL */
3446 ARDOUR::Connection *
3447 Session::connection_by_name (string name) const
3449 Glib::Mutex::Lock lm (connection_lock);
3451 for (ConnectionList::const_iterator i = _connections.begin(); i != _connections.end(); ++i) {
3452 if ((*i)->name() == name) {
3461 Session::tempo_map_changed (Change ignored)
3468 Session::ensure_passthru_buffers (uint32_t howmany)
3470 while (howmany > _passthru_buffers.size()) {
3472 #ifdef NO_POSIX_MEMALIGN
3473 p = (Sample *) malloc(current_block_size * sizeof(Sample));
3475 posix_memalign((void **)&p,16,current_block_size * 4);
3477 _passthru_buffers.push_back (p);
3481 #ifdef NO_POSIX_MEMALIGN
3482 p = (Sample *) malloc(current_block_size * sizeof(Sample));
3484 posix_memalign((void **)&p,16,current_block_size * 4);
3486 memset (p, 0, sizeof (Sample) * current_block_size);
3487 _silent_buffers.push_back (p);
3491 #ifdef NO_POSIX_MEMALIGN
3492 p = (Sample *) malloc(current_block_size * sizeof(Sample));
3494 posix_memalign((void **)&p,16,current_block_size * 4);
3496 memset (p, 0, sizeof (Sample) * current_block_size);
3497 _send_buffers.push_back (p);
3500 allocate_pan_automation_buffers (current_block_size, howmany, false);
3504 Session::next_insert_id ()
3506 /* this doesn't really loop forever. just think about it */
3509 for (boost::dynamic_bitset<uint32_t>::size_type n = 0; n < insert_bitset.size(); ++n) {
3510 if (!insert_bitset[n]) {
3511 insert_bitset[n] = true;
3512 cerr << "Returning " << n << " as insert ID\n";
3518 /* none available, so resize and try again */
3520 insert_bitset.resize (insert_bitset.size() + 16, false);
3525 Session::next_send_id ()
3527 /* this doesn't really loop forever. just think about it */
3530 for (boost::dynamic_bitset<uint32_t>::size_type n = 0; n < send_bitset.size(); ++n) {
3531 if (!send_bitset[n]) {
3532 send_bitset[n] = true;
3533 cerr << "Returning " << n << " as send ID\n";
3539 /* none available, so resize and try again */
3541 send_bitset.resize (send_bitset.size() + 16, false);
3546 Session::mark_send_id (uint32_t id)
3548 if (id >= send_bitset.size()) {
3549 send_bitset.resize (id+16, false);
3551 if (send_bitset[id]) {
3552 warning << string_compose (_("send ID %1 appears to be in use already"), id) << endmsg;
3554 send_bitset[id] = true;
3558 Session::mark_insert_id (uint32_t id)
3560 if (id >= insert_bitset.size()) {
3561 insert_bitset.resize (id+16, false);
3563 if (insert_bitset[id]) {
3564 warning << string_compose (_("insert ID %1 appears to be in use already"), id) << endmsg;
3566 insert_bitset[id] = true;
3569 /* Named Selection management */
3572 Session::named_selection_by_name (string name)
3574 Glib::Mutex::Lock lm (named_selection_lock);
3575 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
3576 if ((*i)->name == name) {
3584 Session::add_named_selection (NamedSelection* named_selection)
3587 Glib::Mutex::Lock lm (named_selection_lock);
3588 named_selections.insert (named_selections.begin(), named_selection);
3593 NamedSelectionAdded (); /* EMIT SIGNAL */
3597 Session::remove_named_selection (NamedSelection* named_selection)
3599 bool removed = false;
3602 Glib::Mutex::Lock lm (named_selection_lock);
3604 NamedSelectionList::iterator i = find (named_selections.begin(), named_selections.end(), named_selection);
3606 if (i != named_selections.end()) {
3608 named_selections.erase (i);
3615 NamedSelectionRemoved (); /* EMIT SIGNAL */
3620 Session::reset_native_file_format ()
3622 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
3624 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
3625 (*i)->reset_write_sources (false);
3630 Session::route_name_unique (string n) const
3632 shared_ptr<RouteList> r = routes.reader ();
3634 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
3635 if ((*i)->name() == n) {
3644 Session::n_playlists () const
3646 Glib::Mutex::Lock lm (playlist_lock);
3647 return playlists.size();
3651 Session::allocate_pan_automation_buffers (nframes_t nframes, uint32_t howmany, bool force)
3653 if (!force && howmany <= _npan_buffers) {
3657 if (_pan_automation_buffer) {
3659 for (uint32_t i = 0; i < _npan_buffers; ++i) {
3660 delete [] _pan_automation_buffer[i];
3663 delete [] _pan_automation_buffer;
3666 _pan_automation_buffer = new pan_t*[howmany];
3668 for (uint32_t i = 0; i < howmany; ++i) {
3669 _pan_automation_buffer[i] = new pan_t[nframes];
3672 _npan_buffers = howmany;
3676 Session::freeze (InterThreadInfo& itt)
3678 shared_ptr<RouteList> r = routes.reader ();
3680 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
3684 if ((at = dynamic_cast<AudioTrack*>((*i).get())) != 0) {
3685 /* XXX this is wrong because itt.progress will keep returning to zero at the start
3696 Session::write_one_audio_track (AudioTrack& track, nframes_t start, nframes_t len,
3697 bool overwrite, vector<boost::shared_ptr<AudioSource> >& srcs, InterThreadInfo& itt)
3700 boost::shared_ptr<Playlist> playlist;
3701 boost::shared_ptr<AudioFileSource> fsource;
3703 char buf[PATH_MAX+1];
3707 nframes_t this_chunk;
3709 vector<Sample*> buffers;
3711 // any bigger than this seems to cause stack overflows in called functions
3712 const nframes_t chunk_size = (128 * 1024)/4;
3714 g_atomic_int_set (&processing_prohibited, 1);
3716 /* call tree *MUST* hold route_lock */
3718 if ((playlist = track.diskstream()->playlist()) == 0) {
3722 /* external redirects will be a problem */
3724 if (track.has_external_redirects()) {
3728 nchans = track.audio_diskstream()->n_channels();
3730 dir = discover_best_sound_dir ();
3732 for (uint32_t chan_n=0; chan_n < nchans; ++chan_n) {
3734 for (x = 0; x < 99999; ++x) {
3735 snprintf (buf, sizeof(buf), "%s/%s-%d-bounce-%" PRIu32 ".wav", dir.c_str(), playlist->name().c_str(), chan_n, x+1);
3736 if (access (buf, F_OK) != 0) {
3742 error << string_compose (_("too many bounced versions of playlist \"%1\""), playlist->name()) << endmsg;
3747 fsource = boost::dynamic_pointer_cast<AudioFileSource> (SourceFactory::createWritable (*this, buf, false, frame_rate()));
3750 catch (failed_constructor& err) {
3751 error << string_compose (_("cannot create new audio file \"%1\" for %2"), buf, track.name()) << endmsg;
3755 srcs.push_back (fsource);
3758 /* XXX need to flush all redirects */
3763 /* create a set of reasonably-sized buffers */
3765 for (vector<Sample*>::iterator i = _passthru_buffers.begin(); i != _passthru_buffers.end(); ++i) {
3767 #ifdef NO_POSIX_MEMALIGN
3768 b = (Sample *) malloc(chunk_size * sizeof(Sample));
3770 posix_memalign((void **)&b,16,chunk_size * 4);
3772 buffers.push_back (b);
3775 while (to_do && !itt.cancel) {
3777 this_chunk = min (to_do, chunk_size);
3779 if (track.export_stuff (buffers, nchans, start, this_chunk)) {
3784 for (vector<boost::shared_ptr<AudioSource> >::iterator src=srcs.begin(); src != srcs.end(); ++src, ++n) {
3785 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
3788 if (afs->write (buffers[n], this_chunk) != this_chunk) {
3794 start += this_chunk;
3795 to_do -= this_chunk;
3797 itt.progress = (float) (1.0 - ((double) to_do / len));
3806 xnow = localtime (&now);
3808 for (vector<boost::shared_ptr<AudioSource> >::iterator src=srcs.begin(); src != srcs.end(); ++src) {
3809 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
3812 afs->update_header (position, *xnow, now);
3816 /* build peakfile for new source */
3818 for (vector<boost::shared_ptr<AudioSource> >::iterator src=srcs.begin(); src != srcs.end(); ++src) {
3819 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
3821 afs->build_peaks ();
3825 /* construct a region to represent the bounced material */
3827 boost::shared_ptr<Region> aregion = RegionFactory::create (srcs, 0, srcs.front()->length(),
3828 region_name_from_path (srcs.front()->name(), true));
3835 for (vector<boost::shared_ptr<AudioSource> >::iterator src = srcs.begin(); src != srcs.end(); ++src) {
3836 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
3839 afs->mark_for_remove ();
3842 (*src)->drop_references ();
3846 for (vector<Sample*>::iterator i = buffers.begin(); i != buffers.end(); ++i) {
3850 g_atomic_int_set (&processing_prohibited, 0);
3858 Session::get_silent_buffers (uint32_t howmany)
3860 for (uint32_t i = 0; i < howmany; ++i) {
3861 memset (_silent_buffers[i], 0, sizeof (Sample) * current_block_size);
3863 return _silent_buffers;
3867 Session::ntracks () const
3870 shared_ptr<RouteList> r = routes.reader ();
3872 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
3873 if (dynamic_cast<AudioTrack*> ((*i).get())) {
3882 Session::nbusses () const
3885 shared_ptr<RouteList> r = routes.reader ();
3887 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
3888 if (dynamic_cast<AudioTrack*> ((*i).get()) == 0) {
3897 Session::add_automation_list(AutomationList *al)
3899 automation_lists[al->id()] = al;
3903 Session::compute_initial_length ()
3905 return _engine.frame_rate() * 60 * 5;