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);
274 _butler->map_parameters ();
276 /* Reset all panners */
278 Delivery::reset_panners ();
280 /* this will cause the CPM to instantiate any protocols that are in use
281 * (or mandatory), which will pass it this Session, and then call
282 * set_state() on each instantiated protocol to match stored state.
285 ControlProtocolManager::instance().set_session (this);
287 /* This must be done after the ControlProtocolManager set_session above,
288 as it will set states for ports which the ControlProtocolManager creates.
291 // XXX set state of MIDI::Port's
292 // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
294 /* And this must be done after the MIDI::Manager::set_port_states as
295 * it will try to make connections whose details are loaded by set_port_states.
300 /* Let control protocols know that we are now all connected, so they
301 * could start talking to surfaces if they want to.
304 ControlProtocolManager::instance().midi_connectivity_established ();
306 if (_is_new && !no_auto_connect()) {
307 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
308 auto_connect_master_bus ();
311 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
313 /* update latencies */
315 initialize_latencies ();
317 _locations->added.connect_same_thread (*this, boost::bind (&Session::location_added, this, _1));
318 _locations->removed.connect_same_thread (*this, boost::bind (&Session::location_removed, this, _1));
319 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
321 } catch (AudioEngine::PortRegistrationFailure& err) {
322 /* handle this one in a different way than all others, so that its clear what happened */
323 error << err.what() << endmsg;
329 BootMessage (_("Reset Remote Controls"));
331 // send_full_time_code (0);
332 _engine.transport_locate (0);
334 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
335 send_immediate_mmc (MIDI::MachineControlCommand (Timecode::Time ()));
337 MIDI::Name::MidiPatchManager::instance().set_session (this);
340 /* initial program change will be delivered later; see ::config_changed() */
342 _state_of_the_state = Clean;
344 Port::set_connecting_blocked (false);
346 DirtyChanged (); /* EMIT SIGNAL */
350 } else if (state_was_pending) {
352 remove_pending_capture_state ();
353 state_was_pending = false;
356 /* Now, finally, we can fill the playback buffers */
358 BootMessage (_("Filling playback buffers"));
360 boost::shared_ptr<RouteList> rl = routes.reader();
361 for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
362 boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<Track> (*r);
363 if (trk && !trk->hidden()) {
364 trk->seek (_transport_frame, true);
372 Session::session_loaded ()
376 _state_of_the_state = Clean;
378 DirtyChanged (); /* EMIT SIGNAL */
382 } else if (state_was_pending) {
384 remove_pending_capture_state ();
385 state_was_pending = false;
388 /* Now, finally, we can fill the playback buffers */
390 BootMessage (_("Filling playback buffers"));
392 boost::shared_ptr<RouteList> rl = routes.reader();
393 for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
394 boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<Track> (*r);
395 if (trk && !trk->hidden()) {
396 trk->seek (_transport_frame, true);
402 Session::raid_path () const
404 Searchpath raid_search_path;
406 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
407 raid_search_path += (*i).path;
410 return raid_search_path.to_string ();
414 Session::setup_raid_path (string path)
423 session_dirs.clear ();
425 Searchpath search_path(path);
426 Searchpath sound_search_path;
427 Searchpath midi_search_path;
429 for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
431 sp.blocks = 0; // not needed
432 session_dirs.push_back (sp);
434 SessionDirectory sdir(sp.path);
436 sound_search_path += sdir.sound_path ();
437 midi_search_path += sdir.midi_path ();
440 // reset the round-robin soundfile path thingie
441 last_rr_session_dir = session_dirs.begin();
445 Session::path_is_within_session (const std::string& path)
447 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
448 if (PBD::path_is_within (i->path, path)) {
456 Session::ensure_subdirs ()
460 dir = session_directory().peak_path();
462 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
463 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
467 dir = session_directory().sound_path();
469 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
470 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
474 dir = session_directory().midi_path();
476 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
477 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
481 dir = session_directory().dead_path();
483 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
484 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
488 dir = session_directory().export_path();
490 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
491 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
495 dir = analysis_dir ();
497 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
498 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
502 dir = plugins_dir ();
504 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
505 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
509 dir = externals_dir ();
511 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
512 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
519 /** @param session_template directory containing session template, or empty.
520 * Caller must not hold process lock.
523 Session::create (const string& session_template, BusProfile* bus_profile)
525 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
526 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
530 if (ensure_subdirs ()) {
534 _writable = exists_and_writable (_path);
536 if (!session_template.empty()) {
537 std::string in_path = (ARDOUR::Profile->get_trx () ? session_template : session_template_dir_to_file (session_template));
539 ifstream in(in_path.c_str());
542 /* no need to call legalize_for_path() since the string
543 * in session_template is already a legal path name
545 string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
547 ofstream out(out_path.c_str());
553 if (!ARDOUR::Profile->get_trx()) {
554 /* Copy plugin state files from template to new session */
555 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
556 copy_recurse (template_plugins, plugins_dir ());
562 error << string_compose (_("Could not open %1 for writing session template"), out_path)
568 error << string_compose (_("Could not open session template %1 for reading"), in_path)
575 if (Profile->get_trx()) {
577 /* set initial start + end point : ARDOUR::Session::session_end_shift long.
578 Remember that this is a brand new session. Sessions
579 loaded from saved state will get this range from the saved state.
582 set_session_range_location (0, 0);
584 /* Initial loop location, from absolute zero, length 10 seconds */
586 Location* loc = new Location (*this, 0, 10.0 * _engine.sample_rate(), _("Loop"), Location::IsAutoLoop);
587 _locations->add (loc, true);
588 set_auto_loop_location (loc);
591 _state_of_the_state = Clean;
593 /* set up Master Out and Control Out if necessary */
598 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
600 // Waves Tracks: always create master bus for Tracks
601 if (ARDOUR::Profile->get_trx() || bus_profile->master_out_channels) {
602 boost::shared_ptr<Route> r (new Route (*this, _("Master"), Route::MasterOut, DataType::AUDIO));
606 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
607 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
610 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
611 r->input()->ensure_io (count, false, this);
612 r->output()->ensure_io (count, false, this);
618 /* prohibit auto-connect to master, because there isn't one */
619 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
623 add_routes (rl, false, false, false);
626 // Waves Tracks: Skip this. Always use autoconnection for Tracks
627 if (!ARDOUR::Profile->get_trx()) {
629 /* this allows the user to override settings with an environment variable.
632 if (no_auto_connect()) {
633 bus_profile->input_ac = AutoConnectOption (0);
634 bus_profile->output_ac = AutoConnectOption (0);
637 Config->set_input_auto_connect (bus_profile->input_ac);
638 Config->set_output_auto_connect (bus_profile->output_ac);
642 if (Config->get_use_monitor_bus() && bus_profile) {
643 add_monitor_section ();
650 Session::maybe_write_autosave()
652 if (dirty() && record_status() != Recording) {
653 save_state("", true);
658 Session::remove_pending_capture_state ()
660 std::string pending_state_file_path(_session_dir->root_path());
662 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
664 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
666 if (g_remove (pending_state_file_path.c_str()) != 0) {
667 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
668 pending_state_file_path, g_strerror (errno)) << endmsg;
672 /** Rename a state file.
673 * @param old_name Old snapshot name.
674 * @param new_name New snapshot name.
677 Session::rename_state (string old_name, string new_name)
679 if (old_name == _current_snapshot_name || old_name == _name) {
680 /* refuse to rename the current snapshot or the "main" one */
684 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
685 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
687 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
688 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
690 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
691 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
692 old_name, new_name, g_strerror(errno)) << endmsg;
696 /** Remove a state file.
697 * @param snapshot_name Snapshot name.
700 Session::remove_state (string snapshot_name)
702 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
703 // refuse to remove the current snapshot or the "main" one
707 std::string xml_path(_session_dir->root_path());
709 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
711 if (!create_backup_file (xml_path)) {
712 // don't remove it if a backup can't be made
713 // create_backup_file will log the error.
718 if (g_remove (xml_path.c_str()) != 0) {
719 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
720 xml_path, g_strerror (errno)) << endmsg;
724 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
726 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot, bool template_only)
729 std::string xml_path(_session_dir->root_path());
731 /* prevent concurrent saves from different threads */
733 Glib::Threads::Mutex::Lock lm (save_state_lock);
735 if (!_writable || (_state_of_the_state & CannotSave)) {
739 if (g_atomic_int_get(&_suspend_save)) {
743 _save_queued = false;
745 if (!_engine.connected ()) {
746 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
752 /* tell sources we're saving first, in case they write out to a new file
753 * which should be saved with the state rather than the old one */
754 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
756 i->second->session_saved();
757 } catch (Evoral::SMF::FileError& e) {
758 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
762 SessionSaveUnderway (); /* EMIT SIGNAL */
765 tree.set_root (&get_template());
767 tree.set_root (&get_state());
770 if (snapshot_name.empty()) {
771 snapshot_name = _current_snapshot_name;
772 } else if (switch_to_snapshot) {
773 _current_snapshot_name = snapshot_name;
778 /* proper save: use statefile_suffix (.ardour in English) */
780 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
782 /* make a backup copy of the old file */
784 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
785 // create_backup_file will log the error
791 /* pending save: use pending_suffix (.pending in English) */
792 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
795 std::string tmp_path(_session_dir->root_path());
796 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
798 cerr << "actually writing state to " << tmp_path << endl;
800 if (!tree.write (tmp_path)) {
801 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
802 if (g_remove (tmp_path.c_str()) != 0) {
803 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
804 tmp_path, g_strerror (errno)) << endmsg;
810 cerr << "renaming state to " << xml_path << endl;
812 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
813 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
814 tmp_path, xml_path, g_strerror(errno)) << endmsg;
815 if (g_remove (tmp_path.c_str()) != 0) {
816 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
817 tmp_path, g_strerror (errno)) << endmsg;
825 save_history (snapshot_name);
827 bool was_dirty = dirty();
829 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
832 DirtyChanged (); /* EMIT SIGNAL */
835 StateSaved (snapshot_name); /* EMIT SIGNAL */
842 Session::restore_state (string snapshot_name)
844 if (load_state (snapshot_name) == 0) {
845 set_state (*state_tree->root(), Stateful::loading_state_version);
852 Session::load_state (string snapshot_name)
857 state_was_pending = false;
859 /* check for leftover pending state from a crashed capture attempt */
861 std::string xmlpath(_session_dir->root_path());
862 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
864 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
866 /* there is pending state from a crashed capture attempt */
868 boost::optional<int> r = AskAboutPendingState();
869 if (r.get_value_or (1)) {
870 state_was_pending = true;
874 if (!state_was_pending) {
875 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
878 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
879 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
880 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
881 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
886 state_tree = new XMLTree;
890 _writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
892 if (!state_tree->read (xmlpath)) {
893 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
899 XMLNode& root (*state_tree->root());
901 if (root.name() != X_("Session")) {
902 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
908 const XMLProperty* prop;
910 if ((prop = root.property ("version")) == 0) {
911 /* no version implies very old version of Ardour */
912 Stateful::loading_state_version = 1000;
914 if (prop->value().find ('.') != string::npos) {
915 /* old school version format */
916 if (prop->value()[0] == '2') {
917 Stateful::loading_state_version = 2000;
919 Stateful::loading_state_version = 3000;
922 Stateful::loading_state_version = atoi (prop->value());
926 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
928 std::string backup_path(_session_dir->root_path());
929 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
930 backup_path = Glib::build_filename (backup_path, backup_filename);
932 // only create a backup for a given statefile version once
934 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
936 VersionMismatch (xmlpath, backup_path);
938 if (!copy_file (xmlpath, backup_path)) {;
948 Session::load_options (const XMLNode& node)
950 LocaleGuard lg (X_("C"));
951 config.set_variables (node);
956 Session::save_default_options ()
958 return config.save_state();
968 Session::get_template()
970 /* if we don't disable rec-enable, diskstreams
971 will believe they need to store their capture
972 sources in their state node.
975 disable_record (false);
981 Session::state (bool full_state)
983 XMLNode* node = new XMLNode("Session");
987 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
988 node->add_property("version", buf);
990 /* store configuration settings */
994 node->add_property ("name", _name);
995 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
996 node->add_property ("sample-rate", buf);
998 if (session_dirs.size() > 1) {
1002 vector<space_and_path>::iterator i = session_dirs.begin();
1003 vector<space_and_path>::iterator next;
1005 ++i; /* skip the first one */
1009 while (i != session_dirs.end()) {
1013 if (next != session_dirs.end()) {
1014 p += G_SEARCHPATH_SEPARATOR;
1023 child = node->add_child ("Path");
1024 child->add_content (p);
1028 /* save the ID counter */
1030 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1031 node->add_property ("id-counter", buf);
1033 /* save the event ID counter */
1035 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1036 node->add_property ("event-counter", buf);
1038 /* various options */
1040 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
1041 if (!midi_port_nodes.empty()) {
1042 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
1043 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
1044 midi_port_stuff->add_child_nocopy (**n);
1046 node->add_child_nocopy (*midi_port_stuff);
1049 node->add_child_nocopy (config.get_variables ());
1051 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1053 child = node->add_child ("Sources");
1056 Glib::Threads::Mutex::Lock sl (source_lock);
1058 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1060 /* Don't save information about non-file Sources, or
1061 * about non-destructive file sources that are empty
1062 * and unused by any regions.
1065 boost::shared_ptr<FileSource> fs;
1067 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1069 if (!fs->destructive()) {
1070 if (fs->empty() && !fs->used()) {
1075 child->add_child_nocopy (siter->second->get_state());
1080 child = node->add_child ("Regions");
1083 Glib::Threads::Mutex::Lock rl (region_lock);
1084 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1085 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1086 boost::shared_ptr<Region> r = i->second;
1087 /* only store regions not attached to playlists */
1088 if (r->playlist() == 0) {
1089 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1090 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1092 child->add_child_nocopy (r->get_state ());
1097 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1099 if (!cassocs.empty()) {
1100 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1102 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1104 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1105 i->first->id().print (buf, sizeof (buf));
1106 can->add_property (X_("copy"), buf);
1107 i->second->id().print (buf, sizeof (buf));
1108 can->add_property (X_("original"), buf);
1109 ca->add_child_nocopy (*can);
1119 node->add_child_nocopy (_locations->get_state());
1122 Locations loc (*this);
1123 // for a template, just create a new Locations, populate it
1124 // with the default start and end, and get the state for that.
1125 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1126 range->set (max_framepos, 0);
1128 XMLNode& locations_state = loc.get_state();
1130 if (ARDOUR::Profile->get_trx() && _locations) {
1131 // For tracks we need stored the Auto Loop Range and all MIDI markers.
1132 for (Locations::LocationList::const_iterator i = _locations->list ().begin (); i != _locations->list ().end (); ++i) {
1133 if ((*i)->is_mark () || (*i)->is_auto_loop ()) {
1134 locations_state.add_child_nocopy ((*i)->get_state ());
1138 node->add_child_nocopy (locations_state);
1141 child = node->add_child ("Bundles");
1143 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1144 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1145 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1147 child->add_child_nocopy (b->get_state());
1152 child = node->add_child ("Routes");
1154 boost::shared_ptr<RouteList> r = routes.reader ();
1156 RoutePublicOrderSorter cmp;
1157 RouteList public_order (*r);
1158 public_order.sort (cmp);
1160 /* the sort should have put control outs first */
1163 assert (_monitor_out == public_order.front());
1166 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1167 if (!(*i)->is_auditioner()) {
1169 child->add_child_nocopy ((*i)->get_state());
1171 child->add_child_nocopy ((*i)->get_template());
1177 playlists->add_state (node, full_state);
1179 child = node->add_child ("RouteGroups");
1180 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1181 child->add_child_nocopy ((*i)->get_state());
1185 XMLNode* gain_child = node->add_child ("Click");
1186 gain_child->add_child_nocopy (_click_io->state (full_state));
1187 gain_child->add_child_nocopy (_click_gain->state (full_state));
1191 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1192 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1196 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1197 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1200 node->add_child_nocopy (_speakers->get_state());
1201 node->add_child_nocopy (_tempo_map->get_state());
1202 node->add_child_nocopy (get_control_protocol_state());
1205 node->add_child_copy (*_extra_xml);
1212 Session::get_control_protocol_state ()
1214 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1215 return cpm.get_state();
1219 Session::set_state (const XMLNode& node, int version)
1223 const XMLProperty* prop;
1226 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1228 if (node.name() != X_("Session")) {
1229 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1233 if ((prop = node.property ("name")) != 0) {
1234 _name = prop->value ();
1237 if ((prop = node.property (X_("sample-rate"))) != 0) {
1239 _nominal_frame_rate = atoi (prop->value());
1241 if (_nominal_frame_rate != _current_frame_rate) {
1242 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1243 if (r.get_value_or (0)) {
1249 setup_raid_path(_session_dir->root_path());
1251 if ((prop = node.property (X_("id-counter"))) != 0) {
1253 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1254 ID::init_counter (x);
1256 /* old sessions used a timebased counter, so fake
1257 the startup ID counter based on a standard
1262 ID::init_counter (now);
1265 if ((prop = node.property (X_("event-counter"))) != 0) {
1266 Evoral::init_event_id_counter (atoi (prop->value()));
1270 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1271 _midi_ports->set_midi_port_states (child->children());
1274 IO::disable_connecting ();
1276 Stateful::save_extra_xml (node);
1278 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1279 load_options (*child);
1280 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1281 load_options (*child);
1283 error << _("Session: XML state has no options section") << endmsg;
1286 if (version >= 3000) {
1287 if ((child = find_named_node (node, "Metadata")) == 0) {
1288 warning << _("Session: XML state has no metadata section") << endmsg;
1289 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1294 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1295 _speakers->set_state (*child, version);
1298 if ((child = find_named_node (node, "Sources")) == 0) {
1299 error << _("Session: XML state has no sources section") << endmsg;
1301 } else if (load_sources (*child)) {
1305 if ((child = find_named_node (node, "TempoMap")) == 0) {
1306 error << _("Session: XML state has no Tempo Map section") << endmsg;
1308 } else if (_tempo_map->set_state (*child, version)) {
1312 if ((child = find_named_node (node, "Locations")) == 0) {
1313 error << _("Session: XML state has no locations section") << endmsg;
1315 } else if (_locations->set_state (*child, version)) {
1319 locations_changed ();
1321 if (_session_range_location) {
1322 AudioFileSource::set_header_position_offset (_session_range_location->start());
1325 if ((child = find_named_node (node, "Regions")) == 0) {
1326 error << _("Session: XML state has no Regions section") << endmsg;
1328 } else if (load_regions (*child)) {
1332 if ((child = find_named_node (node, "Playlists")) == 0) {
1333 error << _("Session: XML state has no playlists section") << endmsg;
1335 } else if (playlists->load (*this, *child)) {
1339 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1341 } else if (playlists->load_unused (*this, *child)) {
1345 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1346 if (load_compounds (*child)) {
1351 if (version >= 3000) {
1352 if ((child = find_named_node (node, "Bundles")) == 0) {
1353 warning << _("Session: XML state has no bundles section") << endmsg;
1356 /* We can't load Bundles yet as they need to be able
1357 to convert from port names to Port objects, which can't happen until
1359 _bundle_xml_node = new XMLNode (*child);
1363 if (version < 3000) {
1364 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1365 error << _("Session: XML state has no diskstreams section") << endmsg;
1367 } else if (load_diskstreams_2X (*child, version)) {
1372 if ((child = find_named_node (node, "Routes")) == 0) {
1373 error << _("Session: XML state has no routes section") << endmsg;
1375 } else if (load_routes (*child, version)) {
1379 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1380 _diskstreams_2X.clear ();
1382 if (version >= 3000) {
1384 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1385 error << _("Session: XML state has no route groups section") << endmsg;
1387 } else if (load_route_groups (*child, version)) {
1391 } else if (version < 3000) {
1393 if ((child = find_named_node (node, "EditGroups")) == 0) {
1394 error << _("Session: XML state has no edit groups section") << endmsg;
1396 } else if (load_route_groups (*child, version)) {
1400 if ((child = find_named_node (node, "MixGroups")) == 0) {
1401 error << _("Session: XML state has no mix groups section") << endmsg;
1403 } else if (load_route_groups (*child, version)) {
1408 if ((child = find_named_node (node, "Click")) == 0) {
1409 warning << _("Session: XML state has no click section") << endmsg;
1410 } else if (_click_io) {
1411 setup_click_state (&node);
1414 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1415 ControlProtocolManager::instance().set_state (*child, version);
1418 update_route_record_state ();
1420 /* here beginneth the second phase ... */
1422 StateReady (); /* EMIT SIGNAL */
1435 Session::load_routes (const XMLNode& node, int version)
1438 XMLNodeConstIterator niter;
1439 RouteList new_routes;
1441 nlist = node.children();
1445 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1447 boost::shared_ptr<Route> route;
1448 if (version < 3000) {
1449 route = XMLRouteFactory_2X (**niter, version);
1451 route = XMLRouteFactory (**niter, version);
1455 error << _("Session: cannot create Route from XML description.") << endmsg;
1459 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1461 new_routes.push_back (route);
1464 BootMessage (_("Tracks/busses loaded; Adding to Session"));
1466 add_routes (new_routes, false, false, false);
1468 BootMessage (_("Finished adding tracks/busses"));
1473 boost::shared_ptr<Route>
1474 Session::XMLRouteFactory (const XMLNode& node, int version)
1476 boost::shared_ptr<Route> ret;
1478 if (node.name() != "Route") {
1482 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1484 DataType type = DataType::AUDIO;
1485 const XMLProperty* prop = node.property("default-type");
1488 type = DataType (prop->value());
1491 assert (type != DataType::NIL);
1495 boost::shared_ptr<Track> track;
1497 if (type == DataType::AUDIO) {
1498 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1500 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1503 if (track->init()) {
1507 if (track->set_state (node, version)) {
1511 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1512 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1517 enum Route::Flag flags = Route::Flag(0);
1518 const XMLProperty* prop = node.property("flags");
1520 flags = Route::Flag (string_2_enum (prop->value(), flags));
1523 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1525 if (r->init () == 0 && r->set_state (node, version) == 0) {
1526 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1527 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1536 boost::shared_ptr<Route>
1537 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1539 boost::shared_ptr<Route> ret;
1541 if (node.name() != "Route") {
1545 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1547 ds_prop = node.property (X_("diskstream"));
1550 DataType type = DataType::AUDIO;
1551 const XMLProperty* prop = node.property("default-type");
1554 type = DataType (prop->value());
1557 assert (type != DataType::NIL);
1561 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1562 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1566 if (i == _diskstreams_2X.end()) {
1567 error << _("Could not find diskstream for route") << endmsg;
1568 return boost::shared_ptr<Route> ();
1571 boost::shared_ptr<Track> track;
1573 if (type == DataType::AUDIO) {
1574 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1576 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1579 if (track->init()) {
1583 if (track->set_state (node, version)) {
1587 track->set_diskstream (*i);
1589 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1590 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1595 enum Route::Flag flags = Route::Flag(0);
1596 const XMLProperty* prop = node.property("flags");
1598 flags = Route::Flag (string_2_enum (prop->value(), flags));
1601 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1603 if (r->init () == 0 && r->set_state (node, version) == 0) {
1604 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1605 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1615 Session::load_regions (const XMLNode& node)
1618 XMLNodeConstIterator niter;
1619 boost::shared_ptr<Region> region;
1621 nlist = node.children();
1625 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1626 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1627 error << _("Session: cannot create Region from XML description.");
1628 const XMLProperty *name = (**niter).property("name");
1631 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1642 Session::load_compounds (const XMLNode& node)
1644 XMLNodeList calist = node.children();
1645 XMLNodeConstIterator caiter;
1646 XMLProperty *caprop;
1648 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1649 XMLNode* ca = *caiter;
1653 if ((caprop = ca->property (X_("original"))) == 0) {
1656 orig_id = caprop->value();
1658 if ((caprop = ca->property (X_("copy"))) == 0) {
1661 copy_id = caprop->value();
1663 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1664 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1666 if (!orig || !copy) {
1667 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1673 RegionFactory::add_compound_association (orig, copy);
1680 Session::load_nested_sources (const XMLNode& node)
1683 XMLNodeConstIterator niter;
1685 nlist = node.children();
1687 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1688 if ((*niter)->name() == "Source") {
1690 /* it may already exist, so don't recreate it unnecessarily
1693 XMLProperty* prop = (*niter)->property (X_("id"));
1695 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1699 ID source_id (prop->value());
1701 if (!source_by_id (source_id)) {
1704 SourceFactory::create (*this, **niter, true);
1706 catch (failed_constructor& err) {
1707 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1714 boost::shared_ptr<Region>
1715 Session::XMLRegionFactory (const XMLNode& node, bool full)
1717 const XMLProperty* type = node.property("type");
1721 const XMLNodeList& nlist = node.children();
1723 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1724 XMLNode *child = (*niter);
1725 if (child->name() == "NestedSource") {
1726 load_nested_sources (*child);
1730 if (!type || type->value() == "audio") {
1731 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1732 } else if (type->value() == "midi") {
1733 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1736 } catch (failed_constructor& err) {
1737 return boost::shared_ptr<Region> ();
1740 return boost::shared_ptr<Region> ();
1743 boost::shared_ptr<AudioRegion>
1744 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1746 const XMLProperty* prop;
1747 boost::shared_ptr<Source> source;
1748 boost::shared_ptr<AudioSource> as;
1750 SourceList master_sources;
1751 uint32_t nchans = 1;
1754 if (node.name() != X_("Region")) {
1755 return boost::shared_ptr<AudioRegion>();
1758 if ((prop = node.property (X_("channels"))) != 0) {
1759 nchans = atoi (prop->value().c_str());
1762 if ((prop = node.property ("name")) == 0) {
1763 cerr << "no name for this region\n";
1767 if ((prop = node.property (X_("source-0"))) == 0) {
1768 if ((prop = node.property ("source")) == 0) {
1769 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1770 return boost::shared_ptr<AudioRegion>();
1774 PBD::ID s_id (prop->value());
1776 if ((source = source_by_id (s_id)) == 0) {
1777 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1778 return boost::shared_ptr<AudioRegion>();
1781 as = boost::dynamic_pointer_cast<AudioSource>(source);
1783 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1784 return boost::shared_ptr<AudioRegion>();
1787 sources.push_back (as);
1789 /* pickup other channels */
1791 for (uint32_t n=1; n < nchans; ++n) {
1792 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1793 if ((prop = node.property (buf)) != 0) {
1795 PBD::ID id2 (prop->value());
1797 if ((source = source_by_id (id2)) == 0) {
1798 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1799 return boost::shared_ptr<AudioRegion>();
1802 as = boost::dynamic_pointer_cast<AudioSource>(source);
1804 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1805 return boost::shared_ptr<AudioRegion>();
1807 sources.push_back (as);
1811 for (uint32_t n = 0; n < nchans; ++n) {
1812 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1813 if ((prop = node.property (buf)) != 0) {
1815 PBD::ID id2 (prop->value());
1817 if ((source = source_by_id (id2)) == 0) {
1818 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1819 return boost::shared_ptr<AudioRegion>();
1822 as = boost::dynamic_pointer_cast<AudioSource>(source);
1824 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1825 return boost::shared_ptr<AudioRegion>();
1827 master_sources.push_back (as);
1832 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1834 /* a final detail: this is the one and only place that we know how long missing files are */
1836 if (region->whole_file()) {
1837 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1838 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1840 sfp->set_length (region->length());
1845 if (!master_sources.empty()) {
1846 if (master_sources.size() != nchans) {
1847 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1849 region->set_master_sources (master_sources);
1857 catch (failed_constructor& err) {
1858 return boost::shared_ptr<AudioRegion>();
1862 boost::shared_ptr<MidiRegion>
1863 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1865 const XMLProperty* prop;
1866 boost::shared_ptr<Source> source;
1867 boost::shared_ptr<MidiSource> ms;
1870 if (node.name() != X_("Region")) {
1871 return boost::shared_ptr<MidiRegion>();
1874 if ((prop = node.property ("name")) == 0) {
1875 cerr << "no name for this region\n";
1879 if ((prop = node.property (X_("source-0"))) == 0) {
1880 if ((prop = node.property ("source")) == 0) {
1881 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1882 return boost::shared_ptr<MidiRegion>();
1886 PBD::ID s_id (prop->value());
1888 if ((source = source_by_id (s_id)) == 0) {
1889 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1890 return boost::shared_ptr<MidiRegion>();
1893 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1895 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1896 return boost::shared_ptr<MidiRegion>();
1899 sources.push_back (ms);
1902 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1903 /* a final detail: this is the one and only place that we know how long missing files are */
1905 if (region->whole_file()) {
1906 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1907 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1909 sfp->set_length (region->length());
1917 catch (failed_constructor& err) {
1918 return boost::shared_ptr<MidiRegion>();
1923 Session::get_sources_as_xml ()
1926 XMLNode* node = new XMLNode (X_("Sources"));
1927 Glib::Threads::Mutex::Lock lm (source_lock);
1929 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1930 node->add_child_nocopy (i->second->get_state());
1937 Session::reset_write_sources (bool mark_write_complete, bool force)
1939 boost::shared_ptr<RouteList> rl = routes.reader();
1940 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1941 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1943 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
1944 tr->reset_write_sources(mark_write_complete, force);
1945 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
1951 Session::load_sources (const XMLNode& node)
1954 XMLNodeConstIterator niter;
1955 boost::shared_ptr<Source> source; /* don't need this but it stops some
1956 * versions of gcc complaining about
1957 * discarded return values.
1960 nlist = node.children();
1964 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1967 if ((source = XMLSourceFactory (**niter)) == 0) {
1968 error << _("Session: cannot create Source from XML description.") << endmsg;
1971 } catch (MissingSource& err) {
1975 if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
1976 error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
1977 PROGRAM_NAME) << endmsg;
1981 if (!no_questions_about_missing_files) {
1982 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1987 switch (user_choice) {
1989 /* user added a new search location, so try again */
1994 /* user asked to quit the entire session load
1999 no_questions_about_missing_files = true;
2003 no_questions_about_missing_files = true;
2010 case DataType::AUDIO:
2011 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
2014 case DataType::MIDI:
2015 /* The MIDI file is actually missing so
2016 * just create a new one in the same
2017 * location. Do not announce its
2021 if (!Glib::path_is_absolute (err.path)) {
2022 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
2024 /* this should be an unrecoverable error: we would be creating a MIDI file outside
2029 /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
2030 source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
2031 /* reset ID to match the missing one */
2032 source->set_id (**niter);
2033 /* Now we can announce it */
2034 SourceFactory::SourceCreated (source);
2045 boost::shared_ptr<Source>
2046 Session::XMLSourceFactory (const XMLNode& node)
2048 if (node.name() != "Source") {
2049 return boost::shared_ptr<Source>();
2053 /* note: do peak building in another thread when loading session state */
2054 return SourceFactory::create (*this, node, true);
2057 catch (failed_constructor& err) {
2058 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
2059 return boost::shared_ptr<Source>();
2064 Session::save_template (string template_name)
2066 if ((_state_of_the_state & CannotSave) || template_name.empty ()) {
2070 bool absolute_path = Glib::path_is_absolute (template_name);
2072 /* directory to put the template in */
2073 std::string template_dir_path;
2075 if (!absolute_path) {
2076 std::string user_template_dir(user_template_directory());
2078 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2079 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2080 user_template_dir, g_strerror (errno)) << endmsg;
2084 template_dir_path = Glib::build_filename (user_template_dir, template_name);
2086 template_dir_path = template_name;
2089 if (!ARDOUR::Profile->get_trx()) {
2090 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2091 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2092 template_dir_path) << endmsg;
2096 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2097 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2098 template_dir_path, g_strerror (errno)) << endmsg;
2104 std::string template_file_path;
2106 if (ARDOUR::Profile->get_trx()) {
2107 template_file_path = template_name;
2109 if (absolute_path) {
2110 template_file_path = Glib::build_filename (template_dir_path, Glib::path_get_basename (template_dir_path) + template_suffix);
2112 template_file_path = Glib::build_filename (template_dir_path, template_name + template_suffix);
2116 SessionSaveUnderway (); /* EMIT SIGNAL */
2120 tree.set_root (&get_template());
2121 if (!tree.write (template_file_path)) {
2122 error << _("template not saved") << endmsg;
2126 if (!ARDOUR::Profile->get_trx()) {
2127 /* copy plugin state directory */
2129 std::string template_plugin_state_path (Glib::build_filename (template_dir_path, X_("plugins")));
2131 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
2132 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
2133 template_plugin_state_path, g_strerror (errno)) << endmsg;
2136 copy_files (plugins_dir(), template_plugin_state_path);
2139 store_recent_templates (template_file_path);
2145 Session::refresh_disk_space ()
2147 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2149 Glib::Threads::Mutex::Lock lm (space_lock);
2151 /* get freespace on every FS that is part of the session path */
2153 _total_free_4k_blocks = 0;
2154 _total_free_4k_blocks_uncertain = false;
2156 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2158 struct statfs statfsbuf;
2159 statfs (i->path.c_str(), &statfsbuf);
2161 double const scale = statfsbuf.f_bsize / 4096.0;
2163 /* See if this filesystem is read-only */
2164 struct statvfs statvfsbuf;
2165 statvfs (i->path.c_str(), &statvfsbuf);
2167 /* f_bavail can be 0 if it is undefined for whatever
2168 filesystem we are looking at; Samba shares mounted
2169 via GVFS are an example of this.
2171 if (statfsbuf.f_bavail == 0) {
2172 /* block count unknown */
2174 i->blocks_unknown = true;
2175 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2176 /* read-only filesystem */
2178 i->blocks_unknown = false;
2180 /* read/write filesystem with known space */
2181 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2182 i->blocks_unknown = false;
2185 _total_free_4k_blocks += i->blocks;
2186 if (i->blocks_unknown) {
2187 _total_free_4k_blocks_uncertain = true;
2190 #elif defined PLATFORM_WINDOWS
2191 vector<string> scanned_volumes;
2192 vector<string>::iterator j;
2193 vector<space_and_path>::iterator i;
2194 DWORD nSectorsPerCluster, nBytesPerSector,
2195 nFreeClusters, nTotalClusters;
2199 _total_free_4k_blocks = 0;
2201 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2202 strncpy (disk_drive, (*i).path.c_str(), 3);
2206 volume_found = false;
2207 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2209 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2210 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2211 i->blocks = (uint32_t)(nFreeBytes / 4096);
2213 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2214 if (0 == j->compare(disk_drive)) {
2215 volume_found = true;
2220 if (!volume_found) {
2221 scanned_volumes.push_back(disk_drive);
2222 _total_free_4k_blocks += i->blocks;
2227 if (0 == _total_free_4k_blocks) {
2228 strncpy (disk_drive, path().c_str(), 3);
2231 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2233 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2234 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2235 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2242 Session::get_best_session_directory_for_new_audio ()
2244 vector<space_and_path>::iterator i;
2245 string result = _session_dir->root_path();
2247 /* handle common case without system calls */
2249 if (session_dirs.size() == 1) {
2253 /* OK, here's the algorithm we're following here:
2255 We want to select which directory to use for
2256 the next file source to be created. Ideally,
2257 we'd like to use a round-robin process so as to
2258 get maximum performance benefits from splitting
2259 the files across multiple disks.
2261 However, in situations without much diskspace, an
2262 RR approach may end up filling up a filesystem
2263 with new files while others still have space.
2264 Its therefore important to pay some attention to
2265 the freespace in the filesystem holding each
2266 directory as well. However, if we did that by
2267 itself, we'd keep creating new files in the file
2268 system with the most space until it was as full
2269 as all others, thus negating any performance
2270 benefits of this RAID-1 like approach.
2272 So, we use a user-configurable space threshold. If
2273 there are at least 2 filesystems with more than this
2274 much space available, we use RR selection between them.
2275 If not, then we pick the filesystem with the most space.
2277 This gets a good balance between the two
2281 refresh_disk_space ();
2283 int free_enough = 0;
2285 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2286 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2291 if (free_enough >= 2) {
2292 /* use RR selection process, ensuring that the one
2296 i = last_rr_session_dir;
2299 if (++i == session_dirs.end()) {
2300 i = session_dirs.begin();
2303 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2304 SessionDirectory sdir(i->path);
2305 if (sdir.create ()) {
2307 last_rr_session_dir = i;
2312 } while (i != last_rr_session_dir);
2316 /* pick FS with the most freespace (and that
2317 seems to actually work ...)
2320 vector<space_and_path> sorted;
2321 space_and_path_ascending_cmp cmp;
2323 sorted = session_dirs;
2324 sort (sorted.begin(), sorted.end(), cmp);
2326 for (i = sorted.begin(); i != sorted.end(); ++i) {
2327 SessionDirectory sdir(i->path);
2328 if (sdir.create ()) {
2330 last_rr_session_dir = i;
2340 Session::automation_dir () const
2342 return Glib::build_filename (_path, automation_dir_name);
2346 Session::analysis_dir () const
2348 return Glib::build_filename (_path, analysis_dir_name);
2352 Session::plugins_dir () const
2354 return Glib::build_filename (_path, plugins_dir_name);
2358 Session::externals_dir () const
2360 return Glib::build_filename (_path, externals_dir_name);
2364 Session::load_bundles (XMLNode const & node)
2366 XMLNodeList nlist = node.children();
2367 XMLNodeConstIterator niter;
2371 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2372 if ((*niter)->name() == "InputBundle") {
2373 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2374 } else if ((*niter)->name() == "OutputBundle") {
2375 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2377 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2386 Session::load_route_groups (const XMLNode& node, int version)
2388 XMLNodeList nlist = node.children();
2389 XMLNodeConstIterator niter;
2393 if (version >= 3000) {
2395 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2396 if ((*niter)->name() == "RouteGroup") {
2397 RouteGroup* rg = new RouteGroup (*this, "");
2398 add_route_group (rg);
2399 rg->set_state (**niter, version);
2403 } else if (version < 3000) {
2405 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2406 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2407 RouteGroup* rg = new RouteGroup (*this, "");
2408 add_route_group (rg);
2409 rg->set_state (**niter, version);
2418 state_file_filter (const string &str, void* /*arg*/)
2420 return (str.length() > strlen(statefile_suffix) &&
2421 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2425 remove_end(string state)
2427 string statename(state);
2429 string::size_type start,end;
2430 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2431 statename = statename.substr (start+1);
2434 if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2435 end = statename.length();
2438 return string(statename.substr (0, end));
2442 Session::possible_states (string path)
2444 vector<string> states;
2445 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2447 transform(states.begin(), states.end(), states.begin(), remove_end);
2449 sort (states.begin(), states.end());
2455 Session::possible_states () const
2457 return possible_states(_path);
2461 Session::add_route_group (RouteGroup* g)
2463 _route_groups.push_back (g);
2464 route_group_added (g); /* EMIT SIGNAL */
2466 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2467 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2468 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2474 Session::remove_route_group (RouteGroup& rg)
2476 list<RouteGroup*>::iterator i;
2478 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2479 _route_groups.erase (i);
2482 route_group_removed (); /* EMIT SIGNAL */
2486 /** Set a new order for our route groups, without adding or removing any.
2487 * @param groups Route group list in the new order.
2490 Session::reorder_route_groups (list<RouteGroup*> groups)
2492 _route_groups = groups;
2494 route_groups_reordered (); /* EMIT SIGNAL */
2500 Session::route_group_by_name (string name)
2502 list<RouteGroup *>::iterator i;
2504 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2505 if ((*i)->name() == name) {
2513 Session::all_route_group() const
2515 return *_all_route_group;
2519 Session::add_commands (vector<Command*> const & cmds)
2521 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2527 Session::begin_reversible_command (const string& name)
2529 begin_reversible_command (g_quark_from_string (name.c_str ()));
2532 /** Begin a reversible command using a GQuark to identify it.
2533 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2534 * but there must be as many begin...()s as there are commit...()s.
2537 Session::begin_reversible_command (GQuark q)
2539 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2540 to hold all the commands that are committed. This keeps the order of
2541 commands correct in the history.
2544 if (_current_trans == 0) {
2545 /* start a new transaction */
2546 assert (_current_trans_quarks.empty ());
2547 _current_trans = new UndoTransaction();
2548 _current_trans->set_name (g_quark_to_string (q));
2551 _current_trans_quarks.push_front (q);
2555 Session::abort_reversible_command ()
2557 if (_current_trans != 0) {
2558 _current_trans->clear();
2559 delete _current_trans;
2561 _current_trans_quarks.clear();
2566 Session::commit_reversible_command (Command *cmd)
2568 assert (_current_trans);
2569 assert (!_current_trans_quarks.empty ());
2574 _current_trans->add_command (cmd);
2577 _current_trans_quarks.pop_front ();
2579 if (!_current_trans_quarks.empty ()) {
2580 /* the transaction we're committing is not the top-level one */
2584 if (_current_trans->empty()) {
2585 /* no commands were added to the transaction, so just get rid of it */
2586 delete _current_trans;
2591 gettimeofday (&now, 0);
2592 _current_trans->set_timestamp (now);
2594 _history.add (_current_trans);
2599 accept_all_audio_files (const string& path, void* /*arg*/)
2601 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2605 if (!AudioFileSource::safe_audio_file_extension (path)) {
2613 accept_all_midi_files (const string& path, void* /*arg*/)
2615 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2619 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2620 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2621 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2625 accept_all_state_files (const string& path, void* /*arg*/)
2627 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2631 std::string const statefile_ext (statefile_suffix);
2632 if (path.length() >= statefile_ext.length()) {
2633 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2640 Session::find_all_sources (string path, set<string>& result)
2645 if (!tree.read (path)) {
2649 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2654 XMLNodeConstIterator niter;
2656 nlist = node->children();
2660 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2664 if ((prop = (*niter)->property (X_("type"))) == 0) {
2668 DataType type (prop->value());
2670 if ((prop = (*niter)->property (X_("name"))) == 0) {
2674 if (Glib::path_is_absolute (prop->value())) {
2675 /* external file, ignore */
2683 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2684 result.insert (found_path);
2692 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2694 vector<string> state_files;
2696 string this_snapshot_path;
2702 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2703 ripped = ripped.substr (0, ripped.length() - 1);
2706 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2708 if (state_files.empty()) {
2713 this_snapshot_path = _path;
2714 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2715 this_snapshot_path += statefile_suffix;
2717 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2719 if (exclude_this_snapshot && *i == this_snapshot_path) {
2723 if (find_all_sources (*i, result) < 0) {
2731 struct RegionCounter {
2732 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2733 AudioSourceList::iterator iter;
2734 boost::shared_ptr<Region> region;
2737 RegionCounter() : count (0) {}
2741 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2743 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2744 return r.get_value_or (1);
2748 Session::cleanup_regions ()
2750 bool removed = false;
2751 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2753 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2755 uint32_t used = playlists->region_use_count (i->second);
2757 if (used == 0 && !i->second->automatic ()) {
2759 RegionFactory::map_remove (i->second);
2764 // re-check to remove parent references of compound regions
2765 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2766 if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2769 assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2770 if (0 == playlists->region_use_count (i->second)) {
2771 RegionFactory::map_remove (i->second);
2776 /* dump the history list */
2783 Session::cleanup_sources (CleanupReport& rep)
2785 // FIXME: needs adaptation to midi
2787 vector<boost::shared_ptr<Source> > dead_sources;
2790 vector<string> candidates;
2791 vector<string> unused;
2792 set<string> all_sources;
2801 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2803 /* consider deleting all unused playlists */
2805 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2810 /* sync the "all regions" property of each playlist with its current state
2813 playlists->sync_all_regions_with_regions ();
2815 /* find all un-used sources */
2820 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2822 SourceMap::iterator tmp;
2827 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2831 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2832 dead_sources.push_back (i->second);
2833 i->second->drop_references ();
2839 /* build a list of all the possible audio directories for the session */
2841 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2842 SessionDirectory sdir ((*i).path);
2843 asp += sdir.sound_path();
2845 audio_path += asp.to_string();
2848 /* build a list of all the possible midi directories for the session */
2850 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2851 SessionDirectory sdir ((*i).path);
2852 msp += sdir.midi_path();
2854 midi_path += msp.to_string();
2856 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
2857 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
2859 /* find all sources, but don't use this snapshot because the
2860 state file on disk still references sources we may have already
2864 find_all_sources_across_snapshots (all_sources, true);
2866 /* add our current source list
2869 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2870 boost::shared_ptr<FileSource> fs;
2871 SourceMap::iterator tmp = i;
2874 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2876 if (!fs->is_stub()) {
2878 if (playlists->source_use_count (fs) != 0) {
2879 all_sources.insert (fs->path());
2882 /* we might not remove this source from disk, because it may be used
2883 by other snapshots, but its not being used in this version
2884 so lets get rid of it now, along with any representative regions
2888 RegionFactory::remove_regions_using_source (i->second);
2891 // also remove source from all_sources
2893 for (set<string>::iterator j = all_sources.begin(); j != all_sources.end(); ++j) {
2894 spath = Glib::path_get_basename (*j);
2895 if ( spath == i->second->name () ) {
2896 all_sources.erase (j);
2907 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
2912 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2914 tmppath1 = canonical_path (spath);
2915 tmppath2 = canonical_path ((*i));
2917 if (tmppath1 == tmppath2) {
2924 unused.push_back (spath);
2928 /* now try to move all unused files into the "dead" directory(ies) */
2930 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2931 struct stat statbuf;
2935 /* don't move the file across filesystems, just
2936 stick it in the `dead_dir_name' directory
2937 on whichever filesystem it was already on.
2940 if ((*x).find ("/sounds/") != string::npos) {
2942 /* old school, go up 1 level */
2944 newpath = Glib::path_get_dirname (*x); // "sounds"
2945 newpath = Glib::path_get_dirname (newpath); // "session-name"
2949 /* new school, go up 4 levels */
2951 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2952 newpath = Glib::path_get_dirname (newpath); // "session-name"
2953 newpath = Glib::path_get_dirname (newpath); // "interchange"
2954 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2957 newpath = Glib::build_filename (newpath, dead_dir_name);
2959 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2960 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2964 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2966 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2968 /* the new path already exists, try versioning */
2970 char buf[PATH_MAX+1];
2974 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2977 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2978 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2982 if (version == 999) {
2983 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2987 newpath = newpath_v;
2992 /* it doesn't exist, or we can't read it or something */
2996 stat ((*x).c_str(), &statbuf);
2998 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2999 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
3000 (*x), newpath, strerror (errno))
3005 /* see if there an easy to find peakfile for this file, and remove it.
3008 string base = basename_nosuffix (*x);
3009 base += "%A"; /* this is what we add for the channel suffix of all native files,
3010 or for the first channel of embedded files. it will miss
3011 some peakfiles for other channels
3013 string peakpath = peak_path (base);
3015 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
3016 if (::g_unlink (peakpath.c_str()) != 0) {
3017 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3018 peakpath, _path, strerror (errno))
3020 /* try to back out */
3021 ::rename (newpath.c_str(), _path.c_str());
3026 rep.paths.push_back (*x);
3027 rep.space += statbuf.st_size;
3030 /* dump the history list */
3034 /* save state so we don't end up a session file
3035 referring to non-existent sources.
3042 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3048 Session::cleanup_trash_sources (CleanupReport& rep)
3050 // FIXME: needs adaptation for MIDI
3052 vector<space_and_path>::iterator i;
3058 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3060 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
3062 clear_directory (dead_dir, &rep.space, &rep.paths);
3069 Session::set_dirty ()
3071 /* never mark session dirty during loading */
3073 if (_state_of_the_state & Loading) {
3077 bool was_dirty = dirty();
3079 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3083 DirtyChanged(); /* EMIT SIGNAL */
3089 Session::set_clean ()
3091 bool was_dirty = dirty();
3093 _state_of_the_state = Clean;
3097 DirtyChanged(); /* EMIT SIGNAL */
3102 Session::set_deletion_in_progress ()
3104 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3108 Session::clear_deletion_in_progress ()
3110 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3114 Session::add_controllable (boost::shared_ptr<Controllable> c)
3116 /* this adds a controllable to the list managed by the Session.
3117 this is a subset of those managed by the Controllable class
3118 itself, and represents the only ones whose state will be saved
3119 as part of the session.
3122 Glib::Threads::Mutex::Lock lm (controllables_lock);
3123 controllables.insert (c);
3126 struct null_deleter { void operator()(void const *) const {} };
3129 Session::remove_controllable (Controllable* c)
3131 if (_state_of_the_state & Deletion) {
3135 Glib::Threads::Mutex::Lock lm (controllables_lock);
3137 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3139 if (x != controllables.end()) {
3140 controllables.erase (x);
3144 boost::shared_ptr<Controllable>
3145 Session::controllable_by_id (const PBD::ID& id)
3147 Glib::Threads::Mutex::Lock lm (controllables_lock);
3149 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3150 if ((*i)->id() == id) {
3155 return boost::shared_ptr<Controllable>();
3158 boost::shared_ptr<Controllable>
3159 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3161 boost::shared_ptr<Controllable> c;
3162 boost::shared_ptr<Route> r;
3164 switch (desc.top_level_type()) {
3165 case ControllableDescriptor::NamedRoute:
3167 std::string str = desc.top_level_name();
3168 if (str == "Master" || str == "master") {
3170 } else if (str == "control" || str == "listen") {
3173 r = route_by_name (desc.top_level_name());
3178 case ControllableDescriptor::RemoteControlID:
3179 r = route_by_remote_id (desc.rid());
3187 switch (desc.subtype()) {
3188 case ControllableDescriptor::Gain:
3189 c = r->gain_control ();
3192 case ControllableDescriptor::Trim:
3193 c = r->trim()->gain_control ();
3196 case ControllableDescriptor::Solo:
3197 c = r->solo_control();
3200 case ControllableDescriptor::Mute:
3201 c = r->mute_control();
3204 case ControllableDescriptor::Recenable:
3206 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3209 c = t->rec_enable_control ();
3214 case ControllableDescriptor::PanDirection:
3216 c = r->pannable()->pan_azimuth_control;
3220 case ControllableDescriptor::PanWidth:
3222 c = r->pannable()->pan_width_control;
3226 case ControllableDescriptor::PanElevation:
3228 c = r->pannable()->pan_elevation_control;
3232 case ControllableDescriptor::Balance:
3233 /* XXX simple pan control */
3236 case ControllableDescriptor::PluginParameter:
3238 uint32_t plugin = desc.target (0);
3239 uint32_t parameter_index = desc.target (1);
3241 /* revert to zero based counting */
3247 if (parameter_index > 0) {
3251 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3254 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3255 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3260 case ControllableDescriptor::SendGain:
3262 uint32_t send = desc.target (0);
3264 /* revert to zero-based counting */
3270 boost::shared_ptr<Processor> p = r->nth_send (send);
3273 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3274 boost::shared_ptr<Amp> a = s->amp();
3277 c = s->amp()->gain_control();
3284 /* relax and return a null pointer */
3292 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3295 Stateful::add_instant_xml (node, _path);
3298 if (write_to_config) {
3299 Config->add_instant_xml (node);
3304 Session::instant_xml (const string& node_name)
3306 return Stateful::instant_xml (node_name, _path);
3310 Session::save_history (string snapshot_name)
3318 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3319 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3323 if (snapshot_name.empty()) {
3324 snapshot_name = _current_snapshot_name;
3327 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3328 const string backup_filename = history_filename + backup_suffix;
3329 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3330 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3332 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3333 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3334 error << _("could not backup old history file, current history not saved") << endmsg;
3339 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3341 if (!tree.write (xml_path))
3343 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3345 if (g_remove (xml_path.c_str()) != 0) {
3346 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3347 xml_path, g_strerror (errno)) << endmsg;
3349 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3350 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3351 backup_path, g_strerror (errno)) << endmsg;
3361 Session::restore_history (string snapshot_name)
3365 if (snapshot_name.empty()) {
3366 snapshot_name = _current_snapshot_name;
3369 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3370 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3372 info << "Loading history from " << xml_path << endmsg;
3374 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3375 info << string_compose (_("%1: no history file \"%2\" for this session."),
3376 _name, xml_path) << endmsg;
3380 if (!tree.read (xml_path)) {
3381 error << string_compose (_("Could not understand session history file \"%1\""),
3382 xml_path) << endmsg;
3389 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3392 UndoTransaction* ut = new UndoTransaction ();
3395 ut->set_name(t->property("name")->value());
3396 stringstream ss(t->property("tv-sec")->value());
3398 ss.str(t->property("tv-usec")->value());
3400 ut->set_timestamp(tv);
3402 for (XMLNodeConstIterator child_it = t->children().begin();
3403 child_it != t->children().end(); child_it++)
3405 XMLNode *n = *child_it;
3408 if (n->name() == "MementoCommand" ||
3409 n->name() == "MementoUndoCommand" ||
3410 n->name() == "MementoRedoCommand") {
3412 if ((c = memento_command_factory(n))) {
3416 } else if (n->name() == "NoteDiffCommand") {
3417 PBD::ID id (n->property("midi-source")->value());
3418 boost::shared_ptr<MidiSource> midi_source =
3419 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3421 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3423 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3426 } else if (n->name() == "SysExDiffCommand") {
3428 PBD::ID id (n->property("midi-source")->value());
3429 boost::shared_ptr<MidiSource> midi_source =
3430 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3432 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3434 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3437 } else if (n->name() == "PatchChangeDiffCommand") {
3439 PBD::ID id (n->property("midi-source")->value());
3440 boost::shared_ptr<MidiSource> midi_source =
3441 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3443 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3445 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3448 } else if (n->name() == "StatefulDiffCommand") {
3449 if ((c = stateful_diff_command_factory (n))) {
3450 ut->add_command (c);
3453 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3464 Session::config_changed (std::string p, bool ours)
3470 if (p == "seamless-loop") {
3472 } else if (p == "rf-speed") {
3474 } else if (p == "auto-loop") {
3476 } else if (p == "auto-input") {
3478 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3479 /* auto-input only makes a difference if we're rolling */
3480 set_track_monitor_input_status (!config.get_auto_input());
3483 } else if (p == "punch-in") {
3487 if ((location = _locations->auto_punch_location()) != 0) {
3489 if (config.get_punch_in ()) {
3490 replace_event (SessionEvent::PunchIn, location->start());
3492 remove_event (location->start(), SessionEvent::PunchIn);
3496 } else if (p == "punch-out") {
3500 if ((location = _locations->auto_punch_location()) != 0) {
3502 if (config.get_punch_out()) {
3503 replace_event (SessionEvent::PunchOut, location->end());
3505 clear_events (SessionEvent::PunchOut);
3509 } else if (p == "edit-mode") {
3511 Glib::Threads::Mutex::Lock lm (playlists->lock);
3513 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3514 (*i)->set_edit_mode (Config->get_edit_mode ());
3517 } else if (p == "use-video-sync") {
3519 waiting_for_sync_offset = config.get_use_video_sync();
3521 } else if (p == "mmc-control") {
3523 //poke_midi_thread ();
3525 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3527 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3529 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3531 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3533 } else if (p == "midi-control") {
3535 //poke_midi_thread ();
3537 } else if (p == "raid-path") {
3539 setup_raid_path (config.get_raid_path());
3541 } else if (p == "timecode-format") {
3545 } else if (p == "video-pullup") {
3549 } else if (p == "seamless-loop") {
3551 if (play_loop && transport_rolling()) {
3552 // to reset diskstreams etc
3553 request_play_loop (true);
3556 } else if (p == "rf-speed") {
3558 cumulative_rf_motion = 0;
3561 } else if (p == "click-sound") {
3563 setup_click_sounds (1);
3565 } else if (p == "click-emphasis-sound") {
3567 setup_click_sounds (-1);
3569 } else if (p == "clicking") {
3571 if (Config->get_clicking()) {
3572 if (_click_io && click_data) { // don't require emphasis data
3579 } else if (p == "click-gain") {
3582 _click_gain->set_gain (Config->get_click_gain(), this);
3585 } else if (p == "send-mtc") {
3587 if (Config->get_send_mtc ()) {
3588 /* mark us ready to send */
3589 next_quarter_frame_to_send = 0;
3592 } else if (p == "send-mmc") {
3594 _mmc->enable_send (Config->get_send_mmc ());
3596 } else if (p == "midi-feedback") {
3598 session_midi_feedback = Config->get_midi_feedback();
3600 } else if (p == "jack-time-master") {
3602 engine().reset_timebase ();
3604 } else if (p == "native-file-header-format") {
3606 if (!first_file_header_format_reset) {
3607 reset_native_file_format ();
3610 first_file_header_format_reset = false;
3612 } else if (p == "native-file-data-format") {
3614 if (!first_file_data_format_reset) {
3615 reset_native_file_format ();
3618 first_file_data_format_reset = false;
3620 } else if (p == "external-sync") {
3621 if (!config.get_external_sync()) {
3622 drop_sync_source ();
3624 switch_to_sync_source (Config->get_sync_source());
3626 } else if (p == "denormal-model") {
3628 } else if (p == "history-depth") {
3629 set_history_depth (Config->get_history_depth());
3630 } else if (p == "remote-model") {
3631 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3634 } else if (p == "initial-program-change") {
3636 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3639 buf[0] = MIDI::program; // channel zero by default
3640 buf[1] = (Config->get_initial_program_change() & 0x7f);
3642 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3644 } else if (p == "solo-mute-override") {
3645 // catch_up_on_solo_mute_override ();
3646 } else if (p == "listen-position" || p == "pfl-position") {
3647 listen_position_changed ();
3648 } else if (p == "solo-control-is-listen-control") {
3649 solo_control_mode_changed ();
3650 } else if (p == "solo-mute-gain") {
3651 _solo_cut_control->Changed();
3652 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3653 last_timecode_valid = false;
3654 } else if (p == "playback-buffer-seconds") {
3655 AudioSource::allocate_working_buffers (frame_rate());
3656 } else if (p == "ltc-source-port") {
3657 reconnect_ltc_input ();
3658 } else if (p == "ltc-sink-port") {
3659 reconnect_ltc_output ();
3660 } else if (p == "timecode-generator-offset") {
3661 ltc_tx_parse_offset();
3662 } else if (p == "auto-return-target-list") {
3663 follow_playhead_priority ();
3670 Session::set_history_depth (uint32_t d)
3672 _history.set_depth (d);
3676 Session::load_diskstreams_2X (XMLNode const & node, int)
3679 XMLNodeConstIterator citer;
3681 clist = node.children();
3683 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3686 /* diskstreams added automatically by DiskstreamCreated handler */
3687 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3688 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3689 _diskstreams_2X.push_back (dsp);
3691 error << _("Session: unknown diskstream type in XML") << endmsg;
3695 catch (failed_constructor& err) {
3696 error << _("Session: could not load diskstream via XML state") << endmsg;
3704 /** Connect things to the MMC object */
3706 Session::setup_midi_machine_control ()
3708 _mmc = new MIDI::MachineControl;
3709 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3711 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3712 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3713 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3714 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3715 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3716 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3717 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3718 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3719 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3720 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3721 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3722 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3723 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3725 /* also handle MIDI SPP because its so common */
3727 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3728 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3729 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3732 boost::shared_ptr<Controllable>
3733 Session::solo_cut_control() const
3735 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3736 controls in Ardour that currently get presented to the user in the GUI that require
3737 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3739 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3740 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3744 return _solo_cut_control;
3748 Session::rename (const std::string& new_name)
3750 string legal_name = legalize_for_path (new_name);
3756 string const old_sources_root = _session_dir->sources_root();
3758 if (!_writable || (_state_of_the_state & CannotSave)) {
3759 error << _("Cannot rename read-only session.") << endmsg;
3760 return 0; // don't show "messed up" warning
3762 if (record_status() == Recording) {
3763 error << _("Cannot rename session while recording") << endmsg;
3764 return 0; // don't show "messed up" warning
3767 StateProtector stp (this);
3772 * interchange subdirectory
3776 * Backup files are left unchanged and not renamed.
3779 /* Windows requires that we close all files before attempting the
3780 * rename. This works on other platforms, but isn't necessary there.
3781 * Leave it in place for all platforms though, since it may help
3782 * catch issues that could arise if the way Source files work ever
3783 * change (since most developers are not using Windows).
3786 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
3787 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3793 /* pass one: not 100% safe check that the new directory names don't
3797 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3801 /* this is a stupid hack because Glib::path_get_dirname() is
3802 * lexical-only, and so passing it /a/b/c/ gives a different
3803 * result than passing it /a/b/c ...
3806 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3807 oldstr = oldstr.substr (0, oldstr.length() - 1);
3810 string base = Glib::path_get_dirname (oldstr);
3812 newstr = Glib::build_filename (base, legal_name);
3814 cerr << "Looking for " << newstr << endl;
3816 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3817 cerr << " exists\n";
3826 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3832 /* this is a stupid hack because Glib::path_get_dirname() is
3833 * lexical-only, and so passing it /a/b/c/ gives a different
3834 * result than passing it /a/b/c ...
3837 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3838 oldstr = oldstr.substr (0, oldstr.length() - 1);
3841 string base = Glib::path_get_dirname (oldstr);
3842 newstr = Glib::build_filename (base, legal_name);
3844 cerr << "for " << oldstr << " new dir = " << newstr << endl;
3846 cerr << "Rename " << oldstr << " => " << newstr << endl;
3847 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3848 cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3849 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3853 /* Reset path in "session dirs" */
3858 /* reset primary SessionDirectory object */
3861 (*_session_dir) = newstr;
3866 /* now rename directory below session_dir/interchange */
3868 string old_interchange_dir;
3869 string new_interchange_dir;
3871 /* use newstr here because we renamed the path
3872 * (folder/directory) that used to be oldstr to newstr above
3875 v.push_back (newstr);
3876 v.push_back (interchange_dir_name);
3877 v.push_back (Glib::path_get_basename (oldstr));
3879 old_interchange_dir = Glib::build_filename (v);
3882 v.push_back (newstr);
3883 v.push_back (interchange_dir_name);
3884 v.push_back (legal_name);
3886 new_interchange_dir = Glib::build_filename (v);
3888 cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
3890 if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
3891 cerr << string_compose (_("renaming %s as %2 failed (%3)"),
3892 old_interchange_dir, new_interchange_dir,
3895 error << string_compose (_("renaming %s as %2 failed (%3)"),
3896 old_interchange_dir, new_interchange_dir,
3905 oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
3906 newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
3908 cerr << "Rename " << oldstr << " => " << newstr << endl;
3910 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3911 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3912 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3918 oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
3920 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3921 newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
3923 cerr << "Rename " << oldstr << " => " << newstr << endl;
3925 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3926 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3927 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3932 /* remove old name from recent sessions */
3933 remove_recent_sessions (_path);
3936 /* update file source paths */
3938 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3939 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3941 string p = fs->path ();
3942 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3944 SourceFactory::setup_peakfile(i->second, true);
3948 _current_snapshot_name = new_name;
3953 /* save state again to get everything just right */
3955 save_state (_current_snapshot_name);
3957 /* add to recent sessions */
3959 store_recent_sessions (new_name, _path);
3965 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
3967 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
3971 if (!tree.read (xmlpath)) {
3979 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
3982 bool found_sr = false;
3983 bool found_data_format = false;
3985 if (get_session_info_from_path (tree, xmlpath)) {
3991 const XMLProperty* prop;
3992 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
3993 sample_rate = atoi (prop->value());
3997 const XMLNodeList& children (tree.root()->children());
3998 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
3999 const XMLNode* child = *c;
4000 if (child->name() == "Config") {
4001 const XMLNodeList& options (child->children());
4002 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
4003 const XMLNode* option = *oc;
4004 const XMLProperty* name = option->property("name");
4010 if (name->value() == "native-file-data-format") {
4011 const XMLProperty* value = option->property ("value");
4013 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
4015 found_data_format = true;
4021 if (found_data_format) {
4026 return !(found_sr && found_data_format); // zero if they are both found
4029 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
4030 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
4033 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
4037 SourcePathMap source_path_map;
4039 boost::shared_ptr<AudioFileSource> afs;
4044 Glib::Threads::Mutex::Lock lm (source_lock);
4046 cerr << " total sources = " << sources.size();
4048 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4049 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4055 if (fs->within_session()) {
4059 if (source_path_map.find (fs->path()) != source_path_map.end()) {
4060 source_path_map[fs->path()].push_back (fs);
4062 SeveralFileSources v;
4064 source_path_map.insert (make_pair (fs->path(), v));
4070 cerr << " fsources = " << total << endl;
4072 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
4074 /* tell caller where we are */
4076 string old_path = i->first;
4078 callback (n, total, old_path);
4080 cerr << old_path << endl;
4084 switch (i->second.front()->type()) {
4085 case DataType::AUDIO:
4086 new_path = new_audio_source_path_for_embedded (old_path);
4089 case DataType::MIDI:
4090 /* XXX not implemented yet */
4094 if (new_path.empty()) {
4098 cerr << "Move " << old_path << " => " << new_path << endl;
4100 if (!copy_file (old_path, new_path)) {
4101 cerr << "failed !\n";
4105 /* make sure we stop looking in the external
4106 dir/folder. Remember, this is an all-or-nothing
4107 operations, it doesn't merge just some files.
4109 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
4111 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
4112 (*f)->set_path (new_path);
4117 save_state ("", false, false);
4123 bool accept_all_files (string const &, void *)
4129 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4131 /* 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.
4136 make_new_media_path (string old_path, string new_session_folder, string new_session_path)
4138 /* typedir is the "midifiles" or "audiofiles" etc. part of the path. */
4140 string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4142 v.push_back (new_session_folder); /* full path */
4143 v.push_back (interchange_dir_name);
4144 v.push_back (new_session_path); /* just one directory/folder */
4145 v.push_back (typedir);
4146 v.push_back (Glib::path_get_basename (old_path));
4148 return Glib::build_filename (v);
4152 Session::save_as (SaveAs& saveas)
4154 vector<string> files;
4155 string current_folder = Glib::path_get_dirname (_path);
4156 string new_folder = legalize_for_path (saveas.new_name);
4157 string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4158 int64_t total_bytes = 0;
4162 int32_t internal_file_cnt = 0;
4164 vector<string> do_not_copy_extensions;
4165 do_not_copy_extensions.push_back (statefile_suffix);
4166 do_not_copy_extensions.push_back (pending_suffix);
4167 do_not_copy_extensions.push_back (backup_suffix);
4168 do_not_copy_extensions.push_back (temp_suffix);
4169 do_not_copy_extensions.push_back (history_suffix);
4171 /* get total size */
4173 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4175 /* need to clear this because
4176 * find_files_matching_filter() is cumulative
4181 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4183 all += files.size();
4185 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4187 g_stat ((*i).c_str(), &gsb);
4188 total_bytes += gsb.st_size;
4192 /* save old values so we can switch back if we are not switching to the new session */
4194 string old_path = _path;
4195 string old_name = _name;
4196 string old_snapshot = _current_snapshot_name;
4197 string old_sd = _session_dir->root_path();
4198 vector<string> old_search_path[DataType::num_types];
4199 string old_config_search_path[DataType::num_types];
4201 old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4202 old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4203 old_config_search_path[DataType::AUDIO] = config.get_audio_search_path ();
4204 old_config_search_path[DataType::MIDI] = config.get_midi_search_path ();
4206 /* switch session directory */
4208 (*_session_dir) = to_dir;
4210 /* create new tree */
4212 if (!_session_dir->create()) {
4213 saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4218 /* copy all relevant files. Find each location in session_dirs,
4219 * and copy files from there to target.
4222 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4224 /* need to clear this because
4225 * find_files_matching_filter() is cumulative
4230 const size_t prefix_len = (*sd).path.size();
4232 /* Work just on the files within this session dir */
4234 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4236 /* add dir separator to protect against collisions with
4237 * track names (e.g. track named "audiofiles" or
4241 static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
4242 static const std::string midifile_dir_string = string (midi_dir_name) + G_DIR_SEPARATOR;
4243 static const std::string analysis_dir_string = analysis_dir() + G_DIR_SEPARATOR;
4245 /* copy all the files. Handling is different for media files
4246 than others because of the *silly* subtree we have below the interchange
4247 folder. That really was a bad idea, but I'm not fixing it as part of
4248 implementing ::save_as().
4251 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4253 std::string from = *i;
4256 string filename = Glib::path_get_basename (from);
4257 std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
4258 if (filename == ".DS_STORE") {
4263 if (from.find (audiofile_dir_string) != string::npos) {
4265 /* audio file: only copy if asked */
4267 if (saveas.include_media && saveas.copy_media) {
4269 string to = make_new_media_path (*i, to_dir, new_folder);
4271 info << "media file copying from " << from << " to " << to << endmsg;
4273 if (!copy_file (from, to)) {
4274 throw Glib::FileError (Glib::FileError::IO_ERROR,
4275 string_compose(_("\ncopying \"%1\" failed !"), from));
4279 /* we found media files inside the session folder */
4281 internal_file_cnt++;
4283 } else if (from.find (midifile_dir_string) != string::npos) {
4285 /* midi file: always copy unless
4286 * creating an empty new session
4289 if (saveas.include_media) {
4291 string to = make_new_media_path (*i, to_dir, new_folder);
4293 info << "media file copying from " << from << " to " << to << endmsg;
4295 if (!copy_file (from, to)) {
4296 throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4300 /* we found media files inside the session folder */
4302 internal_file_cnt++;
4304 } else if (from.find (analysis_dir_string) != string::npos) {
4306 /* make sure analysis dir exists in
4307 * new session folder, but we're not
4308 * copying analysis files here, see
4312 (void) g_mkdir_with_parents (analysis_dir().c_str(), 775);
4317 /* normal non-media file. Don't copy state, history, etc.
4320 bool do_copy = true;
4322 for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
4323 if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
4324 /* end of filename matches extension, do not copy file */
4330 if (!saveas.copy_media && from.find (peakfile_suffix) != string::npos) {
4331 /* don't copy peakfiles if
4332 * we're not copying media
4338 string to = Glib::build_filename (to_dir, from.substr (prefix_len));
4340 info << "attempting to make directory/folder " << to << endmsg;
4342 if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
4343 throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
4346 info << "attempting to copy " << from << " to " << to << endmsg;
4348 if (!copy_file (from, to)) {
4349 throw Glib::FileError (Glib::FileError::IO_ERROR,
4350 string_compose(_("\ncopying \"%1\" failed !"), from));
4355 /* measure file size even if we're not going to copy so that our Progress
4356 signals are correct, since we included these do-not-copy files
4357 in the computation of the total size and file count.
4361 g_stat (from.c_str(), &gsb);
4362 copied += gsb.st_size;
4365 double fraction = (double) copied / total_bytes;
4367 bool keep_going = true;
4369 if (saveas.copy_media) {
4371 /* no need or expectation of this if
4372 * media is not being copied, because
4373 * it will be fast(ish).
4376 /* tell someone "X percent, file M of N"; M is one-based */
4378 boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
4386 throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
4392 /* copy optional folders, if any */
4394 string old = plugins_dir ();
4395 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4396 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4397 copy_files (old, newdir);
4400 old = externals_dir ();
4401 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4402 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4403 copy_files (old, newdir);
4406 old = automation_dir ();
4407 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4408 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4409 copy_files (old, newdir);
4412 if (saveas.include_media) {
4414 if (saveas.copy_media) {
4415 #ifndef PLATFORM_WINDOWS
4416 /* There are problems with analysis files on
4417 * Windows, because they used a colon in their
4418 * names as late as 4.0. Colons are not legal
4419 * under Windows even if NTFS allows them.
4421 * This is a tricky problem to solve so for
4422 * just don't copy these files. They will be
4423 * regenerated as-needed anyway, subject to the
4424 * existing issue that the filenames will be
4425 * rejected by Windows, which is a separate
4426 * problem (though related).
4429 /* only needed if we are copying media, since the
4430 * analysis data refers to media data
4433 old = analysis_dir ();
4434 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4435 string newdir = Glib::build_filename (to_dir, "analysis");
4436 copy_files (old, newdir);
4438 #endif /* PLATFORM_WINDOWS */
4444 _current_snapshot_name = saveas.new_name;
4445 _name = saveas.new_name;
4447 if (saveas.include_media && !saveas.copy_media) {
4449 /* reset search paths of the new session (which we're pretending to be right now) to
4450 include the original session search path, so we can still find all audio.
4453 if (internal_file_cnt) {
4454 for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
4455 ensure_search_path_includes (*s, DataType::AUDIO);
4458 /* we do not do this for MIDI because we copy
4459 all MIDI files if saveas.include_media is
4465 bool was_dirty = dirty ();
4467 save_state ("", false, false, !saveas.include_media);
4468 save_default_options ();
4470 if (saveas.copy_media && saveas.copy_external) {
4471 if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
4472 throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
4476 saveas.final_session_folder_name = _path;
4478 store_recent_sessions (_name, _path);
4480 if (!saveas.switch_to) {
4482 /* switch back to the way things were */
4486 _current_snapshot_name = old_snapshot;
4488 (*_session_dir) = old_sd;
4494 if (internal_file_cnt) {
4495 /* reset these to their original values */
4496 config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
4497 config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
4502 /* prune session dirs, and update disk space statistics
4507 session_dirs.clear ();
4508 session_dirs.push_back (sp);
4509 refresh_disk_space ();
4511 /* ensure that all existing tracks reset their current capture source paths
4513 reset_write_sources (true, true);
4515 /* the copying above was based on actually discovering files, not just iterating over the sources list.
4516 But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
4519 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4520 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4526 if (fs->within_session()) {
4527 string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
4528 fs->set_path (newpath);
4533 } catch (Glib::FileError& e) {
4535 saveas.failure_message = e.what();
4537 /* recursively remove all the directories */
4539 remove_directory (to_dir);
4547 saveas.failure_message = _("unknown reason");
4549 /* recursively remove all the directories */
4551 remove_directory (to_dir);