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 */
44 #include <sys/param.h>
45 #include <sys/mount.h>
48 #ifdef HAVE_SYS_STATVFS_H
49 #include <sys/statvfs.h>
53 #include <glib/gstdio.h>
56 #include <glibmm/threads.h>
58 #include <boost/algorithm/string.hpp>
60 #include "midi++/mmc.h"
61 #include "midi++/port.h"
63 #include "evoral/SMF.hpp"
65 #include "pbd/boost_debug.h"
66 #include "pbd/basename.h"
67 #include "pbd/controllable_descriptor.h"
68 #include "pbd/enumwriter.h"
69 #include "pbd/error.h"
70 #include "pbd/file_utils.h"
71 #include "pbd/pathexpand.h"
72 #include "pbd/pthread_utils.h"
73 #include "pbd/stacktrace.h"
74 #include "pbd/convert.h"
75 #include "pbd/localtime_r.h"
77 #include "ardour/amp.h"
78 #include "ardour/async_midi_port.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/graph.h"
90 #include "ardour/location.h"
91 #include "ardour/midi_model.h"
92 #include "ardour/midi_patch_manager.h"
93 #include "ardour/midi_region.h"
94 #include "ardour/midi_scene_changer.h"
95 #include "ardour/midi_source.h"
96 #include "ardour/midi_track.h"
97 #include "ardour/pannable.h"
98 #include "ardour/playlist_factory.h"
99 #include "ardour/port.h"
100 #include "ardour/processor.h"
101 #include "ardour/proxy_controllable.h"
102 #include "ardour/recent_sessions.h"
103 #include "ardour/region_factory.h"
104 #include "ardour/route_group.h"
105 #include "ardour/send.h"
106 #include "ardour/session.h"
107 #include "ardour/session_directory.h"
108 #include "ardour/session_metadata.h"
109 #include "ardour/session_playlists.h"
110 #include "ardour/session_state_utils.h"
111 #include "ardour/silentfilesource.h"
112 #include "ardour/sndfilesource.h"
113 #include "ardour/source_factory.h"
114 #include "ardour/speakers.h"
115 #include "ardour/template_utils.h"
116 #include "ardour/tempo.h"
117 #include "ardour/ticker.h"
118 #include "ardour/user_bundle.h"
120 #include "control_protocol/control_protocol.h"
126 using namespace ARDOUR;
130 Session::pre_engine_init (string fullpath)
132 if (fullpath.empty()) {
134 throw failed_constructor();
137 /* discover canonical fullpath */
139 _path = canonical_path(fullpath);
141 /* we require _path to end with a dir separator */
143 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
144 _path += G_DIR_SEPARATOR;
149 _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
151 /* finish initialization that can't be done in a normal C++ constructor
155 timerclear (&last_mmc_step);
156 g_atomic_int_set (&processing_prohibited, 0);
157 g_atomic_int_set (&_record_status, Disabled);
158 g_atomic_int_set (&_playback_load, 100);
159 g_atomic_int_set (&_capture_load, 100);
161 _all_route_group->set_active (true, this);
162 interpolation.add_channel_to (0, 0);
164 if (config.get_use_video_sync()) {
165 waiting_for_sync_offset = true;
167 waiting_for_sync_offset = false;
170 last_rr_session_dir = session_dirs.begin();
172 set_history_depth (Config->get_history_depth());
174 /* default: assume simple stereo speaker configuration */
176 _speakers->setup_default_speakers (2);
178 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
179 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
180 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
181 add_controllable (_solo_cut_control);
183 /* These are all static "per-class" signals */
185 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
186 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
187 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
188 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
189 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
191 /* stop IO objects from doing stuff until we're ready for them */
193 Delivery::disable_panners ();
194 IO::disable_connecting ();
196 AudioFileSource::set_peak_dir (_session_dir->peak_path());
200 Session::post_engine_init ()
202 BootMessage (_("Set block size and sample rate"));
204 set_block_size (_engine.samples_per_cycle());
205 set_frame_rate (_engine.sample_rate());
207 BootMessage (_("Using configuration"));
209 _midi_ports = new MidiPortManager;
211 MIDISceneChanger* msc;
213 _scene_changer = msc = new MIDISceneChanger (*this);
214 msc->set_input_port (scene_input_port());
215 msc->set_output_port (scene_out());
217 boost::function<framecnt_t(void)> timer_func (boost::bind (&Session::audible_frame, this));
218 boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_in())->set_timer (timer_func);
220 setup_midi_machine_control ();
222 if (_butler->start_thread()) {
226 if (start_midi_thread ()) {
230 setup_click_sounds (0);
231 setup_midi_control ();
233 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
234 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
237 /* tempo map requires sample rate knowledge */
239 _tempo_map = new TempoMap (_current_frame_rate);
240 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
242 /* MidiClock requires a tempo map */
244 midi_clock = new MidiClockTicker ();
245 midi_clock->set_session (this);
247 /* crossfades require sample rate knowledge */
249 SndFileSource::setup_standard_crossfades (*this, frame_rate());
250 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
252 AudioDiskstream::allocate_working_buffers();
253 refresh_disk_space ();
255 /* we're finally ready to call set_state() ... all objects have
256 * been created, the engine is running.
260 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
264 // set_state() will call setup_raid_path(), but if it's a new session we need
265 // to call setup_raid_path() here.
266 setup_raid_path (_path);
271 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
272 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
274 Config->map_parameters (ff);
275 config.map_parameters (ft);
277 /* Reset all panners */
279 Delivery::reset_panners ();
281 /* this will cause the CPM to instantiate any protocols that are in use
282 * (or mandatory), which will pass it this Session, and then call
283 * set_state() on each instantiated protocol to match stored state.
286 ControlProtocolManager::instance().set_session (this);
288 /* This must be done after the ControlProtocolManager set_session above,
289 as it will set states for ports which the ControlProtocolManager creates.
292 // XXX set state of MIDI::Port's
293 // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
295 /* And this must be done after the MIDI::Manager::set_port_states as
296 * it will try to make connections whose details are loaded by set_port_states.
301 /* Let control protocols know that we are now all connected, so they
302 * could start talking to surfaces if they want to.
305 ControlProtocolManager::instance().midi_connectivity_established ();
307 if (_is_new && !no_auto_connect()) {
308 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
309 auto_connect_master_bus ();
312 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
314 /* update latencies */
316 initialize_latencies ();
318 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
319 _locations->added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
321 } catch (AudioEngine::PortRegistrationFailure& err) {
322 /* handle this one in a different way than all others, so that its clear what happened */
323 error << err.what() << endmsg;
329 BootMessage (_("Reset Remote Controls"));
331 // send_full_time_code (0);
332 _engine.transport_locate (0);
334 _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
335 _mmc->send (MIDI::MachineControlCommand (Timecode::Time ()));
337 MIDI::Name::MidiPatchManager::instance().set_session (this);
340 /* initial program change will be delivered later; see ::config_changed() */
342 _state_of_the_state = Clean;
344 Port::set_connecting_blocked (false);
346 DirtyChanged (); /* EMIT SIGNAL */
350 } else if (state_was_pending) {
352 remove_pending_capture_state ();
353 state_was_pending = false;
360 Session::raid_path () const
362 Searchpath raid_search_path;
364 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
365 raid_search_path += (*i).path;
368 return raid_search_path.to_string ();
372 Session::setup_raid_path (string path)
381 session_dirs.clear ();
383 Searchpath search_path(path);
384 Searchpath sound_search_path;
385 Searchpath midi_search_path;
387 for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
389 sp.blocks = 0; // not needed
390 session_dirs.push_back (sp);
392 SessionDirectory sdir(sp.path);
394 sound_search_path += sdir.sound_path ();
395 midi_search_path += sdir.midi_path ();
398 // reset the round-robin soundfile path thingie
399 last_rr_session_dir = session_dirs.begin();
403 Session::path_is_within_session (const std::string& path)
405 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
406 if (PBD::path_is_within (i->path, path)) {
414 Session::ensure_subdirs ()
418 dir = session_directory().peak_path();
420 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
421 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
425 dir = session_directory().sound_path();
427 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
428 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
432 dir = session_directory().midi_path();
434 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
435 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
439 dir = session_directory().dead_path();
441 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
442 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
446 dir = session_directory().export_path();
448 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
449 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
453 dir = analysis_dir ();
455 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
456 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
460 dir = plugins_dir ();
462 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
463 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
467 dir = externals_dir ();
469 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
470 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
477 /** @param session_template directory containing session template, or empty.
478 * Caller must not hold process lock.
481 Session::create (const string& session_template, BusProfile* bus_profile)
483 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
484 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
488 if (ensure_subdirs ()) {
492 _writable = exists_and_writable (_path);
494 if (!session_template.empty()) {
495 std::string in_path = session_template_dir_to_file (session_template);
497 ifstream in(in_path.c_str());
500 /* no need to call legalize_for_path() since the string
501 * in session_template is already a legal path name
503 string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
505 ofstream out(out_path.c_str());
511 /* Copy plugin state files from template to new session */
512 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
513 copy_files (template_plugins, plugins_dir ());
518 error << string_compose (_("Could not open %1 for writing session template"), out_path)
524 error << string_compose (_("Could not open session template %1 for reading"), in_path)
531 /* set initial start + end point */
533 _state_of_the_state = Clean;
535 /* set up Master Out and Control Out if necessary */
540 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
542 if (bus_profile->master_out_channels) {
543 boost::shared_ptr<Route> r (new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO));
547 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
548 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
551 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
552 r->input()->ensure_io (count, false, this);
553 r->output()->ensure_io (count, false, this);
559 /* prohibit auto-connect to master, because there isn't one */
560 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
564 add_routes (rl, false, false, false);
567 /* this allows the user to override settings with an environment variable.
570 if (no_auto_connect()) {
571 bus_profile->input_ac = AutoConnectOption (0);
572 bus_profile->output_ac = AutoConnectOption (0);
575 Config->set_input_auto_connect (bus_profile->input_ac);
576 Config->set_output_auto_connect (bus_profile->output_ac);
579 if (Config->get_use_monitor_bus() && bus_profile) {
580 add_monitor_section ();
587 Session::maybe_write_autosave()
589 if (dirty() && record_status() != Recording) {
590 save_state("", true);
595 Session::remove_pending_capture_state ()
597 std::string pending_state_file_path(_session_dir->root_path());
599 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
601 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
603 if (g_remove (pending_state_file_path.c_str()) != 0) {
604 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
605 pending_state_file_path, g_strerror (errno)) << endmsg;
609 /** Rename a state file.
610 * @param old_name Old snapshot name.
611 * @param new_name New snapshot name.
614 Session::rename_state (string old_name, string new_name)
616 if (old_name == _current_snapshot_name || old_name == _name) {
617 /* refuse to rename the current snapshot or the "main" one */
621 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
622 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
624 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
625 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
627 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
628 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
629 old_name, new_name, g_strerror(errno)) << endmsg;
633 /** Remove a state file.
634 * @param snapshot_name Snapshot name.
637 Session::remove_state (string snapshot_name)
639 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
640 // refuse to remove the current snapshot or the "main" one
644 std::string xml_path(_session_dir->root_path());
646 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
648 if (!create_backup_file (xml_path)) {
649 // don't remove it if a backup can't be made
650 // create_backup_file will log the error.
655 if (g_remove (xml_path.c_str()) != 0) {
656 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
657 xml_path, g_strerror (errno)) << endmsg;
661 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
663 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
666 std::string xml_path(_session_dir->root_path());
668 if (!_writable || (_state_of_the_state & CannotSave)) {
672 if (g_atomic_int_get(&_suspend_save)) {
676 _save_queued = false;
678 if (!_engine.connected ()) {
679 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
685 /* tell sources we're saving first, in case they write out to a new file
686 * which should be saved with the state rather than the old one */
687 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
689 i->second->session_saved();
690 } catch (Evoral::SMF::FileError& e) {
691 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
695 SaveSession (); /* EMIT SIGNAL */
697 tree.set_root (&get_state());
699 if (snapshot_name.empty()) {
700 snapshot_name = _current_snapshot_name;
701 } else if (switch_to_snapshot) {
702 _current_snapshot_name = snapshot_name;
707 /* proper save: use statefile_suffix (.ardour in English) */
709 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
711 /* make a backup copy of the old file */
713 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
714 // create_backup_file will log the error
720 /* pending save: use pending_suffix (.pending in English) */
721 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
724 std::string tmp_path(_session_dir->root_path());
725 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
727 // cerr << "actually writing state to " << xml_path << endl;
729 if (!tree.write (tmp_path)) {
730 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
731 if (g_remove (tmp_path.c_str()) != 0) {
732 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
733 tmp_path, g_strerror (errno)) << endmsg;
739 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
740 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
741 tmp_path, xml_path, g_strerror(errno)) << endmsg;
742 if (g_remove (tmp_path.c_str()) != 0) {
743 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
744 tmp_path, g_strerror (errno)) << endmsg;
752 save_history (snapshot_name);
754 bool was_dirty = dirty();
756 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
759 DirtyChanged (); /* EMIT SIGNAL */
762 StateSaved (snapshot_name); /* EMIT SIGNAL */
769 Session::restore_state (string snapshot_name)
771 if (load_state (snapshot_name) == 0) {
772 set_state (*state_tree->root(), Stateful::loading_state_version);
779 Session::load_state (string snapshot_name)
784 state_was_pending = false;
786 /* check for leftover pending state from a crashed capture attempt */
788 std::string xmlpath(_session_dir->root_path());
789 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
791 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
793 /* there is pending state from a crashed capture attempt */
795 boost::optional<int> r = AskAboutPendingState();
796 if (r.get_value_or (1)) {
797 state_was_pending = true;
801 if (!state_was_pending) {
802 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
805 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
806 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
807 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
808 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
813 state_tree = new XMLTree;
817 _writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
819 if (!state_tree->read (xmlpath)) {
820 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
826 XMLNode& root (*state_tree->root());
828 if (root.name() != X_("Session")) {
829 error << string_compose (_("Session file %1 is not a session"), xmlpath) << 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;
841 if (prop->value().find ('.') != string::npos) {
842 /* old school version format */
843 if (prop->value()[0] == '2') {
844 Stateful::loading_state_version = 2000;
846 Stateful::loading_state_version = 3000;
849 Stateful::loading_state_version = atoi (prop->value());
853 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
855 std::string backup_path(_session_dir->root_path());
856 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
857 backup_path = Glib::build_filename (backup_path, backup_filename);
859 // only create a backup for a given statefile version once
861 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
863 VersionMismatch (xmlpath, backup_path);
865 if (!copy_file (xmlpath, backup_path)) {;
875 Session::load_options (const XMLNode& node)
877 LocaleGuard lg (X_("POSIX"));
878 config.set_variables (node);
883 Session::save_default_options ()
885 return config.save_state();
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");
914 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
915 node->add_property("version", buf);
917 /* store configuration settings */
921 node->add_property ("name", _name);
922 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
923 node->add_property ("sample-rate", buf);
925 if (session_dirs.size() > 1) {
929 vector<space_and_path>::iterator i = session_dirs.begin();
930 vector<space_and_path>::iterator next;
932 ++i; /* skip the first one */
936 while (i != session_dirs.end()) {
940 if (next != session_dirs.end()) {
941 p += G_SEARCHPATH_SEPARATOR;
950 child = node->add_child ("Path");
951 child->add_content (p);
955 /* save the ID counter */
957 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
958 node->add_property ("id-counter", buf);
960 /* save the event ID counter */
962 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
963 node->add_property ("event-counter", buf);
965 /* various options */
967 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
968 if (!midi_port_nodes.empty()) {
969 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
970 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
971 midi_port_stuff->add_child_nocopy (**n);
973 node->add_child_nocopy (*midi_port_stuff);
976 node->add_child_nocopy (config.get_variables ());
978 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
980 child = node->add_child ("Sources");
983 Glib::Threads::Mutex::Lock sl (source_lock);
985 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
987 /* Don't save information about non-file Sources, or
988 * about non-destructive file sources that are empty
989 * and unused by any regions.
992 boost::shared_ptr<FileSource> fs;
994 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
996 if (!fs->destructive()) {
997 if (fs->empty() && !fs->used()) {
1002 child->add_child_nocopy (siter->second->get_state());
1007 child = node->add_child ("Regions");
1010 Glib::Threads::Mutex::Lock rl (region_lock);
1011 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1012 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1013 boost::shared_ptr<Region> r = i->second;
1014 /* only store regions not attached to playlists */
1015 if (r->playlist() == 0) {
1016 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1017 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1019 child->add_child_nocopy (r->get_state ());
1024 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1026 if (!cassocs.empty()) {
1027 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1029 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1031 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1032 i->first->id().print (buf, sizeof (buf));
1033 can->add_property (X_("copy"), buf);
1034 i->second->id().print (buf, sizeof (buf));
1035 can->add_property (X_("original"), buf);
1036 ca->add_child_nocopy (*can);
1042 node->add_child_nocopy (_locations->get_state());
1044 // for a template, just create a new Locations, populate it
1045 // with the default start and end, and get the state for that.
1046 Locations loc (*this);
1047 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1048 range->set (max_framepos, 0);
1050 node->add_child_nocopy (loc.get_state());
1053 child = node->add_child ("Bundles");
1055 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1056 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1057 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1059 child->add_child_nocopy (b->get_state());
1064 child = node->add_child ("Routes");
1066 boost::shared_ptr<RouteList> r = routes.reader ();
1068 RoutePublicOrderSorter cmp;
1069 RouteList public_order (*r);
1070 public_order.sort (cmp);
1072 /* the sort should have put control outs first */
1075 assert (_monitor_out == public_order.front());
1078 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1079 if (!(*i)->is_auditioner()) {
1081 child->add_child_nocopy ((*i)->get_state());
1083 child->add_child_nocopy ((*i)->get_template());
1089 playlists->add_state (node, full_state);
1091 child = node->add_child ("RouteGroups");
1092 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1093 child->add_child_nocopy ((*i)->get_state());
1097 XMLNode* gain_child = node->add_child ("Click");
1098 gain_child->add_child_nocopy (_click_io->state (full_state));
1099 gain_child->add_child_nocopy (_click_gain->state (full_state));
1103 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1104 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1108 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1109 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1112 node->add_child_nocopy (_speakers->get_state());
1113 node->add_child_nocopy (_tempo_map->get_state());
1114 node->add_child_nocopy (get_control_protocol_state());
1117 node->add_child_copy (*_extra_xml);
1124 Session::get_control_protocol_state ()
1126 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1127 return cpm.get_state();
1131 Session::set_state (const XMLNode& node, int version)
1135 const XMLProperty* prop;
1138 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1140 if (node.name() != X_("Session")) {
1141 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1145 if ((prop = node.property ("name")) != 0) {
1146 _name = prop->value ();
1149 if ((prop = node.property (X_("sample-rate"))) != 0) {
1151 _nominal_frame_rate = atoi (prop->value());
1153 if (_nominal_frame_rate != _current_frame_rate) {
1154 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1155 if (r.get_value_or (0)) {
1161 setup_raid_path(_session_dir->root_path());
1163 if ((prop = node.property (X_("id-counter"))) != 0) {
1165 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1166 ID::init_counter (x);
1168 /* old sessions used a timebased counter, so fake
1169 the startup ID counter based on a standard
1174 ID::init_counter (now);
1177 if ((prop = node.property (X_("event-counter"))) != 0) {
1178 Evoral::init_event_id_counter (atoi (prop->value()));
1182 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1183 _midi_ports->set_midi_port_states (child->children());
1186 IO::disable_connecting ();
1188 Stateful::save_extra_xml (node);
1190 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1191 load_options (*child);
1192 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1193 load_options (*child);
1195 error << _("Session: XML state has no options section") << endmsg;
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 ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1206 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1207 _speakers->set_state (*child, version);
1210 if ((child = find_named_node (node, "Sources")) == 0) {
1211 error << _("Session: XML state has no sources section") << endmsg;
1213 } else if (load_sources (*child)) {
1217 if ((child = find_named_node (node, "TempoMap")) == 0) {
1218 error << _("Session: XML state has no Tempo Map section") << endmsg;
1220 } else if (_tempo_map->set_state (*child, version)) {
1224 if ((child = find_named_node (node, "Locations")) == 0) {
1225 error << _("Session: XML state has no locations section") << endmsg;
1227 } else if (_locations->set_state (*child, version)) {
1233 if ((location = _locations->auto_loop_location()) != 0) {
1234 set_auto_loop_location (location);
1237 if ((location = _locations->auto_punch_location()) != 0) {
1238 set_auto_punch_location (location);
1241 if ((location = _locations->session_range_location()) != 0) {
1242 delete _session_range_location;
1243 _session_range_location = location;
1246 if (_session_range_location) {
1247 AudioFileSource::set_header_position_offset (_session_range_location->start());
1250 if ((child = find_named_node (node, "Regions")) == 0) {
1251 error << _("Session: XML state has no Regions section") << endmsg;
1253 } else if (load_regions (*child)) {
1257 if ((child = find_named_node (node, "Playlists")) == 0) {
1258 error << _("Session: XML state has no playlists section") << endmsg;
1260 } else if (playlists->load (*this, *child)) {
1264 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1266 } else if (playlists->load_unused (*this, *child)) {
1270 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1271 if (load_compounds (*child)) {
1276 if (version >= 3000) {
1277 if ((child = find_named_node (node, "Bundles")) == 0) {
1278 warning << _("Session: XML state has no bundles section") << endmsg;
1281 /* We can't load Bundles yet as they need to be able
1282 to convert from port names to Port objects, which can't happen until
1284 _bundle_xml_node = new XMLNode (*child);
1288 if (version < 3000) {
1289 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1290 error << _("Session: XML state has no diskstreams section") << endmsg;
1292 } else if (load_diskstreams_2X (*child, version)) {
1297 if ((child = find_named_node (node, "Routes")) == 0) {
1298 error << _("Session: XML state has no routes section") << endmsg;
1300 } else if (load_routes (*child, version)) {
1304 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1305 _diskstreams_2X.clear ();
1307 if (version >= 3000) {
1309 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1310 error << _("Session: XML state has no route groups section") << endmsg;
1312 } else if (load_route_groups (*child, version)) {
1316 } else if (version < 3000) {
1318 if ((child = find_named_node (node, "EditGroups")) == 0) {
1319 error << _("Session: XML state has no edit groups section") << endmsg;
1321 } else if (load_route_groups (*child, version)) {
1325 if ((child = find_named_node (node, "MixGroups")) == 0) {
1326 error << _("Session: XML state has no mix groups section") << endmsg;
1328 } else if (load_route_groups (*child, version)) {
1333 if ((child = find_named_node (node, "Click")) == 0) {
1334 warning << _("Session: XML state has no click section") << endmsg;
1335 } else if (_click_io) {
1336 setup_click_state (&node);
1339 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1340 ControlProtocolManager::instance().set_state (*child, version);
1343 update_have_rec_enabled_track ();
1345 /* here beginneth the second phase ... */
1347 StateReady (); /* EMIT SIGNAL */
1356 Session::load_routes (const XMLNode& node, int version)
1359 XMLNodeConstIterator niter;
1360 RouteList new_routes;
1362 nlist = node.children();
1366 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1368 boost::shared_ptr<Route> route;
1369 if (version < 3000) {
1370 route = XMLRouteFactory_2X (**niter, version);
1372 route = XMLRouteFactory (**niter, version);
1376 error << _("Session: cannot create Route from XML description.") << endmsg;
1380 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1382 new_routes.push_back (route);
1385 add_routes (new_routes, false, false, false);
1390 boost::shared_ptr<Route>
1391 Session::XMLRouteFactory (const XMLNode& node, int version)
1393 boost::shared_ptr<Route> ret;
1395 if (node.name() != "Route") {
1399 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1401 DataType type = DataType::AUDIO;
1402 const XMLProperty* prop = node.property("default-type");
1405 type = DataType (prop->value());
1408 assert (type != DataType::NIL);
1412 boost::shared_ptr<Track> track;
1414 if (type == DataType::AUDIO) {
1415 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1417 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1420 if (track->init()) {
1424 if (track->set_state (node, version)) {
1428 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1429 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1434 enum Route::Flag flags = Route::Flag(0);
1435 const XMLProperty* prop = node.property("flags");
1437 flags = Route::Flag (string_2_enum (prop->value(), flags));
1440 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1442 if (r->init () == 0 && r->set_state (node, version) == 0) {
1443 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1444 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1453 boost::shared_ptr<Route>
1454 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1456 boost::shared_ptr<Route> ret;
1458 if (node.name() != "Route") {
1462 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1464 ds_prop = node.property (X_("diskstream"));
1467 DataType type = DataType::AUDIO;
1468 const XMLProperty* prop = node.property("default-type");
1471 type = DataType (prop->value());
1474 assert (type != DataType::NIL);
1478 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1479 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1483 if (i == _diskstreams_2X.end()) {
1484 error << _("Could not find diskstream for route") << endmsg;
1485 return boost::shared_ptr<Route> ();
1488 boost::shared_ptr<Track> track;
1490 if (type == DataType::AUDIO) {
1491 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1493 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1496 if (track->init()) {
1500 if (track->set_state (node, version)) {
1504 track->set_diskstream (*i);
1506 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1507 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1512 enum Route::Flag flags = Route::Flag(0);
1513 const XMLProperty* prop = node.property("flags");
1515 flags = Route::Flag (string_2_enum (prop->value(), flags));
1518 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1520 if (r->init () == 0 && r->set_state (node, version) == 0) {
1521 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1522 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1532 Session::load_regions (const XMLNode& node)
1535 XMLNodeConstIterator niter;
1536 boost::shared_ptr<Region> region;
1538 nlist = node.children();
1542 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1543 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1544 error << _("Session: cannot create Region from XML description.");
1545 const XMLProperty *name = (**niter).property("name");
1548 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1559 Session::load_compounds (const XMLNode& node)
1561 XMLNodeList calist = node.children();
1562 XMLNodeConstIterator caiter;
1563 XMLProperty *caprop;
1565 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1566 XMLNode* ca = *caiter;
1570 if ((caprop = ca->property (X_("original"))) == 0) {
1573 orig_id = caprop->value();
1575 if ((caprop = ca->property (X_("copy"))) == 0) {
1578 copy_id = caprop->value();
1580 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1581 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1583 if (!orig || !copy) {
1584 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1590 RegionFactory::add_compound_association (orig, copy);
1597 Session::load_nested_sources (const XMLNode& node)
1600 XMLNodeConstIterator niter;
1602 nlist = node.children();
1604 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1605 if ((*niter)->name() == "Source") {
1607 /* it may already exist, so don't recreate it unnecessarily
1610 XMLProperty* prop = (*niter)->property (X_("id"));
1612 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1616 ID source_id (prop->value());
1618 if (!source_by_id (source_id)) {
1621 SourceFactory::create (*this, **niter, true);
1623 catch (failed_constructor& err) {
1624 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1631 boost::shared_ptr<Region>
1632 Session::XMLRegionFactory (const XMLNode& node, bool full)
1634 const XMLProperty* type = node.property("type");
1638 const XMLNodeList& nlist = node.children();
1640 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1641 XMLNode *child = (*niter);
1642 if (child->name() == "NestedSource") {
1643 load_nested_sources (*child);
1647 if (!type || type->value() == "audio") {
1648 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1649 } else if (type->value() == "midi") {
1650 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1653 } catch (failed_constructor& err) {
1654 return boost::shared_ptr<Region> ();
1657 return boost::shared_ptr<Region> ();
1660 boost::shared_ptr<AudioRegion>
1661 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1663 const XMLProperty* prop;
1664 boost::shared_ptr<Source> source;
1665 boost::shared_ptr<AudioSource> as;
1667 SourceList master_sources;
1668 uint32_t nchans = 1;
1671 if (node.name() != X_("Region")) {
1672 return boost::shared_ptr<AudioRegion>();
1675 if ((prop = node.property (X_("channels"))) != 0) {
1676 nchans = atoi (prop->value().c_str());
1679 if ((prop = node.property ("name")) == 0) {
1680 cerr << "no name for this region\n";
1684 if ((prop = node.property (X_("source-0"))) == 0) {
1685 if ((prop = node.property ("source")) == 0) {
1686 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1687 return boost::shared_ptr<AudioRegion>();
1691 PBD::ID s_id (prop->value());
1693 if ((source = source_by_id (s_id)) == 0) {
1694 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1695 return boost::shared_ptr<AudioRegion>();
1698 as = boost::dynamic_pointer_cast<AudioSource>(source);
1700 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1701 return boost::shared_ptr<AudioRegion>();
1704 sources.push_back (as);
1706 /* pickup other channels */
1708 for (uint32_t n=1; n < nchans; ++n) {
1709 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1710 if ((prop = node.property (buf)) != 0) {
1712 PBD::ID id2 (prop->value());
1714 if ((source = source_by_id (id2)) == 0) {
1715 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1716 return boost::shared_ptr<AudioRegion>();
1719 as = boost::dynamic_pointer_cast<AudioSource>(source);
1721 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1722 return boost::shared_ptr<AudioRegion>();
1724 sources.push_back (as);
1728 for (uint32_t n = 0; n < nchans; ++n) {
1729 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1730 if ((prop = node.property (buf)) != 0) {
1732 PBD::ID id2 (prop->value());
1734 if ((source = source_by_id (id2)) == 0) {
1735 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1736 return boost::shared_ptr<AudioRegion>();
1739 as = boost::dynamic_pointer_cast<AudioSource>(source);
1741 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1742 return boost::shared_ptr<AudioRegion>();
1744 master_sources.push_back (as);
1749 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1751 /* a final detail: this is the one and only place that we know how long missing files are */
1753 if (region->whole_file()) {
1754 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1755 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1757 sfp->set_length (region->length());
1762 if (!master_sources.empty()) {
1763 if (master_sources.size() != nchans) {
1764 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1766 region->set_master_sources (master_sources);
1774 catch (failed_constructor& err) {
1775 return boost::shared_ptr<AudioRegion>();
1779 boost::shared_ptr<MidiRegion>
1780 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1782 const XMLProperty* prop;
1783 boost::shared_ptr<Source> source;
1784 boost::shared_ptr<MidiSource> ms;
1787 if (node.name() != X_("Region")) {
1788 return boost::shared_ptr<MidiRegion>();
1791 if ((prop = node.property ("name")) == 0) {
1792 cerr << "no name for this region\n";
1796 if ((prop = node.property (X_("source-0"))) == 0) {
1797 if ((prop = node.property ("source")) == 0) {
1798 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1799 return boost::shared_ptr<MidiRegion>();
1803 PBD::ID s_id (prop->value());
1805 if ((source = source_by_id (s_id)) == 0) {
1806 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1807 return boost::shared_ptr<MidiRegion>();
1810 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1812 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1813 return boost::shared_ptr<MidiRegion>();
1816 sources.push_back (ms);
1819 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1820 /* a final detail: this is the one and only place that we know how long missing files are */
1822 if (region->whole_file()) {
1823 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1824 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1826 sfp->set_length (region->length());
1834 catch (failed_constructor& err) {
1835 return boost::shared_ptr<MidiRegion>();
1840 Session::get_sources_as_xml ()
1843 XMLNode* node = new XMLNode (X_("Sources"));
1844 Glib::Threads::Mutex::Lock lm (source_lock);
1846 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1847 node->add_child_nocopy (i->second->get_state());
1854 Session::load_sources (const XMLNode& node)
1857 XMLNodeConstIterator niter;
1858 boost::shared_ptr<Source> source;
1860 nlist = node.children();
1864 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1867 if ((source = XMLSourceFactory (**niter)) == 0) {
1868 error << _("Session: cannot create Source from XML description.") << endmsg;
1871 } catch (MissingSource& err) {
1875 if (!no_questions_about_missing_files) {
1876 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1881 switch (user_choice) {
1883 /* user added a new search location, so try again */
1888 /* user asked to quit the entire session load
1893 no_questions_about_missing_files = true;
1897 no_questions_about_missing_files = true;
1902 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1903 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1912 boost::shared_ptr<Source>
1913 Session::XMLSourceFactory (const XMLNode& node)
1915 if (node.name() != "Source") {
1916 return boost::shared_ptr<Source>();
1920 /* note: do peak building in another thread when loading session state */
1921 return SourceFactory::create (*this, node, true);
1924 catch (failed_constructor& err) {
1925 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
1926 return boost::shared_ptr<Source>();
1931 Session::save_template (string template_name)
1935 if (_state_of_the_state & CannotSave) {
1939 std::string user_template_dir(user_template_directory());
1941 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
1942 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
1943 user_template_dir, g_strerror (errno)) << endmsg;
1947 tree.set_root (&get_template());
1949 std::string template_dir_path(user_template_dir);
1951 /* directory to put the template in */
1952 template_dir_path = Glib::build_filename (template_dir_path, template_name);
1954 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
1955 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1956 template_dir_path) << endmsg;
1960 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
1961 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
1962 template_dir_path, g_strerror (errno)) << endmsg;
1967 std::string template_file_path(template_dir_path);
1968 template_file_path = Glib::build_filename (template_file_path, template_name + template_suffix);
1970 if (!tree.write (template_file_path)) {
1971 error << _("template not saved") << endmsg;
1975 /* copy plugin state directory */
1977 std::string template_plugin_state_path(template_dir_path);
1978 template_plugin_state_path = Glib::build_filename (template_plugin_state_path, X_("plugins"));
1980 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
1981 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
1982 template_plugin_state_path, g_strerror (errno)) << endmsg;
1986 copy_files (plugins_dir(), template_plugin_state_path);
1992 Session::refresh_disk_space ()
1994 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
1996 Glib::Threads::Mutex::Lock lm (space_lock);
1998 /* get freespace on every FS that is part of the session path */
2000 _total_free_4k_blocks = 0;
2001 _total_free_4k_blocks_uncertain = false;
2003 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2005 struct statfs statfsbuf;
2006 statfs (i->path.c_str(), &statfsbuf);
2008 double const scale = statfsbuf.f_bsize / 4096.0;
2010 /* See if this filesystem is read-only */
2011 struct statvfs statvfsbuf;
2012 statvfs (i->path.c_str(), &statvfsbuf);
2014 /* f_bavail can be 0 if it is undefined for whatever
2015 filesystem we are looking at; Samba shares mounted
2016 via GVFS are an example of this.
2018 if (statfsbuf.f_bavail == 0) {
2019 /* block count unknown */
2021 i->blocks_unknown = true;
2022 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2023 /* read-only filesystem */
2025 i->blocks_unknown = false;
2027 /* read/write filesystem with known space */
2028 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2029 i->blocks_unknown = false;
2032 _total_free_4k_blocks += i->blocks;
2033 if (i->blocks_unknown) {
2034 _total_free_4k_blocks_uncertain = true;
2037 #elif defined (COMPILER_MSVC)
2038 vector<string> scanned_volumes;
2039 vector<string>::iterator j;
2040 vector<space_and_path>::iterator i;
2041 DWORD nSectorsPerCluster, nBytesPerSector,
2042 nFreeClusters, nTotalClusters;
2046 _total_free_4k_blocks = 0;
2048 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2049 strncpy (disk_drive, (*i).path.c_str(), 3);
2053 volume_found = false;
2054 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2056 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2057 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2058 i->blocks = (uint32_t)(nFreeBytes / 4096);
2060 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2061 if (0 == j->compare(disk_drive)) {
2062 volume_found = true;
2067 if (!volume_found) {
2068 scanned_volumes.push_back(disk_drive);
2069 _total_free_4k_blocks += i->blocks;
2074 if (0 == _total_free_4k_blocks) {
2075 strncpy (disk_drive, path().c_str(), 3);
2078 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2080 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2081 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2082 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2089 Session::get_best_session_directory_for_new_audio ()
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 state_file_filter (const string &str, void* /*arg*/)
2267 return (str.length() > strlen(statefile_suffix) &&
2268 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2272 remove_end(string state)
2274 string statename(state);
2276 string::size_type start,end;
2277 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2278 statename = statename.substr (start+1);
2281 if ((end = statename.rfind(".ardour")) == string::npos) {
2282 end = statename.length();
2285 return string(statename.substr (0, end));
2289 Session::possible_states (string path)
2291 vector<string> states;
2292 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2294 transform(states.begin(), states.end(), states.begin(), remove_end);
2296 sort (states.begin(), states.end());
2302 Session::possible_states () const
2304 return possible_states(_path);
2308 Session::add_route_group (RouteGroup* g)
2310 _route_groups.push_back (g);
2311 route_group_added (g); /* EMIT SIGNAL */
2313 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2314 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2315 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2321 Session::remove_route_group (RouteGroup& rg)
2323 list<RouteGroup*>::iterator i;
2325 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2326 _route_groups.erase (i);
2329 route_group_removed (); /* EMIT SIGNAL */
2333 /** Set a new order for our route groups, without adding or removing any.
2334 * @param groups Route group list in the new order.
2337 Session::reorder_route_groups (list<RouteGroup*> groups)
2339 _route_groups = groups;
2341 route_groups_reordered (); /* EMIT SIGNAL */
2347 Session::route_group_by_name (string name)
2349 list<RouteGroup *>::iterator i;
2351 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2352 if ((*i)->name() == name) {
2360 Session::all_route_group() const
2362 return *_all_route_group;
2366 Session::add_commands (vector<Command*> const & cmds)
2368 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2374 Session::begin_reversible_command (const string& name)
2376 begin_reversible_command (g_quark_from_string (name.c_str ()));
2379 /** Begin a reversible command using a GQuark to identify it.
2380 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2381 * but there must be as many begin...()s as there are commit...()s.
2384 Session::begin_reversible_command (GQuark q)
2386 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2387 to hold all the commands that are committed. This keeps the order of
2388 commands correct in the history.
2391 if (_current_trans == 0) {
2392 /* start a new transaction */
2393 assert (_current_trans_quarks.empty ());
2394 _current_trans = new UndoTransaction();
2395 _current_trans->set_name (g_quark_to_string (q));
2398 _current_trans_quarks.push_front (q);
2402 Session::commit_reversible_command (Command *cmd)
2404 assert (_current_trans);
2405 assert (!_current_trans_quarks.empty ());
2410 _current_trans->add_command (cmd);
2413 _current_trans_quarks.pop_front ();
2415 if (!_current_trans_quarks.empty ()) {
2416 /* the transaction we're committing is not the top-level one */
2420 if (_current_trans->empty()) {
2421 /* no commands were added to the transaction, so just get rid of it */
2422 delete _current_trans;
2427 gettimeofday (&now, 0);
2428 _current_trans->set_timestamp (now);
2430 _history.add (_current_trans);
2435 accept_all_audio_files (const string& path, void* /*arg*/)
2437 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2441 if (!AudioFileSource::safe_audio_file_extension (path)) {
2449 accept_all_midi_files (const string& path, void* /*arg*/)
2451 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2455 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2456 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2457 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2461 accept_all_state_files (const string& path, void* /*arg*/)
2463 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2467 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2471 Session::find_all_sources (string path, set<string>& result)
2476 if (!tree.read (path)) {
2480 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2485 XMLNodeConstIterator niter;
2487 nlist = node->children();
2491 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2495 if ((prop = (*niter)->property (X_("type"))) == 0) {
2499 DataType type (prop->value());
2501 if ((prop = (*niter)->property (X_("name"))) == 0) {
2505 if (Glib::path_is_absolute (prop->value())) {
2506 /* external file, ignore */
2514 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2515 result.insert (found_path);
2523 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2525 vector<string> state_files;
2527 string this_snapshot_path;
2533 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2534 ripped = ripped.substr (0, ripped.length() - 1);
2537 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2539 if (state_files.empty()) {
2544 this_snapshot_path = _path;
2545 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2546 this_snapshot_path += statefile_suffix;
2548 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2550 if (exclude_this_snapshot && *i == this_snapshot_path) {
2554 if (find_all_sources (*i, result) < 0) {
2562 struct RegionCounter {
2563 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2564 AudioSourceList::iterator iter;
2565 boost::shared_ptr<Region> region;
2568 RegionCounter() : count (0) {}
2572 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2574 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2575 return r.get_value_or (1);
2579 Session::cleanup_regions ()
2581 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2583 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2585 uint32_t used = playlists->region_use_count (i->second);
2587 if (used == 0 && !i->second->automatic ()) {
2588 RegionFactory::map_remove (i->second);
2592 /* dump the history list */
2599 Session::cleanup_sources (CleanupReport& rep)
2601 // FIXME: needs adaptation to midi
2603 vector<boost::shared_ptr<Source> > dead_sources;
2606 vector<string> candidates;
2607 vector<string> unused;
2608 set<string> all_sources;
2617 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2619 /* consider deleting all unused playlists */
2621 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2626 /* sync the "all regions" property of each playlist with its current state
2629 playlists->sync_all_regions_with_regions ();
2631 /* find all un-used sources */
2636 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2638 SourceMap::iterator tmp;
2643 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2647 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2648 dead_sources.push_back (i->second);
2649 i->second->drop_references ();
2655 /* build a list of all the possible audio directories for the session */
2657 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2658 SessionDirectory sdir ((*i).path);
2659 asp += sdir.sound_path();
2661 audio_path += asp.to_string();
2664 /* build a list of all the possible midi directories for the session */
2666 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2667 SessionDirectory sdir ((*i).path);
2668 msp += sdir.midi_path();
2670 midi_path += msp.to_string();
2672 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
2673 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
2675 /* find all sources, but don't use this snapshot because the
2676 state file on disk still references sources we may have already
2680 find_all_sources_across_snapshots (all_sources, true);
2682 /* add our current source list
2685 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2686 boost::shared_ptr<FileSource> fs;
2687 SourceMap::iterator tmp = i;
2690 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2692 if (!fs->is_stub()) {
2694 if (playlists->source_use_count (fs) != 0) {
2695 all_sources.insert (fs->path());
2698 /* we might not remove this source from disk, because it may be used
2699 by other snapshots, but its not being used in this version
2700 so lets get rid of it now, along with any representative regions
2704 RegionFactory::remove_regions_using_source (i->second);
2713 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
2718 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2720 tmppath1 = canonical_path (spath);
2721 tmppath2 = canonical_path ((*i));
2723 if (tmppath1 == tmppath2) {
2730 unused.push_back (spath);
2734 /* now try to move all unused files into the "dead" directory(ies) */
2736 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2737 struct stat statbuf;
2741 /* don't move the file across filesystems, just
2742 stick it in the `dead_dir_name' directory
2743 on whichever filesystem it was already on.
2746 if ((*x).find ("/sounds/") != string::npos) {
2748 /* old school, go up 1 level */
2750 newpath = Glib::path_get_dirname (*x); // "sounds"
2751 newpath = Glib::path_get_dirname (newpath); // "session-name"
2755 /* new school, go up 4 levels */
2757 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2758 newpath = Glib::path_get_dirname (newpath); // "session-name"
2759 newpath = Glib::path_get_dirname (newpath); // "interchange"
2760 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2763 newpath = Glib::build_filename (newpath, dead_dir_name);
2765 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2766 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2770 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2772 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2774 /* the new path already exists, try versioning */
2776 char buf[PATH_MAX+1];
2780 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2783 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2784 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2788 if (version == 999) {
2789 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2793 newpath = newpath_v;
2798 /* it doesn't exist, or we can't read it or something */
2802 stat ((*x).c_str(), &statbuf);
2804 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2805 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2806 (*x), newpath, strerror (errno))
2811 /* see if there an easy to find peakfile for this file, and remove it.
2814 string base = basename_nosuffix (*x);
2815 base += "%A"; /* this is what we add for the channel suffix of all native files,
2816 or for the first channel of embedded files. it will miss
2817 some peakfiles for other channels
2819 string peakpath = peak_path (base);
2821 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2822 if (::g_unlink (peakpath.c_str()) != 0) {
2823 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2824 peakpath, _path, strerror (errno))
2826 /* try to back out */
2827 ::rename (newpath.c_str(), _path.c_str());
2832 rep.paths.push_back (*x);
2833 rep.space += statbuf.st_size;
2836 /* dump the history list */
2840 /* save state so we don't end up a session file
2841 referring to non-existent sources.
2848 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2854 Session::cleanup_trash_sources (CleanupReport& rep)
2856 // FIXME: needs adaptation for MIDI
2858 vector<space_and_path>::iterator i;
2864 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2866 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2868 clear_directory (dead_dir, &rep.space, &rep.paths);
2875 Session::set_dirty ()
2877 bool was_dirty = dirty();
2879 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2883 DirtyChanged(); /* EMIT SIGNAL */
2889 Session::set_clean ()
2891 bool was_dirty = dirty();
2893 _state_of_the_state = Clean;
2897 DirtyChanged(); /* EMIT SIGNAL */
2902 Session::set_deletion_in_progress ()
2904 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2908 Session::clear_deletion_in_progress ()
2910 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2914 Session::add_controllable (boost::shared_ptr<Controllable> c)
2916 /* this adds a controllable to the list managed by the Session.
2917 this is a subset of those managed by the Controllable class
2918 itself, and represents the only ones whose state will be saved
2919 as part of the session.
2922 Glib::Threads::Mutex::Lock lm (controllables_lock);
2923 controllables.insert (c);
2926 struct null_deleter { void operator()(void const *) const {} };
2929 Session::remove_controllable (Controllable* c)
2931 if (_state_of_the_state & Deletion) {
2935 Glib::Threads::Mutex::Lock lm (controllables_lock);
2937 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
2939 if (x != controllables.end()) {
2940 controllables.erase (x);
2944 boost::shared_ptr<Controllable>
2945 Session::controllable_by_id (const PBD::ID& id)
2947 Glib::Threads::Mutex::Lock lm (controllables_lock);
2949 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2950 if ((*i)->id() == id) {
2955 return boost::shared_ptr<Controllable>();
2958 boost::shared_ptr<Controllable>
2959 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
2961 boost::shared_ptr<Controllable> c;
2962 boost::shared_ptr<Route> r;
2964 switch (desc.top_level_type()) {
2965 case ControllableDescriptor::NamedRoute:
2967 std::string str = desc.top_level_name();
2968 if (str == "master") {
2970 } else if (str == "control" || str == "listen") {
2973 r = route_by_name (desc.top_level_name());
2978 case ControllableDescriptor::RemoteControlID:
2979 r = route_by_remote_id (desc.rid());
2987 switch (desc.subtype()) {
2988 case ControllableDescriptor::Gain:
2989 c = r->gain_control ();
2992 case ControllableDescriptor::Solo:
2993 c = r->solo_control();
2996 case ControllableDescriptor::Mute:
2997 c = r->mute_control();
3000 case ControllableDescriptor::Recenable:
3002 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3005 c = t->rec_enable_control ();
3010 case ControllableDescriptor::PanDirection:
3012 c = r->pannable()->pan_azimuth_control;
3016 case ControllableDescriptor::PanWidth:
3018 c = r->pannable()->pan_width_control;
3022 case ControllableDescriptor::PanElevation:
3024 c = r->pannable()->pan_elevation_control;
3028 case ControllableDescriptor::Balance:
3029 /* XXX simple pan control */
3032 case ControllableDescriptor::PluginParameter:
3034 uint32_t plugin = desc.target (0);
3035 uint32_t parameter_index = desc.target (1);
3037 /* revert to zero based counting */
3043 if (parameter_index > 0) {
3047 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3050 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3051 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3056 case ControllableDescriptor::SendGain:
3058 uint32_t send = desc.target (0);
3060 /* revert to zero-based counting */
3066 boost::shared_ptr<Processor> p = r->nth_send (send);
3069 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3070 boost::shared_ptr<Amp> a = s->amp();
3073 c = s->amp()->gain_control();
3080 /* relax and return a null pointer */
3088 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3091 Stateful::add_instant_xml (node, _path);
3094 if (write_to_config) {
3095 Config->add_instant_xml (node);
3100 Session::instant_xml (const string& node_name)
3102 return Stateful::instant_xml (node_name, _path);
3106 Session::save_history (string snapshot_name)
3114 if (snapshot_name.empty()) {
3115 snapshot_name = _current_snapshot_name;
3118 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3119 const string backup_filename = history_filename + backup_suffix;
3120 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3121 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3123 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3124 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3125 error << _("could not backup old history file, current history not saved") << endmsg;
3130 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3134 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3136 if (!tree.write (xml_path))
3138 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3140 if (g_remove (xml_path.c_str()) != 0) {
3141 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3142 xml_path, g_strerror (errno)) << endmsg;
3144 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3145 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3146 backup_path, g_strerror (errno)) << endmsg;
3156 Session::restore_history (string snapshot_name)
3160 if (snapshot_name.empty()) {
3161 snapshot_name = _current_snapshot_name;
3164 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3165 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3167 info << "Loading history from " << xml_path << endmsg;
3169 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3170 info << string_compose (_("%1: no history file \"%2\" for this session."),
3171 _name, xml_path) << endmsg;
3175 if (!tree.read (xml_path)) {
3176 error << string_compose (_("Could not understand session history file \"%1\""),
3177 xml_path) << endmsg;
3184 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3187 UndoTransaction* ut = new UndoTransaction ();
3190 ut->set_name(t->property("name")->value());
3191 stringstream ss(t->property("tv-sec")->value());
3193 ss.str(t->property("tv-usec")->value());
3195 ut->set_timestamp(tv);
3197 for (XMLNodeConstIterator child_it = t->children().begin();
3198 child_it != t->children().end(); child_it++)
3200 XMLNode *n = *child_it;
3203 if (n->name() == "MementoCommand" ||
3204 n->name() == "MementoUndoCommand" ||
3205 n->name() == "MementoRedoCommand") {
3207 if ((c = memento_command_factory(n))) {
3211 } else if (n->name() == "NoteDiffCommand") {
3212 PBD::ID id (n->property("midi-source")->value());
3213 boost::shared_ptr<MidiSource> midi_source =
3214 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3216 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3218 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3221 } else if (n->name() == "SysExDiffCommand") {
3223 PBD::ID id (n->property("midi-source")->value());
3224 boost::shared_ptr<MidiSource> midi_source =
3225 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3227 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3229 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3232 } else if (n->name() == "PatchChangeDiffCommand") {
3234 PBD::ID id (n->property("midi-source")->value());
3235 boost::shared_ptr<MidiSource> midi_source =
3236 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3238 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3240 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3243 } else if (n->name() == "StatefulDiffCommand") {
3244 if ((c = stateful_diff_command_factory (n))) {
3245 ut->add_command (c);
3248 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3259 Session::config_changed (std::string p, bool ours)
3265 if (p == "seamless-loop") {
3267 } else if (p == "rf-speed") {
3269 } else if (p == "auto-loop") {
3271 } else if (p == "auto-input") {
3273 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3274 /* auto-input only makes a difference if we're rolling */
3275 set_track_monitor_input_status (!config.get_auto_input());
3278 } else if (p == "punch-in") {
3282 if ((location = _locations->auto_punch_location()) != 0) {
3284 if (config.get_punch_in ()) {
3285 replace_event (SessionEvent::PunchIn, location->start());
3287 remove_event (location->start(), SessionEvent::PunchIn);
3291 } else if (p == "punch-out") {
3295 if ((location = _locations->auto_punch_location()) != 0) {
3297 if (config.get_punch_out()) {
3298 replace_event (SessionEvent::PunchOut, location->end());
3300 clear_events (SessionEvent::PunchOut);
3304 } else if (p == "edit-mode") {
3306 Glib::Threads::Mutex::Lock lm (playlists->lock);
3308 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3309 (*i)->set_edit_mode (Config->get_edit_mode ());
3312 } else if (p == "use-video-sync") {
3314 waiting_for_sync_offset = config.get_use_video_sync();
3316 } else if (p == "mmc-control") {
3318 //poke_midi_thread ();
3320 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3322 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3324 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3326 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3328 } else if (p == "midi-control") {
3330 //poke_midi_thread ();
3332 } else if (p == "raid-path") {
3334 setup_raid_path (config.get_raid_path());
3336 } else if (p == "timecode-format") {
3340 } else if (p == "video-pullup") {
3344 } else if (p == "seamless-loop") {
3346 if (play_loop && transport_rolling()) {
3347 // to reset diskstreams etc
3348 request_play_loop (true);
3351 } else if (p == "rf-speed") {
3353 cumulative_rf_motion = 0;
3356 } else if (p == "click-sound") {
3358 setup_click_sounds (1);
3360 } else if (p == "click-emphasis-sound") {
3362 setup_click_sounds (-1);
3364 } else if (p == "clicking") {
3366 if (Config->get_clicking()) {
3367 if (_click_io && click_data) { // don't require emphasis data
3374 } else if (p == "click-gain") {
3377 _click_gain->set_gain (Config->get_click_gain(), this);
3380 } else if (p == "send-mtc") {
3382 if (Config->get_send_mtc ()) {
3383 /* mark us ready to send */
3384 next_quarter_frame_to_send = 0;
3387 } else if (p == "send-mmc") {
3389 _mmc->enable_send (Config->get_send_mmc ());
3391 } else if (p == "midi-feedback") {
3393 session_midi_feedback = Config->get_midi_feedback();
3395 } else if (p == "jack-time-master") {
3397 engine().reset_timebase ();
3399 } else if (p == "native-file-header-format") {
3401 if (!first_file_header_format_reset) {
3402 reset_native_file_format ();
3405 first_file_header_format_reset = false;
3407 } else if (p == "native-file-data-format") {
3409 if (!first_file_data_format_reset) {
3410 reset_native_file_format ();
3413 first_file_data_format_reset = false;
3415 } else if (p == "external-sync") {
3416 if (!config.get_external_sync()) {
3417 drop_sync_source ();
3419 switch_to_sync_source (Config->get_sync_source());
3421 } else if (p == "denormal-model") {
3423 } else if (p == "history-depth") {
3424 set_history_depth (Config->get_history_depth());
3425 } else if (p == "remote-model") {
3426 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3429 } else if (p == "initial-program-change") {
3431 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3434 buf[0] = MIDI::program; // channel zero by default
3435 buf[1] = (Config->get_initial_program_change() & 0x7f);
3437 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3439 } else if (p == "solo-mute-override") {
3440 // catch_up_on_solo_mute_override ();
3441 } else if (p == "listen-position" || p == "pfl-position") {
3442 listen_position_changed ();
3443 } else if (p == "solo-control-is-listen-control") {
3444 solo_control_mode_changed ();
3445 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3446 last_timecode_valid = false;
3447 } else if (p == "playback-buffer-seconds") {
3448 AudioSource::allocate_working_buffers (frame_rate());
3449 } else if (p == "automation-thinning-factor") {
3450 Evoral::ControlList::set_thinning_factor (Config->get_automation_thinning_factor());
3451 } else if (p == "ltc-source-port") {
3452 reconnect_ltc_input ();
3453 } else if (p == "ltc-sink-port") {
3454 reconnect_ltc_output ();
3455 } else if (p == "timecode-generator-offset") {
3456 ltc_tx_parse_offset();
3463 Session::set_history_depth (uint32_t d)
3465 _history.set_depth (d);
3469 Session::load_diskstreams_2X (XMLNode const & node, int)
3472 XMLNodeConstIterator citer;
3474 clist = node.children();
3476 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3479 /* diskstreams added automatically by DiskstreamCreated handler */
3480 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3481 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3482 _diskstreams_2X.push_back (dsp);
3484 error << _("Session: unknown diskstream type in XML") << endmsg;
3488 catch (failed_constructor& err) {
3489 error << _("Session: could not load diskstream via XML state") << endmsg;
3497 /** Connect things to the MMC object */
3499 Session::setup_midi_machine_control ()
3501 _mmc = new MIDI::MachineControl;
3502 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3504 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3505 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3506 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3507 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3508 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3509 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3510 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3511 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3512 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3513 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3514 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3515 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3516 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3518 /* also handle MIDI SPP because its so common */
3520 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3521 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3522 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3525 boost::shared_ptr<Controllable>
3526 Session::solo_cut_control() const
3528 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3529 controls in Ardour that currently get presented to the user in the GUI that require
3530 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3532 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3533 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3537 return _solo_cut_control;
3541 Session::rename (const std::string& new_name)
3543 string legal_name = legalize_for_path (new_name);
3549 string const old_sources_root = _session_dir->sources_root();
3554 * interchange subdirectory
3558 * Backup files are left unchanged and not renamed.
3561 /* pass one: not 100% safe check that the new directory names don't
3565 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3570 /* this is a stupid hack because Glib::path_get_dirname() is
3571 * lexical-only, and so passing it /a/b/c/ gives a different
3572 * result than passing it /a/b/c ...
3575 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3576 oldstr = oldstr.substr (0, oldstr.length() - 1);
3579 string base = Glib::path_get_dirname (oldstr);
3580 string p = Glib::path_get_basename (oldstr);
3582 newstr = Glib::build_filename (base, legal_name);
3584 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3591 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3596 /* this is a stupid hack because Glib::path_get_dirname() is
3597 * lexical-only, and so passing it /a/b/c/ gives a different
3598 * result than passing it /a/b/c ...
3601 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3602 oldstr = oldstr.substr (0, oldstr.length() - 1);
3605 string base = Glib::path_get_dirname (oldstr);
3606 string p = Glib::path_get_basename (oldstr);
3608 newstr = Glib::build_filename (base, legal_name);
3610 cerr << "Rename " << oldstr << " => " << newstr << endl;
3612 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3613 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3618 (*_session_dir) = newstr;
3623 /* directory below interchange */
3625 v.push_back (newstr);
3626 v.push_back (interchange_dir_name);
3629 oldstr = Glib::build_filename (v);
3632 v.push_back (newstr);
3633 v.push_back (interchange_dir_name);
3634 v.push_back (legal_name);
3636 newstr = Glib::build_filename (v);
3638 cerr << "Rename " << oldstr << " => " << newstr << endl;
3640 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3641 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3648 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3649 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3651 cerr << "Rename " << oldstr << " => " << newstr << endl;
3653 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3654 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3661 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3663 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3664 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3666 cerr << "Rename " << oldstr << " => " << newstr << endl;
3668 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3669 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3674 /* update file source paths */
3676 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3677 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3679 string p = fs->path ();
3680 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3685 /* remove old name from recent sessions */
3687 remove_recent_sessions (_path);
3690 _current_snapshot_name = new_name;
3693 /* re-add directory separator - reverse hack to oldstr above */
3694 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
3695 _path += G_DIR_SEPARATOR;
3700 /* save state again to get everything just right */
3702 save_state (_current_snapshot_name);
3705 /* add to recent sessions */
3707 store_recent_sessions (new_name, _path);
3713 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
3715 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
3719 if (!tree.read (xmlpath)) {
3727 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
3730 bool found_sr = false;
3731 bool found_data_format = false;
3733 if (get_session_info_from_path (tree, xmlpath)) {
3739 const XMLProperty* prop;
3740 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
3741 sample_rate = atoi (prop->value());
3745 const XMLNodeList& children (tree.root()->children());
3746 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
3747 const XMLNode* child = *c;
3748 if (child->name() == "Config") {
3749 const XMLNodeList& options (child->children());
3750 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
3751 const XMLNode* option = *oc;
3752 const XMLProperty* name = option->property("name");
3758 if (name->value() == "native-file-data-format") {
3759 const XMLProperty* value = option->property ("value");
3761 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
3763 found_data_format = true;
3769 if (found_data_format) {
3774 return !(found_sr && found_data_format); // zero if they are both found