2 Copyright (C) 1999-2002 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include <sigc++/bind.h>
27 #include <cstdio> /* snprintf(3) ... grrr */
42 #include <sys/param.h>
43 #include <sys/mount.h>
47 #include <glibmm/thread.h>
49 #include <midi++/mmc.h>
50 #include <midi++/port.h>
52 #include <pbd/error.h>
53 #include <pbd/pathscanner.h>
54 #include <pbd/pthread_utils.h>
55 #include <pbd/strsplit.h>
56 #include <pbd/stacktrace.h>
57 #include <pbd/copyfile.h>
59 #include <ardour/audioengine.h>
60 #include <ardour/configuration.h>
61 #include <ardour/session.h>
62 #include <ardour/audio_diskstream.h>
63 #include <ardour/utils.h>
64 #include <ardour/audioplaylist.h>
65 #include <ardour/audiofilesource.h>
66 #include <ardour/silentfilesource.h>
67 #include <ardour/sndfilesource.h>
68 #include <ardour/sndfile_helpers.h>
69 #include <ardour/auditioner.h>
70 #include <ardour/export.h>
71 #include <ardour/redirect.h>
72 #include <ardour/send.h>
73 #include <ardour/insert.h>
74 #include <ardour/connection.h>
75 #include <ardour/slave.h>
76 #include <ardour/tempo.h>
77 #include <ardour/audio_track.h>
78 #include <ardour/cycle_timer.h>
79 #include <ardour/utils.h>
80 #include <ardour/named_selection.h>
81 #include <ardour/version.h>
82 #include <ardour/location.h>
83 #include <ardour/audioregion.h>
84 #include <ardour/crossfade.h>
85 #include <ardour/control_protocol_manager.h>
86 #include <ardour/region_factory.h>
87 #include <ardour/source_factory.h>
88 #include <ardour/playlist_factory.h>
90 #include <control_protocol/control_protocol.h>
96 using namespace ARDOUR;
100 Session::first_stage_init (string fullpath, string snapshot_name)
102 if (fullpath.length() == 0) {
104 throw failed_constructor();
107 char buf[PATH_MAX+1];
108 if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
109 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
111 throw failed_constructor();
116 if (_path[_path.length()-1] != '/') {
120 set_history_depth (Config->get_history_depth());
123 /* these two are just provisional settings. set_state()
124 will likely override them.
127 _name = _current_snapshot_name = snapshot_name;
129 _current_frame_rate = _engine.frame_rate ();
130 _nominal_frame_rate = _current_frame_rate;
131 _base_frame_rate = _current_frame_rate;
133 _tempo_map = new TempoMap (_current_frame_rate);
134 _tempo_map->StateChanged.connect (mem_fun (*this, &Session::tempo_map_changed));
136 g_atomic_int_set (&processing_prohibited, 0);
138 _transport_speed = 0;
139 _last_transport_speed = 0;
140 auto_play_legal = false;
141 transport_sub_state = 0;
142 _transport_frame = 0;
144 _requested_return_frame = -1;
145 end_location = new Location (0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
146 start_location = new Location (0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart)));
147 _end_location_is_free = true;
148 g_atomic_int_set (&_record_status, Disabled);
149 loop_changing = false;
151 _last_roll_location = 0;
152 _last_record_location = 0;
153 pending_locate_frame = 0;
154 pending_locate_roll = false;
155 pending_locate_flush = false;
156 dstream_buffer_size = 0;
158 state_was_pending = false;
160 outbound_mtc_smpte_frame = 0;
161 next_quarter_frame_to_send = -1;
162 current_block_size = 0;
163 solo_update_disabled = false;
164 currently_soloing = false;
165 _have_captured = false;
166 _worst_output_latency = 0;
167 _worst_input_latency = 0;
168 _worst_track_latency = 0;
169 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
173 butler_mixdown_buffer = 0;
174 butler_gain_buffer = 0;
176 session_send_mmc = false;
177 session_send_mtc = false;
178 post_transport_work = PostTransportWork (0);
179 g_atomic_int_set (&butler_should_do_transport_work, 0);
180 g_atomic_int_set (&butler_active, 0);
181 g_atomic_int_set (&_playback_load, 100);
182 g_atomic_int_set (&_capture_load, 100);
183 g_atomic_int_set (&_playback_load_min, 100);
184 g_atomic_int_set (&_capture_load_min, 100);
187 _gain_automation_buffer = 0;
188 _pan_automation_buffer = 0;
190 pending_abort = false;
191 destructive_index = 0;
193 first_file_data_format_reset = true;
194 first_file_header_format_reset = true;
195 butler_thread = (pthread_t) 0;
196 midi_thread = (pthread_t) 0;
198 AudioDiskstream::allocate_working_buffers();
200 /* default short fade = 15ms */
202 Crossfade::set_short_xfade_length ((nframes_t) floor (Config->get_short_xfade_seconds() * frame_rate()));
203 SndFileSource::setup_standard_crossfades (frame_rate());
205 last_mmc_step.tv_sec = 0;
206 last_mmc_step.tv_usec = 0;
209 /* click sounds are unset by default, which causes us to internal
210 waveforms for clicks.
214 click_emphasis_data = 0;
216 click_emphasis_length = 0;
219 process_function = &Session::process_with_events;
221 if (Config->get_use_video_sync()) {
222 waiting_for_sync_offset = true;
224 waiting_for_sync_offset = false;
229 _smpte_offset_negative = true;
230 last_smpte_valid = false;
231 af_last_transport_speed = 0.0;
236 last_rr_session_dir = session_dirs.begin();
237 refresh_disk_space ();
239 // set_default_fade (0.2, 5.0); /* steepness, millisecs */
243 average_slave_delta = 1800; // !!! why 1800 ????
244 have_first_delta_accumulator = false;
245 delta_accumulator_cnt = 0;
246 slave_state = Stopped;
248 _engine.GraphReordered.connect (mem_fun (*this, &Session::graph_reordered));
250 /* These are all static "per-class" signals */
252 RegionFactory::CheckNewRegion.connect (mem_fun (*this, &Session::add_region));
253 SourceFactory::SourceCreated.connect (mem_fun (*this, &Session::add_source));
254 PlaylistFactory::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist));
255 Redirect::RedirectCreated.connect (mem_fun (*this, &Session::add_redirect));
256 NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection));
257 AutomationList::AutomationListCreated.connect (mem_fun (*this, &Session::add_automation_list));
259 Controllable::Destroyed.connect (mem_fun (*this, &Session::remove_controllable));
261 IO::MoreOutputs.connect (mem_fun (*this, &Session::ensure_passthru_buffers));
263 /* stop IO objects from doing stuff until we're ready for them */
265 IO::disable_panners ();
266 IO::disable_ports ();
267 IO::disable_connecting ();
271 Session::second_stage_init (bool new_session)
273 AudioFileSource::set_peak_dir (peak_dir());
276 if (load_state (_current_snapshot_name)) {
279 remove_empty_sounds ();
282 if (start_butler_thread()) {
286 if (start_midi_thread ()) {
290 // set_state() will call setup_raid_path(), but if it's a new session we need
291 // to call setup_raid_path() here.
294 if (set_state (*state_tree->root())) {
298 setup_raid_path(_path);
301 /* we can't save till after ::when_engine_running() is called,
302 because otherwise we save state with no connections made.
303 therefore, we reset _state_of_the_state because ::set_state()
304 will have cleared it.
306 we also have to include Loading so that any events that get
307 generated between here and the end of ::when_engine_running()
308 will be processed directly rather than queued.
311 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
314 _locations.changed.connect (mem_fun (this, &Session::locations_changed));
315 _locations.added.connect (mem_fun (this, &Session::locations_added));
316 setup_click_sounds (0);
317 setup_midi_control ();
319 /* Pay attention ... */
321 _engine.Halted.connect (mem_fun (*this, &Session::engine_halted));
322 _engine.Xrun.connect (mem_fun (*this, &Session::xrun_recovery));
325 when_engine_running();
328 /* handle this one in a different way than all others, so that its clear what happened */
330 catch (AudioEngine::PortRegistrationFailure& err) {
339 BootMessage (_("Reset Remote Controls"));
341 send_full_time_code ();
342 _engine.transport_locate (0);
343 deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
344 deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
346 /* initial program change will be delivered later; see ::config_changed() */
348 BootMessage (_("Reset Control Protocols"));
350 ControlProtocolManager::instance().set_session (*this);
353 _end_location_is_free = true;
355 _end_location_is_free = false;
358 _state_of_the_state = Clean;
360 DirtyChanged (); /* EMIT SIGNAL */
362 if (state_was_pending) {
363 save_state (_current_snapshot_name);
364 remove_pending_capture_state ();
365 state_was_pending = false;
368 BootMessage (_("Session loading complete"));
374 Session::raid_path () const
378 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
383 return path.substr (0, path.length() - 1); // drop final colon
387 Session::setup_raid_path (string path)
389 string::size_type colon;
393 string::size_type len = path.length();
398 if (path.length() == 0) {
402 session_dirs.clear ();
404 for (string::size_type n = 0; n < len; ++n) {
405 if (path[n] == ':') {
412 /* no multiple search path, just one location (common case) */
416 session_dirs.push_back (sp);
419 AudioFileSource::set_search_path (Glib::build_filename(sp.path, sound_dir (false)));
425 while ((colon = remaining.find_first_of (':')) != string::npos) {
428 sp.path = remaining.substr (0, colon);
429 session_dirs.push_back (sp);
431 /* add sounds to file search path */
433 fspath += Glib::build_filename(sp.path, sound_dir (false));
436 remaining = remaining.substr (colon+1);
439 if (remaining.length()) {
445 fspath += Glib::build_filename(sp.path, sound_dir (false));
448 session_dirs.push_back (sp);
451 /* set the AudioFileSource search path */
453 AudioFileSource::set_search_path (fspath);
455 /* reset the round-robin soundfile path thingie */
457 last_rr_session_dir = session_dirs.begin();
461 Session::ensure_subdirs ()
467 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
468 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
472 /* if this is is an existing session with an old "sounds" directory, just use it. see Session::sound_dir() for more details */
474 if (!Glib::file_test (old_sound_dir(), Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
478 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
479 error << string_compose(_("Session: cannot create session sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
484 dir = dead_sound_dir ();
486 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
487 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
493 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
494 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
498 dir = analysis_dir ();
500 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
501 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
509 Session::create (bool& new_session, const string& mix_template, nframes_t initial_length)
512 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
513 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
517 if (ensure_subdirs ()) {
521 /* check new_session so we don't overwrite an existing one */
523 if (!mix_template.empty()) {
524 std::string in_path = mix_template;
526 ifstream in(in_path.c_str());
529 string out_path = _path;
531 out_path += _statefile_suffix;
533 ofstream out(out_path.c_str());
538 // okay, session is set up. Treat like normal saved
539 // session from now on.
545 error << string_compose (_("Could not open %1 for writing mix template"), out_path)
551 error << string_compose (_("Could not open mix template %1 for reading"), in_path)
558 /* set initial start + end point */
560 start_location->set_end (0);
561 _locations.add (start_location);
563 end_location->set_end (initial_length);
564 _locations.add (end_location);
566 _state_of_the_state = Clean;
574 Session::load_diskstreams (const XMLNode& node)
577 XMLNodeConstIterator citer;
579 clist = node.children();
581 for (citer = clist.begin(); citer != clist.end(); ++citer) {
585 boost::shared_ptr<AudioDiskstream> dstream (new AudioDiskstream (*this, **citer));
586 add_diskstream (dstream);
589 catch (failed_constructor& err) {
590 error << _("Session: could not load diskstream via XML state") << endmsg;
599 Session::maybe_write_autosave()
601 if (dirty() && record_status() != Recording) {
602 save_state("", true);
607 Session::remove_pending_capture_state ()
612 xml_path += _current_snapshot_name;
613 xml_path += _pending_suffix;
615 unlink (xml_path.c_str());
618 /** Rename a state file.
619 * @param snapshot_name Snapshot name.
622 Session::rename_state (string old_name, string new_name)
624 if (old_name == _current_snapshot_name || old_name == _name) {
625 /* refuse to rename the current snapshot or the "main" one */
629 const string old_xml_path = _path + old_name + _statefile_suffix;
630 const string new_xml_path = _path + new_name + _statefile_suffix;
632 if (rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
633 error << string_compose(_("could not rename snapshot %1 to %2"), old_name, new_name) << endmsg;
637 /** Remove a state file.
638 * @param snapshot_name Snapshot name.
641 Session::remove_state (string snapshot_name)
643 if (snapshot_name == _current_snapshot_name || snapshot_name == _name) {
644 /* refuse to remove the current snapshot or the "main" one */
648 const string xml_path = _path + snapshot_name + _statefile_suffix;
650 /* make a backup copy of the state file */
651 const string bak_path = xml_path + ".bak";
652 if (g_file_test (xml_path.c_str(), G_FILE_TEST_EXISTS)) {
653 copy_file (xml_path, bak_path);
657 unlink (xml_path.c_str());
661 Session::save_state (string snapshot_name, bool pending)
667 if (_state_of_the_state & CannotSave) {
671 if (!_engine.connected ()) {
672 error << _("Ardour's audio engine is not connected and state saving would lose all I/O connections. Session not saved")
677 tree.set_root (&get_state());
679 if (snapshot_name.empty()) {
680 snapshot_name = _current_snapshot_name;
685 /* proper save: use _statefile_suffix (.ardour in English) */
687 xml_path += snapshot_name;
688 xml_path += _statefile_suffix;
690 /* make a backup copy of the old file */
694 if (g_file_test (xml_path.c_str(), G_FILE_TEST_EXISTS)) {
695 copy_file (xml_path, bak_path);
700 /* pending save: use _pending_suffix (.pending in English) */
702 xml_path += snapshot_name;
703 xml_path += _pending_suffix;
710 tmp_path += snapshot_name;
713 // cerr << "actually writing state to " << xml_path << endl;
715 if (!tree.write (tmp_path)) {
716 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
717 unlink (tmp_path.c_str());
722 if (rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
723 error << string_compose (_("could not rename temporary session file %1 to %2"), tmp_path, xml_path) << endmsg;
724 unlink (tmp_path.c_str());
731 save_history (snapshot_name);
733 bool was_dirty = dirty();
735 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
739 DirtyChanged (); /* EMIT SIGNAL */
742 StateSaved (snapshot_name); /* EMIT SIGNAL */
749 Session::restore_state (string snapshot_name)
751 if (load_state (snapshot_name) == 0) {
752 set_state (*state_tree->root());
759 Session::load_state (string snapshot_name)
768 state_was_pending = false;
770 /* check for leftover pending state from a crashed capture attempt */
773 xmlpath += snapshot_name;
774 xmlpath += _pending_suffix;
776 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
778 /* there is pending state from a crashed capture attempt */
780 if (AskAboutPendingState()) {
781 state_was_pending = true;
785 if (!state_was_pending) {
788 xmlpath += snapshot_name;
789 xmlpath += _statefile_suffix;
792 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
793 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
797 state_tree = new XMLTree;
801 if (!state_tree->read (xmlpath)) {
802 error << string_compose(_("Could not understand ardour file %1"), xmlpath) << endmsg;
808 XMLNode& root (*state_tree->root());
810 if (root.name() != X_("Session")) {
811 error << string_compose (_("Session file %1 is not an Ardour session"), xmlpath) << endmsg;
817 const XMLProperty* prop;
820 if ((prop = root.property ("version")) == 0) {
821 /* no version implies very old version of Ardour */
825 major_version = atoi (prop->value()); // grab just the first number before the period
826 if (major_version < 2) {
835 backup_path += snapshot_name;
837 backup_path += _statefile_suffix;
839 /* don't make another copy if it already exists */
841 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
842 info << string_compose (_("Copying old session file %1 to %2\nUse %2 with Ardour versions before 2.0 from now on"),
843 xmlpath, backup_path)
846 copy_file (xmlpath, backup_path);
848 /* if it fails, don't worry. right? */
856 Session::load_options (const XMLNode& node)
860 LocaleGuard lg (X_("POSIX"));
862 Config->set_variables (node, ConfigVariableBase::Session);
864 /* now reset MIDI ports because the session can have its own
870 if ((child = find_named_node (node, "end-marker-is-free")) != 0) {
871 if ((prop = child->property ("val")) != 0) {
872 _end_location_is_free = (prop->value() == "yes");
880 Session::save_config_options_predicate (ConfigVariableBase::Owner owner) const
882 const ConfigVariableBase::Owner modified_by_session_or_user = (ConfigVariableBase::Owner)
883 (ConfigVariableBase::Session|ConfigVariableBase::Interface);
885 return owner & modified_by_session_or_user;
889 Session::get_options () const
892 LocaleGuard lg (X_("POSIX"));
894 XMLNode& option_root = Config->get_variables (mem_fun (*this, &Session::save_config_options_predicate));
896 child = option_root.add_child ("end-marker-is-free");
897 child->add_property ("val", _end_location_is_free ? "yes" : "no");
909 Session::get_template()
911 /* if we don't disable rec-enable, diskstreams
912 will believe they need to store their capture
913 sources in their state node.
916 disable_record (false);
922 Session::state(bool full_state)
924 XMLNode* node = new XMLNode("Session");
927 // store libardour version, just in case
929 snprintf(buf, sizeof(buf), "%d.%d.%d", libardour2_major_version, libardour2_minor_version, libardour2_micro_version);
930 node->add_property("version", string(buf));
932 /* store configuration settings */
936 node->add_property ("name", _name);
937 snprintf (buf, sizeof (buf), "%" PRId32, _nominal_frame_rate);
938 node->add_property ("sample-rate", buf);
940 if (session_dirs.size() > 1) {
944 vector<space_and_path>::iterator i = session_dirs.begin();
945 vector<space_and_path>::iterator next;
947 ++i; /* skip the first one */
951 while (i != session_dirs.end()) {
955 if (next != session_dirs.end()) {
965 child = node->add_child ("Path");
966 child->add_content (p);
970 /* save the ID counter */
972 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
973 node->add_property ("id-counter", buf);
975 /* various options */
977 node->add_child_nocopy (get_options());
979 child = node->add_child ("Sources");
982 Glib::Mutex::Lock sl (audio_source_lock);
984 for (AudioSourceList::iterator siter = audio_sources.begin(); siter != audio_sources.end(); ++siter) {
986 /* Don't save information about AudioFileSources that are empty */
988 boost::shared_ptr<AudioFileSource> fs;
990 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (siter->second)) != 0) {
992 /* destructive file sources are OK if they are empty, because
993 we will re-use them every time.
996 if (!fs->destructive()) {
997 if (fs->length() == 0) {
1003 child->add_child_nocopy (siter->second->get_state());
1007 child = node->add_child ("Regions");
1010 Glib::Mutex::Lock rl (region_lock);
1012 for (AudioRegionList::const_iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) {
1014 /* only store regions not attached to playlists */
1016 if (i->second->playlist() == 0) {
1017 child->add_child_nocopy (i->second->state (true));
1022 child = node->add_child ("DiskStreams");
1025 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1026 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1027 if (!(*i)->hidden()) {
1028 child->add_child_nocopy ((*i)->get_state());
1034 node->add_child_nocopy (_locations.get_state());
1036 // for a template, just create a new Locations, populate it
1037 // with the default start and end, and get the state for that.
1039 Location* start = new Location(0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart)));
1040 Location* end = new Location(0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
1043 end->set_end(compute_initial_length());
1045 node->add_child_nocopy (loc.get_state());
1048 child = node->add_child ("Connections");
1050 Glib::Mutex::Lock lm (connection_lock);
1051 for (ConnectionList::iterator i = _connections.begin(); i != _connections.end(); ++i) {
1052 if (!(*i)->system_dependent()) {
1053 child->add_child_nocopy ((*i)->get_state());
1058 child = node->add_child ("Routes");
1060 boost::shared_ptr<RouteList> r = routes.reader ();
1062 RoutePublicOrderSorter cmp;
1063 RouteList public_order (*r);
1064 public_order.sort (cmp);
1066 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1067 if (!(*i)->hidden()) {
1069 child->add_child_nocopy ((*i)->get_state());
1071 child->add_child_nocopy ((*i)->get_template());
1078 child = node->add_child ("EditGroups");
1079 for (list<RouteGroup *>::iterator i = edit_groups.begin(); i != edit_groups.end(); ++i) {
1080 child->add_child_nocopy ((*i)->get_state());
1083 child = node->add_child ("MixGroups");
1084 for (list<RouteGroup *>::iterator i = mix_groups.begin(); i != mix_groups.end(); ++i) {
1085 child->add_child_nocopy ((*i)->get_state());
1088 child = node->add_child ("Playlists");
1089 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
1090 if (!(*i)->hidden()) {
1091 if (!(*i)->empty()) {
1093 child->add_child_nocopy ((*i)->get_state());
1095 child->add_child_nocopy ((*i)->get_template());
1101 child = node->add_child ("UnusedPlaylists");
1102 for (PlaylistList::iterator i = unused_playlists.begin(); i != unused_playlists.end(); ++i) {
1103 if (!(*i)->hidden()) {
1104 if (!(*i)->empty()) {
1106 child->add_child_nocopy ((*i)->get_state());
1108 child->add_child_nocopy ((*i)->get_template());
1116 child = node->add_child ("Click");
1117 child->add_child_nocopy (_click_io->state (full_state));
1121 child = node->add_child ("NamedSelections");
1122 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1124 child->add_child_nocopy ((*i)->get_state());
1129 node->add_child_nocopy (_tempo_map->get_state());
1131 node->add_child_nocopy (get_control_protocol_state());
1134 node->add_child_copy (*_extra_xml);
1141 Session::get_control_protocol_state ()
1143 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1144 return cpm.get_state();
1148 Session::set_state (const XMLNode& node)
1152 const XMLProperty* prop;
1155 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1157 if (node.name() != X_("Session")){
1158 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1162 if ((prop = node.property ("name")) != 0) {
1163 _name = prop->value ();
1166 if ((prop = node.property (X_("sample-rate"))) != 0) {
1168 _nominal_frame_rate = atoi (prop->value());
1170 if (_nominal_frame_rate != _current_frame_rate) {
1171 if (AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate)) {
1177 setup_raid_path(_path);
1179 if ((prop = node.property (X_("id-counter"))) != 0) {
1181 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1182 ID::init_counter (x);
1184 /* old sessions used a timebased counter, so fake
1185 the startup ID counter based on a standard
1190 ID::init_counter (now);
1194 IO::disable_ports ();
1195 IO::disable_connecting ();
1197 /* Object loading order:
1202 MIDI <= relies on data from Options/Config
1215 if ((child = find_named_node (node, "extra")) != 0) {
1216 _extra_xml = new XMLNode (*child);
1219 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1220 load_options (*child);
1221 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1222 load_options (*child);
1224 error << _("Session: XML state has no options section") << endmsg;
1227 if (use_config_midi_ports ()) {
1230 if ((child = find_named_node (node, "Locations")) == 0) {
1231 error << _("Session: XML state has no locations section") << endmsg;
1233 } else if (_locations.set_state (*child)) {
1239 if ((location = _locations.auto_loop_location()) != 0) {
1240 set_auto_loop_location (location);
1243 if ((location = _locations.auto_punch_location()) != 0) {
1244 set_auto_punch_location (location);
1247 if ((location = _locations.end_location()) == 0) {
1248 _locations.add (end_location);
1250 delete end_location;
1251 end_location = location;
1254 if ((location = _locations.start_location()) == 0) {
1255 _locations.add (start_location);
1257 delete start_location;
1258 start_location = location;
1261 AudioFileSource::set_header_position_offset (start_location->start());
1263 if ((child = find_named_node (node, "Sources")) == 0) {
1264 error << _("Session: XML state has no sources section") << endmsg;
1266 } else if (load_sources (*child)) {
1270 if ((child = find_named_node (node, "Regions")) == 0) {
1271 error << _("Session: XML state has no Regions section") << endmsg;
1273 } else if (load_regions (*child)) {
1277 if ((child = find_named_node (node, "Playlists")) == 0) {
1278 error << _("Session: XML state has no playlists section") << endmsg;
1280 } else if (load_playlists (*child)) {
1284 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1286 } else if (load_unused_playlists (*child)) {
1290 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1291 if (load_named_selections (*child)) {
1296 if ((child = find_named_node (node, "DiskStreams")) == 0) {
1297 error << _("Session: XML state has no diskstreams section") << endmsg;
1299 } else if (load_diskstreams (*child)) {
1303 if ((child = find_named_node (node, "Connections")) == 0) {
1304 error << _("Session: XML state has no connections section") << endmsg;
1306 } else if (load_connections (*child)) {
1310 if ((child = find_named_node (node, "EditGroups")) == 0) {
1311 error << _("Session: XML state has no edit groups section") << endmsg;
1313 } else if (load_edit_groups (*child)) {
1317 if ((child = find_named_node (node, "MixGroups")) == 0) {
1318 error << _("Session: XML state has no mix groups section") << endmsg;
1320 } else if (load_mix_groups (*child)) {
1324 if ((child = find_named_node (node, "TempoMap")) == 0) {
1325 error << _("Session: XML state has no Tempo Map section") << endmsg;
1327 } else if (_tempo_map->set_state (*child)) {
1331 if ((child = find_named_node (node, "Routes")) == 0) {
1332 error << _("Session: XML state has no routes section") << endmsg;
1334 } else if (load_routes (*child)) {
1338 if ((child = find_named_node (node, "Click")) == 0) {
1339 warning << _("Session: XML state has no click section") << endmsg;
1340 } else if (_click_io) {
1341 _click_io->set_state (*child);
1344 if ((child = find_named_node (node, "ControlProtocols")) != 0) {
1345 ControlProtocolManager::instance().set_protocol_states (*child);
1348 /* here beginneth the second phase ... */
1350 StateReady (); /* EMIT SIGNAL */
1359 Session::load_routes (const XMLNode& node)
1362 XMLNodeConstIterator niter;
1363 RouteList new_routes;
1365 nlist = node.children();
1369 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1371 boost::shared_ptr<Route> route (XMLRouteFactory (**niter));
1374 error << _("Session: cannot create Route from XML description.") << endmsg;
1378 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1380 new_routes.push_back (route);
1383 add_routes (new_routes, false);
1388 boost::shared_ptr<Route>
1389 Session::XMLRouteFactory (const XMLNode& node)
1391 if (node.name() != "Route") {
1392 return boost::shared_ptr<Route> ((Route*) 0);
1395 if (node.property ("diskstream") != 0 || node.property ("diskstream-id") != 0) {
1396 boost::shared_ptr<Route> x (new AudioTrack (*this, node));
1399 boost::shared_ptr<Route> x (new Route (*this, node));
1405 Session::load_regions (const XMLNode& node)
1408 XMLNodeConstIterator niter;
1409 boost::shared_ptr<AudioRegion> region;
1411 nlist = node.children();
1415 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1416 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1417 error << _("Session: cannot create Region from XML description.");
1418 const XMLProperty *name = (**niter).property("name");
1421 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1431 boost::shared_ptr<AudioRegion>
1432 Session::XMLRegionFactory (const XMLNode& node, bool full)
1434 const XMLProperty* prop;
1435 boost::shared_ptr<Source> source;
1436 boost::shared_ptr<AudioSource> as;
1438 SourceList master_sources;
1439 uint32_t nchans = 1;
1442 if (node.name() != X_("Region")) {
1443 return boost::shared_ptr<AudioRegion>();
1446 if ((prop = node.property (X_("channels"))) != 0) {
1447 nchans = atoi (prop->value().c_str());
1451 if ((prop = node.property ("name")) == 0) {
1452 cerr << "no name for this region\n";
1456 if ((prop = node.property (X_("source-0"))) == 0) {
1457 if ((prop = node.property ("source")) == 0) {
1458 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1459 return boost::shared_ptr<AudioRegion>();
1463 PBD::ID s_id (prop->value());
1465 if ((source = source_by_id (s_id)) == 0) {
1466 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1467 return boost::shared_ptr<AudioRegion>();
1470 as = boost::dynamic_pointer_cast<AudioSource>(source);
1472 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1473 return boost::shared_ptr<AudioRegion>();
1476 sources.push_back (as);
1478 /* pickup other channels */
1480 for (uint32_t n=1; n < nchans; ++n) {
1481 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1482 if ((prop = node.property (buf)) != 0) {
1484 PBD::ID id2 (prop->value());
1486 if ((source = source_by_id (id2)) == 0) {
1487 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1488 return boost::shared_ptr<AudioRegion>();
1491 as = boost::dynamic_pointer_cast<AudioSource>(source);
1493 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1494 return boost::shared_ptr<AudioRegion>();
1496 sources.push_back (as);
1500 for (uint32_t n=0; n < nchans; ++n) {
1501 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1502 if ((prop = node.property (buf)) != 0) {
1504 PBD::ID id2 (prop->value());
1506 if ((source = source_by_id (id2)) == 0) {
1507 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1508 return boost::shared_ptr<AudioRegion>();
1511 as = boost::dynamic_pointer_cast<AudioSource>(source);
1513 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1514 return boost::shared_ptr<AudioRegion>();
1516 master_sources.push_back (as);
1521 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1523 /* a final detail: this is the one and only place that we know how long missing files are */
1525 if (region->whole_file()) {
1526 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1527 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1529 sfp->set_length (region->length());
1534 if (!master_sources.empty()) {
1535 if (master_sources.size() != nchans) {
1536 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1538 region->set_master_sources (master_sources);
1546 catch (failed_constructor& err) {
1547 return boost::shared_ptr<AudioRegion>();
1552 Session::get_sources_as_xml ()
1555 XMLNode* node = new XMLNode (X_("Sources"));
1556 Glib::Mutex::Lock lm (audio_source_lock);
1558 for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ++i) {
1559 node->add_child_nocopy (i->second->get_state());
1562 /* XXX get MIDI and other sources here */
1568 Session::path_from_region_name (string name, string identifier)
1570 char buf[PATH_MAX+1];
1572 string dir = discover_best_sound_dir ();
1574 for (n = 0; n < 999999; ++n) {
1575 if (identifier.length()) {
1576 snprintf (buf, sizeof(buf), "%s/%s%s%" PRIu32 ".wav", dir.c_str(), name.c_str(),
1577 identifier.c_str(), n);
1579 snprintf (buf, sizeof(buf), "%s/%s-%" PRIu32 ".wav", dir.c_str(), name.c_str(), n);
1582 if (!Glib::file_test (buf, Glib::FILE_TEST_EXISTS)) {
1587 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1596 Session::load_sources (const XMLNode& node)
1599 XMLNodeConstIterator niter;
1600 boost::shared_ptr<Source> source;
1602 nlist = node.children();
1606 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1609 if ((source = XMLSourceFactory (**niter)) == 0) {
1610 error << _("Session: cannot create Source from XML description.") << endmsg;
1614 catch (non_existent_source& err) {
1615 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1616 source = SourceFactory::createSilent (*this, **niter, max_frames, _current_frame_rate);
1623 boost::shared_ptr<Source>
1624 Session::XMLSourceFactory (const XMLNode& node)
1626 if (node.name() != "Source") {
1627 return boost::shared_ptr<Source>();
1631 /* note: do peak building in another thread when loading session state */
1632 return SourceFactory::create (*this, node, true);
1635 catch (failed_constructor& err) {
1636 error << _("Found a sound file that cannot be used by Ardour. Talk to the progammers.") << endmsg;
1637 return boost::shared_ptr<Source>();
1642 Session::save_template (string template_name)
1645 string xml_path, bak_path, template_path;
1647 if (_state_of_the_state & CannotSave) {
1652 string dir = template_dir();
1654 if ((dp = opendir (dir.c_str()))) {
1657 if (g_mkdir_with_parents (dir.c_str(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
1658 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
1663 tree.set_root (&get_template());
1665 xml_path = Glib::build_filename(dir, template_name + _template_suffix);
1667 ifstream in(xml_path.c_str());
1670 warning << string_compose(_("Template \"%1\" already exists - new version not created"), template_name) << endmsg;
1676 if (!tree.write (xml_path)) {
1677 error << _("mix template not saved") << endmsg;
1685 Session::rename_template (string old_name, string new_name)
1687 string old_path = Glib::build_filename(template_dir(), old_name + _template_suffix);
1688 string new_path = Glib::build_filename(template_dir(), new_name + _template_suffix);
1690 return rename (old_path.c_str(), new_path.c_str());
1694 Session::delete_template (string name)
1696 string template_path = Glib::build_filename(template_dir(), name + _template_suffix);
1698 return remove (template_path.c_str());
1702 Session::refresh_disk_space ()
1705 struct statfs statfsbuf;
1706 vector<space_and_path>::iterator i;
1707 Glib::Mutex::Lock lm (space_lock);
1710 /* get freespace on every FS that is part of the session path */
1712 _total_free_4k_blocks = 0;
1714 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1715 statfs ((*i).path.c_str(), &statfsbuf);
1717 scale = statfsbuf.f_bsize/4096.0;
1719 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
1720 _total_free_4k_blocks += (*i).blocks;
1726 Session::ensure_sound_dir (string path, string& result)
1731 /* Ensure that the parent directory exists */
1733 if (g_mkdir_with_parents (path.c_str(), 0775)) {
1734 error << string_compose(_("cannot create session directory \"%1\"; ignored"), path) << endmsg;
1738 /* Ensure that the sounds directory exists */
1740 result = Glib::build_filename(path, sound_dir_name);
1742 if (g_mkdir_with_parents (result.c_str(), 0775)) {
1743 error << string_compose(_("cannot create sounds directory \"%1\"; ignored"), result) << endmsg;
1747 dead = Glib::build_filename(path, dead_sound_dir_name);
1749 if (g_mkdir_with_parents (dead.c_str(), 0775)) {
1750 error << string_compose(_("cannot create dead sounds directory \"%1\"; ignored"), dead) << endmsg;
1754 peak = Glib::build_filename(path, peak_dir_name);
1756 if (g_mkdir_with_parents (peak.c_str(), 0775)) {
1757 error << string_compose(_("cannot create peak file directory \"%1\"; ignored"), peak) << endmsg;
1761 /* callers expect this to be terminated ... */
1768 Session::discover_best_sound_dir (bool destructive)
1770 vector<space_and_path>::iterator i;
1773 /* handle common case without system calls */
1775 if (session_dirs.size() == 1) {
1779 /* OK, here's the algorithm we're following here:
1781 We want to select which directory to use for
1782 the next file source to be created. Ideally,
1783 we'd like to use a round-robin process so as to
1784 get maximum performance benefits from splitting
1785 the files across multiple disks.
1787 However, in situations without much diskspace, an
1788 RR approach may end up filling up a filesystem
1789 with new files while others still have space.
1790 Its therefore important to pay some attention to
1791 the freespace in the filesystem holding each
1792 directory as well. However, if we did that by
1793 itself, we'd keep creating new files in the file
1794 system with the most space until it was as full
1795 as all others, thus negating any performance
1796 benefits of this RAID-1 like approach.
1798 So, we use a user-configurable space threshold. If
1799 there are at least 2 filesystems with more than this
1800 much space available, we use RR selection between them.
1801 If not, then we pick the filesystem with the most space.
1803 This gets a good balance between the two
1807 refresh_disk_space ();
1809 int free_enough = 0;
1811 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1812 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
1817 if (free_enough >= 2) {
1819 bool found_it = false;
1821 /* use RR selection process, ensuring that the one
1825 i = last_rr_session_dir;
1828 if (++i == session_dirs.end()) {
1829 i = session_dirs.begin();
1832 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
1833 if (ensure_sound_dir ((*i).path, result) == 0) {
1834 last_rr_session_dir = i;
1840 } while (i != last_rr_session_dir);
1843 result = sound_dir();
1848 /* pick FS with the most freespace (and that
1849 seems to actually work ...)
1852 vector<space_and_path> sorted;
1853 space_and_path_ascending_cmp cmp;
1855 sorted = session_dirs;
1856 sort (sorted.begin(), sorted.end(), cmp);
1858 for (i = sorted.begin(); i != sorted.end(); ++i) {
1859 if (ensure_sound_dir ((*i).path, result) == 0) {
1860 last_rr_session_dir = i;
1865 /* if the above fails, fall back to the most simplistic solution */
1867 if (i == sorted.end()) {
1876 Session::load_playlists (const XMLNode& node)
1879 XMLNodeConstIterator niter;
1880 boost::shared_ptr<Playlist> playlist;
1882 nlist = node.children();
1886 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1888 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
1889 error << _("Session: cannot create Playlist from XML description.") << endmsg;
1897 Session::load_unused_playlists (const XMLNode& node)
1900 XMLNodeConstIterator niter;
1901 boost::shared_ptr<Playlist> playlist;
1903 nlist = node.children();
1907 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1909 if ((playlist = XMLPlaylistFactory (**niter)) == 0) {
1910 error << _("Session: cannot create Playlist from XML description.") << endmsg;
1914 // now manually untrack it
1916 track_playlist (false, boost::weak_ptr<Playlist> (playlist));
1923 boost::shared_ptr<Playlist>
1924 Session::XMLPlaylistFactory (const XMLNode& node)
1927 return PlaylistFactory::create (*this, node);
1930 catch (failed_constructor& err) {
1931 return boost::shared_ptr<Playlist>();
1936 Session::load_named_selections (const XMLNode& node)
1939 XMLNodeConstIterator niter;
1942 nlist = node.children();
1946 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1948 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
1949 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
1957 Session::XMLNamedSelectionFactory (const XMLNode& node)
1960 return new NamedSelection (*this, node);
1963 catch (failed_constructor& err) {
1969 Session::dead_sound_dir () const
1972 res += dead_sound_dir_name;
1978 Session::old_sound_dir (bool with_path) const
1986 res += old_sound_dir_name;
1992 Session::sound_dir (bool with_path) const
1996 vector<string> parts;
2004 parts.push_back(interchange_dir_name);
2005 parts.push_back(legalize_for_path (_name));
2006 parts.push_back(sound_dir_name);
2008 res += Glib::build_filename(parts);
2015 /* if this already exists, don't check for the old session sound directory */
2017 if (Glib::file_test (full, Glib::FILE_TEST_IS_DIR|Glib::FILE_TEST_EXISTS)) {
2021 /* possibly support old session structure */
2024 string old_withpath;
2026 old_nopath += old_sound_dir_name;
2029 old_withpath = _path;
2030 old_withpath += old_sound_dir_name;
2032 if (Glib::file_test (old_withpath.c_str(), Glib::FILE_TEST_IS_DIR|Glib::FILE_TEST_EXISTS)) {
2034 return old_withpath;
2039 /* ok, old "sounds" directory isn't there, return the new path */
2045 Session::peak_dir () const
2047 return Glib::build_filename (_path, peak_dir_name);
2051 Session::automation_dir () const
2053 return Glib::build_filename (_path, "automation");
2057 Session::analysis_dir () const
2059 return Glib::build_filename (_path, "analysis");
2063 Session::template_dir ()
2065 return Glib::build_filename (get_user_ardour_path(), "templates");
2069 Session::export_dir () const
2071 return Glib::build_filename (_path, export_dir_name);
2075 Session::suffixed_search_path (string suffix, bool data)
2079 path += get_user_ardour_path();
2080 if (path[path.length()-1] != ':') {
2085 path += get_system_data_path();
2087 path += get_system_module_path();
2090 vector<string> split_path;
2092 split (path, split_path, ':');
2095 for (vector<string>::iterator i = split_path.begin(); i != split_path.end(); ++i) {
2100 if (distance (i, split_path.end()) != 1) {
2109 Session::template_path ()
2111 return suffixed_search_path (X_("templates"), true);
2115 Session::control_protocol_path ()
2117 char *p = getenv ("ARDOUR_CONTROL_SURFACE_PATH");
2121 return suffixed_search_path (X_("surfaces"), false);
2125 Session::load_connections (const XMLNode& node)
2127 XMLNodeList nlist = node.children();
2128 XMLNodeConstIterator niter;
2132 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2133 if ((*niter)->name() == "InputConnection") {
2134 add_connection (new ARDOUR::InputConnection (**niter));
2135 } else if ((*niter)->name() == "OutputConnection") {
2136 add_connection (new ARDOUR::OutputConnection (**niter));
2138 error << string_compose(_("Unknown node \"%1\" found in Connections list from state file"), (*niter)->name()) << endmsg;
2147 Session::load_edit_groups (const XMLNode& node)
2149 return load_route_groups (node, true);
2153 Session::load_mix_groups (const XMLNode& node)
2155 return load_route_groups (node, false);
2159 Session::load_route_groups (const XMLNode& node, bool edit)
2161 XMLNodeList nlist = node.children();
2162 XMLNodeConstIterator niter;
2167 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2168 if ((*niter)->name() == "RouteGroup") {
2170 rg = add_edit_group ("");
2171 rg->set_state (**niter);
2173 rg = add_mix_group ("");
2174 rg->set_state (**niter);
2183 state_file_filter (const string &str, void *arg)
2185 return (str.length() > strlen(Session::statefile_suffix()) &&
2186 str.find (Session::statefile_suffix()) == (str.length() - strlen (Session::statefile_suffix())));
2190 bool operator()(const string* a, const string* b) {
2196 remove_end(string* state)
2198 string statename(*state);
2200 string::size_type start,end;
2201 if ((start = statename.find_last_of ('/')) != string::npos) {
2202 statename = statename.substr (start+1);
2205 if ((end = statename.rfind(".ardour")) == string::npos) {
2206 end = statename.length();
2209 return new string(statename.substr (0, end));
2213 Session::possible_states (string path)
2215 PathScanner scanner;
2216 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2218 transform(states->begin(), states->end(), states->begin(), remove_end);
2221 sort (states->begin(), states->end(), cmp);
2227 Session::possible_states () const
2229 return possible_states(_path);
2233 Session::auto_save()
2235 save_state (_current_snapshot_name);
2239 Session::add_edit_group (string name)
2241 RouteGroup* rg = new RouteGroup (*this, name);
2242 edit_groups.push_back (rg);
2243 edit_group_added (rg); /* EMIT SIGNAL */
2249 Session::add_mix_group (string name)
2251 RouteGroup* rg = new RouteGroup (*this, name, RouteGroup::Relative);
2252 mix_groups.push_back (rg);
2253 mix_group_added (rg); /* EMIT SIGNAL */
2259 Session::remove_edit_group (RouteGroup& rg)
2261 list<RouteGroup*>::iterator i;
2263 if ((i = find (edit_groups.begin(), edit_groups.end(), &rg)) != edit_groups.end()) {
2264 (*i)->apply (&Route::drop_edit_group, this);
2265 edit_groups.erase (i);
2266 edit_group_removed (); /* EMIT SIGNAL */
2273 Session::remove_mix_group (RouteGroup& rg)
2275 list<RouteGroup*>::iterator i;
2277 if ((i = find (mix_groups.begin(), mix_groups.end(), &rg)) != mix_groups.end()) {
2278 (*i)->apply (&Route::drop_mix_group, this);
2279 mix_groups.erase (i);
2280 mix_group_removed (); /* EMIT SIGNAL */
2287 Session::mix_group_by_name (string name)
2289 list<RouteGroup *>::iterator i;
2291 for (i = mix_groups.begin(); i != mix_groups.end(); ++i) {
2292 if ((*i)->name() == name) {
2300 Session::edit_group_by_name (string name)
2302 list<RouteGroup *>::iterator i;
2304 for (i = edit_groups.begin(); i != edit_groups.end(); ++i) {
2305 if ((*i)->name() == name) {
2313 Session::begin_reversible_command (string name)
2315 current_trans = new UndoTransaction;
2316 current_trans->set_name (name);
2320 Session::commit_reversible_command (Command *cmd)
2325 current_trans->add_command (cmd);
2328 if (current_trans->empty()) {
2332 gettimeofday (&now, 0);
2333 current_trans->set_timestamp (now);
2335 _history.add (current_trans);
2338 Session::GlobalRouteBooleanState
2339 Session::get_global_route_boolean (bool (Route::*method)(void) const)
2341 GlobalRouteBooleanState s;
2342 boost::shared_ptr<RouteList> r = routes.reader ();
2344 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2345 if (!(*i)->hidden()) {
2346 RouteBooleanState v;
2349 Route* r = (*i).get();
2350 v.second = (r->*method)();
2359 Session::GlobalRouteMeterState
2360 Session::get_global_route_metering ()
2362 GlobalRouteMeterState s;
2363 boost::shared_ptr<RouteList> r = routes.reader ();
2365 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2366 if (!(*i)->hidden()) {
2370 v.second = (*i)->meter_point();
2380 Session::set_global_route_metering (GlobalRouteMeterState s, void* arg)
2382 for (GlobalRouteMeterState::iterator i = s.begin(); i != s.end(); ++i) {
2384 boost::shared_ptr<Route> r = (i->first.lock());
2387 r->set_meter_point (i->second, arg);
2393 Session::set_global_route_boolean (GlobalRouteBooleanState s, void (Route::*method)(bool, void*), void* arg)
2395 for (GlobalRouteBooleanState::iterator i = s.begin(); i != s.end(); ++i) {
2397 boost::shared_ptr<Route> r = (i->first.lock());
2400 Route* rp = r.get();
2401 (rp->*method) (i->second, arg);
2407 Session::set_global_mute (GlobalRouteBooleanState s, void* src)
2409 set_global_route_boolean (s, &Route::set_mute, src);
2413 Session::set_global_solo (GlobalRouteBooleanState s, void* src)
2415 set_global_route_boolean (s, &Route::set_solo, src);
2419 Session::set_global_record_enable (GlobalRouteBooleanState s, void* src)
2421 set_global_route_boolean (s, &Route::set_record_enable, src);
2426 Session::global_mute_memento (void* src)
2428 return sigc::bind (mem_fun (*this, &Session::set_global_mute), get_global_route_boolean (&Route::muted), src);
2432 Session::global_metering_memento (void* src)
2434 return sigc::bind (mem_fun (*this, &Session::set_global_route_metering), get_global_route_metering (), src);
2438 Session::global_solo_memento (void* src)
2440 return sigc::bind (mem_fun (*this, &Session::set_global_solo), get_global_route_boolean (&Route::soloed), src);
2444 Session::global_record_enable_memento (void* src)
2446 return sigc::bind (mem_fun (*this, &Session::set_global_record_enable), get_global_route_boolean (&Route::record_enabled), src);
2451 template_filter (const string &str, void *arg)
2453 return (str.length() > strlen(Session::template_suffix()) &&
2454 str.find (Session::template_suffix()) == (str.length() - strlen (Session::template_suffix())));
2458 Session::get_template_list (list<string> &template_names)
2460 vector<string *> *templates;
2461 PathScanner scanner;
2464 path = template_path ();
2466 templates = scanner (path, template_filter, 0, false, true);
2468 vector<string*>::iterator i;
2469 for (i = templates->begin(); i != templates->end(); ++i) {
2470 string fullpath = *(*i);
2473 start = fullpath.find_last_of ('/') + 1;
2474 if ((end = fullpath.find_last_of ('.')) <0) {
2475 end = fullpath.length();
2478 template_names.push_back(fullpath.substr(start, (end-start)));
2483 Session::read_favorite_dirs (FavoriteDirs & favs)
2485 Glib::ustring path = Glib::build_filename (get_user_ardour_path(), "favorite_dirs");
2487 ifstream fav (path.c_str());
2492 if (errno != ENOENT) {
2493 //error << string_compose (_("cannot open favorite file %1 (%2)"), path, strerror (errno)) << endmsg;
2504 getline(fav, newfav);
2510 favs.push_back (newfav);
2517 Session::write_favorite_dirs (FavoriteDirs & favs)
2519 Glib::ustring path = Glib::build_filename (get_user_ardour_path(), "favorite_dirs");
2521 ofstream fav (path.c_str());
2527 for (FavoriteDirs::iterator i = favs.begin(); i != favs.end(); ++i) {
2528 fav << (*i) << endl;
2535 accept_all_non_peak_files (const string& path, void *arg)
2537 return (path.length() > 5 && path.find (".peak") != (path.length() - 5));
2541 accept_all_state_files (const string& path, void *arg)
2543 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2547 Session::find_all_sources (string path, set<string>& result)
2552 if (!tree.read (path)) {
2556 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2561 XMLNodeConstIterator niter;
2563 nlist = node->children();
2567 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2571 if ((prop = (*niter)->property (X_("name"))) == 0) {
2575 if (prop->value()[0] == '/') {
2576 /* external file, ignore */
2580 string path = _path; /* /-terminated */
2581 path += sound_dir_name;
2583 path += prop->value();
2585 result.insert (path);
2592 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2594 PathScanner scanner;
2595 vector<string*>* state_files;
2597 string this_snapshot_path;
2603 if (ripped[ripped.length()-1] == '/') {
2604 ripped = ripped.substr (0, ripped.length() - 1);
2607 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2609 if (state_files == 0) {
2614 this_snapshot_path = _path;
2615 this_snapshot_path += _current_snapshot_name;
2616 this_snapshot_path += _statefile_suffix;
2618 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2620 if (exclude_this_snapshot && **i == this_snapshot_path) {
2624 if (find_all_sources (**i, result) < 0) {
2632 struct RegionCounter {
2633 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2634 AudioSourceList::iterator iter;
2635 boost::shared_ptr<Region> region;
2638 RegionCounter() : count (0) {}
2642 Session::cleanup_sources (Session::cleanup_report& rep)
2644 vector<boost::shared_ptr<Source> > dead_sources;
2645 vector<boost::shared_ptr<Playlist> > playlists_tbd;
2646 PathScanner scanner;
2648 vector<space_and_path>::iterator i;
2649 vector<space_and_path>::iterator nexti;
2650 vector<string*>* soundfiles;
2651 vector<string> unused;
2652 set<string> all_sources;
2657 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2660 /* step 1: consider deleting all unused playlists */
2662 for (PlaylistList::iterator x = unused_playlists.begin(); x != unused_playlists.end(); ++x) {
2665 status = AskAboutPlaylistDeletion (*x);
2674 playlists_tbd.push_back (*x);
2678 /* leave it alone */
2683 /* now delete any that were marked for deletion */
2685 for (vector<boost::shared_ptr<Playlist> >::iterator x = playlists_tbd.begin(); x != playlists_tbd.end(); ++x) {
2686 (*x)->drop_references ();
2689 playlists_tbd.clear ();
2691 /* step 2: find all un-used sources */
2696 for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ) {
2698 AudioSourceList::iterator tmp;
2703 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2707 if (!i->second->used() && i->second->length() > 0) {
2708 dead_sources.push_back (i->second);
2709 i->second->GoingAway();
2715 /* build a list of all the possible sound directories for the session */
2717 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2722 sound_path += (*i).path;
2723 sound_path += sound_dir (false);
2725 if (nexti != session_dirs.end()) {
2732 /* now do the same thing for the files that ended up in the sounds dir(s)
2733 but are not referenced as sources in any snapshot.
2736 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
2738 if (soundfiles == 0) {
2742 /* find all sources, but don't use this snapshot because the
2743 state file on disk still references sources we may have already
2747 find_all_sources_across_snapshots (all_sources, true);
2749 /* add our current source list
2752 for (AudioSourceList::iterator i = audio_sources.begin(); i != audio_sources.end(); ++i) {
2753 boost::shared_ptr<AudioFileSource> fs;
2755 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (i->second)) != 0) {
2756 all_sources.insert (fs->path());
2760 char tmppath1[PATH_MAX+1];
2761 char tmppath2[PATH_MAX+1];
2763 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
2768 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2770 realpath(spath.c_str(), tmppath1);
2771 realpath((*i).c_str(), tmppath2);
2773 if (strcmp(tmppath1, tmppath2) == 0) {
2780 unused.push_back (spath);
2784 /* now try to move all unused files into the "dead_sounds" directory(ies) */
2786 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2787 struct stat statbuf;
2789 rep.paths.push_back (*x);
2790 if (stat ((*x).c_str(), &statbuf) == 0) {
2791 rep.space += statbuf.st_size;
2796 /* don't move the file across filesystems, just
2797 stick it in the `dead_sound_dir_name' directory
2798 on whichever filesystem it was already on.
2801 if ((*x).find ("/sounds/") != string::npos) {
2803 /* old school, go up 1 level */
2805 newpath = Glib::path_get_dirname (*x); // "sounds"
2806 newpath = Glib::path_get_dirname (newpath); // "session-name"
2810 /* new school, go up 4 levels */
2812 newpath = Glib::path_get_dirname (*x); // "audiofiles"
2813 newpath = Glib::path_get_dirname (newpath); // "session-name"
2814 newpath = Glib::path_get_dirname (newpath); // "interchange"
2815 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2819 newpath += dead_sound_dir_name;
2821 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2822 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2827 newpath += Glib::path_get_basename ((*x));
2829 if (access (newpath.c_str(), F_OK) == 0) {
2831 /* the new path already exists, try versioning */
2833 char buf[PATH_MAX+1];
2837 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2840 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
2841 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2845 if (version == 999) {
2846 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2850 newpath = newpath_v;
2855 /* it doesn't exist, or we can't read it or something */
2859 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2860 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
2861 (*x), newpath, strerror (errno))
2866 /* see if there an easy to find peakfile for this file, and remove it.
2869 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
2870 peakpath += ".peak";
2872 if (access (peakpath.c_str(), W_OK) == 0) {
2873 if (::unlink (peakpath.c_str()) != 0) {
2874 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2875 peakpath, _path, strerror (errno))
2877 /* try to back out */
2878 rename (newpath.c_str(), _path.c_str());
2886 /* dump the history list */
2890 /* save state so we don't end up a session file
2891 referring to non-existent sources.
2897 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2903 Session::cleanup_trash_sources (Session::cleanup_report& rep)
2905 vector<space_and_path>::iterator i;
2906 string dead_sound_dir;
2907 struct dirent* dentry;
2908 struct stat statbuf;
2914 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2916 dead_sound_dir = (*i).path;
2917 dead_sound_dir += dead_sound_dir_name;
2919 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
2923 while ((dentry = readdir (dead)) != 0) {
2925 /* avoid '.' and '..' */
2927 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
2928 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
2934 fullpath = dead_sound_dir;
2936 fullpath += dentry->d_name;
2938 if (stat (fullpath.c_str(), &statbuf)) {
2942 if (!S_ISREG (statbuf.st_mode)) {
2946 if (unlink (fullpath.c_str())) {
2947 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
2948 fullpath, strerror (errno))
2952 rep.paths.push_back (dentry->d_name);
2953 rep.space += statbuf.st_size;
2964 Session::set_dirty ()
2966 bool was_dirty = dirty();
2968 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2972 DirtyChanged(); /* EMIT SIGNAL */
2978 Session::set_clean ()
2980 bool was_dirty = dirty();
2982 _state_of_the_state = Clean;
2986 DirtyChanged(); /* EMIT SIGNAL */
2991 Session::set_deletion_in_progress ()
2993 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2998 Session::add_controllable (Controllable* c)
3000 /* this adds a controllable to the list managed by the Session.
3001 this is a subset of those managed by the Controllable class
3002 itself, and represents the only ones whose state will be saved
3003 as part of the session.
3006 Glib::Mutex::Lock lm (controllables_lock);
3007 controllables.insert (c);
3011 Session::remove_controllable (Controllable* c)
3013 if (_state_of_the_state | Deletion) {
3017 Glib::Mutex::Lock lm (controllables_lock);
3019 Controllables::iterator x = controllables.find (c);
3021 if (x != controllables.end()) {
3022 controllables.erase (x);
3027 Session::controllable_by_id (const PBD::ID& id)
3029 Glib::Mutex::Lock lm (controllables_lock);
3031 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3032 if ((*i)->id() == id) {
3041 Session::add_instant_xml (XMLNode& node, const std::string& dir)
3043 Stateful::add_instant_xml (node, dir);
3044 Config->add_instant_xml (node, get_user_ardour_path());
3048 Session::save_history (string snapshot_name)
3054 if (snapshot_name.empty()) {
3055 snapshot_name = _current_snapshot_name;
3058 xml_path = _path + snapshot_name + ".history";
3060 bak_path = xml_path + ".bak";
3062 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && ::rename (xml_path.c_str(), bak_path.c_str())) {
3063 error << _("could not backup old history file, current history not saved.") << endmsg;
3067 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3071 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3073 if (!tree.write (xml_path))
3075 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3077 /* don't leave a corrupt file lying around if it is
3081 if (unlink (xml_path.c_str())) {
3082 error << string_compose (_("could not remove corrupt history file %1"), xml_path) << endmsg;
3084 if (rename (bak_path.c_str(), xml_path.c_str()))
3086 error << string_compose (_("could not restore history file from backup %1"), bak_path) << endmsg;
3097 Session::restore_history (string snapshot_name)
3102 if (snapshot_name.empty()) {
3103 snapshot_name = _current_snapshot_name;
3107 xmlpath = _path + snapshot_name + ".history";
3108 cerr << string_compose(_("Loading history from '%1'."), xmlpath) << endmsg;
3110 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
3114 if (!tree.read (xmlpath)) {
3115 error << string_compose (_("Could not understand session history file \"%1\""), xmlpath) << endmsg;
3119 /* replace history */
3122 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3125 UndoTransaction* ut = new UndoTransaction ();
3128 ut->set_name(t->property("name")->value());
3129 stringstream ss(t->property("tv_sec")->value());
3131 ss.str(t->property("tv_usec")->value());
3133 ut->set_timestamp(tv);
3135 for (XMLNodeConstIterator child_it = t->children().begin();
3136 child_it != t->children().end();
3139 XMLNode *n = *child_it;
3142 if (n->name() == "MementoCommand" ||
3143 n->name() == "MementoUndoCommand" ||
3144 n->name() == "MementoRedoCommand") {
3146 if ((c = memento_command_factory(n))) {
3150 } else if (n->name() == X_("GlobalRouteStateCommand")) {
3152 if ((c = global_state_command_factory (*n))) {
3153 ut->add_command (c);
3158 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3169 Session::config_changed (const char* parameter_name)
3171 #define PARAM_IS(x) (!strcmp (parameter_name, (x)))
3173 if (PARAM_IS ("seamless-loop")) {
3175 } else if (PARAM_IS ("rf-speed")) {
3177 } else if (PARAM_IS ("auto-loop")) {
3179 } else if (PARAM_IS ("auto-input")) {
3181 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3182 /* auto-input only makes a difference if we're rolling */
3184 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
3186 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
3187 if ((*i)->record_enabled ()) {
3188 (*i)->monitor_input (!Config->get_auto_input());
3193 } else if (PARAM_IS ("punch-in")) {
3197 if ((location = _locations.auto_punch_location()) != 0) {
3199 if (Config->get_punch_in ()) {
3200 replace_event (Event::PunchIn, location->start());
3202 remove_event (location->start(), Event::PunchIn);
3206 } else if (PARAM_IS ("punch-out")) {
3210 if ((location = _locations.auto_punch_location()) != 0) {
3212 if (Config->get_punch_out()) {
3213 replace_event (Event::PunchOut, location->end());
3215 clear_events (Event::PunchOut);
3219 } else if (PARAM_IS ("edit-mode")) {
3221 Glib::Mutex::Lock lm (playlist_lock);
3223 for (PlaylistList::iterator i = playlists.begin(); i != playlists.end(); ++i) {
3224 (*i)->set_edit_mode (Config->get_edit_mode ());
3227 } else if (PARAM_IS ("use-video-sync")) {
3229 waiting_for_sync_offset = Config->get_use_video_sync();
3231 } else if (PARAM_IS ("mmc-control")) {
3233 poke_midi_thread ();
3235 } else if (PARAM_IS ("mmc-device-id") || PARAM_IS ("mmc-receive-device-id")) {
3237 set_mmc_receive_device_id (Config->get_mmc_receive_device_id());
3239 } else if (PARAM_IS ("mmc-send-device-id")) {
3241 set_mmc_send_device_id (Config->get_mmc_send_device_id());
3243 } else if (PARAM_IS ("midi-control")) {
3245 poke_midi_thread ();
3247 } else if (PARAM_IS ("raid-path")) {
3249 setup_raid_path (Config->get_raid_path());
3251 } else if (PARAM_IS ("smpte-format")) {
3255 } else if (PARAM_IS ("video-pullup")) {
3259 } else if (PARAM_IS ("seamless-loop")) {
3261 if (play_loop && transport_rolling()) {
3262 // to reset diskstreams etc
3263 request_play_loop (true);
3266 } else if (PARAM_IS ("rf-speed")) {
3268 cumulative_rf_motion = 0;
3271 } else if (PARAM_IS ("click-sound")) {
3273 setup_click_sounds (1);
3275 } else if (PARAM_IS ("click-emphasis-sound")) {
3277 setup_click_sounds (-1);
3279 } else if (PARAM_IS ("clicking")) {
3281 if (Config->get_clicking()) {
3282 if (_click_io && click_data) { // don't require emphasis data
3289 } else if (PARAM_IS ("send-mtc")) {
3291 /* only set the internal flag if we have
3295 if (_mtc_port != 0) {
3296 session_send_mtc = Config->get_send_mtc();
3297 if (session_send_mtc) {
3298 /* mark us ready to send */
3299 next_quarter_frame_to_send = 0;
3302 session_send_mtc = false;
3305 } else if (PARAM_IS ("send-mmc")) {
3307 /* only set the internal flag if we have
3311 if (_mmc_port != 0) {
3312 session_send_mmc = Config->get_send_mmc();
3315 session_send_mmc = false;
3318 } else if (PARAM_IS ("midi-feedback")) {
3320 /* only set the internal flag if we have
3324 if (_mtc_port != 0) {
3325 session_midi_feedback = Config->get_midi_feedback();
3328 } else if (PARAM_IS ("jack-time-master")) {
3330 engine().reset_timebase ();
3332 } else if (PARAM_IS ("native-file-header-format")) {
3334 if (!first_file_header_format_reset) {
3335 reset_native_file_format ();
3338 first_file_header_format_reset = false;
3340 } else if (PARAM_IS ("native-file-data-format")) {
3342 if (!first_file_data_format_reset) {
3343 reset_native_file_format ();
3346 first_file_data_format_reset = false;
3348 } else if (PARAM_IS ("slave-source")) {
3349 set_slave_source (Config->get_slave_source());
3350 } else if (PARAM_IS ("remote-model")) {
3351 set_remote_control_ids ();
3352 } else if (PARAM_IS ("denormal-model")) {
3354 } else if (PARAM_IS ("history-depth")) {
3355 set_history_depth (Config->get_history_depth());
3356 } else if (PARAM_IS ("sync-all-route-ordering")) {
3357 sync_order_keys ("session");
3358 } else if (PARAM_IS ("initial-program-change")) {
3360 if (_mmc_port && Config->get_initial_program_change() >= 0) {
3361 MIDI::byte* buf = new MIDI::byte[2];
3363 buf[0] = MIDI::program; // channel zero by default
3364 buf[1] = (Config->get_initial_program_change() & 0x7f);
3365 deliver_midi (_mmc_port, buf, 2);
3376 Session::set_history_depth (uint32_t d)
3378 _history.set_depth (d);