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 #define __STDC_LIMIT_MACROS
28 #include <cstdio> /* sprintf(3) ... grrr */
34 #include <glibmm/thread.h>
35 #include <glibmm/miscutils.h>
36 #include <glibmm/fileutils.h>
38 #include <boost/algorithm/string/erase.hpp>
40 #include "pbd/error.h"
41 #include "pbd/boost_debug.h"
42 #include "pbd/pathscanner.h"
43 #include "pbd/stl_delete.h"
44 #include "pbd/basename.h"
45 #include "pbd/stacktrace.h"
46 #include "pbd/file_utils.h"
47 #include "pbd/convert.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"
103 #include "midi++/port.h"
104 #include "midi++/mmc.h"
105 #include "midi++/manager.h"
110 using namespace ARDOUR;
112 using boost::shared_ptr;
113 using boost::weak_ptr;
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,nframes_t,nframes_t> Session::AskAboutSampleRateMismatch;
120 PBD::Signal0<void> Session::SendFeedback;
122 PBD::Signal0<void> Session::TimecodeOffsetChanged;
123 PBD::Signal0<void> Session::StartTimeChanged;
124 PBD::Signal0<void> 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;
130 static void clean_up_session_event (SessionEvent* ev) { delete ev; }
131 const SessionEvent::RTeventCallback Session::rt_cleanup (clean_up_session_event);
133 Session::Session (AudioEngine &eng,
134 const string& fullpath,
135 const string& snapshot_name,
136 BusProfile* bus_profile,
140 _target_transport_speed (0.0),
141 _requested_return_frame (-1),
142 _session_dir (new SessionDirectory(fullpath)),
144 _butler (new Butler (*this)),
145 _post_transport_work (0),
146 _send_timecode_update (false),
147 route_graph (new Graph(*this)),
148 routes (new RouteList),
149 _total_free_4k_blocks (0),
150 _bundles (new BundleList),
151 _bundle_xml_node (0),
154 click_emphasis_data (0),
156 _metadata (new SessionMetadata()),
157 _have_rec_enabled_track (false),
158 _suspend_timecode_transmission (0)
160 _locations = new Locations (*this);
162 playlists.reset (new SessionPlaylists);
164 interpolation.add_channel_to (0, 0);
166 if (!eng.connected()) {
167 throw failed_constructor();
170 n_physical_outputs = _engine.n_physical_outputs ();
171 n_physical_inputs = _engine.n_physical_inputs ();
173 first_stage_init (fullpath, snapshot_name);
175 _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
178 if (create (mix_template, bus_profile)) {
180 throw failed_constructor ();
184 if (second_stage_init ()) {
186 throw failed_constructor ();
189 store_recent_sessions(_name, _path);
191 bool was_dirty = dirty();
193 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
195 Config->ParameterChanged.connect_same_thread (*this, boost::bind (&Session::config_changed, this, _1, false));
196 config.ParameterChanged.connect_same_thread (*this, boost::bind (&Session::config_changed, this, _1, true));
199 DirtyChanged (); /* EMIT SIGNAL */
213 vector<void*> debug_pointers;
215 /* if we got to here, leaving pending capture state around
219 remove_pending_capture_state ();
221 _state_of_the_state = StateOfTheState (CannotSave|Deletion);
223 _engine.remove_session ();
225 /* clear history so that no references to objects are held any more */
229 /* clear state tree so that no references to objects are held any more */
233 /* remove all stubfiles that might still be lurking */
235 cleanup_stubfiles ();
237 /* reset dynamic state version back to default */
239 Stateful::loading_state_version = 0;
241 _butler->drop_references ();
243 delete midi_control_ui;
245 if (click_data != default_click) {
246 delete [] click_data;
249 if (click_emphasis_data != default_click_emphasis) {
250 delete [] click_emphasis_data;
255 /* clear out any pending dead wood from RCU managed objects */
260 AudioDiskstream::free_working_buffers();
262 /* tell everyone who is still standing that we're about to die */
265 /* tell everyone to drop references and delete objects as we go */
267 DEBUG_TRACE (DEBUG::Destruction, "delete named selections\n");
268 named_selections.clear ();
270 DEBUG_TRACE (DEBUG::Destruction, "delete regions\n");
271 RegionFactory::delete_all_regions ();
273 DEBUG_TRACE (DEBUG::Destruction, "delete routes\n");
275 /* reset these three references to special routes before we do the usual route delete thing */
278 _master_out.reset ();
279 _monitor_out.reset ();
282 RCUWriter<RouteList> writer (routes);
283 boost::shared_ptr<RouteList> r = writer.get_copy ();
285 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
286 DEBUG_TRACE(DEBUG::Destruction, string_compose ("Dropping for route %1 ; pre-ref = %2\n", (*i)->name(), (*i).use_count()));
287 (*i)->drop_references ();
291 /* writer goes out of scope and updates master */
295 boost::shared_ptr<RouteList> r = routes.reader ();
297 DEBUG_TRACE (DEBUG::Destruction, "delete sources\n");
298 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
299 DEBUG_TRACE(DEBUG::Destruction, string_compose ("Dropping for source %1 ; pre-ref = %2\n", i->second->path(), i->second.use_count()));
300 i->second->drop_references ();
305 DEBUG_TRACE (DEBUG::Destruction, "delete route groups\n");
306 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
311 Crossfade::set_buffer_size (0);
313 /* not strictly necessary, but doing it here allows the shared_ptr debugging to work */
316 boost_debug_list_ptrs ();
320 DEBUG_TRACE (DEBUG::Destruction, "Session::destroy() done\n");
324 Session::set_worst_io_latencies ()
326 _worst_output_latency = 0;
327 _worst_input_latency = 0;
329 if (!_engine.connected()) {
333 boost::shared_ptr<RouteList> r = routes.reader ();
335 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
336 _worst_output_latency = max (_worst_output_latency, (*i)->output()->latency());
337 _worst_input_latency = max (_worst_input_latency, (*i)->input()->latency());
342 Session::when_engine_running ()
344 string first_physical_output;
346 BootMessage (_("Set block size and sample rate"));
348 set_block_size (_engine.frames_per_cycle());
349 set_frame_rate (_engine.frame_rate());
351 BootMessage (_("Using configuration"));
353 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
354 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
356 Config->map_parameters (ff);
357 config.map_parameters (ft);
359 /* every time we reconnect, recompute worst case output latencies */
361 _engine.Running.connect_same_thread (*this, boost::bind (&Session::set_worst_io_latencies, this));
363 if (synced_to_jack()) {
364 _engine.transport_stop ();
367 if (config.get_jack_time_master()) {
368 _engine.transport_locate (_transport_frame);
376 _click_io.reset (new ClickIO (*this, "click"));
378 if (state_tree && (child = find_named_node (*state_tree->root(), "Click")) != 0) {
380 /* existing state for Click */
383 if (Stateful::loading_state_version < 3000) {
384 c = _click_io->set_state_2X (*child->children().front(), Stateful::loading_state_version, false);
386 c = _click_io->set_state (*child->children().front(), Stateful::loading_state_version);
391 _clicking = Config->get_clicking ();
395 error << _("could not setup Click I/O") << endmsg;
402 /* default state for Click: dual-mono to first 2 physical outputs */
405 _engine.get_physical_outputs (DataType::AUDIO, outs);
407 for (uint32_t physport = 0; physport < 2; ++physport) {
408 if (outs.size() > physport) {
409 if (_click_io->add_port (outs[physport], this)) {
410 // relax, even though its an error
415 if (_click_io->n_ports () > ChanCount::ZERO) {
416 _clicking = Config->get_clicking ();
421 catch (failed_constructor& err) {
422 error << _("cannot setup Click I/O") << endmsg;
425 BootMessage (_("Compute I/O Latencies"));
427 set_worst_io_latencies ();
430 // XXX HOW TO ALERT UI TO THIS ? DO WE NEED TO?
433 BootMessage (_("Set up standard connections"));
435 vector<string> inputs[DataType::num_types];
436 vector<string> outputs[DataType::num_types];
437 for (uint32_t i = 0; i < DataType::num_types; ++i) {
438 _engine.get_physical_inputs (DataType (DataType::Symbol (i)), inputs[i]);
439 _engine.get_physical_outputs (DataType (DataType::Symbol (i)), outputs[i]);
442 /* Create a set of Bundle objects that map
443 to the physical I/O currently available. We create both
444 mono and stereo bundles, so that the common cases of mono
445 and stereo tracks get bundles to put in their mixer strip
446 in / out menus. There may be a nicer way of achieving that;
447 it doesn't really scale that well to higher channel counts
450 /* mono output bundles */
452 for (uint32_t np = 0; np < outputs[DataType::AUDIO].size(); ++np) {
454 snprintf (buf, sizeof (buf), _("out %" PRIu32), np+1);
456 shared_ptr<Bundle> c (new Bundle (buf, true));
457 c->add_channel (_("mono"), DataType::AUDIO);
458 c->set_port (0, outputs[DataType::AUDIO][np]);
463 /* stereo output bundles */
465 for (uint32_t np = 0; np < outputs[DataType::AUDIO].size(); np += 2) {
466 if (np + 1 < outputs[DataType::AUDIO].size()) {
468 snprintf (buf, sizeof(buf), _("out %" PRIu32 "+%" PRIu32), np + 1, np + 2);
469 shared_ptr<Bundle> c (new Bundle (buf, true));
470 c->add_channel (_("L"), DataType::AUDIO);
471 c->set_port (0, outputs[DataType::AUDIO][np]);
472 c->add_channel (_("R"), DataType::AUDIO);
473 c->set_port (1, outputs[DataType::AUDIO][np + 1]);
479 /* mono input bundles */
481 for (uint32_t np = 0; np < inputs[DataType::AUDIO].size(); ++np) {
483 snprintf (buf, sizeof (buf), _("in %" PRIu32), np+1);
485 shared_ptr<Bundle> c (new Bundle (buf, false));
486 c->add_channel (_("mono"), DataType::AUDIO);
487 c->set_port (0, inputs[DataType::AUDIO][np]);
492 /* stereo input bundles */
494 for (uint32_t np = 0; np < inputs[DataType::AUDIO].size(); np += 2) {
495 if (np + 1 < inputs[DataType::AUDIO].size()) {
497 snprintf (buf, sizeof(buf), _("in %" PRIu32 "+%" PRIu32), np + 1, np + 2);
499 shared_ptr<Bundle> c (new Bundle (buf, false));
500 c->add_channel (_("L"), DataType::AUDIO);
501 c->set_port (0, inputs[DataType::AUDIO][np]);
502 c->add_channel (_("R"), DataType::AUDIO);
503 c->set_port (1, inputs[DataType::AUDIO][np + 1]);
509 /* MIDI input bundles */
511 for (uint32_t np = 0; np < inputs[DataType::MIDI].size(); ++np) {
512 string n = inputs[DataType::MIDI][np];
513 boost::erase_first (n, X_("alsa_pcm:"));
515 shared_ptr<Bundle> c (new Bundle (n, false));
516 c->add_channel ("", DataType::MIDI);
517 c->set_port (0, inputs[DataType::MIDI][np]);
521 /* MIDI output bundles */
523 for (uint32_t np = 0; np < outputs[DataType::MIDI].size(); ++np) {
524 string n = outputs[DataType::MIDI][np];
525 boost::erase_first (n, X_("alsa_pcm:"));
527 shared_ptr<Bundle> c (new Bundle (n, true));
528 c->add_channel ("", DataType::MIDI);
529 c->set_port (0, outputs[DataType::MIDI][np]);
533 BootMessage (_("Setup signal flow and plugins"));
537 if (_is_new && !no_auto_connect()) {
539 /* don't connect the master bus outputs if there is a monitor bus */
541 if (_master_out && Config->get_auto_connect_standard_busses() && !_monitor_out) {
543 /* if requested auto-connect the outputs to the first N physical ports.
546 uint32_t limit = _master_out->n_outputs().n_total();
548 for (uint32_t n = 0; n < limit; ++n) {
549 Port* p = _master_out->output()->nth (n);
551 if (outputs[p->type()].size() > n) {
552 connect_to = outputs[p->type()][n];
555 if (!connect_to.empty() && p->connected_to (connect_to) == false) {
556 if (_master_out->output()->connect (p, connect_to, this)) {
557 error << string_compose (_("cannot connect master output %1 to %2"), n, connect_to)
567 /* AUDIO ONLY as of june 29th 2009, because listen semantics for anything else
568 are undefined, at best.
571 /* control out listens to master bus (but ignores it
572 under some conditions)
575 uint32_t limit = _monitor_out->n_inputs().n_audio();
578 for (uint32_t n = 0; n < limit; ++n) {
579 AudioPort* p = _monitor_out->input()->ports().nth_audio_port (n);
580 AudioPort* o = _master_out->output()->ports().nth_audio_port (n);
583 string connect_to = o->name();
584 if (_monitor_out->input()->connect (p, connect_to, this)) {
585 error << string_compose (_("cannot connect control input %1 to %2"), n, connect_to)
593 /* if control out is not connected, connect control out to physical outs
596 if (!_monitor_out->output()->connected ()) {
598 if (!Config->get_monitor_bus_preferred_bundle().empty()) {
600 boost::shared_ptr<Bundle> b = bundle_by_name (Config->get_monitor_bus_preferred_bundle());
603 _monitor_out->output()->connect_ports_to_bundle (b, this);
605 warning << string_compose (_("The preferred I/O for the monitor bus (%1) cannot be found"),
606 Config->get_monitor_bus_preferred_bundle())
612 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
613 uint32_t mod = n_physical_outputs.get (*t);
614 uint32_t limit = _monitor_out->n_outputs().get(*t);
616 for (uint32_t n = 0; n < limit; ++n) {
618 Port* p = _monitor_out->output()->ports().port(*t, n);
620 if (outputs[*t].size() > (n % mod)) {
621 connect_to = outputs[*t][n % mod];
624 if (!connect_to.empty()) {
625 if (_monitor_out->output()->connect (p, connect_to, this)) {
626 error << string_compose (
627 _("cannot connect control output %1 to %2"),
640 /* catch up on send+insert cnts */
642 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
644 /* hook us up to the engine */
646 BootMessage (_("Connect to engine"));
648 _engine.set_session (this);
652 Session::hookup_io ()
654 /* stop graph reordering notifications from
655 causing resorts, etc.
658 _state_of_the_state = StateOfTheState (_state_of_the_state | InitialConnecting);
663 /* we delay creating the auditioner till now because
664 it makes its own connections to ports.
668 Auditioner* a = new Auditioner (*this);
671 throw failed_constructor();
673 a->use_new_diskstream ();
674 auditioner.reset (a);
677 catch (failed_constructor& err) {
678 warning << _("cannot create Auditioner: no auditioning of regions possible") << endmsg;
682 /* load bundles, which we may have postponed earlier on */
683 if (_bundle_xml_node) {
684 load_bundles (*_bundle_xml_node);
685 delete _bundle_xml_node;
688 /* Tell all IO objects to connect themselves together */
690 IO::enable_connecting ();
691 MIDI::Port::MakeConnections ();
693 /* Now reset all panners */
695 Delivery::reset_panners ();
697 /* Connect tracks to monitor/listen bus if there is one.
698 Note that in an existing session, the internal sends will
699 already exist, but we want the routes to notice that
700 they connect to the control out specifically.
704 boost::shared_ptr<RouteList> r = routes.reader ();
705 for (RouteList::iterator x = r->begin(); x != r->end(); ++x) {
707 if ((*x)->is_monitor()) {
711 } else if ((*x)->is_master()) {
717 (*x)->listen_via (_monitor_out,
718 (Config->get_listen_position() == AfterFaderListen ? PostFader : PreFader),
724 /* Anyone who cares about input state, wake up and do something */
726 IOConnectionsComplete (); /* EMIT SIGNAL */
728 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InitialConnecting);
730 /* now handle the whole enchilada as if it was one
736 /* update the full solo state, which can't be
737 correctly determined on a per-route basis, but
738 needs the global overview that only the session
742 update_route_solo_state ();
746 Session::playlist_length_changed ()
748 update_session_range_location_marker ();
752 Session::track_playlist_changed (boost::weak_ptr<Track> wp)
754 boost::shared_ptr<Track> track = wp.lock ();
759 boost::shared_ptr<Playlist> playlist;
761 if ((playlist = track->playlist()) != 0) {
762 playlist->LengthChanged.connect_same_thread (*this, boost::bind (&Session::playlist_length_changed, this));
765 update_session_range_location_marker ();
769 Session::record_enabling_legal () const
771 /* this used to be in here, but survey says.... we don't need to restrict it */
772 // if (record_status() == Recording) {
776 if (Config->get_all_safe()) {
783 Session::reset_input_monitor_state ()
785 if (transport_rolling()) {
787 boost::shared_ptr<RouteList> rl = routes.reader ();
788 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
789 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
790 if (tr && tr->record_enabled ()) {
791 //cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
792 tr->monitor_input (Config->get_monitoring_model() == HardwareMonitoring && !config.get_auto_input());
798 boost::shared_ptr<RouteList> rl = routes.reader ();
799 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
800 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
801 if (tr && tr->record_enabled ()) {
802 //cerr << "switching to input = " << !Config->get_auto_input() << __FILE__ << __LINE__ << endl << endl;
803 tr->monitor_input (Config->get_monitoring_model() == HardwareMonitoring);
810 Session::auto_punch_start_changed (Location* location)
812 replace_event (SessionEvent::PunchIn, location->start());
814 if (get_record_enabled() && config.get_punch_in()) {
815 /* capture start has been changed, so save new pending state */
816 save_state ("", true);
821 Session::auto_punch_end_changed (Location* location)
823 nframes_t when_to_stop = location->end();
824 // when_to_stop += _worst_output_latency + _worst_input_latency;
825 replace_event (SessionEvent::PunchOut, when_to_stop);
829 Session::auto_punch_changed (Location* location)
831 nframes_t when_to_stop = location->end();
833 replace_event (SessionEvent::PunchIn, location->start());
834 //when_to_stop += _worst_output_latency + _worst_input_latency;
835 replace_event (SessionEvent::PunchOut, when_to_stop);
839 Session::auto_loop_changed (Location* location)
841 replace_event (SessionEvent::AutoLoop, location->end(), location->start());
843 if (transport_rolling() && play_loop) {
846 // if (_transport_frame > location->end()) {
848 if (_transport_frame < location->start() || _transport_frame > location->end()) {
849 // relocate to beginning of loop
850 clear_events (SessionEvent::LocateRoll);
852 request_locate (location->start(), true);
855 else if (Config->get_seamless_loop() && !loop_changing) {
857 // schedule a locate-roll to refill the diskstreams at the
859 loop_changing = true;
861 if (location->end() > last_loopend) {
862 clear_events (SessionEvent::LocateRoll);
863 SessionEvent *ev = new SessionEvent (SessionEvent::LocateRoll, SessionEvent::Add, last_loopend, last_loopend, 0, true);
870 last_loopend = location->end();
874 Session::set_auto_punch_location (Location* location)
878 if ((existing = _locations->auto_punch_location()) != 0 && existing != location) {
879 punch_connections.drop_connections();
880 existing->set_auto_punch (false, this);
881 remove_event (existing->start(), SessionEvent::PunchIn);
882 clear_events (SessionEvent::PunchOut);
883 auto_punch_location_changed (0);
892 if (location->end() <= location->start()) {
893 error << _("Session: you can't use that location for auto punch (start <= end)") << endmsg;
897 punch_connections.drop_connections ();
899 location->start_changed.connect_same_thread (punch_connections, boost::bind (&Session::auto_punch_start_changed, this, _1));
900 location->end_changed.connect_same_thread (punch_connections, boost::bind (&Session::auto_punch_end_changed, this, _1));
901 location->changed.connect_same_thread (punch_connections, boost::bind (&Session::auto_punch_changed, this, _1));
903 location->set_auto_punch (true, this);
905 auto_punch_changed (location);
907 auto_punch_location_changed (location);
911 Session::set_auto_loop_location (Location* location)
915 if ((existing = _locations->auto_loop_location()) != 0 && existing != location) {
916 loop_connections.drop_connections ();
917 existing->set_auto_loop (false, this);
918 remove_event (existing->end(), SessionEvent::AutoLoop);
919 auto_loop_location_changed (0);
928 if (location->end() <= location->start()) {
929 error << _("Session: you can't use a mark for auto loop") << endmsg;
933 last_loopend = location->end();
935 loop_connections.drop_connections ();
937 location->start_changed.connect_same_thread (loop_connections, boost::bind (&Session::auto_loop_changed, this, _1));
938 location->end_changed.connect_same_thread (loop_connections, boost::bind (&Session::auto_loop_changed, this, _1));
939 location->changed.connect_same_thread (loop_connections, boost::bind (&Session::auto_loop_changed, this, _1));
941 location->set_auto_loop (true, this);
943 /* take care of our stuff first */
945 auto_loop_changed (location);
947 /* now tell everyone else */
949 auto_loop_location_changed (location);
953 Session::locations_added (Location *)
959 Session::locations_changed ()
961 _locations->apply (*this, &Session::handle_locations_changed);
965 Session::handle_locations_changed (Locations::LocationList& locations)
967 Locations::LocationList::iterator i;
969 bool set_loop = false;
970 bool set_punch = false;
972 for (i = locations.begin(); i != locations.end(); ++i) {
976 if (location->is_auto_punch()) {
977 set_auto_punch_location (location);
980 if (location->is_auto_loop()) {
981 set_auto_loop_location (location);
985 if (location->is_session_range()) {
986 _session_range_location = location;
991 set_auto_loop_location (0);
994 set_auto_punch_location (0);
1001 Session::enable_record ()
1004 RecordState rs = (RecordState) g_atomic_int_get (&_record_status);
1006 if (rs == Recording) {
1010 if (g_atomic_int_compare_and_exchange (&_record_status, rs, Recording)) {
1012 _last_record_location = _transport_frame;
1013 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordStrobe));
1015 if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
1017 boost::shared_ptr<RouteList> rl = routes.reader ();
1018 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1019 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1020 if (tr && tr->record_enabled ()) {
1021 tr->monitor_input (true);
1026 RecordStateChanged ();
1033 Session::disable_record (bool rt_context, bool force)
1037 if ((rs = (RecordState) g_atomic_int_get (&_record_status)) != Disabled) {
1039 if ((!Config->get_latched_record_enable () && !play_loop) || force) {
1040 g_atomic_int_set (&_record_status, Disabled);
1041 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordExit));
1043 if (rs == Recording) {
1044 g_atomic_int_set (&_record_status, Enabled);
1048 if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
1050 boost::shared_ptr<RouteList> rl = routes.reader ();
1051 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1052 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1053 if (tr && tr->record_enabled ()) {
1054 tr->monitor_input (false);
1059 RecordStateChanged (); /* emit signal */
1062 remove_pending_capture_state ();
1068 Session::step_back_from_record ()
1070 if (g_atomic_int_compare_and_exchange (&_record_status, Recording, Enabled)) {
1072 if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
1073 boost::shared_ptr<RouteList> rl = routes.reader ();
1074 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1075 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1076 if (tr && tr->record_enabled ()) {
1077 //cerr << "switching from input" << __FILE__ << __LINE__ << endl << endl;
1078 tr->monitor_input (false);
1086 Session::maybe_enable_record ()
1088 if (_step_editors > 0) {
1092 g_atomic_int_set (&_record_status, Enabled);
1094 /* this function is currently called from somewhere other than an RT thread.
1095 this save_state() call therefore doesn't impact anything.
1098 save_state ("", true);
1100 if (_transport_speed) {
1101 if (!config.get_punch_in()) {
1105 MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordPause));
1106 RecordStateChanged (); /* EMIT SIGNAL */
1113 Session::audible_frame () const
1119 /* the first of these two possible settings for "offset"
1120 mean that the audible frame is stationary until
1121 audio emerges from the latency compensation
1124 the second means that the audible frame is stationary
1125 until audio would emerge from a physical port
1126 in the absence of any plugin latency compensation
1129 offset = _worst_output_latency;
1131 if (offset > current_block_size) {
1132 offset -= current_block_size;
1134 /* XXX is this correct? if we have no external
1135 physical connections and everything is internal
1136 then surely this is zero? still, how
1137 likely is that anyway?
1139 offset = current_block_size;
1142 if (synced_to_jack()) {
1143 tf = _engine.transport_frame();
1145 tf = _transport_frame;
1150 if (!non_realtime_work_pending()) {
1154 /* Check to see if we have passed the first guaranteed
1155 audible frame past our last start position. if not,
1156 return that last start point because in terms
1157 of audible frames, we have not moved yet.
1159 `Start position' in this context means the time we last
1160 either started or changed transport direction.
1163 if (_transport_speed > 0.0f) {
1165 if (!play_loop || !have_looped) {
1166 if (tf < _last_roll_or_reversal_location + offset) {
1167 return _last_roll_or_reversal_location;
1175 } else if (_transport_speed < 0.0f) {
1177 /* XXX wot? no backward looping? */
1179 if (tf > _last_roll_or_reversal_location - offset) {
1180 return _last_roll_or_reversal_location;
1192 Session::set_frame_rate (nframes_t frames_per_second)
1194 /** \fn void Session::set_frame_size(nframes_t)
1195 the AudioEngine object that calls this guarantees
1196 that it will not be called while we are also in
1197 ::process(). Its fine to do things that block
1201 _base_frame_rate = frames_per_second;
1205 Automatable::set_automation_interval ((jack_nframes_t) ceil ((double) frames_per_second * (0.001 * Config->get_automation_interval())));
1209 // XXX we need some equivalent to this, somehow
1210 // SndFileSource::setup_standard_crossfades (frames_per_second);
1214 /* XXX need to reset/reinstantiate all LADSPA plugins */
1218 Session::set_block_size (nframes_t nframes)
1220 /* the AudioEngine guarantees
1221 that it will not be called while we are also in
1222 ::process(). It is therefore fine to do things that block
1227 current_block_size = nframes;
1231 boost::shared_ptr<RouteList> r = routes.reader ();
1233 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1234 (*i)->set_block_size (nframes);
1237 boost::shared_ptr<RouteList> rl = routes.reader ();
1238 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1239 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1241 tr->set_block_size (nframes);
1245 set_worst_io_latencies ();
1250 Session::set_default_fade (float /*steepness*/, float /*fade_msecs*/)
1253 nframes_t fade_frames;
1255 /* Don't allow fade of less 1 frame */
1257 if (fade_msecs < (1000.0 * (1.0/_current_frame_rate))) {
1264 fade_frames = (nframes_t) floor (fade_msecs * _current_frame_rate * 0.001);
1268 default_fade_msecs = fade_msecs;
1269 default_fade_steepness = steepness;
1272 // jlc, WTF is this!
1273 Glib::RWLock::ReaderLock lm (route_lock);
1274 AudioRegion::set_default_fade (steepness, fade_frames);
1279 /* XXX have to do this at some point */
1280 /* foreach region using default fade, reset, then
1281 refill_all_diskstream_buffers ();
1286 struct RouteSorter {
1287 bool operator() (boost::shared_ptr<Route> r1, boost::shared_ptr<Route> r2) {
1288 if (r2->feeds (r1)) {
1290 } else if (r1->feeds (r2)) {
1293 if (r1->not_fed ()) {
1294 if (r2->not_fed ()) {
1295 /* no ardour-based connections inbound to either route. just use signal order */
1296 return r1->order_key(N_("signal")) < r2->order_key(N_("signal"));
1298 /* r2 has connections, r1 does not; run r1 early */
1302 return r1->order_key(N_("signal")) < r2->order_key(N_("signal"));
1309 trace_terminal (shared_ptr<Route> r1, shared_ptr<Route> rbase)
1311 shared_ptr<Route> r2;
1313 if (r1->feeds (rbase) && rbase->feeds (r1)) {
1314 info << string_compose(_("feedback loop setup between %1 and %2"), r1->name(), rbase->name()) << endmsg;
1318 /* make a copy of the existing list of routes that feed r1 */
1320 Route::FedBy existing (r1->fed_by());
1322 /* for each route that feeds r1, recurse, marking it as feeding
1326 for (Route::FedBy::iterator i = existing.begin(); i != existing.end(); ++i) {
1327 if (!(r2 = i->r.lock ())) {
1328 /* (*i) went away, ignore it */
1332 /* r2 is a route that feeds r1 which somehow feeds base. mark
1333 base as being fed by r2
1336 rbase->add_fed_by (r2, i->sends_only);
1340 /* 2nd level feedback loop detection. if r1 feeds or is fed by r2,
1344 if (r1->feeds (r2) && r2->feeds (r1)) {
1348 /* now recurse, so that we can mark base as being fed by
1349 all routes that feed r2
1352 trace_terminal (r2, rbase);
1359 Session::resort_routes ()
1361 /* don't do anything here with signals emitted
1362 by Routes while we are being destroyed.
1365 if (_state_of_the_state & Deletion) {
1370 RCUWriter<RouteList> writer (routes);
1371 shared_ptr<RouteList> r = writer.get_copy ();
1372 resort_routes_using (r);
1373 /* writer goes out of scope and forces update */
1376 //route_graph->dump(1);
1379 boost::shared_ptr<RouteList> rl = routes.reader ();
1380 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1381 DEBUG_TRACE (DEBUG::Graph, string_compose ("%1 fed by ...\n", (*i)->name()));
1383 const Route::FedBy& fb ((*i)->fed_by());
1385 for (Route::FedBy::const_iterator f = fb.begin(); f != fb.end(); ++f) {
1386 boost::shared_ptr<Route> sf = f->r.lock();
1388 DEBUG_TRACE (DEBUG::Graph, string_compose ("\t%1 (sends only ? %2)\n", sf->name(), f->sends_only));
1396 Session::resort_routes_using (shared_ptr<RouteList> r)
1398 RouteList::iterator i, j;
1400 for (i = r->begin(); i != r->end(); ++i) {
1402 (*i)->clear_fed_by ();
1404 for (j = r->begin(); j != r->end(); ++j) {
1406 /* although routes can feed themselves, it will
1407 cause an endless recursive descent if we
1408 detect it. so don't bother checking for
1416 bool via_sends_only;
1418 if ((*j)->direct_feeds (*i, &via_sends_only)) {
1419 (*i)->add_fed_by (*j, via_sends_only);
1424 for (i = r->begin(); i != r->end(); ++i) {
1425 trace_terminal (*i, *i);
1431 route_graph->rechain (r);
1434 DEBUG_TRACE (DEBUG::Graph, "Routes resorted, order follows:\n");
1435 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1436 DEBUG_TRACE (DEBUG::Graph, string_compose ("\t%1 signal order %2\n",
1437 (*i)->name(), (*i)->order_key ("signal")));
1443 /** Find the route name starting with \a base with the lowest \a id.
1445 * Names are constructed like e.g. "Audio 3" for base="Audio" and id=3.
1446 * The available route name with the lowest ID will be used, and \a id
1447 * will be set to the ID.
1449 * \return false if a route name could not be found, and \a track_name
1450 * and \a id do not reflect a free route name.
1453 Session::find_route_name (const char* base, uint32_t& id, char* name, size_t name_len)
1456 snprintf (name, name_len, "%s %" PRIu32, base, id);
1458 if (route_by_name (name) == 0) {
1464 } while (id < (UINT_MAX-1));
1470 Session::count_existing_route_channels (ChanCount& in, ChanCount& out)
1472 in = ChanCount::ZERO;
1473 out = ChanCount::ZERO;
1474 shared_ptr<RouteList> r = routes.reader ();
1475 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1476 if (!(*i)->is_hidden()) {
1477 in += (*i)->n_inputs();
1478 out += (*i)->n_outputs();
1483 list<boost::shared_ptr<MidiTrack> >
1484 Session::new_midi_track (TrackMode mode, RouteGroup* route_group, uint32_t how_many)
1486 char track_name[32];
1487 uint32_t track_id = 0;
1488 ChanCount existing_inputs;
1489 ChanCount existing_outputs;
1491 RouteList new_routes;
1492 list<boost::shared_ptr<MidiTrack> > ret;
1493 uint32_t control_id;
1495 count_existing_route_channels (existing_inputs, existing_outputs);
1497 control_id = ntracks() + nbusses();
1500 if (!find_route_name ("Midi", ++track_id, track_name, sizeof(track_name))) {
1501 error << "cannot find name for new midi track" << endmsg;
1505 shared_ptr<MidiTrack> track;
1508 MidiTrack* mt = new MidiTrack (*this, track_name, Route::Flag (0), mode);
1515 mt->use_new_diskstream();
1517 boost_debug_shared_ptr_mark_interesting (mt, "Track");
1518 track = boost::shared_ptr<MidiTrack>(mt);
1520 if (track->input()->ensure_io (ChanCount(DataType::MIDI, 1), false, this)) {
1521 error << "cannot configure 1 in/1 out configuration for new midi track" << endmsg;
1526 if (track->output()->ensure_io (ChanCount(DataType::MIDI, 1), false, this)) {
1527 error << "cannot configure 1 in/1 out configuration for new midi track" << endmsg;
1531 auto_connect_route (track, existing_inputs, existing_outputs);
1533 track->non_realtime_input_change();
1536 route_group->add (track);
1539 track->DiskstreamChanged.connect_same_thread (*this, boost::bind (&Session::resort_routes, this));
1540 track->set_remote_control_id (control_id);
1542 new_routes.push_back (track);
1543 ret.push_back (track);
1546 catch (failed_constructor &err) {
1547 error << _("Session: could not create new midi track.") << endmsg;
1551 catch (AudioEngine::PortRegistrationFailure& pfe) {
1553 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;
1561 if (!new_routes.empty()) {
1562 add_routes (new_routes, false);
1563 save_state (_current_snapshot_name);
1569 /** @param connect_inputs true to connect inputs as well as outputs, false to connect just outputs */
1571 Session::auto_connect_route (boost::shared_ptr<Route> route, ChanCount& existing_inputs, ChanCount& existing_outputs, bool connect_inputs)
1573 /* If both inputs and outputs are auto-connected to physical ports,
1574 use the max of input and output offsets to ensure auto-connected
1575 port numbers always match up (e.g. the first audio input and the
1576 first audio output of the route will have the same physical
1577 port number). Otherwise just use the lowest input or output
1581 const bool in_out_physical =
1582 (Config->get_input_auto_connect() & AutoConnectPhysical)
1583 && (Config->get_output_auto_connect() & AutoConnectPhysical)
1586 const ChanCount in_offset = in_out_physical
1587 ? ChanCount::max(existing_inputs, existing_outputs)
1590 const ChanCount out_offset = in_out_physical
1591 ? ChanCount::max(existing_inputs, existing_outputs)
1594 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
1595 vector<string> physinputs;
1596 vector<string> physoutputs;
1598 _engine.get_physical_outputs (*t, physoutputs);
1599 _engine.get_physical_inputs (*t, physinputs);
1601 if (!physinputs.empty() && connect_inputs) {
1602 uint32_t nphysical_in = physinputs.size();
1603 for (uint32_t i = 0; i < route->n_inputs().get(*t) && i < nphysical_in; ++i) {
1606 if (Config->get_input_auto_connect() & AutoConnectPhysical) {
1607 port = physinputs[(in_offset.get(*t) + i) % nphysical_in];
1610 if (!port.empty() && route->input()->connect (
1611 route->input()->ports().port(*t, i), port, this)) {
1617 if (!physoutputs.empty()) {
1618 uint32_t nphysical_out = physoutputs.size();
1619 for (uint32_t i = 0; i < route->n_outputs().get(*t); ++i) {
1622 if (Config->get_output_auto_connect() & AutoConnectPhysical) {
1623 port = physoutputs[(out_offset.get(*t) + i) % nphysical_out];
1624 } else if (Config->get_output_auto_connect() & AutoConnectMaster) {
1625 if (_master_out && _master_out->n_inputs().get(*t) > 0) {
1626 port = _master_out->input()->ports().port(*t,
1627 i % _master_out->input()->n_ports().get(*t))->name();
1631 if (!port.empty() && route->output()->connect (
1632 route->output()->ports().port(*t, i), port, this)) {
1639 existing_inputs += route->n_inputs();
1640 existing_outputs += route->n_outputs();
1643 list< boost::shared_ptr<AudioTrack> >
1644 Session::new_audio_track (int input_channels, int output_channels, TrackMode mode, RouteGroup* route_group, uint32_t how_many)
1646 char track_name[32];
1647 uint32_t track_id = 0;
1648 ChanCount existing_inputs;
1649 ChanCount existing_outputs;
1651 RouteList new_routes;
1652 list<boost::shared_ptr<AudioTrack> > ret;
1653 uint32_t control_id;
1655 count_existing_route_channels (existing_inputs, existing_outputs);
1657 control_id = ntracks() + nbusses() + 1;
1660 if (!find_route_name ("Audio", ++track_id, track_name, sizeof(track_name))) {
1661 error << "cannot find name for new audio track" << endmsg;
1665 shared_ptr<AudioTrack> track;
1668 AudioTrack* at = new AudioTrack (*this, track_name, Route::Flag (0), mode);
1675 at->use_new_diskstream();
1677 boost_debug_shared_ptr_mark_interesting (at, "Track");
1678 track = boost::shared_ptr<AudioTrack>(at);
1680 if (track->input()->ensure_io (ChanCount(DataType::AUDIO, input_channels), false, this)) {
1681 error << string_compose (
1682 _("cannot configure %1 in/%2 out configuration for new audio track"),
1683 input_channels, output_channels)
1688 if (track->output()->ensure_io (ChanCount(DataType::AUDIO, output_channels), false, this)) {
1689 error << string_compose (
1690 _("cannot configure %1 in/%2 out configuration for new audio track"),
1691 input_channels, output_channels)
1696 auto_connect_route (track, existing_inputs, existing_outputs);
1699 route_group->add (track);
1702 track->non_realtime_input_change();
1704 track->DiskstreamChanged.connect_same_thread (*this, boost::bind (&Session::resort_routes, this));
1705 track->set_remote_control_id (control_id);
1708 new_routes.push_back (track);
1709 ret.push_back (track);
1712 catch (failed_constructor &err) {
1713 error << _("Session: could not create new audio track.") << endmsg;
1717 catch (AudioEngine::PortRegistrationFailure& pfe) {
1719 error << pfe.what() << endmsg;
1727 if (!new_routes.empty()) {
1728 add_routes (new_routes, true);
1735 Session::set_remote_control_ids ()
1737 RemoteModel m = Config->get_remote_model();
1738 bool emit_signal = false;
1740 shared_ptr<RouteList> r = routes.reader ();
1742 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
1743 if (MixerOrdered == m) {
1744 int32_t order = (*i)->order_key(N_("signal"));
1745 (*i)->set_remote_control_id (order+1, false);
1747 } else if (EditorOrdered == m) {
1748 int32_t order = (*i)->order_key(N_("editor"));
1749 (*i)->set_remote_control_id (order+1, false);
1751 } else if (UserOrdered == m) {
1752 //do nothing ... only changes to remote id's are initiated by user
1757 Route::RemoteControlIDChange();
1763 Session::new_audio_route (bool aux, int input_channels, int output_channels, RouteGroup* route_group, uint32_t how_many)
1766 uint32_t bus_id = 0;
1767 ChanCount existing_inputs;
1768 ChanCount existing_outputs;
1771 uint32_t control_id;
1773 count_existing_route_channels (existing_inputs, existing_outputs);
1775 control_id = ntracks() + nbusses() + 1;
1778 if (!find_route_name ("Bus", ++bus_id, bus_name, sizeof(bus_name))) {
1779 error << "cannot find name for new audio bus" << endmsg;
1784 Route* rt = new Route (*this, bus_name, Route::Flag(0), DataType::AUDIO);
1791 boost_debug_shared_ptr_mark_interesting (rt, "Route");
1792 shared_ptr<Route> bus (rt);
1794 if (bus->input()->ensure_io (ChanCount(DataType::AUDIO, input_channels), false, this)) {
1795 error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
1796 input_channels, output_channels)
1802 if (bus->output()->ensure_io (ChanCount(DataType::AUDIO, output_channels), false, this)) {
1803 error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
1804 input_channels, output_channels)
1809 auto_connect_route (bus, existing_inputs, existing_outputs, false);
1812 route_group->add (bus);
1814 bus->set_remote_control_id (control_id);
1818 bus->add_internal_return ();
1821 ret.push_back (bus);
1825 catch (failed_constructor &err) {
1826 error << _("Session: could not create new audio route.") << endmsg;
1830 catch (AudioEngine::PortRegistrationFailure& pfe) {
1831 error << pfe.what() << endmsg;
1841 add_routes (ret, true);
1849 Session::new_route_from_template (uint32_t how_many, const std::string& template_path)
1853 uint32_t control_id;
1855 uint32_t number = 0;
1857 if (!tree.read (template_path.c_str())) {
1861 XMLNode* node = tree.root();
1863 control_id = ntracks() + nbusses() + 1;
1867 XMLNode node_copy (*node); // make a copy so we can change the name if we need to
1869 std::string node_name = IO::name_from_state (*node_copy.children().front());
1871 /* generate a new name by adding a number to the end of the template name */
1872 if (!find_route_name (node_name.c_str(), ++number, name, sizeof(name))) {
1873 fatal << _("Session: UINT_MAX routes? impossible!") << endmsg;
1877 /* set IO children to use the new name */
1878 XMLNodeList const & children = node_copy.children ();
1879 for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
1880 if ((*i)->name() == IO::state_node_name) {
1881 IO::set_name_in_state (**i, name);
1885 Track::zero_diskstream_id_in_xml (node_copy);
1888 shared_ptr<Route> route (XMLRouteFactory (node_copy, 3000));
1891 error << _("Session: cannot create track/bus from template description") << endmsg;
1895 if (boost::dynamic_pointer_cast<Track>(route)) {
1896 /* force input/output change signals so that the new diskstream
1897 picks up the configuration of the route. During session
1898 loading this normally happens in a different way.
1900 route->input()->changed (IOChange (ConfigurationChanged|ConnectionsChanged), this);
1901 route->output()->changed (IOChange (ConfigurationChanged|ConnectionsChanged), this);
1904 route->set_remote_control_id (control_id);
1907 ret.push_back (route);
1910 catch (failed_constructor &err) {
1911 error << _("Session: could not create new route from template") << endmsg;
1915 catch (AudioEngine::PortRegistrationFailure& pfe) {
1916 error << pfe.what() << endmsg;
1925 add_routes (ret, true);
1932 Session::add_routes (RouteList& new_routes, bool save)
1935 RCUWriter<RouteList> writer (routes);
1936 shared_ptr<RouteList> r = writer.get_copy ();
1937 r->insert (r->end(), new_routes.begin(), new_routes.end());
1940 /* if there is no control out and we're not in the middle of loading,
1941 resort the graph here. if there is a control out, we will resort
1942 toward the end of this method. if we are in the middle of loading,
1943 we will resort when done.
1946 if (!_monitor_out && IO::connecting_legal) {
1947 resort_routes_using (r);
1951 for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) {
1953 boost::weak_ptr<Route> wpr (*x);
1954 boost::shared_ptr<Route> r (*x);
1956 r->listen_changed.connect_same_thread (*this, boost::bind (&Session::route_listen_changed, this, _1, wpr));
1957 r->solo_changed.connect_same_thread (*this, boost::bind (&Session::route_solo_changed, this, _1, _2, wpr));
1958 r->solo_isolated_changed.connect_same_thread (*this, boost::bind (&Session::route_solo_isolated_changed, this, _1, wpr));
1959 r->mute_changed.connect_same_thread (*this, boost::bind (&Session::route_mute_changed, this, _1));
1960 r->output()->changed.connect_same_thread (*this, boost::bind (&Session::set_worst_io_latencies_x, this, _1, _2));
1961 r->processors_changed.connect_same_thread (*this, boost::bind (&Session::route_processors_changed, this, _1));
1962 r->order_key_changed.connect_same_thread (*this, boost::bind (&Session::route_order_key_changed, this));
1964 if (r->is_master()) {
1968 if (r->is_monitor()) {
1972 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (r);
1974 tr->PlaylistChanged.connect_same_thread (*this, boost::bind (&Session::track_playlist_changed, this, boost::weak_ptr<Track> (tr)));
1975 track_playlist_changed (boost::weak_ptr<Track> (tr));
1976 tr->RecordEnableChanged.connect_same_thread (*this, boost::bind (&Session::update_have_rec_enabled_track, this));
1978 boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (tr);
1980 mt->StepEditStatusChange.connect_same_thread (*this, boost::bind (&Session::step_edit_status_change, this, _1));
1985 if (_monitor_out && IO::connecting_legal) {
1987 for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) {
1988 if ((*x)->is_monitor()) {
1990 } else if ((*x)->is_master()) {
1993 (*x)->listen_via (_monitor_out,
1994 (Config->get_listen_position() == AfterFaderListen ? PostFader : PreFader),
2005 save_state (_current_snapshot_name);
2008 RouteAdded (new_routes); /* EMIT SIGNAL */
2009 Route::RemoteControlIDChange (); /* EMIT SIGNAL */
2013 Session::globally_set_send_gains_to_zero (boost::shared_ptr<Route> dest)
2015 boost::shared_ptr<RouteList> r = routes.reader ();
2016 boost::shared_ptr<Send> s;
2020 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2021 if (boost::dynamic_pointer_cast<Track>(*i)) {
2022 if ((s = (*i)->internal_send_for (dest)) != 0) {
2023 s->amp()->gain_control()->set_value (0.0);
2030 Session::globally_set_send_gains_to_unity (boost::shared_ptr<Route> dest)
2032 boost::shared_ptr<RouteList> r = routes.reader ();
2033 boost::shared_ptr<Send> s;
2037 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2038 if (boost::dynamic_pointer_cast<Track>(*i)) {
2039 if ((s = (*i)->internal_send_for (dest)) != 0) {
2040 s->amp()->gain_control()->set_value (1.0);
2047 Session::globally_set_send_gains_from_track(boost::shared_ptr<Route> dest)
2049 boost::shared_ptr<RouteList> r = routes.reader ();
2050 boost::shared_ptr<Send> s;
2054 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2055 if (boost::dynamic_pointer_cast<Track>(*i)) {
2056 if ((s = (*i)->internal_send_for (dest)) != 0) {
2057 s->amp()->gain_control()->set_value ((*i)->gain_control()->get_value());
2064 Session::globally_add_internal_sends (boost::shared_ptr<Route> dest, Placement p)
2066 boost::shared_ptr<RouteList> r = routes.reader ();
2067 boost::shared_ptr<RouteList> t (new RouteList);
2069 /* only send tracks */
2071 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2072 if (boost::dynamic_pointer_cast<Track>(*i)) {
2077 add_internal_sends (dest, p, t);
2081 Session::add_internal_sends (boost::shared_ptr<Route> dest, Placement p, boost::shared_ptr<RouteList> senders)
2083 if (dest->is_monitor() || dest->is_master()) {
2087 if (!dest->internal_return()) {
2088 dest->add_internal_return();
2091 for (RouteList::iterator i = senders->begin(); i != senders->end(); ++i) {
2093 if ((*i)->is_monitor() || (*i)->is_master() || (*i) == dest) {
2097 (*i)->listen_via (dest, p, true, true);
2104 Session::remove_route (shared_ptr<Route> route)
2106 if (((route == _master_out) || (route == _monitor_out)) && !Config->get_allow_special_bus_removal()) {
2111 RCUWriter<RouteList> writer (routes);
2112 shared_ptr<RouteList> rs = writer.get_copy ();
2116 /* deleting the master out seems like a dumb
2117 idea, but its more of a UI policy issue
2121 if (route == _master_out) {
2122 _master_out = shared_ptr<Route> ();
2125 if (route == _monitor_out) {
2127 /* cancel control outs for all routes */
2129 for (RouteList::iterator r = rs->begin(); r != rs->end(); ++r) {
2130 (*r)->drop_listen (_monitor_out);
2133 _monitor_out.reset ();
2136 /* writer goes out of scope, forces route list update */
2139 update_route_solo_state ();
2140 update_session_range_location_marker ();
2142 // We need to disconnect the route's inputs and outputs
2144 route->input()->disconnect (0);
2145 route->output()->disconnect (0);
2147 /* if the route had internal sends sending to it, remove them */
2148 if (route->internal_return()) {
2150 boost::shared_ptr<RouteList> r = routes.reader ();
2151 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2152 boost::shared_ptr<Send> s = (*i)->internal_send_for (route);
2154 (*i)->remove_processor (s);
2159 boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (route);
2160 if (mt && mt->step_editing()) {
2161 if (_step_editors > 0) {
2166 update_latency_compensation (false, false);
2169 /* Re-sort routes to remove the graph's current references to the one that is
2170 * going away, then flush old references out of the graph.
2174 route_graph->clear_other_chain ();
2176 /* get rid of it from the dead wood collection in the route list manager */
2178 /* XXX i think this is unsafe as it currently stands, but i am not sure. (pd, october 2nd, 2006) */
2182 /* try to cause everyone to drop their references */
2184 route->drop_references ();
2186 sync_order_keys (N_("session"));
2188 Route::RemoteControlIDChange(); /* EMIT SIGNAL */
2190 /* save the new state of the world */
2192 if (save_state (_current_snapshot_name)) {
2193 save_history (_current_snapshot_name);
2198 Session::route_mute_changed (void* /*src*/)
2204 Session::route_listen_changed (void* /*src*/, boost::weak_ptr<Route> wpr)
2206 boost::shared_ptr<Route> route = wpr.lock();
2208 error << string_compose (_("programming error: %1"), X_("invalid route weak ptr passed to route_solo_changed")) << endmsg;
2212 if (route->listening()) {
2214 if (Config->get_exclusive_solo()) {
2215 /* new listen: disable all other listen */
2216 shared_ptr<RouteList> r = routes.reader ();
2217 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2218 if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_hidden()) {
2221 (*i)->set_listen (false, this);
2227 } else if (_listen_cnt > 0) {
2233 Session::route_solo_isolated_changed (void* /*src*/, boost::weak_ptr<Route> wpr)
2235 boost::shared_ptr<Route> route = wpr.lock ();
2238 /* should not happen */
2239 error << string_compose (_("programming error: %1"), X_("invalid route weak ptr passed to route_solo_changed")) << endmsg;
2243 bool send_changed = false;
2245 if (route->solo_isolated()) {
2246 if (_solo_isolated_cnt == 0) {
2247 send_changed = true;
2249 _solo_isolated_cnt++;
2250 } else if (_solo_isolated_cnt > 0) {
2251 _solo_isolated_cnt--;
2252 if (_solo_isolated_cnt == 0) {
2253 send_changed = true;
2258 IsolatedChanged (); /* EMIT SIGNAL */
2263 Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_ptr<Route> wpr)
2265 if (!self_solo_change) {
2266 // session doesn't care about changes to soloed-by-others
2270 if (solo_update_disabled) {
2275 boost::shared_ptr<Route> route = wpr.lock ();
2278 /* should not happen */
2279 error << string_compose (_("programming error: %1"), X_("invalid route weak ptr passed to route_solo_changed")) << endmsg;
2283 shared_ptr<RouteList> r = routes.reader ();
2286 if (route->self_soloed()) {
2292 if (delta == 1 && Config->get_exclusive_solo()) {
2293 /* new solo: disable all other solos */
2294 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2295 if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_hidden()) {
2298 (*i)->set_solo (false, this);
2302 solo_update_disabled = true;
2304 RouteList uninvolved;
2306 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2307 bool via_sends_only;
2308 bool in_signal_flow;
2310 if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_hidden()) {
2314 in_signal_flow = false;
2316 if ((*i)->feeds (route, &via_sends_only)) {
2317 if (!via_sends_only) {
2318 if (!route->soloed_by_others_upstream()) {
2319 (*i)->mod_solo_by_others_downstream (delta);
2321 in_signal_flow = true;
2325 if (route->feeds (*i, &via_sends_only)) {
2326 (*i)->mod_solo_by_others_upstream (delta);
2327 in_signal_flow = true;
2330 if (!in_signal_flow) {
2331 uninvolved.push_back (*i);
2335 solo_update_disabled = false;
2336 update_route_solo_state (r);
2338 /* now notify that the mute state of the routes not involved in the signal
2339 pathway of the just-solo-changed route may have altered.
2342 for (RouteList::iterator i = uninvolved.begin(); i != uninvolved.end(); ++i) {
2343 (*i)->mute_changed (this);
2346 SoloChanged (); /* EMIT SIGNAL */
2351 Session::update_route_solo_state (boost::shared_ptr<RouteList> r)
2353 /* now figure out if anything that matters is soloed (or is "listening")*/
2355 bool something_soloed = false;
2356 uint32_t listeners = 0;
2357 uint32_t isolated = 0;
2360 r = routes.reader();
2363 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2364 if (!(*i)->is_master() && !(*i)->is_monitor() && !(*i)->is_hidden() && (*i)->self_soloed()) {
2365 something_soloed = true;
2368 if (!(*i)->is_hidden() && (*i)->listening()) {
2369 if (Config->get_solo_control_is_listen_control()) {
2372 (*i)->set_listen (false, this);
2376 if ((*i)->solo_isolated()) {
2381 if (something_soloed != _non_soloed_outs_muted) {
2382 _non_soloed_outs_muted = something_soloed;
2383 SoloActive (_non_soloed_outs_muted); /* EMIT SIGNAL */
2386 _listen_cnt = listeners;
2388 if (isolated != _solo_isolated_cnt) {
2389 _solo_isolated_cnt = isolated;
2390 IsolatedChanged (); /* EMIT SIGNAL */
2394 boost::shared_ptr<RouteList>
2395 Session::get_routes_with_internal_returns() const
2397 shared_ptr<RouteList> r = routes.reader ();
2398 boost::shared_ptr<RouteList> rl (new RouteList);
2400 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2401 if ((*i)->internal_return ()) {
2409 Session::io_name_is_legal (const std::string& name)
2411 shared_ptr<RouteList> r = routes.reader ();
2413 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2414 if ((*i)->name() == name) {
2418 if ((*i)->has_io_processor_named (name)) {
2427 Session::route_by_name (string name)
2429 shared_ptr<RouteList> r = routes.reader ();
2431 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2432 if ((*i)->name() == name) {
2437 return shared_ptr<Route> ((Route*) 0);
2441 Session::route_by_id (PBD::ID id)
2443 shared_ptr<RouteList> r = routes.reader ();
2445 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2446 if ((*i)->id() == id) {
2451 return shared_ptr<Route> ((Route*) 0);
2455 Session::route_by_remote_id (uint32_t id)
2457 shared_ptr<RouteList> r = routes.reader ();
2459 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2460 if ((*i)->remote_control_id() == id) {
2465 return shared_ptr<Route> ((Route*) 0);
2468 /** If either end of the session range location marker lies inside the current
2469 * session extent, move it to the corresponding session extent.
2472 Session::update_session_range_location_marker ()
2474 if (_state_of_the_state & Loading) {
2478 pair<nframes_t, nframes_t> const ext = get_extent ();
2480 if (_session_range_location == 0) {
2481 /* we don't have a session range yet; use this one (provided it is valid) */
2482 if (ext.first != max_frames) {
2483 add_session_range_location (ext.first, ext.second);
2486 /* update the existing session range */
2487 if (ext.first < _session_range_location->start()) {
2488 _session_range_location->set_start (ext.first);
2492 if (ext.second > _session_range_location->end()) {
2493 _session_range_location->set_end (ext.second);
2500 /** @return Extent of the session's contents; if the session is empty, the first value of
2501 * the pair will equal max_frames.
2503 pair<nframes_t, nframes_t>
2504 Session::get_extent () const
2506 pair<nframes_t, nframes_t> ext (max_frames, 0);
2508 boost::shared_ptr<RouteList> rl = routes.reader ();
2509 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
2510 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
2511 if (!tr || tr->destructive()) {
2512 // ignore tape tracks when getting extents
2516 pair<nframes_t, nframes_t> e = tr->playlist()->get_extent ();
2517 if (e.first < ext.first) {
2518 ext.first = e.first;
2520 if (e.second > ext.second) {
2521 ext.second = e.second;
2528 /* Region management */
2530 boost::shared_ptr<Region>
2531 Session::find_whole_file_parent (boost::shared_ptr<Region const> child) const
2533 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2534 RegionFactory::RegionMap::const_iterator i;
2535 boost::shared_ptr<Region> region;
2537 Glib::Mutex::Lock lm (region_lock);
2539 for (i = regions.begin(); i != regions.end(); ++i) {
2543 if (region->whole_file()) {
2545 if (child->source_equivalent (region)) {
2551 return boost::shared_ptr<Region> ();
2555 Session::destroy_sources (list<boost::shared_ptr<Source> > srcs)
2557 set<boost::shared_ptr<Region> > relevant_regions;
2559 for (list<boost::shared_ptr<Source> >::iterator s = srcs.begin(); s != srcs.end(); ++s) {
2560 RegionFactory::get_regions_using_source (*s, relevant_regions);
2563 cerr << "There are " << relevant_regions.size() << " using " << srcs.size() << " sources" << endl;
2565 for (set<boost::shared_ptr<Region> >::iterator r = relevant_regions.begin(); r != relevant_regions.end(); ) {
2566 set<boost::shared_ptr<Region> >::iterator tmp;
2571 cerr << "Cleanup " << (*r)->name() << " UC = " << (*r).use_count() << endl;
2573 playlists->destroy_region (*r);
2574 RegionFactory::map_remove (*r);
2576 (*r)->drop_sources ();
2577 (*r)->drop_references ();
2579 cerr << "\tdone UC = " << (*r).use_count() << endl;
2581 relevant_regions.erase (r);
2586 for (list<boost::shared_ptr<Source> >::iterator s = srcs.begin(); s != srcs.end(); ) {
2589 Glib::Mutex::Lock ls (source_lock);
2590 /* remove from the main source list */
2591 sources.erase ((*s)->id());
2594 (*s)->mark_for_remove ();
2595 (*s)->drop_references ();
2604 Session::remove_last_capture ()
2606 list<boost::shared_ptr<Source> > srcs;
2608 boost::shared_ptr<RouteList> rl = routes.reader ();
2609 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
2610 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
2615 list<boost::shared_ptr<Source> >& l = tr->last_capture_sources();
2618 srcs.insert (srcs.end(), l.begin(), l.end());
2623 destroy_sources (srcs);
2625 save_state (_current_snapshot_name);
2630 /* Source Management */
2633 Session::add_source (boost::shared_ptr<Source> source)
2635 pair<SourceMap::key_type, SourceMap::mapped_type> entry;
2636 pair<SourceMap::iterator,bool> result;
2638 entry.first = source->id();
2639 entry.second = source;
2642 Glib::Mutex::Lock lm (source_lock);
2643 result = sources.insert (entry);
2646 if (result.second) {
2648 /* yay, new source */
2652 boost::shared_ptr<AudioFileSource> afs;
2654 if ((afs = boost::dynamic_pointer_cast<AudioFileSource>(source)) != 0) {
2655 if (Config->get_auto_analyse_audio()) {
2656 Analyser::queue_source_for_analysis (source, false);
2663 Session::remove_source (boost::weak_ptr<Source> src)
2665 SourceMap::iterator i;
2666 boost::shared_ptr<Source> source = src.lock();
2673 Glib::Mutex::Lock lm (source_lock);
2675 if ((i = sources.find (source->id())) != sources.end()) {
2676 cerr << "Removing source " << source->name() << endl;
2681 if (!_state_of_the_state & InCleanup) {
2683 /* save state so we don't end up with a session file
2684 referring to non-existent sources.
2687 save_state (_current_snapshot_name);
2691 boost::shared_ptr<Source>
2692 Session::source_by_id (const PBD::ID& id)
2694 Glib::Mutex::Lock lm (source_lock);
2695 SourceMap::iterator i;
2696 boost::shared_ptr<Source> source;
2698 if ((i = sources.find (id)) != sources.end()) {
2705 boost::shared_ptr<Source>
2706 Session::source_by_path_and_channel (const Glib::ustring& path, uint16_t chn)
2708 Glib::Mutex::Lock lm (source_lock);
2710 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2711 boost::shared_ptr<AudioFileSource> afs
2712 = boost::dynamic_pointer_cast<AudioFileSource>(i->second);
2714 if (afs && afs->path() == path && chn == afs->channel()) {
2718 return boost::shared_ptr<Source>();
2723 Session::change_source_path_by_name (string path, string oldname, string newname, bool destructive)
2726 string old_basename = PBD::basename_nosuffix (oldname);
2727 string new_legalized = legalize_for_path (newname);
2729 /* note: we know (or assume) the old path is already valid */
2733 /* destructive file sources have a name of the form:
2735 /path/to/Tnnnn-NAME(%[LR])?.wav
2737 the task here is to replace NAME with the new name.
2742 string::size_type dash;
2744 dir = Glib::path_get_dirname (path);
2745 path = Glib::path_get_basename (path);
2747 /* '-' is not a legal character for the NAME part of the path */
2749 if ((dash = path.find_last_of ('-')) == string::npos) {
2753 prefix = path.substr (0, dash);
2757 path += new_legalized;
2758 path += native_header_format_extension (config.get_native_file_header_format(), DataType::AUDIO);
2760 path = Glib::build_filename (dir, path);
2764 /* non-destructive file sources have a name of the form:
2766 /path/to/NAME-nnnnn(%[LR])?.ext
2768 the task here is to replace NAME with the new name.
2773 string::size_type dash;
2774 string::size_type postfix;
2776 dir = Glib::path_get_dirname (path);
2777 path = Glib::path_get_basename (path);
2779 /* '-' is not a legal character for the NAME part of the path */
2781 if ((dash = path.find_last_of ('-')) == string::npos) {
2785 suffix = path.substr (dash+1);
2787 // Suffix is now everything after the dash. Now we need to eliminate
2788 // the nnnnn part, which is done by either finding a '%' or a '.'
2790 postfix = suffix.find_last_of ("%");
2791 if (postfix == string::npos) {
2792 postfix = suffix.find_last_of ('.');
2795 if (postfix != string::npos) {
2796 suffix = suffix.substr (postfix);
2798 error << "Logic error in Session::change_source_path_by_name(), please report" << endl;
2802 const uint32_t limit = 10000;
2803 char buf[PATH_MAX+1];
2805 for (uint32_t cnt = 1; cnt <= limit; ++cnt) {
2807 snprintf (buf, sizeof(buf), "%s-%u%s", newname.c_str(), cnt, suffix.c_str());
2809 if (!matching_unsuffixed_filename_exists_in (dir, buf)) {
2810 path = Glib::build_filename (dir, buf);
2818 fatal << string_compose (_("FATAL ERROR! Could not find a suitable version of %1 for a rename"),
2827 /** Return the full path (in some session directory) for a new within-session source.
2828 * \a name must be a session-unique name that does not contain slashes
2829 * (e.g. as returned by new_*_source_name)
2832 Session::new_source_path_from_name (DataType type, const string& name, bool as_stub)
2834 assert(name.find("/") == string::npos);
2836 SessionDirectory sdir(get_best_session_directory_for_new_source());
2839 if (type == DataType::AUDIO) {
2840 p = (as_stub ? sdir.sound_stub_path() : sdir.sound_path());
2841 } else if (type == DataType::MIDI) {
2842 p = (as_stub ? sdir.midi_stub_path() : sdir.midi_path());
2844 error << "Unknown source type, unable to create file path" << endmsg;
2849 return p.to_string();
2853 Session::peak_path (Glib::ustring base) const
2855 sys::path peakfile_path(_session_dir->peak_path());
2856 peakfile_path /= basename_nosuffix (base) + peakfile_suffix;
2857 return peakfile_path.to_string();
2860 /** Return a unique name based on \a base for a new internal audio source */
2862 Session::new_audio_source_name (const string& base, uint32_t nchan, uint32_t chan, bool destructive)
2865 char buf[PATH_MAX+1];
2866 const uint32_t limit = 10000;
2868 string ext = native_header_format_extension (config.get_native_file_header_format(), DataType::AUDIO);
2871 legalized = legalize_for_path (base);
2873 // Find a "version" of the base name that doesn't exist in any of the possible directories.
2874 for (cnt = (destructive ? ++destructive_index : 1); cnt <= limit; ++cnt) {
2876 vector<space_and_path>::iterator i;
2877 uint32_t existing = 0;
2879 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2884 snprintf (buf, sizeof(buf), "T%04d-%s%s",
2885 cnt, legalized.c_str(), ext.c_str());
2886 } else if (nchan == 2) {
2888 snprintf (buf, sizeof(buf), "T%04d-%s%%L%s",
2889 cnt, legalized.c_str(), ext.c_str());
2891 snprintf (buf, sizeof(buf), "T%04d-%s%%R%s",
2892 cnt, legalized.c_str(), ext.c_str());
2894 } else if (nchan < 26) {
2895 snprintf (buf, sizeof(buf), "T%04d-%s%%%c%s",
2896 cnt, legalized.c_str(), 'a' + chan, ext.c_str());
2898 snprintf (buf, sizeof(buf), "T%04d-%s%s",
2899 cnt, legalized.c_str(), ext.c_str());
2905 snprintf (buf, sizeof(buf), "%s-%u%s", legalized.c_str(), cnt, ext.c_str());
2906 } else if (nchan == 2) {
2908 snprintf (buf, sizeof(buf), "%s-%u%%L%s", legalized.c_str(), cnt, ext.c_str());
2910 snprintf (buf, sizeof(buf), "%s-%u%%R%s", legalized.c_str(), cnt, ext.c_str());
2912 } else if (nchan < 26) {
2913 snprintf (buf, sizeof(buf), "%s-%u%%%c%s", legalized.c_str(), cnt, 'a' + chan, ext.c_str());
2915 snprintf (buf, sizeof(buf), "%s-%u%s", legalized.c_str(), cnt, ext.c_str());
2919 SessionDirectory sdir((*i).path);
2921 string spath = sdir.sound_path().to_string();
2922 string spath_stubs = sdir.sound_stub_path().to_string();
2924 /* note that we search *without* the extension so that
2925 we don't end up both "Audio 1-1.wav" and "Audio 1-1.caf"
2926 in the event that this new name is required for
2927 a file format change.
2930 if (matching_unsuffixed_filename_exists_in (spath, buf) ||
2931 matching_unsuffixed_filename_exists_in (spath_stubs, buf)) {
2937 if (existing == 0) {
2942 error << string_compose(
2943 _("There are already %1 recordings for %2, which I consider too many."),
2944 limit, base) << endmsg;
2946 throw failed_constructor();
2950 return Glib::path_get_basename (buf);
2953 /** Create a new within-session audio source */
2954 boost::shared_ptr<AudioFileSource>
2955 Session::create_audio_source_for_session (size_t n_chans, string const & n, uint32_t chan, bool destructive, bool as_stub)
2957 const string name = new_audio_source_name (n, n_chans, chan, destructive);
2958 const string path = new_source_path_from_name(DataType::AUDIO, name, as_stub);
2960 return boost::dynamic_pointer_cast<AudioFileSource> (
2961 SourceFactory::createWritable (DataType::AUDIO, *this, path, destructive, frame_rate()));
2964 /** Return a unique name based on \a base for a new internal MIDI source */
2966 Session::new_midi_source_name (const string& base)
2969 char buf[PATH_MAX+1];
2970 const uint32_t limit = 10000;
2974 legalized = legalize_for_path (base);
2976 // Find a "version" of the file name that doesn't exist in any of the possible directories.
2977 for (cnt = 1; cnt <= limit; ++cnt) {
2979 vector<space_and_path>::iterator i;
2980 uint32_t existing = 0;
2982 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2984 SessionDirectory sdir((*i).path);
2986 sys::path p = sdir.midi_path();
2989 snprintf (buf, sizeof(buf), "%s-%u.mid", p.to_string().c_str(), cnt);
2991 if (sys::exists (buf)) {
2996 if (existing == 0) {
3001 error << string_compose(
3002 _("There are already %1 recordings for %2, which I consider too many."),
3003 limit, base) << endmsg;
3005 throw failed_constructor();
3009 return Glib::path_get_basename(buf);
3013 /** Create a new within-session MIDI source */
3014 boost::shared_ptr<MidiSource>
3015 Session::create_midi_source_for_session (Track* track, string const & n, bool as_stub)
3017 /* try to use the existing write source for the track, to keep numbering sane
3021 /*MidiTrack* mt = dynamic_cast<Track*> (track);
3025 list<boost::shared_ptr<Source> > l = track->steal_write_sources ();
3028 assert (boost::dynamic_pointer_cast<MidiSource> (l.front()));
3029 return boost::dynamic_pointer_cast<MidiSource> (l.front());
3033 const string name = new_midi_source_name (n);
3034 const string path = new_source_path_from_name (DataType::MIDI, name, as_stub);
3036 return boost::dynamic_pointer_cast<SMFSource> (
3037 SourceFactory::createWritable (
3038 DataType::MIDI, *this, path, false, frame_rate()));
3043 Session::add_playlist (boost::shared_ptr<Playlist> playlist, bool unused)
3045 if (playlist->hidden()) {
3049 playlists->add (playlist);
3052 playlist->release();
3059 Session::remove_playlist (boost::weak_ptr<Playlist> weak_playlist)
3061 if (_state_of_the_state & Deletion) {
3065 boost::shared_ptr<Playlist> playlist (weak_playlist.lock());
3071 playlists->remove (playlist);
3077 Session::set_audition (boost::shared_ptr<Region> r)
3079 pending_audition_region = r;
3080 add_post_transport_work (PostTransportAudition);
3081 _butler->schedule_transport_work ();
3085 Session::audition_playlist ()
3087 SessionEvent* ev = new SessionEvent (SessionEvent::Audition, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
3088 ev->region.reset ();
3093 Session::non_realtime_set_audition ()
3095 if (!pending_audition_region) {
3096 auditioner->audition_current_playlist ();
3098 auditioner->audition_region (pending_audition_region);
3099 pending_audition_region.reset ();
3101 AuditionActive (true); /* EMIT SIGNAL */
3105 Session::audition_region (boost::shared_ptr<Region> r)
3107 SessionEvent* ev = new SessionEvent (SessionEvent::Audition, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
3113 Session::cancel_audition ()
3115 if (auditioner->auditioning()) {
3116 auditioner->cancel_audition ();
3117 AuditionActive (false); /* EMIT SIGNAL */
3122 Session::RoutePublicOrderSorter::operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b)
3124 if (a->is_monitor()) {
3127 if (b->is_monitor()) {
3130 return a->order_key(N_("signal")) < b->order_key(N_("signal"));
3134 Session::is_auditioning () const
3136 /* can be called before we have an auditioner object */
3138 return auditioner->auditioning();
3145 Session::graph_reordered ()
3147 /* don't do this stuff if we are setting up connections
3148 from a set_state() call or creating new tracks. Ditto for deletion.
3151 if (_state_of_the_state & (InitialConnecting|Deletion)) {
3155 /* every track/bus asked for this to be handled but it was deferred because
3156 we were connecting. do it now.
3159 request_input_change_handling ();
3163 /* force all diskstreams to update their capture offset values to
3164 reflect any changes in latencies within the graph.
3167 boost::shared_ptr<RouteList> rl = routes.reader ();
3168 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
3169 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
3171 tr->set_capture_offset ();
3177 Session::available_capture_duration ()
3179 float sample_bytes_on_disk = 4.0; // keep gcc happy
3181 switch (config.get_native_file_data_format()) {
3183 sample_bytes_on_disk = 4.0;
3187 sample_bytes_on_disk = 3.0;
3191 sample_bytes_on_disk = 2.0;
3195 /* impossible, but keep some gcc versions happy */
3196 fatal << string_compose (_("programming error: %1"),
3197 X_("illegal native file data format"))
3202 double scale = 4096.0 / sample_bytes_on_disk;
3204 if (_total_free_4k_blocks * scale > (double) max_frames) {
3208 return (nframes_t) floor (_total_free_4k_blocks * scale);
3212 Session::add_bundle (shared_ptr<Bundle> bundle)
3215 RCUWriter<BundleList> writer (_bundles);
3216 boost::shared_ptr<BundleList> b = writer.get_copy ();
3217 b->push_back (bundle);
3220 BundleAdded (bundle); /* EMIT SIGNAL */
3226 Session::remove_bundle (shared_ptr<Bundle> bundle)
3228 bool removed = false;
3231 RCUWriter<BundleList> writer (_bundles);
3232 boost::shared_ptr<BundleList> b = writer.get_copy ();
3233 BundleList::iterator i = find (b->begin(), b->end(), bundle);
3235 if (i != b->end()) {
3242 BundleRemoved (bundle); /* EMIT SIGNAL */
3249 Session::bundle_by_name (string name) const
3251 boost::shared_ptr<BundleList> b = _bundles.reader ();
3253 for (BundleList::const_iterator i = b->begin(); i != b->end(); ++i) {
3254 if ((*i)->name() == name) {
3259 return boost::shared_ptr<Bundle> ();
3263 Session::tempo_map_changed (const PropertyChange&)
3267 playlists->update_after_tempo_map_change ();
3269 _locations->apply (*this, &Session::update_locations_after_tempo_map_change);
3275 Session::update_locations_after_tempo_map_change (Locations::LocationList& loc)
3277 for (Locations::LocationList::iterator i = loc.begin(); i != loc.end(); ++i) {
3278 (*i)->recompute_frames_from_bbt ();
3282 /** Ensures that all buffers (scratch, send, silent, etc) are allocated for
3283 * the given count with the current block size.
3286 Session::ensure_buffers (ChanCount howmany)
3288 BufferManager::ensure_buffers (howmany);
3292 Session::ensure_buffer_set(BufferSet& buffers, const ChanCount& count)
3294 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
3295 buffers.ensure_buffers(*t, count.get(*t), _engine.raw_buffer_size(*t));
3300 Session::next_insert_id ()
3302 /* this doesn't really loop forever. just think about it */
3305 for (boost::dynamic_bitset<uint32_t>::size_type n = 0; n < insert_bitset.size(); ++n) {
3306 if (!insert_bitset[n]) {
3307 insert_bitset[n] = true;
3313 /* none available, so resize and try again */
3315 insert_bitset.resize (insert_bitset.size() + 16, false);
3320 Session::next_send_id ()
3322 /* this doesn't really loop forever. just think about it */
3325 for (boost::dynamic_bitset<uint32_t>::size_type n = 0; n < send_bitset.size(); ++n) {
3326 if (!send_bitset[n]) {
3327 send_bitset[n] = true;
3333 /* none available, so resize and try again */
3335 send_bitset.resize (send_bitset.size() + 16, false);
3340 Session::next_return_id ()
3342 /* this doesn't really loop forever. just think about it */
3345 for (boost::dynamic_bitset<uint32_t>::size_type n = 0; n < return_bitset.size(); ++n) {
3346 if (!return_bitset[n]) {
3347 return_bitset[n] = true;
3353 /* none available, so resize and try again */
3355 return_bitset.resize (return_bitset.size() + 16, false);
3360 Session::mark_send_id (uint32_t id)
3362 if (id >= send_bitset.size()) {
3363 send_bitset.resize (id+16, false);
3365 if (send_bitset[id]) {
3366 warning << string_compose (_("send ID %1 appears to be in use already"), id) << endmsg;
3368 send_bitset[id] = true;
3372 Session::mark_return_id (uint32_t id)
3374 if (id >= return_bitset.size()) {
3375 return_bitset.resize (id+16, false);
3377 if (return_bitset[id]) {
3378 warning << string_compose (_("return ID %1 appears to be in use already"), id) << endmsg;
3380 return_bitset[id] = true;
3384 Session::mark_insert_id (uint32_t id)
3386 if (id >= insert_bitset.size()) {
3387 insert_bitset.resize (id+16, false);
3389 if (insert_bitset[id]) {
3390 warning << string_compose (_("insert ID %1 appears to be in use already"), id) << endmsg;
3392 insert_bitset[id] = true;
3396 Session::unmark_send_id (uint32_t id)
3398 if (id < send_bitset.size()) {
3399 send_bitset[id] = false;
3404 Session::unmark_return_id (uint32_t id)
3406 if (id < return_bitset.size()) {
3407 return_bitset[id] = false;
3412 Session::unmark_insert_id (uint32_t id)
3414 if (id < insert_bitset.size()) {
3415 insert_bitset[id] = false;
3420 /* Named Selection management */
3422 boost::shared_ptr<NamedSelection>
3423 Session::named_selection_by_name (string name)
3425 Glib::Mutex::Lock lm (named_selection_lock);
3426 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
3427 if ((*i)->name == name) {
3431 return boost::shared_ptr<NamedSelection>();
3435 Session::add_named_selection (boost::shared_ptr<NamedSelection> named_selection)
3438 Glib::Mutex::Lock lm (named_selection_lock);
3439 named_selections.insert (named_selections.begin(), named_selection);
3444 NamedSelectionAdded (); /* EMIT SIGNAL */
3448 Session::remove_named_selection (boost::shared_ptr<NamedSelection> named_selection)
3450 bool removed = false;
3453 Glib::Mutex::Lock lm (named_selection_lock);
3455 NamedSelectionList::iterator i = find (named_selections.begin(), named_selections.end(), named_selection);
3457 if (i != named_selections.end()) {
3458 named_selections.erase (i);
3465 NamedSelectionRemoved (); /* EMIT SIGNAL */
3470 Session::reset_native_file_format ()
3472 boost::shared_ptr<RouteList> rl = routes.reader ();
3473 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
3474 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
3476 /* don't save state as we do this, there's no point
3479 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
3480 tr->reset_write_sources (false);
3481 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
3487 Session::route_name_unique (string n) const
3489 shared_ptr<RouteList> r = routes.reader ();
3491 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
3492 if ((*i)->name() == n) {
3501 Session::route_name_internal (string n) const
3503 if (auditioner && auditioner->name() == n) {
3507 if (_click_io && _click_io->name() == n) {
3515 Session::freeze_all (InterThreadInfo& itt)
3517 shared_ptr<RouteList> r = routes.reader ();
3519 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
3521 boost::shared_ptr<Track> t;
3523 if ((t = boost::dynamic_pointer_cast<Track>(*i)) != 0) {
3524 /* XXX this is wrong because itt.progress will keep returning to zero at the start
3534 boost::shared_ptr<Region>
3535 Session::write_one_track (AudioTrack& track, nframes_t start, nframes_t end,
3536 bool /*overwrite*/, vector<boost::shared_ptr<Source> >& srcs,
3537 InterThreadInfo& itt, bool enable_processing)
3539 boost::shared_ptr<Region> result;
3540 boost::shared_ptr<Playlist> playlist;
3541 boost::shared_ptr<AudioFileSource> fsource;
3543 char buf[PATH_MAX+1];
3544 ChanCount nchans(track.n_channels());
3546 nframes_t this_chunk;
3549 SessionDirectory sdir(get_best_session_directory_for_new_source ());
3550 const string sound_dir = sdir.sound_path().to_string();
3551 nframes_t len = end - start;
3555 error << string_compose (_("Cannot write a range where end <= start (e.g. %1 <= %2)"),
3556 end, start) << endmsg;
3560 const nframes_t chunk_size = (256 * 1024)/4;
3562 // block all process callback handling
3564 block_processing ();
3566 /* call tree *MUST* hold route_lock */
3568 if ((playlist = track.playlist()) == 0) {
3572 /* external redirects will be a problem */
3574 if (track.has_external_redirects()) {
3578 ext = native_header_format_extension (config.get_native_file_header_format(), DataType::AUDIO);
3580 for (uint32_t chan_n=0; chan_n < nchans.n_audio(); ++chan_n) {
3582 for (x = 0; x < 99999; ++x) {
3583 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());
3584 if (access (buf, F_OK) != 0) {
3590 error << string_compose (_("too many bounced versions of playlist \"%1\""), playlist->name()) << endmsg;
3595 fsource = boost::dynamic_pointer_cast<AudioFileSource> (
3596 SourceFactory::createWritable (DataType::AUDIO, *this, buf, false, frame_rate()));
3599 catch (failed_constructor& err) {
3600 error << string_compose (_("cannot create new audio file \"%1\" for %2"), buf, track.name()) << endmsg;
3604 srcs.push_back (fsource);
3607 /* XXX need to flush all redirects */
3612 /* create a set of reasonably-sized buffers */
3613 buffers.ensure_buffers(DataType::AUDIO, nchans.n_audio(), chunk_size);
3614 buffers.set_count(nchans);
3616 for (vector<boost::shared_ptr<Source> >::iterator src=srcs.begin(); src != srcs.end(); ++src) {
3617 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
3619 afs->prepare_for_peakfile_writes ();
3622 while (to_do && !itt.cancel) {
3624 this_chunk = min (to_do, chunk_size);
3626 if (track.export_stuff (buffers, start, this_chunk, enable_processing)) {
3631 for (vector<boost::shared_ptr<Source> >::iterator src=srcs.begin(); src != srcs.end(); ++src, ++n) {
3632 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
3635 if (afs->write (buffers.get_audio(n).data(), this_chunk) != this_chunk) {
3641 start += this_chunk;
3642 to_do -= this_chunk;
3644 itt.progress = (float) (1.0 - ((double) to_do / len));
3653 xnow = localtime (&now);
3655 for (vector<boost::shared_ptr<Source> >::iterator src=srcs.begin(); src != srcs.end(); ++src) {
3656 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
3659 afs->update_header (position, *xnow, now);
3660 afs->flush_header ();
3664 /* construct a region to represent the bounced material */
3668 plist.add (Properties::start, 0);
3669 plist.add (Properties::length, srcs.front()->length(srcs.front()->timeline_position()));
3670 plist.add (Properties::name, region_name_from_path (srcs.front()->name(), true));
3672 result = RegionFactory::create (srcs, plist);
3678 for (vector<boost::shared_ptr<Source> >::iterator src = srcs.begin(); src != srcs.end(); ++src) {
3679 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
3682 afs->mark_for_remove ();
3685 (*src)->drop_references ();
3689 for (vector<boost::shared_ptr<Source> >::iterator src = srcs.begin(); src != srcs.end(); ++src) {
3690 boost::shared_ptr<AudioFileSource> afs = boost::dynamic_pointer_cast<AudioFileSource>(*src);
3693 afs->done_with_peakfile_writes ();
3697 unblock_processing ();
3703 Session::gain_automation_buffer() const
3705 return ProcessThread::gain_automation_buffer ();
3709 Session::pan_automation_buffer() const
3711 return ProcessThread::pan_automation_buffer ();
3715 Session::get_silent_buffers (ChanCount count)
3717 return ProcessThread::get_silent_buffers (count);
3719 assert(_silent_buffers->available() >= count);
3720 _silent_buffers->set_count(count);
3722 for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
3723 for (size_t i= 0; i < count.get(*t); ++i) {
3724 _silent_buffers->get(*t, i).clear();
3728 return *_silent_buffers;
3733 Session::get_scratch_buffers (ChanCount count)
3735 return ProcessThread::get_scratch_buffers (count);
3737 if (count != ChanCount::ZERO) {
3738 assert(_scratch_buffers->available() >= count);
3739 _scratch_buffers->set_count(count);
3741 _scratch_buffers->set_count (_scratch_buffers->available());
3744 return *_scratch_buffers;
3749 Session::get_mix_buffers (ChanCount count)
3751 return ProcessThread::get_mix_buffers (count);
3753 assert(_mix_buffers->available() >= count);
3754 _mix_buffers->set_count(count);
3755 return *_mix_buffers;
3760 Session::ntracks () const
3763 shared_ptr<RouteList> r = routes.reader ();
3765 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
3766 if (boost::dynamic_pointer_cast<Track> (*i)) {
3775 Session::nbusses () const
3778 shared_ptr<RouteList> r = routes.reader ();
3780 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
3781 if (boost::dynamic_pointer_cast<Track>(*i) == 0) {
3790 Session::add_automation_list(AutomationList *al)
3792 automation_lists[al->id()] = al;
3796 Session::sync_order_keys (std::string const & base)
3798 if (deletion_in_progress()) {
3802 if (!Config->get_sync_all_route_ordering()) {
3803 /* leave order keys as they are */
3807 boost::shared_ptr<RouteList> r = routes.reader ();
3809 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
3810 (*i)->sync_order_keys (base);
3813 Route::SyncOrderKeys (base); // EMIT SIGNAL
3815 /* this might not do anything */
3817 set_remote_control_ids ();
3820 /** @return true if there is at least one record-enabled track, otherwise false */
3822 Session::have_rec_enabled_track () const
3824 return g_atomic_int_get (&_have_rec_enabled_track) == 1;
3827 /** Update the state of our rec-enabled tracks flag */
3829 Session::update_have_rec_enabled_track ()
3831 boost::shared_ptr<RouteList> rl = routes.reader ();
3832 RouteList::iterator i = rl->begin();
3833 while (i != rl->end ()) {
3835 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
3836 if (tr && tr->record_enabled ()) {
3843 int const old = g_atomic_int_get (&_have_rec_enabled_track);
3845 g_atomic_int_set (&_have_rec_enabled_track, i != rl->end () ? 1 : 0);
3847 if (g_atomic_int_get (&_have_rec_enabled_track) != old) {
3848 RecordStateChanged (); /* EMIT SIGNAL */
3853 Session::listen_position_changed ()
3857 switch (Config->get_listen_position()) {
3858 case AfterFaderListen:
3862 case PreFaderListen:
3867 boost::shared_ptr<RouteList> r = routes.reader ();
3869 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
3870 (*i)->put_monitor_send_at (p);
3875 Session::solo_control_mode_changed ()
3877 /* cancel all solo or all listen when solo control mode changes */
3880 set_solo (get_routes(), false);
3881 } else if (listening()) {
3882 set_listen (get_routes(), false);
3886 /** Called when anything about any of our route groups changes (membership, state etc.) */
3888 Session::route_group_changed ()
3890 RouteGroupChanged (); /* EMIT SIGNAL */
3894 Session::get_available_sync_options () const
3896 vector<SyncSource> ret;
3898 ret.push_back (JACK);
3899 ret.push_back (MTC);
3900 ret.push_back (MIDIClock);
3905 boost::shared_ptr<RouteList>
3906 Session::get_routes_with_regions_at (nframes64_t const p) const
3908 shared_ptr<RouteList> r = routes.reader ();
3909 shared_ptr<RouteList> rl (new RouteList);
3911 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
3912 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
3917 boost::shared_ptr<Playlist> pl = tr->playlist ();
3922 if (pl->has_region_at (p)) {
3931 Session::goto_end ()
3933 if (_session_range_location) {
3934 request_locate (_session_range_location->end(), false);
3936 request_locate (0, false);
3941 Session::goto_start ()
3943 if (_session_range_location) {
3944 request_locate (_session_range_location->start(), false);
3946 request_locate (0, false);
3951 Session::set_session_start (nframes_t start)
3953 if (_session_range_location) {
3954 _session_range_location->set_start (start);
3956 add_session_range_location (start, start);
3961 Session::set_session_end (nframes_t end)
3963 if (_session_range_location) {
3964 _session_range_location->set_end (end);
3966 add_session_range_location (end, end);
3971 Session::current_start_frame () const
3973 return _session_range_location ? _session_range_location->start() : 0;
3977 Session::current_end_frame () const
3979 return _session_range_location ? _session_range_location->end() : 0;
3983 Session::add_session_range_location (nframes_t start, nframes_t end)
3985 _session_range_location = new Location (*this, start, end, _("session"), Location::IsSessionRange);
3986 _locations->add (_session_range_location);
3989 /** Called when one of our routes' order keys has changed */
3991 Session::route_order_key_changed ()
3993 RouteOrderKeyChanged (); /* EMIT SIGNAL */
3997 Session::step_edit_status_change (bool yn)
4003 send = (_step_editors == 0);
4008 send = (_step_editors == 1);
4011 if (_step_editors > 0) {
4017 StepEditStatusChange (val);