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 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 remove_end(string state)
2280 string statename(state);
2282 string::size_type start,end;
2283 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2284 statename = statename.substr (start+1);
2287 if ((end = statename.rfind(".ardour")) == string::npos) {
2288 end = statename.length();
2291 return string(statename.substr (0, end));
2295 Session::possible_states (string path)
2297 vector<string> states;
2298 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2300 transform(states.begin(), states.end(), states.begin(), remove_end);
2302 sort (states.begin(), states.end());
2308 Session::possible_states () const
2310 return possible_states(_path);
2314 Session::add_route_group (RouteGroup* g)
2316 _route_groups.push_back (g);
2317 route_group_added (g); /* EMIT SIGNAL */
2319 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2320 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2321 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2327 Session::remove_route_group (RouteGroup& rg)
2329 list<RouteGroup*>::iterator i;
2331 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2332 _route_groups.erase (i);
2335 route_group_removed (); /* EMIT SIGNAL */
2339 /** Set a new order for our route groups, without adding or removing any.
2340 * @param groups Route group list in the new order.
2343 Session::reorder_route_groups (list<RouteGroup*> groups)
2345 _route_groups = groups;
2347 route_groups_reordered (); /* EMIT SIGNAL */
2353 Session::route_group_by_name (string name)
2355 list<RouteGroup *>::iterator i;
2357 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2358 if ((*i)->name() == name) {
2366 Session::all_route_group() const
2368 return *_all_route_group;
2372 Session::add_commands (vector<Command*> const & cmds)
2374 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2380 Session::begin_reversible_command (const string& name)
2382 begin_reversible_command (g_quark_from_string (name.c_str ()));
2385 /** Begin a reversible command using a GQuark to identify it.
2386 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2387 * but there must be as many begin...()s as there are commit...()s.
2390 Session::begin_reversible_command (GQuark q)
2392 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2393 to hold all the commands that are committed. This keeps the order of
2394 commands correct in the history.
2397 if (_current_trans == 0) {
2398 /* start a new transaction */
2399 assert (_current_trans_quarks.empty ());
2400 _current_trans = new UndoTransaction();
2401 _current_trans->set_name (g_quark_to_string (q));
2404 _current_trans_quarks.push_front (q);
2408 Session::commit_reversible_command (Command *cmd)
2410 assert (_current_trans);
2411 assert (!_current_trans_quarks.empty ());
2416 _current_trans->add_command (cmd);
2419 _current_trans_quarks.pop_front ();
2421 if (!_current_trans_quarks.empty ()) {
2422 /* the transaction we're committing is not the top-level one */
2426 if (_current_trans->empty()) {
2427 /* no commands were added to the transaction, so just get rid of it */
2428 delete _current_trans;
2433 gettimeofday (&now, 0);
2434 _current_trans->set_timestamp (now);
2436 _history.add (_current_trans);
2441 accept_all_audio_files (const string& path, void* /*arg*/)
2443 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2447 if (!AudioFileSource::safe_audio_file_extension (path)) {
2455 accept_all_midi_files (const string& path, void* /*arg*/)
2457 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2461 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2462 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2463 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2467 accept_all_state_files (const string& path, void* /*arg*/)
2469 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2473 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2477 Session::find_all_sources (string path, set<string>& result)
2482 if (!tree.read (path)) {
2486 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2491 XMLNodeConstIterator niter;
2493 nlist = node->children();
2497 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2501 if ((prop = (*niter)->property (X_("type"))) == 0) {
2505 DataType type (prop->value());
2507 if ((prop = (*niter)->property (X_("name"))) == 0) {
2511 if (Glib::path_is_absolute (prop->value())) {
2512 /* external file, ignore */
2520 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2521 result.insert (found_path);
2529 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2531 vector<string> state_files;
2533 string this_snapshot_path;
2539 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2540 ripped = ripped.substr (0, ripped.length() - 1);
2543 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2545 if (state_files.empty()) {
2550 this_snapshot_path = _path;
2551 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2552 this_snapshot_path += statefile_suffix;
2554 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2556 if (exclude_this_snapshot && *i == this_snapshot_path) {
2560 if (find_all_sources (*i, result) < 0) {
2568 struct RegionCounter {
2569 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2570 AudioSourceList::iterator iter;
2571 boost::shared_ptr<Region> region;
2574 RegionCounter() : count (0) {}
2578 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2580 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2581 return r.get_value_or (1);
2585 Session::cleanup_regions ()
2587 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2589 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2591 uint32_t used = playlists->region_use_count (i->second);
2593 if (used == 0 && !i->second->automatic ()) {
2594 RegionFactory::map_remove (i->second);
2598 /* dump the history list */
2605 Session::cleanup_sources (CleanupReport& rep)
2607 // FIXME: needs adaptation to midi
2609 vector<boost::shared_ptr<Source> > dead_sources;
2612 vector<string> candidates;
2613 vector<string> unused;
2614 set<string> all_sources;
2623 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2625 /* consider deleting all unused playlists */
2627 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2632 /* sync the "all regions" property of each playlist with its current state
2635 playlists->sync_all_regions_with_regions ();
2637 /* find all un-used sources */
2642 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2644 SourceMap::iterator tmp;
2649 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2653 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2654 dead_sources.push_back (i->second);
2655 i->second->drop_references ();
2661 /* build a list of all the possible audio directories for the session */
2663 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2664 SessionDirectory sdir ((*i).path);
2665 asp += sdir.sound_path();
2667 audio_path += asp.to_string();
2670 /* build a list of all the possible midi directories for the session */
2672 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2673 SessionDirectory sdir ((*i).path);
2674 msp += sdir.midi_path();
2676 midi_path += msp.to_string();
2678 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
2679 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
2681 /* find all sources, but don't use this snapshot because the
2682 state file on disk still references sources we may have already
2686 find_all_sources_across_snapshots (all_sources, true);
2688 /* add our current source list
2691 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2692 boost::shared_ptr<FileSource> fs;
2693 SourceMap::iterator tmp = i;
2696 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2698 if (!fs->is_stub()) {
2700 if (playlists->source_use_count (fs) != 0) {
2701 all_sources.insert (fs->path());
2704 /* we might not remove this source from disk, because it may be used
2705 by other snapshots, but its not being used in this version
2706 so lets get rid of it now, along with any representative regions
2710 RegionFactory::remove_regions_using_source (i->second);
2719 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
2724 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2726 tmppath1 = canonical_path (spath);
2727 tmppath2 = canonical_path ((*i));
2729 if (tmppath1 == tmppath2) {
2736 unused.push_back (spath);
2740 /* now try to move all unused files into the "dead" directory(ies) */
2742 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2743 struct stat statbuf;
2747 /* don't move the file across filesystems, just
2748 stick it in the `dead_dir_name' directory
2749 on whichever filesystem it was already on.
2752 if ((*x).find ("/sounds/") != string::npos) {
2754 /* old school, go up 1 level */
2756 newpath = Glib::path_get_dirname (*x); // "sounds"
2757 newpath = Glib::path_get_dirname (newpath); // "session-name"
2761 /* new school, go up 4 levels */
2763 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2764 newpath = Glib::path_get_dirname (newpath); // "session-name"
2765 newpath = Glib::path_get_dirname (newpath); // "interchange"
2766 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2769 newpath = Glib::build_filename (newpath, dead_dir_name);
2771 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2772 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2776 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2778 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2780 /* the new path already exists, try versioning */
2782 char buf[PATH_MAX+1];
2786 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2789 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2790 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2794 if (version == 999) {
2795 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2799 newpath = newpath_v;
2804 /* it doesn't exist, or we can't read it or something */
2808 stat ((*x).c_str(), &statbuf);
2810 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2811 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2812 (*x), newpath, strerror (errno))
2817 /* see if there an easy to find peakfile for this file, and remove it.
2820 string base = basename_nosuffix (*x);
2821 base += "%A"; /* this is what we add for the channel suffix of all native files,
2822 or for the first channel of embedded files. it will miss
2823 some peakfiles for other channels
2825 string peakpath = peak_path (base);
2827 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2828 if (::g_unlink (peakpath.c_str()) != 0) {
2829 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2830 peakpath, _path, strerror (errno))
2832 /* try to back out */
2833 ::rename (newpath.c_str(), _path.c_str());
2838 rep.paths.push_back (*x);
2839 rep.space += statbuf.st_size;
2842 /* dump the history list */
2846 /* save state so we don't end up a session file
2847 referring to non-existent sources.
2854 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2860 Session::cleanup_trash_sources (CleanupReport& rep)
2862 // FIXME: needs adaptation for MIDI
2864 vector<space_and_path>::iterator i;
2870 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2872 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2874 clear_directory (dead_dir, &rep.space, &rep.paths);
2881 Session::set_dirty ()
2883 bool was_dirty = dirty();
2885 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2889 DirtyChanged(); /* EMIT SIGNAL */
2895 Session::set_clean ()
2897 bool was_dirty = dirty();
2899 _state_of_the_state = Clean;
2903 DirtyChanged(); /* EMIT SIGNAL */
2908 Session::set_deletion_in_progress ()
2910 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2914 Session::clear_deletion_in_progress ()
2916 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2920 Session::add_controllable (boost::shared_ptr<Controllable> c)
2922 /* this adds a controllable to the list managed by the Session.
2923 this is a subset of those managed by the Controllable class
2924 itself, and represents the only ones whose state will be saved
2925 as part of the session.
2928 Glib::Threads::Mutex::Lock lm (controllables_lock);
2929 controllables.insert (c);
2932 struct null_deleter { void operator()(void const *) const {} };
2935 Session::remove_controllable (Controllable* c)
2937 if (_state_of_the_state & Deletion) {
2941 Glib::Threads::Mutex::Lock lm (controllables_lock);
2943 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
2945 if (x != controllables.end()) {
2946 controllables.erase (x);
2950 boost::shared_ptr<Controllable>
2951 Session::controllable_by_id (const PBD::ID& id)
2953 Glib::Threads::Mutex::Lock lm (controllables_lock);
2955 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
2956 if ((*i)->id() == id) {
2961 return boost::shared_ptr<Controllable>();
2964 boost::shared_ptr<Controllable>
2965 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
2967 boost::shared_ptr<Controllable> c;
2968 boost::shared_ptr<Route> r;
2970 switch (desc.top_level_type()) {
2971 case ControllableDescriptor::NamedRoute:
2973 std::string str = desc.top_level_name();
2974 if (str == "master") {
2976 } else if (str == "control" || str == "listen") {
2979 r = route_by_name (desc.top_level_name());
2984 case ControllableDescriptor::RemoteControlID:
2985 r = route_by_remote_id (desc.rid());
2993 switch (desc.subtype()) {
2994 case ControllableDescriptor::Gain:
2995 c = r->gain_control ();
2998 case ControllableDescriptor::Solo:
2999 c = r->solo_control();
3002 case ControllableDescriptor::Mute:
3003 c = r->mute_control();
3006 case ControllableDescriptor::Recenable:
3008 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3011 c = t->rec_enable_control ();
3016 case ControllableDescriptor::PanDirection:
3018 c = r->pannable()->pan_azimuth_control;
3022 case ControllableDescriptor::PanWidth:
3024 c = r->pannable()->pan_width_control;
3028 case ControllableDescriptor::PanElevation:
3030 c = r->pannable()->pan_elevation_control;
3034 case ControllableDescriptor::Balance:
3035 /* XXX simple pan control */
3038 case ControllableDescriptor::PluginParameter:
3040 uint32_t plugin = desc.target (0);
3041 uint32_t parameter_index = desc.target (1);
3043 /* revert to zero based counting */
3049 if (parameter_index > 0) {
3053 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3056 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3057 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3062 case ControllableDescriptor::SendGain:
3064 uint32_t send = desc.target (0);
3066 /* revert to zero-based counting */
3072 boost::shared_ptr<Processor> p = r->nth_send (send);
3075 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3076 boost::shared_ptr<Amp> a = s->amp();
3079 c = s->amp()->gain_control();
3086 /* relax and return a null pointer */
3094 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3097 Stateful::add_instant_xml (node, _path);
3100 if (write_to_config) {
3101 Config->add_instant_xml (node);
3106 Session::instant_xml (const string& node_name)
3108 return Stateful::instant_xml (node_name, _path);
3112 Session::save_history (string snapshot_name)
3120 if (snapshot_name.empty()) {
3121 snapshot_name = _current_snapshot_name;
3124 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3125 const string backup_filename = history_filename + backup_suffix;
3126 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3127 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3129 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3130 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3131 error << _("could not backup old history file, current history not saved") << endmsg;
3136 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3140 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3142 if (!tree.write (xml_path))
3144 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3146 if (g_remove (xml_path.c_str()) != 0) {
3147 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3148 xml_path, g_strerror (errno)) << endmsg;
3150 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3151 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3152 backup_path, g_strerror (errno)) << endmsg;
3162 Session::restore_history (string snapshot_name)
3166 if (snapshot_name.empty()) {
3167 snapshot_name = _current_snapshot_name;
3170 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3171 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3173 info << "Loading history from " << xml_path << endmsg;
3175 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3176 info << string_compose (_("%1: no history file \"%2\" for this session."),
3177 _name, xml_path) << endmsg;
3181 if (!tree.read (xml_path)) {
3182 error << string_compose (_("Could not understand session history file \"%1\""),
3183 xml_path) << endmsg;
3190 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3193 UndoTransaction* ut = new UndoTransaction ();
3196 ut->set_name(t->property("name")->value());
3197 stringstream ss(t->property("tv-sec")->value());
3199 ss.str(t->property("tv-usec")->value());
3201 ut->set_timestamp(tv);
3203 for (XMLNodeConstIterator child_it = t->children().begin();
3204 child_it != t->children().end(); child_it++)
3206 XMLNode *n = *child_it;
3209 if (n->name() == "MementoCommand" ||
3210 n->name() == "MementoUndoCommand" ||
3211 n->name() == "MementoRedoCommand") {
3213 if ((c = memento_command_factory(n))) {
3217 } else if (n->name() == "NoteDiffCommand") {
3218 PBD::ID id (n->property("midi-source")->value());
3219 boost::shared_ptr<MidiSource> midi_source =
3220 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3222 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3224 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3227 } else if (n->name() == "SysExDiffCommand") {
3229 PBD::ID id (n->property("midi-source")->value());
3230 boost::shared_ptr<MidiSource> midi_source =
3231 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3233 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3235 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3238 } else if (n->name() == "PatchChangeDiffCommand") {
3240 PBD::ID id (n->property("midi-source")->value());
3241 boost::shared_ptr<MidiSource> midi_source =
3242 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3244 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3246 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3249 } else if (n->name() == "StatefulDiffCommand") {
3250 if ((c = stateful_diff_command_factory (n))) {
3251 ut->add_command (c);
3254 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3265 Session::config_changed (std::string p, bool ours)
3271 if (p == "seamless-loop") {
3273 } else if (p == "rf-speed") {
3275 } else if (p == "auto-loop") {
3277 } else if (p == "auto-input") {
3279 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3280 /* auto-input only makes a difference if we're rolling */
3281 set_track_monitor_input_status (!config.get_auto_input());
3284 } else if (p == "punch-in") {
3288 if ((location = _locations->auto_punch_location()) != 0) {
3290 if (config.get_punch_in ()) {
3291 replace_event (SessionEvent::PunchIn, location->start());
3293 remove_event (location->start(), SessionEvent::PunchIn);
3297 } else if (p == "punch-out") {
3301 if ((location = _locations->auto_punch_location()) != 0) {
3303 if (config.get_punch_out()) {
3304 replace_event (SessionEvent::PunchOut, location->end());
3306 clear_events (SessionEvent::PunchOut);
3310 } else if (p == "edit-mode") {
3312 Glib::Threads::Mutex::Lock lm (playlists->lock);
3314 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3315 (*i)->set_edit_mode (Config->get_edit_mode ());
3318 } else if (p == "use-video-sync") {
3320 waiting_for_sync_offset = config.get_use_video_sync();
3322 } else if (p == "mmc-control") {
3324 //poke_midi_thread ();
3326 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3328 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3330 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3332 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3334 } else if (p == "midi-control") {
3336 //poke_midi_thread ();
3338 } else if (p == "raid-path") {
3340 setup_raid_path (config.get_raid_path());
3342 } else if (p == "timecode-format") {
3346 } else if (p == "video-pullup") {
3350 } else if (p == "seamless-loop") {
3352 if (play_loop && transport_rolling()) {
3353 // to reset diskstreams etc
3354 request_play_loop (true);
3357 } else if (p == "rf-speed") {
3359 cumulative_rf_motion = 0;
3362 } else if (p == "click-sound") {
3364 setup_click_sounds (1);
3366 } else if (p == "click-emphasis-sound") {
3368 setup_click_sounds (-1);
3370 } else if (p == "clicking") {
3372 if (Config->get_clicking()) {
3373 if (_click_io && click_data) { // don't require emphasis data
3380 } else if (p == "click-gain") {
3383 _click_gain->set_gain (Config->get_click_gain(), this);
3386 } else if (p == "send-mtc") {
3388 if (Config->get_send_mtc ()) {
3389 /* mark us ready to send */
3390 next_quarter_frame_to_send = 0;
3393 } else if (p == "send-mmc") {
3395 _mmc->enable_send (Config->get_send_mmc ());
3397 } else if (p == "midi-feedback") {
3399 session_midi_feedback = Config->get_midi_feedback();
3401 } else if (p == "jack-time-master") {
3403 engine().reset_timebase ();
3405 } else if (p == "native-file-header-format") {
3407 if (!first_file_header_format_reset) {
3408 reset_native_file_format ();
3411 first_file_header_format_reset = false;
3413 } else if (p == "native-file-data-format") {
3415 if (!first_file_data_format_reset) {
3416 reset_native_file_format ();
3419 first_file_data_format_reset = false;
3421 } else if (p == "external-sync") {
3422 if (!config.get_external_sync()) {
3423 drop_sync_source ();
3425 switch_to_sync_source (Config->get_sync_source());
3427 } else if (p == "denormal-model") {
3429 } else if (p == "history-depth") {
3430 set_history_depth (Config->get_history_depth());
3431 } else if (p == "remote-model") {
3432 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3435 } else if (p == "initial-program-change") {
3437 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3440 buf[0] = MIDI::program; // channel zero by default
3441 buf[1] = (Config->get_initial_program_change() & 0x7f);
3443 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3445 } else if (p == "solo-mute-override") {
3446 // catch_up_on_solo_mute_override ();
3447 } else if (p == "listen-position" || p == "pfl-position") {
3448 listen_position_changed ();
3449 } else if (p == "solo-control-is-listen-control") {
3450 solo_control_mode_changed ();
3451 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3452 last_timecode_valid = false;
3453 } else if (p == "playback-buffer-seconds") {
3454 AudioSource::allocate_working_buffers (frame_rate());
3455 } else if (p == "automation-thinning-factor") {
3456 Evoral::ControlList::set_thinning_factor (Config->get_automation_thinning_factor());
3457 } else if (p == "ltc-source-port") {
3458 reconnect_ltc_input ();
3459 } else if (p == "ltc-sink-port") {
3460 reconnect_ltc_output ();
3461 } else if (p == "timecode-generator-offset") {
3462 ltc_tx_parse_offset();
3469 Session::set_history_depth (uint32_t d)
3471 _history.set_depth (d);
3475 Session::load_diskstreams_2X (XMLNode const & node, int)
3478 XMLNodeConstIterator citer;
3480 clist = node.children();
3482 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3485 /* diskstreams added automatically by DiskstreamCreated handler */
3486 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3487 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3488 _diskstreams_2X.push_back (dsp);
3490 error << _("Session: unknown diskstream type in XML") << endmsg;
3494 catch (failed_constructor& err) {
3495 error << _("Session: could not load diskstream via XML state") << endmsg;
3503 /** Connect things to the MMC object */
3505 Session::setup_midi_machine_control ()
3507 _mmc = new MIDI::MachineControl;
3508 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3510 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3511 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3512 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3513 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3514 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3515 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3516 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3517 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3518 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3519 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3520 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3521 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3522 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3524 /* also handle MIDI SPP because its so common */
3526 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3527 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3528 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3531 boost::shared_ptr<Controllable>
3532 Session::solo_cut_control() const
3534 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3535 controls in Ardour that currently get presented to the user in the GUI that require
3536 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3538 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3539 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3543 return _solo_cut_control;
3547 Session::rename (const std::string& new_name)
3549 string legal_name = legalize_for_path (new_name);
3555 string const old_sources_root = _session_dir->sources_root();
3560 * interchange subdirectory
3564 * Backup files are left unchanged and not renamed.
3567 /* pass one: not 100% safe check that the new directory names don't
3571 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3576 /* this is a stupid hack because Glib::path_get_dirname() is
3577 * lexical-only, and so passing it /a/b/c/ gives a different
3578 * result than passing it /a/b/c ...
3581 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3582 oldstr = oldstr.substr (0, oldstr.length() - 1);
3585 string base = Glib::path_get_dirname (oldstr);
3586 string p = Glib::path_get_basename (oldstr);
3588 newstr = Glib::build_filename (base, legal_name);
3590 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3597 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3602 /* this is a stupid hack because Glib::path_get_dirname() is
3603 * lexical-only, and so passing it /a/b/c/ gives a different
3604 * result than passing it /a/b/c ...
3607 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3608 oldstr = oldstr.substr (0, oldstr.length() - 1);
3611 string base = Glib::path_get_dirname (oldstr);
3612 string p = Glib::path_get_basename (oldstr);
3614 newstr = Glib::build_filename (base, legal_name);
3616 cerr << "Rename " << oldstr << " => " << newstr << endl;
3618 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3619 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3624 (*_session_dir) = newstr;
3629 /* directory below interchange */
3631 v.push_back (newstr);
3632 v.push_back (interchange_dir_name);
3635 oldstr = Glib::build_filename (v);
3638 v.push_back (newstr);
3639 v.push_back (interchange_dir_name);
3640 v.push_back (legal_name);
3642 newstr = Glib::build_filename (v);
3644 cerr << "Rename " << oldstr << " => " << newstr << endl;
3646 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3647 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3654 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3655 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3657 cerr << "Rename " << oldstr << " => " << newstr << endl;
3659 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3660 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3667 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3669 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3670 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3672 cerr << "Rename " << oldstr << " => " << newstr << endl;
3674 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3675 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3680 /* update file source paths */
3682 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3683 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3685 string p = fs->path ();
3686 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3691 /* remove old name from recent sessions */
3693 remove_recent_sessions (_path);
3696 _current_snapshot_name = new_name;
3699 /* re-add directory separator - reverse hack to oldstr above */
3700 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
3701 _path += G_DIR_SEPARATOR;
3706 /* save state again to get everything just right */
3708 save_state (_current_snapshot_name);
3711 /* add to recent sessions */
3713 store_recent_sessions (new_name, _path);
3719 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
3721 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
3725 if (!tree.read (xmlpath)) {
3733 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
3736 bool found_sr = false;
3737 bool found_data_format = false;
3739 if (get_session_info_from_path (tree, xmlpath)) {
3745 const XMLProperty* prop;
3746 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
3747 sample_rate = atoi (prop->value());
3751 const XMLNodeList& children (tree.root()->children());
3752 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
3753 const XMLNode* child = *c;
3754 if (child->name() == "Config") {
3755 const XMLNodeList& options (child->children());
3756 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
3757 const XMLNode* option = *oc;
3758 const XMLProperty* name = option->property("name");
3764 if (name->value() == "native-file-data-format") {
3765 const XMLProperty* value = option->property ("value");
3767 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
3769 found_data_format = true;
3775 if (found_data_format) {
3780 return !(found_sr && found_data_format); // zero if they are both found