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
34 #include <cstdio> /* snprintf(3) ... grrr */
49 #include <sys/param.h>
50 #include <sys/mount.h>
54 #include <glibmm/thread.h>
56 #include "midi++/mmc.h"
57 #include "midi++/port.h"
59 #include "pbd/boost_debug.h"
60 #include "pbd/controllable_descriptor.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"
67 #include "pbd/convert.h"
69 #include "ardour/amp.h"
70 #include "ardour/audio_diskstream.h"
71 #include "ardour/audio_track.h"
72 #include "ardour/audioengine.h"
73 #include "ardour/audiofilesource.h"
74 #include "ardour/audioplaylist.h"
75 #include "ardour/audioregion.h"
76 #include "ardour/auditioner.h"
77 #include "ardour/buffer.h"
78 #include "ardour/butler.h"
79 #include "ardour/configuration.h"
80 #include "ardour/control_protocol_manager.h"
81 #include "ardour/crossfade.h"
82 #include "ardour/cycle_timer.h"
83 #include "ardour/directory_names.h"
84 #include "ardour/filename_extensions.h"
85 #include "ardour/io_processor.h"
86 #include "ardour/location.h"
87 #include "ardour/midi_diskstream.h"
88 #include "ardour/midi_patch_manager.h"
89 #include "ardour/midi_playlist.h"
90 #include "ardour/midi_region.h"
91 #include "ardour/midi_source.h"
92 #include "ardour/midi_track.h"
93 #include "ardour/named_selection.h"
94 #include "ardour/processor.h"
95 #include "ardour/region_factory.h"
96 #include "ardour/route_group.h"
97 #include "ardour/send.h"
98 #include "ardour/session.h"
99 #include "ardour/session_directory.h"
100 #include "ardour/session_metadata.h"
101 #include "ardour/session_state_utils.h"
102 #include "ardour/session_playlists.h"
103 #include "ardour/session_utils.h"
104 #include "ardour/silentfilesource.h"
105 #include "ardour/slave.h"
106 #include "ardour/smf_source.h"
107 #include "ardour/sndfile_helpers.h"
108 #include "ardour/sndfilesource.h"
109 #include "ardour/source_factory.h"
110 #include "ardour/template_utils.h"
111 #include "ardour/tempo.h"
112 #include "ardour/ticker.h"
113 #include "ardour/user_bundle.h"
114 #include "ardour/utils.h"
115 #include "ardour/utils.h"
116 #include "ardour/version.h"
117 #include "ardour/playlist_factory.h"
119 #include "control_protocol/control_protocol.h"
125 using namespace ARDOUR;
129 Session::first_stage_init (string fullpath, string snapshot_name)
131 if (fullpath.length() == 0) {
133 throw failed_constructor();
136 char buf[PATH_MAX+1];
137 if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
138 error << string_compose(_("Could not use path %1 (%s)"), buf, strerror(errno)) << endmsg;
140 throw failed_constructor();
145 if (_path[_path.length()-1] != '/') {
149 if (Glib::file_test (_path, Glib::FILE_TEST_EXISTS) && ::access (_path.c_str(), W_OK)) {
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->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
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 _gain_automation_buffer = 0;
214 _pan_automation_buffer = 0;
216 pending_abort = false;
217 destructive_index = 0;
218 first_file_data_format_reset = true;
219 first_file_header_format_reset = true;
220 post_export_sync = false;
223 AudioDiskstream::allocate_working_buffers();
225 /* default short fade = 15ms */
227 Crossfade::set_short_xfade_length ((nframes_t) floor (config.get_short_xfade_seconds() * frame_rate()));
228 SndFileSource::setup_standard_crossfades (*this, frame_rate());
230 last_mmc_step.tv_sec = 0;
231 last_mmc_step.tv_usec = 0;
234 /* click sounds are unset by default, which causes us to internal
235 waveforms for clicks.
239 click_emphasis_length = 0;
242 process_function = &Session::process_with_events;
244 if (config.get_use_video_sync()) {
245 waiting_for_sync_offset = true;
247 waiting_for_sync_offset = false;
250 last_timecode_when = 0;
251 _timecode_offset = 0;
252 _timecode_offset_negative = true;
253 last_timecode_valid = false;
257 last_rr_session_dir = session_dirs.begin();
258 refresh_disk_space ();
260 // set_default_fade (0.2, 5.0); /* steepness, millisecs */
264 average_slave_delta = 1800; // !!! why 1800 ????
265 have_first_delta_accumulator = false;
266 delta_accumulator_cnt = 0;
267 _slave_state = Stopped;
269 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
271 /* These are all static "per-class" signals */
273 RegionFactory::CheckNewRegion.connect_same_thread (*this, boost::bind (&Session::add_region, this, _1));
274 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
275 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
276 Processor::ProcessorCreated.connect_same_thread (*this, boost::bind (&Session::add_processor, this, _1));
277 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
278 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
279 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
281 /* stop IO objects from doing stuff until we're ready for them */
283 Delivery::disable_panners ();
284 IO::disable_connecting ();
288 Session::second_stage_init (bool new_session)
290 AudioFileSource::set_peak_dir (_session_dir->peak_path().to_string());
293 if (load_state (_current_snapshot_name)) {
296 remove_empty_sounds ();
299 if (_butler->start_thread()) {
303 if (start_midi_thread ()) {
307 // set_state() will call setup_raid_path(), but if it's a new session we need
308 // to call setup_raid_path() here.
311 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
315 setup_raid_path(_path);
318 /* we can't save till after ::when_engine_running() is called,
319 because otherwise we save state with no connections made.
320 therefore, we reset _state_of_the_state because ::set_state()
321 will have cleared it.
323 we also have to include Loading so that any events that get
324 generated between here and the end of ::when_engine_running()
325 will be processed directly rather than queued.
328 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave|Loading);
331 _locations.changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
332 _locations.added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
333 setup_click_sounds (0);
334 setup_midi_control ();
336 /* Pay attention ... */
338 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
339 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
342 when_engine_running();
345 /* handle this one in a different way than all others, so that its clear what happened */
347 catch (AudioEngine::PortRegistrationFailure& err) {
348 error << err.what() << endmsg;
356 BootMessage (_("Reset Remote Controls"));
358 send_full_time_code (0);
359 _engine.transport_locate (0);
360 deliver_mmc (MIDI::MachineControl::cmdMmcReset, 0);
361 deliver_mmc (MIDI::MachineControl::cmdLocate, 0);
363 MidiClockTicker::instance().set_session (this);
364 MIDI::Name::MidiPatchManager::instance().set_session (this);
366 /* initial program change will be delivered later; see ::config_changed() */
368 BootMessage (_("Reset Control Protocols"));
370 ControlProtocolManager::instance().set_session (this);
372 config.set_end_marker_is_free (new_session);
374 _state_of_the_state = Clean;
376 DirtyChanged (); /* EMIT SIGNAL */
378 if (state_was_pending) {
379 save_state (_current_snapshot_name);
380 remove_pending_capture_state ();
381 state_was_pending = false;
384 BootMessage (_("Session loading complete"));
390 Session::raid_path () const
392 SearchPath raid_search_path;
394 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
395 raid_search_path += sys::path((*i).path);
398 return raid_search_path.to_string ();
402 Session::setup_raid_path (string path)
411 session_dirs.clear ();
413 SearchPath search_path(path);
414 SearchPath sound_search_path;
415 SearchPath midi_search_path;
417 for (SearchPath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
418 sp.path = (*i).to_string ();
419 sp.blocks = 0; // not needed
420 session_dirs.push_back (sp);
422 SessionDirectory sdir(sp.path);
424 sound_search_path += sdir.sound_path ();
425 midi_search_path += sdir.midi_path ();
428 // set the search path for each data type
429 FileSource::set_search_path (DataType::AUDIO, sound_search_path.to_string ());
430 SMFSource::set_search_path (DataType::MIDI, midi_search_path.to_string ());
432 // reset the round-robin soundfile path thingie
433 last_rr_session_dir = session_dirs.begin();
437 Session::path_is_within_session (const std::string& path)
439 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
440 if (path.find ((*i).path) == 0) {
448 Session::ensure_subdirs ()
452 dir = session_directory().peak_path().to_string();
454 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
455 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
459 dir = session_directory().sound_path().to_string();
461 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
462 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
466 dir = session_directory().midi_path().to_string();
468 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
469 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
473 dir = session_directory().dead_sound_path().to_string();
475 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
476 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
480 dir = session_directory().export_path().to_string();
482 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
483 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
487 dir = analysis_dir ();
489 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
490 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
498 Session::create (bool& new_session, const string& mix_template, nframes_t initial_length)
501 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
502 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
506 if (ensure_subdirs ()) {
510 /* check new_session so we don't overwrite an existing one */
512 if (!mix_template.empty()) {
513 std::string in_path = mix_template;
515 ifstream in(in_path.c_str());
518 string out_path = _path;
520 out_path += statefile_suffix;
522 ofstream out(out_path.c_str());
527 // okay, session is set up. Treat like normal saved
528 // session from now on.
534 error << string_compose (_("Could not open %1 for writing mix template"), out_path)
540 error << string_compose (_("Could not open mix template %1 for reading"), in_path)
547 /* Instantiate metadata */
549 _metadata = new SessionMetadata ();
551 /* set initial start + end point */
553 start_location->set_end (0);
554 _locations.add (start_location);
556 end_location->set_end (initial_length);
557 _locations.add (end_location);
559 _state_of_the_state = Clean;
568 Session::load_diskstreams (const XMLNode& node)
571 XMLNodeConstIterator citer;
573 clist = node.children();
575 for (citer = clist.begin(); citer != clist.end(); ++citer) {
578 /* diskstreams added automatically by DiskstreamCreated handler */
579 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
580 AudioDiskstream* dsp (new AudioDiskstream (*this, **citer));
581 boost::shared_ptr<AudioDiskstream> dstream (dsp);
582 add_diskstream (dstream);
583 } else if ((*citer)->name() == "MidiDiskstream") {
584 boost::shared_ptr<MidiDiskstream> dstream (new MidiDiskstream (*this, **citer));
585 add_diskstream (dstream);
587 error << _("Session: unknown diskstream type in XML") << endmsg;
591 catch (failed_constructor& err) {
592 error << _("Session: could not load diskstream via XML state") << endmsg;
601 Session::maybe_write_autosave()
603 if (dirty() && record_status() != Recording) {
604 save_state("", true);
609 Session::remove_pending_capture_state ()
611 sys::path pending_state_file_path(_session_dir->root_path());
613 pending_state_file_path /= legalize_for_path (_current_snapshot_name) + pending_suffix;
617 sys::remove (pending_state_file_path);
619 catch(sys::filesystem_error& ex)
621 error << string_compose(_("Could remove pending capture state at path \"%1\" (%2)"),
622 pending_state_file_path.to_string(), ex.what()) << endmsg;
626 /** Rename a state file.
627 * @param snapshot_name Snapshot name.
630 Session::rename_state (string old_name, string new_name)
632 if (old_name == _current_snapshot_name || old_name == _name) {
633 /* refuse to rename the current snapshot or the "main" one */
637 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
638 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
640 const sys::path old_xml_path = _session_dir->root_path() / old_xml_filename;
641 const sys::path new_xml_path = _session_dir->root_path() / new_xml_filename;
645 sys::rename (old_xml_path, new_xml_path);
647 catch (const sys::filesystem_error& err)
649 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
650 old_name, new_name, err.what()) << endmsg;
654 /** Remove a state file.
655 * @param snapshot_name Snapshot name.
658 Session::remove_state (string snapshot_name)
660 if (snapshot_name == _current_snapshot_name || snapshot_name == _name) {
661 // refuse to remove the current snapshot or the "main" one
665 sys::path xml_path(_session_dir->root_path());
667 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
669 if (!create_backup_file (xml_path)) {
670 // don't remove it if a backup can't be made
671 // create_backup_file will log the error.
676 sys::remove (xml_path);
680 Session::save_state (string snapshot_name, bool pending)
683 sys::path xml_path(_session_dir->root_path());
685 if (!_writable || (_state_of_the_state & CannotSave)) {
689 if (!_engine.connected ()) {
690 error << _("Ardour's audio engine is not connected and state saving would lose all I/O connections. Session not saved")
695 /* tell sources we're saving first, in case they write out to a new file
696 * which should be saved with the state rather than the old one */
697 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i)
698 i->second->session_saved();
700 tree.set_root (&get_state());
702 if (snapshot_name.empty()) {
703 snapshot_name = _current_snapshot_name;
708 /* proper save: use statefile_suffix (.ardour in English) */
710 xml_path /= legalize_for_path (snapshot_name) + statefile_suffix;
712 /* make a backup copy of the old file */
714 if (sys::exists(xml_path) && !create_backup_file (xml_path)) {
715 // create_backup_file will log the error
721 /* pending save: use pending_suffix (.pending in English) */
722 xml_path /= legalize_for_path (snapshot_name) + pending_suffix;
725 sys::path tmp_path(_session_dir->root_path());
727 tmp_path /= legalize_for_path (snapshot_name) + temp_suffix;
729 // cerr << "actually writing state to " << xml_path.to_string() << endl;
731 if (!tree.write (tmp_path.to_string())) {
732 error << string_compose (_("state could not be saved to %1"), tmp_path.to_string()) << endmsg;
733 sys::remove (tmp_path);
738 if (rename (tmp_path.to_string().c_str(), xml_path.to_string().c_str()) != 0) {
739 error << string_compose (_("could not rename temporary session file %1 to %2"),
740 tmp_path.to_string(), xml_path.to_string()) << endmsg;
741 sys::remove (tmp_path);
748 save_history (snapshot_name);
750 bool was_dirty = dirty();
752 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
755 DirtyChanged (); /* EMIT SIGNAL */
758 StateSaved (snapshot_name); /* EMIT SIGNAL */
765 Session::restore_state (string snapshot_name)
767 if (load_state (snapshot_name) == 0) {
768 set_state (*state_tree->root(), Stateful::loading_state_version);
775 Session::load_state (string snapshot_name)
780 state_was_pending = false;
782 /* check for leftover pending state from a crashed capture attempt */
784 sys::path xmlpath(_session_dir->root_path());
785 xmlpath /= legalize_for_path (snapshot_name) + pending_suffix;
787 if (sys::exists (xmlpath)) {
789 /* there is pending state from a crashed capture attempt */
791 if (*AskAboutPendingState()) {
792 state_was_pending = true;
796 if (!state_was_pending) {
797 xmlpath = _session_dir->root_path();
798 xmlpath /= legalize_for_path (snapshot_name) + statefile_suffix;
801 if (!sys::exists (xmlpath)) {
802 error << string_compose(_("%1: session state information file \"%2\" doesn't exist!"), _name, xmlpath.to_string()) << endmsg;
806 state_tree = new XMLTree;
810 /* writable() really reflects the whole folder, but if for any
811 reason the session state file can't be written to, still
815 if (::access (xmlpath.to_string().c_str(), W_OK) != 0) {
819 if (!state_tree->read (xmlpath.to_string())) {
820 error << string_compose(_("Could not understand ardour file %1"), xmlpath.to_string()) << endmsg;
826 XMLNode& root (*state_tree->root());
828 if (root.name() != X_("Session")) {
829 error << string_compose (_("Session file %1 is not an Ardour session"), xmlpath.to_string()) << endmsg;
835 const XMLProperty* prop;
837 if ((prop = root.property ("version")) == 0) {
838 /* no version implies very old version of Ardour */
839 Stateful::loading_state_version = 1000;
845 sscanf (prop->value().c_str(), "%d.%d.%d", &major, &minor, µ);
846 Stateful::loading_state_version = (major * 1000) + minor;
849 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION) {
851 sys::path backup_path(_session_dir->root_path());
853 backup_path /= legalize_for_path (snapshot_name) + "-1" + statefile_suffix;
855 // only create a backup once
856 if (sys::exists (backup_path)) {
860 info << string_compose (_("Copying old session file %1 to %2\nUse %2 with Ardour versions before 2.0 from now on"),
861 xmlpath.to_string(), backup_path.to_string())
866 sys::copy_file (xmlpath, backup_path);
868 catch(sys::filesystem_error& ex)
870 error << string_compose (_("Unable to make backup of state file %1 (%2)"),
871 xmlpath.to_string(), ex.what())
881 Session::load_options (const XMLNode& node)
883 LocaleGuard lg (X_("POSIX"));
884 config.set_variables (node);
895 Session::get_template()
897 /* if we don't disable rec-enable, diskstreams
898 will believe they need to store their capture
899 sources in their state node.
902 disable_record (false);
908 Session::state(bool full_state)
910 XMLNode* node = new XMLNode("Session");
913 // store libardour version, just in case
915 snprintf(buf, sizeof(buf), "%d.%d.%d", libardour3_major_version, libardour3_minor_version, libardour3_micro_version);
916 node->add_property("version", string(buf));
918 /* store configuration settings */
922 node->add_property ("name", _name);
923 snprintf (buf, sizeof (buf), "%" PRId32, _nominal_frame_rate);
924 node->add_property ("sample-rate", buf);
926 if (session_dirs.size() > 1) {
930 vector<space_and_path>::iterator i = session_dirs.begin();
931 vector<space_and_path>::iterator next;
933 ++i; /* skip the first one */
937 while (i != session_dirs.end()) {
941 if (next != session_dirs.end()) {
951 child = node->add_child ("Path");
952 child->add_content (p);
956 /* save the ID counter */
958 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
959 node->add_property ("id-counter", buf);
961 /* various options */
963 node->add_child_nocopy (config.get_variables ());
965 node->add_child_nocopy (_metadata->get_state());
967 child = node->add_child ("Sources");
970 Glib::Mutex::Lock sl (source_lock);
972 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
974 /* Don't save information about non-destructive file sources that are empty */
975 /* FIXME: MIDI breaks if this is made FileSource like it should be... */
977 boost::shared_ptr<AudioFileSource> fs;
978 if ((fs = boost::dynamic_pointer_cast<AudioFileSource> (siter->second)) != 0) {
979 if (!fs->destructive()) {
980 if (fs->length(fs->timeline_position()) == 0) {
986 child->add_child_nocopy (siter->second->get_state());
990 child = node->add_child ("Regions");
993 Glib::Mutex::Lock rl (region_lock);
995 for (RegionList::const_iterator i = regions.begin(); i != regions.end(); ++i) {
997 /* only store regions not attached to playlists */
999 if (i->second->playlist() == 0) {
1000 child->add_child_nocopy (i->second->state (true));
1004 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1005 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1006 boost::shared_ptr<Region> r = i->second;
1007 /* only store regions not attached to playlists */
1008 if (r->playlist() == 0) {
1009 child->add_child_nocopy (r->state (true));
1016 child = node->add_child ("DiskStreams");
1019 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
1020 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
1021 if (!(*i)->hidden()) {
1022 child->add_child_nocopy ((*i)->get_state());
1028 node->add_child_nocopy (_locations.get_state());
1030 // for a template, just create a new Locations, populate it
1031 // with the default start and end, and get the state for that.
1033 Location* start = new Location(0, 0, _("start"), Location::Flags ((Location::IsMark|Location::IsStart)));
1034 Location* end = new Location(0, 0, _("end"), Location::Flags ((Location::IsMark|Location::IsEnd)));
1037 end->set_end(compute_initial_length());
1039 node->add_child_nocopy (loc.get_state());
1042 child = node->add_child ("Bundles");
1044 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1045 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1046 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1048 child->add_child_nocopy (b->get_state());
1053 child = node->add_child ("Routes");
1055 boost::shared_ptr<RouteList> r = routes.reader ();
1057 RoutePublicOrderSorter cmp;
1058 RouteList public_order (*r);
1059 public_order.sort (cmp);
1061 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1062 if (!(*i)->is_hidden()) {
1064 child->add_child_nocopy ((*i)->get_state());
1066 child->add_child_nocopy ((*i)->get_template());
1072 playlists->add_state (node, full_state);
1074 child = node->add_child ("RouteGroups");
1075 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1076 child->add_child_nocopy ((*i)->get_state());
1080 child = node->add_child ("Click");
1081 child->add_child_nocopy (_click_io->state (full_state));
1085 child = node->add_child ("NamedSelections");
1086 for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
1088 child->add_child_nocopy ((*i)->get_state());
1093 node->add_child_nocopy (_tempo_map->get_state());
1095 node->add_child_nocopy (get_control_protocol_state());
1098 node->add_child_copy (*_extra_xml);
1105 Session::get_control_protocol_state ()
1107 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1108 return cpm.get_state();
1112 Session::set_state (const XMLNode& node, int version)
1116 const XMLProperty* prop;
1119 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1121 if (node.name() != X_("Session")){
1122 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1126 if ((prop = node.property ("version")) != 0) {
1127 version = atoi (prop->value ()) * 1000;
1130 if ((prop = node.property ("name")) != 0) {
1131 _name = prop->value ();
1134 if ((prop = node.property (X_("sample-rate"))) != 0) {
1136 _nominal_frame_rate = atoi (prop->value());
1138 if (_nominal_frame_rate != _current_frame_rate) {
1139 if (*AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate)) {
1145 setup_raid_path(_session_dir->root_path().to_string());
1147 if ((prop = node.property (X_("id-counter"))) != 0) {
1149 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1150 ID::init_counter (x);
1152 /* old sessions used a timebased counter, so fake
1153 the startup ID counter based on a standard
1158 ID::init_counter (now);
1162 IO::disable_connecting ();
1164 /* Object loading order:
1169 MIDI Control // relies on data from Options/Config
1183 if ((child = find_named_node (node, "Extra")) != 0) {
1184 _extra_xml = new XMLNode (*child);
1187 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1188 load_options (*child);
1189 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1190 load_options (*child);
1192 error << _("Session: XML state has no options section") << endmsg;
1195 if (use_config_midi_ports ()) {
1198 if (version >= 3000) {
1199 if ((child = find_named_node (node, "Metadata")) == 0) {
1200 warning << _("Session: XML state has no metadata section") << endmsg;
1201 } else if (_metadata->set_state (*child, version)) {
1206 if ((child = find_named_node (node, "Locations")) == 0) {
1207 error << _("Session: XML state has no locations section") << endmsg;
1209 } else if (_locations.set_state (*child, version)) {
1215 if ((location = _locations.auto_loop_location()) != 0) {
1216 set_auto_loop_location (location);
1219 if ((location = _locations.auto_punch_location()) != 0) {
1220 set_auto_punch_location (location);
1223 if ((location = _locations.end_location()) == 0) {
1224 _locations.add (end_location);
1226 delete end_location;
1227 end_location = location;
1230 if ((location = _locations.start_location()) == 0) {
1231 _locations.add (start_location);
1233 delete start_location;
1234 start_location = location;
1237 AudioFileSource::set_header_position_offset (start_location->start());
1239 if ((child = find_named_node (node, "Sources")) == 0) {
1240 error << _("Session: XML state has no sources section") << endmsg;
1242 } else if (load_sources (*child)) {
1246 if ((child = find_named_node (node, "Regions")) == 0) {
1247 error << _("Session: XML state has no Regions section") << endmsg;
1249 } else if (load_regions (*child)) {
1253 if ((child = find_named_node (node, "Playlists")) == 0) {
1254 error << _("Session: XML state has no playlists section") << endmsg;
1256 } else if (playlists->load (*this, *child)) {
1260 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1262 } else if (playlists->load_unused (*this, *child)) {
1266 if ((child = find_named_node (node, "NamedSelections")) != 0) {
1267 if (load_named_selections (*child)) {
1272 if ((child = find_named_node (node, "DiskStreams")) == 0) {
1273 error << _("Session: XML state has no diskstreams section") << endmsg;
1275 } else if (load_diskstreams (*child)) {
1279 if (version >= 3000) {
1280 if ((child = find_named_node (node, "Bundles")) == 0) {
1281 warning << _("Session: XML state has no bundles section") << endmsg;
1284 /* We can't load Bundles yet as they need to be able
1285 to convert from port names to Port objects, which can't happen until
1287 _bundle_xml_node = new XMLNode (*child);
1291 if ((child = find_named_node (node, "TempoMap")) == 0) {
1292 error << _("Session: XML state has no Tempo Map section") << endmsg;
1294 } else if (_tempo_map->set_state (*child, version)) {
1298 if ((child = find_named_node (node, "Routes")) == 0) {
1299 error << _("Session: XML state has no routes section") << endmsg;
1301 } else if (load_routes (*child, version)) {
1305 if (version >= 3000) {
1307 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1308 error << _("Session: XML state has no route groups section") << endmsg;
1310 } else if (load_route_groups (*child, version)) {
1314 } else if (version < 3000) {
1316 if ((child = find_named_node (node, "EditGroups")) == 0) {
1317 error << _("Session: XML state has no edit groups section") << endmsg;
1319 } else if (load_route_groups (*child, version)) {
1323 if ((child = find_named_node (node, "MixGroups")) == 0) {
1324 error << _("Session: XML state has no mix groups section") << endmsg;
1326 } else if (load_route_groups (*child, version)) {
1331 if ((child = find_named_node (node, "Click")) == 0) {
1332 warning << _("Session: XML state has no click section") << endmsg;
1333 } else if (_click_io) {
1334 _click_io->set_state (*child, version);
1337 if ((child = find_named_node (node, "ControlProtocols")) != 0) {
1338 ControlProtocolManager::instance().set_protocol_states (*child);
1341 /* here beginneth the second phase ... */
1343 StateReady (); /* EMIT SIGNAL */
1352 Session::load_routes (const XMLNode& node, int version)
1355 XMLNodeConstIterator niter;
1356 RouteList new_routes;
1358 nlist = node.children();
1362 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1364 boost::shared_ptr<Route> route (XMLRouteFactory (**niter, version));
1367 error << _("Session: cannot create Route from XML description.") << endmsg;
1371 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1373 new_routes.push_back (route);
1376 add_routes (new_routes, false);
1381 boost::shared_ptr<Route>
1382 Session::XMLRouteFactory (const XMLNode& node, int version)
1384 if (node.name() != "Route") {
1385 return boost::shared_ptr<Route> ((Route*) 0);
1388 bool has_diskstream = (node.property ("diskstream") != 0 || node.property ("diskstream-id") != 0);
1390 DataType type = DataType::AUDIO;
1391 const XMLProperty* prop = node.property("default-type");
1392 boost::shared_ptr<Route> ret;
1395 type = DataType(prop->value());
1398 assert(type != DataType::NIL);
1400 if (has_diskstream) {
1401 if (type == DataType::AUDIO) {
1402 AudioTrack* at = new AudioTrack (*this, node, version);
1403 boost_debug_shared_ptr_mark_interesting (at, "Track");
1407 ret.reset (new MidiTrack (*this, node, version));
1410 Route* rt = new Route (*this, node);
1411 boost_debug_shared_ptr_mark_interesting (rt, "Route");
1419 Session::load_regions (const XMLNode& node)
1422 XMLNodeConstIterator niter;
1423 boost::shared_ptr<Region> region;
1425 nlist = node.children();
1429 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1430 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1431 error << _("Session: cannot create Region from XML description.");
1432 const XMLProperty *name = (**niter).property("name");
1435 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1445 boost::shared_ptr<Region>
1446 Session::XMLRegionFactory (const XMLNode& node, bool full)
1448 const XMLProperty* type = node.property("type");
1452 if ( !type || type->value() == "audio" ) {
1454 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1456 } else if (type->value() == "midi") {
1458 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1462 } catch (failed_constructor& err) {
1463 return boost::shared_ptr<Region> ();
1466 return boost::shared_ptr<Region> ();
1469 boost::shared_ptr<AudioRegion>
1470 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1472 const XMLProperty* prop;
1473 boost::shared_ptr<Source> source;
1474 boost::shared_ptr<AudioSource> as;
1476 SourceList master_sources;
1477 uint32_t nchans = 1;
1480 if (node.name() != X_("Region")) {
1481 return boost::shared_ptr<AudioRegion>();
1484 if ((prop = node.property (X_("channels"))) != 0) {
1485 nchans = atoi (prop->value().c_str());
1488 if ((prop = node.property ("name")) == 0) {
1489 cerr << "no name for this region\n";
1493 if ((prop = node.property (X_("source-0"))) == 0) {
1494 if ((prop = node.property ("source")) == 0) {
1495 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1496 return boost::shared_ptr<AudioRegion>();
1500 PBD::ID s_id (prop->value());
1502 if ((source = source_by_id (s_id)) == 0) {
1503 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1504 return boost::shared_ptr<AudioRegion>();
1507 as = boost::dynamic_pointer_cast<AudioSource>(source);
1509 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1510 return boost::shared_ptr<AudioRegion>();
1513 sources.push_back (as);
1515 /* pickup other channels */
1517 for (uint32_t n=1; n < nchans; ++n) {
1518 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1519 if ((prop = node.property (buf)) != 0) {
1521 PBD::ID id2 (prop->value());
1523 if ((source = source_by_id (id2)) == 0) {
1524 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1525 return boost::shared_ptr<AudioRegion>();
1528 as = boost::dynamic_pointer_cast<AudioSource>(source);
1530 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1531 return boost::shared_ptr<AudioRegion>();
1533 sources.push_back (as);
1537 for (uint32_t n = 0; n < nchans; ++n) {
1538 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1539 if ((prop = node.property (buf)) != 0) {
1541 PBD::ID id2 (prop->value());
1543 if ((source = source_by_id (id2)) == 0) {
1544 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1545 return boost::shared_ptr<AudioRegion>();
1548 as = boost::dynamic_pointer_cast<AudioSource>(source);
1550 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1551 return boost::shared_ptr<AudioRegion>();
1553 master_sources.push_back (as);
1558 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1560 /* a final detail: this is the one and only place that we know how long missing files are */
1562 if (region->whole_file()) {
1563 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1564 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1566 sfp->set_length (region->length());
1571 if (!master_sources.empty()) {
1572 if (master_sources.size() != nchans) {
1573 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1575 region->set_master_sources (master_sources);
1583 catch (failed_constructor& err) {
1584 return boost::shared_ptr<AudioRegion>();
1588 boost::shared_ptr<MidiRegion>
1589 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1591 const XMLProperty* prop;
1592 boost::shared_ptr<Source> source;
1593 boost::shared_ptr<MidiSource> ms;
1595 uint32_t nchans = 1;
1597 if (node.name() != X_("Region")) {
1598 return boost::shared_ptr<MidiRegion>();
1601 if ((prop = node.property (X_("channels"))) != 0) {
1602 nchans = atoi (prop->value().c_str());
1605 if ((prop = node.property ("name")) == 0) {
1606 cerr << "no name for this region\n";
1610 // Multiple midi channels? that's just crazy talk
1611 assert(nchans == 1);
1613 if ((prop = node.property (X_("source-0"))) == 0) {
1614 if ((prop = node.property ("source")) == 0) {
1615 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1616 return boost::shared_ptr<MidiRegion>();
1620 PBD::ID s_id (prop->value());
1622 if ((source = source_by_id (s_id)) == 0) {
1623 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1624 return boost::shared_ptr<MidiRegion>();
1627 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1629 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1630 return boost::shared_ptr<MidiRegion>();
1633 sources.push_back (ms);
1636 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1637 /* a final detail: this is the one and only place that we know how long missing files are */
1639 if (region->whole_file()) {
1640 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1641 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1643 sfp->set_length (region->length());
1651 catch (failed_constructor& err) {
1652 return boost::shared_ptr<MidiRegion>();
1657 Session::get_sources_as_xml ()
1660 XMLNode* node = new XMLNode (X_("Sources"));
1661 Glib::Mutex::Lock lm (source_lock);
1663 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1664 node->add_child_nocopy (i->second->get_state());
1671 Session::path_from_region_name (DataType type, string name, string identifier)
1673 char buf[PATH_MAX+1];
1675 SessionDirectory sdir(get_best_session_directory_for_new_source());
1676 sys::path source_dir = ((type == DataType::AUDIO)
1677 ? sdir.sound_path() : sdir.midi_path());
1679 string ext = ((type == DataType::AUDIO) ? ".wav" : ".mid");
1681 for (n = 0; n < 999999; ++n) {
1682 if (identifier.length()) {
1683 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1684 identifier.c_str(), n, ext.c_str());
1686 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1690 sys::path source_path = source_dir / buf;
1692 if (!sys::exists (source_path)) {
1693 return source_path.to_string();
1697 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1706 Session::load_sources (const XMLNode& node)
1709 XMLNodeConstIterator niter;
1710 boost::shared_ptr<Source> source;
1712 nlist = node.children();
1716 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1718 if ((source = XMLSourceFactory (**niter)) == 0) {
1719 error << _("Session: cannot create Source from XML description.") << endmsg;
1721 } catch (MissingSource& err) {
1722 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1723 source = SourceFactory::createSilent (*this, **niter, max_frames, _current_frame_rate);
1730 boost::shared_ptr<Source>
1731 Session::XMLSourceFactory (const XMLNode& node)
1733 if (node.name() != "Source") {
1734 return boost::shared_ptr<Source>();
1738 /* note: do peak building in another thread when loading session state */
1739 return SourceFactory::create (*this, node, true);
1742 catch (failed_constructor& err) {
1743 error << _("Found a sound file that cannot be used by Ardour. Talk to the progammers.") << endmsg;
1744 return boost::shared_ptr<Source>();
1749 Session::save_template (string template_name)
1753 if (_state_of_the_state & CannotSave) {
1757 sys::path user_template_dir(user_template_directory());
1761 sys::create_directories (user_template_dir);
1763 catch(sys::filesystem_error& ex)
1765 error << string_compose(_("Could not create mix templates directory \"%1\" (%2)"),
1766 user_template_dir.to_string(), ex.what()) << endmsg;
1770 tree.set_root (&get_template());
1772 sys::path template_file_path(user_template_dir);
1773 template_file_path /= template_name + template_suffix;
1775 if (sys::exists (template_file_path))
1777 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1778 template_file_path.to_string()) << endmsg;
1782 if (!tree.write (template_file_path.to_string())) {
1783 error << _("mix template not saved") << endmsg;
1791 Session::rename_template (string old_name, string new_name)
1793 sys::path old_path (user_template_directory());
1794 old_path /= old_name + template_suffix;
1796 sys::path new_path(user_template_directory());
1797 new_path /= new_name + template_suffix;
1799 if (sys::exists (new_path)) {
1800 warning << string_compose(_("Template \"%1\" already exists - template not renamed"),
1801 new_path.to_string()) << endmsg;
1806 sys::rename (old_path, new_path);
1814 Session::delete_template (string name)
1816 sys::path path = user_template_directory();
1817 path /= name + template_suffix;
1828 Session::refresh_disk_space ()
1831 struct statfs statfsbuf;
1832 vector<space_and_path>::iterator i;
1833 Glib::Mutex::Lock lm (space_lock);
1836 /* get freespace on every FS that is part of the session path */
1838 _total_free_4k_blocks = 0;
1840 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1841 statfs ((*i).path.c_str(), &statfsbuf);
1843 scale = statfsbuf.f_bsize/4096.0;
1845 (*i).blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
1846 _total_free_4k_blocks += (*i).blocks;
1852 Session::get_best_session_directory_for_new_source ()
1854 vector<space_and_path>::iterator i;
1855 string result = _session_dir->root_path().to_string();
1857 /* handle common case without system calls */
1859 if (session_dirs.size() == 1) {
1863 /* OK, here's the algorithm we're following here:
1865 We want to select which directory to use for
1866 the next file source to be created. Ideally,
1867 we'd like to use a round-robin process so as to
1868 get maximum performance benefits from splitting
1869 the files across multiple disks.
1871 However, in situations without much diskspace, an
1872 RR approach may end up filling up a filesystem
1873 with new files while others still have space.
1874 Its therefore important to pay some attention to
1875 the freespace in the filesystem holding each
1876 directory as well. However, if we did that by
1877 itself, we'd keep creating new files in the file
1878 system with the most space until it was as full
1879 as all others, thus negating any performance
1880 benefits of this RAID-1 like approach.
1882 So, we use a user-configurable space threshold. If
1883 there are at least 2 filesystems with more than this
1884 much space available, we use RR selection between them.
1885 If not, then we pick the filesystem with the most space.
1887 This gets a good balance between the two
1891 refresh_disk_space ();
1893 int free_enough = 0;
1895 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
1896 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
1901 if (free_enough >= 2) {
1902 /* use RR selection process, ensuring that the one
1906 i = last_rr_session_dir;
1909 if (++i == session_dirs.end()) {
1910 i = session_dirs.begin();
1913 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
1914 if (create_session_directory ((*i).path)) {
1916 last_rr_session_dir = i;
1921 } while (i != last_rr_session_dir);
1925 /* pick FS with the most freespace (and that
1926 seems to actually work ...)
1929 vector<space_and_path> sorted;
1930 space_and_path_ascending_cmp cmp;
1932 sorted = session_dirs;
1933 sort (sorted.begin(), sorted.end(), cmp);
1935 for (i = sorted.begin(); i != sorted.end(); ++i) {
1936 if (create_session_directory ((*i).path)) {
1938 last_rr_session_dir = i;
1948 Session::load_named_selections (const XMLNode& node)
1951 XMLNodeConstIterator niter;
1954 nlist = node.children();
1958 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1960 if ((ns = XMLNamedSelectionFactory (**niter)) == 0) {
1961 error << _("Session: cannot create Named Selection from XML description.") << endmsg;
1969 Session::XMLNamedSelectionFactory (const XMLNode& node)
1972 return new NamedSelection (*this, node);
1975 catch (failed_constructor& err) {
1981 Session::automation_dir () const
1983 return Glib::build_filename (_path, "automation");
1987 Session::analysis_dir () const
1989 return Glib::build_filename (_path, "analysis");
1993 Session::load_bundles (XMLNode const & node)
1995 XMLNodeList nlist = node.children();
1996 XMLNodeConstIterator niter;
2000 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2001 if ((*niter)->name() == "InputBundle") {
2002 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2003 } else if ((*niter)->name() == "OutputBundle") {
2004 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2006 error << string_compose(_("Unknown node \"%1\" found in Bundles list from state file"), (*niter)->name()) << endmsg;
2015 Session::load_route_groups (const XMLNode& node, int version)
2017 XMLNodeList nlist = node.children();
2018 XMLNodeConstIterator niter;
2022 if (version >= 3000) {
2024 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2025 if ((*niter)->name() == "RouteGroup") {
2026 RouteGroup* rg = new RouteGroup (*this, "");
2027 add_route_group (rg);
2028 rg->set_state (**niter, version);
2032 } else if (version < 3000) {
2034 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2035 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2036 RouteGroup* rg = new RouteGroup (*this, "");
2037 add_route_group (rg);
2038 rg->set_state (**niter, version);
2047 Session::auto_save()
2049 save_state (_current_snapshot_name);
2053 state_file_filter (const string &str, void */*arg*/)
2055 return (str.length() > strlen(statefile_suffix) &&
2056 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2060 bool operator()(const string* a, const string* b) {
2066 remove_end(string* state)
2068 string statename(*state);
2070 string::size_type start,end;
2071 if ((start = statename.find_last_of ('/')) != string::npos) {
2072 statename = statename.substr (start+1);
2075 if ((end = statename.rfind(".ardour")) == string::npos) {
2076 end = statename.length();
2079 return new string(statename.substr (0, end));
2083 Session::possible_states (string path)
2085 PathScanner scanner;
2086 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2088 transform(states->begin(), states->end(), states->begin(), remove_end);
2091 sort (states->begin(), states->end(), cmp);
2097 Session::possible_states () const
2099 return possible_states(_path);
2103 Session::add_route_group (RouteGroup* g)
2105 _route_groups.push_back (g);
2106 route_group_added (g); /* EMIT SIGNAL */
2111 Session::remove_route_group (RouteGroup& rg)
2113 list<RouteGroup*>::iterator i;
2115 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2116 _route_groups.erase (i);
2119 route_group_removed (); /* EMIT SIGNAL */
2125 Session::route_group_by_name (string name)
2127 list<RouteGroup *>::iterator i;
2129 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2130 if ((*i)->name() == name) {
2138 Session::start_reversible_command (const string& name)
2140 UndoTransaction* trans = new UndoTransaction();
2141 trans->set_name(name);
2146 Session::finish_reversible_command (UndoTransaction& ut)
2149 gettimeofday(&now, 0);
2150 ut.set_timestamp(now);
2155 Session::begin_reversible_command(const string& name)
2157 UndoTransaction* trans = new UndoTransaction();
2158 trans->set_name(name);
2160 if (!_current_trans.empty()) {
2161 _current_trans.top()->add_command (trans);
2163 _current_trans.push(trans);
2168 Session::commit_reversible_command(Command *cmd)
2170 assert(!_current_trans.empty());
2174 _current_trans.top()->add_command(cmd);
2177 if (_current_trans.top()->empty()) {
2178 _current_trans.pop();
2182 gettimeofday(&now, 0);
2183 _current_trans.top()->set_timestamp(now);
2185 _history.add(_current_trans.top());
2186 _current_trans.pop();
2190 accept_all_non_peak_files (const string& path, void */*arg*/)
2192 return (path.length() > 5 && path.find (peakfile_suffix) != (path.length() - 5));
2196 accept_all_state_files (const string& path, void */*arg*/)
2198 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2202 Session::find_all_sources (string path, set<string>& result)
2207 if (!tree.read (path)) {
2211 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2216 XMLNodeConstIterator niter;
2218 nlist = node->children();
2222 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2226 if ((prop = (*niter)->property (X_("type"))) == 0) {
2230 DataType type (prop->value());
2232 if ((prop = (*niter)->property (X_("name"))) == 0) {
2236 if (prop->value()[0] == '/') {
2237 /* external file, ignore */
2241 Glib::ustring found_path;
2245 if (FileSource::find (type, prop->value(), true, is_new, chan, found_path)) {
2246 result.insert (found_path);
2254 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2256 PathScanner scanner;
2257 vector<string*>* state_files;
2259 string this_snapshot_path;
2265 if (ripped[ripped.length()-1] == '/') {
2266 ripped = ripped.substr (0, ripped.length() - 1);
2269 state_files = scanner (ripped, accept_all_state_files, (void *) 0, false, true);
2271 if (state_files == 0) {
2276 this_snapshot_path = _path;
2277 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2278 this_snapshot_path += statefile_suffix;
2280 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2282 if (exclude_this_snapshot && **i == this_snapshot_path) {
2286 if (find_all_sources (**i, result) < 0) {
2294 struct RegionCounter {
2295 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2296 AudioSourceList::iterator iter;
2297 boost::shared_ptr<Region> region;
2300 RegionCounter() : count (0) {}
2304 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2306 return *AskAboutPlaylistDeletion (p);
2310 Session::cleanup_sources (CleanupReport& rep)
2312 // FIXME: needs adaptation to midi
2314 vector<boost::shared_ptr<Source> > dead_sources;
2315 PathScanner scanner;
2317 vector<space_and_path>::iterator i;
2318 vector<space_and_path>::iterator nexti;
2319 vector<string*>* soundfiles;
2320 vector<string> unused;
2321 set<string> all_sources;
2326 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2328 /* step 1: consider deleting all unused playlists */
2330 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2335 /* step 2: find all un-used sources */
2340 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2342 SourceMap::iterator tmp;
2347 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2351 if (!playlists->source_use_count(i->second) && i->second->length(i->second->timeline_position()) > 0) {
2352 dead_sources.push_back (i->second);
2353 i->second->drop_references ();
2359 /* build a list of all the possible sound directories for the session */
2361 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2366 SessionDirectory sdir ((*i).path);
2367 sound_path += sdir.sound_path().to_string();
2369 if (nexti != session_dirs.end()) {
2376 /* now do the same thing for the files that ended up in the sounds dir(s)
2377 but are not referenced as sources in any snapshot.
2380 soundfiles = scanner (sound_path, accept_all_non_peak_files, (void *) 0, false, true);
2382 if (soundfiles == 0) {
2386 /* find all sources, but don't use this snapshot because the
2387 state file on disk still references sources we may have already
2391 find_all_sources_across_snapshots (all_sources, true);
2393 /* add our current source list
2396 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2397 boost::shared_ptr<FileSource> fs;
2399 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2400 all_sources.insert (fs->path());
2404 char tmppath1[PATH_MAX+1];
2405 char tmppath2[PATH_MAX+1];
2407 for (vector<string*>::iterator x = soundfiles->begin(); x != soundfiles->end(); ++x) {
2412 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2414 realpath(spath.c_str(), tmppath1);
2415 realpath((*i).c_str(), tmppath2);
2417 if (strcmp(tmppath1, tmppath2) == 0) {
2424 unused.push_back (spath);
2428 /* now try to move all unused files into the "dead_sounds" directory(ies) */
2430 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2431 struct stat statbuf;
2433 rep.paths.push_back (*x);
2434 if (stat ((*x).c_str(), &statbuf) == 0) {
2435 rep.space += statbuf.st_size;
2440 /* don't move the file across filesystems, just
2441 stick it in the `dead_sound_dir_name' directory
2442 on whichever filesystem it was already on.
2445 if ((*x).find ("/sounds/") != string::npos) {
2447 /* old school, go up 1 level */
2449 newpath = Glib::path_get_dirname (*x); // "sounds"
2450 newpath = Glib::path_get_dirname (newpath); // "session-name"
2454 /* new school, go up 4 levels */
2456 newpath = Glib::path_get_dirname (*x); // "audiofiles"
2457 newpath = Glib::path_get_dirname (newpath); // "session-name"
2458 newpath = Glib::path_get_dirname (newpath); // "interchange"
2459 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2463 newpath += dead_sound_dir_name;
2465 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2466 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2471 newpath += Glib::path_get_basename ((*x));
2473 if (access (newpath.c_str(), F_OK) == 0) {
2475 /* the new path already exists, try versioning */
2477 char buf[PATH_MAX+1];
2481 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2484 while (access (newpath_v.c_str(), F_OK) == 0 && version < 999) {
2485 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2489 if (version == 999) {
2490 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2494 newpath = newpath_v;
2499 /* it doesn't exist, or we can't read it or something */
2503 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2504 error << string_compose (_("cannot rename audio file source from %1 to %2 (%3)"),
2505 (*x), newpath, strerror (errno))
2510 /* see if there an easy to find peakfile for this file, and remove it.
2513 string peakpath = (*x).substr (0, (*x).find_last_of ('.'));
2514 peakpath += peakfile_suffix;
2516 if (access (peakpath.c_str(), W_OK) == 0) {
2517 if (::unlink (peakpath.c_str()) != 0) {
2518 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2519 peakpath, _path, strerror (errno))
2521 /* try to back out */
2522 rename (newpath.c_str(), _path.c_str());
2530 /* dump the history list */
2534 /* save state so we don't end up a session file
2535 referring to non-existent sources.
2541 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2547 Session::cleanup_trash_sources (CleanupReport& rep)
2549 // FIXME: needs adaptation for MIDI
2551 vector<space_and_path>::iterator i;
2552 string dead_sound_dir;
2553 struct dirent* dentry;
2554 struct stat statbuf;
2560 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2562 dead_sound_dir = (*i).path;
2563 dead_sound_dir += dead_sound_dir_name;
2565 if ((dead = opendir (dead_sound_dir.c_str())) == 0) {
2569 while ((dentry = readdir (dead)) != 0) {
2571 /* avoid '.' and '..' */
2573 if ((dentry->d_name[0] == '.' && dentry->d_name[1] == '\0') ||
2574 (dentry->d_name[2] == '\0' && dentry->d_name[0] == '.' && dentry->d_name[1] == '.')) {
2580 fullpath = dead_sound_dir;
2582 fullpath += dentry->d_name;
2584 if (stat (fullpath.c_str(), &statbuf)) {
2588 if (!S_ISREG (statbuf.st_mode)) {
2592 if (unlink (fullpath.c_str())) {
2593 error << string_compose (_("cannot remove dead sound file %1 (%2)"),
2594 fullpath, strerror (errno))
2598 rep.paths.push_back (dentry->d_name);
2599 rep.space += statbuf.st_size;
2610 Session::set_dirty ()
2612 bool was_dirty = dirty();
2614 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2618 DirtyChanged(); /* EMIT SIGNAL */
2624 Session::set_clean ()
2626 bool was_dirty = dirty();
2628 _state_of_the_state = Clean;
2632 DirtyChanged(); /* EMIT SIGNAL */
2637 Session::set_deletion_in_progress ()
2639 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2643 Session::clear_deletion_in_progress ()
2645 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2649 Session::add_controllable (boost::shared_ptr<Controllable> c)
2651 /* this adds a controllable to the list managed by the Session.
2652 this is a subset of those managed by the Controllable class
2653 itself, and represents the only ones whose state will be saved
2654 as part of the session.
2657 Glib::Mutex::Lock lm (controllables_lock);
2658 controllables.insert (c);
2661 struct null_deleter { void operator()(void const *) const {} };
2664 Session::remove_controllable (Controllable* c)
2666 if (_state_of_the_state | Deletion) {
2670 Glib::Mutex::Lock lm (controllables_lock);
2672 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
2674 if (x != controllables.end()) {
2675 controllables.erase (x);
2679 boost::shared_ptr<Controllable>
2680 Session::controllable_by_id (const PBD::ID& id)
2682 Glib::Mutex::Lock lm (controllables_lock);
2684 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2685 if ((*i)->id() == id) {
2690 return boost::shared_ptr<Controllable>();
2693 boost::shared_ptr<Controllable>
2694 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
2696 boost::shared_ptr<Controllable> c;
2697 boost::shared_ptr<Route> r;
2699 switch (desc.top_level_type()) {
2700 case ControllableDescriptor::NamedRoute:
2702 std::string str = desc.top_level_name();
2703 if (str == "master") {
2705 } else if (str == "control" || str == "listen") {
2708 r = route_by_name (desc.top_level_name());
2713 case ControllableDescriptor::RemoteControlID:
2714 r = route_by_remote_id (desc.rid());
2722 switch (desc.subtype()) {
2723 case ControllableDescriptor::Gain:
2724 c = r->gain_control ();
2727 case ControllableDescriptor::Solo:
2728 c = r->solo_control();
2731 case ControllableDescriptor::Mute:
2732 c = r->mute_control();
2735 case ControllableDescriptor::Recenable:
2737 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
2740 c = t->rec_enable_control ();
2745 case ControllableDescriptor::Pan:
2746 /* XXX pan control */
2749 case ControllableDescriptor::Balance:
2750 /* XXX simple pan control */
2753 case ControllableDescriptor::PluginParameter:
2755 uint32_t plugin = desc.target (0);
2756 uint32_t parameter_index = desc.target (1);
2758 /* revert to zero based counting */
2764 if (parameter_index > 0) {
2768 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
2771 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
2772 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
2777 case ControllableDescriptor::SendGain:
2779 uint32_t send = desc.target (0);
2781 /* revert to zero-based counting */
2787 boost::shared_ptr<Processor> p = r->nth_send (send);
2790 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
2791 boost::shared_ptr<Amp> a = s->amp();
2794 c = s->amp()->gain_control();
2801 /* relax and return a null pointer */
2809 Session::add_instant_xml (XMLNode& node, bool write_to_config)
2812 Stateful::add_instant_xml (node, _path);
2815 if (write_to_config) {
2816 Config->add_instant_xml (node);
2821 Session::instant_xml (const string& node_name)
2823 return Stateful::instant_xml (node_name, _path);
2827 Session::save_history (string snapshot_name)
2835 if (snapshot_name.empty()) {
2836 snapshot_name = _current_snapshot_name;
2839 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
2840 const string backup_filename = history_filename + backup_suffix;
2841 const sys::path xml_path = _session_dir->root_path() / history_filename;
2842 const sys::path backup_path = _session_dir->root_path() / backup_filename;
2844 if (sys::exists (xml_path)) {
2847 sys::rename (xml_path, backup_path);
2849 catch (const sys::filesystem_error& err)
2851 error << _("could not backup old history file, current history not saved") << endmsg;
2856 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
2860 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
2862 if (!tree.write (xml_path.to_string()))
2864 error << string_compose (_("history could not be saved to %1"), xml_path.to_string()) << endmsg;
2868 sys::remove (xml_path);
2869 sys::rename (backup_path, xml_path);
2871 catch (const sys::filesystem_error& err)
2873 error << string_compose (_("could not restore history file from backup %1 (%2)"),
2874 backup_path.to_string(), err.what()) << endmsg;
2884 Session::restore_history (string snapshot_name)
2888 if (snapshot_name.empty()) {
2889 snapshot_name = _current_snapshot_name;
2892 const string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
2893 const sys::path xml_path = _session_dir->root_path() / xml_filename;
2895 info << "Loading history from " << xml_path.to_string() << endmsg;
2897 if (!sys::exists (xml_path)) {
2898 info << string_compose (_("%1: no history file \"%2\" for this session."),
2899 _name, xml_path.to_string()) << endmsg;
2903 if (!tree.read (xml_path.to_string())) {
2904 error << string_compose (_("Could not understand session history file \"%1\""),
2905 xml_path.to_string()) << endmsg;
2912 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
2915 UndoTransaction* ut = new UndoTransaction ();
2918 ut->set_name(t->property("name")->value());
2919 stringstream ss(t->property("tv-sec")->value());
2921 ss.str(t->property("tv-usec")->value());
2923 ut->set_timestamp(tv);
2925 for (XMLNodeConstIterator child_it = t->children().begin();
2926 child_it != t->children().end(); child_it++)
2928 XMLNode *n = *child_it;
2931 if (n->name() == "MementoCommand" ||
2932 n->name() == "MementoUndoCommand" ||
2933 n->name() == "MementoRedoCommand") {
2935 if ((c = memento_command_factory(n))) {
2939 } else if (n->name() == "DeltaCommand") {
2940 PBD::ID id(n->property("midi-source")->value());
2941 boost::shared_ptr<MidiSource> midi_source =
2942 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
2944 ut->add_command(new MidiModel::DeltaCommand(midi_source->model(), *n));
2946 error << _("Failed to downcast MidiSource for DeltaCommand") << endmsg;
2949 } else if (n->name() == "DiffCommand") {
2950 PBD::ID id(n->property("midi-source")->value());
2951 boost::shared_ptr<MidiSource> midi_source =
2952 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
2954 ut->add_command(new MidiModel::DiffCommand(midi_source->model(), *n));
2956 error << _("Failed to downcast MidiSource for DeltaCommand") << endmsg;
2959 } else if (n->name() == "StatefulDiffCommand") {
2960 if ((c = stateful_diff_command_factory (n))) {
2961 ut->add_command (c);
2964 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
2975 Session::config_changed (std::string p, bool ours)
2981 if (p == "seamless-loop") {
2983 } else if (p == "rf-speed") {
2985 } else if (p == "auto-loop") {
2987 } else if (p == "auto-input") {
2989 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
2990 /* auto-input only makes a difference if we're rolling */
2992 boost::shared_ptr<DiskstreamList> dsl = diskstreams.reader();
2994 for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
2995 if ((*i)->record_enabled ()) {
2996 (*i)->monitor_input (!config.get_auto_input());
3001 } else if (p == "punch-in") {
3005 if ((location = _locations.auto_punch_location()) != 0) {
3007 if (config.get_punch_in ()) {
3008 replace_event (SessionEvent::PunchIn, location->start());
3010 remove_event (location->start(), SessionEvent::PunchIn);
3014 } else if (p == "punch-out") {
3018 if ((location = _locations.auto_punch_location()) != 0) {
3020 if (config.get_punch_out()) {
3021 replace_event (SessionEvent::PunchOut, location->end());
3023 clear_events (SessionEvent::PunchOut);
3027 } else if (p == "edit-mode") {
3029 Glib::Mutex::Lock lm (playlists->lock);
3031 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3032 (*i)->set_edit_mode (Config->get_edit_mode ());
3035 } else if (p == "use-video-sync") {
3037 waiting_for_sync_offset = config.get_use_video_sync();
3039 } else if (p == "mmc-control") {
3041 //poke_midi_thread ();
3043 } else if (p == "mmc-device-id" || p == "mmc-receive-id") {
3046 mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3049 } else if (p == "mmc-send-id") {
3052 mmc->set_send_device_id (Config->get_mmc_send_device_id());
3055 } else if (p == "midi-control") {
3057 //poke_midi_thread ();
3059 } else if (p == "raid-path") {
3061 setup_raid_path (config.get_raid_path());
3063 } else if (p == "timecode-format") {
3067 } else if (p == "video-pullup") {
3071 } else if (p == "seamless-loop") {
3073 if (play_loop && transport_rolling()) {
3074 // to reset diskstreams etc
3075 request_play_loop (true);
3078 } else if (p == "rf-speed") {
3080 cumulative_rf_motion = 0;
3083 } else if (p == "click-sound") {
3085 setup_click_sounds (1);
3087 } else if (p == "click-emphasis-sound") {
3089 setup_click_sounds (-1);
3091 } else if (p == "clicking") {
3093 if (Config->get_clicking()) {
3094 if (_click_io && click_data) { // don't require emphasis data
3101 } else if (p == "send-mtc") {
3103 /* only set the internal flag if we have
3107 if (_mtc_port != 0) {
3108 session_send_mtc = Config->get_send_mtc();
3109 if (session_send_mtc) {
3110 /* mark us ready to send */
3111 next_quarter_frame_to_send = 0;
3114 session_send_mtc = false;
3117 } else if (p == "send-mmc") {
3119 /* only set the internal flag if we have
3123 if (_mmc_port != 0) {
3124 session_send_mmc = Config->get_send_mmc();
3127 session_send_mmc = false;
3130 } else if (p == "midi-feedback") {
3132 /* only set the internal flag if we have
3136 if (_mtc_port != 0) {
3137 session_midi_feedback = Config->get_midi_feedback();
3140 } else if (p == "jack-time-master") {
3142 engine().reset_timebase ();
3144 } else if (p == "native-file-header-format") {
3146 if (!first_file_header_format_reset) {
3147 reset_native_file_format ();
3150 first_file_header_format_reset = false;
3152 } else if (p == "native-file-data-format") {
3154 if (!first_file_data_format_reset) {
3155 reset_native_file_format ();
3158 first_file_data_format_reset = false;
3160 } else if (p == "external-sync") {
3161 if (!config.get_external_sync()) {
3162 drop_sync_source ();
3164 switch_to_sync_source (config.get_sync_source());
3166 } else if (p == "remote-model") {
3167 set_remote_control_ids ();
3168 } else if (p == "denormal-model") {
3170 } else if (p == "history-depth") {
3171 set_history_depth (Config->get_history_depth());
3172 } else if (p == "sync-all-route-ordering") {
3173 sync_order_keys ("session");
3174 } else if (p == "initial-program-change") {
3176 if (_mmc_port && Config->get_initial_program_change() >= 0) {
3179 buf[0] = MIDI::program; // channel zero by default
3180 buf[1] = (Config->get_initial_program_change() & 0x7f);
3182 _mmc_port->midimsg (buf, sizeof (buf), 0);
3184 } else if (p == "initial-program-change") {
3186 if (_mmc_port && Config->get_initial_program_change() >= 0) {
3187 MIDI::byte* buf = new MIDI::byte[2];
3189 buf[0] = MIDI::program; // channel zero by default
3190 buf[1] = (Config->get_initial_program_change() & 0x7f);
3191 // deliver_midi (_mmc_port, buf, 2);
3193 } else if (p == "solo-mute-override") {
3194 // catch_up_on_solo_mute_override ();
3195 } else if (p == "listen-position") {
3196 listen_position_changed ();
3197 } else if (p == "solo-control-is-listen-control") {
3198 solo_control_mode_changed ();
3206 Session::set_history_depth (uint32_t d)
3208 _history.set_depth (d);