remove another instance of access(2)
[ardour2.git] / libs / ardour / session.cc
blob35d7514089e2f5f14241993f2cc8ac29cef253de
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/crossfade.h"
67 #include "ardour/cycle_timer.h"
68 #include "ardour/data_type.h"
69 #include "ardour/debug.h"
70 #include "ardour/filename_extensions.h"
71 #include "ardour/internal_send.h"
72 #include "ardour/io_processor.h"
73 #include "ardour/midi_diskstream.h"
74 #include "ardour/midi_playlist.h"
75 #include "ardour/midi_region.h"
76 #include "ardour/midi_track.h"
77 #include "ardour/midi_ui.h"
78 #include "ardour/named_selection.h"
79 #include "ardour/process_thread.h"
80 #include "ardour/playlist.h"
81 #include "ardour/plugin_insert.h"
82 #include "ardour/port_insert.h"
83 #include "ardour/processor.h"
84 #include "ardour/rc_configuration.h"
85 #include "ardour/recent_sessions.h"
86 #include "ardour/region_factory.h"
87 #include "ardour/return.h"
88 #include "ardour/route_group.h"
89 #include "ardour/send.h"
90 #include "ardour/session.h"
91 #include "ardour/session_directory.h"
92 #include "ardour/session_directory.h"
93 #include "ardour/session_metadata.h"
94 #include "ardour/session_playlists.h"
95 #include "ardour/slave.h"
96 #include "ardour/smf_source.h"
97 #include "ardour/source_factory.h"
98 #include "ardour/tape_file_matcher.h"
99 #include "ardour/tempo.h"
100 #include "ardour/utils.h"
101 #include "ardour/graph.h"
102 #include "ardour/speakers.h"
103 #include "ardour/operations.h"
105 #include "midi++/port.h"
106 #include "midi++/mmc.h"
107 #include "midi++/manager.h"
109 #include "i18n.h"
111 using namespace std;
112 using namespace ARDOUR;
113 using namespace PBD;
115 bool Session::_disable_all_loaded_plugins = false;
117 PBD::Signal1<void,std::string> Session::Dialog;
118 PBD::Signal0<int> Session::AskAboutPendingState;
119 PBD::Signal2<int, framecnt_t, framecnt_t> Session::AskAboutSampleRateMismatch;
120 PBD::Signal0<void> Session::SendFeedback;
121 PBD::Signal3<int,Session*,std::string,DataType> Session::MissingFile;
123 PBD::Signal1<void, framepos_t> Session::StartTimeChanged;
124 PBD::Signal1<void, framepos_t> Session::EndTimeChanged;
125 PBD::Signal0<void> Session::AutoBindingOn;
126 PBD::Signal0<void> Session::AutoBindingOff;
127 PBD::Signal2<void,std::string, std::string> Session::Exported;
128 PBD::Signal1<int,boost::shared_ptr<Playlist> > Session::AskAboutPlaylistDeletion;
129 PBD::Signal0<void> Session::Quit;
131 static void clean_up_session_event (SessionEvent* ev) { delete ev; }
132 const SessionEvent::RTeventCallback Session::rt_cleanup (clean_up_session_event);
134 Session::Session (AudioEngine &eng,
135 const string& fullpath,
136 const string& snapshot_name,
137 BusProfile* bus_profile,
138 string mix_template)
139 : _engine (eng)
140 , _target_transport_speed (0.0)
141 , _requested_return_frame (-1)
142 , _session_dir (new SessionDirectory(fullpath))
143 , state_tree (0)
144 , _state_of_the_state (Clean)
145 , _butler (new Butler (*this))
146 , _post_transport_work (0)
147 , _send_timecode_update (false)
148 , _all_route_group (new RouteGroup (*this, "all"))
149 , route_graph (new Graph(*this))
150 , routes (new RouteList)
151 , _total_free_4k_blocks (0)
152 , _bundles (new BundleList)
153 , _bundle_xml_node (0)
154 , _current_trans (0)
155 , _click_io ((IO*) 0)
156 , click_data (0)
157 , click_emphasis_data (0)
158 , main_outs (0)
159 , _metadata (new SessionMetadata())
160 , _have_rec_enabled_track (false)
161 , _suspend_timecode_transmission (0)
163 _locations = new Locations (*this);
165 playlists.reset (new SessionPlaylists);
167 _all_route_group->set_active (true, this);
169 interpolation.add_channel_to (0, 0);
171 if (!eng.connected()) {
172 throw failed_constructor();
175 n_physical_outputs = _engine.n_physical_outputs ();
176 n_physical_inputs = _engine.n_physical_inputs ();
178 first_stage_init (fullpath, snapshot_name);
180 _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
182 if (_is_new) {
183 if (create (mix_template, bus_profile)) {
184 destroy ();
185 throw failed_constructor ();
189 if (second_stage_init ()) {
190 destroy ();
191 throw failed_constructor ();
194 store_recent_sessions(_name, _path);
196 bool was_dirty = dirty();
198 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
200 Config->ParameterChanged.connect_same_thread (*this, boost::bind (&Session::config_changed, this, _1, false));
201 config.ParameterChanged.connect_same_thread (*this, boost::bind (&Session::config_changed, this, _1, true));
203 if (was_dirty) {
204 DirtyChanged (); /* EMIT SIGNAL */
207 StartTimeChanged.connect_same_thread (*this, boost::bind (&Session::start_time_changed, this, _1));
208 EndTimeChanged.connect_same_thread (*this, boost::bind (&Session::end_time_changed, this, _1));
210 _is_new = false;
213 Session::~Session ()
215 destroy ();
218 void
219 Session::destroy ()
221 vector<void*> debug_pointers;
223 /* if we got to here, leaving pending capture state around
224 is a mistake.
227 remove_pending_capture_state ();
229 _state_of_the_state = StateOfTheState (CannotSave|Deletion);
231 _engine.remove_session ();
233 /* clear history so that no references to objects are held any more */
235 _history.clear ();
237 /* clear state tree so that no references to objects are held any more */
239 delete state_tree;
241 /* reset dynamic state version back to default */
243 Stateful::loading_state_version = 0;
245 _butler->drop_references ();
246 delete _butler;
247 delete midi_control_ui;
248 delete _all_route_group;
250 if (click_data != default_click) {
251 delete [] click_data;
254 if (click_emphasis_data != default_click_emphasis) {
255 delete [] click_emphasis_data;
258 clear_clicks ();
260 /* clear out any pending dead wood from RCU managed objects */
262 routes.flush ();
263 _bundles.flush ();
265 AudioDiskstream::free_working_buffers();
267 /* tell everyone who is still standing that we're about to die */
268 drop_references ();
270 /* tell everyone to drop references and delete objects as we go */
272 DEBUG_TRACE (DEBUG::Destruction, "delete named selections\n");
273 named_selections.clear ();
275 DEBUG_TRACE (DEBUG::Destruction, "delete regions\n");
276 RegionFactory::delete_all_regions ();
278 DEBUG_TRACE (DEBUG::Destruction, "delete routes\n");
280 /* reset these three references to special routes before we do the usual route delete thing */
282 auditioner.reset ();
283 _master_out.reset ();
284 _monitor_out.reset ();
287 RCUWriter<RouteList> writer (routes);
288 boost::shared_ptr<RouteList> r = writer.get_copy ();
290 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
291 DEBUG_TRACE(DEBUG::Destruction, string_compose ("Dropping for route %1 ; pre-ref = %2\n", (*i)->name(), (*i).use_count()));
292 (*i)->drop_references ();
295 r->clear ();
296 /* writer goes out of scope and updates master */
298 routes.flush ();
300 DEBUG_TRACE (DEBUG::Destruction, "delete sources\n");
301 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
302 DEBUG_TRACE(DEBUG::Destruction, string_compose ("Dropping for source %1 ; pre-ref = %2\n", i->second->path(), i->second.use_count()));
303 i->second->drop_references ();
306 sources.clear ();
308 DEBUG_TRACE (DEBUG::Destruction, "delete route groups\n");
309 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
311 delete *i;
314 Crossfade::set_buffer_size (0);
316 /* not strictly necessary, but doing it here allows the shared_ptr debugging to work */
317 playlists.reset ();
319 delete _locations;
321 DEBUG_TRACE (DEBUG::Destruction, "Session::destroy() done\n");
323 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
324 boost_debug_list_ptrs ();
325 #endif
328 void
329 Session::when_engine_running ()
331 string first_physical_output;
333 BootMessage (_("Set block size and sample rate"));
335 set_block_size (_engine.frames_per_cycle());
336 set_frame_rate (_engine.frame_rate());
338 BootMessage (_("Using configuration"));
340 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
341 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
343 Config->map_parameters (ff);
344 config.map_parameters (ft);
346 /* every time we reconnect, recompute worst case output latencies */
348 _engine.Running.connect_same_thread (*this, boost::bind (&Session::set_worst_io_latencies, this));
350 if (synced_to_jack()) {
351 _engine.transport_stop ();
354 if (config.get_jack_time_master()) {
355 _engine.transport_locate (_transport_frame);
358 _clicking = false;
360 try {
361 XMLNode* child = 0;
363 _click_io.reset (new ClickIO (*this, "click"));
365 if (state_tree && (child = find_named_node (*state_tree->root(), "Click")) != 0) {
367 /* existing state for Click */
368 int c;
370 if (Stateful::loading_state_version < 3000) {
371 c = _click_io->set_state_2X (*child->children().front(), Stateful::loading_state_version, false);
372 } else {
373 c = _click_io->set_state (*child->children().front(), Stateful::loading_state_version);
377 if (c == 0) {
378 _clicking = Config->get_clicking ();
380 } else {
382 error << _("could not setup Click I/O") << endmsg;
383 _clicking = false;
387 } else {
389 /* default state for Click: dual-mono to first 2 physical outputs */
391 vector<string> outs;
392 _engine.get_physical_outputs (DataType::AUDIO, outs);
394 for (uint32_t physport = 0; physport < 2; ++physport) {
395 if (outs.size() > physport) {
396 if (_click_io->add_port (outs[physport], this)) {
397 // relax, even though its an error
402 if (_click_io->n_ports () > ChanCount::ZERO) {
403 _clicking = Config->get_clicking ();
408 catch (failed_constructor& err) {
409 error << _("cannot setup Click I/O") << endmsg;
412 BootMessage (_("Compute I/O Latencies"));
414 if (_clicking) {
415 // XXX HOW TO ALERT UI TO THIS ? DO WE NEED TO?
418 BootMessage (_("Set up standard connections"));
420 vector<string> inputs[DataType::num_types];
421 vector<string> outputs[DataType::num_types];
422 for (uint32_t i = 0; i < DataType::num_types; ++i) {
423 _engine.get_physical_inputs (DataType (DataType::Symbol (i)), inputs[i]);
424 _engine.get_physical_outputs (DataType (DataType::Symbol (i)), outputs[i]);
427 /* Create a set of Bundle objects that map
428 to the physical I/O currently available. We create both
429 mono and stereo bundles, so that the common cases of mono
430 and stereo tracks get bundles to put in their mixer strip
431 in / out menus. There may be a nicer way of achieving that;
432 it doesn't really scale that well to higher channel counts
435 /* mono output bundles */
437 for (uint32_t np = 0; np < outputs[DataType::AUDIO].size(); ++np) {
438 char buf[32];
439 snprintf (buf, sizeof (buf), _("out %" PRIu32), np+1);
441 boost::shared_ptr<Bundle> c (new Bundle (buf, true));
442 c->add_channel (_("mono"), DataType::AUDIO);
443 c->set_port (0, outputs[DataType::AUDIO][np]);
445 add_bundle (c);
448 /* stereo output bundles */
450 for (uint32_t np = 0; np < outputs[DataType::AUDIO].size(); np += 2) {
451 if (np + 1 < outputs[DataType::AUDIO].size()) {
452 char buf[32];
453 snprintf (buf, sizeof(buf), _("out %" PRIu32 "+%" PRIu32), np + 1, np + 2);
454 boost::shared_ptr<Bundle> c (new Bundle (buf, true));
455 c->add_channel (_("L"), DataType::AUDIO);
456 c->set_port (0, outputs[DataType::AUDIO][np]);
457 c->add_channel (_("R"), DataType::AUDIO);
458 c->set_port (1, outputs[DataType::AUDIO][np + 1]);
460 add_bundle (c);
464 /* mono input bundles */
466 for (uint32_t np = 0; np < inputs[DataType::AUDIO].size(); ++np) {
467 char buf[32];
468 snprintf (buf, sizeof (buf), _("in %" PRIu32), np+1);
470 boost::shared_ptr<Bundle> c (new Bundle (buf, false));
471 c->add_channel (_("mono"), DataType::AUDIO);
472 c->set_port (0, inputs[DataType::AUDIO][np]);
474 add_bundle (c);
477 /* stereo input bundles */
479 for (uint32_t np = 0; np < inputs[DataType::AUDIO].size(); np += 2) {
480 if (np + 1 < inputs[DataType::AUDIO].size()) {
481 char buf[32];
482 snprintf (buf, sizeof(buf), _("in %" PRIu32 "+%" PRIu32), np + 1, np + 2);
484 boost::shared_ptr<Bundle> c (new Bundle (buf, false));
485 c->add_channel (_("L"), DataType::AUDIO);
486 c->set_port (0, inputs[DataType::AUDIO][np]);
487 c->add_channel (_("R"), DataType::AUDIO);
488 c->set_port (1, inputs[DataType::AUDIO][np + 1]);
490 add_bundle (c);
494 /* MIDI input bundles */
496 for (uint32_t np = 0; np < inputs[DataType::MIDI].size(); ++np) {
497 string n = inputs[DataType::MIDI][np];
498 boost::erase_first (n, X_("alsa_pcm:"));
500 boost::shared_ptr<Bundle> c (new Bundle (n, false));
501 c->add_channel ("", DataType::MIDI);
502 c->set_port (0, inputs[DataType::MIDI][np]);
503 add_bundle (c);
506 /* MIDI output bundles */
508 for (uint32_t np = 0; np < outputs[DataType::MIDI].size(); ++np) {
509 string n = outputs[DataType::MIDI][np];
510 boost::erase_first (n, X_("alsa_pcm:"));
512 boost::shared_ptr<Bundle> c (new Bundle (n, true));
513 c->add_channel ("", DataType::MIDI);
514 c->set_port (0, outputs[DataType::MIDI][np]);
515 add_bundle (c);
518 BootMessage (_("Setup signal flow and plugins"));
520 hookup_io ();
522 if (_is_new && !no_auto_connect()) {
524 Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock());
526 /* don't connect the master bus outputs if there is a monitor bus */
528 if (_master_out && Config->get_auto_connect_standard_busses() && !_monitor_out) {
530 /* if requested auto-connect the outputs to the first N physical ports.
533 uint32_t limit = _master_out->n_outputs().n_total();
535 for (uint32_t n = 0; n < limit; ++n) {
536 Port* p = _master_out->output()->nth (n);
537 string connect_to;
538 if (outputs[p->type()].size() > n) {
539 connect_to = outputs[p->type()][n];
542 if (!connect_to.empty() && p->connected_to (connect_to) == false) {
543 if (_master_out->output()->connect (p, connect_to, this)) {
544 error << string_compose (_("cannot connect master output %1 to %2"), n, connect_to)
545 << endmsg;
546 break;
552 if (_monitor_out) {
554 /* AUDIO ONLY as of june 29th 2009, because listen semantics for anything else
555 are undefined, at best.
558 /* control out listens to master bus (but ignores it
559 under some conditions)
562 uint32_t limit = _monitor_out->n_inputs().n_audio();
564 if (_master_out) {
565 for (uint32_t n = 0; n < limit; ++n) {
566 AudioPort* p = _monitor_out->input()->ports().nth_audio_port (n);
567 AudioPort* o = _master_out->output()->ports().nth_audio_port (n);
569 if (o) {
570 string connect_to = o->name();
571 if (_monitor_out->input()->connect (p, connect_to, this)) {
572 error << string_compose (_("cannot connect control input %1 to %2"), n, connect_to)
573 << endmsg;
574 break;
580 /* if control out is not connected, connect control out to physical outs
583 if (!_monitor_out->output()->connected ()) {
585 if (!Config->get_monitor_bus_preferred_bundle().empty()) {
587 boost::shared_ptr<Bundle> b = bundle_by_name (Config->get_monitor_bus_preferred_bundle());
589 if (b) {
590 _monitor_out->output()->connect_ports_to_bundle (b, this);
591 } else {
592 warning << string_compose (_("The preferred I/O for the monitor bus (%1) cannot be found"),
593 Config->get_monitor_bus_preferred_bundle())
594 << endmsg;
597 } else {
599 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
600 uint32_t mod = n_physical_outputs.get (*t);
601 uint32_t limit = _monitor_out->n_outputs().get(*t);
603 for (uint32_t n = 0; n < limit; ++n) {
605 Port* p = _monitor_out->output()->ports().port(*t, n);
606 string connect_to;
607 if (outputs[*t].size() > (n % mod)) {
608 connect_to = outputs[*t][n % mod];
611 if (!connect_to.empty()) {
612 if (_monitor_out->output()->connect (p, connect_to, this)) {
613 error << string_compose (
614 _("cannot connect control output %1 to %2"),
615 n, connect_to)
616 << endmsg;
617 break;
627 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
629 /* hook us up to the engine */
631 BootMessage (_("Connect to engine"));
632 _engine.set_session (this);
634 update_latency_compensation (true);
637 void
638 Session::hookup_io ()
640 /* stop graph reordering notifications from
641 causing resorts, etc.
644 _state_of_the_state = StateOfTheState (_state_of_the_state | InitialConnecting);
646 if (!auditioner) {
648 /* we delay creating the auditioner till now because
649 it makes its own connections to ports.
652 try {
653 boost::shared_ptr<Auditioner> a (new Auditioner (*this));
654 if (a->init()) {
655 throw failed_constructor ();
657 a->use_new_diskstream ();
658 auditioner = a;
661 catch (failed_constructor& err) {
662 warning << _("cannot create Auditioner: no auditioning of regions possible") << endmsg;
666 /* load bundles, which we may have postponed earlier on */
667 if (_bundle_xml_node) {
668 load_bundles (*_bundle_xml_node);
669 delete _bundle_xml_node;
672 /* Tell all IO objects to connect themselves together */
674 IO::enable_connecting ();
675 MIDI::Port::MakeConnections ();
677 /* Now reset all panners */
679 Delivery::reset_panners ();
681 /* Connect tracks to monitor/listen bus if there is one. Note that in an
682 existing session, the internal sends will already exist, but we want the
683 routes to notice that they connect to the control out specifically.
686 if (_monitor_out) {
687 boost::shared_ptr<RouteList> r = routes.reader ();
688 for (RouteList::iterator x = r->begin(); x != r->end(); ++x) {
690 if ((*x)->is_monitor()) {
692 /* relax */
694 } else if ((*x)->is_master()) {
696 /* relax */
698 } else {
700 (*x)->listen_via_monitor ();
705 /* Anyone who cares about input state, wake up and do something */
707 IOConnectionsComplete (); /* EMIT SIGNAL */
709 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InitialConnecting);
711 /* now handle the whole enchilada as if it was one
712 graph reorder event.
715 graph_reordered ();
717 /* update the full solo state, which can't be
718 correctly determined on a per-route basis, but
719 needs the global overview that only the session
720 has.
723 update_route_solo_state ();
726 void
727 Session::track_playlist_changed (boost::weak_ptr<Track> wp)
729 boost::shared_ptr<Track> track = wp.lock ();
730 if (!track) {
731 return;
734 boost::shared_ptr<Playlist> playlist;
736 if ((playlist = track->playlist()) != 0) {
737 playlist->RegionAdded.connect_same_thread (*this, boost::bind (&Session::playlist_region_added, this, _1));
738 playlist->RangesMoved.connect_same_thread (*this, boost::bind (&Session::playlist_ranges_moved, this, _1));
739 playlist->RegionsExtended.connect_same_thread (*this, boost::bind (&Session::playlist_regions_extended, this, _1));
743 bool
744 Session::record_enabling_legal () const
746 /* this used to be in here, but survey says.... we don't need to restrict it */
747 // if (record_status() == Recording) {
748 // return false;
749 // }
751 if (Config->get_all_safe()) {
752 return false;
754 return true;
757 void
758 Session::set_track_monitor_input_status (bool yn)
760 boost::shared_ptr<RouteList> rl = routes.reader ();
761 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
762 boost::shared_ptr<AudioTrack> tr = boost::dynamic_pointer_cast<AudioTrack> (*i);
763 if (tr && tr->record_enabled ()) {
764 //cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
765 tr->monitor_input (yn);
770 void
771 Session::reset_input_monitor_state ()
773 if (transport_rolling()) {
774 set_track_monitor_input_status (Config->get_monitoring_model() == HardwareMonitoring && !config.get_auto_input());
775 } else {
776 set_track_monitor_input_status (Config->get_monitoring_model() == HardwareMonitoring);
780 void
781 Session::auto_punch_start_changed (Location* location)
783 replace_event (SessionEvent::PunchIn, location->start());
785 if (get_record_enabled() && config.get_punch_in()) {
786 /* capture start has been changed, so save new pending state */
787 save_state ("", true);
791 void
792 Session::auto_punch_end_changed (Location* location)
794 framepos_t when_to_stop = location->end();
795 // when_to_stop += _worst_output_latency + _worst_input_latency;
796 replace_event (SessionEvent::PunchOut, when_to_stop);
799 void
800 Session::auto_punch_changed (Location* location)
802 framepos_t when_to_stop = location->end();
804 replace_event (SessionEvent::PunchIn, location->start());
805 //when_to_stop += _worst_output_latency + _worst_input_latency;
806 replace_event (SessionEvent::PunchOut, when_to_stop);
809 void
810 Session::auto_loop_changed (Location* location)
812 replace_event (SessionEvent::AutoLoop, location->end(), location->start());
814 if (transport_rolling() && play_loop) {
817 // if (_transport_frame > location->end()) {
819 if (_transport_frame < location->start() || _transport_frame > location->end()) {
820 // relocate to beginning of loop
821 clear_events (SessionEvent::LocateRoll);
823 request_locate (location->start(), true);
826 else if (Config->get_seamless_loop() && !loop_changing) {
828 // schedule a locate-roll to refill the diskstreams at the
829 // previous loop end
830 loop_changing = true;
832 if (location->end() > last_loopend) {
833 clear_events (SessionEvent::LocateRoll);
834 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, last_loopend, last_loopend, 0, true);
835 queue_event (ev);
841 last_loopend = location->end();
844 void
845 Session::set_auto_punch_location (Location* location)
847 Location* existing;
849 if ((existing = _locations->auto_punch_location()) != 0 && existing != location) {
850 punch_connections.drop_connections();
851 existing->set_auto_punch (false, this);
852 remove_event (existing->start(), SessionEvent::PunchIn);
853 clear_events (SessionEvent::PunchOut);
854 auto_punch_location_changed (0);
857 set_dirty();
859 if (location == 0) {
860 return;
863 if (location->end() <= location->start()) {
864 error << _("Session: you can't use that location for auto punch (start <= end)") << endmsg;
865 return;
868 punch_connections.drop_connections ();
870 location->start_changed.connect_same_thread (punch_connections, boost::bind (&Session::auto_punch_start_changed, this, _1));
871 location->end_changed.connect_same_thread (punch_connections, boost::bind (&Session::auto_punch_end_changed, this, _1));
872 location->changed.connect_same_thread (punch_connections, boost::bind (&Session::auto_punch_changed, this, _1));
874 location->set_auto_punch (true, this);
876 auto_punch_changed (location);
878 auto_punch_location_changed (location);
881 void
882 Session::set_auto_loop_location (Location* location)
884 Location* existing;
886 if ((existing = _locations->auto_loop_location()) != 0 && existing != location) {
887 loop_connections.drop_connections ();
888 existing->set_auto_loop (false, this);
889 remove_event (existing->end(), SessionEvent::AutoLoop);
890 auto_loop_location_changed (0);
893 set_dirty();
895 if (location == 0) {
896 return;
899 if (location->end() <= location->start()) {
900 error << _("Session: you can't use a mark for auto loop") << endmsg;
901 return;
904 last_loopend = location->end();
906 loop_connections.drop_connections ();
908 location->start_changed.connect_same_thread (loop_connections, boost::bind (&Session::auto_loop_changed, this, _1));
909 location->end_changed.connect_same_thread (loop_connections, boost::bind (&Session::auto_loop_changed, this, _1));
910 location->changed.connect_same_thread (loop_connections, boost::bind (&Session::auto_loop_changed, this, _1));
912 location->set_auto_loop (true, this);
914 /* take care of our stuff first */
916 auto_loop_changed (location);
918 /* now tell everyone else */
920 auto_loop_location_changed (location);
923 void
924 Session::locations_added (Location *)
926 set_dirty ();
929 void
930 Session::locations_changed ()
932 _locations->apply (*this, &Session::handle_locations_changed);
935 void
936 Session::handle_locations_changed (Locations::LocationList& locations)
938 Locations::LocationList::iterator i;
939 Location* location;
940 bool set_loop = false;
941 bool set_punch = false;
943 for (i = locations.begin(); i != locations.end(); ++i) {
945 location =* i;
947 if (location->is_auto_punch()) {
948 set_auto_punch_location (location);
949 set_punch = true;
951 if (location->is_auto_loop()) {
952 set_auto_loop_location (location);
953 set_loop = true;
956 if (location->is_session_range()) {
957 _session_range_location = location;
961 if (!set_loop) {
962 set_auto_loop_location (0);
964 if (!set_punch) {
965 set_auto_punch_location (0);
968 set_dirty();
971 void
972 Session::enable_record ()
974 while (1) {
975 RecordState rs = (RecordState) g_atomic_int_get (&_record_status);
977 if (rs == Recording) {
978 break;
981 if (g_atomic_int_compare_and_exchange (&_record_status, rs, Recording)) {
983 _last_record_location = _transport_frame;
984 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordStrobe));
986 if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
987 set_track_monitor_input_status (true);
990 RecordStateChanged ();
991 break;
996 void
997 Session::disable_record (bool rt_context, bool force)
999 RecordState rs;
1001 if ((rs = (RecordState) g_atomic_int_get (&_record_status)) != Disabled) {
1003 if ((!Config->get_latched_record_enable () && !play_loop) || force) {
1004 g_atomic_int_set (&_record_status, Disabled);
1005 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordExit));
1006 } else {
1007 if (rs == Recording) {
1008 g_atomic_int_set (&_record_status, Enabled);
1012 if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
1013 set_track_monitor_input_status (false);
1016 RecordStateChanged (); /* emit signal */
1018 if (!rt_context) {
1019 remove_pending_capture_state ();
1024 void
1025 Session::step_back_from_record ()
1027 if (g_atomic_int_compare_and_exchange (&_record_status, Recording, Enabled)) {
1029 if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
1030 set_track_monitor_input_status (false);
1035 void
1036 Session::maybe_enable_record ()
1038 if (_step_editors > 0) {
1039 return;
1042 g_atomic_int_set (&_record_status, Enabled);
1044 /* This function is currently called from somewhere other than an RT thread.
1045 This save_state() call therefore doesn't impact anything. Doing it here
1046 means that we save pending state of which sources the next record will use,
1047 which gives us some chance of recovering from a crash during the record.
1050 save_state ("", true);
1052 if (_transport_speed) {
1053 if (!config.get_punch_in()) {
1054 enable_record ();
1056 } else {
1057 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordPause));
1058 RecordStateChanged (); /* EMIT SIGNAL */
1061 set_dirty();
1064 framepos_t
1065 Session::audible_frame () const
1067 framepos_t ret;
1068 framepos_t tf;
1069 framecnt_t offset;
1071 /* the first of these two possible settings for "offset"
1072 mean that the audible frame is stationary until
1073 audio emerges from the latency compensation
1074 "pseudo-pipeline".
1076 the second means that the audible frame is stationary
1077 until audio would emerge from a physical port
1078 in the absence of any plugin latency compensation
1081 offset = worst_playback_latency ();
1083 if (offset > current_block_size) {
1084 offset -= current_block_size;
1085 } else {
1086 /* XXX is this correct? if we have no external
1087 physical connections and everything is internal
1088 then surely this is zero? still, how
1089 likely is that anyway?
1091 offset = current_block_size;
1094 if (synced_to_jack()) {
1095 tf = _engine.transport_frame();
1096 } else {
1097 tf = _transport_frame;
1100 ret = tf;
1102 if (!non_realtime_work_pending()) {
1104 /* MOVING */
1106 /* Check to see if we have passed the first guaranteed
1107 audible frame past our last start position. if not,
1108 return that last start point because in terms
1109 of audible frames, we have not moved yet.
1111 `Start position' in this context means the time we last
1112 either started or changed transport direction.
1115 if (_transport_speed > 0.0f) {
1117 if (!play_loop || !have_looped) {
1118 if (tf < _last_roll_or_reversal_location + offset) {
1119 return _last_roll_or_reversal_location;
1124 /* forwards */
1125 ret -= offset;
1127 } else if (_transport_speed < 0.0f) {
1129 /* XXX wot? no backward looping? */
1131 if (tf > _last_roll_or_reversal_location - offset) {
1132 return _last_roll_or_reversal_location;
1133 } else {
1134 /* backwards */
1135 ret += offset;
1140 return ret;
1143 void
1144 Session::set_frame_rate (framecnt_t frames_per_second)
1146 /** \fn void Session::set_frame_size(framecnt_t)
1147 the AudioEngine object that calls this guarantees
1148 that it will not be called while we are also in
1149 ::process(). Its fine to do things that block
1150 here.
1153 _base_frame_rate = frames_per_second;
1155 sync_time_vars();
1157 Automatable::set_automation_interval (ceil ((double) frames_per_second * (0.001 * Config->get_automation_interval())));
1159 clear_clicks ();
1161 // XXX we need some equivalent to this, somehow
1162 // SndFileSource::setup_standard_crossfades (frames_per_second);
1164 set_dirty();
1166 /* XXX need to reset/reinstantiate all LADSPA plugins */
1169 void
1170 Session::set_block_size (pframes_t nframes)
1172 /* the AudioEngine guarantees
1173 that it will not be called while we are also in
1174 ::process(). It is therefore fine to do things that block
1175 here.
1179 current_block_size = nframes;
1181 ensure_buffers ();
1183 boost::shared_ptr<RouteList> r = routes.reader ();
1185 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1186 (*i)->set_block_size (nframes);
1189 boost::shared_ptr<RouteList> rl = routes.reader ();
1190 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1191 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1192 if (tr) {
1193 tr->set_block_size (nframes);
1197 set_worst_io_latencies ();
1201 struct RouteSorter {
1202 /** @return true to run r1 before r2, otherwise false */
1203 bool sort_by_rec_enabled (const boost::shared_ptr<Route>& r1, const boost::shared_ptr<Route>& r2) {
1204 if (r1->record_enabled()) {
1205 if (r2->record_enabled()) {
1206 /* both rec-enabled, just use signal order */
1207 return r1->order_key(N_("signal")) < r2->order_key(N_("signal"));
1208 } else {
1209 /* r1 rec-enabled, r2 not rec-enabled, run r2 early */
1210 return false;
1212 } else {
1213 if (r2->record_enabled()) {
1214 /* r2 rec-enabled, r1 not rec-enabled, run r1 early */
1215 return true;
1216 } else {
1217 /* neither rec-enabled, use signal order */
1218 return r1->order_key(N_("signal")) < r2->order_key(N_("signal"));
1223 bool operator() (boost::shared_ptr<Route> r1, boost::shared_ptr<Route> r2) {
1224 if (r2->feeds (r1)) {
1225 /* r1 fed by r2; run r2 early */
1226 return false;
1227 } else if (r1->feeds (r2)) {
1228 /* r2 fed by r1; run r1 early */
1229 return true;
1230 } else {
1231 if (r1->not_fed ()) {
1232 if (r2->not_fed ()) {
1233 /* no ardour-based connections inbound to either route. */
1234 return sort_by_rec_enabled (r1, r2);
1235 } else {
1236 /* r2 has connections, r1 does not; run r1 early */
1237 return true;
1239 } else {
1240 if (r2->not_fed()) {
1241 /* r1 has connections, r2 does not; run r2 early */
1242 return false;
1243 } else {
1244 /* both r1 and r2 have connections, but not to each other. just use signal order */
1245 return r1->order_key(N_("signal")) < r2->order_key(N_("signal"));
1252 static void
1253 trace_terminal (boost::shared_ptr<Route> r1, boost::shared_ptr<Route> rbase)
1255 boost::shared_ptr<Route> r2;
1257 if (r1->feeds (rbase) && rbase->feeds (r1)) {
1258 info << string_compose(_("feedback loop setup between %1 and %2"), r1->name(), rbase->name()) << endmsg;
1259 return;
1262 /* make a copy of the existing list of routes that feed r1 */
1264 Route::FedBy existing (r1->fed_by());
1266 /* for each route that feeds r1, recurse, marking it as feeding
1267 rbase as well.
1270 for (Route::FedBy::iterator i = existing.begin(); i != existing.end(); ++i) {
1271 if (!(r2 = i->r.lock ())) {
1272 /* (*i) went away, ignore it */
1273 continue;
1276 /* r2 is a route that feeds r1 which somehow feeds base. mark
1277 base as being fed by r2
1280 rbase->add_fed_by (r2, i->sends_only);
1282 if (r2 != rbase) {
1284 /* 2nd level feedback loop detection. if r1 feeds or is fed by r2,
1285 stop here.
1288 if (r1->feeds (r2) && r2->feeds (r1)) {
1289 continue;
1292 /* now recurse, so that we can mark base as being fed by
1293 all routes that feed r2
1296 trace_terminal (r2, rbase);
1302 void
1303 Session::resort_routes ()
1305 /* don't do anything here with signals emitted
1306 by Routes while we are being destroyed.
1309 if (_state_of_the_state & Deletion) {
1310 return;
1314 RCUWriter<RouteList> writer (routes);
1315 boost::shared_ptr<RouteList> r = writer.get_copy ();
1316 resort_routes_using (r);
1317 /* writer goes out of scope and forces update */
1320 //route_graph->dump(1);
1322 #ifndef NDEBUG
1323 boost::shared_ptr<RouteList> rl = routes.reader ();
1324 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1325 DEBUG_TRACE (DEBUG::Graph, string_compose ("%1 fed by ...\n", (*i)->name()));
1327 const Route::FedBy& fb ((*i)->fed_by());
1329 for (Route::FedBy::const_iterator f = fb.begin(); f != fb.end(); ++f) {
1330 boost::shared_ptr<Route> sf = f->r.lock();
1331 if (sf) {
1332 DEBUG_TRACE (DEBUG::Graph, string_compose ("\t%1 (sends only ? %2)\n", sf->name(), f->sends_only));
1336 #endif
1339 void
1340 Session::resort_routes_using (boost::shared_ptr<RouteList> r)
1342 RouteList::iterator i, j;
1344 for (i = r->begin(); i != r->end(); ++i) {
1346 (*i)->clear_fed_by ();
1348 for (j = r->begin(); j != r->end(); ++j) {
1350 /* although routes can feed themselves, it will
1351 cause an endless recursive descent if we
1352 detect it. so don't bother checking for
1353 self-feeding.
1356 if (*j == *i) {
1357 continue;
1360 bool via_sends_only;
1362 if ((*j)->direct_feeds (*i, &via_sends_only)) {
1363 (*i)->add_fed_by (*j, via_sends_only);
1368 for (i = r->begin(); i != r->end(); ++i) {
1369 trace_terminal (*i, *i);
1372 RouteSorter cmp;
1373 r->sort (cmp);
1375 route_graph->rechain (r);
1377 #ifndef NDEBUG
1378 DEBUG_TRACE (DEBUG::Graph, "Routes resorted, order follows:\n");
1379 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1380 DEBUG_TRACE (DEBUG::Graph, string_compose ("\t%1 signal order %2\n",
1381 (*i)->name(), (*i)->order_key ("signal")));
1383 #endif
1387 /** Find a route name starting with \a base, maybe followed by the
1388 * lowest \a id. \a id will always be added if \a definitely_add_number
1389 * is true on entry; otherwise it will only be added if required
1390 * to make the name unique.
1392 * Names are constructed like e.g. "Audio 3" for base="Audio" and id=3.
1393 * The available route name with the lowest ID will be used, and \a id
1394 * will be set to the ID.
1396 * \return false if a route name could not be found, and \a track_name
1397 * and \a id do not reflect a free route name.
1399 bool
1400 Session::find_route_name (string const & base, uint32_t& id, char* name, size_t name_len, bool definitely_add_number)
1402 if (!definitely_add_number && route_by_name (base) == 0) {
1403 /* juse use the base */
1404 snprintf (name, name_len, "%s", base.c_str());
1405 return true;
1408 do {
1409 snprintf (name, name_len, "%s %" PRIu32, base.c_str(), id);
1411 if (route_by_name (name) == 0) {
1412 return true;
1415 ++id;
1417 } while (id < (UINT_MAX-1));
1419 return false;
1422 /** Count the total ins and outs of all non-hidden tracks in the session and return them in in and out */
1423 void
1424 Session::count_existing_track_channels (ChanCount& in, ChanCount& out)
1426 in = ChanCount::ZERO;
1427 out = ChanCount::ZERO;
1429 boost::shared_ptr<RouteList> r = routes.reader ();
1431 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1432 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1433 if (tr && !tr->is_hidden()) {
1434 in += tr->n_inputs();
1435 out += tr->n_outputs();
1440 /** Caller must not hold process lock
1441 * @param name_template string to use for the start of the name, or "" to use "Midi".
1443 list<boost::shared_ptr<MidiTrack> >
1444 Session::new_midi_track (TrackMode mode, RouteGroup* route_group, uint32_t how_many, string name_template)
1446 char track_name[32];
1447 uint32_t track_id = 0;
1448 string port;
1449 RouteList new_routes;
1450 list<boost::shared_ptr<MidiTrack> > ret;
1451 uint32_t control_id;
1453 control_id = ntracks() + nbusses();
1455 bool const use_number = (how_many != 1);
1457 while (how_many) {
1458 if (!find_route_name (name_template.empty() ? _("Midi") : name_template, ++track_id, track_name, sizeof(track_name), use_number)) {
1459 error << "cannot find name for new midi track" << endmsg;
1460 goto failed;
1463 boost::shared_ptr<MidiTrack> track;
1465 try {
1466 track.reset (new MidiTrack (*this, track_name, Route::Flag (0), mode));
1468 if (track->init ()) {
1469 goto failed;
1472 track->use_new_diskstream();
1474 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1475 boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1476 #endif
1478 Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
1479 if (track->input()->ensure_io (ChanCount(DataType::MIDI, 1), false, this)) {
1480 error << "cannot configure 1 in/1 out configuration for new midi track" << endmsg;
1481 goto failed;
1484 if (track->output()->ensure_io (ChanCount(DataType::MIDI, 1), false, this)) {
1485 error << "cannot configure 1 in/1 out configuration for new midi track" << endmsg;
1486 goto failed;
1490 track->non_realtime_input_change();
1492 if (route_group) {
1493 route_group->add (track);
1496 track->DiskstreamChanged.connect_same_thread (*this, boost::bind (&Session::resort_routes, this));
1497 track->set_remote_control_id (control_id);
1499 new_routes.push_back (track);
1500 ret.push_back (track);
1503 catch (failed_constructor &err) {
1504 error << _("Session: could not create new midi track.") << endmsg;
1505 goto failed;
1508 catch (AudioEngine::PortRegistrationFailure& pfe) {
1510 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;
1511 goto failed;
1514 --how_many;
1517 failed:
1518 if (!new_routes.empty()) {
1519 add_routes (new_routes, true, true);
1522 return ret;
1525 void
1526 Session::midi_output_change_handler (IOChange change, void * /*src*/, boost::weak_ptr<Route> wmt)
1528 boost::shared_ptr<Route> midi_track (wmt.lock());
1530 if (!midi_track) {
1531 return;
1534 if ((change.type & IOChange::ConfigurationChanged) && Config->get_output_auto_connect() != ManualConnect) {
1536 if (change.after.n_audio() <= change.before.n_audio()) {
1537 return;
1540 /* new audio ports: make sure the audio goes somewhere useful,
1541 unless the user has no-auto-connect selected.
1543 The existing ChanCounts don't matter for this call as they are only
1544 to do with matching input and output indices, and we are only changing
1545 outputs here.
1548 ChanCount dummy;
1550 auto_connect_route (midi_track, dummy, dummy, false, false, ChanCount(), change.before);
1554 /** @param connect_inputs true to connect inputs as well as outputs, false to connect just outputs.
1555 * @param input_start Where to start from when auto-connecting inputs; e.g. if this is 0, auto-connect starting from input 0.
1556 * @param output_start As \a input_start, but for outputs.
1558 void
1559 Session::auto_connect_route (boost::shared_ptr<Route> route, ChanCount& existing_inputs, ChanCount& existing_outputs,
1560 bool with_lock, bool connect_inputs, ChanCount input_start, ChanCount output_start)
1562 if (!IO::connecting_legal) {
1563 return;
1566 Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock (), Glib::NOT_LOCK);
1568 if (with_lock) {
1569 lm.acquire ();
1572 /* If both inputs and outputs are auto-connected to physical ports,
1573 use the max of input and output offsets to ensure auto-connected
1574 port numbers always match up (e.g. the first audio input and the
1575 first audio output of the route will have the same physical
1576 port number). Otherwise just use the lowest input or output
1577 offset possible.
1580 DEBUG_TRACE (DEBUG::Graph,
1581 string_compose("Auto-connect: existing in = %1 out = %2\n",
1582 existing_inputs, existing_outputs));
1584 const bool in_out_physical =
1585 (Config->get_input_auto_connect() & AutoConnectPhysical)
1586 && (Config->get_output_auto_connect() & AutoConnectPhysical)
1587 && connect_inputs;
1589 const ChanCount in_offset = in_out_physical
1590 ? ChanCount::max(existing_inputs, existing_outputs)
1591 : existing_inputs;
1593 const ChanCount out_offset = in_out_physical
1594 ? ChanCount::max(existing_inputs, existing_outputs)
1595 : existing_outputs;
1597 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1598 vector<string> physinputs;
1599 vector<string> physoutputs;
1601 _engine.get_physical_outputs (*t, physoutputs);
1602 _engine.get_physical_inputs (*t, physinputs);
1604 if (!physinputs.empty() && connect_inputs) {
1605 uint32_t nphysical_in = physinputs.size();
1607 DEBUG_TRACE (DEBUG::Graph,
1608 string_compose("There are %1 physical inputs of type %2\n",
1609 nphysical_in, *t));
1611 for (uint32_t i = input_start.get(*t); i < route->n_inputs().get(*t) && i < nphysical_in; ++i) {
1612 string port;
1614 if (Config->get_input_auto_connect() & AutoConnectPhysical) {
1615 DEBUG_TRACE (DEBUG::Graph,
1616 string_compose("Get index %1 + %2 % %3 = %4\n",
1617 in_offset.get(*t), i, nphysical_in,
1618 (in_offset.get(*t) + i) % nphysical_in));
1619 port = physinputs[(in_offset.get(*t) + i) % nphysical_in];
1622 DEBUG_TRACE (DEBUG::Graph,
1623 string_compose("Connect route %1 IN to %2\n",
1624 route->name(), port));
1626 if (!port.empty() && route->input()->connect (route->input()->ports().port(*t, i), port, this)) {
1627 break;
1630 ChanCount one_added (*t, 1);
1631 existing_inputs += one_added;
1635 if (!physoutputs.empty()) {
1636 uint32_t nphysical_out = physoutputs.size();
1637 for (uint32_t i = output_start.get(*t); i < route->n_outputs().get(*t); ++i) {
1638 string port;
1640 if ((*t) == DataType::MIDI || Config->get_output_auto_connect() & AutoConnectPhysical) {
1641 port = physoutputs[(out_offset.get(*t) + i) % nphysical_out];
1642 } else if ((*t) == DataType::AUDIO && Config->get_output_auto_connect() & AutoConnectMaster) {
1643 /* master bus is audio only */
1644 if (_master_out && _master_out->n_inputs().get(*t) > 0) {
1645 port = _master_out->input()->ports().port(*t,
1646 i % _master_out->input()->n_ports().get(*t))->name();
1650 DEBUG_TRACE (DEBUG::Graph,
1651 string_compose("Connect route %1 OUT to %2\n",
1652 route->name(), port));
1654 if (!port.empty() && route->output()->connect (route->output()->ports().port(*t, i), port, this)) {
1655 break;
1658 ChanCount one_added (*t, 1);
1659 existing_outputs += one_added;
1665 /** Caller must not hold process lock
1666 * @param name_template string to use for the start of the name, or "" to use "Audio".
1668 list< boost::shared_ptr<AudioTrack> >
1669 Session::new_audio_track (
1670 int input_channels, int output_channels, TrackMode mode, RouteGroup* route_group, uint32_t how_many, string name_template
1673 char track_name[32];
1674 uint32_t track_id = 0;
1675 string port;
1676 RouteList new_routes;
1677 list<boost::shared_ptr<AudioTrack> > ret;
1678 uint32_t control_id;
1680 control_id = ntracks() + nbusses() + 1;
1682 bool const use_number = (how_many != 1);
1684 while (how_many) {
1685 if (!find_route_name (name_template.empty() ? _("Audio") : name_template, ++track_id, track_name, sizeof(track_name), use_number)) {
1686 error << "cannot find name for new audio track" << endmsg;
1687 goto failed;
1690 boost::shared_ptr<AudioTrack> track;
1692 try {
1693 track.reset (new AudioTrack (*this, track_name, Route::Flag (0), mode));
1695 if (track->init ()) {
1696 goto failed;
1699 track->use_new_diskstream();
1701 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1702 boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1703 #endif
1705 Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
1707 if (track->input()->ensure_io (ChanCount(DataType::AUDIO, input_channels), false, this)) {
1708 error << string_compose (
1709 _("cannot configure %1 in/%2 out configuration for new audio track"),
1710 input_channels, output_channels)
1711 << endmsg;
1712 goto failed;
1715 if (track->output()->ensure_io (ChanCount(DataType::AUDIO, output_channels), false, this)) {
1716 error << string_compose (
1717 _("cannot configure %1 in/%2 out configuration for new audio track"),
1718 input_channels, output_channels)
1719 << endmsg;
1720 goto failed;
1724 if (route_group) {
1725 route_group->add (track);
1728 track->non_realtime_input_change();
1730 track->DiskstreamChanged.connect_same_thread (*this, boost::bind (&Session::resort_routes, this));
1731 track->set_remote_control_id (control_id);
1732 ++control_id;
1734 new_routes.push_back (track);
1735 ret.push_back (track);
1738 catch (failed_constructor &err) {
1739 error << _("Session: could not create new audio track.") << endmsg;
1740 goto failed;
1743 catch (AudioEngine::PortRegistrationFailure& pfe) {
1745 error << pfe.what() << endmsg;
1746 goto failed;
1749 --how_many;
1752 failed:
1753 if (!new_routes.empty()) {
1754 add_routes (new_routes, true, true);
1757 return ret;
1760 void
1761 Session::set_remote_control_ids ()
1763 RemoteModel m = Config->get_remote_model();
1764 bool emit_signal = false;
1766 boost::shared_ptr<RouteList> r = routes.reader ();
1768 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1769 if (MixerOrdered == m) {
1770 int32_t order = (*i)->order_key(N_("signal"));
1771 (*i)->set_remote_control_id (order+1, false);
1772 emit_signal = true;
1773 } else if (EditorOrdered == m) {
1774 int32_t order = (*i)->order_key(N_("editor"));
1775 (*i)->set_remote_control_id (order+1, false);
1776 emit_signal = true;
1777 } else if (UserOrdered == m) {
1778 //do nothing ... only changes to remote id's are initiated by user
1782 if (emit_signal) {
1783 Route::RemoteControlIDChange();
1787 /** Caller must not hold process lock.
1788 * @param name_template string to use for the start of the name, or "" to use "Bus".
1790 RouteList
1791 Session::new_audio_route (int input_channels, int output_channels, RouteGroup* route_group, uint32_t how_many, string name_template)
1793 char bus_name[32];
1794 uint32_t bus_id = 0;
1795 string port;
1796 RouteList ret;
1797 uint32_t control_id;
1799 control_id = ntracks() + nbusses() + 1;
1801 bool const use_number = (how_many != 1);
1802 while (how_many) {
1803 if (!find_route_name (name_template.empty () ? _("Bus") : name_template, ++bus_id, bus_name, sizeof(bus_name), use_number)) {
1804 error << "cannot find name for new audio bus" << endmsg;
1805 goto failure;
1808 try {
1809 boost::shared_ptr<Route> bus (new Route (*this, bus_name, Route::Flag(0), DataType::AUDIO));
1811 if (bus->init ()) {
1812 goto failure;
1815 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1816 boost_debug_shared_ptr_mark_interesting (bus.get(), "Route");
1817 #endif
1819 Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
1821 if (bus->input()->ensure_io (ChanCount(DataType::AUDIO, input_channels), false, this)) {
1822 error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
1823 input_channels, output_channels)
1824 << endmsg;
1825 goto failure;
1829 if (bus->output()->ensure_io (ChanCount(DataType::AUDIO, output_channels), false, this)) {
1830 error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
1831 input_channels, output_channels)
1832 << endmsg;
1833 goto failure;
1837 if (route_group) {
1838 route_group->add (bus);
1840 bus->set_remote_control_id (control_id);
1841 ++control_id;
1843 bus->add_internal_return ();
1845 ret.push_back (bus);
1849 catch (failed_constructor &err) {
1850 error << _("Session: could not create new audio route.") << endmsg;
1851 goto failure;
1854 catch (AudioEngine::PortRegistrationFailure& pfe) {
1855 error << pfe.what() << endmsg;
1856 goto failure;
1860 --how_many;
1863 failure:
1864 if (!ret.empty()) {
1865 add_routes (ret, true, true);
1868 return ret;
1872 RouteList
1873 Session::new_route_from_template (uint32_t how_many, const std::string& template_path)
1875 char name[32];
1876 RouteList ret;
1877 uint32_t control_id;
1878 XMLTree tree;
1879 uint32_t number = 0;
1881 if (!tree.read (template_path.c_str())) {
1882 return ret;
1885 XMLNode* node = tree.root();
1887 control_id = ntracks() + nbusses() + 1;
1889 while (how_many) {
1891 XMLNode node_copy (*node); // make a copy so we can change the name if we need to
1893 std::string node_name = IO::name_from_state (*node_copy.children().front());
1895 /* generate a new name by adding a number to the end of the template name */
1896 if (!find_route_name (node_name.c_str(), ++number, name, sizeof(name), true)) {
1897 fatal << _("Session: UINT_MAX routes? impossible!") << endmsg;
1898 /*NOTREACHED*/
1901 /* set IO children to use the new name */
1902 XMLNodeList const & children = node_copy.children ();
1903 for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
1904 if ((*i)->name() == IO::state_node_name) {
1905 IO::set_name_in_state (**i, name);
1909 Track::zero_diskstream_id_in_xml (node_copy);
1911 try {
1912 boost::shared_ptr<Route> route (XMLRouteFactory (node_copy, 3000));
1914 if (route == 0) {
1915 error << _("Session: cannot create track/bus from template description") << endmsg;
1916 goto out;
1919 if (boost::dynamic_pointer_cast<Track>(route)) {
1920 /* force input/output change signals so that the new diskstream
1921 picks up the configuration of the route. During session
1922 loading this normally happens in a different way.
1925 Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
1927 IOChange change (IOChange::Type (IOChange::ConfigurationChanged | IOChange::ConnectionsChanged));
1928 change.after = route->input()->n_ports();
1929 route->input()->changed (change, this);
1930 change.after = route->output()->n_ports();
1931 route->output()->changed (change, this);
1934 route->set_remote_control_id (control_id);
1935 ++control_id;
1937 ret.push_back (route);
1940 catch (failed_constructor &err) {
1941 error << _("Session: could not create new route from template") << endmsg;
1942 goto out;
1945 catch (AudioEngine::PortRegistrationFailure& pfe) {
1946 error << pfe.what() << endmsg;
1947 goto out;
1950 --how_many;
1953 out:
1954 if (!ret.empty()) {
1955 add_routes (ret, true, true);
1958 return ret;
1961 void
1962 Session::add_routes (RouteList& new_routes, bool auto_connect, bool save)
1964 ChanCount existing_inputs;
1965 ChanCount existing_outputs;
1967 count_existing_track_channels (existing_inputs, existing_outputs);
1970 RCUWriter<RouteList> writer (routes);
1971 boost::shared_ptr<RouteList> r = writer.get_copy ();
1972 r->insert (r->end(), new_routes.begin(), new_routes.end());
1975 /* if there is no control out and we're not in the middle of loading,
1976 resort the graph here. if there is a control out, we will resort
1977 toward the end of this method. if we are in the middle of loading,
1978 we will resort when done.
1981 if (!_monitor_out && IO::connecting_legal) {
1982 resort_routes_using (r);
1986 for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) {
1988 boost::weak_ptr<Route> wpr (*x);
1989 boost::shared_ptr<Route> r (*x);
1991 r->listen_changed.connect_same_thread (*this, boost::bind (&Session::route_listen_changed, this, _1, wpr));
1992 r->solo_changed.connect_same_thread (*this, boost::bind (&Session::route_solo_changed, this, _1, _2, wpr));
1993 r->solo_isolated_changed.connect_same_thread (*this, boost::bind (&Session::route_solo_isolated_changed, this, _1, wpr));
1994 r->mute_changed.connect_same_thread (*this, boost::bind (&Session::route_mute_changed, this, _1));
1995 r->output()->changed.connect_same_thread (*this, boost::bind (&Session::set_worst_io_latencies_x, this, _1, _2));
1996 r->processors_changed.connect_same_thread (*this, boost::bind (&Session::route_processors_changed, this, _1));
1997 r->order_key_changed.connect_same_thread (*this, boost::bind (&Session::route_order_key_changed, this));
1999 if (r->is_master()) {
2000 _master_out = r;
2003 if (r->is_monitor()) {
2004 _monitor_out = r;
2007 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (r);
2008 if (tr) {
2009 tr->PlaylistChanged.connect_same_thread (*this, boost::bind (&Session::track_playlist_changed, this, boost::weak_ptr<Track> (tr)));
2010 track_playlist_changed (boost::weak_ptr<Track> (tr));
2011 tr->RecordEnableChanged.connect_same_thread (*this, boost::bind (&Session::update_have_rec_enabled_track, this));
2013 boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (tr);
2014 if (mt) {
2015 mt->StepEditStatusChange.connect_same_thread (*this, boost::bind (&Session::step_edit_status_change, this, _1));
2016 mt->output()->changed.connect_same_thread (*this, boost::bind (&Session::midi_output_change_handler, this, _1, _2, boost::weak_ptr<Route>(mt)));
2020 if (auto_connect) {
2021 auto_connect_route (r, existing_inputs, existing_outputs, true);
2025 if (_monitor_out && IO::connecting_legal) {
2027 for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) {
2028 if ((*x)->is_monitor()) {
2029 /* relax */
2030 } else if ((*x)->is_master()) {
2031 /* relax */
2032 } else {
2033 (*x)->listen_via_monitor ();
2037 resort_routes ();
2040 set_dirty();
2042 if (save) {
2043 save_state (_current_snapshot_name);
2046 RouteAdded (new_routes); /* EMIT SIGNAL */
2047 Route::RemoteControlIDChange (); /* EMIT SIGNAL */
2050 void
2051 Session::globally_set_send_gains_to_zero (boost::shared_ptr<Route> dest)
2053 boost::shared_ptr<RouteList> r = routes.reader ();
2054 boost::shared_ptr<Send> s;
2056 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2057 if ((s = (*i)->internal_send_for (dest)) != 0) {
2058 s->amp()->gain_control()->set_value (0.0);
2063 void
2064 Session::globally_set_send_gains_to_unity (boost::shared_ptr<Route> dest)
2066 boost::shared_ptr<RouteList> r = routes.reader ();
2067 boost::shared_ptr<Send> s;
2069 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2070 if ((s = (*i)->internal_send_for (dest)) != 0) {
2071 s->amp()->gain_control()->set_value (1.0);
2076 void
2077 Session::globally_set_send_gains_from_track(boost::shared_ptr<Route> dest)
2079 boost::shared_ptr<RouteList> r = routes.reader ();
2080 boost::shared_ptr<Send> s;
2082 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2083 if ((s = (*i)->internal_send_for (dest)) != 0) {
2084 s->amp()->gain_control()->set_value ((*i)->gain_control()->get_value());
2089 /** @param include_buses true to add sends to buses and tracks, false for just tracks */
2090 void
2091 Session::globally_add_internal_sends (boost::shared_ptr<Route> dest, Placement p, bool include_buses)
2093 boost::shared_ptr<RouteList> r = routes.reader ();
2094 boost::shared_ptr<RouteList> t (new RouteList);
2096 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2097 if (include_buses || boost::dynamic_pointer_cast<Track>(*i)) {
2098 t->push_back (*i);
2102 add_internal_sends (dest, p, t);
2105 void
2106 Session::add_internal_sends (boost::shared_ptr<Route> dest, Placement p, boost::shared_ptr<RouteList> senders)
2108 if (dest->is_monitor() || dest->is_master()) {
2109 return;
2112 if (!dest->internal_return()) {
2113 dest->add_internal_return();
2116 for (RouteList::iterator i = senders->begin(); i != senders->end(); ++i) {
2118 if ((*i)->is_monitor() || (*i)->is_master() || (*i) == dest) {
2119 continue;
2122 (*i)->listen_via (dest, p);
2125 graph_reordered ();
2128 void
2129 Session::remove_route (boost::shared_ptr<Route> route)
2131 if (((route == _master_out) || (route == _monitor_out)) && !Config->get_allow_special_bus_removal()) {
2132 return;
2135 route->set_solo (false, this);
2138 RCUWriter<RouteList> writer (routes);
2139 boost::shared_ptr<RouteList> rs = writer.get_copy ();
2141 rs->remove (route);
2143 /* deleting the master out seems like a dumb
2144 idea, but its more of a UI policy issue
2145 than our concern.
2148 if (route == _master_out) {
2149 _master_out = boost::shared_ptr<Route> ();
2152 if (route == _monitor_out) {
2154 /* cancel control outs for all routes */
2156 for (RouteList::iterator r = rs->begin(); r != rs->end(); ++r) {
2157 (*r)->drop_listen (_monitor_out);
2160 _monitor_out.reset ();
2163 /* writer goes out of scope, forces route list update */
2166 update_route_solo_state ();
2168 // We need to disconnect the route's inputs and outputs
2170 route->input()->disconnect (0);
2171 route->output()->disconnect (0);
2173 /* if the route had internal sends sending to it, remove them */
2174 if (route->internal_return()) {
2176 boost::shared_ptr<RouteList> r = routes.reader ();
2177 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2178 boost::shared_ptr<Send> s = (*i)->internal_send_for (route);
2179 if (s) {
2180 (*i)->remove_processor (s);
2185 boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (route);
2186 if (mt && mt->step_editing()) {
2187 if (_step_editors > 0) {
2188 _step_editors--;
2192 update_latency_compensation ();
2193 set_dirty();
2195 /* Re-sort routes to remove the graph's current references to the one that is
2196 * going away, then flush old references out of the graph.
2199 resort_routes ();
2200 route_graph->clear_other_chain ();
2202 /* get rid of it from the dead wood collection in the route list manager */
2204 /* XXX i think this is unsafe as it currently stands, but i am not sure. (pd, october 2nd, 2006) */
2206 routes.flush ();
2208 /* try to cause everyone to drop their references */
2210 route->drop_references ();
2212 sync_order_keys (N_("session"));
2214 Route::RemoteControlIDChange(); /* EMIT SIGNAL */
2216 /* save the new state of the world */
2218 if (save_state (_current_snapshot_name)) {
2219 save_history (_current_snapshot_name);
2223 void
2224 Session::route_mute_changed (void* /*src*/)
2226 set_dirty ();
2229 void
2230 Session::route_listen_changed (void* /*src*/, boost::weak_ptr<Route> wpr)
2232 boost::shared_ptr<Route> route = wpr.lock();
2233 if (!route) {
2234 error << string_compose (_("programming error: %1"), X_("invalid route weak ptr passed to route_solo_changed")) << endmsg;
2235 return;
2238 if (route->listening_via_monitor ()) {
2240 if (Config->get_exclusive_solo()) {
2241 /* new listen: disable all other listen */
2242 boost::shared_ptr<RouteList> r = routes.reader ();
2243 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2244 if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_hidden()) {
2245 continue;
2247 (*i)->set_listen (false, this);
2251 _listen_cnt++;
2253 } else if (_listen_cnt > 0) {
2255 _listen_cnt--;
2258 update_route_solo_state ();
2260 void
2261 Session::route_solo_isolated_changed (void* /*src*/, boost::weak_ptr<Route> wpr)
2263 boost::shared_ptr<Route> route = wpr.lock ();
2265 if (!route) {
2266 /* should not happen */
2267 error << string_compose (_("programming error: %1"), X_("invalid route weak ptr passed to route_solo_changed")) << endmsg;
2268 return;
2271 bool send_changed = false;
2273 if (route->solo_isolated()) {
2274 if (_solo_isolated_cnt == 0) {
2275 send_changed = true;
2277 _solo_isolated_cnt++;
2278 } else if (_solo_isolated_cnt > 0) {
2279 _solo_isolated_cnt--;
2280 if (_solo_isolated_cnt == 0) {
2281 send_changed = true;
2285 if (send_changed) {
2286 IsolatedChanged (); /* EMIT SIGNAL */
2290 void
2291 Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_ptr<Route> wpr)
2293 if (!self_solo_change) {
2294 // session doesn't care about changes to soloed-by-others
2295 return;
2298 if (solo_update_disabled) {
2299 // We know already
2300 return;
2303 boost::shared_ptr<Route> route = wpr.lock ();
2305 if (!route) {
2306 /* should not happen */
2307 error << string_compose (_("programming error: %1"), X_("invalid route weak ptr passed to route_solo_changed")) << endmsg;
2308 return;
2311 boost::shared_ptr<RouteList> r = routes.reader ();
2312 int32_t delta;
2314 if (route->self_soloed()) {
2315 delta = 1;
2316 } else {
2317 delta = -1;
2320 if (delta == 1 && Config->get_exclusive_solo()) {
2321 /* new solo: disable all other solos */
2322 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2323 if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_hidden()) {
2324 continue;
2326 (*i)->set_solo (false, this);
2330 solo_update_disabled = true;
2332 RouteList uninvolved;
2334 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2335 bool via_sends_only;
2336 bool in_signal_flow;
2338 if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_hidden()) {
2339 continue;
2342 in_signal_flow = false;
2344 if ((*i)->feeds (route, &via_sends_only)) {
2345 if (!via_sends_only) {
2346 if (!route->soloed_by_others_upstream()) {
2347 (*i)->mod_solo_by_others_downstream (delta);
2349 in_signal_flow = true;
2353 if (route->feeds (*i, &via_sends_only)) {
2354 (*i)->mod_solo_by_others_upstream (delta);
2355 in_signal_flow = true;
2358 if (!in_signal_flow) {
2359 uninvolved.push_back (*i);
2363 solo_update_disabled = false;
2364 update_route_solo_state (r);
2366 /* now notify that the mute state of the routes not involved in the signal
2367 pathway of the just-solo-changed route may have altered.
2370 for (RouteList::iterator i = uninvolved.begin(); i != uninvolved.end(); ++i) {
2371 (*i)->mute_changed (this);
2374 SoloChanged (); /* EMIT SIGNAL */
2375 set_dirty();
2378 void
2379 Session::update_route_solo_state (boost::shared_ptr<RouteList> r)
2381 /* now figure out if anything that matters is soloed (or is "listening")*/
2383 bool something_soloed = false;
2384 uint32_t listeners = 0;
2385 uint32_t isolated = 0;
2387 if (!r) {
2388 r = routes.reader();
2391 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2392 if (!(*i)->is_master() && !(*i)->is_monitor() && !(*i)->is_hidden() && (*i)->self_soloed()) {
2393 something_soloed = true;
2396 if (!(*i)->is_hidden() && (*i)->listening_via_monitor()) {
2397 if (Config->get_solo_control_is_listen_control()) {
2398 listeners++;
2399 } else {
2400 (*i)->set_listen (false, this);
2404 if ((*i)->solo_isolated()) {
2405 isolated++;
2409 if (something_soloed != _non_soloed_outs_muted) {
2410 _non_soloed_outs_muted = something_soloed;
2411 SoloActive (_non_soloed_outs_muted); /* EMIT SIGNAL */
2414 _listen_cnt = listeners;
2416 if (isolated != _solo_isolated_cnt) {
2417 _solo_isolated_cnt = isolated;
2418 IsolatedChanged (); /* EMIT SIGNAL */
2422 boost::shared_ptr<RouteList>
2423 Session::get_routes_with_internal_returns() const
2425 boost::shared_ptr<RouteList> r = routes.reader ();
2426 boost::shared_ptr<RouteList> rl (new RouteList);
2428 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2429 if ((*i)->internal_return ()) {
2430 rl->push_back (*i);
2433 return rl;
2436 bool
2437 Session::io_name_is_legal (const std::string& name)
2439 boost::shared_ptr<RouteList> r = routes.reader ();
2441 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2442 if ((*i)->name() == name) {
2443 return false;
2446 if ((*i)->has_io_processor_named (name)) {
2447 return false;
2451 return true;
2454 boost::shared_ptr<Route>
2455 Session::route_by_name (string name)
2457 boost::shared_ptr<RouteList> r = routes.reader ();
2459 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2460 if ((*i)->name() == name) {
2461 return *i;
2465 return boost::shared_ptr<Route> ((Route*) 0);
2468 boost::shared_ptr<Route>
2469 Session::route_by_id (PBD::ID id)
2471 boost::shared_ptr<RouteList> r = routes.reader ();
2473 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2474 if ((*i)->id() == id) {
2475 return *i;
2479 return boost::shared_ptr<Route> ((Route*) 0);
2482 boost::shared_ptr<Route>
2483 Session::route_by_remote_id (uint32_t id)
2485 boost::shared_ptr<RouteList> r = routes.reader ();
2487 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2488 if ((*i)->remote_control_id() == id) {
2489 return *i;
2493 return boost::shared_ptr<Route> ((Route*) 0);
2496 void
2497 Session::playlist_region_added (boost::weak_ptr<Region> w)
2499 boost::shared_ptr<Region> r = w.lock ();
2500 if (!r) {
2501 return;
2504 /* These are the operations that are currently in progress... */
2505 list<GQuark> curr = _current_trans_quarks;
2506 curr.sort ();
2508 /* ...and these are the operations during which we want to update
2509 the session range location markers.
2511 list<GQuark> ops;
2512 ops.push_back (Operations::capture);
2513 ops.push_back (Operations::paste);
2514 ops.push_back (Operations::duplicate_region);
2515 ops.push_back (Operations::insert_file);
2516 ops.push_back (Operations::insert_region);
2517 ops.push_back (Operations::drag_region_brush);
2518 ops.push_back (Operations::region_drag);
2519 ops.push_back (Operations::selection_grab);
2520 ops.push_back (Operations::region_fill);
2521 ops.push_back (Operations::fill_selection);
2522 ops.push_back (Operations::create_region);
2523 ops.sort ();
2525 /* See if any of the current operations match the ones that we want */
2526 list<GQuark> in;
2527 set_intersection (_current_trans_quarks.begin(), _current_trans_quarks.end(), ops.begin(), ops.end(), back_inserter (in));
2529 /* If so, update the session range markers */
2530 if (!in.empty ()) {
2531 maybe_update_session_range (r->position (), r->last_frame ());
2535 /** Update the session range markers if a is before the current start or
2536 * b is after the current end.
2538 void
2539 Session::maybe_update_session_range (framepos_t a, framepos_t b)
2541 if (_state_of_the_state & Loading) {
2542 return;
2545 if (_session_range_location == 0) {
2547 add_session_range_location (a, b);
2549 } else {
2551 if (a < _session_range_location->start()) {
2552 _session_range_location->set_start (a);
2555 if (b > _session_range_location->end()) {
2556 _session_range_location->set_end (b);
2561 void
2562 Session::playlist_ranges_moved (list<Evoral::RangeMove<framepos_t> > const & ranges)
2564 for (list<Evoral::RangeMove<framepos_t> >::const_iterator i = ranges.begin(); i != ranges.end(); ++i) {
2565 maybe_update_session_range (i->to, i->to + i->length);
2569 void
2570 Session::playlist_regions_extended (list<Evoral::Range<framepos_t> > const & ranges)
2572 for (list<Evoral::Range<framepos_t> >::const_iterator i = ranges.begin(); i != ranges.end(); ++i) {
2573 maybe_update_session_range (i->from, i->to);
2577 /* Region management */
2579 boost::shared_ptr<Region>
2580 Session::find_whole_file_parent (boost::shared_ptr<Region const> child) const
2582 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2583 RegionFactory::RegionMap::const_iterator i;
2584 boost::shared_ptr<Region> region;
2586 Glib::Mutex::Lock lm (region_lock);
2588 for (i = regions.begin(); i != regions.end(); ++i) {
2590 region = i->second;
2592 if (region->whole_file()) {
2594 if (child->source_equivalent (region)) {
2595 return region;
2600 return boost::shared_ptr<Region> ();
2604 Session::destroy_sources (list<boost::shared_ptr<Source> > srcs)
2606 set<boost::shared_ptr<Region> > relevant_regions;
2608 for (list<boost::shared_ptr<Source> >::iterator s = srcs.begin(); s != srcs.end(); ++s) {
2609 RegionFactory::get_regions_using_source (*s, relevant_regions);
2612 for (set<boost::shared_ptr<Region> >::iterator r = relevant_regions.begin(); r != relevant_regions.end(); ) {
2613 set<boost::shared_ptr<Region> >::iterator tmp;
2615 tmp = r;
2616 ++tmp;
2618 playlists->destroy_region (*r);
2619 RegionFactory::map_remove (*r);
2621 (*r)->drop_sources ();
2622 (*r)->drop_references ();
2624 relevant_regions.erase (r);
2626 r = tmp;
2629 for (list<boost::shared_ptr<Source> >::iterator s = srcs.begin(); s != srcs.end(); ) {
2632 Glib::Mutex::Lock ls (source_lock);
2633 /* remove from the main source list */
2634 sources.erase ((*s)->id());
2637 (*s)->mark_for_remove ();
2638 (*s)->drop_references ();
2640 s = srcs.erase (s);
2643 return 0;
2647 Session::remove_last_capture ()
2649 list<boost::shared_ptr<Source> > srcs;
2651 boost::shared_ptr<RouteList> rl = routes.reader ();
2652 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
2653 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
2654 if (!tr) {
2655 continue;
2658 list<boost::shared_ptr<Source> >& l = tr->last_capture_sources();
2660 if (!l.empty()) {
2661 srcs.insert (srcs.end(), l.begin(), l.end());
2662 l.clear ();
2666 destroy_sources (srcs);
2668 save_state (_current_snapshot_name);
2670 return 0;
2673 /* Source Management */
2675 void
2676 Session::add_source (boost::shared_ptr<Source> source)
2678 pair<SourceMap::key_type, SourceMap::mapped_type> entry;
2679 pair<SourceMap::iterator,bool> result;
2681 entry.first = source->id();
2682 entry.second = source;
2685 Glib::Mutex::Lock lm (source_lock);
2686 result = sources.insert (entry);
2689 if (result.second) {
2691 /* yay, new source */
2693 set_dirty();
2695 boost::shared_ptr<AudioFileSource> afs;
2697 if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(source)) != 0) {
2698 if (Config->get_auto_analyse_audio()) {
2699 Analyser::queue_source_for_analysis (source, false);
2703 source->DropReferences.connect_same_thread (*this, boost::bind (&Session::remove_source, this, boost::weak_ptr<Source> (source)));
2707 void
2708 Session::remove_source (boost::weak_ptr<Source> src)
2710 if (_state_of_the_state & Deletion) {
2711 return;
2714 SourceMap::iterator i;
2715 boost::shared_ptr<Source> source = src.lock();
2717 if (!source) {
2718 return;
2722 Glib::Mutex::Lock lm (source_lock);
2724 if ((i = sources.find (source->id())) != sources.end()) {
2725 sources.erase (i);
2729 if (!_state_of_the_state & InCleanup) {
2731 /* save state so we don't end up with a session file
2732 referring to non-existent sources.
2735 save_state (_current_snapshot_name);
2739 boost::shared_ptr<Source>
2740 Session::source_by_id (const PBD::ID& id)
2742 Glib::Mutex::Lock lm (source_lock);
2743 SourceMap::iterator i;
2744 boost::shared_ptr<Source> source;
2746 if ((i = sources.find (id)) != sources.end()) {
2747 source = i->second;
2750 return source;
2753 boost::shared_ptr<Source>
2754 Session::source_by_path_and_channel (const string& path, uint16_t chn)
2756 Glib::Mutex::Lock lm (source_lock);
2758 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2759 boost::shared_ptr<AudioFileSource> afs
2760 = boost::dynamic_pointer_cast<AudioFileSource>(i->second);
2762 if (afs && afs->path() == path && chn == afs->channel()) {
2763 return afs;
2766 return boost::shared_ptr<Source>();
2769 uint32_t
2770 Session::count_sources_by_origin (const string& path)
2772 uint32_t cnt = 0;
2773 Glib::Mutex::Lock lm (source_lock);
2775 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2776 boost::shared_ptr<FileSource> fs
2777 = boost::dynamic_pointer_cast<FileSource>(i->second);
2779 if (fs && fs->origin() == path) {
2780 ++cnt;
2784 return cnt;
2788 string
2789 Session::change_source_path_by_name (string path, string oldname, string newname, bool destructive)
2791 string look_for;
2792 string old_basename = PBD::basename_nosuffix (oldname);
2793 string new_legalized = legalize_for_path (newname);
2795 /* note: we know (or assume) the old path is already valid */
2797 if (destructive) {
2799 /* destructive file sources have a name of the form:
2801 /path/to/Tnnnn-NAME(%[LR])?.wav
2803 the task here is to replace NAME with the new name.
2806 string dir;
2807 string prefix;
2808 string::size_type dash;
2810 dir = Glib::path_get_dirname (path);
2811 path = Glib::path_get_basename (path);
2813 /* '-' is not a legal character for the NAME part of the path */
2815 if ((dash = path.find_last_of ('-')) == string::npos) {
2816 return "";
2819 prefix = path.substr (0, dash);
2821 path += prefix;
2822 path += '-';
2823 path += new_legalized;
2824 path += native_header_format_extension (config.get_native_file_header_format(), DataType::AUDIO);
2825 path = Glib::build_filename (dir, path);
2827 } else {
2829 /* non-destructive file sources have a name of the form:
2831 /path/to/NAME-nnnnn(%[LR])?.ext
2833 the task here is to replace NAME with the new name.
2836 string dir;
2837 string suffix;
2838 string::size_type dash;
2839 string::size_type postfix;
2841 dir = Glib::path_get_dirname (path);
2842 path = Glib::path_get_basename (path);
2844 /* '-' is not a legal character for the NAME part of the path */
2846 if ((dash = path.find_last_of ('-')) == string::npos) {
2847 return "";
2850 suffix = path.substr (dash+1);
2852 // Suffix is now everything after the dash. Now we need to eliminate
2853 // the nnnnn part, which is done by either finding a '%' or a '.'
2855 postfix = suffix.find_last_of ("%");
2856 if (postfix == string::npos) {
2857 postfix = suffix.find_last_of ('.');
2860 if (postfix != string::npos) {
2861 suffix = suffix.substr (postfix);
2862 } else {
2863 error << "Logic error in Session::change_source_path_by_name(), please report" << endl;
2864 return "";
2867 const uint32_t limit = 10000;
2868 char buf[PATH_MAX+1];
2870 for (uint32_t cnt = 1; cnt <= limit; ++cnt) {
2872 snprintf (buf, sizeof(buf), "%s-%u%s", newname.c_str(), cnt, suffix.c_str());
2874 if (!matching_unsuffixed_filename_exists_in (dir, buf)) {
2875 path = Glib::build_filename (dir, buf);
2876 break;
2879 path = "";
2882 if (path.empty()) {
2883 fatal << string_compose (_("FATAL ERROR! Could not find a suitable version of %1 for a rename"),
2884 newname) << endl;
2885 /*NOTREACHED*/
2889 return path;
2892 /** Return the full path (in some session directory) for a new within-session source.
2893 * \a name must be a session-unique name that does not contain slashes
2894 * (e.g. as returned by new_*_source_name)
2896 string
2897 Session::new_source_path_from_name (DataType type, const string& name)
2899 assert(name.find("/") == string::npos);
2901 SessionDirectory sdir(get_best_session_directory_for_new_source());
2903 sys::path p;
2904 if (type == DataType::AUDIO) {
2905 p = sdir.sound_path();
2906 } else if (type == DataType::MIDI) {
2907 p = sdir.midi_path();
2908 } else {
2909 error << "Unknown source type, unable to create file path" << endmsg;
2910 return "";
2913 p /= name;
2914 return p.to_string();
2917 string
2918 Session::peak_path (string base) const
2920 sys::path peakfile_path(_session_dir->peak_path());
2921 peakfile_path /= base + peakfile_suffix;
2922 return peakfile_path.to_string();
2925 /** Return a unique name based on \a base for a new internal audio source */
2926 string
2927 Session::new_audio_source_name (const string& base, uint32_t nchan, uint32_t chan, bool destructive)
2929 uint32_t cnt;
2930 char buf[PATH_MAX+1];
2931 const uint32_t limit = 10000;
2932 string legalized;
2933 string ext = native_header_format_extension (config.get_native_file_header_format(), DataType::AUDIO);
2935 buf[0] = '\0';
2936 legalized = legalize_for_path (base);
2938 // Find a "version" of the base name that doesn't exist in any of the possible directories.
2939 for (cnt = (destructive ? ++destructive_index : 1); cnt <= limit; ++cnt) {
2941 vector<space_and_path>::iterator i;
2942 uint32_t existing = 0;
2944 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2946 if (destructive) {
2948 if (nchan < 2) {
2949 snprintf (buf, sizeof(buf), "T%04d-%s%s",
2950 cnt, legalized.c_str(), ext.c_str());
2951 } else if (nchan == 2) {
2952 if (chan == 0) {
2953 snprintf (buf, sizeof(buf), "T%04d-%s%%L%s",
2954 cnt, legalized.c_str(), ext.c_str());
2955 } else {
2956 snprintf (buf, sizeof(buf), "T%04d-%s%%R%s",
2957 cnt, legalized.c_str(), ext.c_str());
2959 } else if (nchan < 26) {
2960 snprintf (buf, sizeof(buf), "T%04d-%s%%%c%s",
2961 cnt, legalized.c_str(), 'a' + chan, ext.c_str());
2962 } else {
2963 snprintf (buf, sizeof(buf), "T%04d-%s%s",
2964 cnt, legalized.c_str(), ext.c_str());
2967 } else {
2969 if (nchan < 2) {
2970 snprintf (buf, sizeof(buf), "%s-%u%s", legalized.c_str(), cnt, ext.c_str());
2971 } else if (nchan == 2) {
2972 if (chan == 0) {
2973 snprintf (buf, sizeof(buf), "%s-%u%%L%s", legalized.c_str(), cnt, ext.c_str());
2974 } else {
2975 snprintf (buf, sizeof(buf), "%s-%u%%R%s", legalized.c_str(), cnt, ext.c_str());
2977 } else if (nchan < 26) {
2978 snprintf (buf, sizeof(buf), "%s-%u%%%c%s", legalized.c_str(), cnt, 'a' + chan, ext.c_str());
2979 } else {
2980 snprintf (buf, sizeof(buf), "%s-%u%s", legalized.c_str(), cnt, ext.c_str());
2984 SessionDirectory sdir((*i).path);
2986 string spath = sdir.sound_path().to_string();
2988 /* note that we search *without* the extension so that
2989 we don't end up both "Audio 1-1.wav" and "Audio 1-1.caf"
2990 in the event that this new name is required for
2991 a file format change.
2994 if (matching_unsuffixed_filename_exists_in (spath, buf)) {
2995 existing++;
2996 break;
3000 if (existing == 0) {
3001 break;
3004 if (cnt > limit) {
3005 error << string_compose(
3006 _("There are already %1 recordings for %2, which I consider too many."),
3007 limit, base) << endmsg;
3008 destroy ();
3009 throw failed_constructor();
3013 return Glib::path_get_basename (buf);
3016 /** Create a new within-session audio source */
3017 boost::shared_ptr<AudioFileSource>
3018 Session::create_audio_source_for_session (size_t n_chans, string const & n, uint32_t chan, bool destructive)
3020 const string name = new_audio_source_name (n, n_chans, chan, destructive);
3021 const string path = new_source_path_from_name(DataType::AUDIO, name);
3023 return boost::dynamic_pointer_cast<AudioFileSource> (
3024 SourceFactory::createWritable (DataType::AUDIO, *this, path, string(), destructive, frame_rate()));
3027 /** Return a unique name based on \a base for a new internal MIDI source */
3028 string
3029 Session::new_midi_source_name (const string& base)
3031 uint32_t cnt;
3032 char buf[PATH_MAX+1];
3033 const uint32_t limit = 10000;
3034 string legalized;
3036 buf[0] = '\0';
3037 legalized = legalize_for_path (base);
3039 // Find a "version" of the file name that doesn't exist in any of the possible directories.
3040 for (cnt = 1; cnt <= limit; ++cnt) {
3042 vector<space_and_path>::iterator i;
3043 uint32_t existing = 0;
3045 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3047 SessionDirectory sdir((*i).path);
3049 sys::path p = sdir.midi_path();
3050 p /= legalized;
3052 snprintf (buf, sizeof(buf), "%s-%u.mid", p.to_string().c_str(), cnt);
3054 if (sys::exists (buf)) {
3055 existing++;
3059 if (existing == 0) {
3060 break;
3063 if (cnt > limit) {
3064 error << string_compose(
3065 _("There are already %1 recordings for %2, which I consider too many."),
3066 limit, base) << endmsg;
3067 destroy ();
3068 throw failed_constructor();
3072 return Glib::path_get_basename(buf);
3076 /** Create a new within-session MIDI source */
3077 boost::shared_ptr<MidiSource>
3078 Session::create_midi_source_for_session (Track* track, string const & n)
3080 /* try to use the existing write source for the track, to keep numbering sane
3083 if (track) {
3084 /*MidiTrack* mt = dynamic_cast<Track*> (track);
3085 assert (mt);
3088 list<boost::shared_ptr<Source> > l = track->steal_write_sources ();
3090 if (!l.empty()) {
3091 assert (boost::dynamic_pointer_cast<MidiSource> (l.front()));
3092 return boost::dynamic_pointer_cast<MidiSource> (l.front());
3096 const string name = new_midi_source_name (n);
3097 const string path = new_source_path_from_name (DataType::MIDI, name);
3099 return boost::dynamic_pointer_cast<SMFSource> (
3100 SourceFactory::createWritable (
3101 DataType::MIDI, *this, path, string(), false, frame_rate()));
3105 void
3106 Session::add_playlist (boost::shared_ptr<Playlist> playlist, bool unused)
3108 if (playlist->hidden()) {
3109 return;
3112 playlists->add (playlist);
3114 if (unused) {
3115 playlist->release();
3118 set_dirty();
3121 void
3122 Session::remove_playlist (boost::weak_ptr<Playlist> weak_playlist)
3124 if (_state_of_the_state & Deletion) {
3125 return;
3128 boost::shared_ptr<Playlist> playlist (weak_playlist.lock());
3130 if (!playlist) {
3131 return;
3134 playlists->remove (playlist);
3136 set_dirty();
3139 void
3140 Session::set_audition (boost::shared_ptr<Region> r)
3142 pending_audition_region = r;
3143 add_post_transport_work (PostTransportAudition);
3144 _butler->schedule_transport_work ();
3147 void
3148 Session::audition_playlist ()
3150 SessionEvent* ev = new SessionEvent (SessionEvent::Audition, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
3151 ev->region.reset ();
3152 queue_event (ev);
3155 void
3156 Session::non_realtime_set_audition ()
3158 if (!pending_audition_region) {
3159 auditioner->audition_current_playlist ();
3160 } else {
3161 auditioner->audition_region (pending_audition_region);
3162 pending_audition_region.reset ();
3164 AuditionActive (true); /* EMIT SIGNAL */
3167 void
3168 Session::audition_region (boost::shared_ptr<Region> r)
3170 SessionEvent* ev = new SessionEvent (SessionEvent::Audition, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
3171 ev->region = r;
3172 queue_event (ev);
3175 void
3176 Session::cancel_audition ()
3178 if (auditioner->auditioning()) {
3179 auditioner->cancel_audition ();
3180 AuditionActive (false); /* EMIT SIGNAL */
3184 bool
3185 Session::RoutePublicOrderSorter::operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b)
3187 if (a->is_monitor()) {
3188 return true;
3190 if (b->is_monitor()) {
3191 return false;
3193 return a->order_key(N_("signal")) < b->order_key(N_("signal"));
3196 bool
3197 Session::is_auditioning () const
3199 /* can be called before we have an auditioner object */
3200 if (auditioner) {
3201 return auditioner->auditioning();
3202 } else {
3203 return false;
3207 void
3208 Session::graph_reordered ()
3210 /* don't do this stuff if we are setting up connections
3211 from a set_state() call or creating new tracks. Ditto for deletion.
3214 if (_state_of_the_state & (InitialConnecting|Deletion)) {
3215 return;
3218 /* every track/bus asked for this to be handled but it was deferred because
3219 we were connecting. do it now.
3222 request_input_change_handling ();
3224 resort_routes ();
3226 /* force all diskstreams to update their capture offset values to
3227 reflect any changes in latencies within the graph.
3230 boost::shared_ptr<RouteList> rl = routes.reader ();
3231 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
3232 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
3233 if (tr) {
3234 tr->set_capture_offset ();
3239 framecnt_t
3240 Session::available_capture_duration ()
3242 float sample_bytes_on_disk = 4.0; // keep gcc happy
3244 switch (config.get_native_file_data_format()) {
3245 case FormatFloat:
3246 sample_bytes_on_disk = 4.0;
3247 break;
3249 case FormatInt24:
3250 sample_bytes_on_disk = 3.0;
3251 break;
3253 case FormatInt16:
3254 sample_bytes_on_disk = 2.0;
3255 break;
3257 default:
3258 /* impossible, but keep some gcc versions happy */
3259 fatal << string_compose (_("programming error: %1"),
3260 X_("illegal native file data format"))
3261 << endmsg;
3262 /*NOTREACHED*/
3265 double scale = 4096.0 / sample_bytes_on_disk;
3267 if (_total_free_4k_blocks * scale > (double) max_framecnt) {
3268 return max_framecnt;
3271 return (framecnt_t) floor (_total_free_4k_blocks * scale);
3274 void
3275 Session::add_bundle (boost::shared_ptr<Bundle> bundle)
3278 RCUWriter<BundleList> writer (_bundles);
3279 boost::shared_ptr<BundleList> b = writer.get_copy ();
3280 b->push_back (bundle);
3283 BundleAdded (bundle); /* EMIT SIGNAL */
3285 set_dirty();
3288 void
3289 Session::remove_bundle (boost::shared_ptr<Bundle> bundle)
3291 bool removed = false;
3294 RCUWriter<BundleList> writer (_bundles);
3295 boost::shared_ptr<BundleList> b = writer.get_copy ();
3296 BundleList::iterator i = find (b->begin(), b->end(), bundle);
3298 if (i != b->end()) {
3299 b->erase (i);
3300 removed = true;
3304 if (removed) {
3305 BundleRemoved (bundle); /* EMIT SIGNAL */
3308 set_dirty();
3311 boost::shared_ptr<Bundle>
3312 Session::bundle_by_name (string name) const
3314 boost::shared_ptr<BundleList> b = _bundles.reader ();
3316 for (BundleList::const_iterator i = b->begin(); i != b->end(); ++i) {
3317 if ((*i)->name() == name) {
3318 return* i;
3322 return boost::shared_ptr<Bundle> ();
3325 void
3326 Session::tempo_map_changed (const PropertyChange&)
3328 clear_clicks ();
3330 playlists->update_after_tempo_map_change ();
3332 _locations->apply (*this, &Session::update_locations_after_tempo_map_change);
3334 set_dirty ();
3337 void
3338 Session::update_locations_after_tempo_map_change (Locations::LocationList& loc)
3340 for (Locations::LocationList::iterator i = loc.begin(); i != loc.end(); ++i) {
3341 (*i)->recompute_frames_from_bbt ();
3345 /** Ensures that all buffers (scratch, send, silent, etc) are allocated for
3346 * the given count with the current block size.
3348 void
3349 Session::ensure_buffers (ChanCount howmany)
3351 BufferManager::ensure_buffers (howmany);
3354 void
3355 Session::ensure_buffer_set(BufferSet& buffers, const ChanCount& count)
3357 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
3358 buffers.ensure_buffers(*t, count.get(*t), _engine.raw_buffer_size(*t));
3362 uint32_t
3363 Session::next_insert_id ()
3365 /* this doesn't really loop forever. just think about it */
3367 while (true) {
3368 for (boost::dynamic_bitset<uint32_t>::size_type n = 0; n < insert_bitset.size(); ++n) {
3369 if (!insert_bitset[n]) {
3370 insert_bitset[n] = true;
3371 return n;
3376 /* none available, so resize and try again */
3378 insert_bitset.resize (insert_bitset.size() + 16, false);
3382 uint32_t
3383 Session::next_send_id ()
3385 /* this doesn't really loop forever. just think about it */
3387 while (true) {
3388 for (boost::dynamic_bitset<uint32_t>::size_type n = 0; n < send_bitset.size(); ++n) {
3389 if (!send_bitset[n]) {
3390 send_bitset[n] = true;
3391 return n;
3396 /* none available, so resize and try again */
3398 send_bitset.resize (send_bitset.size() + 16, false);
3402 uint32_t
3403 Session::next_return_id ()
3405 /* this doesn't really loop forever. just think about it */
3407 while (true) {
3408 for (boost::dynamic_bitset<uint32_t>::size_type n = 0; n < return_bitset.size(); ++n) {
3409 if (!return_bitset[n]) {
3410 return_bitset[n] = true;
3411 return n;
3416 /* none available, so resize and try again */
3418 return_bitset.resize (return_bitset.size() + 16, false);
3422 void
3423 Session::mark_send_id (uint32_t id)
3425 if (id >= send_bitset.size()) {
3426 send_bitset.resize (id+16, false);
3428 if (send_bitset[id]) {
3429 warning << string_compose (_("send ID %1 appears to be in use already"), id) << endmsg;
3431 send_bitset[id] = true;
3434 void
3435 Session::mark_return_id (uint32_t id)
3437 if (id >= return_bitset.size()) {
3438 return_bitset.resize (id+16, false);
3440 if (return_bitset[id]) {
3441 warning << string_compose (_("return ID %1 appears to be in use already"), id) << endmsg;
3443 return_bitset[id] = true;
3446 void
3447 Session::mark_insert_id (uint32_t id)
3449 if (id >= insert_bitset.size()) {
3450 insert_bitset.resize (id+16, false);
3452 if (insert_bitset[id]) {
3453 warning << string_compose (_("insert ID %1 appears to be in use already"), id) << endmsg;
3455 insert_bitset[id] = true;
3458 void
3459 Session::unmark_send_id (uint32_t id)
3461 if (id < send_bitset.size()) {
3462 send_bitset[id] = false;
3466 void
3467 Session::unmark_return_id (uint32_t id)
3469 if (id < return_bitset.size()) {
3470 return_bitset[id] = false;
3474 void
3475 Session::unmark_insert_id (uint32_t id)
3477 if (id < insert_bitset.size()) {
3478 insert_bitset[id] = false;
3483 /* Named Selection management */
3485 boost::shared_ptr<NamedSelection>
3486 Session::named_selection_by_name (string name)
3488 Glib::Mutex::Lock lm (named_selection_lock);
3489 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
3490 if ((*i)->name == name) {
3491 return *i;
3494 return boost::shared_ptr<NamedSelection>();
3497 void
3498 Session::add_named_selection (boost::shared_ptr<NamedSelection> named_selection)
3501 Glib::Mutex::Lock lm (named_selection_lock);
3502 named_selections.insert (named_selections.begin(), named_selection);
3505 set_dirty();
3507 NamedSelectionAdded (); /* EMIT SIGNAL */
3510 void
3511 Session::remove_named_selection (boost::shared_ptr<NamedSelection> named_selection)
3513 bool removed = false;
3516 Glib::Mutex::Lock lm (named_selection_lock);
3518 NamedSelectionList::iterator i = find (named_selections.begin(), named_selections.end(), named_selection);
3520 if (i != named_selections.end()) {
3521 named_selections.erase (i);
3522 set_dirty();
3523 removed = true;
3527 if (removed) {
3528 NamedSelectionRemoved (); /* EMIT SIGNAL */
3532 void
3533 Session::reset_native_file_format ()
3535 boost::shared_ptr<RouteList> rl = routes.reader ();
3536 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
3537 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
3538 if (tr) {
3539 /* don't save state as we do this, there's no point
3542 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
3543 tr->reset_write_sources (false);
3544 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
3549 bool
3550 Session::route_name_unique (string n) const
3552 boost::shared_ptr<RouteList> r = routes.reader ();
3554 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
3555 if ((*i)->name() == n) {
3556 return false;
3560 return true;
3563 bool
3564 Session::route_name_internal (string n) const
3566 if (auditioner && auditioner->name() == n) {
3567 return true;
3570 if (_click_io && _click_io->name() == n) {
3571 return true;
3574 return false;
3578 Session::freeze_all (InterThreadInfo& itt)
3580 boost::shared_ptr<RouteList> r = routes.reader ();
3582 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
3584 boost::shared_ptr<Track> t;
3586 if ((t = boost::dynamic_pointer_cast<Track>(*i)) != 0) {
3587 /* XXX this is wrong because itt.progress will keep returning to zero at the start
3588 of every track.
3590 t->freeze_me (itt);
3594 return 0;
3597 boost::shared_ptr<Region>
3598 Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end,
3599 bool /*overwrite*/, vector<boost::shared_ptr<Source> >& srcs,
3600 InterThreadInfo& itt, bool enable_processing)
3602 boost::shared_ptr<Region> result;
3603 boost::shared_ptr<Playlist> playlist;
3604 boost::shared_ptr<AudioFileSource> fsource;
3605 uint32_t x;
3606 char buf[PATH_MAX+1];
3607 ChanCount diskstream_channels (track.n_channels());
3608 framepos_t position;
3609 framecnt_t this_chunk;
3610 framepos_t to_do;
3611 BufferSet buffers;
3612 SessionDirectory sdir(get_best_session_directory_for_new_source ());
3613 const string sound_dir = sdir.sound_path().to_string();
3614 framepos_t len = end - start;
3615 bool need_block_size_reset = false;
3616 string ext;
3617 ChanCount const max_proc = track.max_processor_streams ();
3619 if (end <= start) {
3620 error << string_compose (_("Cannot write a range where end <= start (e.g. %1 <= %2)"),
3621 end, start) << endmsg;
3622 return result;
3625 const framecnt_t chunk_size = (256 * 1024)/4;
3627 // block all process callback handling
3629 block_processing ();
3631 /* call tree *MUST* hold route_lock */
3633 if ((playlist = track.playlist()) == 0) {
3634 goto out;
3637 /* external redirects will be a problem */
3639 if (track.has_external_redirects()) {
3640 goto out;
3643 ext = native_header_format_extension (config.get_native_file_header_format(), DataType::AUDIO);
3645 for (uint32_t chan_n = 0; chan_n < diskstream_channels.n_audio(); ++chan_n) {
3647 for (x = 0; x < 99999; ++x) {
3648 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());
3649 if (!Glib::file_test (buf, Glib::FILE_TEST_EXISTS)) {
3650 break;
3654 if (x == 99999) {
3655 error << string_compose (_("too many bounced versions of playlist \"%1\""), playlist->name()) << endmsg;
3656 goto out;
3659 try {
3660 fsource = boost::dynamic_pointer_cast<AudioFileSource> (
3661 SourceFactory::createWritable (DataType::AUDIO, *this, buf, string(), false, frame_rate()));
3664 catch (failed_constructor& err) {
3665 error << string_compose (_("cannot create new audio file \"%1\" for %2"), buf, track.name()) << endmsg;
3666 goto out;
3669 srcs.push_back (fsource);
3672 /* tell redirects that care that we are about to use a much larger blocksize */
3674 need_block_size_reset = true;
3675 track.set_block_size (chunk_size);
3677 /* XXX need to flush all redirects */
3679 position = start;
3680 to_do = len;
3682 /* create a set of reasonably-sized buffers */
3683 buffers.ensure_buffers (DataType::AUDIO, max_proc.n_audio(), chunk_size);
3684 buffers.set_count (max_proc);
3686 for (vector<boost::shared_ptr<Source> >::iterator src = srcs.begin(); src != srcs.end(); ++src) {
3687 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
3688 if (afs)
3689 afs->prepare_for_peakfile_writes ();
3692 while (to_do && !itt.cancel) {
3694 this_chunk = min (to_do, chunk_size);
3696 if (track.export_stuff (buffers, start, this_chunk, enable_processing)) {
3697 goto out;
3700 uint32_t n = 0;
3701 for (vector<boost::shared_ptr<Source> >::iterator src=srcs.begin(); src != srcs.end(); ++src, ++n) {
3702 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
3704 if (afs) {
3705 if (afs->write (buffers.get_audio(n).data(), this_chunk) != this_chunk) {
3706 goto out;
3711 start += this_chunk;
3712 to_do -= this_chunk;
3714 itt.progress = (float) (1.0 - ((double) to_do / len));
3718 if (!itt.cancel) {
3720 time_t now;
3721 struct tm* xnow;
3722 time (&now);
3723 xnow = localtime (&now);
3725 for (vector<boost::shared_ptr<Source> >::iterator src=srcs.begin(); src != srcs.end(); ++src) {
3726 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
3728 if (afs) {
3729 afs->update_header (position, *xnow, now);
3730 afs->flush_header ();
3734 /* construct a region to represent the bounced material */
3736 PropertyList plist;
3738 plist.add (Properties::start, 0);
3739 plist.add (Properties::length, srcs.front()->length(srcs.front()->timeline_position()));
3740 plist.add (Properties::name, region_name_from_path (srcs.front()->name(), true));
3742 result = RegionFactory::create (srcs, plist);
3746 out:
3747 if (!result) {
3748 for (vector<boost::shared_ptr<Source> >::iterator src = srcs.begin(); src != srcs.end(); ++src) {
3749 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
3751 if (afs) {
3752 afs->mark_for_remove ();
3755 (*src)->drop_references ();
3758 } else {
3759 for (vector<boost::shared_ptr<Source> >::iterator src = srcs.begin(); src != srcs.end(); ++src) {
3760 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
3762 if (afs)
3763 afs->done_with_peakfile_writes ();
3768 if (need_block_size_reset) {
3769 track.set_block_size (get_block_size());
3772 unblock_processing ();
3774 return result;
3777 gain_t*
3778 Session::gain_automation_buffer() const
3780 return ProcessThread::gain_automation_buffer ();
3783 pan_t**
3784 Session::pan_automation_buffer() const
3786 return ProcessThread::pan_automation_buffer ();
3789 BufferSet&
3790 Session::get_silent_buffers (ChanCount count)
3792 return ProcessThread::get_silent_buffers (count);
3795 BufferSet&
3796 Session::get_scratch_buffers (ChanCount count)
3798 return ProcessThread::get_scratch_buffers (count);
3801 BufferSet&
3802 Session::get_mix_buffers (ChanCount count)
3804 return ProcessThread::get_mix_buffers (count);
3807 uint32_t
3808 Session::ntracks () const
3810 uint32_t n = 0;
3811 boost::shared_ptr<RouteList> r = routes.reader ();
3813 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
3814 if (boost::dynamic_pointer_cast<Track> (*i)) {
3815 ++n;
3819 return n;
3822 uint32_t
3823 Session::nbusses () const
3825 uint32_t n = 0;
3826 boost::shared_ptr<RouteList> r = routes.reader ();
3828 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
3829 if (boost::dynamic_pointer_cast<Track>(*i) == 0) {
3830 ++n;
3834 return n;
3837 void
3838 Session::add_automation_list(AutomationList *al)
3840 automation_lists[al->id()] = al;
3843 void
3844 Session::sync_order_keys (std::string const & base)
3846 if (deletion_in_progress()) {
3847 return;
3850 if (!Config->get_sync_all_route_ordering()) {
3851 /* leave order keys as they are */
3852 return;
3855 boost::shared_ptr<RouteList> r = routes.reader ();
3857 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
3858 (*i)->sync_order_keys (base);
3861 Route::SyncOrderKeys (base); // EMIT SIGNAL
3863 /* this might not do anything */
3865 set_remote_control_ids ();
3868 /** @return true if there is at least one record-enabled track, otherwise false */
3869 bool
3870 Session::have_rec_enabled_track () const
3872 return g_atomic_int_get (&_have_rec_enabled_track) == 1;
3875 /** Update the state of our rec-enabled tracks flag */
3876 void
3877 Session::update_have_rec_enabled_track ()
3879 boost::shared_ptr<RouteList> rl = routes.reader ();
3880 RouteList::iterator i = rl->begin();
3881 while (i != rl->end ()) {
3883 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
3884 if (tr && tr->record_enabled ()) {
3885 break;
3888 ++i;
3891 int const old = g_atomic_int_get (&_have_rec_enabled_track);
3893 g_atomic_int_set (&_have_rec_enabled_track, i != rl->end () ? 1 : 0);
3895 if (g_atomic_int_get (&_have_rec_enabled_track) != old) {
3896 RecordStateChanged (); /* EMIT SIGNAL */
3900 void
3901 Session::listen_position_changed ()
3903 boost::shared_ptr<RouteList> r = routes.reader ();
3905 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
3906 (*i)->listen_position_changed ();
3910 void
3911 Session::solo_control_mode_changed ()
3913 /* cancel all solo or all listen when solo control mode changes */
3915 if (soloing()) {
3916 set_solo (get_routes(), false);
3917 } else if (listening()) {
3918 set_listen (get_routes(), false);
3922 /** Called when anything about any of our route groups changes (membership, state etc.) */
3923 void
3924 Session::route_group_changed ()
3926 RouteGroupChanged (); /* EMIT SIGNAL */
3929 vector<SyncSource>
3930 Session::get_available_sync_options () const
3932 vector<SyncSource> ret;
3934 ret.push_back (JACK);
3935 ret.push_back (MTC);
3936 ret.push_back (MIDIClock);
3938 return ret;
3941 boost::shared_ptr<RouteList>
3942 Session::get_routes_with_regions_at (framepos_t const p) const
3944 boost::shared_ptr<RouteList> r = routes.reader ();
3945 boost::shared_ptr<RouteList> rl (new RouteList);
3947 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
3948 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
3949 if (!tr) {
3950 continue;
3953 boost::shared_ptr<Playlist> pl = tr->playlist ();
3954 if (!pl) {
3955 continue;
3958 if (pl->has_region_at (p)) {
3959 rl->push_back (*i);
3963 return rl;
3966 void
3967 Session::goto_end ()
3969 if (_session_range_location) {
3970 request_locate (_session_range_location->end(), false);
3971 } else {
3972 request_locate (0, false);
3976 void
3977 Session::goto_start ()
3979 if (_session_range_location) {
3980 request_locate (_session_range_location->start(), false);
3981 } else {
3982 request_locate (0, false);
3986 framepos_t
3987 Session::current_start_frame () const
3989 return _session_range_location ? _session_range_location->start() : 0;
3992 framepos_t
3993 Session::current_end_frame () const
3995 return _session_range_location ? _session_range_location->end() : 0;
3998 void
3999 Session::add_session_range_location (framepos_t start, framepos_t end)
4001 _session_range_location = new Location (*this, start, end, _("session"), Location::IsSessionRange);
4002 _locations->add (_session_range_location);
4005 /** Called when one of our routes' order keys has changed */
4006 void
4007 Session::route_order_key_changed ()
4009 RouteOrderKeyChanged (); /* EMIT SIGNAL */
4012 void
4013 Session::step_edit_status_change (bool yn)
4015 bool send = false;
4017 bool val = false;
4018 if (yn) {
4019 send = (_step_editors == 0);
4020 val = true;
4022 _step_editors++;
4023 } else {
4024 send = (_step_editors == 1);
4025 val = false;
4027 if (_step_editors > 0) {
4028 _step_editors--;
4032 if (send) {
4033 StepEditStatusChange (val);
4038 void
4039 Session::start_time_changed (framepos_t old)
4041 /* Update the auto loop range to match the session range
4042 (unless the auto loop range has been changed by the user)
4045 Location* s = _locations->session_range_location ();
4046 if (s == 0) {
4047 return;
4050 Location* l = _locations->auto_loop_location ();
4052 if (l->start() == old) {
4053 l->set_start (s->start(), true);
4057 void
4058 Session::end_time_changed (framepos_t old)
4060 /* Update the auto loop range to match the session range
4061 (unless the auto loop range has been changed by the user)
4064 Location* s = _locations->session_range_location ();
4065 if (s == 0) {
4066 return;
4069 Location* l = _locations->auto_loop_location ();
4071 if (l->end() == old) {
4072 l->set_end (s->end(), true);
4076 string
4077 Session::source_search_path (DataType type) const
4079 string search_path;
4081 if (session_dirs.size() == 1) {
4082 switch (type) {
4083 case DataType::AUDIO:
4084 search_path = _session_dir->sound_path().to_string();
4085 break;
4086 case DataType::MIDI:
4087 search_path = _session_dir->midi_path().to_string();
4088 break;
4090 } else {
4091 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4092 SessionDirectory sdir (i->path);
4093 if (!search_path.empty()) {
4094 search_path += ':';
4096 switch (type) {
4097 case DataType::AUDIO:
4098 search_path += sdir.sound_path().to_string();
4099 break;
4100 case DataType::MIDI:
4101 search_path += sdir.midi_path().to_string();
4102 break;
4107 /* now add user-specified locations
4110 vector<string> dirs;
4112 switch (type) {
4113 case DataType::AUDIO:
4114 split (config.get_audio_search_path (), dirs, ':');
4115 break;
4116 case DataType::MIDI:
4117 split (config.get_midi_search_path (), dirs, ':');
4118 break;
4121 for (vector<string>::iterator i = dirs.begin(); i != dirs.end(); ++i) {
4122 search_path += ':';
4123 search_path += *i;
4127 return search_path;
4130 void
4131 Session::ensure_search_path_includes (const string& path, DataType type)
4133 string search_path;
4134 vector<string> dirs;
4136 if (path == ".") {
4137 return;
4140 switch (type) {
4141 case DataType::AUDIO:
4142 search_path = config.get_audio_search_path ();
4143 break;
4144 case DataType::MIDI:
4145 search_path = config.get_midi_search_path ();
4146 break;
4149 split (search_path, dirs, ':');
4151 for (vector<string>::iterator i = dirs.begin(); i != dirs.end(); ++i) {
4152 if (*i == path) {
4153 return;
4157 if (!search_path.empty()) {
4158 search_path += ':';
4161 search_path += path;
4163 switch (type) {
4164 case DataType::AUDIO:
4165 config.set_audio_search_path (search_path);
4166 break;
4167 case DataType::MIDI:
4168 config.set_midi_search_path (search_path);
4169 break;
4173 boost::shared_ptr<Speakers>
4174 Session::get_speakers()
4176 return _speakers;
4179 list<string>
4180 Session::unknown_processors () const
4182 list<string> p;
4184 boost::shared_ptr<RouteList> r = routes.reader ();
4185 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
4186 list<string> t = (*i)->unknown_processors ();
4187 copy (t.begin(), t.end(), back_inserter (p));
4190 p.sort ();
4191 p.unique ();
4193 return p;
4196 void
4197 Session::update_latency (bool playback)
4199 DEBUG_TRACE (DEBUG::Latency, string_compose ("JACK latency callback: %1\n", (playback ? "PLAYBACK" : "CAPTURE")));
4201 if (_state_of_the_state & (InitialConnecting|Deletion)) {
4202 return;
4205 boost::shared_ptr<RouteList> r = routes.reader ();
4206 framecnt_t max_latency = 0;
4208 if (playback) {
4209 /* reverse the list so that we work backwards from the last route to run to the first */
4210 reverse (r->begin(), r->end());
4213 /* compute actual latency values for the given direction and store them all in per-port
4214 structures. this will also publish the same values (to JACK) so that computation of latency
4215 for routes can consistently use public latency values.
4218 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
4219 max_latency = max (max_latency, (*i)->set_private_port_latencies (playback));
4222 /* because we latency compensate playback, our published playback latencies should
4223 be the same for all output ports - all material played back by ardour has
4224 the same latency, whether its caused by plugins or by latency compensation. since
4225 these may differ from the values computed above, reset all playback port latencies
4226 to the same value.
4229 DEBUG_TRACE (DEBUG::Latency, string_compose ("Set public port latencies to %1\n", max_latency));
4231 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
4232 (*i)->set_public_port_latencies (max_latency, playback);
4235 if (playback) {
4237 post_playback_latency ();
4239 } else {
4241 post_capture_latency ();
4244 DEBUG_TRACE (DEBUG::Latency, "JACK latency callback: DONE\n");
4247 void
4248 Session::post_playback_latency ()
4250 set_worst_playback_latency ();
4252 boost::shared_ptr<RouteList> r = routes.reader ();
4253 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
4254 if (!(*i)->is_hidden() && ((*i)->active())) {
4255 _worst_track_latency = max (_worst_track_latency, (*i)->update_signal_latency ());
4258 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
4259 (*i)->set_latency_compensation (_worst_track_latency);
4264 void
4265 Session::post_capture_latency ()
4267 set_worst_capture_latency ();
4269 /* reflect any changes in capture latencies into capture offsets
4272 boost::shared_ptr<RouteList> rl = routes.reader();
4273 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
4274 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
4275 if (tr) {
4276 tr->set_capture_offset ();
4281 void
4282 Session::set_worst_io_latencies ()
4284 set_worst_playback_latency ();
4285 set_worst_capture_latency ();
4288 void
4289 Session::set_worst_playback_latency ()
4291 if (_state_of_the_state & (InitialConnecting|Deletion)) {
4292 return;
4295 _worst_output_latency = 0;
4297 if (!_engine.connected()) {
4298 return;
4301 boost::shared_ptr<RouteList> r = routes.reader ();
4303 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
4304 _worst_output_latency = max (_worst_output_latency, (*i)->output()->latency());
4307 DEBUG_TRACE (DEBUG::Latency, string_compose ("Worst output latency: %1\n", _worst_output_latency));
4310 void
4311 Session::set_worst_capture_latency ()
4313 if (_state_of_the_state & (InitialConnecting|Deletion)) {
4314 return;
4317 _worst_input_latency = 0;
4319 if (!_engine.connected()) {
4320 return;
4323 boost::shared_ptr<RouteList> r = routes.reader ();
4325 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
4326 _worst_input_latency = max (_worst_input_latency, (*i)->input()->latency());
4329 DEBUG_TRACE (DEBUG::Latency, string_compose ("Worst input latency: %1\n", _worst_input_latency));
4332 void
4333 Session::update_latency_compensation (bool force_whole_graph)
4335 bool some_track_latency_changed = false;
4337 if (_state_of_the_state & (InitialConnecting|Deletion)) {
4338 return;
4341 DEBUG_TRACE(DEBUG::Latency, "---------------------------- update latency compensation\n\n");
4343 _worst_track_latency = 0;
4345 boost::shared_ptr<RouteList> r = routes.reader ();
4347 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
4348 if (!(*i)->is_hidden() && ((*i)->active())) {
4349 framecnt_t tl;
4350 if ((*i)->signal_latency () != (tl = (*i)->update_signal_latency ())) {
4351 some_track_latency_changed = true;
4353 _worst_track_latency = max (tl, _worst_track_latency);
4357 DEBUG_TRACE (DEBUG::Latency, string_compose ("worst signal processing latency: %1 (changed ? %2)\n", _worst_track_latency,
4358 (some_track_latency_changed ? "yes" : "no")));
4360 if (force_whole_graph || some_track_latency_changed) {
4361 /* trigger a full recompute of latency numbers for the graph.
4362 everything else that we need to do will be done in the latency
4363 callback.
4365 _engine.update_total_latencies ();
4366 return; // everything else will be done in the latency callback
4369 DEBUG_TRACE(DEBUG::Latency, "---------------------------- DONE update latency compensation\n\n")