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/pathscanner.h"
73 #include "pbd/pthread_utils.h"
74 #include "pbd/stacktrace.h"
75 #include "pbd/convert.h"
76 #include "pbd/clear_dir.h"
77 #include "pbd/localtime_r.h"
79 #include "ardour/amp.h"
80 #include "ardour/audio_diskstream.h"
81 #include "ardour/audio_track.h"
82 #include "ardour/audioengine.h"
83 #include "ardour/audiofilesource.h"
84 #include "ardour/audioregion.h"
85 #include "ardour/automation_control.h"
86 #include "ardour/butler.h"
87 #include "ardour/control_protocol_manager.h"
88 #include "ardour/directory_names.h"
89 #include "ardour/filename_extensions.h"
90 #include "ardour/graph.h"
91 #include "ardour/location.h"
92 #include "ardour/midi_model.h"
93 #include "ardour/midi_patch_manager.h"
94 #include "ardour/midi_region.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 char buf[PATH_MAX+1];
140 if (!realpath (fullpath.c_str(), buf) && (errno != ENOENT)) {
141 error << string_compose(_("Could not use path %1 (%2)"), buf, strerror(errno)) << endmsg;
143 throw failed_constructor();
148 /* we require _path to end with a dir separator */
150 if (_path[_path.length()-1] != G_DIR_SEPARATOR) {
151 _path += G_DIR_SEPARATOR;
156 _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
158 /* finish initialization that can't be done in a normal C++ constructor
162 timerclear (&last_mmc_step);
163 g_atomic_int_set (&processing_prohibited, 0);
164 g_atomic_int_set (&_record_status, Disabled);
165 g_atomic_int_set (&_playback_load, 100);
166 g_atomic_int_set (&_capture_load, 100);
168 _all_route_group->set_active (true, this);
169 interpolation.add_channel_to (0, 0);
171 if (config.get_use_video_sync()) {
172 waiting_for_sync_offset = true;
174 waiting_for_sync_offset = false;
177 last_rr_session_dir = session_dirs.begin();
179 set_history_depth (Config->get_history_depth());
181 /* default: assume simple stereo speaker configuration */
183 _speakers->setup_default_speakers (2);
185 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
186 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
187 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
188 add_controllable (_solo_cut_control);
190 /* These are all static "per-class" signals */
192 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
193 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
194 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
195 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
196 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
198 /* stop IO objects from doing stuff until we're ready for them */
200 Delivery::disable_panners ();
201 IO::disable_connecting ();
203 AudioFileSource::set_peak_dir (_session_dir->peak_path());
207 Session::post_engine_init ()
209 BootMessage (_("Set block size and sample rate"));
211 set_block_size (_engine.samples_per_cycle());
212 set_frame_rate (_engine.sample_rate());
214 BootMessage (_("Using configuration"));
216 _midi_ports = new MidiPortManager;
217 setup_midi_machine_control ();
219 if (_butler->start_thread()) {
223 if (start_midi_thread ()) {
227 setup_click_sounds (0);
228 setup_midi_control ();
230 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
231 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
234 /* tempo map requires sample rate knowledge */
236 _tempo_map = new TempoMap (_current_frame_rate);
237 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
239 /* MidiClock requires a tempo map */
241 midi_clock = new MidiClockTicker ();
242 midi_clock->set_session (this);
244 /* crossfades require sample rate knowledge */
246 SndFileSource::setup_standard_crossfades (*this, frame_rate());
247 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
249 AudioDiskstream::allocate_working_buffers();
250 refresh_disk_space ();
252 /* we're finally ready to call set_state() ... all objects have
253 * been created, the engine is running.
257 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
261 // set_state() will call setup_raid_path(), but if it's a new session we need
262 // to call setup_raid_path() here.
263 setup_raid_path (_path);
268 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
269 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
271 Config->map_parameters (ff);
272 config.map_parameters (ft);
274 /* Reset all panners */
276 Delivery::reset_panners ();
278 /* this will cause the CPM to instantiate any protocols that are in use
279 * (or mandatory), which will pass it this Session, and then call
280 * set_state() on each instantiated protocol to match stored state.
283 ControlProtocolManager::instance().set_session (this);
285 /* This must be done after the ControlProtocolManager set_session above,
286 as it will set states for ports which the ControlProtocolManager creates.
289 // XXX set state of MIDI::Port's
290 // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
292 /* And this must be done after the MIDI::Manager::set_port_states as
293 * it will try to make connections whose details are loaded by set_port_states.
298 /* Let control protocols know that we are now all connected, so they
299 * could start talking to surfaces if they want to.
302 ControlProtocolManager::instance().midi_connectivity_established ();
304 if (_is_new && !no_auto_connect()) {
305 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
306 auto_connect_master_bus ();
309 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
311 /* update latencies */
313 initialize_latencies ();
315 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
316 _locations->added.connect_same_thread (*this, boost::bind (&Session::locations_added, this, _1));
318 } catch (AudioEngine::PortRegistrationFailure& err) {
319 /* handle this one in a different way than all others, so that its clear what happened */
320 error << err.what() << endmsg;
326 BootMessage (_("Reset Remote Controls"));
328 // send_full_time_code (0);
329 _engine.transport_locate (0);
331 _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
332 _mmc->send (MIDI::MachineControlCommand (Timecode::Time ()));
334 MIDI::Name::MidiPatchManager::instance().set_session (this);
337 /* initial program change will be delivered later; see ::config_changed() */
339 _state_of_the_state = Clean;
341 Port::set_connecting_blocked (false);
343 DirtyChanged (); /* EMIT SIGNAL */
347 } else if (state_was_pending) {
349 remove_pending_capture_state ();
350 state_was_pending = false;
357 Session::raid_path () const
359 Searchpath raid_search_path;
361 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
362 raid_search_path += (*i).path;
365 return raid_search_path.to_string ();
369 Session::setup_raid_path (string path)
378 session_dirs.clear ();
380 Searchpath search_path(path);
381 Searchpath sound_search_path;
382 Searchpath midi_search_path;
384 for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
386 sp.blocks = 0; // not needed
387 session_dirs.push_back (sp);
389 SessionDirectory sdir(sp.path);
391 sound_search_path += sdir.sound_path ();
392 midi_search_path += sdir.midi_path ();
395 // reset the round-robin soundfile path thingie
396 last_rr_session_dir = session_dirs.begin();
400 Session::path_is_within_session (const std::string& path)
402 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
403 if (PBD::path_is_within (i->path, path)) {
411 Session::ensure_subdirs ()
415 dir = session_directory().peak_path();
417 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
418 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
422 dir = session_directory().sound_path();
424 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
425 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
429 dir = session_directory().midi_path();
431 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
432 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
436 dir = session_directory().dead_path();
438 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
439 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
443 dir = session_directory().export_path();
445 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
446 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
450 dir = analysis_dir ();
452 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
453 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
457 dir = plugins_dir ();
459 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
460 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
464 dir = externals_dir ();
466 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
467 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
474 /** @param session_template directory containing session template, or empty.
475 * Caller must not hold process lock.
478 Session::create (const string& session_template, BusProfile* bus_profile)
480 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
481 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
485 if (ensure_subdirs ()) {
489 _writable = exists_and_writable (_path);
491 if (!session_template.empty()) {
492 std::string in_path = session_template_dir_to_file (session_template);
494 ifstream in(in_path.c_str());
497 /* no need to call legalize_for_path() since the string
498 * in session_template is already a legal path name
500 string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
502 ofstream out(out_path.c_str());
508 /* Copy plugin state files from template to new session */
509 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
510 copy_files (template_plugins, plugins_dir ());
515 error << string_compose (_("Could not open %1 for writing session template"), out_path)
521 error << string_compose (_("Could not open session template %1 for reading"), in_path)
528 /* set initial start + end point */
530 _state_of_the_state = Clean;
532 /* set up Master Out and Control Out if necessary */
537 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
539 if (bus_profile->master_out_channels) {
540 boost::shared_ptr<Route> r (new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO));
544 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
545 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
548 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
549 r->input()->ensure_io (count, false, this);
550 r->output()->ensure_io (count, false, this);
556 /* prohibit auto-connect to master, because there isn't one */
557 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
561 add_routes (rl, false, false, false);
564 /* this allows the user to override settings with an environment variable.
567 if (no_auto_connect()) {
568 bus_profile->input_ac = AutoConnectOption (0);
569 bus_profile->output_ac = AutoConnectOption (0);
572 Config->set_input_auto_connect (bus_profile->input_ac);
573 Config->set_output_auto_connect (bus_profile->output_ac);
576 if (Config->get_use_monitor_bus() && bus_profile) {
577 add_monitor_section ();
584 Session::maybe_write_autosave()
586 if (dirty() && record_status() != Recording) {
587 save_state("", true);
592 Session::remove_pending_capture_state ()
594 std::string pending_state_file_path(_session_dir->root_path());
596 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
598 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
600 if (g_remove (pending_state_file_path.c_str()) != 0) {
601 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
602 pending_state_file_path, g_strerror (errno)) << endmsg;
606 /** Rename a state file.
607 * @param old_name Old snapshot name.
608 * @param new_name New snapshot name.
611 Session::rename_state (string old_name, string new_name)
613 if (old_name == _current_snapshot_name || old_name == _name) {
614 /* refuse to rename the current snapshot or the "main" one */
618 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
619 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
621 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
622 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
624 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
625 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
626 old_name, new_name, g_strerror(errno)) << endmsg;
630 /** Remove a state file.
631 * @param snapshot_name Snapshot name.
634 Session::remove_state (string snapshot_name)
636 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
637 // refuse to remove the current snapshot or the "main" one
641 std::string xml_path(_session_dir->root_path());
643 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
645 if (!create_backup_file (xml_path)) {
646 // don't remove it if a backup can't be made
647 // create_backup_file will log the error.
652 if (g_remove (xml_path.c_str()) != 0) {
653 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
654 xml_path, g_strerror (errno)) << endmsg;
658 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
660 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot)
663 std::string xml_path(_session_dir->root_path());
665 if (!_writable || (_state_of_the_state & CannotSave)) {
669 if (!_engine.connected ()) {
670 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
676 /* tell sources we're saving first, in case they write out to a new file
677 * which should be saved with the state rather than the old one */
678 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
680 i->second->session_saved();
681 } catch (Evoral::SMF::FileError& e) {
682 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
686 SaveSession (); /* EMIT SIGNAL */
688 tree.set_root (&get_state());
690 if (snapshot_name.empty()) {
691 snapshot_name = _current_snapshot_name;
692 } else if (switch_to_snapshot) {
693 _current_snapshot_name = snapshot_name;
698 /* proper save: use statefile_suffix (.ardour in English) */
700 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
702 /* make a backup copy of the old file */
704 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
705 // create_backup_file will log the error
711 /* pending save: use pending_suffix (.pending in English) */
712 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
715 std::string tmp_path(_session_dir->root_path());
716 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
718 // cerr << "actually writing state to " << xml_path << endl;
720 if (!tree.write (tmp_path)) {
721 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
722 if (g_remove (tmp_path.c_str()) != 0) {
723 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
724 tmp_path, g_strerror (errno)) << endmsg;
730 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
731 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
732 tmp_path, xml_path, g_strerror(errno)) << endmsg;
733 if (g_remove (tmp_path.c_str()) != 0) {
734 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
735 tmp_path, g_strerror (errno)) << endmsg;
743 save_history (snapshot_name);
745 bool was_dirty = dirty();
747 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
750 DirtyChanged (); /* EMIT SIGNAL */
753 StateSaved (snapshot_name); /* EMIT SIGNAL */
760 Session::restore_state (string snapshot_name)
762 if (load_state (snapshot_name) == 0) {
763 set_state (*state_tree->root(), Stateful::loading_state_version);
770 Session::load_state (string snapshot_name)
775 state_was_pending = false;
777 /* check for leftover pending state from a crashed capture attempt */
779 std::string xmlpath(_session_dir->root_path());
780 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
782 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
784 /* there is pending state from a crashed capture attempt */
786 boost::optional<int> r = AskAboutPendingState();
787 if (r.get_value_or (1)) {
788 state_was_pending = true;
792 if (!state_was_pending) {
793 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
796 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
797 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
798 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
799 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
804 state_tree = new XMLTree;
808 _writable = exists_and_writable (xmlpath);
810 if (!state_tree->read (xmlpath)) {
811 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
817 XMLNode& root (*state_tree->root());
819 if (root.name() != X_("Session")) {
820 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
826 const XMLProperty* prop;
828 if ((prop = root.property ("version")) == 0) {
829 /* no version implies very old version of Ardour */
830 Stateful::loading_state_version = 1000;
832 if (prop->value().find ('.') != string::npos) {
833 /* old school version format */
834 if (prop->value()[0] == '2') {
835 Stateful::loading_state_version = 2000;
837 Stateful::loading_state_version = 3000;
840 Stateful::loading_state_version = atoi (prop->value());
844 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
846 std::string backup_path(_session_dir->root_path());
847 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
848 backup_path = Glib::build_filename (backup_path, backup_filename);
850 // only create a backup for a given statefile version once
852 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
854 VersionMismatch (xmlpath, backup_path);
856 if (!copy_file (xmlpath, backup_path)) {;
866 Session::load_options (const XMLNode& node)
868 LocaleGuard lg (X_("POSIX"));
869 config.set_variables (node);
880 Session::get_template()
882 /* if we don't disable rec-enable, diskstreams
883 will believe they need to store their capture
884 sources in their state node.
887 disable_record (false);
893 Session::state (bool full_state)
895 XMLNode* node = new XMLNode("Session");
899 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
900 node->add_property("version", buf);
902 /* store configuration settings */
906 node->add_property ("name", _name);
907 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
908 node->add_property ("sample-rate", buf);
910 if (session_dirs.size() > 1) {
914 vector<space_and_path>::iterator i = session_dirs.begin();
915 vector<space_and_path>::iterator next;
917 ++i; /* skip the first one */
921 while (i != session_dirs.end()) {
925 if (next != session_dirs.end()) {
935 child = node->add_child ("Path");
936 child->add_content (p);
940 /* save the ID counter */
942 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
943 node->add_property ("id-counter", buf);
945 /* save the event ID counter */
947 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
948 node->add_property ("event-counter", buf);
950 /* various options */
952 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
953 if (!midi_port_nodes.empty()) {
954 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
955 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
956 midi_port_stuff->add_child_nocopy (**n);
958 node->add_child_nocopy (*midi_port_stuff);
961 node->add_child_nocopy (config.get_variables ());
963 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
965 child = node->add_child ("Sources");
968 Glib::Threads::Mutex::Lock sl (source_lock);
970 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
972 /* Don't save information about non-file Sources, or
973 * about non-destructive file sources that are empty
974 * and unused by any regions.
977 boost::shared_ptr<FileSource> fs;
979 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
981 if (!fs->destructive()) {
982 if (fs->empty() && !fs->used()) {
987 child->add_child_nocopy (siter->second->get_state());
992 child = node->add_child ("Regions");
995 Glib::Threads::Mutex::Lock rl (region_lock);
996 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
997 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
998 boost::shared_ptr<Region> r = i->second;
999 /* only store regions not attached to playlists */
1000 if (r->playlist() == 0) {
1001 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1002 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1004 child->add_child_nocopy (r->get_state ());
1009 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1011 if (!cassocs.empty()) {
1012 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1014 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1016 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1017 i->first->id().print (buf, sizeof (buf));
1018 can->add_property (X_("copy"), buf);
1019 i->second->id().print (buf, sizeof (buf));
1020 can->add_property (X_("original"), buf);
1021 ca->add_child_nocopy (*can);
1027 node->add_child_nocopy (_locations->get_state());
1029 // for a template, just create a new Locations, populate it
1030 // with the default start and end, and get the state for that.
1031 Locations loc (*this);
1032 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1033 range->set (max_framepos, 0);
1035 node->add_child_nocopy (loc.get_state());
1038 child = node->add_child ("Bundles");
1040 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1041 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1042 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1044 child->add_child_nocopy (b->get_state());
1049 child = node->add_child ("Routes");
1051 boost::shared_ptr<RouteList> r = routes.reader ();
1053 RoutePublicOrderSorter cmp;
1054 RouteList public_order (*r);
1055 public_order.sort (cmp);
1057 /* the sort should have put control outs first */
1060 assert (_monitor_out == public_order.front());
1063 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1064 if (!(*i)->is_auditioner()) {
1066 child->add_child_nocopy ((*i)->get_state());
1068 child->add_child_nocopy ((*i)->get_template());
1074 playlists->add_state (node, full_state);
1076 child = node->add_child ("RouteGroups");
1077 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1078 child->add_child_nocopy ((*i)->get_state());
1082 XMLNode* gain_child = node->add_child ("Click");
1083 gain_child->add_child_nocopy (_click_io->state (full_state));
1084 gain_child->add_child_nocopy (_click_gain->state (full_state));
1088 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1089 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1093 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1094 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1097 node->add_child_nocopy (_speakers->get_state());
1098 node->add_child_nocopy (_tempo_map->get_state());
1099 node->add_child_nocopy (get_control_protocol_state());
1102 node->add_child_copy (*_extra_xml);
1109 Session::get_control_protocol_state ()
1111 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1112 return cpm.get_state();
1116 Session::set_state (const XMLNode& node, int version)
1120 const XMLProperty* prop;
1123 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1125 if (node.name() != X_("Session")) {
1126 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1130 if ((prop = node.property ("name")) != 0) {
1131 _name = prop->value ();
1134 if ((prop = node.property (X_("sample-rate"))) != 0) {
1136 _nominal_frame_rate = atoi (prop->value());
1138 if (_nominal_frame_rate != _current_frame_rate) {
1139 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1140 if (r.get_value_or (0)) {
1146 setup_raid_path(_session_dir->root_path());
1148 if ((prop = node.property (X_("id-counter"))) != 0) {
1150 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1151 ID::init_counter (x);
1153 /* old sessions used a timebased counter, so fake
1154 the startup ID counter based on a standard
1159 ID::init_counter (now);
1162 if ((prop = node.property (X_("event-counter"))) != 0) {
1163 Evoral::init_event_id_counter (atoi (prop->value()));
1167 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1168 _midi_ports->set_midi_port_states (child->children());
1171 IO::disable_connecting ();
1173 Stateful::save_extra_xml (node);
1175 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1176 load_options (*child);
1177 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1178 load_options (*child);
1180 error << _("Session: XML state has no options section") << endmsg;
1183 if (version >= 3000) {
1184 if ((child = find_named_node (node, "Metadata")) == 0) {
1185 warning << _("Session: XML state has no metadata section") << endmsg;
1186 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1191 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1192 _speakers->set_state (*child, version);
1195 if ((child = find_named_node (node, "Sources")) == 0) {
1196 error << _("Session: XML state has no sources section") << endmsg;
1198 } else if (load_sources (*child)) {
1202 if ((child = find_named_node (node, "TempoMap")) == 0) {
1203 error << _("Session: XML state has no Tempo Map section") << endmsg;
1205 } else if (_tempo_map->set_state (*child, version)) {
1209 if ((child = find_named_node (node, "Locations")) == 0) {
1210 error << _("Session: XML state has no locations section") << endmsg;
1212 } else if (_locations->set_state (*child, version)) {
1218 if ((location = _locations->auto_loop_location()) != 0) {
1219 set_auto_loop_location (location);
1222 if ((location = _locations->auto_punch_location()) != 0) {
1223 set_auto_punch_location (location);
1226 if ((location = _locations->session_range_location()) != 0) {
1227 delete _session_range_location;
1228 _session_range_location = location;
1231 if (_session_range_location) {
1232 AudioFileSource::set_header_position_offset (_session_range_location->start());
1235 if ((child = find_named_node (node, "Regions")) == 0) {
1236 error << _("Session: XML state has no Regions section") << endmsg;
1238 } else if (load_regions (*child)) {
1242 if ((child = find_named_node (node, "Playlists")) == 0) {
1243 error << _("Session: XML state has no playlists section") << endmsg;
1245 } else if (playlists->load (*this, *child)) {
1249 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1251 } else if (playlists->load_unused (*this, *child)) {
1255 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1256 if (load_compounds (*child)) {
1261 if (version >= 3000) {
1262 if ((child = find_named_node (node, "Bundles")) == 0) {
1263 warning << _("Session: XML state has no bundles section") << endmsg;
1266 /* We can't load Bundles yet as they need to be able
1267 to convert from port names to Port objects, which can't happen until
1269 _bundle_xml_node = new XMLNode (*child);
1273 if (version < 3000) {
1274 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1275 error << _("Session: XML state has no diskstreams section") << endmsg;
1277 } else if (load_diskstreams_2X (*child, version)) {
1282 if ((child = find_named_node (node, "Routes")) == 0) {
1283 error << _("Session: XML state has no routes section") << endmsg;
1285 } else if (load_routes (*child, version)) {
1289 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1290 _diskstreams_2X.clear ();
1292 if (version >= 3000) {
1294 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1295 error << _("Session: XML state has no route groups section") << endmsg;
1297 } else if (load_route_groups (*child, version)) {
1301 } else if (version < 3000) {
1303 if ((child = find_named_node (node, "EditGroups")) == 0) {
1304 error << _("Session: XML state has no edit groups section") << endmsg;
1306 } else if (load_route_groups (*child, version)) {
1310 if ((child = find_named_node (node, "MixGroups")) == 0) {
1311 error << _("Session: XML state has no mix groups section") << endmsg;
1313 } else if (load_route_groups (*child, version)) {
1318 if ((child = find_named_node (node, "Click")) == 0) {
1319 warning << _("Session: XML state has no click section") << endmsg;
1320 } else if (_click_io) {
1321 setup_click_state (node);
1324 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1325 ControlProtocolManager::instance().set_state (*child, version);
1328 update_have_rec_enabled_track ();
1330 /* here beginneth the second phase ... */
1332 StateReady (); /* EMIT SIGNAL */
1341 Session::load_routes (const XMLNode& node, int version)
1344 XMLNodeConstIterator niter;
1345 RouteList new_routes;
1347 nlist = node.children();
1351 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1353 boost::shared_ptr<Route> route;
1354 if (version < 3000) {
1355 route = XMLRouteFactory_2X (**niter, version);
1357 route = XMLRouteFactory (**niter, version);
1361 error << _("Session: cannot create Route from XML description.") << endmsg;
1365 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1367 new_routes.push_back (route);
1370 add_routes (new_routes, false, false, false);
1375 boost::shared_ptr<Route>
1376 Session::XMLRouteFactory (const XMLNode& node, int version)
1378 boost::shared_ptr<Route> ret;
1380 if (node.name() != "Route") {
1384 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1386 DataType type = DataType::AUDIO;
1387 const XMLProperty* prop = node.property("default-type");
1390 type = DataType (prop->value());
1393 assert (type != DataType::NIL);
1397 boost::shared_ptr<Track> track;
1399 if (type == DataType::AUDIO) {
1400 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1402 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1405 if (track->init()) {
1409 if (track->set_state (node, version)) {
1413 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1414 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1419 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1421 if (r->init () == 0 && r->set_state (node, version) == 0) {
1422 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1423 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1432 boost::shared_ptr<Route>
1433 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1435 boost::shared_ptr<Route> ret;
1437 if (node.name() != "Route") {
1441 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1443 ds_prop = node.property (X_("diskstream"));
1446 DataType type = DataType::AUDIO;
1447 const XMLProperty* prop = node.property("default-type");
1450 type = DataType (prop->value());
1453 assert (type != DataType::NIL);
1457 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1458 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1462 if (i == _diskstreams_2X.end()) {
1463 error << _("Could not find diskstream for route") << endmsg;
1464 return boost::shared_ptr<Route> ();
1467 boost::shared_ptr<Track> track;
1469 if (type == DataType::AUDIO) {
1470 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1472 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1475 if (track->init()) {
1479 if (track->set_state (node, version)) {
1483 track->set_diskstream (*i);
1485 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1486 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1491 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML")));
1493 if (r->init () == 0 && r->set_state (node, version) == 0) {
1494 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1495 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1505 Session::load_regions (const XMLNode& node)
1508 XMLNodeConstIterator niter;
1509 boost::shared_ptr<Region> region;
1511 nlist = node.children();
1515 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1516 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1517 error << _("Session: cannot create Region from XML description.");
1518 const XMLProperty *name = (**niter).property("name");
1521 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1532 Session::load_compounds (const XMLNode& node)
1534 XMLNodeList calist = node.children();
1535 XMLNodeConstIterator caiter;
1536 XMLProperty *caprop;
1538 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1539 XMLNode* ca = *caiter;
1543 if ((caprop = ca->property (X_("original"))) == 0) {
1546 orig_id = caprop->value();
1548 if ((caprop = ca->property (X_("copy"))) == 0) {
1551 copy_id = caprop->value();
1553 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1554 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1556 if (!orig || !copy) {
1557 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1563 RegionFactory::add_compound_association (orig, copy);
1570 Session::load_nested_sources (const XMLNode& node)
1573 XMLNodeConstIterator niter;
1575 nlist = node.children();
1577 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1578 if ((*niter)->name() == "Source") {
1580 /* it may already exist, so don't recreate it unnecessarily
1583 XMLProperty* prop = (*niter)->property (X_("id"));
1585 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1589 ID source_id (prop->value());
1591 if (!source_by_id (source_id)) {
1594 SourceFactory::create (*this, **niter, true);
1596 catch (failed_constructor& err) {
1597 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1604 boost::shared_ptr<Region>
1605 Session::XMLRegionFactory (const XMLNode& node, bool full)
1607 const XMLProperty* type = node.property("type");
1611 const XMLNodeList& nlist = node.children();
1613 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1614 XMLNode *child = (*niter);
1615 if (child->name() == "NestedSource") {
1616 load_nested_sources (*child);
1620 if (!type || type->value() == "audio") {
1621 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1622 } else if (type->value() == "midi") {
1623 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1626 } catch (failed_constructor& err) {
1627 return boost::shared_ptr<Region> ();
1630 return boost::shared_ptr<Region> ();
1633 boost::shared_ptr<AudioRegion>
1634 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1636 const XMLProperty* prop;
1637 boost::shared_ptr<Source> source;
1638 boost::shared_ptr<AudioSource> as;
1640 SourceList master_sources;
1641 uint32_t nchans = 1;
1644 if (node.name() != X_("Region")) {
1645 return boost::shared_ptr<AudioRegion>();
1648 if ((prop = node.property (X_("channels"))) != 0) {
1649 nchans = atoi (prop->value().c_str());
1652 if ((prop = node.property ("name")) == 0) {
1653 cerr << "no name for this region\n";
1657 if ((prop = node.property (X_("source-0"))) == 0) {
1658 if ((prop = node.property ("source")) == 0) {
1659 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1660 return boost::shared_ptr<AudioRegion>();
1664 PBD::ID s_id (prop->value());
1666 if ((source = source_by_id (s_id)) == 0) {
1667 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1668 return boost::shared_ptr<AudioRegion>();
1671 as = boost::dynamic_pointer_cast<AudioSource>(source);
1673 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1674 return boost::shared_ptr<AudioRegion>();
1677 sources.push_back (as);
1679 /* pickup other channels */
1681 for (uint32_t n=1; n < nchans; ++n) {
1682 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1683 if ((prop = node.property (buf)) != 0) {
1685 PBD::ID id2 (prop->value());
1687 if ((source = source_by_id (id2)) == 0) {
1688 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1689 return boost::shared_ptr<AudioRegion>();
1692 as = boost::dynamic_pointer_cast<AudioSource>(source);
1694 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1695 return boost::shared_ptr<AudioRegion>();
1697 sources.push_back (as);
1701 for (uint32_t n = 0; n < nchans; ++n) {
1702 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1703 if ((prop = node.property (buf)) != 0) {
1705 PBD::ID id2 (prop->value());
1707 if ((source = source_by_id (id2)) == 0) {
1708 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1709 return boost::shared_ptr<AudioRegion>();
1712 as = boost::dynamic_pointer_cast<AudioSource>(source);
1714 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1715 return boost::shared_ptr<AudioRegion>();
1717 master_sources.push_back (as);
1722 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1724 /* a final detail: this is the one and only place that we know how long missing files are */
1726 if (region->whole_file()) {
1727 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1728 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1730 sfp->set_length (region->length());
1735 if (!master_sources.empty()) {
1736 if (master_sources.size() != nchans) {
1737 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1739 region->set_master_sources (master_sources);
1747 catch (failed_constructor& err) {
1748 return boost::shared_ptr<AudioRegion>();
1752 boost::shared_ptr<MidiRegion>
1753 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1755 const XMLProperty* prop;
1756 boost::shared_ptr<Source> source;
1757 boost::shared_ptr<MidiSource> ms;
1760 if (node.name() != X_("Region")) {
1761 return boost::shared_ptr<MidiRegion>();
1764 if ((prop = node.property ("name")) == 0) {
1765 cerr << "no name for this region\n";
1769 if ((prop = node.property (X_("source-0"))) == 0) {
1770 if ((prop = node.property ("source")) == 0) {
1771 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1772 return boost::shared_ptr<MidiRegion>();
1776 PBD::ID s_id (prop->value());
1778 if ((source = source_by_id (s_id)) == 0) {
1779 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1780 return boost::shared_ptr<MidiRegion>();
1783 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1785 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1786 return boost::shared_ptr<MidiRegion>();
1789 sources.push_back (ms);
1792 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1793 /* a final detail: this is the one and only place that we know how long missing files are */
1795 if (region->whole_file()) {
1796 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1797 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1799 sfp->set_length (region->length());
1807 catch (failed_constructor& err) {
1808 return boost::shared_ptr<MidiRegion>();
1813 Session::get_sources_as_xml ()
1816 XMLNode* node = new XMLNode (X_("Sources"));
1817 Glib::Threads::Mutex::Lock lm (source_lock);
1819 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1820 node->add_child_nocopy (i->second->get_state());
1827 Session::path_from_region_name (DataType type, string name, string identifier)
1829 char buf[PATH_MAX+1];
1831 SessionDirectory sdir(get_best_session_directory_for_new_source());
1832 std::string source_dir = ((type == DataType::AUDIO)
1833 ? sdir.sound_path() : sdir.midi_path());
1835 string ext = native_header_format_extension (config.get_native_file_header_format(), type);
1837 for (n = 0; n < 999999; ++n) {
1838 if (identifier.length()) {
1839 snprintf (buf, sizeof(buf), "%s%s%" PRIu32 "%s", name.c_str(),
1840 identifier.c_str(), n, ext.c_str());
1842 snprintf (buf, sizeof(buf), "%s-%" PRIu32 "%s", name.c_str(),
1846 std::string source_path = Glib::build_filename (source_dir, buf);
1848 if (!Glib::file_test (source_path, Glib::FILE_TEST_EXISTS)) {
1853 error << string_compose (_("cannot create new file from region name \"%1\" with ident = \"%2\": too many existing files with similar names"),
1862 Session::load_sources (const XMLNode& node)
1865 XMLNodeConstIterator niter;
1866 boost::shared_ptr<Source> source;
1868 nlist = node.children();
1872 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1875 if ((source = XMLSourceFactory (**niter)) == 0) {
1876 error << _("Session: cannot create Source from XML description.") << endmsg;
1879 } catch (MissingSource& err) {
1883 if (!no_questions_about_missing_files) {
1884 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1889 switch (user_choice) {
1891 /* user added a new search location, so try again */
1896 /* user asked to quit the entire session load
1901 no_questions_about_missing_files = true;
1905 no_questions_about_missing_files = true;
1910 warning << _("A sound file is missing. It will be replaced by silence.") << endmsg;
1911 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1920 boost::shared_ptr<Source>
1921 Session::XMLSourceFactory (const XMLNode& node)
1923 if (node.name() != "Source") {
1924 return boost::shared_ptr<Source>();
1928 /* note: do peak building in another thread when loading session state */
1929 return SourceFactory::create (*this, node, true);
1932 catch (failed_constructor& err) {
1933 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the progammers."), PROGRAM_NAME) << endmsg;
1934 return boost::shared_ptr<Source>();
1939 Session::save_template (string template_name)
1943 if (_state_of_the_state & CannotSave) {
1947 std::string user_template_dir(user_template_directory());
1949 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
1950 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
1951 user_template_dir, g_strerror (errno)) << endmsg;
1955 tree.set_root (&get_template());
1957 std::string template_dir_path(user_template_dir);
1959 /* directory to put the template in */
1960 template_dir_path = Glib::build_filename (template_dir_path, template_name);
1962 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
1963 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
1964 template_dir_path) << endmsg;
1968 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
1969 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
1970 template_dir_path, g_strerror (errno)) << endmsg;
1975 std::string template_file_path(template_dir_path);
1976 template_file_path = Glib::build_filename (template_file_path, template_name + template_suffix);
1978 if (!tree.write (template_file_path)) {
1979 error << _("template not saved") << endmsg;
1983 /* copy plugin state directory */
1985 std::string template_plugin_state_path(template_dir_path);
1986 template_plugin_state_path = Glib::build_filename (template_plugin_state_path, X_("plugins"));
1988 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
1989 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
1990 template_plugin_state_path, g_strerror (errno)) << endmsg;
1994 copy_files (plugins_dir(), template_plugin_state_path);
2000 Session::refresh_disk_space ()
2002 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2004 Glib::Threads::Mutex::Lock lm (space_lock);
2006 /* get freespace on every FS that is part of the session path */
2008 _total_free_4k_blocks = 0;
2009 _total_free_4k_blocks_uncertain = false;
2011 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2013 struct statfs statfsbuf;
2014 statfs (i->path.c_str(), &statfsbuf);
2016 double const scale = statfsbuf.f_bsize / 4096.0;
2018 /* See if this filesystem is read-only */
2019 struct statvfs statvfsbuf;
2020 statvfs (i->path.c_str(), &statvfsbuf);
2022 /* f_bavail can be 0 if it is undefined for whatever
2023 filesystem we are looking at; Samba shares mounted
2024 via GVFS are an example of this.
2026 if (statfsbuf.f_bavail == 0) {
2027 /* block count unknown */
2029 i->blocks_unknown = true;
2030 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2031 /* read-only filesystem */
2033 i->blocks_unknown = false;
2035 /* read/write filesystem with known space */
2036 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2037 i->blocks_unknown = false;
2040 _total_free_4k_blocks += i->blocks;
2041 if (i->blocks_unknown) {
2042 _total_free_4k_blocks_uncertain = true;
2045 #elif defined (COMPILER_MSVC)
2046 vector<string> scanned_volumes;
2047 vector<string>::iterator j;
2048 vector<space_and_path>::iterator i;
2049 DWORD nSectorsPerCluster, nBytesPerSector,
2050 nFreeClusters, nTotalClusters;
2054 _total_free_4k_blocks = 0;
2056 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2057 strncpy (disk_drive, (*i).path.c_str(), 3);
2061 volume_found = false;
2062 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2064 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2065 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2066 i->blocks = (uint32_t)(nFreeBytes / 4096);
2068 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2069 if (0 == j->compare(disk_drive)) {
2070 volume_found = true;
2075 if (!volume_found) {
2076 scanned_volumes.push_back(disk_drive);
2077 _total_free_4k_blocks += i->blocks;
2082 if (0 == _total_free_4k_blocks) {
2083 strncpy (disk_drive, path().c_str(), 3);
2086 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2088 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2089 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2090 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2097 Session::get_best_session_directory_for_new_source ()
2099 vector<space_and_path>::iterator i;
2100 string result = _session_dir->root_path();
2102 /* handle common case without system calls */
2104 if (session_dirs.size() == 1) {
2108 /* OK, here's the algorithm we're following here:
2110 We want to select which directory to use for
2111 the next file source to be created. Ideally,
2112 we'd like to use a round-robin process so as to
2113 get maximum performance benefits from splitting
2114 the files across multiple disks.
2116 However, in situations without much diskspace, an
2117 RR approach may end up filling up a filesystem
2118 with new files while others still have space.
2119 Its therefore important to pay some attention to
2120 the freespace in the filesystem holding each
2121 directory as well. However, if we did that by
2122 itself, we'd keep creating new files in the file
2123 system with the most space until it was as full
2124 as all others, thus negating any performance
2125 benefits of this RAID-1 like approach.
2127 So, we use a user-configurable space threshold. If
2128 there are at least 2 filesystems with more than this
2129 much space available, we use RR selection between them.
2130 If not, then we pick the filesystem with the most space.
2132 This gets a good balance between the two
2136 refresh_disk_space ();
2138 int free_enough = 0;
2140 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2141 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2146 if (free_enough >= 2) {
2147 /* use RR selection process, ensuring that the one
2151 i = last_rr_session_dir;
2154 if (++i == session_dirs.end()) {
2155 i = session_dirs.begin();
2158 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2159 SessionDirectory sdir(i->path);
2160 if (sdir.create ()) {
2162 last_rr_session_dir = i;
2167 } while (i != last_rr_session_dir);
2171 /* pick FS with the most freespace (and that
2172 seems to actually work ...)
2175 vector<space_and_path> sorted;
2176 space_and_path_ascending_cmp cmp;
2178 sorted = session_dirs;
2179 sort (sorted.begin(), sorted.end(), cmp);
2181 for (i = sorted.begin(); i != sorted.end(); ++i) {
2182 SessionDirectory sdir(i->path);
2183 if (sdir.create ()) {
2185 last_rr_session_dir = i;
2195 Session::automation_dir () const
2197 return Glib::build_filename (_path, "automation");
2201 Session::analysis_dir () const
2203 return Glib::build_filename (_path, "analysis");
2207 Session::plugins_dir () const
2209 return Glib::build_filename (_path, "plugins");
2213 Session::externals_dir () const
2215 return Glib::build_filename (_path, "externals");
2219 Session::load_bundles (XMLNode const & node)
2221 XMLNodeList nlist = node.children();
2222 XMLNodeConstIterator niter;
2226 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2227 if ((*niter)->name() == "InputBundle") {
2228 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2229 } else if ((*niter)->name() == "OutputBundle") {
2230 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2232 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2241 Session::load_route_groups (const XMLNode& node, int version)
2243 XMLNodeList nlist = node.children();
2244 XMLNodeConstIterator niter;
2248 if (version >= 3000) {
2250 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2251 if ((*niter)->name() == "RouteGroup") {
2252 RouteGroup* rg = new RouteGroup (*this, "");
2253 add_route_group (rg);
2254 rg->set_state (**niter, version);
2258 } else if (version < 3000) {
2260 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2261 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2262 RouteGroup* rg = new RouteGroup (*this, "");
2263 add_route_group (rg);
2264 rg->set_state (**niter, version);
2273 Session::auto_save()
2275 save_state (_current_snapshot_name);
2279 state_file_filter (const string &str, void* /*arg*/)
2281 return (str.length() > strlen(statefile_suffix) &&
2282 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2286 bool operator()(const string* a, const string* b) {
2292 remove_end(string* state)
2294 string statename(*state);
2296 string::size_type start,end;
2297 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2298 statename = statename.substr (start+1);
2301 if ((end = statename.rfind(".ardour")) == string::npos) {
2302 end = statename.length();
2305 return new string(statename.substr (0, end));
2309 Session::possible_states (string path)
2311 PathScanner scanner;
2312 vector<string*>* states = scanner (path, state_file_filter, 0, false, false);
2314 transform(states->begin(), states->end(), states->begin(), remove_end);
2317 sort (states->begin(), states->end(), cmp);
2323 Session::possible_states () const
2325 return possible_states(_path);
2329 Session::add_route_group (RouteGroup* g)
2331 _route_groups.push_back (g);
2332 route_group_added (g); /* EMIT SIGNAL */
2334 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2335 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2336 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2342 Session::remove_route_group (RouteGroup& rg)
2344 list<RouteGroup*>::iterator i;
2346 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2347 _route_groups.erase (i);
2350 route_group_removed (); /* EMIT SIGNAL */
2354 /** Set a new order for our route groups, without adding or removing any.
2355 * @param groups Route group list in the new order.
2358 Session::reorder_route_groups (list<RouteGroup*> groups)
2360 _route_groups = groups;
2362 route_groups_reordered (); /* EMIT SIGNAL */
2368 Session::route_group_by_name (string name)
2370 list<RouteGroup *>::iterator i;
2372 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2373 if ((*i)->name() == name) {
2381 Session::all_route_group() const
2383 return *_all_route_group;
2387 Session::add_commands (vector<Command*> const & cmds)
2389 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2395 Session::begin_reversible_command (const string& name)
2397 begin_reversible_command (g_quark_from_string (name.c_str ()));
2400 /** Begin a reversible command using a GQuark to identify it.
2401 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2402 * but there must be as many begin...()s as there are commit...()s.
2405 Session::begin_reversible_command (GQuark q)
2407 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2408 to hold all the commands that are committed. This keeps the order of
2409 commands correct in the history.
2412 if (_current_trans == 0) {
2413 /* start a new transaction */
2414 assert (_current_trans_quarks.empty ());
2415 _current_trans = new UndoTransaction();
2416 _current_trans->set_name (g_quark_to_string (q));
2419 _current_trans_quarks.push_front (q);
2423 Session::commit_reversible_command (Command *cmd)
2425 assert (_current_trans);
2426 assert (!_current_trans_quarks.empty ());
2431 _current_trans->add_command (cmd);
2434 _current_trans_quarks.pop_front ();
2436 if (!_current_trans_quarks.empty ()) {
2437 /* the transaction we're committing is not the top-level one */
2441 if (_current_trans->empty()) {
2442 /* no commands were added to the transaction, so just get rid of it */
2443 delete _current_trans;
2448 gettimeofday (&now, 0);
2449 _current_trans->set_timestamp (now);
2451 _history.add (_current_trans);
2456 accept_all_audio_files (const string& path, void* /*arg*/)
2458 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2462 if (!AudioFileSource::safe_audio_file_extension (path)) {
2470 accept_all_midi_files (const string& path, void* /*arg*/)
2472 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2476 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2477 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2478 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2482 accept_all_state_files (const string& path, void* /*arg*/)
2484 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2488 return (path.length() > 7 && path.find (".ardour") == (path.length() - 7));
2492 Session::find_all_sources (string path, set<string>& result)
2497 if (!tree.read (path)) {
2501 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2506 XMLNodeConstIterator niter;
2508 nlist = node->children();
2512 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2516 if ((prop = (*niter)->property (X_("type"))) == 0) {
2520 DataType type (prop->value());
2522 if ((prop = (*niter)->property (X_("name"))) == 0) {
2526 if (Glib::path_is_absolute (prop->value())) {
2527 /* external file, ignore */
2535 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2536 result.insert (found_path);
2544 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2546 PathScanner scanner;
2547 vector<string*>* state_files;
2549 string this_snapshot_path;
2555 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2556 ripped = ripped.substr (0, ripped.length() - 1);
2559 state_files = scanner (ripped, accept_all_state_files, (void *) 0, true, true);
2561 if (state_files == 0) {
2566 this_snapshot_path = _path;
2567 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2568 this_snapshot_path += statefile_suffix;
2570 for (vector<string*>::iterator i = state_files->begin(); i != state_files->end(); ++i) {
2572 if (exclude_this_snapshot && **i == this_snapshot_path) {
2576 if (find_all_sources (**i, result) < 0) {
2584 struct RegionCounter {
2585 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2586 AudioSourceList::iterator iter;
2587 boost::shared_ptr<Region> region;
2590 RegionCounter() : count (0) {}
2594 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2596 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2597 return r.get_value_or (1);
2601 Session::cleanup_regions ()
2603 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2605 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2607 uint32_t used = playlists->region_use_count (i->second);
2609 if (used == 0 && !i->second->automatic ()) {
2610 RegionFactory::map_remove (i->second);
2614 /* dump the history list */
2621 Session::cleanup_sources (CleanupReport& rep)
2623 // FIXME: needs adaptation to midi
2625 vector<boost::shared_ptr<Source> > dead_sources;
2626 PathScanner scanner;
2629 vector<space_and_path>::iterator i;
2630 vector<space_and_path>::iterator nexti;
2631 vector<string*>* candidates;
2632 vector<string*>* candidates2;
2633 vector<string> unused;
2634 set<string> all_sources;
2641 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2643 /* consider deleting all unused playlists */
2645 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2650 /* sync the "all regions" property of each playlist with its current state
2653 playlists->sync_all_regions_with_regions ();
2655 /* find all un-used sources */
2660 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2662 SourceMap::iterator tmp;
2667 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2671 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2672 dead_sources.push_back (i->second);
2673 i->second->drop_references ();
2679 /* build a list of all the possible audio directories for the session */
2681 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2686 SessionDirectory sdir ((*i).path);
2687 audio_path += sdir.sound_path();
2689 if (nexti != session_dirs.end()) {
2697 /* build a list of all the possible midi directories for the session */
2699 for (i = session_dirs.begin(); i != session_dirs.end(); ) {
2704 SessionDirectory sdir ((*i).path);
2705 midi_path += sdir.midi_path();
2707 if (nexti != session_dirs.end()) {
2714 candidates = scanner (audio_path, accept_all_audio_files, (void *) 0, true, true);
2715 candidates2 = scanner (midi_path, accept_all_midi_files, (void *) 0, true, true);
2721 for (vector<string*>::iterator i = candidates2->begin(); i != candidates2->end(); ++i) {
2722 candidates->push_back (*i);
2727 candidates = candidates2; // might still be null
2730 /* find all sources, but don't use this snapshot because the
2731 state file on disk still references sources we may have already
2735 find_all_sources_across_snapshots (all_sources, true);
2737 /* add our current source list
2740 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2741 boost::shared_ptr<FileSource> fs;
2742 SourceMap::iterator tmp = i;
2745 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2746 if (playlists->source_use_count (fs) != 0) {
2747 all_sources.insert (fs->path());
2750 /* we might not remove this source from disk, because it may be used
2751 by other snapshots, but its not being used in this version
2752 so lets get rid of it now, along with any representative regions
2756 RegionFactory::remove_regions_using_source (i->second);
2765 for (vector<string*>::iterator x = candidates->begin(); x != candidates->end(); ++x) {
2770 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2772 tmppath1 = canonical_path (spath);
2773 tmppath2 = canonical_path ((*i));
2775 if (tmppath1 == tmppath2) {
2782 unused.push_back (spath);
2791 /* now try to move all unused files into the "dead" directory(ies) */
2793 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2794 struct stat statbuf;
2798 /* don't move the file across filesystems, just
2799 stick it in the `dead_dir_name' directory
2800 on whichever filesystem it was already on.
2803 if ((*x).find ("/sounds/") != string::npos) {
2805 /* old school, go up 1 level */
2807 newpath = Glib::path_get_dirname (*x); // "sounds"
2808 newpath = Glib::path_get_dirname (newpath); // "session-name"
2812 /* new school, go up 4 levels */
2814 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2815 newpath = Glib::path_get_dirname (newpath); // "session-name"
2816 newpath = Glib::path_get_dirname (newpath); // "interchange"
2817 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2820 newpath = Glib::build_filename (newpath, dead_dir_name);
2822 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2823 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2827 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2829 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2831 /* the new path already exists, try versioning */
2833 char buf[PATH_MAX+1];
2837 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2840 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2841 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2845 if (version == 999) {
2846 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2850 newpath = newpath_v;
2855 /* it doesn't exist, or we can't read it or something */
2859 stat ((*x).c_str(), &statbuf);
2861 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2862 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2863 (*x), newpath, strerror (errno))
2868 /* see if there an easy to find peakfile for this file, and remove it.
2871 string base = basename_nosuffix (*x);
2872 base += "%A"; /* this is what we add for the channel suffix of all native files,
2873 or for the first channel of embedded files. it will miss
2874 some peakfiles for other channels
2876 string peakpath = peak_path (base);
2878 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2879 if (::g_unlink (peakpath.c_str()) != 0) {
2880 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2881 peakpath, _path, strerror (errno))
2883 /* try to back out */
2884 ::rename (newpath.c_str(), _path.c_str());
2889 rep.paths.push_back (*x);
2890 rep.space += statbuf.st_size;
2893 /* dump the history list */
2897 /* save state so we don't end up a session file
2898 referring to non-existent sources.
2905 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2911 Session::cleanup_trash_sources (CleanupReport& rep)
2913 // FIXME: needs adaptation for MIDI
2915 vector<space_and_path>::iterator i;
2921 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2923 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
2925 clear_directory (dead_dir, &rep.space, &rep.paths);
2932 Session::set_dirty ()
2934 bool was_dirty = dirty();
2936 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
2940 DirtyChanged(); /* EMIT SIGNAL */
2946 Session::set_clean ()
2948 bool was_dirty = dirty();
2950 _state_of_the_state = Clean;
2954 DirtyChanged(); /* EMIT SIGNAL */
2959 Session::set_deletion_in_progress ()
2961 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
2965 Session::clear_deletion_in_progress ()
2967 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
2971 Session::add_controllable (boost::shared_ptr<Controllable> c)
2973 /* this adds a controllable to the list managed by the Session.
2974 this is a subset of those managed by the Controllable class
2975 itself, and represents the only ones whose state will be saved
2976 as part of the session.
2979 Glib::Threads::Mutex::Lock lm (controllables_lock);
2980 controllables.insert (c);
2983 struct null_deleter { void operator()(void const *) const {} };
2986 Session::remove_controllable (Controllable* c)
2988 if (_state_of_the_state & Deletion) {
2992 Glib::Threads::Mutex::Lock lm (controllables_lock);
2994 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
2996 if (x != controllables.end()) {
2997 controllables.erase (x);
3001 boost::shared_ptr<Controllable>
3002 Session::controllable_by_id (const PBD::ID& id)
3004 Glib::Threads::Mutex::Lock lm (controllables_lock);
3006 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3007 if ((*i)->id() == id) {
3012 return boost::shared_ptr<Controllable>();
3015 boost::shared_ptr<Controllable>
3016 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3018 boost::shared_ptr<Controllable> c;
3019 boost::shared_ptr<Route> r;
3021 switch (desc.top_level_type()) {
3022 case ControllableDescriptor::NamedRoute:
3024 std::string str = desc.top_level_name();
3025 if (str == "master") {
3027 } else if (str == "control" || str == "listen") {
3030 r = route_by_name (desc.top_level_name());
3035 case ControllableDescriptor::RemoteControlID:
3036 r = route_by_remote_id (desc.rid());
3044 switch (desc.subtype()) {
3045 case ControllableDescriptor::Gain:
3046 c = r->gain_control ();
3049 case ControllableDescriptor::Solo:
3050 c = r->solo_control();
3053 case ControllableDescriptor::Mute:
3054 c = r->mute_control();
3057 case ControllableDescriptor::Recenable:
3059 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3062 c = t->rec_enable_control ();
3067 case ControllableDescriptor::PanDirection:
3069 c = r->pannable()->pan_azimuth_control;
3073 case ControllableDescriptor::PanWidth:
3075 c = r->pannable()->pan_width_control;
3079 case ControllableDescriptor::PanElevation:
3081 c = r->pannable()->pan_elevation_control;
3085 case ControllableDescriptor::Balance:
3086 /* XXX simple pan control */
3089 case ControllableDescriptor::PluginParameter:
3091 uint32_t plugin = desc.target (0);
3092 uint32_t parameter_index = desc.target (1);
3094 /* revert to zero based counting */
3100 if (parameter_index > 0) {
3104 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3107 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3108 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3113 case ControllableDescriptor::SendGain:
3115 uint32_t send = desc.target (0);
3117 /* revert to zero-based counting */
3123 boost::shared_ptr<Processor> p = r->nth_send (send);
3126 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3127 boost::shared_ptr<Amp> a = s->amp();
3130 c = s->amp()->gain_control();
3137 /* relax and return a null pointer */
3145 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3148 Stateful::add_instant_xml (node, _path);
3151 if (write_to_config) {
3152 Config->add_instant_xml (node);
3157 Session::instant_xml (const string& node_name)
3159 return Stateful::instant_xml (node_name, _path);
3163 Session::save_history (string snapshot_name)
3171 if (snapshot_name.empty()) {
3172 snapshot_name = _current_snapshot_name;
3175 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3176 const string backup_filename = history_filename + backup_suffix;
3177 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3178 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3180 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3181 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3182 error << _("could not backup old history file, current history not saved") << endmsg;
3187 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0) {
3191 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3193 if (!tree.write (xml_path))
3195 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3197 if (g_remove (xml_path.c_str()) != 0) {
3198 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3199 xml_path, g_strerror (errno)) << endmsg;
3201 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3202 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3203 backup_path, g_strerror (errno)) << endmsg;
3213 Session::restore_history (string snapshot_name)
3217 if (snapshot_name.empty()) {
3218 snapshot_name = _current_snapshot_name;
3221 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3222 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3224 info << "Loading history from " << xml_path << endmsg;
3226 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3227 info << string_compose (_("%1: no history file \"%2\" for this session."),
3228 _name, xml_path) << endmsg;
3232 if (!tree.read (xml_path)) {
3233 error << string_compose (_("Could not understand session history file \"%1\""),
3234 xml_path) << endmsg;
3241 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3244 UndoTransaction* ut = new UndoTransaction ();
3247 ut->set_name(t->property("name")->value());
3248 stringstream ss(t->property("tv-sec")->value());
3250 ss.str(t->property("tv-usec")->value());
3252 ut->set_timestamp(tv);
3254 for (XMLNodeConstIterator child_it = t->children().begin();
3255 child_it != t->children().end(); child_it++)
3257 XMLNode *n = *child_it;
3260 if (n->name() == "MementoCommand" ||
3261 n->name() == "MementoUndoCommand" ||
3262 n->name() == "MementoRedoCommand") {
3264 if ((c = memento_command_factory(n))) {
3268 } else if (n->name() == "NoteDiffCommand") {
3269 PBD::ID id (n->property("midi-source")->value());
3270 boost::shared_ptr<MidiSource> midi_source =
3271 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3273 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3275 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3278 } else if (n->name() == "SysExDiffCommand") {
3280 PBD::ID id (n->property("midi-source")->value());
3281 boost::shared_ptr<MidiSource> midi_source =
3282 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3284 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3286 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3289 } else if (n->name() == "PatchChangeDiffCommand") {
3291 PBD::ID id (n->property("midi-source")->value());
3292 boost::shared_ptr<MidiSource> midi_source =
3293 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3295 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3297 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3300 } else if (n->name() == "StatefulDiffCommand") {
3301 if ((c = stateful_diff_command_factory (n))) {
3302 ut->add_command (c);
3305 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3316 Session::config_changed (std::string p, bool ours)
3322 if (p == "seamless-loop") {
3324 } else if (p == "rf-speed") {
3326 } else if (p == "auto-loop") {
3328 } else if (p == "auto-input") {
3330 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3331 /* auto-input only makes a difference if we're rolling */
3332 set_track_monitor_input_status (!config.get_auto_input());
3335 } else if (p == "punch-in") {
3339 if ((location = _locations->auto_punch_location()) != 0) {
3341 if (config.get_punch_in ()) {
3342 replace_event (SessionEvent::PunchIn, location->start());
3344 remove_event (location->start(), SessionEvent::PunchIn);
3348 } else if (p == "punch-out") {
3352 if ((location = _locations->auto_punch_location()) != 0) {
3354 if (config.get_punch_out()) {
3355 replace_event (SessionEvent::PunchOut, location->end());
3357 clear_events (SessionEvent::PunchOut);
3361 } else if (p == "edit-mode") {
3363 Glib::Threads::Mutex::Lock lm (playlists->lock);
3365 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3366 (*i)->set_edit_mode (Config->get_edit_mode ());
3369 } else if (p == "use-video-sync") {
3371 waiting_for_sync_offset = config.get_use_video_sync();
3373 } else if (p == "mmc-control") {
3375 //poke_midi_thread ();
3377 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3379 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3381 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3383 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3385 } else if (p == "midi-control") {
3387 //poke_midi_thread ();
3389 } else if (p == "raid-path") {
3391 setup_raid_path (config.get_raid_path());
3393 } else if (p == "timecode-format") {
3397 } else if (p == "video-pullup") {
3401 } else if (p == "seamless-loop") {
3403 if (play_loop && transport_rolling()) {
3404 // to reset diskstreams etc
3405 request_play_loop (true);
3408 } else if (p == "rf-speed") {
3410 cumulative_rf_motion = 0;
3413 } else if (p == "click-sound") {
3415 setup_click_sounds (1);
3417 } else if (p == "click-emphasis-sound") {
3419 setup_click_sounds (-1);
3421 } else if (p == "clicking") {
3423 if (Config->get_clicking()) {
3424 if (_click_io && click_data) { // don't require emphasis data
3431 } else if (p == "click-gain") {
3434 _click_gain->set_gain (Config->get_click_gain(), this);
3437 } else if (p == "send-mtc") {
3439 if (Config->get_send_mtc ()) {
3440 /* mark us ready to send */
3441 next_quarter_frame_to_send = 0;
3444 } else if (p == "send-mmc") {
3446 _mmc->enable_send (Config->get_send_mmc ());
3448 } else if (p == "midi-feedback") {
3450 session_midi_feedback = Config->get_midi_feedback();
3452 } else if (p == "jack-time-master") {
3454 engine().reset_timebase ();
3456 } else if (p == "native-file-header-format") {
3458 if (!first_file_header_format_reset) {
3459 reset_native_file_format ();
3462 first_file_header_format_reset = false;
3464 } else if (p == "native-file-data-format") {
3466 if (!first_file_data_format_reset) {
3467 reset_native_file_format ();
3470 first_file_data_format_reset = false;
3472 } else if (p == "external-sync") {
3473 if (!config.get_external_sync()) {
3474 drop_sync_source ();
3476 switch_to_sync_source (Config->get_sync_source());
3478 } else if (p == "denormal-model") {
3480 } else if (p == "history-depth") {
3481 set_history_depth (Config->get_history_depth());
3482 } else if (p == "remote-model") {
3483 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3486 } else if (p == "sync-all-route-ordering") {
3488 /* sync to editor order unless mixer is used for remote IDs
3491 switch (Config->get_remote_model()) {
3493 sync_order_keys (EditorSort);
3496 sync_order_keys (EditorSort);
3499 sync_order_keys (MixerSort);
3502 } else if (p == "initial-program-change") {
3504 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3507 buf[0] = MIDI::program; // channel zero by default
3508 buf[1] = (Config->get_initial_program_change() & 0x7f);
3510 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3512 } else if (p == "solo-mute-override") {
3513 // catch_up_on_solo_mute_override ();
3514 } else if (p == "listen-position" || p == "pfl-position") {
3515 listen_position_changed ();
3516 } else if (p == "solo-control-is-listen-control") {
3517 solo_control_mode_changed ();
3518 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3519 last_timecode_valid = false;
3520 } else if (p == "playback-buffer-seconds") {
3521 AudioSource::allocate_working_buffers (frame_rate());
3522 } else if (p == "automation-thinning-factor") {
3523 Evoral::ControlList::set_thinning_factor (Config->get_automation_thinning_factor());
3524 } else if (p == "ltc-source-port") {
3525 reconnect_ltc_input ();
3526 } else if (p == "ltc-sink-port") {
3527 reconnect_ltc_output ();
3528 } else if (p == "timecode-generator-offset") {
3529 ltc_tx_parse_offset();
3536 Session::set_history_depth (uint32_t d)
3538 _history.set_depth (d);
3542 Session::load_diskstreams_2X (XMLNode const & node, int)
3545 XMLNodeConstIterator citer;
3547 clist = node.children();
3549 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3552 /* diskstreams added automatically by DiskstreamCreated handler */
3553 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3554 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3555 _diskstreams_2X.push_back (dsp);
3557 error << _("Session: unknown diskstream type in XML") << endmsg;
3561 catch (failed_constructor& err) {
3562 error << _("Session: could not load diskstream via XML state") << endmsg;
3570 /** Connect things to the MMC object */
3572 Session::setup_midi_machine_control ()
3574 _mmc = new MIDI::MachineControl;
3575 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3577 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3578 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3579 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3580 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3581 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3582 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3583 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3584 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3585 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3586 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3587 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3588 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3589 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3591 /* also handle MIDI SPP because its so common */
3593 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3594 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3595 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3598 boost::shared_ptr<Controllable>
3599 Session::solo_cut_control() const
3601 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3602 controls in Ardour that currently get presented to the user in the GUI that require
3603 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3605 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3606 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3610 return _solo_cut_control;
3614 Session::rename (const std::string& new_name)
3616 string legal_name = legalize_for_path (new_name);
3622 string const old_sources_root = _session_dir->sources_root();
3624 #define RENAME ::rename
3629 * interchange subdirectory
3633 * Backup files are left unchanged and not renamed.
3636 /* pass one: not 100% safe check that the new directory names don't
3640 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3645 /* this is a stupid hack because Glib::path_get_dirname() is
3646 * lexical-only, and so passing it /a/b/c/ gives a different
3647 * result than passing it /a/b/c ...
3650 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3651 oldstr = oldstr.substr (0, oldstr.length() - 1);
3654 string base = Glib::path_get_dirname (oldstr);
3655 string p = Glib::path_get_basename (oldstr);
3657 newstr = Glib::build_filename (base, legal_name);
3659 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3666 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3671 /* this is a stupid hack because Glib::path_get_dirname() is
3672 * lexical-only, and so passing it /a/b/c/ gives a different
3673 * result than passing it /a/b/c ...
3676 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3677 oldstr = oldstr.substr (0, oldstr.length() - 1);
3680 string base = Glib::path_get_dirname (oldstr);
3681 string p = Glib::path_get_basename (oldstr);
3683 newstr = Glib::build_filename (base, legal_name);
3685 cerr << "Rename " << oldstr << " => " << newstr << endl;
3687 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3692 (*_session_dir) = newstr;
3697 /* directory below interchange */
3699 v.push_back (newstr);
3700 v.push_back (interchange_dir_name);
3703 oldstr = Glib::build_filename (v);
3706 v.push_back (newstr);
3707 v.push_back (interchange_dir_name);
3708 v.push_back (legal_name);
3710 newstr = Glib::build_filename (v);
3712 cerr << "Rename " << oldstr << " => " << newstr << endl;
3714 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3721 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + statefile_suffix;
3722 newstr= Glib::build_filename (newpath, legal_name) + statefile_suffix;
3724 cerr << "Rename " << oldstr << " => " << newstr << endl;
3726 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3733 oldstr = Glib::build_filename (newpath, _current_snapshot_name) + history_suffix;
3735 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3736 newstr = Glib::build_filename (newpath, legal_name) + history_suffix;
3738 cerr << "Rename " << oldstr << " => " << newstr << endl;
3740 if (RENAME (oldstr.c_str(), newstr.c_str()) != 0) {
3745 /* update file source paths */
3747 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3748 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3750 string p = fs->path ();
3751 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3756 /* remove old name from recent sessions */
3758 remove_recent_sessions (_path);
3761 _current_snapshot_name = new_name;
3766 /* save state again to get everything just right */
3768 save_state (_current_snapshot_name);
3771 /* add to recent sessions */
3773 store_recent_sessions (new_name, _path);
3781 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
3783 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
3787 if (!tree.read (xmlpath)) {
3795 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
3798 bool found_sr = false;
3799 bool found_data_format = false;
3801 if (get_session_info_from_path (tree, xmlpath)) {
3807 const XMLProperty* prop;
3808 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
3809 sample_rate = atoi (prop->value());
3813 const XMLNodeList& children (tree.root()->children());
3814 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
3815 const XMLNode* child = *c;
3816 if (child->name() == "Config") {
3817 const XMLNodeList& options (child->children());
3818 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
3819 const XMLNode* option = *oc;
3820 const XMLProperty* name = option->property("name");
3826 if (name->value() == "native-file-data-format") {
3827 const XMLProperty* value = option->property ("value");
3829 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
3831 found_data_format = true;
3837 if (found_data_format) {
3842 return !(found_sr && found_data_format); // zero if they are both found