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>
57 #include <glibmm/fileutils.h>
59 #include <boost/algorithm/string.hpp>
61 #include "midi++/mmc.h"
62 #include "midi++/port.h"
64 #include "evoral/SMF.hpp"
66 #include "pbd/boost_debug.h"
67 #include "pbd/basename.h"
68 #include "pbd/controllable_descriptor.h"
69 #include "pbd/enumwriter.h"
70 #include "pbd/error.h"
71 #include "pbd/file_utils.h"
72 #include "pbd/pathexpand.h"
73 #include "pbd/pthread_utils.h"
74 #include "pbd/stacktrace.h"
75 #include "pbd/convert.h"
76 #include "pbd/localtime_r.h"
78 #include "ardour/amp.h"
79 #include "ardour/async_midi_port.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_scene_changer.h"
96 #include "ardour/midi_source.h"
97 #include "ardour/midi_track.h"
98 #include "ardour/pannable.h"
99 #include "ardour/playlist_factory.h"
100 #include "ardour/playlist_source.h"
101 #include "ardour/port.h"
102 #include "ardour/processor.h"
103 #include "ardour/profile.h"
104 #include "ardour/proxy_controllable.h"
105 #include "ardour/recent_sessions.h"
106 #include "ardour/region_factory.h"
107 #include "ardour/route_group.h"
108 #include "ardour/send.h"
109 #include "ardour/session.h"
110 #include "ardour/session_directory.h"
111 #include "ardour/session_metadata.h"
112 #include "ardour/session_playlists.h"
113 #include "ardour/session_state_utils.h"
114 #include "ardour/silentfilesource.h"
115 #include "ardour/sndfilesource.h"
116 #include "ardour/source_factory.h"
117 #include "ardour/speakers.h"
118 #include "ardour/template_utils.h"
119 #include "ardour/tempo.h"
120 #include "ardour/ticker.h"
121 #include "ardour/user_bundle.h"
123 #include "control_protocol/control_protocol.h"
129 using namespace ARDOUR;
133 Session::pre_engine_init (string fullpath)
135 if (fullpath.empty()) {
137 throw failed_constructor();
140 /* discover canonical fullpath */
142 _path = canonical_path(fullpath);
146 _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
148 /* finish initialization that can't be done in a normal C++ constructor
152 timerclear (&last_mmc_step);
153 g_atomic_int_set (&processing_prohibited, 0);
154 g_atomic_int_set (&_record_status, Disabled);
155 g_atomic_int_set (&_playback_load, 100);
156 g_atomic_int_set (&_capture_load, 100);
158 _all_route_group->set_active (true, this);
159 interpolation.add_channel_to (0, 0);
161 if (config.get_use_video_sync()) {
162 waiting_for_sync_offset = true;
164 waiting_for_sync_offset = false;
167 last_rr_session_dir = session_dirs.begin();
169 set_history_depth (Config->get_history_depth());
171 /* default: assume simple stereo speaker configuration */
173 _speakers->setup_default_speakers (2);
175 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
176 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
177 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
178 add_controllable (_solo_cut_control);
180 /* These are all static "per-class" signals */
182 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
183 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
184 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
185 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
186 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
188 /* stop IO objects from doing stuff until we're ready for them */
190 Delivery::disable_panners ();
191 IO::disable_connecting ();
193 AudioFileSource::set_peak_dir (_session_dir->peak_path());
197 Session::post_engine_init ()
199 BootMessage (_("Set block size and sample rate"));
201 set_block_size (_engine.samples_per_cycle());
202 set_frame_rate (_engine.sample_rate());
204 BootMessage (_("Using configuration"));
206 _midi_ports = new MidiPortManager;
208 MIDISceneChanger* msc;
210 _scene_changer = msc = new MIDISceneChanger (*this);
211 msc->set_input_port (scene_input_port());
212 msc->set_output_port (scene_out());
214 boost::function<framecnt_t(void)> timer_func (boost::bind (&Session::audible_frame, this));
215 boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_in())->set_timer (timer_func);
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 */
237 _tempo_map = new TempoMap (_current_frame_rate);
238 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
240 /* MidiClock requires a tempo map */
242 midi_clock = new MidiClockTicker ();
243 midi_clock->set_session (this);
245 /* crossfades require sample rate knowledge */
247 SndFileSource::setup_standard_crossfades (*this, frame_rate());
248 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
250 AudioDiskstream::allocate_working_buffers();
251 refresh_disk_space ();
253 /* we're finally ready to call set_state() ... all objects have
254 * been created, the engine is running.
258 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
262 // set_state() will call setup_raid_path(), but if it's a new session we need
263 // to call setup_raid_path() here.
264 setup_raid_path (_path);
269 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
270 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
272 Config->map_parameters (ff);
273 config.map_parameters (ft);
275 /* Reset all panners */
277 Delivery::reset_panners ();
279 /* this will cause the CPM to instantiate any protocols that are in use
280 * (or mandatory), which will pass it this Session, and then call
281 * set_state() on each instantiated protocol to match stored state.
284 ControlProtocolManager::instance().set_session (this);
286 /* This must be done after the ControlProtocolManager set_session above,
287 as it will set states for ports which the ControlProtocolManager creates.
290 // XXX set state of MIDI::Port's
291 // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
293 /* And this must be done after the MIDI::Manager::set_port_states as
294 * it will try to make connections whose details are loaded by set_port_states.
299 /* Let control protocols know that we are now all connected, so they
300 * could start talking to surfaces if they want to.
303 ControlProtocolManager::instance().midi_connectivity_established ();
305 if (_is_new && !no_auto_connect()) {
306 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
307 auto_connect_master_bus ();
310 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
312 /* update latencies */
314 initialize_latencies ();
316 _locations->added.connect_same_thread (*this, boost::bind (&Session::location_added, this, _1));
317 _locations->removed.connect_same_thread (*this, boost::bind (&Session::location_removed, this, _1));
318 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
320 } catch (AudioEngine::PortRegistrationFailure& err) {
321 /* handle this one in a different way than all others, so that its clear what happened */
322 error << err.what() << endmsg;
328 BootMessage (_("Reset Remote Controls"));
330 // send_full_time_code (0);
331 _engine.transport_locate (0);
333 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
334 send_immediate_mmc (MIDI::MachineControlCommand (Timecode::Time ()));
336 MIDI::Name::MidiPatchManager::instance().set_session (this);
339 /* initial program change will be delivered later; see ::config_changed() */
341 _state_of_the_state = Clean;
343 Port::set_connecting_blocked (false);
345 DirtyChanged (); /* EMIT SIGNAL */
349 Session::session_loaded ()
353 _state_of_the_state = Clean;
355 DirtyChanged (); /* EMIT SIGNAL */
359 } else if (state_was_pending) {
361 remove_pending_capture_state ();
362 state_was_pending = false;
365 /* Now, finally, we can fill the playback buffers */
367 BootMessage (_("Filling playback buffers"));
369 boost::shared_ptr<RouteList> rl = routes.reader();
370 for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
371 boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<Track> (*r);
372 if (trk && !trk->hidden()) {
373 trk->seek (_transport_frame, true);
379 Session::session_loaded ()
383 _state_of_the_state = Clean;
385 DirtyChanged (); /* EMIT SIGNAL */
389 } else if (state_was_pending) {
391 remove_pending_capture_state ();
392 state_was_pending = false;
395 /* Now, finally, we can fill the playback buffers */
397 BootMessage (_("Filling playback buffers"));
399 boost::shared_ptr<RouteList> rl = routes.reader();
400 for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
401 boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<Track> (*r);
402 if (trk && !trk->hidden()) {
403 trk->seek (_transport_frame, true);
409 Session::raid_path () const
411 Searchpath raid_search_path;
413 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
414 raid_search_path += (*i).path;
417 return raid_search_path.to_string ();
421 Session::setup_raid_path (string path)
430 session_dirs.clear ();
432 Searchpath search_path(path);
433 Searchpath sound_search_path;
434 Searchpath midi_search_path;
436 for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
438 sp.blocks = 0; // not needed
439 session_dirs.push_back (sp);
441 SessionDirectory sdir(sp.path);
443 sound_search_path += sdir.sound_path ();
444 midi_search_path += sdir.midi_path ();
447 // reset the round-robin soundfile path thingie
448 last_rr_session_dir = session_dirs.begin();
452 Session::path_is_within_session (const std::string& path)
454 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
455 if (PBD::path_is_within (i->path, path)) {
463 Session::ensure_subdirs ()
467 dir = session_directory().peak_path();
469 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
470 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
474 dir = session_directory().sound_path();
476 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
477 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
481 dir = session_directory().midi_path();
483 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
484 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
488 dir = session_directory().dead_path();
490 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
491 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
495 dir = session_directory().export_path();
497 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
498 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
502 dir = analysis_dir ();
504 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
505 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
509 dir = plugins_dir ();
511 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
512 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
516 dir = externals_dir ();
518 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
519 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
526 /** @param session_template directory containing session template, or empty.
527 * Caller must not hold process lock.
530 Session::create (const string& session_template, BusProfile* bus_profile)
532 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
533 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
537 if (ensure_subdirs ()) {
541 _writable = exists_and_writable (_path);
543 if (!session_template.empty()) {
544 std::string in_path = (ARDOUR::Profile->get_trx () ? session_template : session_template_dir_to_file (session_template));
546 ifstream in(in_path.c_str());
549 /* no need to call legalize_for_path() since the string
550 * in session_template is already a legal path name
552 string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
554 ofstream out(out_path.c_str());
560 if (!ARDOUR::Profile->get_trx()) {
561 /* Copy plugin state files from template to new session */
562 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
563 copy_recurse (template_plugins, plugins_dir ());
569 error << string_compose (_("Could not open %1 for writing session template"), out_path)
575 error << string_compose (_("Could not open session template %1 for reading"), in_path)
582 /* set initial start + end point */
584 _state_of_the_state = Clean;
586 /* set up Master Out and Control Out if necessary */
591 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
593 // Waves Tracks: always create master bus for Tracks
594 if (ARDOUR::Profile->get_trx() || bus_profile->master_out_channels) {
595 boost::shared_ptr<Route> r (new Route (*this, _("Master"), Route::MasterOut, DataType::AUDIO));
599 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
600 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
603 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
604 r->input()->ensure_io (count, false, this);
605 r->output()->ensure_io (count, false, this);
611 /* prohibit auto-connect to master, because there isn't one */
612 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
616 add_routes (rl, false, false, false);
619 // Waves Tracks: Skip this. Always use autoconnection for Tracks
620 if (!ARDOUR::Profile->get_trx()) {
622 /* this allows the user to override settings with an environment variable.
625 if (no_auto_connect()) {
626 bus_profile->input_ac = AutoConnectOption (0);
627 bus_profile->output_ac = AutoConnectOption (0);
630 Config->set_input_auto_connect (bus_profile->input_ac);
631 Config->set_output_auto_connect (bus_profile->output_ac);
635 if (Config->get_use_monitor_bus() && bus_profile) {
636 add_monitor_section ();
643 Session::maybe_write_autosave()
645 if (dirty() && record_status() != Recording) {
646 save_state("", true);
651 Session::remove_pending_capture_state ()
653 std::string pending_state_file_path(_session_dir->root_path());
655 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
657 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
659 if (g_remove (pending_state_file_path.c_str()) != 0) {
660 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
661 pending_state_file_path, g_strerror (errno)) << endmsg;
665 /** Rename a state file.
666 * @param old_name Old snapshot name.
667 * @param new_name New snapshot name.
670 Session::rename_state (string old_name, string new_name)
672 if (old_name == _current_snapshot_name || old_name == _name) {
673 /* refuse to rename the current snapshot or the "main" one */
677 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
678 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
680 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
681 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
683 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
684 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
685 old_name, new_name, g_strerror(errno)) << endmsg;
689 /** Remove a state file.
690 * @param snapshot_name Snapshot name.
693 Session::remove_state (string snapshot_name)
695 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
696 // refuse to remove the current snapshot or the "main" one
700 std::string xml_path(_session_dir->root_path());
702 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
704 if (!create_backup_file (xml_path)) {
705 // don't remove it if a backup can't be made
706 // create_backup_file will log the error.
711 if (g_remove (xml_path.c_str()) != 0) {
712 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
713 xml_path, g_strerror (errno)) << endmsg;
717 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
719 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot, bool template_only)
722 std::string xml_path(_session_dir->root_path());
724 /* prevent concurrent saves from different threads */
726 Glib::Threads::Mutex::Lock lm (save_state_lock);
728 if (!_writable || (_state_of_the_state & CannotSave)) {
732 if (g_atomic_int_get(&_suspend_save)) {
736 _save_queued = false;
738 if (!_engine.connected ()) {
739 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
745 /* tell sources we're saving first, in case they write out to a new file
746 * which should be saved with the state rather than the old one */
747 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
749 i->second->session_saved();
750 } catch (Evoral::SMF::FileError& e) {
751 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
755 SessionSaveUnderway (); /* EMIT SIGNAL */
758 tree.set_root (&get_template());
760 tree.set_root (&get_state());
763 if (snapshot_name.empty()) {
764 snapshot_name = _current_snapshot_name;
765 } else if (switch_to_snapshot) {
766 _current_snapshot_name = snapshot_name;
771 /* proper save: use statefile_suffix (.ardour in English) */
773 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
775 /* make a backup copy of the old file */
777 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
778 // create_backup_file will log the error
784 /* pending save: use pending_suffix (.pending in English) */
785 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
788 std::string tmp_path(_session_dir->root_path());
789 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
791 cerr << "actually writing state to " << tmp_path << endl;
793 if (!tree.write (tmp_path)) {
794 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
795 if (g_remove (tmp_path.c_str()) != 0) {
796 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
797 tmp_path, g_strerror (errno)) << endmsg;
803 cerr << "renaming state to " << xml_path << endl;
805 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
806 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
807 tmp_path, xml_path, g_strerror(errno)) << endmsg;
808 if (g_remove (tmp_path.c_str()) != 0) {
809 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
810 tmp_path, g_strerror (errno)) << endmsg;
818 save_history (snapshot_name);
820 bool was_dirty = dirty();
822 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
825 DirtyChanged (); /* EMIT SIGNAL */
828 StateSaved (snapshot_name); /* EMIT SIGNAL */
835 Session::restore_state (string snapshot_name)
837 if (load_state (snapshot_name) == 0) {
838 set_state (*state_tree->root(), Stateful::loading_state_version);
845 Session::load_state (string snapshot_name)
850 state_was_pending = false;
852 /* check for leftover pending state from a crashed capture attempt */
854 std::string xmlpath(_session_dir->root_path());
855 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
857 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
859 /* there is pending state from a crashed capture attempt */
861 boost::optional<int> r = AskAboutPendingState();
862 if (r.get_value_or (1)) {
863 state_was_pending = true;
867 if (!state_was_pending) {
868 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
871 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
872 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
873 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
874 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
879 state_tree = new XMLTree;
883 _writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
885 if (!state_tree->read (xmlpath)) {
886 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
892 XMLNode& root (*state_tree->root());
894 if (root.name() != X_("Session")) {
895 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
901 const XMLProperty* prop;
903 if ((prop = root.property ("version")) == 0) {
904 /* no version implies very old version of Ardour */
905 Stateful::loading_state_version = 1000;
907 if (prop->value().find ('.') != string::npos) {
908 /* old school version format */
909 if (prop->value()[0] == '2') {
910 Stateful::loading_state_version = 2000;
912 Stateful::loading_state_version = 3000;
915 Stateful::loading_state_version = atoi (prop->value());
919 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
921 std::string backup_path(_session_dir->root_path());
922 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
923 backup_path = Glib::build_filename (backup_path, backup_filename);
925 // only create a backup for a given statefile version once
927 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
929 VersionMismatch (xmlpath, backup_path);
931 if (!copy_file (xmlpath, backup_path)) {;
941 Session::load_options (const XMLNode& node)
943 LocaleGuard lg (X_("C"));
944 config.set_variables (node);
949 Session::save_default_options ()
951 return config.save_state();
961 Session::get_template()
963 /* if we don't disable rec-enable, diskstreams
964 will believe they need to store their capture
965 sources in their state node.
968 disable_record (false);
974 Session::state (bool full_state)
976 XMLNode* node = new XMLNode("Session");
980 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
981 node->add_property("version", buf);
983 /* store configuration settings */
987 node->add_property ("name", _name);
988 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
989 node->add_property ("sample-rate", buf);
991 if (session_dirs.size() > 1) {
995 vector<space_and_path>::iterator i = session_dirs.begin();
996 vector<space_and_path>::iterator next;
998 ++i; /* skip the first one */
1002 while (i != session_dirs.end()) {
1006 if (next != session_dirs.end()) {
1007 p += G_SEARCHPATH_SEPARATOR;
1016 child = node->add_child ("Path");
1017 child->add_content (p);
1021 /* save the ID counter */
1023 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1024 node->add_property ("id-counter", buf);
1026 /* save the event ID counter */
1028 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1029 node->add_property ("event-counter", buf);
1031 /* various options */
1033 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
1034 if (!midi_port_nodes.empty()) {
1035 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
1036 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
1037 midi_port_stuff->add_child_nocopy (**n);
1039 node->add_child_nocopy (*midi_port_stuff);
1042 node->add_child_nocopy (config.get_variables ());
1044 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1046 child = node->add_child ("Sources");
1049 Glib::Threads::Mutex::Lock sl (source_lock);
1051 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1053 /* Don't save information about non-file Sources, or
1054 * about non-destructive file sources that are empty
1055 * and unused by any regions.
1058 boost::shared_ptr<FileSource> fs;
1060 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1062 if (!fs->destructive()) {
1063 if (fs->empty() && !fs->used()) {
1068 child->add_child_nocopy (siter->second->get_state());
1073 child = node->add_child ("Regions");
1076 Glib::Threads::Mutex::Lock rl (region_lock);
1077 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1078 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1079 boost::shared_ptr<Region> r = i->second;
1080 /* only store regions not attached to playlists */
1081 if (r->playlist() == 0) {
1082 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1083 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1085 child->add_child_nocopy (r->get_state ());
1090 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1092 if (!cassocs.empty()) {
1093 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1095 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1097 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1098 i->first->id().print (buf, sizeof (buf));
1099 can->add_property (X_("copy"), buf);
1100 i->second->id().print (buf, sizeof (buf));
1101 can->add_property (X_("original"), buf);
1102 ca->add_child_nocopy (*can);
1112 node->add_child_nocopy (_locations->get_state());
1115 Locations loc (*this);
1116 // for a template, just create a new Locations, populate it
1117 // with the default start and end, and get the state for that.
1118 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1119 range->set (max_framepos, 0);
1121 XMLNode& locations_state = loc.get_state();
1123 if (ARDOUR::Profile->get_trx() && _locations) {
1124 // For tracks we need stored the Auto Loop Range and all MIDI markers.
1125 for (Locations::LocationList::const_iterator i = _locations->list ().begin (); i != _locations->list ().end (); ++i) {
1126 if ((*i)->is_mark () || (*i)->is_auto_loop ()) {
1127 locations_state.add_child_nocopy ((*i)->get_state ());
1131 node->add_child_nocopy (locations_state);
1134 child = node->add_child ("Bundles");
1136 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1137 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1138 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1140 child->add_child_nocopy (b->get_state());
1145 child = node->add_child ("Routes");
1147 boost::shared_ptr<RouteList> r = routes.reader ();
1149 RoutePublicOrderSorter cmp;
1150 RouteList public_order (*r);
1151 public_order.sort (cmp);
1153 /* the sort should have put control outs first */
1156 assert (_monitor_out == public_order.front());
1159 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1160 if (!(*i)->is_auditioner()) {
1162 child->add_child_nocopy ((*i)->get_state());
1164 child->add_child_nocopy ((*i)->get_template());
1170 playlists->add_state (node, full_state);
1172 child = node->add_child ("RouteGroups");
1173 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1174 child->add_child_nocopy ((*i)->get_state());
1178 XMLNode* gain_child = node->add_child ("Click");
1179 gain_child->add_child_nocopy (_click_io->state (full_state));
1180 gain_child->add_child_nocopy (_click_gain->state (full_state));
1184 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1185 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1189 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1190 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1193 node->add_child_nocopy (_speakers->get_state());
1194 node->add_child_nocopy (_tempo_map->get_state());
1195 node->add_child_nocopy (get_control_protocol_state());
1198 node->add_child_copy (*_extra_xml);
1205 Session::get_control_protocol_state ()
1207 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1208 return cpm.get_state();
1212 Session::set_state (const XMLNode& node, int version)
1216 const XMLProperty* prop;
1219 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1221 if (node.name() != X_("Session")) {
1222 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1226 if ((prop = node.property ("name")) != 0) {
1227 _name = prop->value ();
1230 if ((prop = node.property (X_("sample-rate"))) != 0) {
1232 _nominal_frame_rate = atoi (prop->value());
1234 if (_nominal_frame_rate != _current_frame_rate) {
1235 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1236 if (r.get_value_or (0)) {
1242 setup_raid_path(_session_dir->root_path());
1244 if ((prop = node.property (X_("id-counter"))) != 0) {
1246 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1247 ID::init_counter (x);
1249 /* old sessions used a timebased counter, so fake
1250 the startup ID counter based on a standard
1255 ID::init_counter (now);
1258 if ((prop = node.property (X_("event-counter"))) != 0) {
1259 Evoral::init_event_id_counter (atoi (prop->value()));
1263 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1264 _midi_ports->set_midi_port_states (child->children());
1267 IO::disable_connecting ();
1269 Stateful::save_extra_xml (node);
1271 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1272 load_options (*child);
1273 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1274 load_options (*child);
1276 error << _("Session: XML state has no options section") << endmsg;
1279 if (version >= 3000) {
1280 if ((child = find_named_node (node, "Metadata")) == 0) {
1281 warning << _("Session: XML state has no metadata section") << endmsg;
1282 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1287 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1288 _speakers->set_state (*child, version);
1291 if ((child = find_named_node (node, "Sources")) == 0) {
1292 error << _("Session: XML state has no sources section") << endmsg;
1294 } else if (load_sources (*child)) {
1298 if ((child = find_named_node (node, "TempoMap")) == 0) {
1299 error << _("Session: XML state has no Tempo Map section") << endmsg;
1301 } else if (_tempo_map->set_state (*child, version)) {
1305 if ((child = find_named_node (node, "Locations")) == 0) {
1306 error << _("Session: XML state has no locations section") << endmsg;
1308 } else if (_locations->set_state (*child, version)) {
1312 locations_changed ();
1314 if (_session_range_location) {
1315 AudioFileSource::set_header_position_offset (_session_range_location->start());
1318 if ((child = find_named_node (node, "Regions")) == 0) {
1319 error << _("Session: XML state has no Regions section") << endmsg;
1321 } else if (load_regions (*child)) {
1325 if ((child = find_named_node (node, "Playlists")) == 0) {
1326 error << _("Session: XML state has no playlists section") << endmsg;
1328 } else if (playlists->load (*this, *child)) {
1332 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1334 } else if (playlists->load_unused (*this, *child)) {
1338 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1339 if (load_compounds (*child)) {
1344 if (version >= 3000) {
1345 if ((child = find_named_node (node, "Bundles")) == 0) {
1346 warning << _("Session: XML state has no bundles section") << endmsg;
1349 /* We can't load Bundles yet as they need to be able
1350 to convert from port names to Port objects, which can't happen until
1352 _bundle_xml_node = new XMLNode (*child);
1356 if (version < 3000) {
1357 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1358 error << _("Session: XML state has no diskstreams section") << endmsg;
1360 } else if (load_diskstreams_2X (*child, version)) {
1365 if ((child = find_named_node (node, "Routes")) == 0) {
1366 error << _("Session: XML state has no routes section") << endmsg;
1368 } else if (load_routes (*child, version)) {
1372 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1373 _diskstreams_2X.clear ();
1375 if (version >= 3000) {
1377 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1378 error << _("Session: XML state has no route groups section") << endmsg;
1380 } else if (load_route_groups (*child, version)) {
1384 } else if (version < 3000) {
1386 if ((child = find_named_node (node, "EditGroups")) == 0) {
1387 error << _("Session: XML state has no edit groups section") << endmsg;
1389 } else if (load_route_groups (*child, version)) {
1393 if ((child = find_named_node (node, "MixGroups")) == 0) {
1394 error << _("Session: XML state has no mix groups section") << endmsg;
1396 } else if (load_route_groups (*child, version)) {
1401 if ((child = find_named_node (node, "Click")) == 0) {
1402 warning << _("Session: XML state has no click section") << endmsg;
1403 } else if (_click_io) {
1404 setup_click_state (&node);
1407 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1408 ControlProtocolManager::instance().set_state (*child, version);
1411 update_route_record_state ();
1413 /* here beginneth the second phase ... */
1415 StateReady (); /* EMIT SIGNAL */
1428 Session::load_routes (const XMLNode& node, int version)
1431 XMLNodeConstIterator niter;
1432 RouteList new_routes;
1434 nlist = node.children();
1438 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1440 boost::shared_ptr<Route> route;
1441 if (version < 3000) {
1442 route = XMLRouteFactory_2X (**niter, version);
1444 route = XMLRouteFactory (**niter, version);
1448 error << _("Session: cannot create Route from XML description.") << endmsg;
1452 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1454 new_routes.push_back (route);
1457 BootMessage (_("Tracks/busses loaded; Adding to Session"));
1459 add_routes (new_routes, false, false, false);
1461 BootMessage (_("Finished adding tracks/busses"));
1466 boost::shared_ptr<Route>
1467 Session::XMLRouteFactory (const XMLNode& node, int version)
1469 boost::shared_ptr<Route> ret;
1471 if (node.name() != "Route") {
1475 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1477 DataType type = DataType::AUDIO;
1478 const XMLProperty* prop = node.property("default-type");
1481 type = DataType (prop->value());
1484 assert (type != DataType::NIL);
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 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1505 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1510 enum Route::Flag flags = Route::Flag(0);
1511 const XMLProperty* prop = node.property("flags");
1513 flags = Route::Flag (string_2_enum (prop->value(), flags));
1516 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1518 if (r->init () == 0 && r->set_state (node, version) == 0) {
1519 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1520 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1529 boost::shared_ptr<Route>
1530 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1532 boost::shared_ptr<Route> ret;
1534 if (node.name() != "Route") {
1538 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1540 ds_prop = node.property (X_("diskstream"));
1543 DataType type = DataType::AUDIO;
1544 const XMLProperty* prop = node.property("default-type");
1547 type = DataType (prop->value());
1550 assert (type != DataType::NIL);
1554 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1555 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1559 if (i == _diskstreams_2X.end()) {
1560 error << _("Could not find diskstream for route") << endmsg;
1561 return boost::shared_ptr<Route> ();
1564 boost::shared_ptr<Track> track;
1566 if (type == DataType::AUDIO) {
1567 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1569 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1572 if (track->init()) {
1576 if (track->set_state (node, version)) {
1580 track->set_diskstream (*i);
1582 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1583 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1588 enum Route::Flag flags = Route::Flag(0);
1589 const XMLProperty* prop = node.property("flags");
1591 flags = Route::Flag (string_2_enum (prop->value(), flags));
1594 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1596 if (r->init () == 0 && r->set_state (node, version) == 0) {
1597 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1598 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1608 Session::load_regions (const XMLNode& node)
1611 XMLNodeConstIterator niter;
1612 boost::shared_ptr<Region> region;
1614 nlist = node.children();
1618 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1619 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1620 error << _("Session: cannot create Region from XML description.");
1621 const XMLProperty *name = (**niter).property("name");
1624 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1635 Session::load_compounds (const XMLNode& node)
1637 XMLNodeList calist = node.children();
1638 XMLNodeConstIterator caiter;
1639 XMLProperty *caprop;
1641 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1642 XMLNode* ca = *caiter;
1646 if ((caprop = ca->property (X_("original"))) == 0) {
1649 orig_id = caprop->value();
1651 if ((caprop = ca->property (X_("copy"))) == 0) {
1654 copy_id = caprop->value();
1656 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1657 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1659 if (!orig || !copy) {
1660 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1666 RegionFactory::add_compound_association (orig, copy);
1673 Session::load_nested_sources (const XMLNode& node)
1676 XMLNodeConstIterator niter;
1678 nlist = node.children();
1680 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1681 if ((*niter)->name() == "Source") {
1683 /* it may already exist, so don't recreate it unnecessarily
1686 XMLProperty* prop = (*niter)->property (X_("id"));
1688 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1692 ID source_id (prop->value());
1694 if (!source_by_id (source_id)) {
1697 SourceFactory::create (*this, **niter, true);
1699 catch (failed_constructor& err) {
1700 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1707 boost::shared_ptr<Region>
1708 Session::XMLRegionFactory (const XMLNode& node, bool full)
1710 const XMLProperty* type = node.property("type");
1714 const XMLNodeList& nlist = node.children();
1716 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1717 XMLNode *child = (*niter);
1718 if (child->name() == "NestedSource") {
1719 load_nested_sources (*child);
1723 if (!type || type->value() == "audio") {
1724 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1725 } else if (type->value() == "midi") {
1726 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1729 } catch (failed_constructor& err) {
1730 return boost::shared_ptr<Region> ();
1733 return boost::shared_ptr<Region> ();
1736 boost::shared_ptr<AudioRegion>
1737 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1739 const XMLProperty* prop;
1740 boost::shared_ptr<Source> source;
1741 boost::shared_ptr<AudioSource> as;
1743 SourceList master_sources;
1744 uint32_t nchans = 1;
1747 if (node.name() != X_("Region")) {
1748 return boost::shared_ptr<AudioRegion>();
1751 if ((prop = node.property (X_("channels"))) != 0) {
1752 nchans = atoi (prop->value().c_str());
1755 if ((prop = node.property ("name")) == 0) {
1756 cerr << "no name for this region\n";
1760 if ((prop = node.property (X_("source-0"))) == 0) {
1761 if ((prop = node.property ("source")) == 0) {
1762 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1763 return boost::shared_ptr<AudioRegion>();
1767 PBD::ID s_id (prop->value());
1769 if ((source = source_by_id (s_id)) == 0) {
1770 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1771 return boost::shared_ptr<AudioRegion>();
1774 as = boost::dynamic_pointer_cast<AudioSource>(source);
1776 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1777 return boost::shared_ptr<AudioRegion>();
1780 sources.push_back (as);
1782 /* pickup other channels */
1784 for (uint32_t n=1; n < nchans; ++n) {
1785 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1786 if ((prop = node.property (buf)) != 0) {
1788 PBD::ID id2 (prop->value());
1790 if ((source = source_by_id (id2)) == 0) {
1791 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1792 return boost::shared_ptr<AudioRegion>();
1795 as = boost::dynamic_pointer_cast<AudioSource>(source);
1797 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1798 return boost::shared_ptr<AudioRegion>();
1800 sources.push_back (as);
1804 for (uint32_t n = 0; n < nchans; ++n) {
1805 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1806 if ((prop = node.property (buf)) != 0) {
1808 PBD::ID id2 (prop->value());
1810 if ((source = source_by_id (id2)) == 0) {
1811 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1812 return boost::shared_ptr<AudioRegion>();
1815 as = boost::dynamic_pointer_cast<AudioSource>(source);
1817 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1818 return boost::shared_ptr<AudioRegion>();
1820 master_sources.push_back (as);
1825 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1827 /* a final detail: this is the one and only place that we know how long missing files are */
1829 if (region->whole_file()) {
1830 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1831 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1833 sfp->set_length (region->length());
1838 if (!master_sources.empty()) {
1839 if (master_sources.size() != nchans) {
1840 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1842 region->set_master_sources (master_sources);
1850 catch (failed_constructor& err) {
1851 return boost::shared_ptr<AudioRegion>();
1855 boost::shared_ptr<MidiRegion>
1856 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1858 const XMLProperty* prop;
1859 boost::shared_ptr<Source> source;
1860 boost::shared_ptr<MidiSource> ms;
1863 if (node.name() != X_("Region")) {
1864 return boost::shared_ptr<MidiRegion>();
1867 if ((prop = node.property ("name")) == 0) {
1868 cerr << "no name for this region\n";
1872 if ((prop = node.property (X_("source-0"))) == 0) {
1873 if ((prop = node.property ("source")) == 0) {
1874 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1875 return boost::shared_ptr<MidiRegion>();
1879 PBD::ID s_id (prop->value());
1881 if ((source = source_by_id (s_id)) == 0) {
1882 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1883 return boost::shared_ptr<MidiRegion>();
1886 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1888 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1889 return boost::shared_ptr<MidiRegion>();
1892 sources.push_back (ms);
1895 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1896 /* a final detail: this is the one and only place that we know how long missing files are */
1898 if (region->whole_file()) {
1899 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1900 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1902 sfp->set_length (region->length());
1910 catch (failed_constructor& err) {
1911 return boost::shared_ptr<MidiRegion>();
1916 Session::get_sources_as_xml ()
1919 XMLNode* node = new XMLNode (X_("Sources"));
1920 Glib::Threads::Mutex::Lock lm (source_lock);
1922 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1923 node->add_child_nocopy (i->second->get_state());
1930 Session::reset_write_sources (bool mark_write_complete, bool force)
1932 boost::shared_ptr<RouteList> rl = routes.reader();
1933 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1934 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1936 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
1937 tr->reset_write_sources(mark_write_complete, force);
1938 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
1944 Session::load_sources (const XMLNode& node)
1947 XMLNodeConstIterator niter;
1948 boost::shared_ptr<Source> source; /* don't need this but it stops some
1949 * versions of gcc complaining about
1950 * discarded return values.
1953 nlist = node.children();
1957 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1960 if ((source = XMLSourceFactory (**niter)) == 0) {
1961 error << _("Session: cannot create Source from XML description.") << endmsg;
1964 } catch (MissingSource& err) {
1968 if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
1969 error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
1970 PROGRAM_NAME) << endmsg;
1974 if (!no_questions_about_missing_files) {
1975 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1980 switch (user_choice) {
1982 /* user added a new search location, so try again */
1987 /* user asked to quit the entire session load
1992 no_questions_about_missing_files = true;
1996 no_questions_about_missing_files = true;
2003 case DataType::AUDIO:
2004 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
2007 case DataType::MIDI:
2008 /* The MIDI file is actually missing so
2009 * just create a new one in the same
2010 * location. Do not announce its
2014 if (!Glib::path_is_absolute (err.path)) {
2015 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
2017 /* this should be an unrecoverable error: we would be creating a MIDI file outside
2022 /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
2023 source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
2024 /* reset ID to match the missing one */
2025 source->set_id (**niter);
2026 /* Now we can announce it */
2027 SourceFactory::SourceCreated (source);
2038 boost::shared_ptr<Source>
2039 Session::XMLSourceFactory (const XMLNode& node)
2041 if (node.name() != "Source") {
2042 return boost::shared_ptr<Source>();
2046 /* note: do peak building in another thread when loading session state */
2047 return SourceFactory::create (*this, node, true);
2050 catch (failed_constructor& err) {
2051 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
2052 return boost::shared_ptr<Source>();
2057 Session::save_template (string template_name)
2059 if ((_state_of_the_state & CannotSave) || template_name.empty ()) {
2063 bool absolute_path = Glib::path_is_absolute (template_name);
2065 /* directory to put the template in */
2066 std::string template_dir_path;
2068 if (!absolute_path) {
2069 std::string user_template_dir(user_template_directory());
2071 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2072 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2073 user_template_dir, g_strerror (errno)) << endmsg;
2077 template_dir_path = Glib::build_filename (user_template_dir, template_name);
2079 template_dir_path = template_name;
2082 if (!ARDOUR::Profile->get_trx()) {
2083 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2084 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2085 template_dir_path) << endmsg;
2089 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2090 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2091 template_dir_path, g_strerror (errno)) << endmsg;
2097 std::string template_file_path;
2099 if (ARDOUR::Profile->get_trx()) {
2100 template_file_path = template_name;
2102 if (absolute_path) {
2103 template_file_path = Glib::build_filename (template_dir_path, Glib::path_get_basename (template_dir_path) + template_suffix);
2105 template_file_path = Glib::build_filename (template_dir_path, template_name + template_suffix);
2109 SessionSaveUnderway (); /* EMIT SIGNAL */
2113 tree.set_root (&get_template());
2114 if (!tree.write (template_file_path)) {
2115 error << _("template not saved") << endmsg;
2119 if (!ARDOUR::Profile->get_trx()) {
2120 /* copy plugin state directory */
2122 std::string template_plugin_state_path (Glib::build_filename (template_dir_path, X_("plugins")));
2124 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
2125 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
2126 template_plugin_state_path, g_strerror (errno)) << endmsg;
2129 copy_files (plugins_dir(), template_plugin_state_path);
2132 store_recent_templates (template_file_path);
2138 Session::refresh_disk_space ()
2140 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2142 Glib::Threads::Mutex::Lock lm (space_lock);
2144 /* get freespace on every FS that is part of the session path */
2146 _total_free_4k_blocks = 0;
2147 _total_free_4k_blocks_uncertain = false;
2149 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2151 struct statfs statfsbuf;
2152 statfs (i->path.c_str(), &statfsbuf);
2154 double const scale = statfsbuf.f_bsize / 4096.0;
2156 /* See if this filesystem is read-only */
2157 struct statvfs statvfsbuf;
2158 statvfs (i->path.c_str(), &statvfsbuf);
2160 /* f_bavail can be 0 if it is undefined for whatever
2161 filesystem we are looking at; Samba shares mounted
2162 via GVFS are an example of this.
2164 if (statfsbuf.f_bavail == 0) {
2165 /* block count unknown */
2167 i->blocks_unknown = true;
2168 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2169 /* read-only filesystem */
2171 i->blocks_unknown = false;
2173 /* read/write filesystem with known space */
2174 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2175 i->blocks_unknown = false;
2178 _total_free_4k_blocks += i->blocks;
2179 if (i->blocks_unknown) {
2180 _total_free_4k_blocks_uncertain = true;
2183 #elif defined PLATFORM_WINDOWS
2184 vector<string> scanned_volumes;
2185 vector<string>::iterator j;
2186 vector<space_and_path>::iterator i;
2187 DWORD nSectorsPerCluster, nBytesPerSector,
2188 nFreeClusters, nTotalClusters;
2192 _total_free_4k_blocks = 0;
2194 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2195 strncpy (disk_drive, (*i).path.c_str(), 3);
2199 volume_found = false;
2200 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2202 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2203 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2204 i->blocks = (uint32_t)(nFreeBytes / 4096);
2206 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2207 if (0 == j->compare(disk_drive)) {
2208 volume_found = true;
2213 if (!volume_found) {
2214 scanned_volumes.push_back(disk_drive);
2215 _total_free_4k_blocks += i->blocks;
2220 if (0 == _total_free_4k_blocks) {
2221 strncpy (disk_drive, path().c_str(), 3);
2224 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2226 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2227 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2228 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2235 Session::get_best_session_directory_for_new_audio ()
2237 vector<space_and_path>::iterator i;
2238 string result = _session_dir->root_path();
2240 /* handle common case without system calls */
2242 if (session_dirs.size() == 1) {
2246 /* OK, here's the algorithm we're following here:
2248 We want to select which directory to use for
2249 the next file source to be created. Ideally,
2250 we'd like to use a round-robin process so as to
2251 get maximum performance benefits from splitting
2252 the files across multiple disks.
2254 However, in situations without much diskspace, an
2255 RR approach may end up filling up a filesystem
2256 with new files while others still have space.
2257 Its therefore important to pay some attention to
2258 the freespace in the filesystem holding each
2259 directory as well. However, if we did that by
2260 itself, we'd keep creating new files in the file
2261 system with the most space until it was as full
2262 as all others, thus negating any performance
2263 benefits of this RAID-1 like approach.
2265 So, we use a user-configurable space threshold. If
2266 there are at least 2 filesystems with more than this
2267 much space available, we use RR selection between them.
2268 If not, then we pick the filesystem with the most space.
2270 This gets a good balance between the two
2274 refresh_disk_space ();
2276 int free_enough = 0;
2278 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2279 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2284 if (free_enough >= 2) {
2285 /* use RR selection process, ensuring that the one
2289 i = last_rr_session_dir;
2292 if (++i == session_dirs.end()) {
2293 i = session_dirs.begin();
2296 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2297 SessionDirectory sdir(i->path);
2298 if (sdir.create ()) {
2300 last_rr_session_dir = i;
2305 } while (i != last_rr_session_dir);
2309 /* pick FS with the most freespace (and that
2310 seems to actually work ...)
2313 vector<space_and_path> sorted;
2314 space_and_path_ascending_cmp cmp;
2316 sorted = session_dirs;
2317 sort (sorted.begin(), sorted.end(), cmp);
2319 for (i = sorted.begin(); i != sorted.end(); ++i) {
2320 SessionDirectory sdir(i->path);
2321 if (sdir.create ()) {
2323 last_rr_session_dir = i;
2333 Session::automation_dir () const
2335 return Glib::build_filename (_path, "automation");
2339 Session::analysis_dir () const
2341 return Glib::build_filename (_path, "analysis");
2345 Session::plugins_dir () const
2347 return Glib::build_filename (_path, "plugins");
2351 Session::externals_dir () const
2353 return Glib::build_filename (_path, "externals");
2357 Session::load_bundles (XMLNode const & node)
2359 XMLNodeList nlist = node.children();
2360 XMLNodeConstIterator niter;
2364 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2365 if ((*niter)->name() == "InputBundle") {
2366 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2367 } else if ((*niter)->name() == "OutputBundle") {
2368 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2370 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2379 Session::load_route_groups (const XMLNode& node, int version)
2381 XMLNodeList nlist = node.children();
2382 XMLNodeConstIterator niter;
2386 if (version >= 3000) {
2388 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2389 if ((*niter)->name() == "RouteGroup") {
2390 RouteGroup* rg = new RouteGroup (*this, "");
2391 add_route_group (rg);
2392 rg->set_state (**niter, version);
2396 } else if (version < 3000) {
2398 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2399 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2400 RouteGroup* rg = new RouteGroup (*this, "");
2401 add_route_group (rg);
2402 rg->set_state (**niter, version);
2411 state_file_filter (const string &str, void* /*arg*/)
2413 return (str.length() > strlen(statefile_suffix) &&
2414 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2418 remove_end(string state)
2420 string statename(state);
2422 string::size_type start,end;
2423 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2424 statename = statename.substr (start+1);
2427 if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2428 end = statename.length();
2431 return string(statename.substr (0, end));
2435 Session::possible_states (string path)
2437 vector<string> states;
2438 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2440 transform(states.begin(), states.end(), states.begin(), remove_end);
2442 sort (states.begin(), states.end());
2448 Session::possible_states () const
2450 return possible_states(_path);
2454 Session::add_route_group (RouteGroup* g)
2456 _route_groups.push_back (g);
2457 route_group_added (g); /* EMIT SIGNAL */
2459 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2460 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2461 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2467 Session::remove_route_group (RouteGroup& rg)
2469 list<RouteGroup*>::iterator i;
2471 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2472 _route_groups.erase (i);
2475 route_group_removed (); /* EMIT SIGNAL */
2479 /** Set a new order for our route groups, without adding or removing any.
2480 * @param groups Route group list in the new order.
2483 Session::reorder_route_groups (list<RouteGroup*> groups)
2485 _route_groups = groups;
2487 route_groups_reordered (); /* EMIT SIGNAL */
2493 Session::route_group_by_name (string name)
2495 list<RouteGroup *>::iterator i;
2497 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2498 if ((*i)->name() == name) {
2506 Session::all_route_group() const
2508 return *_all_route_group;
2512 Session::add_commands (vector<Command*> const & cmds)
2514 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2520 Session::begin_reversible_command (const string& name)
2522 begin_reversible_command (g_quark_from_string (name.c_str ()));
2525 /** Begin a reversible command using a GQuark to identify it.
2526 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2527 * but there must be as many begin...()s as there are commit...()s.
2530 Session::begin_reversible_command (GQuark q)
2532 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2533 to hold all the commands that are committed. This keeps the order of
2534 commands correct in the history.
2537 if (_current_trans == 0) {
2538 /* start a new transaction */
2539 assert (_current_trans_quarks.empty ());
2540 _current_trans = new UndoTransaction();
2541 _current_trans->set_name (g_quark_to_string (q));
2544 _current_trans_quarks.push_front (q);
2548 Session::abort_reversible_command ()
2550 if (_current_trans != 0) {
2551 _current_trans->clear();
2552 delete _current_trans;
2554 _current_trans_quarks.clear();
2559 Session::commit_reversible_command (Command *cmd)
2561 assert (_current_trans);
2562 assert (!_current_trans_quarks.empty ());
2567 _current_trans->add_command (cmd);
2570 _current_trans_quarks.pop_front ();
2572 if (!_current_trans_quarks.empty ()) {
2573 /* the transaction we're committing is not the top-level one */
2577 if (_current_trans->empty()) {
2578 /* no commands were added to the transaction, so just get rid of it */
2579 delete _current_trans;
2584 gettimeofday (&now, 0);
2585 _current_trans->set_timestamp (now);
2587 _history.add (_current_trans);
2592 accept_all_audio_files (const string& path, void* /*arg*/)
2594 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2598 if (!AudioFileSource::safe_audio_file_extension (path)) {
2606 accept_all_midi_files (const string& path, void* /*arg*/)
2608 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2612 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2613 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2614 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2618 accept_all_state_files (const string& path, void* /*arg*/)
2620 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2624 std::string const statefile_ext (statefile_suffix);
2625 if (path.length() >= statefile_ext.length()) {
2626 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2633 Session::find_all_sources (string path, set<string>& result)
2638 if (!tree.read (path)) {
2642 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2647 XMLNodeConstIterator niter;
2649 nlist = node->children();
2653 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2657 if ((prop = (*niter)->property (X_("type"))) == 0) {
2661 DataType type (prop->value());
2663 if ((prop = (*niter)->property (X_("name"))) == 0) {
2667 if (Glib::path_is_absolute (prop->value())) {
2668 /* external file, ignore */
2676 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2677 result.insert (found_path);
2685 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2687 vector<string> state_files;
2689 string this_snapshot_path;
2695 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2696 ripped = ripped.substr (0, ripped.length() - 1);
2699 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2701 if (state_files.empty()) {
2706 this_snapshot_path = _path;
2707 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2708 this_snapshot_path += statefile_suffix;
2710 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2712 if (exclude_this_snapshot && *i == this_snapshot_path) {
2716 if (find_all_sources (*i, result) < 0) {
2724 struct RegionCounter {
2725 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2726 AudioSourceList::iterator iter;
2727 boost::shared_ptr<Region> region;
2730 RegionCounter() : count (0) {}
2734 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2736 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2737 return r.get_value_or (1);
2741 Session::cleanup_regions ()
2743 bool removed = false;
2744 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2746 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2748 uint32_t used = playlists->region_use_count (i->second);
2750 if (used == 0 && !i->second->automatic ()) {
2752 RegionFactory::map_remove (i->second);
2757 // re-check to remove parent references of compound regions
2758 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2759 if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2762 assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2763 if (0 == playlists->region_use_count (i->second)) {
2764 RegionFactory::map_remove (i->second);
2769 /* dump the history list */
2776 Session::cleanup_sources (CleanupReport& rep)
2778 // FIXME: needs adaptation to midi
2780 vector<boost::shared_ptr<Source> > dead_sources;
2783 vector<string> candidates;
2784 vector<string> unused;
2785 set<string> all_sources;
2794 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2796 /* consider deleting all unused playlists */
2798 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2803 /* sync the "all regions" property of each playlist with its current state
2806 playlists->sync_all_regions_with_regions ();
2808 /* find all un-used sources */
2813 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2815 SourceMap::iterator tmp;
2820 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2824 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2825 dead_sources.push_back (i->second);
2826 i->second->drop_references ();
2832 /* build a list of all the possible audio directories for the session */
2834 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2835 SessionDirectory sdir ((*i).path);
2836 asp += sdir.sound_path();
2838 audio_path += asp.to_string();
2841 /* build a list of all the possible midi directories for the session */
2843 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2844 SessionDirectory sdir ((*i).path);
2845 msp += sdir.midi_path();
2847 midi_path += msp.to_string();
2849 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
2850 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
2852 /* find all sources, but don't use this snapshot because the
2853 state file on disk still references sources we may have already
2857 find_all_sources_across_snapshots (all_sources, true);
2859 /* add our current source list
2862 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2863 boost::shared_ptr<FileSource> fs;
2864 SourceMap::iterator tmp = i;
2867 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2869 if (!fs->is_stub()) {
2871 if (playlists->source_use_count (fs) != 0) {
2872 all_sources.insert (fs->path());
2875 /* we might not remove this source from disk, because it may be used
2876 by other snapshots, but its not being used in this version
2877 so lets get rid of it now, along with any representative regions
2881 RegionFactory::remove_regions_using_source (i->second);
2884 // also remove source from all_sources
2886 for (set<string>::iterator j = all_sources.begin(); j != all_sources.end(); ++j) {
2887 spath = Glib::path_get_basename (*j);
2888 if ( spath == i->second->name () ) {
2889 all_sources.erase (j);
2900 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
2905 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2907 tmppath1 = canonical_path (spath);
2908 tmppath2 = canonical_path ((*i));
2910 if (tmppath1 == tmppath2) {
2917 unused.push_back (spath);
2921 /* now try to move all unused files into the "dead" directory(ies) */
2923 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2924 struct stat statbuf;
2928 /* don't move the file across filesystems, just
2929 stick it in the `dead_dir_name' directory
2930 on whichever filesystem it was already on.
2933 if ((*x).find ("/sounds/") != string::npos) {
2935 /* old school, go up 1 level */
2937 newpath = Glib::path_get_dirname (*x); // "sounds"
2938 newpath = Glib::path_get_dirname (newpath); // "session-name"
2942 /* new school, go up 4 levels */
2944 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2945 newpath = Glib::path_get_dirname (newpath); // "session-name"
2946 newpath = Glib::path_get_dirname (newpath); // "interchange"
2947 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2950 newpath = Glib::build_filename (newpath, dead_dir_name);
2952 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2953 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2957 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2959 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2961 /* the new path already exists, try versioning */
2963 char buf[PATH_MAX+1];
2967 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2970 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2971 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2975 if (version == 999) {
2976 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2980 newpath = newpath_v;
2985 /* it doesn't exist, or we can't read it or something */
2989 stat ((*x).c_str(), &statbuf);
2991 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2992 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2993 (*x), newpath, strerror (errno))
2998 /* see if there an easy to find peakfile for this file, and remove it.
3001 string base = basename_nosuffix (*x);
3002 base += "%A"; /* this is what we add for the channel suffix of all native files,
3003 or for the first channel of embedded files. it will miss
3004 some peakfiles for other channels
3006 string peakpath = peak_path (base);
3008 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
3009 if (::g_unlink (peakpath.c_str()) != 0) {
3010 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3011 peakpath, _path, strerror (errno))
3013 /* try to back out */
3014 ::rename (newpath.c_str(), _path.c_str());
3019 rep.paths.push_back (*x);
3020 rep.space += statbuf.st_size;
3023 /* dump the history list */
3027 /* save state so we don't end up a session file
3028 referring to non-existent sources.
3035 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3041 Session::cleanup_trash_sources (CleanupReport& rep)
3043 // FIXME: needs adaptation for MIDI
3045 vector<space_and_path>::iterator i;
3051 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3053 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
3055 clear_directory (dead_dir, &rep.space, &rep.paths);
3062 Session::set_dirty ()
3064 /* never mark session dirty during loading */
3066 if (_state_of_the_state & Loading) {
3070 bool was_dirty = dirty();
3072 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3076 DirtyChanged(); /* EMIT SIGNAL */
3082 Session::set_clean ()
3084 bool was_dirty = dirty();
3086 _state_of_the_state = Clean;
3090 DirtyChanged(); /* EMIT SIGNAL */
3095 Session::set_deletion_in_progress ()
3097 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3101 Session::clear_deletion_in_progress ()
3103 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3107 Session::add_controllable (boost::shared_ptr<Controllable> c)
3109 /* this adds a controllable to the list managed by the Session.
3110 this is a subset of those managed by the Controllable class
3111 itself, and represents the only ones whose state will be saved
3112 as part of the session.
3115 Glib::Threads::Mutex::Lock lm (controllables_lock);
3116 controllables.insert (c);
3119 struct null_deleter { void operator()(void const *) const {} };
3122 Session::remove_controllable (Controllable* c)
3124 if (_state_of_the_state & Deletion) {
3128 Glib::Threads::Mutex::Lock lm (controllables_lock);
3130 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3132 if (x != controllables.end()) {
3133 controllables.erase (x);
3137 boost::shared_ptr<Controllable>
3138 Session::controllable_by_id (const PBD::ID& id)
3140 Glib::Threads::Mutex::Lock lm (controllables_lock);
3142 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3143 if ((*i)->id() == id) {
3148 return boost::shared_ptr<Controllable>();
3151 boost::shared_ptr<Controllable>
3152 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3154 boost::shared_ptr<Controllable> c;
3155 boost::shared_ptr<Route> r;
3157 switch (desc.top_level_type()) {
3158 case ControllableDescriptor::NamedRoute:
3160 std::string str = desc.top_level_name();
3161 if (str == "Master" || str == "master") {
3163 } else if (str == "control" || str == "listen") {
3166 r = route_by_name (desc.top_level_name());
3171 case ControllableDescriptor::RemoteControlID:
3172 r = route_by_remote_id (desc.rid());
3180 switch (desc.subtype()) {
3181 case ControllableDescriptor::Gain:
3182 c = r->gain_control ();
3185 case ControllableDescriptor::Trim:
3186 c = r->trim()->gain_control ();
3189 case ControllableDescriptor::Solo:
3190 c = r->solo_control();
3193 case ControllableDescriptor::Mute:
3194 c = r->mute_control();
3197 case ControllableDescriptor::Recenable:
3199 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3202 c = t->rec_enable_control ();
3207 case ControllableDescriptor::PanDirection:
3209 c = r->pannable()->pan_azimuth_control;
3213 case ControllableDescriptor::PanWidth:
3215 c = r->pannable()->pan_width_control;
3219 case ControllableDescriptor::PanElevation:
3221 c = r->pannable()->pan_elevation_control;
3225 case ControllableDescriptor::Balance:
3226 /* XXX simple pan control */
3229 case ControllableDescriptor::PluginParameter:
3231 uint32_t plugin = desc.target (0);
3232 uint32_t parameter_index = desc.target (1);
3234 /* revert to zero based counting */
3240 if (parameter_index > 0) {
3244 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3247 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3248 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3253 case ControllableDescriptor::SendGain:
3255 uint32_t send = desc.target (0);
3257 /* revert to zero-based counting */
3263 boost::shared_ptr<Processor> p = r->nth_send (send);
3266 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3267 boost::shared_ptr<Amp> a = s->amp();
3270 c = s->amp()->gain_control();
3277 /* relax and return a null pointer */
3285 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3288 Stateful::add_instant_xml (node, _path);
3291 if (write_to_config) {
3292 Config->add_instant_xml (node);
3297 Session::instant_xml (const string& node_name)
3299 return Stateful::instant_xml (node_name, _path);
3303 Session::save_history (string snapshot_name)
3311 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3312 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3316 if (snapshot_name.empty()) {
3317 snapshot_name = _current_snapshot_name;
3320 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3321 const string backup_filename = history_filename + backup_suffix;
3322 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3323 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3325 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3326 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3327 error << _("could not backup old history file, current history not saved") << endmsg;
3332 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3334 if (!tree.write (xml_path))
3336 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3338 if (g_remove (xml_path.c_str()) != 0) {
3339 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3340 xml_path, g_strerror (errno)) << endmsg;
3342 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3343 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3344 backup_path, g_strerror (errno)) << endmsg;
3354 Session::restore_history (string snapshot_name)
3358 if (snapshot_name.empty()) {
3359 snapshot_name = _current_snapshot_name;
3362 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3363 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3365 info << "Loading history from " << xml_path << endmsg;
3367 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3368 info << string_compose (_("%1: no history file \"%2\" for this session."),
3369 _name, xml_path) << endmsg;
3373 if (!tree.read (xml_path)) {
3374 error << string_compose (_("Could not understand session history file \"%1\""),
3375 xml_path) << endmsg;
3382 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3385 UndoTransaction* ut = new UndoTransaction ();
3388 ut->set_name(t->property("name")->value());
3389 stringstream ss(t->property("tv-sec")->value());
3391 ss.str(t->property("tv-usec")->value());
3393 ut->set_timestamp(tv);
3395 for (XMLNodeConstIterator child_it = t->children().begin();
3396 child_it != t->children().end(); child_it++)
3398 XMLNode *n = *child_it;
3401 if (n->name() == "MementoCommand" ||
3402 n->name() == "MementoUndoCommand" ||
3403 n->name() == "MementoRedoCommand") {
3405 if ((c = memento_command_factory(n))) {
3409 } else if (n->name() == "NoteDiffCommand") {
3410 PBD::ID id (n->property("midi-source")->value());
3411 boost::shared_ptr<MidiSource> midi_source =
3412 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3414 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3416 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3419 } else if (n->name() == "SysExDiffCommand") {
3421 PBD::ID id (n->property("midi-source")->value());
3422 boost::shared_ptr<MidiSource> midi_source =
3423 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3425 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3427 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3430 } else if (n->name() == "PatchChangeDiffCommand") {
3432 PBD::ID id (n->property("midi-source")->value());
3433 boost::shared_ptr<MidiSource> midi_source =
3434 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3436 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3438 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3441 } else if (n->name() == "StatefulDiffCommand") {
3442 if ((c = stateful_diff_command_factory (n))) {
3443 ut->add_command (c);
3446 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3457 Session::config_changed (std::string p, bool ours)
3463 if (p == "seamless-loop") {
3465 } else if (p == "rf-speed") {
3467 } else if (p == "auto-loop") {
3469 } else if (p == "auto-input") {
3471 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3472 /* auto-input only makes a difference if we're rolling */
3473 set_track_monitor_input_status (!config.get_auto_input());
3476 } else if (p == "punch-in") {
3480 if ((location = _locations->auto_punch_location()) != 0) {
3482 if (config.get_punch_in ()) {
3483 replace_event (SessionEvent::PunchIn, location->start());
3485 remove_event (location->start(), SessionEvent::PunchIn);
3489 } else if (p == "punch-out") {
3493 if ((location = _locations->auto_punch_location()) != 0) {
3495 if (config.get_punch_out()) {
3496 replace_event (SessionEvent::PunchOut, location->end());
3498 clear_events (SessionEvent::PunchOut);
3502 } else if (p == "edit-mode") {
3504 Glib::Threads::Mutex::Lock lm (playlists->lock);
3506 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3507 (*i)->set_edit_mode (Config->get_edit_mode ());
3510 } else if (p == "use-video-sync") {
3512 waiting_for_sync_offset = config.get_use_video_sync();
3514 } else if (p == "mmc-control") {
3516 //poke_midi_thread ();
3518 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3520 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3522 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3524 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3526 } else if (p == "midi-control") {
3528 //poke_midi_thread ();
3530 } else if (p == "raid-path") {
3532 setup_raid_path (config.get_raid_path());
3534 } else if (p == "timecode-format") {
3538 } else if (p == "video-pullup") {
3542 } else if (p == "seamless-loop") {
3544 if (play_loop && transport_rolling()) {
3545 // to reset diskstreams etc
3546 request_play_loop (true);
3549 } else if (p == "rf-speed") {
3551 cumulative_rf_motion = 0;
3554 } else if (p == "click-sound") {
3556 setup_click_sounds (1);
3558 } else if (p == "click-emphasis-sound") {
3560 setup_click_sounds (-1);
3562 } else if (p == "clicking") {
3564 if (Config->get_clicking()) {
3565 if (_click_io && click_data) { // don't require emphasis data
3572 } else if (p == "click-gain") {
3575 _click_gain->set_gain (Config->get_click_gain(), this);
3578 } else if (p == "send-mtc") {
3580 if (Config->get_send_mtc ()) {
3581 /* mark us ready to send */
3582 next_quarter_frame_to_send = 0;
3585 } else if (p == "send-mmc") {
3587 _mmc->enable_send (Config->get_send_mmc ());
3589 } else if (p == "midi-feedback") {
3591 session_midi_feedback = Config->get_midi_feedback();
3593 } else if (p == "jack-time-master") {
3595 engine().reset_timebase ();
3597 } else if (p == "native-file-header-format") {
3599 if (!first_file_header_format_reset) {
3600 reset_native_file_format ();
3603 first_file_header_format_reset = false;
3605 } else if (p == "native-file-data-format") {
3607 if (!first_file_data_format_reset) {
3608 reset_native_file_format ();
3611 first_file_data_format_reset = false;
3613 } else if (p == "external-sync") {
3614 if (!config.get_external_sync()) {
3615 drop_sync_source ();
3617 switch_to_sync_source (Config->get_sync_source());
3619 } else if (p == "denormal-model") {
3621 } else if (p == "history-depth") {
3622 set_history_depth (Config->get_history_depth());
3623 } else if (p == "remote-model") {
3624 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3627 } else if (p == "initial-program-change") {
3629 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3632 buf[0] = MIDI::program; // channel zero by default
3633 buf[1] = (Config->get_initial_program_change() & 0x7f);
3635 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3637 } else if (p == "solo-mute-override") {
3638 // catch_up_on_solo_mute_override ();
3639 } else if (p == "listen-position" || p == "pfl-position") {
3640 listen_position_changed ();
3641 } else if (p == "solo-control-is-listen-control") {
3642 solo_control_mode_changed ();
3643 } else if (p == "solo-mute-gain") {
3644 _solo_cut_control->Changed();
3645 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3646 last_timecode_valid = false;
3647 } else if (p == "playback-buffer-seconds") {
3648 AudioSource::allocate_working_buffers (frame_rate());
3649 } else if (p == "ltc-source-port") {
3650 reconnect_ltc_input ();
3651 } else if (p == "ltc-sink-port") {
3652 reconnect_ltc_output ();
3653 } else if (p == "timecode-generator-offset") {
3654 ltc_tx_parse_offset();
3661 Session::set_history_depth (uint32_t d)
3663 _history.set_depth (d);
3667 Session::load_diskstreams_2X (XMLNode const & node, int)
3670 XMLNodeConstIterator citer;
3672 clist = node.children();
3674 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3677 /* diskstreams added automatically by DiskstreamCreated handler */
3678 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3679 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3680 _diskstreams_2X.push_back (dsp);
3682 error << _("Session: unknown diskstream type in XML") << endmsg;
3686 catch (failed_constructor& err) {
3687 error << _("Session: could not load diskstream via XML state") << endmsg;
3695 /** Connect things to the MMC object */
3697 Session::setup_midi_machine_control ()
3699 _mmc = new MIDI::MachineControl;
3700 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3702 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3703 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3704 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3705 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3706 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3707 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3708 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3709 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3710 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3711 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3712 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3713 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3714 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3716 /* also handle MIDI SPP because its so common */
3718 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3719 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3720 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3723 boost::shared_ptr<Controllable>
3724 Session::solo_cut_control() const
3726 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3727 controls in Ardour that currently get presented to the user in the GUI that require
3728 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3730 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3731 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3735 return _solo_cut_control;
3739 Session::rename (const std::string& new_name)
3741 string legal_name = legalize_for_path (new_name);
3747 string const old_sources_root = _session_dir->sources_root();
3749 if (!_writable || (_state_of_the_state & CannotSave)) {
3750 error << _("Cannot rename read-only session.") << endmsg;
3751 return 0; // don't show "messed up" warning
3753 if (record_status() == Recording) {
3754 error << _("Cannot rename session while recording") << endmsg;
3755 return 0; // don't show "messed up" warning
3758 StateProtector stp (this);
3763 * interchange subdirectory
3767 * Backup files are left unchanged and not renamed.
3770 /* Windows requires that we close all files before attempting the
3771 * rename. This works on other platforms, but isn't necessary there.
3772 * Leave it in place for all platforms though, since it may help
3773 * catch issues that could arise if the way Source files work ever
3774 * change (since most developers are not using Windows).
3777 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
3778 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3784 /* pass one: not 100% safe check that the new directory names don't
3788 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3792 /* this is a stupid hack because Glib::path_get_dirname() is
3793 * lexical-only, and so passing it /a/b/c/ gives a different
3794 * result than passing it /a/b/c ...
3797 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3798 oldstr = oldstr.substr (0, oldstr.length() - 1);
3801 string base = Glib::path_get_dirname (oldstr);
3803 newstr = Glib::build_filename (base, legal_name);
3805 cerr << "Looking for " << newstr << endl;
3807 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3808 cerr << " exists\n";
3817 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3823 /* this is a stupid hack because Glib::path_get_dirname() is
3824 * lexical-only, and so passing it /a/b/c/ gives a different
3825 * result than passing it /a/b/c ...
3828 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3829 oldstr = oldstr.substr (0, oldstr.length() - 1);
3832 string base = Glib::path_get_dirname (oldstr);
3833 newstr = Glib::build_filename (base, legal_name);
3835 cerr << "for " << oldstr << " new dir = " << newstr << endl;
3837 cerr << "Rename " << oldstr << " => " << newstr << endl;
3838 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3839 cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3840 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3844 /* Reset path in "session dirs" */
3849 /* reset primary SessionDirectory object */
3852 (*_session_dir) = newstr;
3857 /* now rename directory below session_dir/interchange */
3859 string old_interchange_dir;
3860 string new_interchange_dir;
3862 /* use newstr here because we renamed the path
3863 * (folder/directory) that used to be oldstr to newstr above
3866 v.push_back (newstr);
3867 v.push_back (interchange_dir_name);
3868 v.push_back (Glib::path_get_basename (oldstr));
3870 old_interchange_dir = Glib::build_filename (v);
3873 v.push_back (newstr);
3874 v.push_back (interchange_dir_name);
3875 v.push_back (legal_name);
3877 new_interchange_dir = Glib::build_filename (v);
3879 cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
3881 if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
3882 cerr << string_compose (_("renaming %s as %2 failed (%3)"),
3883 old_interchange_dir, new_interchange_dir,
3886 error << string_compose (_("renaming %s as %2 failed (%3)"),
3887 old_interchange_dir, new_interchange_dir,
3896 oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
3897 newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
3899 cerr << "Rename " << oldstr << " => " << newstr << endl;
3901 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3902 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3903 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3909 oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
3911 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3912 newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
3914 cerr << "Rename " << oldstr << " => " << newstr << endl;
3916 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3917 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3918 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3923 /* remove old name from recent sessions */
3924 remove_recent_sessions (_path);
3927 /* update file source paths */
3929 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3930 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3932 string p = fs->path ();
3933 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3935 SourceFactory::setup_peakfile(i->second, true);
3939 _current_snapshot_name = new_name;
3944 /* save state again to get everything just right */
3946 save_state (_current_snapshot_name);
3948 /* add to recent sessions */
3950 store_recent_sessions (new_name, _path);
3956 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
3958 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
3962 if (!tree.read (xmlpath)) {
3970 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
3973 bool found_sr = false;
3974 bool found_data_format = false;
3976 if (get_session_info_from_path (tree, xmlpath)) {
3982 const XMLProperty* prop;
3983 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
3984 sample_rate = atoi (prop->value());
3988 const XMLNodeList& children (tree.root()->children());
3989 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
3990 const XMLNode* child = *c;
3991 if (child->name() == "Config") {
3992 const XMLNodeList& options (child->children());
3993 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
3994 const XMLNode* option = *oc;
3995 const XMLProperty* name = option->property("name");
4001 if (name->value() == "native-file-data-format") {
4002 const XMLProperty* value = option->property ("value");
4004 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
4006 found_data_format = true;
4012 if (found_data_format) {
4017 return !(found_sr && found_data_format); // zero if they are both found
4020 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
4021 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
4024 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
4028 SourcePathMap source_path_map;
4030 boost::shared_ptr<AudioFileSource> afs;
4035 Glib::Threads::Mutex::Lock lm (source_lock);
4037 cerr << " total sources = " << sources.size();
4039 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4040 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4046 if (fs->within_session()) {
4050 if (source_path_map.find (fs->path()) != source_path_map.end()) {
4051 source_path_map[fs->path()].push_back (fs);
4053 SeveralFileSources v;
4055 source_path_map.insert (make_pair (fs->path(), v));
4061 cerr << " fsources = " << total << endl;
4063 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
4065 /* tell caller where we are */
4067 string old_path = i->first;
4069 callback (n, total, old_path);
4071 cerr << old_path << endl;
4075 switch (i->second.front()->type()) {
4076 case DataType::AUDIO:
4077 new_path = new_audio_source_path_for_embedded (old_path);
4080 case DataType::MIDI:
4081 /* XXX not implemented yet */
4085 if (new_path.empty()) {
4089 cerr << "Move " << old_path << " => " << new_path << endl;
4091 if (!copy_file (old_path, new_path)) {
4092 cerr << "failed !\n";
4096 /* make sure we stop looking in the external
4097 dir/folder. Remember, this is an all-or-nothing
4098 operations, it doesn't merge just some files.
4100 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
4102 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
4103 (*f)->set_path (new_path);
4108 save_state ("", false, false);
4114 bool accept_all_files (string const &, void *)
4120 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4122 /* It would be good if this did something useful vis-a-vis save-as, but the arguments doesn't provide the correct information right now to do this.
4127 make_new_media_path (string old_path, string new_session_folder, string new_session_path)
4129 /* typedir is the "midifiles" or "audiofiles" etc. part of the path. */
4131 string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4133 v.push_back (new_session_folder); /* full path */
4134 v.push_back (interchange_dir_name);
4135 v.push_back (new_session_path); /* just one directory/folder */
4136 v.push_back (typedir);
4137 v.push_back (Glib::path_get_basename (old_path));
4139 return Glib::build_filename (v);
4143 Session::save_as (SaveAs& saveas)
4145 vector<string> files;
4146 string current_folder = Glib::path_get_dirname (_path);
4147 string new_folder = legalize_for_path (saveas.new_name);
4148 string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4149 int64_t total_bytes = 0;
4153 int32_t internal_file_cnt = 0;
4155 vector<string> do_not_copy_extensions;
4156 do_not_copy_extensions.push_back (statefile_suffix);
4157 do_not_copy_extensions.push_back (pending_suffix);
4158 do_not_copy_extensions.push_back (backup_suffix);
4159 do_not_copy_extensions.push_back (temp_suffix);
4160 do_not_copy_extensions.push_back (history_suffix);
4162 /* get total size */
4164 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4166 /* need to clear this because
4167 * find_files_matching_filter() is cumulative
4172 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4174 all += files.size();
4176 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4178 g_stat ((*i).c_str(), &gsb);
4179 total_bytes += gsb.st_size;
4183 /* save old values so we can switch back if we are not switching to the new session */
4185 string old_path = _path;
4186 string old_name = _name;
4187 string old_snapshot = _current_snapshot_name;
4188 string old_sd = _session_dir->root_path();
4189 vector<string> old_search_path[DataType::num_types];
4190 string old_config_search_path[DataType::num_types];
4192 old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4193 old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4194 old_config_search_path[DataType::AUDIO] = config.get_audio_search_path ();
4195 old_config_search_path[DataType::MIDI] = config.get_midi_search_path ();
4197 /* switch session directory */
4199 (*_session_dir) = to_dir;
4201 /* create new tree */
4203 if (!_session_dir->create()) {
4204 saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4209 /* copy all relevant files. Find each location in session_dirs,
4210 * and copy files from there to target.
4213 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4215 /* need to clear this because
4216 * find_files_matching_filter() is cumulative
4221 const size_t prefix_len = (*sd).path.size();
4223 /* Work just on the files within this session dir */
4225 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4227 /* add dir separator to protect against collisions with
4228 * track names (e.g. track named "audiofiles" or
4232 static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
4233 static const std::string midifile_dir_string = string (midi_dir_name) + G_DIR_SEPARATOR;
4234 static const std::string analysis_dir_string = analysis_dir() + G_DIR_SEPARATOR;
4236 /* copy all the files. Handling is different for media files
4237 than others because of the *silly* subtree we have below the interchange
4238 folder. That really was a bad idea, but I'm not fixing it as part of
4239 implementing ::save_as().
4242 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4244 std::string from = *i;
4247 string filename = Glib::path_get_basename (from);
4248 std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
4249 if (filename == ".DS_STORE") {
4254 if (from.find (audiofile_dir_string) != string::npos) {
4256 /* audio file: only copy if asked */
4258 if (saveas.include_media && saveas.copy_media) {
4260 string to = make_new_media_path (*i, to_dir, new_folder);
4262 info << "media file copying from " << from << " to " << to << endmsg;
4264 if (!copy_file (from, to)) {
4265 throw Glib::FileError (Glib::FileError::IO_ERROR,
4266 string_compose(_("\ncopying \"%1\" failed !"), from));
4270 /* we found media files inside the session folder */
4272 internal_file_cnt++;
4274 } else if (from.find (midifile_dir_string) != string::npos) {
4276 /* midi file: always copy unless
4277 * creating an empty new session
4280 if (saveas.include_media) {
4282 string to = make_new_media_path (*i, to_dir, new_folder);
4284 info << "media file copying from " << from << " to " << to << endmsg;
4286 if (!copy_file (from, to)) {
4287 throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4291 /* we found media files inside the session folder */
4293 internal_file_cnt++;
4295 } else if (from.find (analysis_dir_string) != string::npos) {
4297 /* make sure analysis dir exists in
4298 * new session folder, but we're not
4299 * copying analysis files here, see
4303 (void) g_mkdir_with_parents (analysis_dir().c_str(), 775);
4308 /* normal non-media file. Don't copy state, history, etc.
4311 bool do_copy = true;
4313 for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
4314 if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
4315 /* end of filename matches extension, do not copy file */
4321 if (!saveas.copy_media && from.find (peakfile_suffix) != string::npos) {
4322 /* don't copy peakfiles if
4323 * we're not copying media
4329 string to = Glib::build_filename (to_dir, from.substr (prefix_len));
4331 info << "attempting to make directory/folder " << to << endmsg;
4333 if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
4334 throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
4337 info << "attempting to copy " << from << " to " << to << endmsg;
4339 if (!copy_file (from, to)) {
4340 throw Glib::FileError (Glib::FileError::IO_ERROR,
4341 string_compose(_("\ncopying \"%1\" failed !"), from));
4346 /* measure file size even if we're not going to copy so that our Progress
4347 signals are correct, since we included these do-not-copy files
4348 in the computation of the total size and file count.
4352 g_stat (from.c_str(), &gsb);
4353 copied += gsb.st_size;
4356 double fraction = (double) copied / total_bytes;
4358 bool keep_going = true;
4360 if (saveas.copy_media) {
4362 /* no need or expectation of this if
4363 * media is not being copied, because
4364 * it will be fast(ish).
4367 /* tell someone "X percent, file M of N"; M is one-based */
4369 boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
4377 throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
4383 /* copy optional folders, if any */
4385 string old = plugins_dir ();
4386 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4387 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4388 copy_files (old, newdir);
4391 old = externals_dir ();
4392 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4393 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4394 copy_files (old, newdir);
4397 old = automation_dir ();
4398 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4399 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4400 copy_files (old, newdir);
4403 if (saveas.include_media) {
4405 if (saveas.copy_media) {
4406 #ifndef PLATFORM_WINDOWS
4407 /* There are problems with analysis files on
4408 * Windows, because they used a colon in their
4409 * names as late as 4.0. Colons are not legal
4410 * under Windows even if NTFS allows them.
4412 * This is a tricky problem to solve so for
4413 * just don't copy these files. They will be
4414 * regenerated as-needed anyway, subject to the
4415 * existing issue that the filenames will be
4416 * rejected by Windows, which is a separate
4417 * problem (though related).
4420 /* only needed if we are copying media, since the
4421 * analysis data refers to media data
4424 old = analysis_dir ();
4425 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4426 string newdir = Glib::build_filename (to_dir, "analysis");
4427 copy_files (old, newdir);
4429 #endif /* PLATFORM_WINDOWS */
4435 _current_snapshot_name = saveas.new_name;
4436 _name = saveas.new_name;
4438 if (saveas.include_media && !saveas.copy_media) {
4440 /* reset search paths of the new session (which we're pretending to be right now) to
4441 include the original session search path, so we can still find all audio.
4444 if (internal_file_cnt) {
4445 for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
4446 ensure_search_path_includes (*s, DataType::AUDIO);
4449 /* we do not do this for MIDI because we copy
4450 all MIDI files if saveas.include_media is
4456 bool was_dirty = dirty ();
4458 save_state ("", false, false, !saveas.include_media);
4459 save_default_options ();
4461 if (saveas.copy_media && saveas.copy_external) {
4462 if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
4463 throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
4467 saveas.final_session_folder_name = _path;
4469 store_recent_sessions (_name, _path);
4471 if (!saveas.switch_to) {
4473 /* switch back to the way things were */
4477 _current_snapshot_name = old_snapshot;
4479 (*_session_dir) = old_sd;
4485 if (internal_file_cnt) {
4486 /* reset these to their original values */
4487 config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
4488 config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
4493 /* prune session dirs, and update disk space statistics
4498 session_dirs.clear ();
4499 session_dirs.push_back (sp);
4500 refresh_disk_space ();
4502 /* ensure that all existing tracks reset their current capture source paths
4504 reset_write_sources (true, true);
4506 /* the copying above was based on actually discovering files, not just iterating over the sources list.
4507 But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
4510 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4511 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4517 if (fs->within_session()) {
4518 string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
4519 fs->set_path (newpath);
4524 } catch (Glib::FileError& e) {
4526 saveas.failure_message = e.what();
4528 /* recursively remove all the directories */
4530 remove_directory (to_dir);
4538 saveas.failure_message = _("unknown reason");
4540 /* recursively remove all the directories */
4542 remove_directory (to_dir);