2 Copyright (C) 1999-2013 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"
31 #include <cstdio> /* snprintf(3) ... grrr */
45 #include <sys/param.h>
46 #include <sys/mount.h>
49 #ifdef HAVE_SYS_STATVFS_H
50 #include <sys/statvfs.h>
54 #include <glib/gstdio.h>
57 #include <glibmm/threads.h>
59 #include <boost/algorithm/string.hpp>
61 #include "midi++/mmc.h"
62 #include "midi++/port.h"
64 #include "evoral/SMF.hpp"
66 #include "pbd/boost_debug.h"
67 #include "pbd/basename.h"
68 #include "pbd/controllable_descriptor.h"
69 #include "pbd/enumwriter.h"
70 #include "pbd/error.h"
71 #include "pbd/file_utils.h"
72 #include "pbd/pathscanner.h"
73 #include "pbd/pthread_utils.h"
74 #include "pbd/stacktrace.h"
75 #include "pbd/convert.h"
76 #include "pbd/clear_dir.h"
78 #include "ardour/amp.h"
79 #include "ardour/audio_diskstream.h"
80 #include "ardour/audio_track.h"
81 #include "ardour/audioengine.h"
82 #include "ardour/audiofilesource.h"
83 #include "ardour/audioregion.h"
84 #include "ardour/automation_control.h"
85 #include "ardour/butler.h"
86 #include "ardour/control_protocol_manager.h"
87 #include "ardour/directory_names.h"
88 #include "ardour/filename_extensions.h"
89 #include "ardour/location.h"
90 #include "ardour/midi_model.h"
91 #include "ardour/midi_patch_manager.h"
92 #include "ardour/midi_region.h"
93 #include "ardour/midi_source.h"
94 #include "ardour/midi_track.h"
95 #include "ardour/pannable.h"
96 #include "ardour/playlist_factory.h"
97 #include "ardour/port.h"
98 #include "ardour/processor.h"
99 #include "ardour/proxy_controllable.h"
100 #include "ardour/recent_sessions.h"
101 #include "ardour/region_factory.h"
102 #include "ardour/route_group.h"
103 #include "ardour/send.h"
104 #include "ardour/session.h"
105 #include "ardour/session_directory.h"
106 #include "ardour/session_metadata.h"
107 #include "ardour/session_playlists.h"
108 #include "ardour/session_state_utils.h"
109 #include "ardour/silentfilesource.h"
110 #include "ardour/sndfilesource.h"
111 #include "ardour/source_factory.h"
112 #include "ardour/speakers.h"
113 #include "ardour/template_utils.h"
114 #include "ardour/tempo.h"
115 #include "ardour/ticker.h"
116 #include "ardour/user_bundle.h"
118 #include "control_protocol/control_protocol.h"
124 using namespace ARDOUR;
127 /** @param snapshot_name Snapshot name, without the .ardour prefix */
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 (%2)"), buf, strerror(errno)) << endmsg;
140 throw failed_constructor();
145 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
146 _path += G_DIR_SEPARATOR;
149 /* these two are just provisional settings. set_state()
150 will likely override them.
153 _name = _current_snapshot_name = snapshot_name;
155 set_history_depth (Config->get_history_depth());
157 _current_frame_rate = _engine.sample_rate ();
158 _nominal_frame_rate = _current_frame_rate;
159 _base_frame_rate = _current_frame_rate;
161 _tempo_map = new TempoMap (_current_frame_rate);
162 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
165 _non_soloed_outs_muted = false;
167 _solo_isolated_cnt = 0;
168 g_atomic_int_set (&processing_prohibited, 0);
169 _transport_speed = 0;
170 _default_transport_speed = 1.0;
171 _last_transport_speed = 0;
172 _target_transport_speed = 0;
173 auto_play_legal = false;
174 transport_sub_state = 0;
175 _transport_frame = 0;
176 _requested_return_frame = -1;
177 _session_range_location = 0;
178 g_atomic_int_set (&_record_status, Disabled);
179 loop_changing = false;
182 _last_roll_location = 0;
183 _last_roll_or_reversal_location = 0;
184 _last_record_location = 0;
185 pending_locate_frame = 0;
186 pending_locate_roll = false;
187 pending_locate_flush = false;
188 state_was_pending = false;
190 outbound_mtc_timecode_frame = 0;
191 next_quarter_frame_to_send = -1;
192 current_block_size = 0;
193 solo_update_disabled = false;
194 _have_captured = false;
195 _worst_output_latency = 0;
196 _worst_input_latency = 0;
197 _worst_track_latency = 0;
198 _state_of_the_state = StateOfTheState(CannotSave|InitialConnecting|Loading);
199 _was_seamless = Config->get_seamless_loop ();
201 _send_qf_mtc = false;
202 _pframes_since_last_mtc = 0;
203 g_atomic_int_set (&_playback_load, 100);
204 g_atomic_int_set (&_capture_load, 100);
207 pending_abort = false;
208 _adding_routes_in_progress = false;
209 destructive_index = 0;
210 first_file_data_format_reset = true;
211 first_file_header_format_reset = true;
212 post_export_sync = false;
215 no_questions_about_missing_files = false;
216 _speakers.reset (new Speakers);
218 ignore_route_processor_changes = false;
219 _pre_export_mmc_enabled = false;
221 AudioDiskstream::allocate_working_buffers();
223 /* default short fade = 15ms */
225 SndFileSource::setup_standard_crossfades (*this, frame_rate());
227 last_mmc_step.tv_sec = 0;
228 last_mmc_step.tv_usec = 0;
231 /* click sounds are unset by default, which causes us to internal
232 waveforms for clicks.
236 click_emphasis_length = 0;
239 process_function = &Session::process_with_events;
241 if (config.get_use_video_sync()) {
242 waiting_for_sync_offset = true;
244 waiting_for_sync_offset = false;
247 last_timecode_when = 0;
248 last_timecode_valid = false;
252 last_rr_session_dir = session_dirs.begin();
253 refresh_disk_space ();
255 /* default: assume simple stereo speaker configuration */
257 _speakers->setup_default_speakers (2);
261 average_slave_delta = 1800; // !!! why 1800 ????
262 have_first_delta_accumulator = false;
263 delta_accumulator_cnt = 0;
264 _slave_state = Stopped;
266 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
267 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
268 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
269 add_controllable (_solo_cut_control);
271 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
273 /* These are all static "per-class" signals */
275 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
276 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
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 ()
290 AudioFileSource::set_peak_dir (_session_dir->peak_path());
293 if (load_state (_current_snapshot_name)) {
298 if (_butler->start_thread()) {
302 if (start_midi_thread ()) {
306 setup_midi_machine_control ();
308 // set_state() will call setup_raid_path(), but if it's a new session we need
309 // to call setup_raid_path() here.
312 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
316 setup_raid_path(_path);
319 /* we can't save till after ::when_engine_running() is called,
320 because otherwise we save state with no connections made.
321 therefore, we reset _state_of_the_state because ::set_state()
322 will have cleared it.
324 we also have to include Loading so that any events that get
325 generated between here and the end of ::when_engine_running()
326 will be processed directly rather than queued.
329 _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));
341 midi_clock = new MidiClockTicker ();
342 midi_clock->set_session (this);
345 when_engine_running ();
348 /* handle this one in a different way than all others, so that its clear what happened */
350 catch (AudioEngine::PortRegistrationFailure& err) {
351 error << err.what() << endmsg;
359 BootMessage (_("Reset Remote Controls"));
361 // send_full_time_code (0);
362 _engine.transport_locate (0);
364 _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
365 _mmc->send (MIDI::MachineControlCommand (Timecode::Time ()));
367 MIDI::Name::MidiPatchManager::instance().set_session (this);
370 /* initial program change will be delivered later; see ::config_changed() */
372 _state_of_the_state = Clean;
374 Port::set_connecting_blocked (false);
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 += (*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) {
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 // reset the round-robin soundfile path thingie
429 last_rr_session_dir = session_dirs.begin();
433 Session::path_is_within_session (const std::string& path)
435 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
436 if (PBD::path_is_within (i->path, path)) {
444 Session::ensure_subdirs ()
448 dir = session_directory().peak_path();
450 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
451 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
455 dir = session_directory().sound_path();
457 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
458 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
462 dir = session_directory().midi_path();
464 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
465 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
469 dir = session_directory().dead_path();
471 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
472 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
476 dir = session_directory().export_path();
478 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
479 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
483 dir = analysis_dir ();
485 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
486 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
490 dir = plugins_dir ();
492 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
493 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
497 dir = externals_dir ();
499 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
500 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
507 /** @param session_template directory containing session template, or empty.
508 * Caller must not hold process lock.
511 Session::create (const string& session_template, BusProfile* bus_profile)
513 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
514 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
518 if (ensure_subdirs ()) {
522 _writable = exists_and_writable (_path);
524 if (!session_template.empty()) {
525 std::string in_path = session_template_dir_to_file (session_template);
527 ifstream in(in_path.c_str());
530 string out_path = _path;
532 out_path += statefile_suffix;
534 ofstream out(out_path.c_str());
540 /* Copy plugin state files from template to new session */
541 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
542 copy_files (template_plugins, plugins_dir ());
547 error << string_compose (_("Could not open %1 for writing session template"), out_path)
553 error << string_compose (_("Could not open session template %1 for reading"), in_path)
560 /* set initial start + end point */
562 _state_of_the_state = Clean;
564 /* set up Master Out and Control Out if necessary */
569 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
571 if (bus_profile->master_out_channels) {
572 boost::shared_ptr<Route> r (new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO));
576 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
577 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
580 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
581 r->input()->ensure_io (count, false, this);
582 r->output()->ensure_io (count, false, this);
588 /* prohibit auto-connect to master, because there isn't one */
589 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
593 add_routes (rl, false, false, false);
596 /* this allows the user to override settings with an environment variable.
599 if (no_auto_connect()) {
600 bus_profile->input_ac = AutoConnectOption (0);
601 bus_profile->output_ac = AutoConnectOption (0);
604 Config->set_input_auto_connect (bus_profile->input_ac);
605 Config->set_output_auto_connect (bus_profile->output_ac);
608 if (Config->get_use_monitor_bus() && bus_profile) {
609 add_monitor_section ();
618 Session::maybe_write_autosave()
620 if (dirty() && record_status() != Recording) {
621 save_state("", true);
626 Session::remove_pending_capture_state ()
628 std::string pending_state_file_path(_session_dir->root_path());
630 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
632 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
634 if (g_remove (pending_state_file_path.c_str()) != 0) {
635 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
636 pending_state_file_path, g_strerror (errno)) << endmsg;
640 /** Rename a state file.
641 * @param old_name Old snapshot name.
642 * @param new_name New snapshot name.
645 Session::rename_state (string old_name, string new_name)
647 if (old_name == _current_snapshot_name || old_name == _name) {
648 /* refuse to rename the current snapshot or the "main" one */
652 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
653 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
655 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
656 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
658 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
659 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
660 old_name, new_name, g_strerror(errno)) << endmsg;
664 /** Remove a state file.
665 * @param snapshot_name Snapshot name.
668 Session::remove_state (string snapshot_name)
670 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
671 // refuse to remove the current snapshot or the "main" one
675 std::string xml_path(_session_dir->root_path());
677 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
679 if (!create_backup_file (xml_path)) {
680 // don't remove it if a backup can't be made
681 // create_backup_file will log the error.
686 if (g_remove (xml_path.c_str()) != 0) {
687 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
688 xml_path, g_strerror (errno)) << endmsg;
692 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
694 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
697 std::string xml_path(_session_dir->root_path());
699 if (!_writable || (_state_of_the_state & CannotSave)) {
703 if (!_engine.connected ()) {
704 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
710 /* tell sources we're saving first, in case they write out to a new file
711 * which should be saved with the state rather than the old one */
712 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
714 i->second->session_saved();
715 } catch (Evoral::SMF::FileError& e) {
716 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
720 SaveSession (); /* EMIT SIGNAL */
722 tree.set_root (&get_state());
724 if (snapshot_name.empty()) {
725 snapshot_name = _current_snapshot_name;
726 } else if (switch_to_snapshot) {
727 _current_snapshot_name = snapshot_name;
732 /* proper save: use statefile_suffix (.ardour in English) */
734 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
736 /* make a backup copy of the old file */
738 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
739 // create_backup_file will log the error
745 /* pending save: use pending_suffix (.pending in English) */
746 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
749 std::string tmp_path(_session_dir->root_path());
750 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
752 // cerr << "actually writing state to " << xml_path << endl;
754 if (!tree.write (tmp_path)) {
755 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
756 if (g_remove (tmp_path.c_str()) != 0) {
757 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
758 tmp_path, g_strerror (errno)) << endmsg;
764 if (::rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
765 error << string_compose (_("could not rename temporary session file %1 to %2"),
766 tmp_path, xml_path) << endmsg;
767 if (g_remove (tmp_path.c_str()) != 0) {
768 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
769 tmp_path, g_strerror (errno)) << endmsg;
777 save_history (snapshot_name);
779 bool was_dirty = dirty();
781 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
784 DirtyChanged (); /* EMIT SIGNAL */
787 StateSaved (snapshot_name); /* EMIT SIGNAL */
794 Session::restore_state (string snapshot_name)
796 if (load_state (snapshot_name) == 0) {
797 set_state (*state_tree->root(), Stateful::loading_state_version);
804 Session::load_state (string snapshot_name)
809 state_was_pending = false;
811 /* check for leftover pending state from a crashed capture attempt */
813 std::string xmlpath(_session_dir->root_path());
814 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
816 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
818 /* there is pending state from a crashed capture attempt */
820 boost::optional<int> r = AskAboutPendingState();
821 if (r.get_value_or (1)) {
822 state_was_pending = true;
826 if (!state_was_pending) {
827 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
830 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
831 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
832 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
833 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
838 state_tree = new XMLTree;
842 _writable = exists_and_writable (xmlpath);
844 if (!state_tree->read (xmlpath)) {
845 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
851 XMLNode& root (*state_tree->root());
853 if (root.name() != X_("Session")) {
854 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
860 const XMLProperty* prop;
862 if ((prop = root.property ("version")) == 0) {
863 /* no version implies very old version of Ardour */
864 Stateful::loading_state_version = 1000;
866 if (prop->value().find ('.') != string::npos) {
867 /* old school version format */
868 if (prop->value()[0] == '2') {
869 Stateful::loading_state_version = 2000;
871 Stateful::loading_state_version = 3000;
874 Stateful::loading_state_version = atoi (prop->value());
878 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
880 std::string backup_path(_session_dir->root_path());
881 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
882 backup_path = Glib::build_filename (backup_path, backup_filename);
884 // only create a backup for a given statefile version once
886 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
888 VersionMismatch (xmlpath, backup_path);
890 if (!copy_file (xmlpath, backup_path)) {;
900 Session::load_options (const XMLNode& node)
902 LocaleGuard lg (X_("POSIX"));
903 config.set_variables (node);
914 Session::get_template()
916 /* if we don't disable rec-enable, diskstreams
917 will believe they need to store their capture
918 sources in their state node.
921 disable_record (false);
927 Session::state (bool full_state)
929 XMLNode* node = new XMLNode("Session");
933 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
934 node->add_property("version", buf);
936 /* store configuration settings */
940 node->add_property ("name", _name);
941 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
942 node->add_property ("sample-rate", buf);
944 if (session_dirs.size() > 1) {
948 vector<space_and_path>::iterator i = session_dirs.begin();
949 vector<space_and_path>::iterator next;
951 ++i; /* skip the first one */
955 while (i != session_dirs.end()) {
959 if (next != session_dirs.end()) {
969 child = node->add_child ("Path");
970 child->add_content (p);
974 /* save the ID counter */
976 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
977 node->add_property ("id-counter", buf);
979 /* save the event ID counter */
981 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
982 node->add_property ("event-counter", buf);
984 /* various options */
986 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
987 if (!midi_port_nodes.empty()) {
988 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
989 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
990 midi_port_stuff->add_child_nocopy (**n);
992 node->add_child_nocopy (*midi_port_stuff);
995 node->add_child_nocopy (config.get_variables ());
997 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
999 child = node->add_child ("Sources");
1002 Glib::Threads::Mutex::Lock sl (source_lock);
1004 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1006 /* Don't save information about non-file Sources, or
1007 * about non-destructive file sources that are empty
1008 * and unused by any regions.
1011 boost::shared_ptr<FileSource> fs;
1013 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1015 if (!fs->destructive()) {
1016 if (fs->empty() && !fs->used()) {
1021 child->add_child_nocopy (siter->second->get_state());
1026 child = node->add_child ("Regions");
1029 Glib::Threads::Mutex::Lock rl (region_lock);
1030 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1031 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1032 boost::shared_ptr<Region> r = i->second;
1033 /* only store regions not attached to playlists */
1034 if (r->playlist() == 0) {
1035 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1036 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1038 child->add_child_nocopy (r->get_state ());
1043 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1045 if (!cassocs.empty()) {
1046 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1048 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1050 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1051 i->first->id().print (buf, sizeof (buf));
1052 can->add_property (X_("copy"), buf);
1053 i->second->id().print (buf, sizeof (buf));
1054 can->add_property (X_("original"), buf);
1055 ca->add_child_nocopy (*can);
1061 node->add_child_nocopy (_locations->get_state());
1063 // for a template, just create a new Locations, populate it
1064 // with the default start and end, and get the state for that.
1065 Locations loc (*this);
1066 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1067 range->set (max_framepos, 0);
1069 node->add_child_nocopy (loc.get_state());
1072 child = node->add_child ("Bundles");
1074 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1075 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1076 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1078 child->add_child_nocopy (b->get_state());
1083 child = node->add_child ("Routes");
1085 boost::shared_ptr<RouteList> r = routes.reader ();
1087 RoutePublicOrderSorter cmp;
1088 RouteList public_order (*r);
1089 public_order.sort (cmp);
1091 /* the sort should have put control outs first */
1094 assert (_monitor_out == public_order.front());
1097 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1098 if (!(*i)->is_auditioner()) {
1100 child->add_child_nocopy ((*i)->get_state());
1102 child->add_child_nocopy ((*i)->get_template());
1108 playlists->add_state (node, full_state);
1110 child = node->add_child ("RouteGroups");
1111 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1112 child->add_child_nocopy ((*i)->get_state());
1116 XMLNode* gain_child = node->add_child ("Click");
1117 gain_child->add_child_nocopy (_click_io->state (full_state));
1118 gain_child->add_child_nocopy (_click_gain->state (full_state));
1122 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1123 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1127 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1128 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1131 node->add_child_nocopy (_speakers->get_state());
1132 node->add_child_nocopy (_tempo_map->get_state());
1133 node->add_child_nocopy (get_control_protocol_state());
1136 node->add_child_copy (*_extra_xml);
1143 Session::get_control_protocol_state ()
1145 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1146 return cpm.get_state();
1150 Session::set_state (const XMLNode& node, int version)
1154 const XMLProperty* prop;
1157 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1159 if (node.name() != X_("Session")) {
1160 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1164 if ((prop = node.property ("name")) != 0) {
1165 _name = prop->value ();
1168 if ((prop = node.property (X_("sample-rate"))) != 0) {
1170 _nominal_frame_rate = atoi (prop->value());
1172 if (_nominal_frame_rate != _current_frame_rate) {
1173 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1174 if (r.get_value_or (0)) {
1180 setup_raid_path(_session_dir->root_path());
1182 if ((prop = node.property (X_("id-counter"))) != 0) {
1184 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1185 ID::init_counter (x);
1187 /* old sessions used a timebased counter, so fake
1188 the startup ID counter based on a standard
1193 ID::init_counter (now);
1196 if ((prop = node.property (X_("event-counter"))) != 0) {
1197 Evoral::init_event_id_counter (atoi (prop->value()));
1201 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1202 _midi_ports->set_midi_port_states (child->children());
1205 IO::disable_connecting ();
1207 Stateful::save_extra_xml (node);
1209 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1210 load_options (*child);
1211 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1212 load_options (*child);
1214 error << _("Session: XML state has no options section") << endmsg;
1217 if (version >= 3000) {
1218 if ((child = find_named_node (node, "Metadata")) == 0) {
1219 warning << _("Session: XML state has no metadata section") << endmsg;
1220 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1225 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1226 _speakers->set_state (*child, version);
1229 if ((child = find_named_node (node, "Sources")) == 0) {
1230 error << _("Session: XML state has no sources section") << endmsg;
1232 } else if (load_sources (*child)) {
1236 if ((child = find_named_node (node, "TempoMap")) == 0) {
1237 error << _("Session: XML state has no Tempo Map section") << endmsg;
1239 } else if (_tempo_map->set_state (*child, version)) {
1243 if ((child = find_named_node (node, "Locations")) == 0) {
1244 error << _("Session: XML state has no locations section") << endmsg;
1246 } else if (_locations->set_state (*child, version)) {
1252 if ((location = _locations->auto_loop_location()) != 0) {
1253 set_auto_loop_location (location);
1256 if ((location = _locations->auto_punch_location()) != 0) {
1257 set_auto_punch_location (location);
1260 if ((location = _locations->session_range_location()) != 0) {
1261 delete _session_range_location;
1262 _session_range_location = location;
1265 if (_session_range_location) {
1266 AudioFileSource::set_header_position_offset (_session_range_location->start());
1269 if ((child = find_named_node (node, "Regions")) == 0) {
1270 error << _("Session: XML state has no Regions section") << endmsg;
1272 } else if (load_regions (*child)) {
1276 if ((child = find_named_node (node, "Playlists")) == 0) {
1277 error << _("Session: XML state has no playlists section") << endmsg;
1279 } else if (playlists->load (*this, *child)) {
1283 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1285 } else if (playlists->load_unused (*this, *child)) {
1289 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1290 if (load_compounds (*child)) {
1295 if (version >= 3000) {
1296 if ((child = find_named_node (node, "Bundles")) == 0) {
1297 warning << _("Session: XML state has no bundles section") << endmsg;
1300 /* We can't load Bundles yet as they need to be able
1301 to convert from port names to Port objects, which can't happen until
1303 _bundle_xml_node = new XMLNode (*child);
1307 if (version < 3000) {
1308 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1309 error << _("Session: XML state has no diskstreams section") << endmsg;
1311 } else if (load_diskstreams_2X (*child, version)) {
1316 if ((child = find_named_node (node, "Routes")) == 0) {
1317 error << _("Session: XML state has no routes section") << endmsg;
1319 } else if (load_routes (*child, version)) {
1323 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1324 _diskstreams_2X.clear ();
1326 if (version >= 3000) {
1328 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1329 error << _("Session: XML state has no route groups section") << endmsg;
1331 } else if (load_route_groups (*child, version)) {
1335 } else if (version < 3000) {
1337 if ((child = find_named_node (node, "EditGroups")) == 0) {
1338 error << _("Session: XML state has no edit groups section") << endmsg;
1340 } else if (load_route_groups (*child, version)) {
1344 if ((child = find_named_node (node, "MixGroups")) == 0) {
1345 error << _("Session: XML state has no mix groups section") << endmsg;
1347 } else if (load_route_groups (*child, version)) {
1352 if ((child = find_named_node (node, "Click")) == 0) {
1353 warning << _("Session: XML state has no click section") << endmsg;
1354 } else if (_click_io) {
1355 const XMLNodeList& children (child->children());
1356 XMLNodeList::const_iterator i = children.begin();
1357 _click_io->set_state (**i, version);
1359 if (i != children.end()) {
1360 _click_gain->set_state (**i, version);
1364 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1365 ControlProtocolManager::instance().set_state (*child, version);
1368 update_have_rec_enabled_track ();
1370 /* here beginneth the second phase ... */
1372 StateReady (); /* EMIT SIGNAL */
1381 Session::load_routes (const XMLNode& node, int version)
1384 XMLNodeConstIterator niter;
1385 RouteList new_routes;
1387 nlist = node.children();
1391 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1393 boost::shared_ptr<Route> route;
1394 if (version < 3000) {
1395 route = XMLRouteFactory_2X (**niter, version);
1397 route = XMLRouteFactory (**niter, version);
1401 error << _("Session: cannot create Route from XML description.") << endmsg;
1405 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1407 new_routes.push_back (route);
1410 add_routes (new_routes, false, false, false);
1415 boost::shared_ptr<Route>
1416 Session::XMLRouteFactory (const XMLNode& node, int version)
1418 boost::shared_ptr<Route> ret;
1420 if (node.name() != "Route") {
1424 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1426 DataType type = DataType::AUDIO;
1427 const XMLProperty* prop = node.property("default-type");
1430 type = DataType (prop->value());
1433 assert (type != DataType::NIL);
1437 boost::shared_ptr<Track> track;
1439 if (type == DataType::AUDIO) {
1440 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1442 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1445 if (track->init()) {
1449 if (track->set_state (node, version)) {
1453 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1454 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1459 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1461 if (r->init () == 0 && r->set_state (node, version) == 0) {
1462 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1463 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1472 boost::shared_ptr<Route>
1473 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1475 boost::shared_ptr<Route> ret;
1477 if (node.name() != "Route") {
1481 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1483 ds_prop = node.property (X_("diskstream"));
1486 DataType type = DataType::AUDIO;
1487 const XMLProperty* prop = node.property("default-type");
1490 type = DataType (prop->value());
1493 assert (type != DataType::NIL);
1497 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1498 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1502 if (i == _diskstreams_2X.end()) {
1503 error << _("Could not find diskstream for route") << endmsg;
1504 return boost::shared_ptr<Route> ();
1507 boost::shared_ptr<Track> track;
1509 if (type == DataType::AUDIO) {
1510 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1512 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1515 if (track->init()) {
1519 if (track->set_state (node, version)) {
1523 track->set_diskstream (*i);
1525 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1526 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1531 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1533 if (r->init () == 0 && r->set_state (node, version) == 0) {
1534 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1535 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1545 Session::load_regions (const XMLNode& node)
1548 XMLNodeConstIterator niter;
1549 boost::shared_ptr<Region> region;
1551 nlist = node.children();
1555 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1556 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1557 error << _("Session: cannot create Region from XML description.");
1558 const XMLProperty *name = (**niter).property("name");
1561 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1572 Session::load_compounds (const XMLNode& node)
1574 XMLNodeList calist = node.children();
1575 XMLNodeConstIterator caiter;
1576 XMLProperty *caprop;
1578 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1579 XMLNode* ca = *caiter;
1583 if ((caprop = ca->property (X_("original"))) == 0) {
1586 orig_id = caprop->value();
1588 if ((caprop = ca->property (X_("copy"))) == 0) {
1591 copy_id = caprop->value();
1593 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1594 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1596 if (!orig || !copy) {
1597 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1603 RegionFactory::add_compound_association (orig, copy);
1610 Session::load_nested_sources (const XMLNode& node)
1613 XMLNodeConstIterator niter;
1615 nlist = node.children();
1617 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1618 if ((*niter)->name() == "Source") {
1620 /* it may already exist, so don't recreate it unnecessarily
1623 XMLProperty* prop = (*niter)->property (X_("id"));
1625 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1629 ID source_id (prop->value());
1631 if (!source_by_id (source_id)) {
1634 SourceFactory::create (*this, **niter, true);
1636 catch (failed_constructor& err) {
1637 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1644 boost::shared_ptr<Region>
1645 Session::XMLRegionFactory (const XMLNode& node, bool full)
1647 const XMLProperty* type = node.property("type");
1651 const XMLNodeList& nlist = node.children();
1653 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1654 XMLNode *child = (*niter);
1655 if (child->name() == "NestedSource") {
1656 load_nested_sources (*child);
1660 if (!type || type->value() == "audio") {
1661 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1662 } else if (type->value() == "midi") {
1663 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1666 } catch (failed_constructor& err) {
1667 return boost::shared_ptr<Region> ();
1670 return boost::shared_ptr<Region> ();
1673 boost::shared_ptr<AudioRegion>
1674 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1676 const XMLProperty* prop;
1677 boost::shared_ptr<Source> source;
1678 boost::shared_ptr<AudioSource> as;
1680 SourceList master_sources;
1681 uint32_t nchans = 1;
1684 if (node.name() != X_("Region")) {
1685 return boost::shared_ptr<AudioRegion>();
1688 if ((prop = node.property (X_("channels"))) != 0) {
1689 nchans = atoi (prop->value().c_str());
1692 if ((prop = node.property ("name")) == 0) {
1693 cerr << "no name for this region\n";
1697 if ((prop = node.property (X_("source-0"))) == 0) {
1698 if ((prop = node.property ("source")) == 0) {
1699 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1700 return boost::shared_ptr<AudioRegion>();
1704 PBD::ID s_id (prop->value());
1706 if ((source = source_by_id (s_id)) == 0) {
1707 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1708 return boost::shared_ptr<AudioRegion>();
1711 as = boost::dynamic_pointer_cast<AudioSource>(source);
1713 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1714 return boost::shared_ptr<AudioRegion>();
1717 sources.push_back (as);
1719 /* pickup other channels */
1721 for (uint32_t n=1; n < nchans; ++n) {
1722 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1723 if ((prop = node.property (buf)) != 0) {
1725 PBD::ID id2 (prop->value());
1727 if ((source = source_by_id (id2)) == 0) {
1728 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1729 return boost::shared_ptr<AudioRegion>();
1732 as = boost::dynamic_pointer_cast<AudioSource>(source);
1734 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1735 return boost::shared_ptr<AudioRegion>();
1737 sources.push_back (as);
1741 for (uint32_t n = 0; n < nchans; ++n) {
1742 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1743 if ((prop = node.property (buf)) != 0) {
1745 PBD::ID id2 (prop->value());
1747 if ((source = source_by_id (id2)) == 0) {
1748 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1749 return boost::shared_ptr<AudioRegion>();
1752 as = boost::dynamic_pointer_cast<AudioSource>(source);
1754 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1755 return boost::shared_ptr<AudioRegion>();
1757 master_sources.push_back (as);
1762 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1764 /* a final detail: this is the one and only place that we know how long missing files are */
1766 if (region->whole_file()) {
1767 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1768 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1770 sfp->set_length (region->length());
1775 if (!master_sources.empty()) {
1776 if (master_sources.size() != nchans) {
1777 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1779 region->set_master_sources (master_sources);
1787 catch (failed_constructor& err) {
1788 return boost::shared_ptr<AudioRegion>();
1792 boost::shared_ptr<MidiRegion>
1793 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1795 const XMLProperty* prop;
1796 boost::shared_ptr<Source> source;
1797 boost::shared_ptr<MidiSource> ms;
1800 if (node.name() != X_("Region")) {
1801 return boost::shared_ptr<MidiRegion>();
1804 if ((prop = node.property ("name")) == 0) {
1805 cerr << "no name for this region\n";
1809 if ((prop = node.property (X_("source-0"))) == 0) {
1810 if ((prop = node.property ("source")) == 0) {
1811 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1812 return boost::shared_ptr<MidiRegion>();
1816 PBD::ID s_id (prop->value());
1818 if ((source = source_by_id (s_id)) == 0) {
1819 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1820 return boost::shared_ptr<MidiRegion>();
1823 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1825 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1826 return boost::shared_ptr<MidiRegion>();
1829 sources.push_back (ms);
1832 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1833 /* a final detail: this is the one and only place that we know how long missing files are */
1835 if (region->whole_file()) {
1836 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1837 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1839 sfp->set_length (region->length());
1847 catch (failed_constructor& err) {
1848 return boost::shared_ptr<MidiRegion>();
1853 Session::get_sources_as_xml ()
1856 XMLNode* node = new XMLNode (X_("Sources"));
1857 Glib::Threads::Mutex::Lock lm (source_lock);
1859 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1860 node->add_child_nocopy (i->second->get_state());
1867 Session::path_from_region_name (DataType type, string name, string identifier)
1869 char buf[PATH_MAX+1];
1871 SessionDirectory sdir(get_best_session_directory_for_new_source());
1872 std::string source_dir = ((type == DataType::AUDIO)
1873 ? sdir.sound_path() : sdir.midi_path());
1875 string ext = native_header_format_extension (config.get_native_file_header_format(), type);
1877 for (n = 0; n < 999999; ++n) {
1878 if (identifier.length()) {
1879 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1880 identifier.c_str(), n, ext.c_str());
1882 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1886 std::string source_path = Glib::build_filename (source_dir, buf);
1888 if (!Glib::file_test (source_path, Glib::FILE_TEST_EXISTS)) {
1893 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1902 Session::load_sources (const XMLNode& node)
1905 XMLNodeConstIterator niter;
1906 boost::shared_ptr<Source> source;
1908 nlist = node.children();
1912 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1915 if ((source = XMLSourceFactory (**niter)) == 0) {
1916 error << _("Session: cannot create Source from XML description.") << endmsg;
1919 } catch (MissingSource& err) {
1923 if (!no_questions_about_missing_files) {
1924 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1929 switch (user_choice) {
1931 /* user added a new search location, so try again */
1936 /* user asked to quit the entire session load
1941 no_questions_about_missing_files = true;
1945 no_questions_about_missing_files = true;
1950 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1951 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1960 boost::shared_ptr<Source>
1961 Session::XMLSourceFactory (const XMLNode& node)
1963 if (node.name() != "Source") {
1964 return boost::shared_ptr<Source>();
1968 /* note: do peak building in another thread when loading session state */
1969 return SourceFactory::create (*this, node, true);
1972 catch (failed_constructor& err) {
1973 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
1974 return boost::shared_ptr<Source>();
1979 Session::save_template (string template_name)
1983 if (_state_of_the_state & CannotSave) {
1987 std::string user_template_dir(user_template_directory());
1989 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
1990 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
1991 user_template_dir, g_strerror (errno)) << endmsg;
1995 tree.set_root (&get_template());
1997 std::string template_dir_path(user_template_dir);
1999 /* directory to put the template in */
2000 template_dir_path = Glib::build_filename (template_dir_path, template_name);
2002 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2003 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2004 template_dir_path) << endmsg;
2008 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2009 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2010 template_dir_path, g_strerror (errno)) << endmsg;
2015 std::string template_file_path(template_dir_path);
2016 template_file_path = Glib::build_filename (template_file_path, template_name + template_suffix);
2018 if (!tree.write (template_file_path)) {
2019 error << _("template not saved") << endmsg;
2023 /* copy plugin state directory */
2025 std::string template_plugin_state_path(template_dir_path);
2026 template_plugin_state_path = Glib::build_filename (template_plugin_state_path, X_("plugins"));
2028 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
2029 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
2030 template_plugin_state_path, g_strerror (errno)) << endmsg;
2034 copy_files (plugins_dir(), template_plugin_state_path);
2040 Session::refresh_disk_space ()
2042 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2044 Glib::Threads::Mutex::Lock lm (space_lock);
2046 /* get freespace on every FS that is part of the session path */
2048 _total_free_4k_blocks = 0;
2049 _total_free_4k_blocks_uncertain = false;
2051 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2053 struct statfs statfsbuf;
2054 statfs (i->path.c_str(), &statfsbuf);
2056 double const scale = statfsbuf.f_bsize / 4096.0;
2058 /* See if this filesystem is read-only */
2059 struct statvfs statvfsbuf;
2060 statvfs (i->path.c_str(), &statvfsbuf);
2062 /* f_bavail can be 0 if it is undefined for whatever
2063 filesystem we are looking at; Samba shares mounted
2064 via GVFS are an example of this.
2066 if (statfsbuf.f_bavail == 0) {
2067 /* block count unknown */
2069 i->blocks_unknown = true;
2070 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2071 /* read-only filesystem */
2073 i->blocks_unknown = false;
2075 /* read/write filesystem with known space */
2076 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2077 i->blocks_unknown = false;
2080 _total_free_4k_blocks += i->blocks;
2081 if (i->blocks_unknown) {
2082 _total_free_4k_blocks_uncertain = true;
2089 Session::get_best_session_directory_for_new_source ()
2091 vector<space_and_path>::iterator i;
2092 string result = _session_dir->root_path();
2094 /* handle common case without system calls */
2096 if (session_dirs.size() == 1) {
2100 /* OK, here's the algorithm we're following here:
2102 We want to select which directory to use for
2103 the next file source to be created. Ideally,
2104 we'd like to use a round-robin process so as to
2105 get maximum performance benefits from splitting
2106 the files across multiple disks.
2108 However, in situations without much diskspace, an
2109 RR approach may end up filling up a filesystem
2110 with new files while others still have space.
2111 Its therefore important to pay some attention to
2112 the freespace in the filesystem holding each
2113 directory as well. However, if we did that by
2114 itself, we'd keep creating new files in the file
2115 system with the most space until it was as full
2116 as all others, thus negating any performance
2117 benefits of this RAID-1 like approach.
2119 So, we use a user-configurable space threshold. If
2120 there are at least 2 filesystems with more than this
2121 much space available, we use RR selection between them.
2122 If not, then we pick the filesystem with the most space.
2124 This gets a good balance between the two
2128 refresh_disk_space ();
2130 int free_enough = 0;
2132 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2133 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2138 if (free_enough >= 2) {
2139 /* use RR selection process, ensuring that the one
2143 i = last_rr_session_dir;
2146 if (++i == session_dirs.end()) {
2147 i = session_dirs.begin();
2150 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2151 SessionDirectory sdir(i->path);
2152 if (sdir.create ()) {
2154 last_rr_session_dir = i;
2159 } while (i != last_rr_session_dir);
2163 /* pick FS with the most freespace (and that
2164 seems to actually work ...)
2167 vector<space_and_path> sorted;
2168 space_and_path_ascending_cmp cmp;
2170 sorted = session_dirs;
2171 sort (sorted.begin(), sorted.end(), cmp);
2173 for (i = sorted.begin(); i != sorted.end(); ++i) {
2174 SessionDirectory sdir(i->path);
2175 if (sdir.create ()) {
2177 last_rr_session_dir = i;
2187 Session::automation_dir () const
2189 return Glib::build_filename (_path, "automation");
2193 Session::analysis_dir () const
2195 return Glib::build_filename (_path, "analysis");
2199 Session::plugins_dir () const
2201 return Glib::build_filename (_path, "plugins");
2205 Session::externals_dir () const
2207 return Glib::build_filename (_path, "externals");
2211 Session::load_bundles (XMLNode const & node)
2213 XMLNodeList nlist = node.children();
2214 XMLNodeConstIterator niter;
2218 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2219 if ((*niter)->name() == "InputBundle") {
2220 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2221 } else if ((*niter)->name() == "OutputBundle") {
2222 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2224 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2233 Session::load_route_groups (const XMLNode& node, int version)
2235 XMLNodeList nlist = node.children();
2236 XMLNodeConstIterator niter;
2240 if (version >= 3000) {
2242 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2243 if ((*niter)->name() == "RouteGroup") {
2244 RouteGroup* rg = new RouteGroup (*this, "");
2245 add_route_group (rg);
2246 rg->set_state (**niter, version);
2250 } else if (version < 3000) {
2252 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2253 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2254 RouteGroup* rg = new RouteGroup (*this, "");
2255 add_route_group (rg);
2256 rg->set_state (**niter, version);
2265 Session::auto_save()
2267 save_state (_current_snapshot_name);
2271 state_file_filter (const string &str, void */*arg*/)
2273 return (str.length() > strlen(statefile_suffix) &&
2274 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2278 bool operator()(const string* a, const string* b) {
2284 remove_end(string* state)
2286 string statename(*state);
2288 string::size_type start,end;
2289 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2290 statename = statename.substr (start+1);
2293 if ((end = statename.rfind(".ardour")) == string::npos) {
2294 end = statename.length();
2297 return new string(statename.substr (0, end));
2301 Session::possible_states (string path)
2303 PathScanner scanner;
2304 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2306 transform(states->begin(), states->end(), states->begin(), remove_end);
2309 sort (states->begin(), states->end(), cmp);
2315 Session::possible_states () const
2317 return possible_states(_path);
2321 Session::add_route_group (RouteGroup* g)
2323 _route_groups.push_back (g);
2324 route_group_added (g); /* EMIT SIGNAL */
2326 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2327 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2328 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2334 Session::remove_route_group (RouteGroup& rg)
2336 list<RouteGroup*>::iterator i;
2338 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2339 _route_groups.erase (i);
2342 route_group_removed (); /* EMIT SIGNAL */
2346 /** Set a new order for our route groups, without adding or removing any.
2347 * @param groups Route group list in the new order.
2350 Session::reorder_route_groups (list<RouteGroup*> groups)
2352 _route_groups = groups;
2354 route_groups_reordered (); /* EMIT SIGNAL */
2360 Session::route_group_by_name (string name)
2362 list<RouteGroup *>::iterator i;
2364 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2365 if ((*i)->name() == name) {
2373 Session::all_route_group() const
2375 return *_all_route_group;
2379 Session::add_commands (vector<Command*> const & cmds)
2381 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2387 Session::begin_reversible_command (const string& name)
2389 begin_reversible_command (g_quark_from_string (name.c_str ()));
2392 /** Begin a reversible command using a GQuark to identify it.
2393 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2394 * but there must be as many begin...()s as there are commit...()s.
2397 Session::begin_reversible_command (GQuark q)
2399 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2400 to hold all the commands that are committed. This keeps the order of
2401 commands correct in the history.
2404 if (_current_trans == 0) {
2405 /* start a new transaction */
2406 assert (_current_trans_quarks.empty ());
2407 _current_trans = new UndoTransaction();
2408 _current_trans->set_name (g_quark_to_string (q));
2411 _current_trans_quarks.push_front (q);
2415 Session::commit_reversible_command (Command *cmd)
2417 assert (_current_trans);
2418 assert (!_current_trans_quarks.empty ());
2423 _current_trans->add_command (cmd);
2426 _current_trans_quarks.pop_front ();
2428 if (!_current_trans_quarks.empty ()) {
2429 /* the transaction we're committing is not the top-level one */
2433 if (_current_trans->empty()) {
2434 /* no commands were added to the transaction, so just get rid of it */
2435 delete _current_trans;
2440 gettimeofday (&now, 0);
2441 _current_trans->set_timestamp (now);
2443 _history.add (_current_trans);
2448 accept_all_audio_files (const string& path, void */*arg*/)
2450 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2454 if (!AudioFileSource::safe_audio_file_extension (path)) {
2462 accept_all_midi_files (const string& path, void */*arg*/)
2464 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2468 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2469 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2470 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2474 accept_all_state_files (const string& path, void */*arg*/)
2476 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2480 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2484 Session::find_all_sources (string path, set<string>& result)
2489 if (!tree.read (path)) {
2493 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2498 XMLNodeConstIterator niter;
2500 nlist = node->children();
2504 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2508 if ((prop = (*niter)->property (X_("type"))) == 0) {
2512 DataType type (prop->value());
2514 if ((prop = (*niter)->property (X_("name"))) == 0) {
2518 if (Glib::path_is_absolute (prop->value())) {
2519 /* external file, ignore */
2527 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2528 result.insert (found_path);
2536 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2538 PathScanner scanner;
2539 vector<string*>* state_files;
2541 string this_snapshot_path;
2547 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2548 ripped = ripped.substr (0, ripped.length() - 1);
2551 state_files = scanner (ripped, accept_all_state_files, (void *) 0, true, true);
2553 if (state_files == 0) {
2558 this_snapshot_path = _path;
2559 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2560 this_snapshot_path += statefile_suffix;
2562 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2564 if (exclude_this_snapshot && **i == this_snapshot_path) {
2568 if (find_all_sources (**i, result) < 0) {
2576 struct RegionCounter {
2577 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2578 AudioSourceList::iterator iter;
2579 boost::shared_ptr<Region> region;
2582 RegionCounter() : count (0) {}
2586 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2588 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2589 return r.get_value_or (1);
2593 Session::cleanup_regions ()
2595 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2597 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2599 uint32_t used = playlists->region_use_count (i->second);
2601 if (used == 0 && !i->second->automatic ()) {
2602 RegionFactory::map_remove (i->second);
2606 /* dump the history list */
2613 Session::cleanup_sources (CleanupReport& rep)
2615 // FIXME: needs adaptation to midi
2617 vector<boost::shared_ptr<Source> > dead_sources;
2618 PathScanner scanner;
2621 vector<space_and_path>::iterator i;
2622 vector<space_and_path>::iterator nexti;
2623 vector<string*>* candidates;
2624 vector<string*>* candidates2;
2625 vector<string> unused;
2626 set<string> all_sources;
2631 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2633 /* consider deleting all unused playlists */
2635 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2640 /* sync the "all regions" property of each playlist with its current state
2643 playlists->sync_all_regions_with_regions ();
2645 /* find all un-used sources */
2650 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2652 SourceMap::iterator tmp;
2657 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2661 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2662 dead_sources.push_back (i->second);
2663 i->second->drop_references ();
2669 /* build a list of all the possible audio directories for the session */
2671 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2676 SessionDirectory sdir ((*i).path);
2677 audio_path += sdir.sound_path();
2679 if (nexti != session_dirs.end()) {
2687 /* build a list of all the possible midi directories for the session */
2689 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2694 SessionDirectory sdir ((*i).path);
2695 midi_path += sdir.midi_path();
2697 if (nexti != session_dirs.end()) {
2704 candidates = scanner (audio_path, accept_all_audio_files, (void *) 0, true, true);
2705 candidates2 = scanner (midi_path, accept_all_midi_files, (void *) 0, true, true);
2711 for (vector<string*>::iterator i = candidates2->begin(); i != candidates2->end(); ++i) {
2712 candidates->push_back (*i);
2717 candidates = candidates2; // might still be null
2720 /* find all sources, but don't use this snapshot because the
2721 state file on disk still references sources we may have already
2725 find_all_sources_across_snapshots (all_sources, true);
2727 /* add our current source list
2730 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2731 boost::shared_ptr<FileSource> fs;
2732 SourceMap::iterator tmp = i;
2735 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2736 if (playlists->source_use_count (fs) != 0) {
2737 all_sources.insert (fs->path());
2740 /* we might not remove this source from disk, because it may be used
2741 by other snapshots, but its not being used in this version
2742 so lets get rid of it now, along with any representative regions
2746 RegionFactory::remove_regions_using_source (i->second);
2754 char tmppath1[PATH_MAX+1];
2755 char tmppath2[PATH_MAX+1];
2758 for (vector<string*>::iterator x = candidates->begin(); x != candidates->end(); ++x) {
2763 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2765 if (realpath(spath.c_str(), tmppath1) == 0) {
2766 error << string_compose (_("Cannot expand path %1 (%2)"),
2767 spath, strerror (errno)) << endmsg;
2771 if (realpath((*i).c_str(), tmppath2) == 0) {
2772 error << string_compose (_("Cannot expand path %1 (%2)"),
2773 (*i), strerror (errno)) << endmsg;
2777 if (strcmp(tmppath1, tmppath2) == 0) {
2784 unused.push_back (spath);
2793 /* now try to move all unused files into the "dead" directory(ies) */
2795 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2796 struct stat statbuf;
2800 /* don't move the file across filesystems, just
2801 stick it in the `dead_dir_name' directory
2802 on whichever filesystem it was already on.
2805 if ((*x).find ("/sounds/") != string::npos) {
2807 /* old school, go up 1 level */
2809 newpath = Glib::path_get_dirname (*x); // "sounds"
2810 newpath = Glib::path_get_dirname (newpath); // "session-name"
2814 /* new school, go up 4 levels */
2816 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2817 newpath = Glib::path_get_dirname (newpath); // "session-name"
2818 newpath = Glib::path_get_dirname (newpath); // "interchange"
2819 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2822 newpath = Glib::build_filename (newpath, dead_dir_name);
2824 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2825 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2829 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2831 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2833 /* the new path already exists, try versioning */
2835 char buf[PATH_MAX+1];
2839 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2842 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2843 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2847 if (version == 999) {
2848 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2852 newpath = newpath_v;
2857 /* it doesn't exist, or we can't read it or something */
2861 stat ((*x).c_str(), &statbuf);
2863 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2864 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2865 (*x), newpath, strerror (errno))
2870 /* see if there an easy to find peakfile for this file, and remove it.
2873 string base = basename_nosuffix (*x);
2874 base += "%A"; /* this is what we add for the channel suffix of all native files,
2875 or for the first channel of embedded files. it will miss
2876 some peakfiles for other channels
2878 string peakpath = peak_path (base);
2880 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2881 if (::unlink (peakpath.c_str()) != 0) {
2882 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2883 peakpath, _path, strerror (errno))
2885 /* try to back out */
2886 ::rename (newpath.c_str(), _path.c_str());
2891 rep.paths.push_back (*x);
2892 rep.space += statbuf.st_size;
2895 /* dump the history list */
2899 /* save state so we don't end up a session file
2900 referring to non-existent sources.
2907 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2913 Session::cleanup_trash_sources (CleanupReport& rep)
2915 // FIXME: needs adaptation for MIDI
2917 vector<space_and_path>::iterator i;
2923 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2925 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2927 clear_directory (dead_dir, &rep.space, &rep.paths);
2934 Session::set_dirty ()
2936 bool was_dirty = dirty();
2938 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2942 DirtyChanged(); /* EMIT SIGNAL */
2948 Session::set_clean ()
2950 bool was_dirty = dirty();
2952 _state_of_the_state = Clean;
2956 DirtyChanged(); /* EMIT SIGNAL */
2961 Session::set_deletion_in_progress ()
2963 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2967 Session::clear_deletion_in_progress ()
2969 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2973 Session::add_controllable (boost::shared_ptr<Controllable> c)
2975 /* this adds a controllable to the list managed by the Session.
2976 this is a subset of those managed by the Controllable class
2977 itself, and represents the only ones whose state will be saved
2978 as part of the session.
2981 Glib::Threads::Mutex::Lock lm (controllables_lock);
2982 controllables.insert (c);
2985 struct null_deleter { void operator()(void const *) const {} };
2988 Session::remove_controllable (Controllable* c)
2990 if (_state_of_the_state & Deletion) {
2994 Glib::Threads::Mutex::Lock lm (controllables_lock);
2996 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
2998 if (x != controllables.end()) {
2999 controllables.erase (x);
3003 boost::shared_ptr<Controllable>
3004 Session::controllable_by_id (const PBD::ID& id)
3006 Glib::Threads::Mutex::Lock lm (controllables_lock);
3008 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3009 if ((*i)->id() == id) {
3014 return boost::shared_ptr<Controllable>();
3017 boost::shared_ptr<Controllable>
3018 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3020 boost::shared_ptr<Controllable> c;
3021 boost::shared_ptr<Route> r;
3023 switch (desc.top_level_type()) {
3024 case ControllableDescriptor::NamedRoute:
3026 std::string str = desc.top_level_name();
3027 if (str == "master") {
3029 } else if (str == "control" || str == "listen") {
3032 r = route_by_name (desc.top_level_name());
3037 case ControllableDescriptor::RemoteControlID:
3038 r = route_by_remote_id (desc.rid());
3046 switch (desc.subtype()) {
3047 case ControllableDescriptor::Gain:
3048 c = r->gain_control ();
3051 case ControllableDescriptor::Solo:
3052 c = r->solo_control();
3055 case ControllableDescriptor::Mute:
3056 c = r->mute_control();
3059 case ControllableDescriptor::Recenable:
3061 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3064 c = t->rec_enable_control ();
3069 case ControllableDescriptor::PanDirection:
3071 c = r->pannable()->pan_azimuth_control;
3075 case ControllableDescriptor::PanWidth:
3077 c = r->pannable()->pan_width_control;
3081 case ControllableDescriptor::PanElevation:
3083 c = r->pannable()->pan_elevation_control;
3087 case ControllableDescriptor::Balance:
3088 /* XXX simple pan control */
3091 case ControllableDescriptor::PluginParameter:
3093 uint32_t plugin = desc.target (0);
3094 uint32_t parameter_index = desc.target (1);
3096 /* revert to zero based counting */
3102 if (parameter_index > 0) {
3106 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3109 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3110 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3115 case ControllableDescriptor::SendGain:
3117 uint32_t send = desc.target (0);
3119 /* revert to zero-based counting */
3125 boost::shared_ptr<Processor> p = r->nth_send (send);
3128 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3129 boost::shared_ptr<Amp> a = s->amp();
3132 c = s->amp()->gain_control();
3139 /* relax and return a null pointer */
3147 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3150 Stateful::add_instant_xml (node, _path);
3153 if (write_to_config) {
3154 Config->add_instant_xml (node);
3159 Session::instant_xml (const string& node_name)
3161 return Stateful::instant_xml (node_name, _path);
3165 Session::save_history (string snapshot_name)
3173 if (snapshot_name.empty()) {
3174 snapshot_name = _current_snapshot_name;
3177 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3178 const string backup_filename = history_filename + backup_suffix;
3179 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3180 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3182 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3183 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3184 error << _("could not backup old history file, current history not saved") << endmsg;
3189 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3193 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3195 if (!tree.write (xml_path))
3197 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3199 if (g_remove (xml_path.c_str()) != 0) {
3200 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3201 xml_path, g_strerror (errno)) << endmsg;
3203 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3204 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3205 backup_path, g_strerror (errno)) << endmsg;
3215 Session::restore_history (string snapshot_name)
3219 if (snapshot_name.empty()) {
3220 snapshot_name = _current_snapshot_name;
3223 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3224 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3226 info << "Loading history from " << xml_path << endmsg;
3228 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3229 info << string_compose (_("%1: no history file \"%2\" for this session."),
3230 _name, xml_path) << endmsg;
3234 if (!tree.read (xml_path)) {
3235 error << string_compose (_("Could not understand session history file \"%1\""),
3236 xml_path) << endmsg;
3243 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3246 UndoTransaction* ut = new UndoTransaction ();
3249 ut->set_name(t->property("name")->value());
3250 stringstream ss(t->property("tv-sec")->value());
3252 ss.str(t->property("tv-usec")->value());
3254 ut->set_timestamp(tv);
3256 for (XMLNodeConstIterator child_it = t->children().begin();
3257 child_it != t->children().end(); child_it++)
3259 XMLNode *n = *child_it;
3262 if (n->name() == "MementoCommand" ||
3263 n->name() == "MementoUndoCommand" ||
3264 n->name() == "MementoRedoCommand") {
3266 if ((c = memento_command_factory(n))) {
3270 } else if (n->name() == "NoteDiffCommand") {
3271 PBD::ID id (n->property("midi-source")->value());
3272 boost::shared_ptr<MidiSource> midi_source =
3273 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3275 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3277 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3280 } else if (n->name() == "SysExDiffCommand") {
3282 PBD::ID id (n->property("midi-source")->value());
3283 boost::shared_ptr<MidiSource> midi_source =
3284 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3286 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3288 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3291 } else if (n->name() == "PatchChangeDiffCommand") {
3293 PBD::ID id (n->property("midi-source")->value());
3294 boost::shared_ptr<MidiSource> midi_source =
3295 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3297 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3299 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3302 } else if (n->name() == "StatefulDiffCommand") {
3303 if ((c = stateful_diff_command_factory (n))) {
3304 ut->add_command (c);
3307 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3318 Session::config_changed (std::string p, bool ours)
3324 if (p == "seamless-loop") {
3326 } else if (p == "rf-speed") {
3328 } else if (p == "auto-loop") {
3330 } else if (p == "auto-input") {
3332 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3333 /* auto-input only makes a difference if we're rolling */
3334 set_track_monitor_input_status (!config.get_auto_input());
3337 } else if (p == "punch-in") {
3341 if ((location = _locations->auto_punch_location()) != 0) {
3343 if (config.get_punch_in ()) {
3344 replace_event (SessionEvent::PunchIn, location->start());
3346 remove_event (location->start(), SessionEvent::PunchIn);
3350 } else if (p == "punch-out") {
3354 if ((location = _locations->auto_punch_location()) != 0) {
3356 if (config.get_punch_out()) {
3357 replace_event (SessionEvent::PunchOut, location->end());
3359 clear_events (SessionEvent::PunchOut);
3363 } else if (p == "edit-mode") {
3365 Glib::Threads::Mutex::Lock lm (playlists->lock);
3367 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3368 (*i)->set_edit_mode (Config->get_edit_mode ());
3371 } else if (p == "use-video-sync") {
3373 waiting_for_sync_offset = config.get_use_video_sync();
3375 } else if (p == "mmc-control") {
3377 //poke_midi_thread ();
3379 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3381 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3383 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3385 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3387 } else if (p == "midi-control") {
3389 //poke_midi_thread ();
3391 } else if (p == "raid-path") {
3393 setup_raid_path (config.get_raid_path());
3395 } else if (p == "timecode-format") {
3399 } else if (p == "video-pullup") {
3403 } else if (p == "seamless-loop") {
3405 if (play_loop && transport_rolling()) {
3406 // to reset diskstreams etc
3407 request_play_loop (true);
3410 } else if (p == "rf-speed") {
3412 cumulative_rf_motion = 0;
3415 } else if (p == "click-sound") {
3417 setup_click_sounds (1);
3419 } else if (p == "click-emphasis-sound") {
3421 setup_click_sounds (-1);
3423 } else if (p == "clicking") {
3425 if (Config->get_clicking()) {
3426 if (_click_io && click_data) { // don't require emphasis data
3433 } else if (p == "click-gain") {
3436 _click_gain->set_gain (Config->get_click_gain(), this);
3439 } else if (p == "send-mtc") {
3441 if (Config->get_send_mtc ()) {
3442 /* mark us ready to send */
3443 next_quarter_frame_to_send = 0;
3446 } else if (p == "send-mmc") {
3448 _mmc->enable_send (Config->get_send_mmc ());
3450 } else if (p == "midi-feedback") {
3452 session_midi_feedback = Config->get_midi_feedback();
3454 } else if (p == "jack-time-master") {
3456 engine().reset_timebase ();
3458 } else if (p == "native-file-header-format") {
3460 if (!first_file_header_format_reset) {
3461 reset_native_file_format ();
3464 first_file_header_format_reset = false;
3466 } else if (p == "native-file-data-format") {
3468 if (!first_file_data_format_reset) {
3469 reset_native_file_format ();
3472 first_file_data_format_reset = false;
3474 } else if (p == "external-sync") {
3475 if (!config.get_external_sync()) {
3476 drop_sync_source ();
3478 switch_to_sync_source (Config->get_sync_source());
3480 } else if (p == "denormal-model") {
3482 } else if (p == "history-depth") {
3483 set_history_depth (Config->get_history_depth());
3484 } else if (p == "remote-model") {
3485 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3488 } else if (p == "sync-all-route-ordering") {
3490 /* sync to editor order unless mixer is used for remote IDs
3493 switch (Config->get_remote_model()) {
3495 sync_order_keys (EditorSort);
3498 sync_order_keys (EditorSort);
3501 sync_order_keys (MixerSort);
3504 } else if (p == "initial-program-change") {
3506 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3509 buf[0] = MIDI::program; // channel zero by default
3510 buf[1] = (Config->get_initial_program_change() & 0x7f);
3512 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3514 } else if (p == "solo-mute-override") {
3515 // catch_up_on_solo_mute_override ();
3516 } else if (p == "listen-position" || p == "pfl-position") {
3517 listen_position_changed ();
3518 } else if (p == "solo-control-is-listen-control") {
3519 solo_control_mode_changed ();
3520 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3521 last_timecode_valid = false;
3522 } else if (p == "playback-buffer-seconds") {
3523 AudioSource::allocate_working_buffers (frame_rate());
3524 } else if (p == "automation-thinning-factor") {
3525 Evoral::ControlList::set_thinning_factor (Config->get_automation_thinning_factor());
3526 } else if (p == "ltc-source-port") {
3527 reconnect_ltc_input ();
3528 } else if (p == "ltc-sink-port") {
3529 reconnect_ltc_output ();
3530 } else if (p == "timecode-generator-offset") {
3531 ltc_tx_parse_offset();
3538 Session::set_history_depth (uint32_t d)
3540 _history.set_depth (d);
3544 Session::load_diskstreams_2X (XMLNode const & node, int)
3547 XMLNodeConstIterator citer;
3549 clist = node.children();
3551 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3554 /* diskstreams added automatically by DiskstreamCreated handler */
3555 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3556 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3557 _diskstreams_2X.push_back (dsp);
3559 error << _("Session: unknown diskstream type in XML") << endmsg;
3563 catch (failed_constructor& err) {
3564 error << _("Session: could not load diskstream via XML state") << endmsg;
3572 /** Connect things to the MMC object */
3574 Session::setup_midi_machine_control ()
3576 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3577 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3578 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3579 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3580 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3581 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3582 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3583 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3584 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3585 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3586 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3587 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3588 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3590 /* also handle MIDI SPP because its so common */
3592 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3593 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3594 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3597 boost::shared_ptr<Controllable>
3598 Session::solo_cut_control() const
3600 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3601 controls in Ardour that currently get presented to the user in the GUI that require
3602 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3604 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3605 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3609 return _solo_cut_control;
3613 Session::rename (const std::string& new_name)
3615 string legal_name = legalize_for_path (new_name);
3621 string const old_sources_root = _session_dir->sources_root();
3623 #define RENAME ::rename
3628 * interchange subdirectory
3632 * Backup files are left unchanged and not renamed.
3635 /* pass one: not 100% safe check that the new directory names don't
3639 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3644 /* this is a stupid hack because Glib::path_get_dirname() is
3645 * lexical-only, and so passing it /a/b/c/ gives a different
3646 * result than passing it /a/b/c ...
3649 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3650 oldstr = oldstr.substr (0, oldstr.length() - 1);
3653 string base = Glib::path_get_dirname (oldstr);
3654 string p = Glib::path_get_basename (oldstr);
3656 newstr = Glib::build_filename (base, legal_name);
3658 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3665 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3670 /* this is a stupid hack because Glib::path_get_dirname() is
3671 * lexical-only, and so passing it /a/b/c/ gives a different
3672 * result than passing it /a/b/c ...
3675 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3676 oldstr = oldstr.substr (0, oldstr.length() - 1);
3679 string base = Glib::path_get_dirname (oldstr);
3680 string p = Glib::path_get_basename (oldstr);
3682 newstr = Glib::build_filename (base, legal_name);
3684 cerr << "Rename " << oldstr << " => " << newstr << endl;
3686 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3691 (*_session_dir) = newstr;
3696 /* directory below interchange */
3698 v.push_back (newstr);
3699 v.push_back (interchange_dir_name);
3702 oldstr = Glib::build_filename (v);
3705 v.push_back (newstr);
3706 v.push_back (interchange_dir_name);
3707 v.push_back (legal_name);
3709 newstr = Glib::build_filename (v);
3711 cerr << "Rename " << oldstr << " => " << newstr << endl;
3713 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3720 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3721 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3723 cerr << "Rename " << oldstr << " => " << newstr << endl;
3725 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3732 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3734 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3735 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3737 cerr << "Rename " << oldstr << " => " << newstr << endl;
3739 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3744 /* update file source paths */
3746 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3747 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3749 string p = fs->path ();
3750 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3755 /* remove old name from recent sessions */
3757 remove_recent_sessions (_path);
3760 _current_snapshot_name = new_name;
3765 /* save state again to get everything just right */
3767 save_state (_current_snapshot_name);
3770 /* add to recent sessions */
3772 store_recent_sessions (new_name, _path);