much ado about nothing when it comes to gain control
[ardour2.git] / libs / ardour / session.cc
blob3e3d391a7a595b25c2eb145ffe335fca7f358767
1 /*
2 Copyright (C) 1999-2010 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.
20 #include <stdint.h>
22 #include <algorithm>
23 #include <string>
24 #include <vector>
25 #include <sstream>
26 #include <fstream>
27 #include <cstdio> /* sprintf(3) ... grrr */
28 #include <cmath>
29 #include <cerrno>
30 #include <unistd.h>
31 #include <limits.h>
33 #include <glibmm/thread.h>
34 #include <glibmm/miscutils.h>
35 #include <glibmm/fileutils.h>
37 #include <boost/algorithm/string/erase.hpp>
39 #include "pbd/error.h"
40 #include "pbd/boost_debug.h"
41 #include "pbd/pathscanner.h"
42 #include "pbd/stl_delete.h"
43 #include "pbd/basename.h"
44 #include "pbd/stacktrace.h"
45 #include "pbd/file_utils.h"
46 #include "pbd/convert.h"
47 #include "pbd/strsplit.h"
49 #include "ardour/amp.h"
50 #include "ardour/analyser.h"
51 #include "ardour/audio_buffer.h"
52 #include "ardour/audio_diskstream.h"
53 #include "ardour/audio_port.h"
54 #include "ardour/audio_track.h"
55 #include "ardour/audioengine.h"
56 #include "ardour/audiofilesource.h"
57 #include "ardour/audioplaylist.h"
58 #include "ardour/audioregion.h"
59 #include "ardour/auditioner.h"
60 #include "ardour/buffer_manager.h"
61 #include "ardour/buffer_set.h"
62 #include "ardour/bundle.h"
63 #include "ardour/butler.h"
64 #include "ardour/click.h"
65 #include "ardour/configuration.h"
66 #include "ardour/control_protocol_manager.h"
67 #include "ardour/crossfade.h"
68 #include "ardour/cycle_timer.h"
69 #include "ardour/data_type.h"
70 #include "ardour/debug.h"
71 #include "ardour/filename_extensions.h"
72 #include "ardour/internal_send.h"
73 #include "ardour/io_processor.h"
74 #include "ardour/midi_diskstream.h"
75 #include "ardour/midi_playlist.h"
76 #include "ardour/midi_region.h"
77 #include "ardour/midi_track.h"
78 #include "ardour/midi_ui.h"
79 #include "ardour/named_selection.h"
80 #include "ardour/process_thread.h"
81 #include "ardour/playlist.h"
82 #include "ardour/plugin_insert.h"
83 #include "ardour/port_insert.h"
84 #include "ardour/processor.h"
85 #include "ardour/rc_configuration.h"
86 #include "ardour/recent_sessions.h"
87 #include "ardour/region_factory.h"
88 #include "ardour/return.h"
89 #include "ardour/route_group.h"
90 #include "ardour/send.h"
91 #include "ardour/session.h"
92 #include "ardour/session_directory.h"
93 #include "ardour/session_directory.h"
94 #include "ardour/session_metadata.h"
95 #include "ardour/session_playlists.h"
96 #include "ardour/slave.h"
97 #include "ardour/smf_source.h"
98 #include "ardour/source_factory.h"
99 #include "ardour/tape_file_matcher.h"
100 #include "ardour/tempo.h"
101 #include "ardour/utils.h"
102 #include "ardour/graph.h"
103 #include "ardour/speakers.h"
104 #include "ardour/operations.h"
106 #include "midi++/port.h"
107 #include "midi++/mmc.h"
108 #include "midi++/manager.h"
110 #include "i18n.h"
112 using namespace std;
113 using namespace ARDOUR;
114 using namespace PBD;
116 bool Session::_disable_all_loaded_plugins = false;
118 PBD::Signal1<void,std::string> Session::Dialog;
119 PBD::Signal0<int> Session::AskAboutPendingState;
120 PBD::Signal2<int, framecnt_t, framecnt_t> Session::AskAboutSampleRateMismatch;
121 PBD::Signal0<void> Session::SendFeedback;
122 PBD::Signal3<int,Session*,std::string,DataType> Session::MissingFile;
124 PBD::Signal1<void, framepos_t> Session::StartTimeChanged;
125 PBD::Signal1<void, framepos_t> Session::EndTimeChanged;
126 PBD::Signal0<void> Session::AutoBindingOn;
127 PBD::Signal0<void> Session::AutoBindingOff;
128 PBD::Signal2<void,std::string, std::string> Session::Exported;
129 PBD::Signal1<int,boost::shared_ptr<Playlist> > Session::AskAboutPlaylistDeletion;
130 PBD::Signal0<void> Session::Quit;
132 static void clean_up_session_event (SessionEvent* ev) { delete ev; }
133 const SessionEvent::RTeventCallback Session::rt_cleanup (clean_up_session_event);
135 Session::Session (AudioEngine &eng,
136 const string& fullpath,
137 const string& snapshot_name,
138 BusProfile* bus_profile,
139 string mix_template)
140 : _engine (eng)
141 , _target_transport_speed (0.0)
142 , _requested_return_frame (-1)
143 , _session_dir (new SessionDirectory(fullpath))
144 , state_tree (0)
145 , _state_of_the_state (Clean)
146 , _butler (new Butler (*this))
147 , _post_transport_work (0)
148 , _send_timecode_update (false)
149 , _all_route_group (new RouteGroup (*this, "all"))
150 , route_graph (new Graph(*this))
151 , routes (new RouteList)
152 , _total_free_4k_blocks (0)
153 , _bundles (new BundleList)
154 , _bundle_xml_node (0)
155 , _current_trans (0)
156 , _click_io ((IO*) 0)
157 , click_data (0)
158 , click_emphasis_data (0)
159 , main_outs (0)
160 , _metadata (new SessionMetadata())
161 , _have_rec_enabled_track (false)
162 , _suspend_timecode_transmission (0)
164 _locations = new Locations (*this);
166 playlists.reset (new SessionPlaylists);
168 _all_route_group->set_active (true, this);
170 interpolation.add_channel_to (0, 0);
172 if (!eng.connected()) {
173 throw failed_constructor();
176 n_physical_outputs = _engine.n_physical_outputs ();
177 n_physical_inputs = _engine.n_physical_inputs ();
179 first_stage_init (fullpath, snapshot_name);
181 _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
183 if (_is_new) {
184 if (create (mix_template, bus_profile)) {
185 destroy ();
186 throw failed_constructor ();
190 if (second_stage_init ()) {
191 destroy ();
192 throw failed_constructor ();
195 store_recent_sessions(_name, _path);
197 bool was_dirty = dirty();
199 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
201 Config->ParameterChanged.connect_same_thread (*this, boost::bind (&Session::config_changed, this, _1, false));
202 config.ParameterChanged.connect_same_thread (*this, boost::bind (&Session::config_changed, this, _1, true));
204 if (was_dirty) {
205 DirtyChanged (); /* EMIT SIGNAL */
208 StartTimeChanged.connect_same_thread (*this, boost::bind (&Session::start_time_changed, this, _1));
209 EndTimeChanged.connect_same_thread (*this, boost::bind (&Session::end_time_changed, this, _1));
211 _is_new = false;
214 Session::~Session ()
216 destroy ();
219 void
220 Session::destroy ()
222 vector<void*> debug_pointers;
224 /* if we got to here, leaving pending capture state around
225 is a mistake.
228 remove_pending_capture_state ();
230 _state_of_the_state = StateOfTheState (CannotSave|Deletion);
232 _engine.remove_session ();
234 /* clear history so that no references to objects are held any more */
236 _history.clear ();
238 /* clear state tree so that no references to objects are held any more */
240 delete state_tree;
242 /* reset dynamic state version back to default */
244 Stateful::loading_state_version = 0;
246 _butler->drop_references ();
247 delete _butler;
248 delete midi_control_ui;
249 delete _all_route_group;
251 if (click_data != default_click) {
252 delete [] click_data;
255 if (click_emphasis_data != default_click_emphasis) {
256 delete [] click_emphasis_data;
259 clear_clicks ();
261 /* clear out any pending dead wood from RCU managed objects */
263 routes.flush ();
264 _bundles.flush ();
266 AudioDiskstream::free_working_buffers();
268 /* tell everyone who is still standing that we're about to die */
269 drop_references ();
271 /* tell everyone to drop references and delete objects as we go */
273 DEBUG_TRACE (DEBUG::Destruction, "delete named selections\n");
274 named_selections.clear ();
276 DEBUG_TRACE (DEBUG::Destruction, "delete regions\n");
277 RegionFactory::delete_all_regions ();
279 DEBUG_TRACE (DEBUG::Destruction, "delete routes\n");
281 /* reset these three references to special routes before we do the usual route delete thing */
283 auditioner.reset ();
284 _master_out.reset ();
285 _monitor_out.reset ();
288 RCUWriter<RouteList> writer (routes);
289 boost::shared_ptr<RouteList> r = writer.get_copy ();
291 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
292 DEBUG_TRACE(DEBUG::Destruction, string_compose ("Dropping for route %1 ; pre-ref = %2\n", (*i)->name(), (*i).use_count()));
293 (*i)->drop_references ();
296 r->clear ();
297 /* writer goes out of scope and updates master */
299 routes.flush ();
301 DEBUG_TRACE (DEBUG::Destruction, "delete sources\n");
302 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
303 DEBUG_TRACE(DEBUG::Destruction, string_compose ("Dropping for source %1 ; pre-ref = %2\n", i->second->name(), i->second.use_count()));
304 i->second->drop_references ();
307 sources.clear ();
309 DEBUG_TRACE (DEBUG::Destruction, "delete route groups\n");
310 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
312 delete *i;
315 Crossfade::set_buffer_size (0);
317 /* not strictly necessary, but doing it here allows the shared_ptr debugging to work */
318 playlists.reset ();
320 delete _locations;
322 DEBUG_TRACE (DEBUG::Destruction, "Session::destroy() done\n");
324 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
325 boost_debug_list_ptrs ();
326 #endif
329 void
330 Session::when_engine_running ()
332 string first_physical_output;
334 BootMessage (_("Set block size and sample rate"));
336 set_block_size (_engine.frames_per_cycle());
337 set_frame_rate (_engine.frame_rate());
339 BootMessage (_("Using configuration"));
341 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
342 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
344 Config->map_parameters (ff);
345 config.map_parameters (ft);
347 /* every time we reconnect, recompute worst case output latencies */
349 _engine.Running.connect_same_thread (*this, boost::bind (&Session::set_worst_io_latencies, this));
351 if (synced_to_jack()) {
352 _engine.transport_stop ();
355 if (config.get_jack_time_master()) {
356 _engine.transport_locate (_transport_frame);
359 _clicking = false;
361 try {
362 XMLNode* child = 0;
364 _click_io.reset (new ClickIO (*this, "click"));
366 if (state_tree && (child = find_named_node (*state_tree->root(), "Click")) != 0) {
368 /* existing state for Click */
369 int c;
371 if (Stateful::loading_state_version < 3000) {
372 c = _click_io->set_state_2X (*child->children().front(), Stateful::loading_state_version, false);
373 } else {
374 c = _click_io->set_state (*child->children().front(), Stateful::loading_state_version);
378 if (c == 0) {
379 _clicking = Config->get_clicking ();
381 } else {
383 error << _("could not setup Click I/O") << endmsg;
384 _clicking = false;
388 } else {
390 /* default state for Click: dual-mono to first 2 physical outputs */
392 vector<string> outs;
393 _engine.get_physical_outputs (DataType::AUDIO, outs);
395 for (uint32_t physport = 0; physport < 2; ++physport) {
396 if (outs.size() > physport) {
397 if (_click_io->add_port (outs[physport], this)) {
398 // relax, even though its an error
403 if (_click_io->n_ports () > ChanCount::ZERO) {
404 _clicking = Config->get_clicking ();
409 catch (failed_constructor& err) {
410 error << _("cannot setup Click I/O") << endmsg;
413 BootMessage (_("Compute I/O Latencies"));
415 if (_clicking) {
416 // XXX HOW TO ALERT UI TO THIS ? DO WE NEED TO?
419 BootMessage (_("Set up standard connections"));
421 vector<string> inputs[DataType::num_types];
422 vector<string> outputs[DataType::num_types];
423 for (uint32_t i = 0; i < DataType::num_types; ++i) {
424 _engine.get_physical_inputs (DataType (DataType::Symbol (i)), inputs[i]);
425 _engine.get_physical_outputs (DataType (DataType::Symbol (i)), outputs[i]);
428 /* Create a set of Bundle objects that map
429 to the physical I/O currently available. We create both
430 mono and stereo bundles, so that the common cases of mono
431 and stereo tracks get bundles to put in their mixer strip
432 in / out menus. There may be a nicer way of achieving that;
433 it doesn't really scale that well to higher channel counts
436 /* mono output bundles */
438 for (uint32_t np = 0; np < outputs[DataType::AUDIO].size(); ++np) {
439 char buf[32];
440 snprintf (buf, sizeof (buf), _("out %" PRIu32), np+1);
442 boost::shared_ptr<Bundle> c (new Bundle (buf, true));
443 c->add_channel (_("mono"), DataType::AUDIO);
444 c->set_port (0, outputs[DataType::AUDIO][np]);
446 add_bundle (c);
449 /* stereo output bundles */
451 for (uint32_t np = 0; np < outputs[DataType::AUDIO].size(); np += 2) {
452 if (np + 1 < outputs[DataType::AUDIO].size()) {
453 char buf[32];
454 snprintf (buf, sizeof(buf), _("out %" PRIu32 "+%" PRIu32), np + 1, np + 2);
455 boost::shared_ptr<Bundle> c (new Bundle (buf, true));
456 c->add_channel (_("L"), DataType::AUDIO);
457 c->set_port (0, outputs[DataType::AUDIO][np]);
458 c->add_channel (_("R"), DataType::AUDIO);
459 c->set_port (1, outputs[DataType::AUDIO][np + 1]);
461 add_bundle (c);
465 /* mono input bundles */
467 for (uint32_t np = 0; np < inputs[DataType::AUDIO].size(); ++np) {
468 char buf[32];
469 snprintf (buf, sizeof (buf), _("in %" PRIu32), np+1);
471 boost::shared_ptr<Bundle> c (new Bundle (buf, false));
472 c->add_channel (_("mono"), DataType::AUDIO);
473 c->set_port (0, inputs[DataType::AUDIO][np]);
475 add_bundle (c);
478 /* stereo input bundles */
480 for (uint32_t np = 0; np < inputs[DataType::AUDIO].size(); np += 2) {
481 if (np + 1 < inputs[DataType::AUDIO].size()) {
482 char buf[32];
483 snprintf (buf, sizeof(buf), _("in %" PRIu32 "+%" PRIu32), np + 1, np + 2);
485 boost::shared_ptr<Bundle> c (new Bundle (buf, false));
486 c->add_channel (_("L"), DataType::AUDIO);
487 c->set_port (0, inputs[DataType::AUDIO][np]);
488 c->add_channel (_("R"), DataType::AUDIO);
489 c->set_port (1, inputs[DataType::AUDIO][np + 1]);
491 add_bundle (c);
495 /* MIDI input bundles */
497 for (uint32_t np = 0; np < inputs[DataType::MIDI].size(); ++np) {
498 string n = inputs[DataType::MIDI][np];
499 boost::erase_first (n, X_("alsa_pcm:"));
501 boost::shared_ptr<Bundle> c (new Bundle (n, false));
502 c->add_channel ("", DataType::MIDI);
503 c->set_port (0, inputs[DataType::MIDI][np]);
504 add_bundle (c);
507 /* MIDI output bundles */
509 for (uint32_t np = 0; np < outputs[DataType::MIDI].size(); ++np) {
510 string n = outputs[DataType::MIDI][np];
511 boost::erase_first (n, X_("alsa_pcm:"));
513 boost::shared_ptr<Bundle> c (new Bundle (n, true));
514 c->add_channel ("", DataType::MIDI);
515 c->set_port (0, outputs[DataType::MIDI][np]);
516 add_bundle (c);
519 BootMessage (_("Setup signal flow and plugins"));
521 ControlProtocolManager::instance().set_session (this);
523 /* This must be done after the ControlProtocolManager set_session above,
524 as it will set states for ports which the ControlProtocolManager creates.
526 MIDI::Manager::instance()->set_port_states (Config->midi_port_states ());
528 /* And this must be done after the MIDI::Manager::set_port_states as
529 * it will try to make connections whose details are loaded by set_port_states.
532 hookup_io ();
534 if (_is_new && !no_auto_connect()) {
536 Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock());
538 /* don't connect the master bus outputs if there is a monitor bus */
540 if (_master_out && Config->get_auto_connect_standard_busses() && !_monitor_out) {
542 /* if requested auto-connect the outputs to the first N physical ports.
545 uint32_t limit = _master_out->n_outputs().n_total();
547 for (uint32_t n = 0; n < limit; ++n) {
548 Port* p = _master_out->output()->nth (n);
549 string connect_to;
550 if (outputs[p->type()].size() > n) {
551 connect_to = outputs[p->type()][n];
554 if (!connect_to.empty() && p->connected_to (connect_to) == false) {
555 if (_master_out->output()->connect (p, connect_to, this)) {
556 error << string_compose (_("cannot connect master output %1 to %2"), n, connect_to)
557 << endmsg;
558 break;
564 if (_monitor_out) {
566 /* AUDIO ONLY as of june 29th 2009, because listen semantics for anything else
567 are undefined, at best.
570 /* control out listens to master bus (but ignores it
571 under some conditions)
574 uint32_t limit = _monitor_out->n_inputs().n_audio();
576 if (_master_out) {
577 for (uint32_t n = 0; n < limit; ++n) {
578 AudioPort* p = _monitor_out->input()->ports().nth_audio_port (n);
579 AudioPort* o = _master_out->output()->ports().nth_audio_port (n);
581 if (o) {
582 string connect_to = o->name();
583 if (_monitor_out->input()->connect (p, connect_to, this)) {
584 error << string_compose (_("cannot connect control input %1 to %2"), n, connect_to)
585 << endmsg;
586 break;
592 /* if control out is not connected, connect control out to physical outs
595 if (!_monitor_out->output()->connected ()) {
597 if (!Config->get_monitor_bus_preferred_bundle().empty()) {
599 boost::shared_ptr<Bundle> b = bundle_by_name (Config->get_monitor_bus_preferred_bundle());
601 if (b) {
602 _monitor_out->output()->connect_ports_to_bundle (b, this);
603 } else {
604 warning << string_compose (_("The preferred I/O for the monitor bus (%1) cannot be found"),
605 Config->get_monitor_bus_preferred_bundle())
606 << endmsg;
609 } else {
611 /* Monitor bus is audio only */
612 uint32_t mod = n_physical_outputs.get (DataType::AUDIO);
613 uint32_t limit = _monitor_out->n_outputs().get (DataType::AUDIO);
615 if (mod != 0) {
617 for (uint32_t n = 0; n < limit; ++n) {
619 Port* p = _monitor_out->output()->ports().port(DataType::AUDIO, n);
620 string connect_to;
621 if (outputs[DataType::AUDIO].size() > (n % mod)) {
622 connect_to = outputs[DataType::AUDIO][n % mod];
625 if (!connect_to.empty()) {
626 if (_monitor_out->output()->connect (p, connect_to, this)) {
627 error << string_compose (
628 _("cannot connect control output %1 to %2"),
629 n, connect_to)
630 << endmsg;
631 break;
641 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
643 /* hook us up to the engine */
645 BootMessage (_("Connect to engine"));
646 _engine.set_session (this);
648 update_latency_compensation (true);
651 void
652 Session::hookup_io ()
654 /* stop graph reordering notifications from
655 causing resorts, etc.
658 _state_of_the_state = StateOfTheState (_state_of_the_state | InitialConnecting);
660 if (!auditioner) {
662 /* we delay creating the auditioner till now because
663 it makes its own connections to ports.
666 try {
667 boost::shared_ptr<Auditioner> a (new Auditioner (*this));
668 if (a->init()) {
669 throw failed_constructor ();
671 a->use_new_diskstream ();
672 auditioner = a;
675 catch (failed_constructor& err) {
676 warning << _("cannot create Auditioner: no auditioning of regions possible") << endmsg;
680 /* load bundles, which we may have postponed earlier on */
681 if (_bundle_xml_node) {
682 load_bundles (*_bundle_xml_node);
683 delete _bundle_xml_node;
686 /* Tell all IO objects to connect themselves together */
688 IO::enable_connecting ();
689 MIDI::Port::MakeConnections ();
691 /* Now reset all panners */
693 Delivery::reset_panners ();
695 /* Connect tracks to monitor/listen bus if there is one. Note that in an
696 existing session, the internal sends will already exist, but we want the
697 routes to notice that they connect to the control out specifically.
700 if (_monitor_out) {
701 boost::shared_ptr<RouteList> r = routes.reader ();
702 for (RouteList::iterator x = r->begin(); x != r->end(); ++x) {
704 if ((*x)->is_monitor()) {
706 /* relax */
708 } else if ((*x)->is_master()) {
710 /* relax */
712 } else {
714 (*x)->listen_via_monitor ();
719 /* Anyone who cares about input state, wake up and do something */
721 IOConnectionsComplete (); /* EMIT SIGNAL */
723 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InitialConnecting);
725 /* now handle the whole enchilada as if it was one
726 graph reorder event.
729 graph_reordered ();
731 /* update the full solo state, which can't be
732 correctly determined on a per-route basis, but
733 needs the global overview that only the session
734 has.
737 update_route_solo_state ();
740 void
741 Session::track_playlist_changed (boost::weak_ptr<Track> wp)
743 boost::shared_ptr<Track> track = wp.lock ();
744 if (!track) {
745 return;
748 boost::shared_ptr<Playlist> playlist;
750 if ((playlist = track->playlist()) != 0) {
751 playlist->RegionAdded.connect_same_thread (*this, boost::bind (&Session::playlist_region_added, this, _1));
752 playlist->RangesMoved.connect_same_thread (*this, boost::bind (&Session::playlist_ranges_moved, this, _1));
753 playlist->RegionsExtended.connect_same_thread (*this, boost::bind (&Session::playlist_regions_extended, this, _1));
757 bool
758 Session::record_enabling_legal () const
760 /* this used to be in here, but survey says.... we don't need to restrict it */
761 // if (record_status() == Recording) {
762 // return false;
763 // }
765 if (Config->get_all_safe()) {
766 return false;
768 return true;
771 void
772 Session::set_track_monitor_input_status (bool yn)
774 boost::shared_ptr<RouteList> rl = routes.reader ();
775 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
776 boost::shared_ptr<AudioTrack> tr = boost::dynamic_pointer_cast<AudioTrack> (*i);
777 if (tr && tr->record_enabled ()) {
778 //cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
779 tr->monitor_input (yn);
784 void
785 Session::reset_input_monitor_state ()
787 if (transport_rolling()) {
788 set_track_monitor_input_status (Config->get_monitoring_model() == HardwareMonitoring && !config.get_auto_input());
789 } else {
790 set_track_monitor_input_status (Config->get_monitoring_model() == HardwareMonitoring);
794 void
795 Session::auto_punch_start_changed (Location* location)
797 replace_event (SessionEvent::PunchIn, location->start());
799 if (get_record_enabled() && config.get_punch_in()) {
800 /* capture start has been changed, so save new pending state */
801 save_state ("", true);
805 void
806 Session::auto_punch_end_changed (Location* location)
808 framepos_t when_to_stop = location->end();
809 // when_to_stop += _worst_output_latency + _worst_input_latency;
810 replace_event (SessionEvent::PunchOut, when_to_stop);
813 void
814 Session::auto_punch_changed (Location* location)
816 framepos_t when_to_stop = location->end();
818 replace_event (SessionEvent::PunchIn, location->start());
819 //when_to_stop += _worst_output_latency + _worst_input_latency;
820 replace_event (SessionEvent::PunchOut, when_to_stop);
823 void
824 Session::auto_loop_changed (Location* location)
826 replace_event (SessionEvent::AutoLoop, location->end(), location->start());
828 if (transport_rolling() && play_loop) {
831 // if (_transport_frame > location->end()) {
833 if (_transport_frame < location->start() || _transport_frame > location->end()) {
834 // relocate to beginning of loop
835 clear_events (SessionEvent::LocateRoll);
837 request_locate (location->start(), true);
840 else if (Config->get_seamless_loop() && !loop_changing) {
842 // schedule a locate-roll to refill the diskstreams at the
843 // previous loop end
844 loop_changing = true;
846 if (location->end() > last_loopend) {
847 clear_events (SessionEvent::LocateRoll);
848 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, last_loopend, last_loopend, 0, true);
849 queue_event (ev);
855 last_loopend = location->end();
858 void
859 Session::set_auto_punch_location (Location* location)
861 Location* existing;
863 if ((existing = _locations->auto_punch_location()) != 0 && existing != location) {
864 punch_connections.drop_connections();
865 existing->set_auto_punch (false, this);
866 remove_event (existing->start(), SessionEvent::PunchIn);
867 clear_events (SessionEvent::PunchOut);
868 auto_punch_location_changed (0);
871 set_dirty();
873 if (location == 0) {
874 return;
877 if (location->end() <= location->start()) {
878 error << _("Session: you can't use that location for auto punch (start <= end)") << endmsg;
879 return;
882 punch_connections.drop_connections ();
884 location->start_changed.connect_same_thread (punch_connections, boost::bind (&Session::auto_punch_start_changed, this, _1));
885 location->end_changed.connect_same_thread (punch_connections, boost::bind (&Session::auto_punch_end_changed, this, _1));
886 location->changed.connect_same_thread (punch_connections, boost::bind (&Session::auto_punch_changed, this, _1));
888 location->set_auto_punch (true, this);
890 auto_punch_changed (location);
892 auto_punch_location_changed (location);
895 void
896 Session::set_auto_loop_location (Location* location)
898 Location* existing;
900 if ((existing = _locations->auto_loop_location()) != 0 && existing != location) {
901 loop_connections.drop_connections ();
902 existing->set_auto_loop (false, this);
903 remove_event (existing->end(), SessionEvent::AutoLoop);
904 auto_loop_location_changed (0);
907 set_dirty();
909 if (location == 0) {
910 return;
913 if (location->end() <= location->start()) {
914 error << _("Session: you can't use a mark for auto loop") << endmsg;
915 return;
918 last_loopend = location->end();
920 loop_connections.drop_connections ();
922 location->start_changed.connect_same_thread (loop_connections, boost::bind (&Session::auto_loop_changed, this, _1));
923 location->end_changed.connect_same_thread (loop_connections, boost::bind (&Session::auto_loop_changed, this, _1));
924 location->changed.connect_same_thread (loop_connections, boost::bind (&Session::auto_loop_changed, this, _1));
926 location->set_auto_loop (true, this);
928 /* take care of our stuff first */
930 auto_loop_changed (location);
932 /* now tell everyone else */
934 auto_loop_location_changed (location);
937 void
938 Session::locations_added (Location *)
940 set_dirty ();
943 void
944 Session::locations_changed ()
946 _locations->apply (*this, &Session::handle_locations_changed);
949 void
950 Session::handle_locations_changed (Locations::LocationList& locations)
952 Locations::LocationList::iterator i;
953 Location* location;
954 bool set_loop = false;
955 bool set_punch = false;
957 for (i = locations.begin(); i != locations.end(); ++i) {
959 location =* i;
961 if (location->is_auto_punch()) {
962 set_auto_punch_location (location);
963 set_punch = true;
965 if (location->is_auto_loop()) {
966 set_auto_loop_location (location);
967 set_loop = true;
970 if (location->is_session_range()) {
971 _session_range_location = location;
975 if (!set_loop) {
976 set_auto_loop_location (0);
978 if (!set_punch) {
979 set_auto_punch_location (0);
982 set_dirty();
985 void
986 Session::enable_record ()
988 while (1) {
989 RecordState rs = (RecordState) g_atomic_int_get (&_record_status);
991 if (rs == Recording) {
992 break;
995 if (g_atomic_int_compare_and_exchange (&_record_status, rs, Recording)) {
997 _last_record_location = _transport_frame;
998 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordStrobe));
1000 if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
1001 set_track_monitor_input_status (true);
1004 RecordStateChanged ();
1005 break;
1010 void
1011 Session::disable_record (bool rt_context, bool force)
1013 RecordState rs;
1015 if ((rs = (RecordState) g_atomic_int_get (&_record_status)) != Disabled) {
1017 if ((!Config->get_latched_record_enable () && !play_loop) || force) {
1018 g_atomic_int_set (&_record_status, Disabled);
1019 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordExit));
1020 } else {
1021 if (rs == Recording) {
1022 g_atomic_int_set (&_record_status, Enabled);
1026 if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
1027 set_track_monitor_input_status (false);
1030 RecordStateChanged (); /* emit signal */
1032 if (!rt_context) {
1033 remove_pending_capture_state ();
1038 void
1039 Session::step_back_from_record ()
1041 if (g_atomic_int_compare_and_exchange (&_record_status, Recording, Enabled)) {
1043 if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
1044 set_track_monitor_input_status (false);
1049 void
1050 Session::maybe_enable_record ()
1052 if (_step_editors > 0) {
1053 return;
1056 g_atomic_int_set (&_record_status, Enabled);
1058 /* This function is currently called from somewhere other than an RT thread.
1059 This save_state() call therefore doesn't impact anything. Doing it here
1060 means that we save pending state of which sources the next record will use,
1061 which gives us some chance of recovering from a crash during the record.
1064 save_state ("", true);
1066 if (_transport_speed) {
1067 if (!config.get_punch_in()) {
1068 enable_record ();
1070 } else {
1071 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordPause));
1072 RecordStateChanged (); /* EMIT SIGNAL */
1075 set_dirty();
1078 framepos_t
1079 Session::audible_frame () const
1081 framepos_t ret;
1082 framepos_t tf;
1083 framecnt_t offset;
1085 /* the first of these two possible settings for "offset"
1086 mean that the audible frame is stationary until
1087 audio emerges from the latency compensation
1088 "pseudo-pipeline".
1090 the second means that the audible frame is stationary
1091 until audio would emerge from a physical port
1092 in the absence of any plugin latency compensation
1095 offset = worst_playback_latency ();
1097 if (offset > current_block_size) {
1098 offset -= current_block_size;
1099 } else {
1100 /* XXX is this correct? if we have no external
1101 physical connections and everything is internal
1102 then surely this is zero? still, how
1103 likely is that anyway?
1105 offset = current_block_size;
1108 if (synced_to_jack()) {
1109 tf = _engine.transport_frame();
1110 } else {
1111 tf = _transport_frame;
1114 ret = tf;
1116 if (!non_realtime_work_pending()) {
1118 /* MOVING */
1120 /* Check to see if we have passed the first guaranteed
1121 audible frame past our last start position. if not,
1122 return that last start point because in terms
1123 of audible frames, we have not moved yet.
1125 `Start position' in this context means the time we last
1126 either started or changed transport direction.
1129 if (_transport_speed > 0.0f) {
1131 if (!play_loop || !have_looped) {
1132 if (tf < _last_roll_or_reversal_location + offset) {
1133 return _last_roll_or_reversal_location;
1138 /* forwards */
1139 ret -= offset;
1141 } else if (_transport_speed < 0.0f) {
1143 /* XXX wot? no backward looping? */
1145 if (tf > _last_roll_or_reversal_location - offset) {
1146 return _last_roll_or_reversal_location;
1147 } else {
1148 /* backwards */
1149 ret += offset;
1154 return ret;
1157 void
1158 Session::set_frame_rate (framecnt_t frames_per_second)
1160 /** \fn void Session::set_frame_size(framecnt_t)
1161 the AudioEngine object that calls this guarantees
1162 that it will not be called while we are also in
1163 ::process(). Its fine to do things that block
1164 here.
1167 _base_frame_rate = frames_per_second;
1169 sync_time_vars();
1171 Automatable::set_automation_interval (ceil ((double) frames_per_second * (0.001 * Config->get_automation_interval())));
1173 clear_clicks ();
1175 // XXX we need some equivalent to this, somehow
1176 // SndFileSource::setup_standard_crossfades (frames_per_second);
1178 set_dirty();
1180 /* XXX need to reset/reinstantiate all LADSPA plugins */
1183 void
1184 Session::set_block_size (pframes_t nframes)
1186 /* the AudioEngine guarantees
1187 that it will not be called while we are also in
1188 ::process(). It is therefore fine to do things that block
1189 here.
1193 current_block_size = nframes;
1195 ensure_buffers ();
1197 boost::shared_ptr<RouteList> r = routes.reader ();
1199 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1200 (*i)->set_block_size (nframes);
1203 boost::shared_ptr<RouteList> rl = routes.reader ();
1204 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1205 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1206 if (tr) {
1207 tr->set_block_size (nframes);
1211 set_worst_io_latencies ();
1215 struct RouteSorter {
1216 /** @return true to run r1 before r2, otherwise false */
1217 bool sort_by_rec_enabled (const boost::shared_ptr<Route>& r1, const boost::shared_ptr<Route>& r2) {
1218 if (r1->record_enabled()) {
1219 if (r2->record_enabled()) {
1220 /* both rec-enabled, just use signal order */
1221 return r1->order_key(N_("signal")) < r2->order_key(N_("signal"));
1222 } else {
1223 /* r1 rec-enabled, r2 not rec-enabled, run r2 early */
1224 return false;
1226 } else {
1227 if (r2->record_enabled()) {
1228 /* r2 rec-enabled, r1 not rec-enabled, run r1 early */
1229 return true;
1230 } else {
1231 /* neither rec-enabled, use signal order */
1232 return r1->order_key(N_("signal")) < r2->order_key(N_("signal"));
1237 bool operator() (boost::shared_ptr<Route> r1, boost::shared_ptr<Route> r2) {
1238 if (r2->feeds (r1)) {
1239 /* r1 fed by r2; run r2 early */
1240 return false;
1241 } else if (r1->feeds (r2)) {
1242 /* r2 fed by r1; run r1 early */
1243 return true;
1244 } else {
1245 if (r1->not_fed ()) {
1246 if (r2->not_fed ()) {
1247 /* no ardour-based connections inbound to either route. */
1248 return sort_by_rec_enabled (r1, r2);
1249 } else {
1250 /* r2 has connections, r1 does not; run r1 early */
1251 return true;
1253 } else {
1254 if (r2->not_fed()) {
1255 /* r1 has connections, r2 does not; run r2 early */
1256 return false;
1257 } else {
1258 /* both r1 and r2 have connections, but not to each other. just use signal order */
1259 return r1->order_key(N_("signal")) < r2->order_key(N_("signal"));
1266 static void
1267 trace_terminal (boost::shared_ptr<Route> r1, boost::shared_ptr<Route> rbase)
1269 boost::shared_ptr<Route> r2;
1271 if (r1->feeds (rbase) && rbase->feeds (r1)) {
1272 info << string_compose(_("feedback loop setup between %1 and %2"), r1->name(), rbase->name()) << endmsg;
1273 return;
1276 /* make a copy of the existing list of routes that feed r1 */
1278 Route::FedBy existing (r1->fed_by());
1280 /* for each route that feeds r1, recurse, marking it as feeding
1281 rbase as well.
1284 for (Route::FedBy::iterator i = existing.begin(); i != existing.end(); ++i) {
1285 if (!(r2 = i->r.lock ())) {
1286 /* (*i) went away, ignore it */
1287 continue;
1290 /* r2 is a route that feeds r1 which somehow feeds base. mark
1291 base as being fed by r2
1294 rbase->add_fed_by (r2, i->sends_only);
1296 if (r2 != rbase) {
1298 /* 2nd level feedback loop detection. if r1 feeds or is fed by r2,
1299 stop here.
1302 if (r1->feeds (r2) && r2->feeds (r1)) {
1303 continue;
1306 /* now recurse, so that we can mark base as being fed by
1307 all routes that feed r2
1310 trace_terminal (r2, rbase);
1316 void
1317 Session::resort_routes ()
1319 /* don't do anything here with signals emitted
1320 by Routes while we are being destroyed.
1323 if (_state_of_the_state & Deletion) {
1324 return;
1328 RCUWriter<RouteList> writer (routes);
1329 boost::shared_ptr<RouteList> r = writer.get_copy ();
1330 resort_routes_using (r);
1331 /* writer goes out of scope and forces update */
1334 //route_graph->dump(1);
1336 #ifndef NDEBUG
1337 boost::shared_ptr<RouteList> rl = routes.reader ();
1338 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1339 DEBUG_TRACE (DEBUG::Graph, string_compose ("%1 fed by ...\n", (*i)->name()));
1341 const Route::FedBy& fb ((*i)->fed_by());
1343 for (Route::FedBy::const_iterator f = fb.begin(); f != fb.end(); ++f) {
1344 boost::shared_ptr<Route> sf = f->r.lock();
1345 if (sf) {
1346 DEBUG_TRACE (DEBUG::Graph, string_compose ("\t%1 (sends only ? %2)\n", sf->name(), f->sends_only));
1350 #endif
1353 void
1354 Session::resort_routes_using (boost::shared_ptr<RouteList> r)
1356 RouteList::iterator i, j;
1358 for (i = r->begin(); i != r->end(); ++i) {
1360 (*i)->clear_fed_by ();
1362 for (j = r->begin(); j != r->end(); ++j) {
1364 /* although routes can feed themselves, it will
1365 cause an endless recursive descent if we
1366 detect it. so don't bother checking for
1367 self-feeding.
1370 if (*j == *i) {
1371 continue;
1374 bool via_sends_only;
1376 if ((*j)->direct_feeds (*i, &via_sends_only)) {
1377 (*i)->add_fed_by (*j, via_sends_only);
1382 for (i = r->begin(); i != r->end(); ++i) {
1383 trace_terminal (*i, *i);
1386 RouteSorter cmp;
1387 r->sort (cmp);
1389 route_graph->rechain (r);
1391 #ifndef NDEBUG
1392 DEBUG_TRACE (DEBUG::Graph, "Routes resorted, order follows:\n");
1393 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1394 DEBUG_TRACE (DEBUG::Graph, string_compose ("\t%1 signal order %2\n",
1395 (*i)->name(), (*i)->order_key ("signal")));
1397 #endif
1401 /** Find a route name starting with \a base, maybe followed by the
1402 * lowest \a id. \a id will always be added if \a definitely_add_number
1403 * is true on entry; otherwise it will only be added if required
1404 * to make the name unique.
1406 * Names are constructed like e.g. "Audio 3" for base="Audio" and id=3.
1407 * The available route name with the lowest ID will be used, and \a id
1408 * will be set to the ID.
1410 * \return false if a route name could not be found, and \a track_name
1411 * and \a id do not reflect a free route name.
1413 bool
1414 Session::find_route_name (string const & base, uint32_t& id, char* name, size_t name_len, bool definitely_add_number)
1416 if (!definitely_add_number && route_by_name (base) == 0) {
1417 /* juse use the base */
1418 snprintf (name, name_len, "%s", base.c_str());
1419 return true;
1422 do {
1423 snprintf (name, name_len, "%s %" PRIu32, base.c_str(), id);
1425 if (route_by_name (name) == 0) {
1426 return true;
1429 ++id;
1431 } while (id < (UINT_MAX-1));
1433 return false;
1436 /** Count the total ins and outs of all non-hidden tracks in the session and return them in in and out */
1437 void
1438 Session::count_existing_track_channels (ChanCount& in, ChanCount& out)
1440 in = ChanCount::ZERO;
1441 out = ChanCount::ZERO;
1443 boost::shared_ptr<RouteList> r = routes.reader ();
1445 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1446 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1447 if (tr && !tr->is_hidden()) {
1448 in += tr->n_inputs();
1449 out += tr->n_outputs();
1454 /** Caller must not hold process lock
1455 * @param name_template string to use for the start of the name, or "" to use "Midi".
1457 list<boost::shared_ptr<MidiTrack> >
1458 Session::new_midi_track (TrackMode mode, RouteGroup* route_group, uint32_t how_many, string name_template)
1460 char track_name[32];
1461 uint32_t track_id = 0;
1462 string port;
1463 RouteList new_routes;
1464 list<boost::shared_ptr<MidiTrack> > ret;
1465 uint32_t control_id;
1467 control_id = ntracks() + nbusses();
1469 bool const use_number = (how_many != 1);
1471 while (how_many) {
1472 if (!find_route_name (name_template.empty() ? _("Midi") : name_template, ++track_id, track_name, sizeof(track_name), use_number)) {
1473 error << "cannot find name for new midi track" << endmsg;
1474 goto failed;
1477 boost::shared_ptr<MidiTrack> track;
1479 try {
1480 track.reset (new MidiTrack (*this, track_name, Route::Flag (0), mode));
1482 if (track->init ()) {
1483 goto failed;
1486 track->use_new_diskstream();
1488 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1489 boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1490 #endif
1492 Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
1493 if (track->input()->ensure_io (ChanCount(DataType::MIDI, 1), false, this)) {
1494 error << "cannot configure 1 in/1 out configuration for new midi track" << endmsg;
1495 goto failed;
1498 if (track->output()->ensure_io (ChanCount(DataType::MIDI, 1), false, this)) {
1499 error << "cannot configure 1 in/1 out configuration for new midi track" << endmsg;
1500 goto failed;
1504 track->non_realtime_input_change();
1506 if (route_group) {
1507 route_group->add (track);
1510 track->DiskstreamChanged.connect_same_thread (*this, boost::bind (&Session::resort_routes, this));
1511 track->set_remote_control_id (control_id);
1513 new_routes.push_back (track);
1514 ret.push_back (track);
1517 catch (failed_constructor &err) {
1518 error << _("Session: could not create new midi track.") << endmsg;
1519 goto failed;
1522 catch (AudioEngine::PortRegistrationFailure& pfe) {
1524 error << string_compose (_("No more JACK ports are available. You will need to stop %1 and restart JACK with ports if you need this many tracks."), PROGRAM_NAME) << endmsg;
1525 goto failed;
1528 --how_many;
1531 failed:
1532 if (!new_routes.empty()) {
1533 add_routes (new_routes, true, true);
1536 return ret;
1539 void
1540 Session::midi_output_change_handler (IOChange change, void * /*src*/, boost::weak_ptr<Route> wmt)
1542 boost::shared_ptr<Route> midi_track (wmt.lock());
1544 if (!midi_track) {
1545 return;
1548 if ((change.type & IOChange::ConfigurationChanged) && Config->get_output_auto_connect() != ManualConnect) {
1550 if (change.after.n_audio() <= change.before.n_audio()) {
1551 return;
1554 /* new audio ports: make sure the audio goes somewhere useful,
1555 unless the user has no-auto-connect selected.
1557 The existing ChanCounts don't matter for this call as they are only
1558 to do with matching input and output indices, and we are only changing
1559 outputs here.
1562 ChanCount dummy;
1564 auto_connect_route (midi_track, dummy, dummy, false, false, ChanCount(), change.before);
1568 /** @param connect_inputs true to connect inputs as well as outputs, false to connect just outputs.
1569 * @param input_start Where to start from when auto-connecting inputs; e.g. if this is 0, auto-connect starting from input 0.
1570 * @param output_start As \a input_start, but for outputs.
1572 void
1573 Session::auto_connect_route (boost::shared_ptr<Route> route, ChanCount& existing_inputs, ChanCount& existing_outputs,
1574 bool with_lock, bool connect_inputs, ChanCount input_start, ChanCount output_start)
1576 if (!IO::connecting_legal) {
1577 return;
1580 Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock (), Glib::NOT_LOCK);
1582 if (with_lock) {
1583 lm.acquire ();
1586 /* If both inputs and outputs are auto-connected to physical ports,
1587 use the max of input and output offsets to ensure auto-connected
1588 port numbers always match up (e.g. the first audio input and the
1589 first audio output of the route will have the same physical
1590 port number). Otherwise just use the lowest input or output
1591 offset possible.
1594 DEBUG_TRACE (DEBUG::Graph,
1595 string_compose("Auto-connect: existing in = %1 out = %2\n",
1596 existing_inputs, existing_outputs));
1598 const bool in_out_physical =
1599 (Config->get_input_auto_connect() & AutoConnectPhysical)
1600 && (Config->get_output_auto_connect() & AutoConnectPhysical)
1601 && connect_inputs;
1603 const ChanCount in_offset = in_out_physical
1604 ? ChanCount::max(existing_inputs, existing_outputs)
1605 : existing_inputs;
1607 const ChanCount out_offset = in_out_physical
1608 ? ChanCount::max(existing_inputs, existing_outputs)
1609 : existing_outputs;
1611 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1612 vector<string> physinputs;
1613 vector<string> physoutputs;
1615 _engine.get_physical_outputs (*t, physoutputs);
1616 _engine.get_physical_inputs (*t, physinputs);
1618 if (!physinputs.empty() && connect_inputs) {
1619 uint32_t nphysical_in = physinputs.size();
1621 DEBUG_TRACE (DEBUG::Graph,
1622 string_compose("There are %1 physical inputs of type %2\n",
1623 nphysical_in, *t));
1625 for (uint32_t i = input_start.get(*t); i < route->n_inputs().get(*t) && i < nphysical_in; ++i) {
1626 string port;
1628 if (Config->get_input_auto_connect() & AutoConnectPhysical) {
1629 DEBUG_TRACE (DEBUG::Graph,
1630 string_compose("Get index %1 + %2 % %3 = %4\n",
1631 in_offset.get(*t), i, nphysical_in,
1632 (in_offset.get(*t) + i) % nphysical_in));
1633 port = physinputs[(in_offset.get(*t) + i) % nphysical_in];
1636 DEBUG_TRACE (DEBUG::Graph,
1637 string_compose("Connect route %1 IN to %2\n",
1638 route->name(), port));
1640 if (!port.empty() && route->input()->connect (route->input()->ports().port(*t, i), port, this)) {
1641 break;
1644 ChanCount one_added (*t, 1);
1645 existing_inputs += one_added;
1649 if (!physoutputs.empty()) {
1650 uint32_t nphysical_out = physoutputs.size();
1651 for (uint32_t i = output_start.get(*t); i < route->n_outputs().get(*t); ++i) {
1652 string port;
1654 if ((*t) == DataType::MIDI || Config->get_output_auto_connect() & AutoConnectPhysical) {
1655 port = physoutputs[(out_offset.get(*t) + i) % nphysical_out];
1656 } else if ((*t) == DataType::AUDIO && Config->get_output_auto_connect() & AutoConnectMaster) {
1657 /* master bus is audio only */
1658 if (_master_out && _master_out->n_inputs().get(*t) > 0) {
1659 port = _master_out->input()->ports().port(*t,
1660 i % _master_out->input()->n_ports().get(*t))->name();
1664 DEBUG_TRACE (DEBUG::Graph,
1665 string_compose("Connect route %1 OUT to %2\n",
1666 route->name(), port));
1668 if (!port.empty() && route->output()->connect (route->output()->ports().port(*t, i), port, this)) {
1669 break;
1672 ChanCount one_added (*t, 1);
1673 existing_outputs += one_added;
1679 /** Caller must not hold process lock
1680 * @param name_template string to use for the start of the name, or "" to use "Audio".
1682 list< boost::shared_ptr<AudioTrack> >
1683 Session::new_audio_track (
1684 int input_channels, int output_channels, TrackMode mode, RouteGroup* route_group, uint32_t how_many, string name_template
1687 char track_name[32];
1688 uint32_t track_id = 0;
1689 string port;
1690 RouteList new_routes;
1691 list<boost::shared_ptr<AudioTrack> > ret;
1692 uint32_t control_id;
1694 control_id = ntracks() + nbusses() + 1;
1696 bool const use_number = (how_many != 1);
1698 while (how_many) {
1699 if (!find_route_name (name_template.empty() ? _("Audio") : name_template, ++track_id, track_name, sizeof(track_name), use_number)) {
1700 error << "cannot find name for new audio track" << endmsg;
1701 goto failed;
1704 boost::shared_ptr<AudioTrack> track;
1706 try {
1707 track.reset (new AudioTrack (*this, track_name, Route::Flag (0), mode));
1709 if (track->init ()) {
1710 goto failed;
1713 track->use_new_diskstream();
1715 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1716 boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1717 #endif
1719 Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
1721 if (track->input()->ensure_io (ChanCount(DataType::AUDIO, input_channels), false, this)) {
1722 error << string_compose (
1723 _("cannot configure %1 in/%2 out configuration for new audio track"),
1724 input_channels, output_channels)
1725 << endmsg;
1726 goto failed;
1729 if (track->output()->ensure_io (ChanCount(DataType::AUDIO, output_channels), false, this)) {
1730 error << string_compose (
1731 _("cannot configure %1 in/%2 out configuration for new audio track"),
1732 input_channels, output_channels)
1733 << endmsg;
1734 goto failed;
1738 if (route_group) {
1739 route_group->add (track);
1742 track->non_realtime_input_change();
1744 track->DiskstreamChanged.connect_same_thread (*this, boost::bind (&Session::resort_routes, this));
1745 track->set_remote_control_id (control_id);
1746 ++control_id;
1748 new_routes.push_back (track);
1749 ret.push_back (track);
1752 catch (failed_constructor &err) {
1753 error << _("Session: could not create new audio track.") << endmsg;
1754 goto failed;
1757 catch (AudioEngine::PortRegistrationFailure& pfe) {
1759 error << pfe.what() << endmsg;
1760 goto failed;
1763 --how_many;
1766 failed:
1767 if (!new_routes.empty()) {
1768 add_routes (new_routes, true, true);
1771 return ret;
1774 void
1775 Session::set_remote_control_ids ()
1777 RemoteModel m = Config->get_remote_model();
1778 bool emit_signal = false;
1780 boost::shared_ptr<RouteList> r = routes.reader ();
1782 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1783 if (MixerOrdered == m) {
1784 int32_t order = (*i)->order_key(N_("signal"));
1785 (*i)->set_remote_control_id (order+1, false);
1786 emit_signal = true;
1787 } else if (EditorOrdered == m) {
1788 int32_t order = (*i)->order_key(N_("editor"));
1789 (*i)->set_remote_control_id (order+1, false);
1790 emit_signal = true;
1791 } else if (UserOrdered == m) {
1792 //do nothing ... only changes to remote id's are initiated by user
1796 if (emit_signal) {
1797 Route::RemoteControlIDChange();
1801 /** Caller must not hold process lock.
1802 * @param name_template string to use for the start of the name, or "" to use "Bus".
1804 RouteList
1805 Session::new_audio_route (int input_channels, int output_channels, RouteGroup* route_group, uint32_t how_many, string name_template)
1807 char bus_name[32];
1808 uint32_t bus_id = 0;
1809 string port;
1810 RouteList ret;
1811 uint32_t control_id;
1813 control_id = ntracks() + nbusses() + 1;
1815 bool const use_number = (how_many != 1);
1816 while (how_many) {
1817 if (!find_route_name (name_template.empty () ? _("Bus") : name_template, ++bus_id, bus_name, sizeof(bus_name), use_number)) {
1818 error << "cannot find name for new audio bus" << endmsg;
1819 goto failure;
1822 try {
1823 boost::shared_ptr<Route> bus (new Route (*this, bus_name, Route::Flag(0), DataType::AUDIO));
1825 if (bus->init ()) {
1826 goto failure;
1829 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1830 boost_debug_shared_ptr_mark_interesting (bus.get(), "Route");
1831 #endif
1833 Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
1835 if (bus->input()->ensure_io (ChanCount(DataType::AUDIO, input_channels), false, this)) {
1836 error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
1837 input_channels, output_channels)
1838 << endmsg;
1839 goto failure;
1843 if (bus->output()->ensure_io (ChanCount(DataType::AUDIO, output_channels), false, this)) {
1844 error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
1845 input_channels, output_channels)
1846 << endmsg;
1847 goto failure;
1851 if (route_group) {
1852 route_group->add (bus);
1854 bus->set_remote_control_id (control_id);
1855 ++control_id;
1857 bus->add_internal_return ();
1859 ret.push_back (bus);
1863 catch (failed_constructor &err) {
1864 error << _("Session: could not create new audio route.") << endmsg;
1865 goto failure;
1868 catch (AudioEngine::PortRegistrationFailure& pfe) {
1869 error << pfe.what() << endmsg;
1870 goto failure;
1874 --how_many;
1877 failure:
1878 if (!ret.empty()) {
1879 add_routes (ret, true, true);
1882 return ret;
1886 RouteList
1887 Session::new_route_from_template (uint32_t how_many, const std::string& template_path)
1889 char name[32];
1890 RouteList ret;
1891 uint32_t control_id;
1892 XMLTree tree;
1893 uint32_t number = 0;
1895 if (!tree.read (template_path.c_str())) {
1896 return ret;
1899 XMLNode* node = tree.root();
1901 control_id = ntracks() + nbusses() + 1;
1903 while (how_many) {
1905 XMLNode node_copy (*node); // make a copy so we can change the name if we need to
1907 std::string node_name = IO::name_from_state (*node_copy.children().front());
1909 /* generate a new name by adding a number to the end of the template name */
1910 if (!find_route_name (node_name.c_str(), ++number, name, sizeof(name), true)) {
1911 fatal << _("Session: UINT_MAX routes? impossible!") << endmsg;
1912 /*NOTREACHED*/
1915 /* set IO children to use the new name */
1916 XMLNodeList const & children = node_copy.children ();
1917 for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
1918 if ((*i)->name() == IO::state_node_name) {
1919 IO::set_name_in_state (**i, name);
1923 Track::zero_diskstream_id_in_xml (node_copy);
1925 try {
1926 boost::shared_ptr<Route> route (XMLRouteFactory (node_copy, 3000));
1928 if (route == 0) {
1929 error << _("Session: cannot create track/bus from template description") << endmsg;
1930 goto out;
1933 if (boost::dynamic_pointer_cast<Track>(route)) {
1934 /* force input/output change signals so that the new diskstream
1935 picks up the configuration of the route. During session
1936 loading this normally happens in a different way.
1939 Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
1941 IOChange change (IOChange::Type (IOChange::ConfigurationChanged | IOChange::ConnectionsChanged));
1942 change.after = route->input()->n_ports();
1943 route->input()->changed (change, this);
1944 change.after = route->output()->n_ports();
1945 route->output()->changed (change, this);
1948 route->set_remote_control_id (control_id);
1949 ++control_id;
1951 ret.push_back (route);
1954 catch (failed_constructor &err) {
1955 error << _("Session: could not create new route from template") << endmsg;
1956 goto out;
1959 catch (AudioEngine::PortRegistrationFailure& pfe) {
1960 error << pfe.what() << endmsg;
1961 goto out;
1964 --how_many;
1967 out:
1968 if (!ret.empty()) {
1969 add_routes (ret, true, true);
1972 return ret;
1975 void
1976 Session::add_routes (RouteList& new_routes, bool auto_connect, bool save)
1978 ChanCount existing_inputs;
1979 ChanCount existing_outputs;
1981 count_existing_track_channels (existing_inputs, existing_outputs);
1984 RCUWriter<RouteList> writer (routes);
1985 boost::shared_ptr<RouteList> r = writer.get_copy ();
1986 r->insert (r->end(), new_routes.begin(), new_routes.end());
1989 /* if there is no control out and we're not in the middle of loading,
1990 resort the graph here. if there is a control out, we will resort
1991 toward the end of this method. if we are in the middle of loading,
1992 we will resort when done.
1995 if (!_monitor_out && IO::connecting_legal) {
1996 resort_routes_using (r);
2000 for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) {
2002 boost::weak_ptr<Route> wpr (*x);
2003 boost::shared_ptr<Route> r (*x);
2005 r->listen_changed.connect_same_thread (*this, boost::bind (&Session::route_listen_changed, this, _1, wpr));
2006 r->solo_changed.connect_same_thread (*this, boost::bind (&Session::route_solo_changed, this, _1, _2, wpr));
2007 r->solo_isolated_changed.connect_same_thread (*this, boost::bind (&Session::route_solo_isolated_changed, this, _1, wpr));
2008 r->mute_changed.connect_same_thread (*this, boost::bind (&Session::route_mute_changed, this, _1));
2009 r->output()->changed.connect_same_thread (*this, boost::bind (&Session::set_worst_io_latencies_x, this, _1, _2));
2010 r->processors_changed.connect_same_thread (*this, boost::bind (&Session::route_processors_changed, this, _1));
2011 r->order_key_changed.connect_same_thread (*this, boost::bind (&Session::route_order_key_changed, this));
2013 if (r->is_master()) {
2014 _master_out = r;
2017 if (r->is_monitor()) {
2018 _monitor_out = r;
2021 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (r);
2022 if (tr) {
2023 tr->PlaylistChanged.connect_same_thread (*this, boost::bind (&Session::track_playlist_changed, this, boost::weak_ptr<Track> (tr)));
2024 track_playlist_changed (boost::weak_ptr<Track> (tr));
2025 tr->RecordEnableChanged.connect_same_thread (*this, boost::bind (&Session::update_have_rec_enabled_track, this));
2027 boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (tr);
2028 if (mt) {
2029 mt->StepEditStatusChange.connect_same_thread (*this, boost::bind (&Session::step_edit_status_change, this, _1));
2030 mt->output()->changed.connect_same_thread (*this, boost::bind (&Session::midi_output_change_handler, this, _1, _2, boost::weak_ptr<Route>(mt)));
2034 if (auto_connect) {
2035 auto_connect_route (r, existing_inputs, existing_outputs, true);
2039 if (_monitor_out && IO::connecting_legal) {
2041 for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) {
2042 if ((*x)->is_monitor()) {
2043 /* relax */
2044 } else if ((*x)->is_master()) {
2045 /* relax */
2046 } else {
2047 (*x)->listen_via_monitor ();
2051 resort_routes ();
2054 set_dirty();
2056 if (save) {
2057 save_state (_current_snapshot_name);
2060 RouteAdded (new_routes); /* EMIT SIGNAL */
2061 Route::RemoteControlIDChange (); /* EMIT SIGNAL */
2064 void
2065 Session::globally_set_send_gains_to_zero (boost::shared_ptr<Route> dest)
2067 boost::shared_ptr<RouteList> r = routes.reader ();
2068 boost::shared_ptr<Send> s;
2070 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2071 if ((s = (*i)->internal_send_for (dest)) != 0) {
2072 s->amp()->gain_control()->set_value (0.0);
2077 void
2078 Session::globally_set_send_gains_to_unity (boost::shared_ptr<Route> dest)
2080 boost::shared_ptr<RouteList> r = routes.reader ();
2081 boost::shared_ptr<Send> s;
2083 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2084 if ((s = (*i)->internal_send_for (dest)) != 0) {
2085 s->amp()->gain_control()->set_value (1.0);
2090 void
2091 Session::globally_set_send_gains_from_track(boost::shared_ptr<Route> dest)
2093 boost::shared_ptr<RouteList> r = routes.reader ();
2094 boost::shared_ptr<Send> s;
2096 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2097 if ((s = (*i)->internal_send_for (dest)) != 0) {
2098 s->amp()->gain_control()->set_value ((*i)->gain_control()->get_value());
2103 /** @param include_buses true to add sends to buses and tracks, false for just tracks */
2104 void
2105 Session::globally_add_internal_sends (boost::shared_ptr<Route> dest, Placement p, bool include_buses)
2107 boost::shared_ptr<RouteList> r = routes.reader ();
2108 boost::shared_ptr<RouteList> t (new RouteList);
2110 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2111 if (include_buses || boost::dynamic_pointer_cast<Track>(*i)) {
2112 t->push_back (*i);
2116 add_internal_sends (dest, p, t);
2119 void
2120 Session::add_internal_sends (boost::shared_ptr<Route> dest, Placement p, boost::shared_ptr<RouteList> senders)
2122 if (dest->is_monitor() || dest->is_master()) {
2123 return;
2126 if (!dest->internal_return()) {
2127 dest->add_internal_return();
2130 for (RouteList::iterator i = senders->begin(); i != senders->end(); ++i) {
2132 if ((*i)->is_monitor() || (*i)->is_master() || (*i) == dest) {
2133 continue;
2136 (*i)->listen_via (dest, p);
2139 graph_reordered ();
2142 void
2143 Session::remove_route (boost::shared_ptr<Route> route)
2145 if (((route == _master_out) || (route == _monitor_out)) && !Config->get_allow_special_bus_removal()) {
2146 return;
2149 route->set_solo (false, this);
2152 RCUWriter<RouteList> writer (routes);
2153 boost::shared_ptr<RouteList> rs = writer.get_copy ();
2155 rs->remove (route);
2157 /* deleting the master out seems like a dumb
2158 idea, but its more of a UI policy issue
2159 than our concern.
2162 if (route == _master_out) {
2163 _master_out = boost::shared_ptr<Route> ();
2166 if (route == _monitor_out) {
2168 /* cancel control outs for all routes */
2170 for (RouteList::iterator r = rs->begin(); r != rs->end(); ++r) {
2171 (*r)->drop_listen (_monitor_out);
2174 _monitor_out.reset ();
2177 /* writer goes out of scope, forces route list update */
2180 update_route_solo_state ();
2182 // We need to disconnect the route's inputs and outputs
2184 route->input()->disconnect (0);
2185 route->output()->disconnect (0);
2187 /* if the route had internal sends sending to it, remove them */
2188 if (route->internal_return()) {
2190 boost::shared_ptr<RouteList> r = routes.reader ();
2191 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2192 boost::shared_ptr<Send> s = (*i)->internal_send_for (route);
2193 if (s) {
2194 (*i)->remove_processor (s);
2199 boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (route);
2200 if (mt && mt->step_editing()) {
2201 if (_step_editors > 0) {
2202 _step_editors--;
2206 update_latency_compensation ();
2207 set_dirty();
2209 /* Re-sort routes to remove the graph's current references to the one that is
2210 * going away, then flush old references out of the graph.
2213 resort_routes ();
2214 route_graph->clear_other_chain ();
2216 /* get rid of it from the dead wood collection in the route list manager */
2218 /* XXX i think this is unsafe as it currently stands, but i am not sure. (pd, october 2nd, 2006) */
2220 routes.flush ();
2222 /* try to cause everyone to drop their references */
2224 route->drop_references ();
2226 sync_order_keys (N_("session"));
2228 Route::RemoteControlIDChange(); /* EMIT SIGNAL */
2230 /* save the new state of the world */
2232 if (save_state (_current_snapshot_name)) {
2233 save_history (_current_snapshot_name);
2237 void
2238 Session::route_mute_changed (void* /*src*/)
2240 set_dirty ();
2243 void
2244 Session::route_listen_changed (void* /*src*/, boost::weak_ptr<Route> wpr)
2246 boost::shared_ptr<Route> route = wpr.lock();
2247 if (!route) {
2248 error << string_compose (_("programming error: %1"), X_("invalid route weak ptr passed to route_solo_changed")) << endmsg;
2249 return;
2252 if (route->listening_via_monitor ()) {
2254 if (Config->get_exclusive_solo()) {
2255 /* new listen: disable all other listen */
2256 boost::shared_ptr<RouteList> r = routes.reader ();
2257 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2258 if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_hidden()) {
2259 continue;
2261 (*i)->set_listen (false, this);
2265 _listen_cnt++;
2267 } else if (_listen_cnt > 0) {
2269 _listen_cnt--;
2272 update_route_solo_state ();
2274 void
2275 Session::route_solo_isolated_changed (void* /*src*/, boost::weak_ptr<Route> wpr)
2277 boost::shared_ptr<Route> route = wpr.lock ();
2279 if (!route) {
2280 /* should not happen */
2281 error << string_compose (_("programming error: %1"), X_("invalid route weak ptr passed to route_solo_changed")) << endmsg;
2282 return;
2285 bool send_changed = false;
2287 if (route->solo_isolated()) {
2288 if (_solo_isolated_cnt == 0) {
2289 send_changed = true;
2291 _solo_isolated_cnt++;
2292 } else if (_solo_isolated_cnt > 0) {
2293 _solo_isolated_cnt--;
2294 if (_solo_isolated_cnt == 0) {
2295 send_changed = true;
2299 if (send_changed) {
2300 IsolatedChanged (); /* EMIT SIGNAL */
2304 void
2305 Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_ptr<Route> wpr)
2307 if (!self_solo_change) {
2308 // session doesn't care about changes to soloed-by-others
2309 return;
2312 if (solo_update_disabled) {
2313 // We know already
2314 return;
2317 boost::shared_ptr<Route> route = wpr.lock ();
2319 if (!route) {
2320 /* should not happen */
2321 error << string_compose (_("programming error: %1"), X_("invalid route weak ptr passed to route_solo_changed")) << endmsg;
2322 return;
2325 boost::shared_ptr<RouteList> r = routes.reader ();
2326 int32_t delta;
2328 if (route->self_soloed()) {
2329 delta = 1;
2330 } else {
2331 delta = -1;
2334 if (delta == 1 && Config->get_exclusive_solo()) {
2335 /* new solo: disable all other solos */
2336 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2337 if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_hidden()) {
2338 continue;
2340 (*i)->set_solo (false, this);
2344 solo_update_disabled = true;
2346 RouteList uninvolved;
2348 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2349 bool via_sends_only;
2350 bool in_signal_flow;
2352 if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_hidden()) {
2353 continue;
2356 in_signal_flow = false;
2358 if ((*i)->feeds (route, &via_sends_only)) {
2359 if (!via_sends_only) {
2360 if (!route->soloed_by_others_upstream()) {
2361 (*i)->mod_solo_by_others_downstream (delta);
2363 in_signal_flow = true;
2367 if (route->feeds (*i, &via_sends_only)) {
2368 (*i)->mod_solo_by_others_upstream (delta);
2369 in_signal_flow = true;
2372 if (!in_signal_flow) {
2373 uninvolved.push_back (*i);
2377 solo_update_disabled = false;
2378 update_route_solo_state (r);
2380 /* now notify that the mute state of the routes not involved in the signal
2381 pathway of the just-solo-changed route may have altered.
2384 for (RouteList::iterator i = uninvolved.begin(); i != uninvolved.end(); ++i) {
2385 (*i)->mute_changed (this);
2388 SoloChanged (); /* EMIT SIGNAL */
2389 set_dirty();
2392 void
2393 Session::update_route_solo_state (boost::shared_ptr<RouteList> r)
2395 /* now figure out if anything that matters is soloed (or is "listening")*/
2397 bool something_soloed = false;
2398 uint32_t listeners = 0;
2399 uint32_t isolated = 0;
2401 if (!r) {
2402 r = routes.reader();
2405 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2406 if (!(*i)->is_master() && !(*i)->is_monitor() && !(*i)->is_hidden() && (*i)->self_soloed()) {
2407 something_soloed = true;
2410 if (!(*i)->is_hidden() && (*i)->listening_via_monitor()) {
2411 if (Config->get_solo_control_is_listen_control()) {
2412 listeners++;
2413 } else {
2414 (*i)->set_listen (false, this);
2418 if ((*i)->solo_isolated()) {
2419 isolated++;
2423 if (something_soloed != _non_soloed_outs_muted) {
2424 _non_soloed_outs_muted = something_soloed;
2425 SoloActive (_non_soloed_outs_muted); /* EMIT SIGNAL */
2428 _listen_cnt = listeners;
2430 if (isolated != _solo_isolated_cnt) {
2431 _solo_isolated_cnt = isolated;
2432 IsolatedChanged (); /* EMIT SIGNAL */
2436 boost::shared_ptr<RouteList>
2437 Session::get_routes_with_internal_returns() const
2439 boost::shared_ptr<RouteList> r = routes.reader ();
2440 boost::shared_ptr<RouteList> rl (new RouteList);
2442 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2443 if ((*i)->internal_return ()) {
2444 rl->push_back (*i);
2447 return rl;
2450 bool
2451 Session::io_name_is_legal (const std::string& name)
2453 boost::shared_ptr<RouteList> r = routes.reader ();
2455 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2456 if ((*i)->name() == name) {
2457 return false;
2460 if ((*i)->has_io_processor_named (name)) {
2461 return false;
2465 return true;
2468 boost::shared_ptr<Route>
2469 Session::route_by_name (string name)
2471 boost::shared_ptr<RouteList> r = routes.reader ();
2473 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2474 if ((*i)->name() == name) {
2475 return *i;
2479 return boost::shared_ptr<Route> ((Route*) 0);
2482 boost::shared_ptr<Route>
2483 Session::route_by_id (PBD::ID id)
2485 boost::shared_ptr<RouteList> r = routes.reader ();
2487 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2488 if ((*i)->id() == id) {
2489 return *i;
2493 return boost::shared_ptr<Route> ((Route*) 0);
2496 boost::shared_ptr<Route>
2497 Session::route_by_remote_id (uint32_t id)
2499 boost::shared_ptr<RouteList> r = routes.reader ();
2501 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2502 if ((*i)->remote_control_id() == id) {
2503 return *i;
2507 return boost::shared_ptr<Route> ((Route*) 0);
2510 void
2511 Session::playlist_region_added (boost::weak_ptr<Region> w)
2513 boost::shared_ptr<Region> r = w.lock ();
2514 if (!r) {
2515 return;
2518 /* These are the operations that are currently in progress... */
2519 list<GQuark> curr = _current_trans_quarks;
2520 curr.sort ();
2522 /* ...and these are the operations during which we want to update
2523 the session range location markers.
2525 list<GQuark> ops;
2526 ops.push_back (Operations::capture);
2527 ops.push_back (Operations::paste);
2528 ops.push_back (Operations::duplicate_region);
2529 ops.push_back (Operations::insert_file);
2530 ops.push_back (Operations::insert_region);
2531 ops.push_back (Operations::drag_region_brush);
2532 ops.push_back (Operations::region_drag);
2533 ops.push_back (Operations::selection_grab);
2534 ops.push_back (Operations::region_fill);
2535 ops.push_back (Operations::fill_selection);
2536 ops.push_back (Operations::create_region);
2537 ops.push_back (Operations::region_copy);
2538 ops.push_back (Operations::fixed_time_region_copy);
2539 ops.sort ();
2541 /* See if any of the current operations match the ones that we want */
2542 list<GQuark> in;
2543 set_intersection (_current_trans_quarks.begin(), _current_trans_quarks.end(), ops.begin(), ops.end(), back_inserter (in));
2545 /* If so, update the session range markers */
2546 if (!in.empty ()) {
2547 maybe_update_session_range (r->position (), r->last_frame ());
2551 /** Update the session range markers if a is before the current start or
2552 * b is after the current end.
2554 void
2555 Session::maybe_update_session_range (framepos_t a, framepos_t b)
2557 if (_state_of_the_state & Loading) {
2558 return;
2561 if (_session_range_location == 0) {
2563 add_session_range_location (a, b);
2565 } else {
2567 if (a < _session_range_location->start()) {
2568 _session_range_location->set_start (a);
2571 if (b > _session_range_location->end()) {
2572 _session_range_location->set_end (b);
2577 void
2578 Session::playlist_ranges_moved (list<Evoral::RangeMove<framepos_t> > const & ranges)
2580 for (list<Evoral::RangeMove<framepos_t> >::const_iterator i = ranges.begin(); i != ranges.end(); ++i) {
2581 maybe_update_session_range (i->to, i->to + i->length);
2585 void
2586 Session::playlist_regions_extended (list<Evoral::Range<framepos_t> > const & ranges)
2588 for (list<Evoral::Range<framepos_t> >::const_iterator i = ranges.begin(); i != ranges.end(); ++i) {
2589 maybe_update_session_range (i->from, i->to);
2593 /* Region management */
2595 boost::shared_ptr<Region>
2596 Session::find_whole_file_parent (boost::shared_ptr<Region const> child) const
2598 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2599 RegionFactory::RegionMap::const_iterator i;
2600 boost::shared_ptr<Region> region;
2602 Glib::Mutex::Lock lm (region_lock);
2604 for (i = regions.begin(); i != regions.end(); ++i) {
2606 region = i->second;
2608 if (region->whole_file()) {
2610 if (child->source_equivalent (region)) {
2611 return region;
2616 return boost::shared_ptr<Region> ();
2620 Session::destroy_sources (list<boost::shared_ptr<Source> > srcs)
2622 set<boost::shared_ptr<Region> > relevant_regions;
2624 for (list<boost::shared_ptr<Source> >::iterator s = srcs.begin(); s != srcs.end(); ++s) {
2625 RegionFactory::get_regions_using_source (*s, relevant_regions);
2628 for (set<boost::shared_ptr<Region> >::iterator r = relevant_regions.begin(); r != relevant_regions.end(); ) {
2629 set<boost::shared_ptr<Region> >::iterator tmp;
2631 tmp = r;
2632 ++tmp;
2634 playlists->destroy_region (*r);
2635 RegionFactory::map_remove (*r);
2637 (*r)->drop_sources ();
2638 (*r)->drop_references ();
2640 relevant_regions.erase (r);
2642 r = tmp;
2645 for (list<boost::shared_ptr<Source> >::iterator s = srcs.begin(); s != srcs.end(); ) {
2648 Glib::Mutex::Lock ls (source_lock);
2649 /* remove from the main source list */
2650 sources.erase ((*s)->id());
2653 (*s)->mark_for_remove ();
2654 (*s)->drop_references ();
2656 s = srcs.erase (s);
2659 return 0;
2663 Session::remove_last_capture ()
2665 list<boost::shared_ptr<Source> > srcs;
2667 boost::shared_ptr<RouteList> rl = routes.reader ();
2668 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
2669 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
2670 if (!tr) {
2671 continue;
2674 list<boost::shared_ptr<Source> >& l = tr->last_capture_sources();
2676 if (!l.empty()) {
2677 srcs.insert (srcs.end(), l.begin(), l.end());
2678 l.clear ();
2682 destroy_sources (srcs);
2684 save_state (_current_snapshot_name);
2686 return 0;
2689 /* Source Management */
2691 void
2692 Session::add_source (boost::shared_ptr<Source> source)
2694 pair<SourceMap::key_type, SourceMap::mapped_type> entry;
2695 pair<SourceMap::iterator,bool> result;
2697 entry.first = source->id();
2698 entry.second = source;
2701 Glib::Mutex::Lock lm (source_lock);
2702 result = sources.insert (entry);
2705 if (result.second) {
2707 /* yay, new source */
2709 set_dirty();
2711 boost::shared_ptr<AudioFileSource> afs;
2713 if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(source)) != 0) {
2714 if (Config->get_auto_analyse_audio()) {
2715 Analyser::queue_source_for_analysis (source, false);
2719 source->DropReferences.connect_same_thread (*this, boost::bind (&Session::remove_source, this, boost::weak_ptr<Source> (source)));
2723 void
2724 Session::remove_source (boost::weak_ptr<Source> src)
2726 if (_state_of_the_state & Deletion) {
2727 return;
2730 SourceMap::iterator i;
2731 boost::shared_ptr<Source> source = src.lock();
2733 if (!source) {
2734 return;
2738 Glib::Mutex::Lock lm (source_lock);
2740 if ((i = sources.find (source->id())) != sources.end()) {
2741 sources.erase (i);
2745 if (!_state_of_the_state & InCleanup) {
2747 /* save state so we don't end up with a session file
2748 referring to non-existent sources.
2751 save_state (_current_snapshot_name);
2755 boost::shared_ptr<Source>
2756 Session::source_by_id (const PBD::ID& id)
2758 Glib::Mutex::Lock lm (source_lock);
2759 SourceMap::iterator i;
2760 boost::shared_ptr<Source> source;
2762 if ((i = sources.find (id)) != sources.end()) {
2763 source = i->second;
2766 return source;
2769 boost::shared_ptr<Source>
2770 Session::source_by_path_and_channel (const string& path, uint16_t chn)
2772 Glib::Mutex::Lock lm (source_lock);
2774 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2775 boost::shared_ptr<AudioFileSource> afs
2776 = boost::dynamic_pointer_cast<AudioFileSource>(i->second);
2778 if (afs && afs->path() == path && chn == afs->channel()) {
2779 return afs;
2782 return boost::shared_ptr<Source>();
2785 uint32_t
2786 Session::count_sources_by_origin (const string& path)
2788 uint32_t cnt = 0;
2789 Glib::Mutex::Lock lm (source_lock);
2791 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2792 boost::shared_ptr<FileSource> fs
2793 = boost::dynamic_pointer_cast<FileSource>(i->second);
2795 if (fs && fs->origin() == path) {
2796 ++cnt;
2800 return cnt;
2804 string
2805 Session::change_source_path_by_name (string path, string oldname, string newname, bool destructive)
2807 string look_for;
2808 string old_basename = PBD::basename_nosuffix (oldname);
2809 string new_legalized = legalize_for_path (newname);
2811 /* note: we know (or assume) the old path is already valid */
2813 if (destructive) {
2815 /* destructive file sources have a name of the form:
2817 /path/to/Tnnnn-NAME(%[LR])?.wav
2819 the task here is to replace NAME with the new name.
2822 string dir;
2823 string prefix;
2824 string::size_type dash;
2826 dir = Glib::path_get_dirname (path);
2827 path = Glib::path_get_basename (path);
2829 /* '-' is not a legal character for the NAME part of the path */
2831 if ((dash = path.find_last_of ('-')) == string::npos) {
2832 return "";
2835 prefix = path.substr (0, dash);
2837 path += prefix;
2838 path += '-';
2839 path += new_legalized;
2840 path += native_header_format_extension (config.get_native_file_header_format(), DataType::AUDIO);
2841 path = Glib::build_filename (dir, path);
2843 } else {
2845 /* non-destructive file sources have a name of the form:
2847 /path/to/NAME-nnnnn(%[LR])?.ext
2849 the task here is to replace NAME with the new name.
2852 string dir;
2853 string suffix;
2854 string::size_type dash;
2855 string::size_type postfix;
2857 dir = Glib::path_get_dirname (path);
2858 path = Glib::path_get_basename (path);
2860 /* '-' is not a legal character for the NAME part of the path */
2862 if ((dash = path.find_last_of ('-')) == string::npos) {
2863 return "";
2866 suffix = path.substr (dash+1);
2868 // Suffix is now everything after the dash. Now we need to eliminate
2869 // the nnnnn part, which is done by either finding a '%' or a '.'
2871 postfix = suffix.find_last_of ("%");
2872 if (postfix == string::npos) {
2873 postfix = suffix.find_last_of ('.');
2876 if (postfix != string::npos) {
2877 suffix = suffix.substr (postfix);
2878 } else {
2879 error << "Logic error in Session::change_source_path_by_name(), please report" << endl;
2880 return "";
2883 const uint32_t limit = 10000;
2884 char buf[PATH_MAX+1];
2886 for (uint32_t cnt = 1; cnt <= limit; ++cnt) {
2888 snprintf (buf, sizeof(buf), "%s-%u%s", newname.c_str(), cnt, suffix.c_str());
2890 if (!matching_unsuffixed_filename_exists_in (dir, buf)) {
2891 path = Glib::build_filename (dir, buf);
2892 break;
2895 path = "";
2898 if (path.empty()) {
2899 fatal << string_compose (_("FATAL ERROR! Could not find a suitable version of %1 for a rename"),
2900 newname) << endl;
2901 /*NOTREACHED*/
2905 return path;
2908 /** Return the full path (in some session directory) for a new within-session source.
2909 * \a name must be a session-unique name that does not contain slashes
2910 * (e.g. as returned by new_*_source_name)
2912 string
2913 Session::new_source_path_from_name (DataType type, const string& name)
2915 assert(name.find("/") == string::npos);
2917 SessionDirectory sdir(get_best_session_directory_for_new_source());
2919 sys::path p;
2920 if (type == DataType::AUDIO) {
2921 p = sdir.sound_path();
2922 } else if (type == DataType::MIDI) {
2923 p = sdir.midi_path();
2924 } else {
2925 error << "Unknown source type, unable to create file path" << endmsg;
2926 return "";
2929 p /= name;
2930 return p.to_string();
2933 string
2934 Session::peak_path (string base) const
2936 sys::path peakfile_path(_session_dir->peak_path());
2937 peakfile_path /= base + peakfile_suffix;
2938 return peakfile_path.to_string();
2941 /** Return a unique name based on \a base for a new internal audio source */
2942 string
2943 Session::new_audio_source_name (const string& base, uint32_t nchan, uint32_t chan, bool destructive)
2945 uint32_t cnt;
2946 char buf[PATH_MAX+1];
2947 const uint32_t limit = 10000;
2948 string legalized;
2949 string ext = native_header_format_extension (config.get_native_file_header_format(), DataType::AUDIO);
2951 buf[0] = '\0';
2952 legalized = legalize_for_path (base);
2954 // Find a "version" of the base name that doesn't exist in any of the possible directories.
2955 for (cnt = (destructive ? ++destructive_index : 1); cnt <= limit; ++cnt) {
2957 vector<space_and_path>::iterator i;
2958 uint32_t existing = 0;
2960 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2962 if (destructive) {
2964 if (nchan < 2) {
2965 snprintf (buf, sizeof(buf), "T%04d-%s%s",
2966 cnt, legalized.c_str(), ext.c_str());
2967 } else if (nchan == 2) {
2968 if (chan == 0) {
2969 snprintf (buf, sizeof(buf), "T%04d-%s%%L%s",
2970 cnt, legalized.c_str(), ext.c_str());
2971 } else {
2972 snprintf (buf, sizeof(buf), "T%04d-%s%%R%s",
2973 cnt, legalized.c_str(), ext.c_str());
2975 } else if (nchan < 26) {
2976 snprintf (buf, sizeof(buf), "T%04d-%s%%%c%s",
2977 cnt, legalized.c_str(), 'a' + chan, ext.c_str());
2978 } else {
2979 snprintf (buf, sizeof(buf), "T%04d-%s%s",
2980 cnt, legalized.c_str(), ext.c_str());
2983 } else {
2985 if (nchan < 2) {
2986 snprintf (buf, sizeof(buf), "%s-%u%s", legalized.c_str(), cnt, ext.c_str());
2987 } else if (nchan == 2) {
2988 if (chan == 0) {
2989 snprintf (buf, sizeof(buf), "%s-%u%%L%s", legalized.c_str(), cnt, ext.c_str());
2990 } else {
2991 snprintf (buf, sizeof(buf), "%s-%u%%R%s", legalized.c_str(), cnt, ext.c_str());
2993 } else if (nchan < 26) {
2994 snprintf (buf, sizeof(buf), "%s-%u%%%c%s", legalized.c_str(), cnt, 'a' + chan, ext.c_str());
2995 } else {
2996 snprintf (buf, sizeof(buf), "%s-%u%s", legalized.c_str(), cnt, ext.c_str());
3000 SessionDirectory sdir((*i).path);
3002 string spath = sdir.sound_path().to_string();
3004 /* note that we search *without* the extension so that
3005 we don't end up both "Audio 1-1.wav" and "Audio 1-1.caf"
3006 in the event that this new name is required for
3007 a file format change.
3010 if (matching_unsuffixed_filename_exists_in (spath, buf)) {
3011 existing++;
3012 break;
3016 if (existing == 0) {
3017 break;
3020 if (cnt > limit) {
3021 error << string_compose(
3022 _("There are already %1 recordings for %2, which I consider too many."),
3023 limit, base) << endmsg;
3024 destroy ();
3025 throw failed_constructor();
3029 return Glib::path_get_basename (buf);
3032 /** Create a new within-session audio source */
3033 boost::shared_ptr<AudioFileSource>
3034 Session::create_audio_source_for_session (size_t n_chans, string const & n, uint32_t chan, bool destructive)
3036 const string name = new_audio_source_name (n, n_chans, chan, destructive);
3037 const string path = new_source_path_from_name(DataType::AUDIO, name);
3039 return boost::dynamic_pointer_cast<AudioFileSource> (
3040 SourceFactory::createWritable (DataType::AUDIO, *this, path, string(), destructive, frame_rate()));
3043 /** Return a unique name based on \a base for a new internal MIDI source */
3044 string
3045 Session::new_midi_source_name (const string& base)
3047 uint32_t cnt;
3048 char buf[PATH_MAX+1];
3049 const uint32_t limit = 10000;
3050 string legalized;
3052 buf[0] = '\0';
3053 legalized = legalize_for_path (base);
3055 // Find a "version" of the file name that doesn't exist in any of the possible directories.
3056 for (cnt = 1; cnt <= limit; ++cnt) {
3058 vector<space_and_path>::iterator i;
3059 uint32_t existing = 0;
3061 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3063 SessionDirectory sdir((*i).path);
3065 sys::path p = sdir.midi_path();
3066 p /= legalized;
3068 snprintf (buf, sizeof(buf), "%s-%u.mid", p.to_string().c_str(), cnt);
3070 if (sys::exists (buf)) {
3071 existing++;
3075 if (existing == 0) {
3076 break;
3079 if (cnt > limit) {
3080 error << string_compose(
3081 _("There are already %1 recordings for %2, which I consider too many."),
3082 limit, base) << endmsg;
3083 destroy ();
3084 throw failed_constructor();
3088 return Glib::path_get_basename(buf);
3092 /** Create a new within-session MIDI source */
3093 boost::shared_ptr<MidiSource>
3094 Session::create_midi_source_for_session (Track* track, string const & n)
3096 /* try to use the existing write source for the track, to keep numbering sane
3099 if (track) {
3100 /*MidiTrack* mt = dynamic_cast<Track*> (track);
3101 assert (mt);
3104 list<boost::shared_ptr<Source> > l = track->steal_write_sources ();
3106 if (!l.empty()) {
3107 assert (boost::dynamic_pointer_cast<MidiSource> (l.front()));
3108 return boost::dynamic_pointer_cast<MidiSource> (l.front());
3112 const string name = new_midi_source_name (n);
3113 const string path = new_source_path_from_name (DataType::MIDI, name);
3115 return boost::dynamic_pointer_cast<SMFSource> (
3116 SourceFactory::createWritable (
3117 DataType::MIDI, *this, path, string(), false, frame_rate()));
3121 void
3122 Session::add_playlist (boost::shared_ptr<Playlist> playlist, bool unused)
3124 if (playlist->hidden()) {
3125 return;
3128 playlists->add (playlist);
3130 if (unused) {
3131 playlist->release();
3134 set_dirty();
3137 void
3138 Session::remove_playlist (boost::weak_ptr<Playlist> weak_playlist)
3140 if (_state_of_the_state & Deletion) {
3141 return;
3144 boost::shared_ptr<Playlist> playlist (weak_playlist.lock());
3146 if (!playlist) {
3147 return;
3150 playlists->remove (playlist);
3152 set_dirty();
3155 void
3156 Session::set_audition (boost::shared_ptr<Region> r)
3158 pending_audition_region = r;
3159 add_post_transport_work (PostTransportAudition);
3160 _butler->schedule_transport_work ();
3163 void
3164 Session::audition_playlist ()
3166 SessionEvent* ev = new SessionEvent (SessionEvent::Audition, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
3167 ev->region.reset ();
3168 queue_event (ev);
3171 void
3172 Session::non_realtime_set_audition ()
3174 if (!pending_audition_region) {
3175 auditioner->audition_current_playlist ();
3176 } else {
3177 auditioner->audition_region (pending_audition_region);
3178 pending_audition_region.reset ();
3180 AuditionActive (true); /* EMIT SIGNAL */
3183 void
3184 Session::audition_region (boost::shared_ptr<Region> r)
3186 SessionEvent* ev = new SessionEvent (SessionEvent::Audition, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
3187 ev->region = r;
3188 queue_event (ev);
3191 void
3192 Session::cancel_audition ()
3194 if (auditioner->auditioning()) {
3195 auditioner->cancel_audition ();
3196 AuditionActive (false); /* EMIT SIGNAL */
3200 bool
3201 Session::RoutePublicOrderSorter::operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b)
3203 if (a->is_monitor()) {
3204 return true;
3206 if (b->is_monitor()) {
3207 return false;
3209 return a->order_key(N_("signal")) < b->order_key(N_("signal"));
3212 bool
3213 Session::is_auditioning () const
3215 /* can be called before we have an auditioner object */
3216 if (auditioner) {
3217 return auditioner->auditioning();
3218 } else {
3219 return false;
3223 void
3224 Session::graph_reordered ()
3226 /* don't do this stuff if we are setting up connections
3227 from a set_state() call or creating new tracks. Ditto for deletion.
3230 if (_state_of_the_state & (InitialConnecting|Deletion)) {
3231 return;
3234 /* every track/bus asked for this to be handled but it was deferred because
3235 we were connecting. do it now.
3238 request_input_change_handling ();
3240 resort_routes ();
3242 /* force all diskstreams to update their capture offset values to
3243 reflect any changes in latencies within the graph.
3246 boost::shared_ptr<RouteList> rl = routes.reader ();
3247 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
3248 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
3249 if (tr) {
3250 tr->set_capture_offset ();
3255 framecnt_t
3256 Session::available_capture_duration ()
3258 float sample_bytes_on_disk = 4.0; // keep gcc happy
3260 switch (config.get_native_file_data_format()) {
3261 case FormatFloat:
3262 sample_bytes_on_disk = 4.0;
3263 break;
3265 case FormatInt24:
3266 sample_bytes_on_disk = 3.0;
3267 break;
3269 case FormatInt16:
3270 sample_bytes_on_disk = 2.0;
3271 break;
3273 default:
3274 /* impossible, but keep some gcc versions happy */
3275 fatal << string_compose (_("programming error: %1"),
3276 X_("illegal native file data format"))
3277 << endmsg;
3278 /*NOTREACHED*/
3281 double scale = 4096.0 / sample_bytes_on_disk;
3283 if (_total_free_4k_blocks * scale > (double) max_framecnt) {
3284 return max_framecnt;
3287 return (framecnt_t) floor (_total_free_4k_blocks * scale);
3290 void
3291 Session::add_bundle (boost::shared_ptr<Bundle> bundle)
3294 RCUWriter<BundleList> writer (_bundles);
3295 boost::shared_ptr<BundleList> b = writer.get_copy ();
3296 b->push_back (bundle);
3299 BundleAdded (bundle); /* EMIT SIGNAL */
3301 set_dirty();
3304 void
3305 Session::remove_bundle (boost::shared_ptr<Bundle> bundle)
3307 bool removed = false;
3310 RCUWriter<BundleList> writer (_bundles);
3311 boost::shared_ptr<BundleList> b = writer.get_copy ();
3312 BundleList::iterator i = find (b->begin(), b->end(), bundle);
3314 if (i != b->end()) {
3315 b->erase (i);
3316 removed = true;
3320 if (removed) {
3321 BundleRemoved (bundle); /* EMIT SIGNAL */
3324 set_dirty();
3327 boost::shared_ptr<Bundle>
3328 Session::bundle_by_name (string name) const
3330 boost::shared_ptr<BundleList> b = _bundles.reader ();
3332 for (BundleList::const_iterator i = b->begin(); i != b->end(); ++i) {
3333 if ((*i)->name() == name) {
3334 return* i;
3338 return boost::shared_ptr<Bundle> ();
3341 void
3342 Session::tempo_map_changed (const PropertyChange&)
3344 clear_clicks ();
3346 playlists->update_after_tempo_map_change ();
3348 _locations->apply (*this, &Session::update_locations_after_tempo_map_change);
3350 set_dirty ();
3353 void
3354 Session::update_locations_after_tempo_map_change (Locations::LocationList& loc)
3356 for (Locations::LocationList::iterator i = loc.begin(); i != loc.end(); ++i) {
3357 (*i)->recompute_frames_from_bbt ();
3361 /** Ensures that all buffers (scratch, send, silent, etc) are allocated for
3362 * the given count with the current block size.
3364 void
3365 Session::ensure_buffers (ChanCount howmany)
3367 BufferManager::ensure_buffers (howmany);
3370 void
3371 Session::ensure_buffer_set(BufferSet& buffers, const ChanCount& count)
3373 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
3374 buffers.ensure_buffers(*t, count.get(*t), _engine.raw_buffer_size(*t));
3378 uint32_t
3379 Session::next_insert_id ()
3381 /* this doesn't really loop forever. just think about it */
3383 while (true) {
3384 for (boost::dynamic_bitset<uint32_t>::size_type n = 0; n < insert_bitset.size(); ++n) {
3385 if (!insert_bitset[n]) {
3386 insert_bitset[n] = true;
3387 return n;
3392 /* none available, so resize and try again */
3394 insert_bitset.resize (insert_bitset.size() + 16, false);
3398 uint32_t
3399 Session::next_send_id ()
3401 /* this doesn't really loop forever. just think about it */
3403 while (true) {
3404 for (boost::dynamic_bitset<uint32_t>::size_type n = 0; n < send_bitset.size(); ++n) {
3405 if (!send_bitset[n]) {
3406 send_bitset[n] = true;
3407 return n;
3412 /* none available, so resize and try again */
3414 send_bitset.resize (send_bitset.size() + 16, false);
3418 uint32_t
3419 Session::next_return_id ()
3421 /* this doesn't really loop forever. just think about it */
3423 while (true) {
3424 for (boost::dynamic_bitset<uint32_t>::size_type n = 0; n < return_bitset.size(); ++n) {
3425 if (!return_bitset[n]) {
3426 return_bitset[n] = true;
3427 return n;
3432 /* none available, so resize and try again */
3434 return_bitset.resize (return_bitset.size() + 16, false);
3438 void
3439 Session::mark_send_id (uint32_t id)
3441 if (id >= send_bitset.size()) {
3442 send_bitset.resize (id+16, false);
3444 if (send_bitset[id]) {
3445 warning << string_compose (_("send ID %1 appears to be in use already"), id) << endmsg;
3447 send_bitset[id] = true;
3450 void
3451 Session::mark_return_id (uint32_t id)
3453 if (id >= return_bitset.size()) {
3454 return_bitset.resize (id+16, false);
3456 if (return_bitset[id]) {
3457 warning << string_compose (_("return ID %1 appears to be in use already"), id) << endmsg;
3459 return_bitset[id] = true;
3462 void
3463 Session::mark_insert_id (uint32_t id)
3465 if (id >= insert_bitset.size()) {
3466 insert_bitset.resize (id+16, false);
3468 if (insert_bitset[id]) {
3469 warning << string_compose (_("insert ID %1 appears to be in use already"), id) << endmsg;
3471 insert_bitset[id] = true;
3474 void
3475 Session::unmark_send_id (uint32_t id)
3477 if (id < send_bitset.size()) {
3478 send_bitset[id] = false;
3482 void
3483 Session::unmark_return_id (uint32_t id)
3485 if (id < return_bitset.size()) {
3486 return_bitset[id] = false;
3490 void
3491 Session::unmark_insert_id (uint32_t id)
3493 if (id < insert_bitset.size()) {
3494 insert_bitset[id] = false;
3499 /* Named Selection management */
3501 boost::shared_ptr<NamedSelection>
3502 Session::named_selection_by_name (string name)
3504 Glib::Mutex::Lock lm (named_selection_lock);
3505 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
3506 if ((*i)->name == name) {
3507 return *i;
3510 return boost::shared_ptr<NamedSelection>();
3513 void
3514 Session::add_named_selection (boost::shared_ptr<NamedSelection> named_selection)
3517 Glib::Mutex::Lock lm (named_selection_lock);
3518 named_selections.insert (named_selections.begin(), named_selection);
3521 set_dirty();
3523 NamedSelectionAdded (); /* EMIT SIGNAL */
3526 void
3527 Session::remove_named_selection (boost::shared_ptr<NamedSelection> named_selection)
3529 bool removed = false;
3532 Glib::Mutex::Lock lm (named_selection_lock);
3534 NamedSelectionList::iterator i = find (named_selections.begin(), named_selections.end(), named_selection);
3536 if (i != named_selections.end()) {
3537 named_selections.erase (i);
3538 set_dirty();
3539 removed = true;
3543 if (removed) {
3544 NamedSelectionRemoved (); /* EMIT SIGNAL */
3548 void
3549 Session::reset_native_file_format ()
3551 boost::shared_ptr<RouteList> rl = routes.reader ();
3552 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
3553 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
3554 if (tr) {
3555 /* don't save state as we do this, there's no point
3558 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
3559 tr->reset_write_sources (false);
3560 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
3565 bool
3566 Session::route_name_unique (string n) const
3568 boost::shared_ptr<RouteList> r = routes.reader ();
3570 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
3571 if ((*i)->name() == n) {
3572 return false;
3576 return true;
3579 bool
3580 Session::route_name_internal (string n) const
3582 if (auditioner && auditioner->name() == n) {
3583 return true;
3586 if (_click_io && _click_io->name() == n) {
3587 return true;
3590 return false;
3594 Session::freeze_all (InterThreadInfo& itt)
3596 boost::shared_ptr<RouteList> r = routes.reader ();
3598 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
3600 boost::shared_ptr<Track> t;
3602 if ((t = boost::dynamic_pointer_cast<Track>(*i)) != 0) {
3603 /* XXX this is wrong because itt.progress will keep returning to zero at the start
3604 of every track.
3606 t->freeze_me (itt);
3610 return 0;
3613 boost::shared_ptr<Region>
3614 Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end,
3615 bool /*overwrite*/, vector<boost::shared_ptr<Source> >& srcs,
3616 InterThreadInfo& itt, bool enable_processing)
3618 boost::shared_ptr<Region> result;
3619 boost::shared_ptr<Playlist> playlist;
3620 boost::shared_ptr<AudioFileSource> fsource;
3621 uint32_t x;
3622 char buf[PATH_MAX+1];
3623 ChanCount diskstream_channels (track.n_channels());
3624 framepos_t position;
3625 framecnt_t this_chunk;
3626 framepos_t to_do;
3627 BufferSet buffers;
3628 SessionDirectory sdir(get_best_session_directory_for_new_source ());
3629 const string sound_dir = sdir.sound_path().to_string();
3630 framepos_t len = end - start;
3631 bool need_block_size_reset = false;
3632 string ext;
3633 ChanCount const max_proc = track.max_processor_streams ();
3635 if (end <= start) {
3636 error << string_compose (_("Cannot write a range where end <= start (e.g. %1 <= %2)"),
3637 end, start) << endmsg;
3638 return result;
3641 const framecnt_t chunk_size = (256 * 1024)/4;
3643 // block all process callback handling
3645 block_processing ();
3647 /* call tree *MUST* hold route_lock */
3649 if ((playlist = track.playlist()) == 0) {
3650 goto out;
3653 /* external redirects will be a problem */
3655 if (track.has_external_redirects()) {
3656 goto out;
3659 ext = native_header_format_extension (config.get_native_file_header_format(), DataType::AUDIO);
3661 for (uint32_t chan_n = 0; chan_n < diskstream_channels.n_audio(); ++chan_n) {
3663 for (x = 0; x < 99999; ++x) {
3664 snprintf (buf, sizeof(buf), "%s/%s-%d-bounce-%" PRIu32 "%s", sound_dir.c_str(), playlist->name().c_str(), chan_n, x+1, ext.c_str());
3665 if (!Glib::file_test (buf, Glib::FILE_TEST_EXISTS)) {
3666 break;
3670 if (x == 99999) {
3671 error << string_compose (_("too many bounced versions of playlist \"%1\""), playlist->name()) << endmsg;
3672 goto out;
3675 try {
3676 fsource = boost::dynamic_pointer_cast<AudioFileSource> (
3677 SourceFactory::createWritable (DataType::AUDIO, *this, buf, string(), false, frame_rate()));
3680 catch (failed_constructor& err) {
3681 error << string_compose (_("cannot create new audio file \"%1\" for %2"), buf, track.name()) << endmsg;
3682 goto out;
3685 srcs.push_back (fsource);
3688 /* tell redirects that care that we are about to use a much larger blocksize */
3690 need_block_size_reset = true;
3691 track.set_block_size (chunk_size);
3693 /* XXX need to flush all redirects */
3695 position = start;
3696 to_do = len;
3698 /* create a set of reasonably-sized buffers */
3699 buffers.ensure_buffers (DataType::AUDIO, max_proc.n_audio(), chunk_size);
3700 buffers.set_count (max_proc);
3702 for (vector<boost::shared_ptr<Source> >::iterator src = srcs.begin(); src != srcs.end(); ++src) {
3703 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
3704 if (afs)
3705 afs->prepare_for_peakfile_writes ();
3708 while (to_do && !itt.cancel) {
3710 this_chunk = min (to_do, chunk_size);
3712 if (track.export_stuff (buffers, start, this_chunk, enable_processing)) {
3713 goto out;
3716 uint32_t n = 0;
3717 for (vector<boost::shared_ptr<Source> >::iterator src=srcs.begin(); src != srcs.end(); ++src, ++n) {
3718 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
3720 if (afs) {
3721 if (afs->write (buffers.get_audio(n).data(), this_chunk) != this_chunk) {
3722 goto out;
3727 start += this_chunk;
3728 to_do -= this_chunk;
3730 itt.progress = (float) (1.0 - ((double) to_do / len));
3734 if (!itt.cancel) {
3736 time_t now;
3737 struct tm* xnow;
3738 time (&now);
3739 xnow = localtime (&now);
3741 for (vector<boost::shared_ptr<Source> >::iterator src=srcs.begin(); src != srcs.end(); ++src) {
3742 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
3744 if (afs) {
3745 afs->update_header (position, *xnow, now);
3746 afs->flush_header ();
3750 /* construct a region to represent the bounced material */
3752 PropertyList plist;
3754 plist.add (Properties::start, 0);
3755 plist.add (Properties::length, srcs.front()->length(srcs.front()->timeline_position()));
3756 plist.add (Properties::name, region_name_from_path (srcs.front()->name(), true));
3758 result = RegionFactory::create (srcs, plist);
3762 out:
3763 if (!result) {
3764 for (vector<boost::shared_ptr<Source> >::iterator src = srcs.begin(); src != srcs.end(); ++src) {
3765 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
3767 if (afs) {
3768 afs->mark_for_remove ();
3771 (*src)->drop_references ();
3774 } else {
3775 for (vector<boost::shared_ptr<Source> >::iterator src = srcs.begin(); src != srcs.end(); ++src) {
3776 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
3778 if (afs)
3779 afs->done_with_peakfile_writes ();
3784 if (need_block_size_reset) {
3785 track.set_block_size (get_block_size());
3788 unblock_processing ();
3790 return result;
3793 gain_t*
3794 Session::gain_automation_buffer() const
3796 return ProcessThread::gain_automation_buffer ();
3799 pan_t**
3800 Session::pan_automation_buffer() const
3802 return ProcessThread::pan_automation_buffer ();
3805 BufferSet&
3806 Session::get_silent_buffers (ChanCount count)
3808 return ProcessThread::get_silent_buffers (count);
3811 BufferSet&
3812 Session::get_scratch_buffers (ChanCount count)
3814 return ProcessThread::get_scratch_buffers (count);
3817 BufferSet&
3818 Session::get_mix_buffers (ChanCount count)
3820 return ProcessThread::get_mix_buffers (count);
3823 uint32_t
3824 Session::ntracks () const
3826 uint32_t n = 0;
3827 boost::shared_ptr<RouteList> r = routes.reader ();
3829 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
3830 if (boost::dynamic_pointer_cast<Track> (*i)) {
3831 ++n;
3835 return n;
3838 uint32_t
3839 Session::nbusses () const
3841 uint32_t n = 0;
3842 boost::shared_ptr<RouteList> r = routes.reader ();
3844 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
3845 if (boost::dynamic_pointer_cast<Track>(*i) == 0) {
3846 ++n;
3850 return n;
3853 void
3854 Session::add_automation_list(AutomationList *al)
3856 automation_lists[al->id()] = al;
3859 void
3860 Session::sync_order_keys (std::string const & base)
3862 if (deletion_in_progress()) {
3863 return;
3866 if (!Config->get_sync_all_route_ordering()) {
3867 /* leave order keys as they are */
3868 return;
3871 boost::shared_ptr<RouteList> r = routes.reader ();
3873 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
3874 (*i)->sync_order_keys (base);
3877 Route::SyncOrderKeys (base); // EMIT SIGNAL
3879 /* this might not do anything */
3881 set_remote_control_ids ();
3884 /** @return true if there is at least one record-enabled track, otherwise false */
3885 bool
3886 Session::have_rec_enabled_track () const
3888 return g_atomic_int_get (&_have_rec_enabled_track) == 1;
3891 /** Update the state of our rec-enabled tracks flag */
3892 void
3893 Session::update_have_rec_enabled_track ()
3895 boost::shared_ptr<RouteList> rl = routes.reader ();
3896 RouteList::iterator i = rl->begin();
3897 while (i != rl->end ()) {
3899 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
3900 if (tr && tr->record_enabled ()) {
3901 break;
3904 ++i;
3907 int const old = g_atomic_int_get (&_have_rec_enabled_track);
3909 g_atomic_int_set (&_have_rec_enabled_track, i != rl->end () ? 1 : 0);
3911 if (g_atomic_int_get (&_have_rec_enabled_track) != old) {
3912 RecordStateChanged (); /* EMIT SIGNAL */
3916 void
3917 Session::listen_position_changed ()
3919 boost::shared_ptr<RouteList> r = routes.reader ();
3921 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
3922 (*i)->listen_position_changed ();
3926 void
3927 Session::solo_control_mode_changed ()
3929 /* cancel all solo or all listen when solo control mode changes */
3931 if (soloing()) {
3932 set_solo (get_routes(), false);
3933 } else if (listening()) {
3934 set_listen (get_routes(), false);
3938 /** Called when anything about any of our route groups changes (membership, state etc.) */
3939 void
3940 Session::route_group_changed ()
3942 RouteGroupChanged (); /* EMIT SIGNAL */
3945 vector<SyncSource>
3946 Session::get_available_sync_options () const
3948 vector<SyncSource> ret;
3950 ret.push_back (JACK);
3951 ret.push_back (MTC);
3952 ret.push_back (MIDIClock);
3954 return ret;
3957 boost::shared_ptr<RouteList>
3958 Session::get_routes_with_regions_at (framepos_t const p) const
3960 boost::shared_ptr<RouteList> r = routes.reader ();
3961 boost::shared_ptr<RouteList> rl (new RouteList);
3963 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
3964 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
3965 if (!tr) {
3966 continue;
3969 boost::shared_ptr<Playlist> pl = tr->playlist ();
3970 if (!pl) {
3971 continue;
3974 if (pl->has_region_at (p)) {
3975 rl->push_back (*i);
3979 return rl;
3982 void
3983 Session::goto_end ()
3985 if (_session_range_location) {
3986 request_locate (_session_range_location->end(), false);
3987 } else {
3988 request_locate (0, false);
3992 void
3993 Session::goto_start ()
3995 if (_session_range_location) {
3996 request_locate (_session_range_location->start(), false);
3997 } else {
3998 request_locate (0, false);
4002 framepos_t
4003 Session::current_start_frame () const
4005 return _session_range_location ? _session_range_location->start() : 0;
4008 framepos_t
4009 Session::current_end_frame () const
4011 return _session_range_location ? _session_range_location->end() : 0;
4014 void
4015 Session::add_session_range_location (framepos_t start, framepos_t end)
4017 _session_range_location = new Location (*this, start, end, _("session"), Location::IsSessionRange);
4018 _locations->add (_session_range_location);
4021 /** Called when one of our routes' order keys has changed */
4022 void
4023 Session::route_order_key_changed ()
4025 RouteOrderKeyChanged (); /* EMIT SIGNAL */
4028 void
4029 Session::step_edit_status_change (bool yn)
4031 bool send = false;
4033 bool val = false;
4034 if (yn) {
4035 send = (_step_editors == 0);
4036 val = true;
4038 _step_editors++;
4039 } else {
4040 send = (_step_editors == 1);
4041 val = false;
4043 if (_step_editors > 0) {
4044 _step_editors--;
4048 if (send) {
4049 StepEditStatusChange (val);
4054 void
4055 Session::start_time_changed (framepos_t old)
4057 /* Update the auto loop range to match the session range
4058 (unless the auto loop range has been changed by the user)
4061 Location* s = _locations->session_range_location ();
4062 if (s == 0) {
4063 return;
4066 Location* l = _locations->auto_loop_location ();
4068 if (l->start() == old) {
4069 l->set_start (s->start(), true);
4073 void
4074 Session::end_time_changed (framepos_t old)
4076 /* Update the auto loop range to match the session range
4077 (unless the auto loop range has been changed by the user)
4080 Location* s = _locations->session_range_location ();
4081 if (s == 0) {
4082 return;
4085 Location* l = _locations->auto_loop_location ();
4087 if (l->end() == old) {
4088 l->set_end (s->end(), true);
4092 string
4093 Session::source_search_path (DataType type) const
4095 string search_path;
4097 if (session_dirs.size() == 1) {
4098 switch (type) {
4099 case DataType::AUDIO:
4100 search_path = _session_dir->sound_path().to_string();
4101 break;
4102 case DataType::MIDI:
4103 search_path = _session_dir->midi_path().to_string();
4104 break;
4106 } else {
4107 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4108 SessionDirectory sdir (i->path);
4109 if (!search_path.empty()) {
4110 search_path += ':';
4112 switch (type) {
4113 case DataType::AUDIO:
4114 search_path += sdir.sound_path().to_string();
4115 break;
4116 case DataType::MIDI:
4117 search_path += sdir.midi_path().to_string();
4118 break;
4123 /* now add user-specified locations
4126 vector<string> dirs;
4128 switch (type) {
4129 case DataType::AUDIO:
4130 split (config.get_audio_search_path (), dirs, ':');
4131 break;
4132 case DataType::MIDI:
4133 split (config.get_midi_search_path (), dirs, ':');
4134 break;
4137 for (vector<string>::iterator i = dirs.begin(); i != dirs.end(); ++i) {
4138 search_path += ':';
4139 search_path += *i;
4143 return search_path;
4146 void
4147 Session::ensure_search_path_includes (const string& path, DataType type)
4149 string search_path;
4150 vector<string> dirs;
4152 if (path == ".") {
4153 return;
4156 switch (type) {
4157 case DataType::AUDIO:
4158 search_path = config.get_audio_search_path ();
4159 break;
4160 case DataType::MIDI:
4161 search_path = config.get_midi_search_path ();
4162 break;
4165 split (search_path, dirs, ':');
4167 for (vector<string>::iterator i = dirs.begin(); i != dirs.end(); ++i) {
4168 if (*i == path) {
4169 return;
4173 if (!search_path.empty()) {
4174 search_path += ':';
4177 search_path += path;
4179 switch (type) {
4180 case DataType::AUDIO:
4181 config.set_audio_search_path (search_path);
4182 break;
4183 case DataType::MIDI:
4184 config.set_midi_search_path (search_path);
4185 break;
4189 boost::shared_ptr<Speakers>
4190 Session::get_speakers()
4192 return _speakers;
4195 list<string>
4196 Session::unknown_processors () const
4198 list<string> p;
4200 boost::shared_ptr<RouteList> r = routes.reader ();
4201 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
4202 list<string> t = (*i)->unknown_processors ();
4203 copy (t.begin(), t.end(), back_inserter (p));
4206 p.sort ();
4207 p.unique ();
4209 return p;
4212 void
4213 Session::update_latency (bool playback)
4215 DEBUG_TRACE (DEBUG::Latency, string_compose ("JACK latency callback: %1\n", (playback ? "PLAYBACK" : "CAPTURE")));
4217 if (_state_of_the_state & (InitialConnecting|Deletion)) {
4218 return;
4221 boost::shared_ptr<RouteList> r = routes.reader ();
4222 framecnt_t max_latency = 0;
4224 if (playback) {
4225 /* reverse the list so that we work backwards from the last route to run to the first */
4226 reverse (r->begin(), r->end());
4229 /* compute actual latency values for the given direction and store them all in per-port
4230 structures. this will also publish the same values (to JACK) so that computation of latency
4231 for routes can consistently use public latency values.
4234 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
4235 max_latency = max (max_latency, (*i)->set_private_port_latencies (playback));
4238 /* because we latency compensate playback, our published playback latencies should
4239 be the same for all output ports - all material played back by ardour has
4240 the same latency, whether its caused by plugins or by latency compensation. since
4241 these may differ from the values computed above, reset all playback port latencies
4242 to the same value.
4245 DEBUG_TRACE (DEBUG::Latency, string_compose ("Set public port latencies to %1\n", max_latency));
4247 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
4248 (*i)->set_public_port_latencies (max_latency, playback);
4251 if (playback) {
4253 post_playback_latency ();
4255 } else {
4257 post_capture_latency ();
4260 DEBUG_TRACE (DEBUG::Latency, "JACK latency callback: DONE\n");
4263 void
4264 Session::post_playback_latency ()
4266 set_worst_playback_latency ();
4268 boost::shared_ptr<RouteList> r = routes.reader ();
4269 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
4270 if (!(*i)->is_hidden() && ((*i)->active())) {
4271 _worst_track_latency = max (_worst_track_latency, (*i)->update_signal_latency ());
4274 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
4275 (*i)->set_latency_compensation (_worst_track_latency);
4280 void
4281 Session::post_capture_latency ()
4283 set_worst_capture_latency ();
4285 /* reflect any changes in capture latencies into capture offsets
4288 boost::shared_ptr<RouteList> rl = routes.reader();
4289 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
4290 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
4291 if (tr) {
4292 tr->set_capture_offset ();
4297 void
4298 Session::set_worst_io_latencies ()
4300 set_worst_playback_latency ();
4301 set_worst_capture_latency ();
4304 void
4305 Session::set_worst_playback_latency ()
4307 if (_state_of_the_state & (InitialConnecting|Deletion)) {
4308 return;
4311 _worst_output_latency = 0;
4313 if (!_engine.connected()) {
4314 return;
4317 boost::shared_ptr<RouteList> r = routes.reader ();
4319 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
4320 _worst_output_latency = max (_worst_output_latency, (*i)->output()->latency());
4323 DEBUG_TRACE (DEBUG::Latency, string_compose ("Worst output latency: %1\n", _worst_output_latency));
4326 void
4327 Session::set_worst_capture_latency ()
4329 if (_state_of_the_state & (InitialConnecting|Deletion)) {
4330 return;
4333 _worst_input_latency = 0;
4335 if (!_engine.connected()) {
4336 return;
4339 boost::shared_ptr<RouteList> r = routes.reader ();
4341 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
4342 _worst_input_latency = max (_worst_input_latency, (*i)->input()->latency());
4345 DEBUG_TRACE (DEBUG::Latency, string_compose ("Worst input latency: %1\n", _worst_input_latency));
4348 void
4349 Session::update_latency_compensation (bool force_whole_graph)
4351 bool some_track_latency_changed = false;
4353 if (_state_of_the_state & (InitialConnecting|Deletion)) {
4354 return;
4357 DEBUG_TRACE(DEBUG::Latency, "---------------------------- update latency compensation\n\n");
4359 _worst_track_latency = 0;
4361 boost::shared_ptr<RouteList> r = routes.reader ();
4363 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
4364 if (!(*i)->is_hidden() && ((*i)->active())) {
4365 framecnt_t tl;
4366 if ((*i)->signal_latency () != (tl = (*i)->update_signal_latency ())) {
4367 some_track_latency_changed = true;
4369 _worst_track_latency = max (tl, _worst_track_latency);
4373 DEBUG_TRACE (DEBUG::Latency, string_compose ("worst signal processing latency: %1 (changed ? %2)\n", _worst_track_latency,
4374 (some_track_latency_changed ? "yes" : "no")));
4376 if (force_whole_graph || some_track_latency_changed) {
4377 /* trigger a full recompute of latency numbers for the graph.
4378 everything else that we need to do will be done in the latency
4379 callback.
4381 _engine.update_total_latencies ();
4382 return; // everything else will be done in the latency callback
4385 DEBUG_TRACE(DEBUG::Latency, "---------------------------- DONE update latency compensation\n\n")