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.
22 #include "libardour-config.h"
25 #define __STDC_FORMAT_MACROS 1
33 #include <sigc++/bind.h>
35 #include <cstdio> /* snprintf(3) ... grrr */
50 #include <sys/param.h>
51 #include <sys/mount.h>
55 #include <glibmm/thread.h>
57 #include "midi++/mmc.h"
58 #include "midi++/port.h"
60 #include "pbd/boost_debug.h"
61 #include "pbd/enumwriter.h"
62 #include "pbd/error.h"
63 #include "pbd/pathscanner.h"
64 #include "pbd/pthread_utils.h"
65 #include "pbd/search_path.h"
66 #include "pbd/stacktrace.h"
68 #include "ardour/audio_diskstream.h"
69 #include "ardour/audio_track.h"
70 #include "ardour/audioengine.h"
71 #include "ardour/audiofilesource.h"
72 #include "ardour/audioplaylist.h"
73 #include "ardour/audioregion.h"
74 #include "ardour/auditioner.h"
75 #include "ardour/buffer.h"
76 #include "ardour/butler.h"
77 #include "ardour/configuration.h"
78 #include "ardour/control_protocol_manager.h"
79 #include "ardour/crossfade.h"
80 #include "ardour/cycle_timer.h"
81 #include "ardour/directory_names.h"
82 #include "ardour/filename_extensions.h"
83 #include "ardour/io_processor.h"
84 #include "ardour/location.h"
85 #include "ardour/midi_diskstream.h"
86 #include "ardour/midi_patch_manager.h"
87 #include "ardour/midi_playlist.h"
88 #include "ardour/midi_region.h"
89 #include "ardour/midi_source.h"
90 #include "ardour/midi_track.h"
91 #include "ardour/named_selection.h"
92 #include "ardour/processor.h"
93 #include "ardour/region_factory.h"
94 #include "ardour/route_group.h"
95 #include "ardour/send.h"
96 #include "ardour/session.h"
97 #include "ardour/session_directory.h"
98 #include "ardour/session_metadata.h"
99 #include "ardour/session_state_utils.h"
100 #include "ardour/session_playlists.h"
101 #include "ardour/session_utils.h"
102 #include "ardour/silentfilesource.h"
103 #include "ardour/slave.h"
104 #include "ardour/smf_source.h"
105 #include "ardour/sndfile_helpers.h"
106 #include "ardour/sndfilesource.h"
107 #include "ardour/source_factory.h"
108 #include "ardour/template_utils.h"
109 #include "ardour/tempo.h"
110 #include "ardour/ticker.h"
111 #include "ardour/user_bundle.h"
112 #include "ardour/utils.h"
113 #include "ardour/utils.h"
114 #include "ardour/version.h"
115 #include "ardour/playlist_factory.h"
117 #include "control_protocol/control_protocol.h"
123 using namespace ARDOUR;
127 Session::first_stage_init (string fullpath, string snapshot_name)
129 if (fullpath.length() == 0) {
131 throw failed_constructor();
134 char buf[PATH_MAX+1];
135 if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
136 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
138 throw failed_constructor();
143 if (_path[_path.length()-1] != '/') {
147 if (Glib::file_test (_path, Glib::FILE_TEST_EXISTS) && ::access (_path.c_str(), W_OK)) {
148 cerr << "Session non-writable based on " << _path << endl;
151 cerr << "Session writable based on " << _path << endl;
155 /* these two are just provisional settings. set_state()
156 will likely override them.
159 _name = _current_snapshot_name = snapshot_name;
161 set_history_depth (Config->get_history_depth());
163 _current_frame_rate = _engine.frame_rate ();
164 _nominal_frame_rate = _current_frame_rate;
165 _base_frame_rate = _current_frame_rate;
167 _tempo_map = new TempoMap (_current_frame_rate);
168 _tempo_map->StateChanged.connect (mem_fun (*this, &Session::tempo_map_changed));
171 _non_soloed_outs_muted = false;
173 g_atomic_int_set (&processing_prohibited, 0);
174 _transport_speed = 0;
175 _last_transport_speed = 0;
176 _target_transport_speed = 0;
177 auto_play_legal = false;
178 transport_sub_state = 0;
179 _transport_frame = 0;
180 _requested_return_frame = -1;
181 end_location = new Location (0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
182 start_location = new Location (0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart)));
183 g_atomic_int_set (&_record_status, Disabled);
184 loop_changing = false;
187 _last_roll_location = 0;
188 _last_record_location = 0;
189 pending_locate_frame = 0;
190 pending_locate_roll = false;
191 pending_locate_flush = false;
192 state_was_pending = false;
194 outbound_mtc_timecode_frame = 0;
195 next_quarter_frame_to_send = -1;
196 current_block_size = 0;
197 solo_update_disabled = false;
198 _have_captured = false;
199 _worst_output_latency = 0;
200 _worst_input_latency = 0;
201 _worst_track_latency = 0;
202 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
203 _was_seamless = Config->get_seamless_loop ();
205 session_send_mmc = false;
206 session_send_mtc = false;
207 g_atomic_int_set (&_playback_load, 100);
208 g_atomic_int_set (&_capture_load, 100);
209 g_atomic_int_set (&_playback_load_min, 100);
210 g_atomic_int_set (&_capture_load_min, 100);
213 _exporting_realtime = false;
214 _gain_automation_buffer = 0;
215 _pan_automation_buffer = 0;
217 pending_abort = false;
218 destructive_index = 0;
219 first_file_data_format_reset = true;
220 first_file_header_format_reset = true;
221 post_export_sync = false;
222 //midi_thread = (pthread_t) 0;
224 AudioDiskstream::allocate_working_buffers();
226 /* default short fade = 15ms */
228 Crossfade::set_short_xfade_length ((nframes_t) floor (config.get_short_xfade_seconds() * frame_rate()));
229 SndFileSource::setup_standard_crossfades (*this, frame_rate());
231 last_mmc_step.tv_sec = 0;
232 last_mmc_step.tv_usec = 0;
235 /* click sounds are unset by default, which causes us to internal
236 waveforms for clicks.
240 click_emphasis_length = 0;
243 process_function = &Session::process_with_events;
245 if (config.get_use_video_sync()) {
246 waiting_for_sync_offset = true;
248 waiting_for_sync_offset = false;
251 last_timecode_when = 0;
252 _timecode_offset = 0;
253 _timecode_offset_negative = true;
254 last_timecode_valid = false;
258 last_rr_session_dir = session_dirs.begin();
259 refresh_disk_space ();
261 // set_default_fade (0.2, 5.0); /* steepness, millisecs */
265 average_slave_delta = 1800; // !!! why 1800 ????
266 have_first_delta_accumulator = false;
267 delta_accumulator_cnt = 0;
268 _slave_state = Stopped;
270 _engine.GraphReordered.connect (mem_fun (*this, &Session::graph_reordered));
272 /* These are all static "per-class" signals */
274 RegionFactory::CheckNewRegion.connect (mem_fun (*this, &Session::add_region));
275 SourceFactory::SourceCreated.connect (mem_fun (*this, &Session::add_source));
276 PlaylistFactory::PlaylistCreated.connect (mem_fun (*this, &Session::add_playlist));
277 Processor::ProcessorCreated.connect (mem_fun (*this, &Session::add_processor));
278 NamedSelection::NamedSelectionCreated.connect (mem_fun (*this, &Session::add_named_selection));
279 AutomationList::AutomationListCreated.connect (mem_fun (*this, &Session::add_automation_list));
281 Controllable::Destroyed.connect (mem_fun (*this, &Session::remove_controllable));
283 IO::PortCountChanged.connect (mem_fun (*this, &Session::ensure_buffers));
285 /* stop IO objects from doing stuff until we're ready for them */
287 Delivery::disable_panners ();
288 IO::disable_connecting ();
292 Session::second_stage_init (bool new_session)
294 AudioFileSource::set_peak_dir (_session_dir->peak_path().to_string());
297 if (load_state (_current_snapshot_name)) {
300 remove_empty_sounds ();
303 if (_butler->start_thread()) {
307 if (start_midi_thread ()) {
311 // set_state() will call setup_raid_path(), but if it's a new session we need
312 // to call setup_raid_path() here.
315 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
319 setup_raid_path(_path);
322 /* we can't save till after ::when_engine_running() is called,
323 because otherwise we save state with no connections made.
324 therefore, we reset _state_of_the_state because ::set_state()
325 will have cleared it.
327 we also have to include Loading so that any events that get
328 generated between here and the end of ::when_engine_running()
329 will be processed directly rather than queued.
332 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
335 _locations.changed.connect (mem_fun (this, &Session::locations_changed));
336 _locations.added.connect (mem_fun (this, &Session::locations_added));
337 setup_click_sounds (0);
338 setup_midi_control ();
340 /* Pay attention ... */
342 _engine.Halted.connect (mem_fun (*this, &Session::engine_halted));
343 _engine.Xrun.connect (mem_fun (*this, &Session::xrun_recovery));
346 when_engine_running();
349 /* handle this one in a different way than all others, so that its clear what happened */
351 catch (AudioEngine::PortRegistrationFailure& err) {
352 error << err.what() << endmsg;
360 BootMessage (_("Reset Remote Controls"));
362 send_full_time_code (0);
363 _engine.transport_locate (0);
364 deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
365 deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
367 MidiClockTicker::instance().set_session(*this);
368 MIDI::Name::MidiPatchManager::instance().set_session(*this);
370 /* initial program change will be delivered later; see ::config_changed() */
372 BootMessage (_("Reset Control Protocols"));
374 ControlProtocolManager::instance().set_session (*this);
376 config.set_end_marker_is_free (new_session);
378 _state_of_the_state = Clean;
380 DirtyChanged (); /* EMIT SIGNAL */
382 if (state_was_pending) {
383 save_state (_current_snapshot_name);
384 remove_pending_capture_state ();
385 state_was_pending = false;
388 BootMessage (_("Session loading complete"));
394 Session::raid_path () const
396 SearchPath raid_search_path;
398 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
399 raid_search_path += sys::path((*i).path);
402 return raid_search_path.to_string ();
406 Session::setup_raid_path (string path)
415 session_dirs.clear ();
417 SearchPath search_path(path);
418 SearchPath sound_search_path;
419 SearchPath midi_search_path;
421 for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
422 sp.path = (*i).to_string ();
423 sp.blocks = 0; // not needed
424 session_dirs.push_back (sp);
426 SessionDirectory sdir(sp.path);
428 sound_search_path += sdir.sound_path ();
429 midi_search_path += sdir.midi_path ();
432 // set the search path for each data type
433 FileSource::set_search_path (DataType::AUDIO, sound_search_path.to_string ());
434 SMFSource::set_search_path (DataType::MIDI, midi_search_path.to_string ());
436 // reset the round-robin soundfile path thingie
437 last_rr_session_dir = session_dirs.begin();
441 Session::path_is_within_session (const std::string& path)
443 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
444 if (path.find ((*i).path) == 0) {
452 Session::ensure_subdirs ()
456 dir = session_directory().peak_path().to_string();
458 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
459 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
463 dir = session_directory().sound_path().to_string();
465 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
466 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
470 dir = session_directory().midi_path().to_string();
472 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
473 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
477 dir = session_directory().dead_sound_path().to_string();
479 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
480 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
484 dir = session_directory().export_path().to_string();
486 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
487 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
491 dir = analysis_dir ();
493 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
494 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
502 Session::create (bool& new_session, const string& mix_template, nframes_t initial_length)
505 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
506 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
510 if (ensure_subdirs ()) {
514 /* check new_session so we don't overwrite an existing one */
516 if (!mix_template.empty()) {
517 std::string in_path = mix_template;
519 ifstream in(in_path.c_str());
522 string out_path = _path;
524 out_path += statefile_suffix;
526 ofstream out(out_path.c_str());
531 // okay, session is set up. Treat like normal saved
532 // session from now on.
538 error << string_compose (_("Could not open %1 for writing mix template"), out_path)
544 error << string_compose (_("Could not open mix template %1 for reading"), in_path)
551 /* Instantiate metadata */
553 _metadata = new SessionMetadata ();
555 /* set initial start + end point */
557 start_location->set_end (0);
558 _locations.add (start_location);
560 end_location->set_end (initial_length);
561 _locations.add (end_location);
563 _state_of_the_state = Clean;
572 Session::load_diskstreams (const XMLNode& node)
575 XMLNodeConstIterator citer;
577 clist = node.children();
579 for (citer = clist.begin(); citer != clist.end(); ++citer) {
582 /* diskstreams added automatically by DiskstreamCreated handler */
583 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
584 AudioDiskstream* dsp (new AudioDiskstream (*this, **citer));
585 boost::shared_ptr<AudioDiskstream> dstream (dsp);
586 add_diskstream (dstream);
587 } else if ((*citer)->name() == "MidiDiskstream") {
588 boost::shared_ptr<MidiDiskstream> dstream (new MidiDiskstream (*this, **citer));
589 add_diskstream (dstream);
591 error << _("Session: unknown diskstream type in XML") << endmsg;
595 catch (failed_constructor& err) {
596 error << _("Session: could not load diskstream via XML state") << endmsg;
605 Session::maybe_write_autosave()
607 if (dirty() && record_status() != Recording) {
608 save_state("", true);
613 Session::remove_pending_capture_state ()
615 sys::path pending_state_file_path(_session_dir->root_path());
617 pending_state_file_path /= legalize_for_path (_current_snapshot_name) + pending_suffix;
621 sys::remove (pending_state_file_path);
623 catch(sys::filesystem_error& ex)
625 error << string_compose(_("Could remove pending capture state at path \"%1\" (%2)"),
626 pending_state_file_path.to_string(), ex.what()) << endmsg;
630 /** Rename a state file.
631 * @param snapshot_name Snapshot name.
634 Session::rename_state (string old_name, string new_name)
636 if (old_name == _current_snapshot_name || old_name == _name) {
637 /* refuse to rename the current snapshot or the "main" one */
641 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
642 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
644 const sys::path old_xml_path = _session_dir->root_path() / old_xml_filename;
645 const sys::path new_xml_path = _session_dir->root_path() / new_xml_filename;
649 sys::rename (old_xml_path, new_xml_path);
651 catch (const sys::filesystem_error& err)
653 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
654 old_name, new_name, err.what()) << endmsg;
658 /** Remove a state file.
659 * @param snapshot_name Snapshot name.
662 Session::remove_state (string snapshot_name)
664 if (snapshot_name == _current_snapshot_name || snapshot_name == _name) {
665 // refuse to remove the current snapshot or the "main" one
669 sys::path xml_path(_session_dir->root_path());
671 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
673 if (!create_backup_file (xml_path)) {
674 // don't remove it if a backup can't be made
675 // create_backup_file will log the error.
680 sys::remove (xml_path);
684 Session::save_state (string snapshot_name, bool pending)
687 sys::path xml_path(_session_dir->root_path());
689 if (!_writable || (_state_of_the_state & CannotSave)) {
693 if (!_engine.connected ()) {
694 error << _("Ardour's audio engine is not connected and state saving would lose all I/O connections. Session not saved")
699 /* tell sources we're saving first, in case they write out to a new file
700 * which should be saved with the state rather than the old one */
701 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i)
702 i->second->session_saved();
704 tree.set_root (&get_state());
706 if (snapshot_name.empty()) {
707 snapshot_name = _current_snapshot_name;
712 /* proper save: use statefile_suffix (.ardour in English) */
714 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
716 /* make a backup copy of the old file */
718 if (sys::exists(xml_path) && !create_backup_file (xml_path)) {
719 // create_backup_file will log the error
725 /* pending save: use pending_suffix (.pending in English) */
726 xml_path /= legalize_for_path (snapshot_name) + pending_suffix;
729 sys::path tmp_path(_session_dir->root_path());
731 tmp_path /= legalize_for_path (snapshot_name) + temp_suffix;
733 // cerr << "actually writing state to " << xml_path.to_string() << endl;
735 if (!tree.write (tmp_path.to_string())) {
736 error << string_compose (_("state could not be saved to %1"), tmp_path.to_string()) << endmsg;
737 sys::remove (tmp_path);
742 if (rename (tmp_path.to_string().c_str(), xml_path.to_string().c_str()) != 0) {
743 error << string_compose (_("could not rename temporary session file %1 to %2"),
744 tmp_path.to_string(), xml_path.to_string()) << endmsg;
745 sys::remove (tmp_path);
752 save_history (snapshot_name);
754 bool was_dirty = dirty();
756 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
759 DirtyChanged (); /* EMIT SIGNAL */
762 StateSaved (snapshot_name); /* EMIT SIGNAL */
769 Session::restore_state (string snapshot_name)
771 if (load_state (snapshot_name) == 0) {
772 set_state (*state_tree->root(), Stateful::loading_state_version);
779 Session::load_state (string snapshot_name)
784 state_was_pending = false;
786 /* check for leftover pending state from a crashed capture attempt */
788 sys::path xmlpath(_session_dir->root_path());
789 xmlpath /= legalize_for_path (snapshot_name) + pending_suffix;
791 if (sys::exists (xmlpath)) {
793 /* there is pending state from a crashed capture attempt */
795 if (AskAboutPendingState()) {
796 state_was_pending = true;
800 if (!state_was_pending) {
801 xmlpath = _session_dir->root_path();
802 xmlpath /= legalize_for_path (snapshot_name) + statefile_suffix;
805 if (!sys::exists (xmlpath)) {
806 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath.to_string()) << endmsg;
810 state_tree = new XMLTree;
814 /* writable() really reflects the whole folder, but if for any
815 reason the session state file can't be written to, still
819 if (::access (xmlpath.to_string().c_str(), W_OK) != 0) {
823 if (!state_tree->read (xmlpath.to_string())) {
824 error << string_compose(_("Could not understand ardour file %1"), xmlpath.to_string()) << endmsg;
830 XMLNode& root (*state_tree->root());
832 if (root.name() != X_("Session")) {
833 error << string_compose (_("Session file %1 is not an Ardour session"), xmlpath.to_string()) << endmsg;
839 const XMLProperty* prop;
841 if ((prop = root.property ("version")) == 0) {
842 /* no version implies very old version of Ardour */
843 Stateful::loading_state_version = 1000;
849 sscanf (prop->value().c_str(), "%d.%d.%d", &major, &minor, µ);
850 Stateful::loading_state_version = (major * 1000) + minor;
853 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION) {
855 sys::path backup_path(_session_dir->root_path());
857 backup_path /= legalize_for_path (snapshot_name) + "-1" + statefile_suffix;
859 // only create a backup once
860 if (sys::exists (backup_path)) {
864 info << string_compose (_("Copying old session file %1 to %2\nUse %2 with Ardour versions before 2.0 from now on"),
865 xmlpath.to_string(), backup_path.to_string())
870 sys::copy_file (xmlpath, backup_path);
872 catch(sys::filesystem_error& ex)
874 error << string_compose (_("Unable to make backup of state file %1 (%2)"),
875 xmlpath.to_string(), ex.what())
885 Session::load_options (const XMLNode& node)
887 LocaleGuard lg (X_("POSIX"));
888 config.set_variables (node);
899 Session::get_template()
901 /* if we don't disable rec-enable, diskstreams
902 will believe they need to store their capture
903 sources in their state node.
906 disable_record (false);
912 Session::state(bool full_state)
914 XMLNode* node = new XMLNode("Session");
917 // store libardour version, just in case
919 snprintf(buf, sizeof(buf), "%d.%d.%d", libardour3_major_version, libardour3_minor_version, libardour3_micro_version);
920 node->add_property("version", string(buf));
922 /* store configuration settings */
926 node->add_property ("name", _name);
927 snprintf (buf, sizeof (buf), "%" PRId32, _nominal_frame_rate);
928 node->add_property ("sample-rate", buf);
930 if (session_dirs.size() > 1) {
934 vector<space_and_path>::iterator i = session_dirs.begin();
935 vector<space_and_path>::iterator next;
937 ++i; /* skip the first one */
941 while (i != session_dirs.end()) {
945 if (next != session_dirs.end()) {
955 child = node->add_child ("Path");
956 child->add_content (p);
960 /* save the ID counter */
962 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
963 node->add_property ("id-counter", buf);
965 /* various options */
967 node->add_child_nocopy (config.get_variables ());
969 node->add_child_nocopy (_metadata->get_state());
971 child = node->add_child ("Sources");
974 Glib::Mutex::Lock sl (source_lock);
976 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
978 /* Don't save information about non-destructive file sources that are empty */
979 /* FIXME: MIDI breaks if this is made FileSource like it should be... */
981 boost::shared_ptr<AudioFileSource> fs;
982 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (siter->second)) != 0) {
983 if (!fs->destructive()) {
984 if (fs->length(fs->timeline_position()) == 0) {
990 child->add_child_nocopy (siter->second->get_state());
994 child = node->add_child ("Regions");
997 Glib::Mutex::Lock rl (region_lock);
999 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
1001 /* only store regions not attached to playlists */
1003 if (i->second->playlist() == 0) {
1004 child->add_child_nocopy (i->second->state (true));
1009 child = node->add_child ("DiskStreams");
1012 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1013 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1014 if (!(*i)->hidden()) {
1015 child->add_child_nocopy ((*i)->get_state());
1021 node->add_child_nocopy (_locations.get_state());
1023 // for a template, just create a new Locations, populate it
1024 // with the default start and end, and get the state for that.
1026 Location* start = new Location(0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart)));
1027 Location* end = new Location(0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
1030 end->set_end(compute_initial_length());
1032 node->add_child_nocopy (loc.get_state());
1035 child = node->add_child ("Bundles");
1037 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1038 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1039 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1041 child->add_child_nocopy (b->get_state());
1046 child = node->add_child ("Routes");
1048 boost::shared_ptr<RouteList> r = routes.reader ();
1050 RoutePublicOrderSorter cmp;
1051 RouteList public_order (*r);
1052 public_order.sort (cmp);
1054 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1055 if (!(*i)->is_hidden()) {
1057 child->add_child_nocopy ((*i)->get_state());
1059 child->add_child_nocopy ((*i)->get_template());
1065 playlists->add_state (node, full_state);
1067 child = node->add_child ("RouteGroups");
1068 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1069 child->add_child_nocopy ((*i)->get_state());
1073 child = node->add_child ("Click");
1074 child->add_child_nocopy (_click_io->state (full_state));
1078 child = node->add_child ("NamedSelections");
1079 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1081 child->add_child_nocopy ((*i)->get_state());
1086 node->add_child_nocopy (_tempo_map->get_state());
1088 node->add_child_nocopy (get_control_protocol_state());
1091 node->add_child_copy (*_extra_xml);
1098 Session::get_control_protocol_state ()
1100 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1101 return cpm.get_state();
1105 Session::set_state (const XMLNode& node, int version)
1109 const XMLProperty* prop;
1112 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1114 if (node.name() != X_("Session")){
1115 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1119 if ((prop = node.property ("version")) != 0) {
1120 version = atoi (prop->value ()) * 1000;
1123 if ((prop = node.property ("name")) != 0) {
1124 _name = prop->value ();
1127 if ((prop = node.property (X_("sample-rate"))) != 0) {
1129 _nominal_frame_rate = atoi (prop->value());
1131 if (_nominal_frame_rate != _current_frame_rate) {
1132 if (AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate)) {
1138 setup_raid_path(_session_dir->root_path().to_string());
1140 if ((prop = node.property (X_("id-counter"))) != 0) {
1142 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1143 ID::init_counter (x);
1145 /* old sessions used a timebased counter, so fake
1146 the startup ID counter based on a standard
1151 ID::init_counter (now);
1155 IO::disable_connecting ();
1157 /* Object loading order:
1162 MIDI Control // relies on data from Options/Config
1176 if ((child = find_named_node (node, "Extra")) != 0) {
1177 _extra_xml = new XMLNode (*child);
1180 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1181 load_options (*child);
1182 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1183 load_options (*child);
1185 error << _("Session: XML state has no options section") << endmsg;
1188 if (use_config_midi_ports ()) {
1191 if (version >= 3000) {
1192 if ((child = find_named_node (node, "Metadata")) == 0) {
1193 warning << _("Session: XML state has no metadata section") << endmsg;
1194 } else if (_metadata->set_state (*child, version)) {
1199 if ((child = find_named_node (node, "Locations")) == 0) {
1200 error << _("Session: XML state has no locations section") << endmsg;
1202 } else if (_locations.set_state (*child, version)) {
1208 if ((location = _locations.auto_loop_location()) != 0) {
1209 set_auto_loop_location (location);
1212 if ((location = _locations.auto_punch_location()) != 0) {
1213 set_auto_punch_location (location);
1216 if ((location = _locations.end_location()) == 0) {
1217 _locations.add (end_location);
1219 delete end_location;
1220 end_location = location;
1223 if ((location = _locations.start_location()) == 0) {
1224 _locations.add (start_location);
1226 delete start_location;
1227 start_location = location;
1230 AudioFileSource::set_header_position_offset (start_location->start());
1232 if ((child = find_named_node (node, "Sources")) == 0) {
1233 error << _("Session: XML state has no sources section") << endmsg;
1235 } else if (load_sources (*child)) {
1239 if ((child = find_named_node (node, "Regions")) == 0) {
1240 error << _("Session: XML state has no Regions section") << endmsg;
1242 } else if (load_regions (*child)) {
1246 if ((child = find_named_node (node, "Playlists")) == 0) {
1247 error << _("Session: XML state has no playlists section") << endmsg;
1249 } else if (playlists->load (*this, *child)) {
1253 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1255 } else if (playlists->load_unused (*this, *child)) {
1259 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1260 if (load_named_selections (*child)) {
1265 if ((child = find_named_node (node, "DiskStreams")) == 0) {
1266 error << _("Session: XML state has no diskstreams section") << endmsg;
1268 } else if (load_diskstreams (*child)) {
1272 if (version >= 3000) {
1273 if ((child = find_named_node (node, "Bundles")) == 0) {
1274 warning << _("Session: XML state has no bundles section") << endmsg;
1277 /* We can't load Bundles yet as they need to be able
1278 to convert from port names to Port objects, which can't happen until
1280 _bundle_xml_node = new XMLNode (*child);
1284 if (version >= 3000) {
1286 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1287 error << _("Session: XML state has no route groups section") << endmsg;
1289 } else if (load_route_groups (*child, version)) {
1293 } else if (version < 3000) {
1295 if ((child = find_named_node (node, "EditGroups")) == 0) {
1296 error << _("Session: XML state has no edit groups section") << endmsg;
1298 } else if (load_route_groups (*child, version)) {
1302 if ((child = find_named_node (node, "MixGroups")) == 0) {
1303 error << _("Session: XML state has no mix groups section") << endmsg;
1305 } else if (load_route_groups (*child, version)) {
1310 if ((child = find_named_node (node, "TempoMap")) == 0) {
1311 error << _("Session: XML state has no Tempo Map section") << endmsg;
1313 } else if (_tempo_map->set_state (*child, version)) {
1317 if ((child = find_named_node (node, "Routes")) == 0) {
1318 error << _("Session: XML state has no routes section") << endmsg;
1320 } else if (load_routes (*child, version)) {
1324 if ((child = find_named_node (node, "Click")) == 0) {
1325 warning << _("Session: XML state has no click section") << endmsg;
1326 } else if (_click_io) {
1327 _click_io->set_state (*child, version);
1330 if ((child = find_named_node (node, "ControlProtocols")) != 0) {
1331 ControlProtocolManager::instance().set_protocol_states (*child);
1334 /* here beginneth the second phase ... */
1336 StateReady (); /* EMIT SIGNAL */
1345 Session::load_routes (const XMLNode& node, int version)
1348 XMLNodeConstIterator niter;
1349 RouteList new_routes;
1351 nlist = node.children();
1355 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1357 boost::shared_ptr<Route> route (XMLRouteFactory (**niter, version));
1360 error << _("Session: cannot create Route from XML description.") << endmsg;
1364 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1366 new_routes.push_back (route);
1369 add_routes (new_routes, false);
1374 boost::shared_ptr<Route>
1375 Session::XMLRouteFactory (const XMLNode& node, int version)
1377 if (node.name() != "Route") {
1378 return boost::shared_ptr<Route> ((Route*) 0);
1381 bool has_diskstream = (node.property ("diskstream") != 0 || node.property ("diskstream-id") != 0);
1383 DataType type = DataType::AUDIO;
1384 const XMLProperty* prop = node.property("default-type");
1387 type = DataType(prop->value());
1390 assert(type != DataType::NIL);
1392 if (has_diskstream) {
1393 if (type == DataType::AUDIO) {
1394 AudioTrack* at = new AudioTrack (*this, node, version);
1395 // boost_debug_shared_ptr_mark_interesting (at, typeid (at).name());
1396 boost::shared_ptr<Route> ret (at);
1399 boost::shared_ptr<Route> ret (new MidiTrack (*this, node, version));
1403 boost::shared_ptr<Route> ret (new Route (*this, node));
1409 Session::load_regions (const XMLNode& node)
1412 XMLNodeConstIterator niter;
1413 boost::shared_ptr<Region> region;
1415 nlist = node.children();
1419 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1420 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1421 error << _("Session: cannot create Region from XML description.");
1422 const XMLProperty *name = (**niter).property("name");
1425 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1435 boost::shared_ptr<Region>
1436 Session::XMLRegionFactory (const XMLNode& node, bool full)
1438 const XMLProperty* type = node.property("type");
1442 if ( !type || type->value() == "audio" ) {
1444 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1446 } else if (type->value() == "midi") {
1448 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1452 } catch (failed_constructor& err) {
1453 return boost::shared_ptr<Region> ();
1456 return boost::shared_ptr<Region> ();
1459 boost::shared_ptr<AudioRegion>
1460 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1462 const XMLProperty* prop;
1463 boost::shared_ptr<Source> source;
1464 boost::shared_ptr<AudioSource> as;
1466 SourceList master_sources;
1467 uint32_t nchans = 1;
1470 if (node.name() != X_("Region")) {
1471 return boost::shared_ptr<AudioRegion>();
1474 if ((prop = node.property (X_("channels"))) != 0) {
1475 nchans = atoi (prop->value().c_str());
1478 if ((prop = node.property ("name")) == 0) {
1479 cerr << "no name for this region\n";
1483 if ((prop = node.property (X_("source-0"))) == 0) {
1484 if ((prop = node.property ("source")) == 0) {
1485 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1486 return boost::shared_ptr<AudioRegion>();
1490 PBD::ID s_id (prop->value());
1492 if ((source = source_by_id (s_id)) == 0) {
1493 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1494 return boost::shared_ptr<AudioRegion>();
1497 as = boost::dynamic_pointer_cast<AudioSource>(source);
1499 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1500 return boost::shared_ptr<AudioRegion>();
1503 sources.push_back (as);
1505 /* pickup other channels */
1507 for (uint32_t n=1; n < nchans; ++n) {
1508 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1509 if ((prop = node.property (buf)) != 0) {
1511 PBD::ID id2 (prop->value());
1513 if ((source = source_by_id (id2)) == 0) {
1514 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1515 return boost::shared_ptr<AudioRegion>();
1518 as = boost::dynamic_pointer_cast<AudioSource>(source);
1520 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1521 return boost::shared_ptr<AudioRegion>();
1523 sources.push_back (as);
1527 for (uint32_t n = 0; n < nchans; ++n) {
1528 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1529 if ((prop = node.property (buf)) != 0) {
1531 PBD::ID id2 (prop->value());
1533 if ((source = source_by_id (id2)) == 0) {
1534 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1535 return boost::shared_ptr<AudioRegion>();
1538 as = boost::dynamic_pointer_cast<AudioSource>(source);
1540 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1541 return boost::shared_ptr<AudioRegion>();
1543 master_sources.push_back (as);
1548 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1550 /* a final detail: this is the one and only place that we know how long missing files are */
1552 if (region->whole_file()) {
1553 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1554 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1556 sfp->set_length (region->length());
1561 if (!master_sources.empty()) {
1562 if (master_sources.size() != nchans) {
1563 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1565 region->set_master_sources (master_sources);
1573 catch (failed_constructor& err) {
1574 return boost::shared_ptr<AudioRegion>();
1578 boost::shared_ptr<MidiRegion>
1579 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1581 const XMLProperty* prop;
1582 boost::shared_ptr<Source> source;
1583 boost::shared_ptr<MidiSource> ms;
1585 uint32_t nchans = 1;
1587 if (node.name() != X_("Region")) {
1588 return boost::shared_ptr<MidiRegion>();
1591 if ((prop = node.property (X_("channels"))) != 0) {
1592 nchans = atoi (prop->value().c_str());
1595 if ((prop = node.property ("name")) == 0) {
1596 cerr << "no name for this region\n";
1600 // Multiple midi channels? that's just crazy talk
1601 assert(nchans == 1);
1603 if ((prop = node.property (X_("source-0"))) == 0) {
1604 if ((prop = node.property ("source")) == 0) {
1605 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1606 return boost::shared_ptr<MidiRegion>();
1610 PBD::ID s_id (prop->value());
1612 if ((source = source_by_id (s_id)) == 0) {
1613 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1614 return boost::shared_ptr<MidiRegion>();
1617 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1619 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1620 return boost::shared_ptr<MidiRegion>();
1623 sources.push_back (ms);
1626 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1627 /* a final detail: this is the one and only place that we know how long missing files are */
1629 if (region->whole_file()) {
1630 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1631 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1633 sfp->set_length (region->length());
1641 catch (failed_constructor& err) {
1642 return boost::shared_ptr<MidiRegion>();
1647 Session::get_sources_as_xml ()
1650 XMLNode* node = new XMLNode (X_("Sources"));
1651 Glib::Mutex::Lock lm (source_lock);
1653 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1654 node->add_child_nocopy (i->second->get_state());
1661 Session::path_from_region_name (DataType type, string name, string identifier)
1663 char buf[PATH_MAX+1];
1665 SessionDirectory sdir(get_best_session_directory_for_new_source());
1666 sys::path source_dir = ((type == DataType::AUDIO)
1667 ? sdir.sound_path() : sdir.midi_path());
1669 string ext = ((type == DataType::AUDIO) ? ".wav" : ".mid");
1671 for (n = 0; n < 999999; ++n) {
1672 if (identifier.length()) {
1673 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1674 identifier.c_str(), n, ext.c_str());
1676 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1680 sys::path source_path = source_dir / buf;
1682 if (!sys::exists (source_path)) {
1683 return source_path.to_string();
1687 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1696 Session::load_sources (const XMLNode& node)
1699 XMLNodeConstIterator niter;
1700 boost::shared_ptr<Source> source;
1702 nlist = node.children();
1706 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1708 if ((source = XMLSourceFactory (**niter)) == 0) {
1709 error << _("Session: cannot create Source from XML description.") << endmsg;
1711 } catch (MissingSource& err) {
1712 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1713 source = SourceFactory::createSilent (*this, **niter, max_frames, _current_frame_rate);
1720 boost::shared_ptr<Source>
1721 Session::XMLSourceFactory (const XMLNode& node)
1723 if (node.name() != "Source") {
1724 return boost::shared_ptr<Source>();
1728 /* note: do peak building in another thread when loading session state */
1729 return SourceFactory::create (*this, node, true);
1732 catch (failed_constructor& err) {
1733 error << _("Found a sound file that cannot be used by Ardour. Talk to the progammers.") << endmsg;
1734 return boost::shared_ptr<Source>();
1739 Session::save_template (string template_name)
1743 if (_state_of_the_state & CannotSave) {
1747 sys::path user_template_dir(user_template_directory());
1751 sys::create_directories (user_template_dir);
1753 catch(sys::filesystem_error& ex)
1755 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"),
1756 user_template_dir.to_string(), ex.what()) << endmsg;
1760 tree.set_root (&get_template());
1762 sys::path template_file_path(user_template_dir);
1763 template_file_path /= template_name + template_suffix;
1765 if (sys::exists (template_file_path))
1767 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1768 template_file_path.to_string()) << endmsg;
1772 if (!tree.write (template_file_path.to_string())) {
1773 error << _("mix template not saved") << endmsg;
1781 Session::rename_template (string old_name, string new_name)
1783 sys::path old_path (user_template_directory());
1784 old_path /= old_name + template_suffix;
1786 sys::path new_path(user_template_directory());
1787 new_path /= new_name + template_suffix;
1789 if (sys::exists (new_path)) {
1790 warning << string_compose(_("Template \"%1\" already exists - template not renamed"),
1791 new_path.to_string()) << endmsg;
1796 sys::rename (old_path, new_path);
1804 Session::delete_template (string name)
1806 sys::path path = user_template_directory();
1807 path /= name + template_suffix;
1818 Session::refresh_disk_space ()
1821 struct statfs statfsbuf;
1822 vector<space_and_path>::iterator i;
1823 Glib::Mutex::Lock lm (space_lock);
1826 /* get freespace on every FS that is part of the session path */
1828 _total_free_4k_blocks = 0;
1830 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1831 statfs ((*i).path.c_str(), &statfsbuf);
1833 scale = statfsbuf.f_bsize/4096.0;
1835 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
1836 _total_free_4k_blocks += (*i).blocks;
1842 Session::get_best_session_directory_for_new_source ()
1844 vector<space_and_path>::iterator i;
1845 string result = _session_dir->root_path().to_string();
1847 /* handle common case without system calls */
1849 if (session_dirs.size() == 1) {
1853 /* OK, here's the algorithm we're following here:
1855 We want to select which directory to use for
1856 the next file source to be created. Ideally,
1857 we'd like to use a round-robin process so as to
1858 get maximum performance benefits from splitting
1859 the files across multiple disks.
1861 However, in situations without much diskspace, an
1862 RR approach may end up filling up a filesystem
1863 with new files while others still have space.
1864 Its therefore important to pay some attention to
1865 the freespace in the filesystem holding each
1866 directory as well. However, if we did that by
1867 itself, we'd keep creating new files in the file
1868 system with the most space until it was as full
1869 as all others, thus negating any performance
1870 benefits of this RAID-1 like approach.
1872 So, we use a user-configurable space threshold. If
1873 there are at least 2 filesystems with more than this
1874 much space available, we use RR selection between them.
1875 If not, then we pick the filesystem with the most space.
1877 This gets a good balance between the two
1881 refresh_disk_space ();
1883 int free_enough = 0;
1885 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1886 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
1891 if (free_enough >= 2) {
1892 /* use RR selection process, ensuring that the one
1896 i = last_rr_session_dir;
1899 if (++i == session_dirs.end()) {
1900 i = session_dirs.begin();
1903 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
1904 if (create_session_directory ((*i).path)) {
1906 last_rr_session_dir = i;
1911 } while (i != last_rr_session_dir);
1915 /* pick FS with the most freespace (and that
1916 seems to actually work ...)
1919 vector<space_and_path> sorted;
1920 space_and_path_ascending_cmp cmp;
1922 sorted = session_dirs;
1923 sort (sorted.begin(), sorted.end(), cmp);
1925 for (i = sorted.begin(); i != sorted.end(); ++i) {
1926 if (create_session_directory ((*i).path)) {
1928 last_rr_session_dir = i;
1938 Session::load_named_selections (const XMLNode& node)
1941 XMLNodeConstIterator niter;
1944 nlist = node.children();
1948 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1950 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
1951 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
1959 Session::XMLNamedSelectionFactory (const XMLNode& node)
1962 return new NamedSelection (*this, node);
1965 catch (failed_constructor& err) {
1971 Session::automation_dir () const
1973 return Glib::build_filename (_path, "automation");
1977 Session::analysis_dir () const
1979 return Glib::build_filename (_path, "analysis");
1983 Session::load_bundles (XMLNode const & node)
1985 XMLNodeList nlist = node.children();
1986 XMLNodeConstIterator niter;
1990 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1991 if ((*niter)->name() == "InputBundle") {
1992 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
1993 } else if ((*niter)->name() == "OutputBundle") {
1994 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
1996 error << string_compose(_("Unknown node \"%1\" found in Bundles list from state file"), (*niter)->name()) << endmsg;
2005 Session::load_route_groups (const XMLNode& node, int version)
2007 XMLNodeList nlist = node.children();
2008 XMLNodeConstIterator niter;
2012 if (version >= 3000) {
2014 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2015 if ((*niter)->name() == "RouteGroup") {
2016 RouteGroup* rg = new RouteGroup (*this, "");
2017 add_route_group (rg);
2018 rg->set_state (**niter, version);
2022 } else if (version < 3000) {
2024 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2025 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2026 RouteGroup* rg = new RouteGroup (*this, "");
2027 add_route_group (rg);
2028 rg->set_state (**niter, version);
2037 Session::auto_save()
2039 save_state (_current_snapshot_name);
2043 state_file_filter (const string &str, void */*arg*/)
2045 return (str.length() > strlen(statefile_suffix) &&
2046 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2050 bool operator()(const string* a, const string* b) {
2056 remove_end(string* state)
2058 string statename(*state);
2060 string::size_type start,end;
2061 if ((start = statename.find_last_of ('/')) != string::npos) {
2062 statename = statename.substr (start+1);
2065 if ((end = statename.rfind(".ardour")) == string::npos) {
2066 end = statename.length();
2069 return new string(statename.substr (0, end));
2073 Session::possible_states (string path)
2075 PathScanner scanner;
2076 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2078 transform(states->begin(), states->end(), states->begin(), remove_end);
2081 sort (states->begin(), states->end(), cmp);
2087 Session::possible_states () const
2089 return possible_states(_path);
2093 Session::add_route_group (RouteGroup* g)
2095 _route_groups.push_back (g);
2096 route_group_added (g); /* EMIT SIGNAL */
2101 Session::remove_route_group (RouteGroup& rg)
2103 list<RouteGroup*>::iterator i;
2105 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2106 (*i)->apply (&Route::drop_route_group, this);
2107 _route_groups.erase (i);
2108 route_group_removed (); /* EMIT SIGNAL */
2116 Session::route_group_by_name (string name)
2118 list<RouteGroup *>::iterator i;
2120 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2121 if ((*i)->name() == name) {
2129 Session::start_reversible_command (const string& name)
2131 UndoTransaction* trans = new UndoTransaction();
2132 trans->set_name(name);
2137 Session::finish_reversible_command (UndoTransaction& ut)
2140 gettimeofday(&now, 0);
2141 ut.set_timestamp(now);
2146 Session::begin_reversible_command(const string& name)
2148 UndoTransaction* trans = new UndoTransaction();
2149 trans->set_name(name);
2151 if (!_current_trans.empty()) {
2152 _current_trans.top()->add_command (trans);
2154 _current_trans.push(trans);
2159 Session::commit_reversible_command(Command *cmd)
2161 assert(!_current_trans.empty());
2165 _current_trans.top()->add_command(cmd);
2168 if (_current_trans.top()->empty()) {
2169 _current_trans.pop();
2173 gettimeofday(&now, 0);
2174 _current_trans.top()->set_timestamp(now);
2176 _history.add(_current_trans.top());
2177 _current_trans.pop();
2180 Session::GlobalRouteBooleanState
2181 Session::get_global_route_boolean (bool (Route::*method)(void) const)
2183 GlobalRouteBooleanState s;
2184 boost::shared_ptr<RouteList> r = routes.reader ();
2186 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2187 if (!(*i)->is_hidden()) {
2188 RouteBooleanState v;
2191 Route* r = (*i).get();
2192 v.second = (r->*method)();
2201 Session::GlobalRouteMeterState
2202 Session::get_global_route_metering ()
2204 GlobalRouteMeterState s;
2205 boost::shared_ptr<RouteList> r = routes.reader ();
2207 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
2208 if (!(*i)->is_hidden()) {
2212 v.second = (*i)->meter_point();
2222 Session::set_global_route_metering (GlobalRouteMeterState s, void* arg)
2224 for (GlobalRouteMeterState::iterator i = s.begin(); i != s.end(); ++i) {
2226 boost::shared_ptr<Route> r = (i->first.lock());
2229 r->set_meter_point (i->second, arg);
2235 Session::set_global_route_boolean (GlobalRouteBooleanState s, void (Route::*method)(bool, void*), void* arg)
2237 for (GlobalRouteBooleanState::iterator i = s.begin(); i != s.end(); ++i) {
2239 boost::shared_ptr<Route> r = (i->first.lock());
2242 Route* rp = r.get();
2243 (rp->*method) (i->second, arg);
2249 Session::set_global_mute (GlobalRouteBooleanState s, void* src)
2251 set_global_route_boolean (s, &Route::set_mute, src);
2255 Session::set_global_solo (GlobalRouteBooleanState s, void* src)
2257 set_global_route_boolean (s, &Route::set_solo, src);
2261 Session::set_global_record_enable (GlobalRouteBooleanState s, void* src)
2263 set_global_route_boolean (s, &Route::set_record_enable, src);
2267 accept_all_non_peak_files (const string& path, void */*arg*/)
2269 return (path.length() > 5 && path.find (peakfile_suffix) != (path.length() - 5));
2273 accept_all_state_files (const string& path, void */*arg*/)
2275 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2279 Session::find_all_sources (string path, set<string>& result)
2284 if (!tree.read (path)) {
2288 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2293 XMLNodeConstIterator niter;
2295 nlist = node->children();
2299 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2303 if ((prop = (*niter)->property (X_("type"))) == 0) {
2307 DataType type (prop->value());
2309 if ((prop = (*niter)->property (X_("name"))) == 0) {
2313 if (prop->value()[0] == '/') {
2314 /* external file, ignore */
2318 Glib::ustring found_path;
2322 if (FileSource::find (type, prop->value(), true, is_new, chan, found_path)) {
2323 result.insert (found_path);
2331 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2333 PathScanner scanner;
2334 vector<string*>* state_files;
2336 string this_snapshot_path;
2342 if (ripped[ripped.length()-1] == '/') {
2343 ripped = ripped.substr (0, ripped.length() - 1);
2346 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2348 if (state_files == 0) {
2353 this_snapshot_path = _path;
2354 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2355 this_snapshot_path += statefile_suffix;
2357 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2359 if (exclude_this_snapshot && **i == this_snapshot_path) {
2363 if (find_all_sources (**i, result) < 0) {
2371 struct RegionCounter {
2372 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2373 AudioSourceList::iterator iter;
2374 boost::shared_ptr<Region> region;
2377 RegionCounter() : count (0) {}
2381 Session::cleanup_sources (CleanupReport& rep)
2383 // FIXME: needs adaptation to midi
2385 vector<boost::shared_ptr<Source> > dead_sources;
2386 PathScanner scanner;
2388 vector<space_and_path>::iterator i;
2389 vector<space_and_path>::iterator nexti;
2390 vector<string*>* soundfiles;
2391 vector<string> unused;
2392 set<string> all_sources;
2397 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2399 /* step 1: consider deleting all unused playlists */
2401 if (playlists->maybe_delete_unused (AskAboutPlaylistDeletion)) {
2406 /* step 2: find all un-used sources */
2411 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2413 SourceMap::iterator tmp;
2418 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2422 if (!playlists->source_use_count(i->second) && i->second->length(i->second->timeline_position()) > 0) {
2423 dead_sources.push_back (i->second);
2424 i->second->GoingAway();
2430 /* build a list of all the possible sound directories for the session */
2432 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2437 SessionDirectory sdir ((*i).path);
2438 sound_path += sdir.sound_path().to_string();
2440 if (nexti != session_dirs.end()) {
2447 /* now do the same thing for the files that ended up in the sounds dir(s)
2448 but are not referenced as sources in any snapshot.
2451 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
2453 if (soundfiles == 0) {
2457 /* find all sources, but don't use this snapshot because the
2458 state file on disk still references sources we may have already
2462 find_all_sources_across_snapshots (all_sources, true);
2464 /* add our current source list
2467 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2468 boost::shared_ptr<FileSource> fs;
2470 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2471 all_sources.insert (fs->path());
2475 char tmppath1[PATH_MAX+1];
2476 char tmppath2[PATH_MAX+1];
2478 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
2483 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2485 realpath(spath.c_str(), tmppath1);
2486 realpath((*i).c_str(), tmppath2);
2488 if (strcmp(tmppath1, tmppath2) == 0) {
2495 unused.push_back (spath);
2499 /* now try to move all unused files into the "dead_sounds" directory(ies) */
2501 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2502 struct stat statbuf;
2504 rep.paths.push_back (*x);
2505 if (stat ((*x).c_str(), &statbuf) == 0) {
2506 rep.space += statbuf.st_size;
2511 /* don't move the file across filesystems, just
2512 stick it in the `dead_sound_dir_name' directory
2513 on whichever filesystem it was already on.
2516 if ((*x).find ("/sounds/") != string::npos) {
2518 /* old school, go up 1 level */
2520 newpath = Glib::path_get_dirname (*x); // "sounds"
2521 newpath = Glib::path_get_dirname (newpath); // "session-name"
2525 /* new school, go up 4 levels */
2527 newpath = Glib::path_get_dirname (*x); // "audiofiles"
2528 newpath = Glib::path_get_dirname (newpath); // "session-name"
2529 newpath = Glib::path_get_dirname (newpath); // "interchange"
2530 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2534 newpath += dead_sound_dir_name;
2536 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2537 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2542 newpath += Glib::path_get_basename ((*x));
2544 if (access (newpath.c_str(), F_OK) == 0) {
2546 /* the new path already exists, try versioning */
2548 char buf[PATH_MAX+1];
2552 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2555 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
2556 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2560 if (version == 999) {
2561 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2565 newpath = newpath_v;
2570 /* it doesn't exist, or we can't read it or something */
2574 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2575 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
2576 (*x), newpath, strerror (errno))
2581 /* see if there an easy to find peakfile for this file, and remove it.
2584 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
2585 peakpath += peakfile_suffix;
2587 if (access (peakpath.c_str(), W_OK) == 0) {
2588 if (::unlink (peakpath.c_str()) != 0) {
2589 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2590 peakpath, _path, strerror (errno))
2592 /* try to back out */
2593 rename (newpath.c_str(), _path.c_str());
2601 /* dump the history list */
2605 /* save state so we don't end up a session file
2606 referring to non-existent sources.
2612 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2618 Session::cleanup_trash_sources (CleanupReport& rep)
2620 // FIXME: needs adaptation for MIDI
2622 vector<space_and_path>::iterator i;
2623 string dead_sound_dir;
2624 struct dirent* dentry;
2625 struct stat statbuf;
2631 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2633 dead_sound_dir = (*i).path;
2634 dead_sound_dir += dead_sound_dir_name;
2636 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
2640 while ((dentry = readdir (dead)) != 0) {
2642 /* avoid '.' and '..' */
2644 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
2645 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
2651 fullpath = dead_sound_dir;
2653 fullpath += dentry->d_name;
2655 if (stat (fullpath.c_str(), &statbuf)) {
2659 if (!S_ISREG (statbuf.st_mode)) {
2663 if (unlink (fullpath.c_str())) {
2664 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
2665 fullpath, strerror (errno))
2669 rep.paths.push_back (dentry->d_name);
2670 rep.space += statbuf.st_size;
2681 Session::set_dirty ()
2683 bool was_dirty = dirty();
2685 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2689 DirtyChanged(); /* EMIT SIGNAL */
2695 Session::set_clean ()
2697 bool was_dirty = dirty();
2699 _state_of_the_state = Clean;
2703 DirtyChanged(); /* EMIT SIGNAL */
2708 Session::set_deletion_in_progress ()
2710 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2714 Session::clear_deletion_in_progress ()
2716 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2720 Session::add_controllable (boost::shared_ptr<Controllable> c)
2722 /* this adds a controllable to the list managed by the Session.
2723 this is a subset of those managed by the Controllable class
2724 itself, and represents the only ones whose state will be saved
2725 as part of the session.
2728 Glib::Mutex::Lock lm (controllables_lock);
2729 controllables.insert (c);
2732 struct null_deleter { void operator()(void const *) const {} };
2735 Session::remove_controllable (Controllable* c)
2737 if (_state_of_the_state | Deletion) {
2741 Glib::Mutex::Lock lm (controllables_lock);
2743 Controllables::iterator x = controllables.find(
2744 boost::shared_ptr<Controllable>(c, null_deleter()));
2746 if (x != controllables.end()) {
2747 controllables.erase (x);
2751 boost::shared_ptr<Controllable>
2752 Session::controllable_by_id (const PBD::ID& id)
2754 Glib::Mutex::Lock lm (controllables_lock);
2756 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2757 if ((*i)->id() == id) {
2762 return boost::shared_ptr<Controllable>();
2766 Session::add_instant_xml (XMLNode& node, bool write_to_config)
2769 Stateful::add_instant_xml (node, _path);
2772 if (write_to_config) {
2773 Config->add_instant_xml (node);
2778 Session::instant_xml (const string& node_name)
2780 return Stateful::instant_xml (node_name, _path);
2784 Session::save_history (string snapshot_name)
2792 if (snapshot_name.empty()) {
2793 snapshot_name = _current_snapshot_name;
2796 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
2797 const string backup_filename = history_filename + backup_suffix;
2798 const sys::path xml_path = _session_dir->root_path() / history_filename;
2799 const sys::path backup_path = _session_dir->root_path() / backup_filename;
2801 if (sys::exists (xml_path)) {
2804 sys::rename (xml_path, backup_path);
2806 catch (const sys::filesystem_error& err)
2808 error << _("could not backup old history file, current history not saved") << endmsg;
2813 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
2817 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
2819 if (!tree.write (xml_path.to_string()))
2821 error << string_compose (_("history could not be saved to %1"), xml_path.to_string()) << endmsg;
2825 sys::remove (xml_path);
2826 sys::rename (backup_path, xml_path);
2828 catch (const sys::filesystem_error& err)
2830 error << string_compose (_("could not restore history file from backup %1 (%2)"),
2831 backup_path.to_string(), err.what()) << endmsg;
2841 Session::restore_history (string snapshot_name)
2845 if (snapshot_name.empty()) {
2846 snapshot_name = _current_snapshot_name;
2849 const string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
2850 const sys::path xml_path = _session_dir->root_path() / xml_filename;
2852 info << "Loading history from " << xml_path.to_string() << endmsg;
2854 if (!sys::exists (xml_path)) {
2855 info << string_compose (_("%1: no history file \"%2\" for this session."),
2856 _name, xml_path.to_string()) << endmsg;
2860 if (!tree.read (xml_path.to_string())) {
2861 error << string_compose (_("Could not understand session history file \"%1\""),
2862 xml_path.to_string()) << endmsg;
2869 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
2872 UndoTransaction* ut = new UndoTransaction ();
2875 ut->set_name(t->property("name")->value());
2876 stringstream ss(t->property("tv-sec")->value());
2878 ss.str(t->property("tv-usec")->value());
2880 ut->set_timestamp(tv);
2882 for (XMLNodeConstIterator child_it = t->children().begin();
2883 child_it != t->children().end(); child_it++)
2885 XMLNode *n = *child_it;
2888 if (n->name() == "MementoCommand" ||
2889 n->name() == "MementoUndoCommand" ||
2890 n->name() == "MementoRedoCommand") {
2892 if ((c = memento_command_factory(n))) {
2896 } else if (n->name() == X_("GlobalRouteStateCommand")) {
2898 if ((c = global_state_command_factory (*n))) {
2899 ut->add_command (c);
2902 } else if (n->name() == "DeltaCommand") {
2903 PBD::ID id(n->property("midi-source")->value());
2904 boost::shared_ptr<MidiSource> midi_source =
2905 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
2907 ut->add_command(new MidiModel::DeltaCommand(midi_source->model(), *n));
2909 error << _("Failed to downcast MidiSource for DeltaCommand") << endmsg;
2912 } else if (n->name() == "DiffCommand") {
2913 PBD::ID id(n->property("midi-source")->value());
2914 boost::shared_ptr<MidiSource> midi_source =
2915 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
2917 ut->add_command(new MidiModel::DiffCommand(midi_source->model(), *n));
2919 error << _("Failed to downcast MidiSource for DeltaCommand") << endmsg;
2923 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
2934 Session::config_changed (std::string p, bool ours)
2940 if (p == "seamless-loop") {
2942 } else if (p == "rf-speed") {
2944 } else if (p == "auto-loop") {
2946 } else if (p == "auto-input") {
2948 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
2949 /* auto-input only makes a difference if we're rolling */
2951 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
2953 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
2954 if ((*i)->record_enabled ()) {
2955 (*i)->monitor_input (!config.get_auto_input());
2960 } else if (p == "punch-in") {
2964 if ((location = _locations.auto_punch_location()) != 0) {
2966 if (config.get_punch_in ()) {
2967 replace_event (SessionEvent::PunchIn, location->start());
2969 remove_event (location->start(), SessionEvent::PunchIn);
2973 } else if (p == "punch-out") {
2977 if ((location = _locations.auto_punch_location()) != 0) {
2979 if (config.get_punch_out()) {
2980 replace_event (SessionEvent::PunchOut, location->end());
2982 clear_events (SessionEvent::PunchOut);
2986 } else if (p == "edit-mode") {
2988 Glib::Mutex::Lock lm (playlists->lock);
2990 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
2991 (*i)->set_edit_mode (Config->get_edit_mode ());
2994 } else if (p == "use-video-sync") {
2996 waiting_for_sync_offset = config.get_use_video_sync();
2998 } else if (p == "mmc-control") {
3000 //poke_midi_thread ();
3002 } else if (p == "mmc-device-id" || p == "mmc-receive-id") {
3005 mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3008 } else if (p == "mmc-send-id") {
3011 mmc->set_send_device_id (Config->get_mmc_send_device_id());
3014 } else if (p == "midi-control") {
3016 //poke_midi_thread ();
3018 } else if (p == "raid-path") {
3020 setup_raid_path (config.get_raid_path());
3022 } else if (p == "timecode-format") {
3026 } else if (p == "video-pullup") {
3030 } else if (p == "seamless-loop") {
3032 if (play_loop && transport_rolling()) {
3033 // to reset diskstreams etc
3034 request_play_loop (true);
3037 } else if (p == "rf-speed") {
3039 cumulative_rf_motion = 0;
3042 } else if (p == "click-sound") {
3044 setup_click_sounds (1);
3046 } else if (p == "click-emphasis-sound") {
3048 setup_click_sounds (-1);
3050 } else if (p == "clicking") {
3052 if (Config->get_clicking()) {
3053 if (_click_io && click_data) { // don't require emphasis data
3060 } else if (p == "send-mtc") {
3062 /* only set the internal flag if we have
3066 if (_mtc_port != 0) {
3067 session_send_mtc = Config->get_send_mtc();
3068 if (session_send_mtc) {
3069 /* mark us ready to send */
3070 next_quarter_frame_to_send = 0;
3073 session_send_mtc = false;
3076 } else if (p == "send-mmc") {
3078 /* only set the internal flag if we have
3082 if (_mmc_port != 0) {
3083 session_send_mmc = Config->get_send_mmc();
3086 session_send_mmc = false;
3089 } else if (p == "midi-feedback") {
3091 /* only set the internal flag if we have
3095 if (_mtc_port != 0) {
3096 session_midi_feedback = Config->get_midi_feedback();
3099 } else if (p == "jack-time-master") {
3101 engine().reset_timebase ();
3103 } else if (p == "native-file-header-format") {
3105 if (!first_file_header_format_reset) {
3106 reset_native_file_format ();
3109 first_file_header_format_reset = false;
3111 } else if (p == "native-file-data-format") {
3113 if (!first_file_data_format_reset) {
3114 reset_native_file_format ();
3117 first_file_data_format_reset = false;
3119 } else if (p == "external-sync") {
3120 if (!config.get_external_sync()) {
3121 drop_sync_source ();
3123 switch_to_sync_source (config.get_sync_source());
3125 } else if (p == "remote-model") {
3126 set_remote_control_ids ();
3127 } else if (p == "denormal-model") {
3129 } else if (p == "history-depth") {
3130 set_history_depth (Config->get_history_depth());
3131 } else if (p == "sync-all-route-ordering") {
3132 sync_order_keys ("session");
3133 } else if (p == "initial-program-change") {
3135 if (_mmc_port && Config->get_initial_program_change() >= 0) {
3138 buf[0] = MIDI::program; // channel zero by default
3139 buf[1] = (Config->get_initial_program_change() & 0x7f);
3141 _mmc_port->midimsg (buf, sizeof (buf), 0);
3143 } else if (p == "initial-program-change") {
3145 if (_mmc_port && Config->get_initial_program_change() >= 0) {
3146 MIDI::byte* buf = new MIDI::byte[2];
3148 buf[0] = MIDI::program; // channel zero by default
3149 buf[1] = (Config->get_initial_program_change() & 0x7f);
3150 // deliver_midi (_mmc_port, buf, 2);
3152 } else if (p == "solo-mute-override") {
3153 // catch_up_on_solo_mute_override ();
3154 } else if (p == "listen-position") {
3155 listen_position_changed ();
3156 } else if (p == "solo-control-is-listen-control") {
3157 solo_control_mode_changed ();
3165 Session::set_history_depth (uint32_t d)
3167 _history.set_depth (d);