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"
30 #include <cstdio> /* snprintf(3) ... grrr */
42 #include <sys/param.h>
43 #include <sys/mount.h>
46 #ifdef HAVE_SYS_STATVFS_H
47 #include <sys/statvfs.h>
51 #include "pbd/gstdio_compat.h"
54 #include <glibmm/threads.h>
55 #include <glibmm/fileutils.h>
57 #include <boost/algorithm/string.hpp>
59 #include "midi++/mmc.h"
60 #include "midi++/port.h"
62 #include "evoral/SMF.hpp"
64 #include "pbd/boost_debug.h"
65 #include "pbd/basename.h"
66 #include "pbd/controllable_descriptor.h"
67 #include "pbd/debug.h"
68 #include "pbd/enumwriter.h"
69 #include "pbd/error.h"
70 #include "pbd/file_utils.h"
71 #include "pbd/pathexpand.h"
72 #include "pbd/pthread_utils.h"
73 #include "pbd/stacktrace.h"
74 #include "pbd/convert.h"
75 #include "pbd/localtime_r.h"
77 #include "ardour/amp.h"
78 #include "ardour/async_midi_port.h"
79 #include "ardour/audio_diskstream.h"
80 #include "ardour/audio_track.h"
81 #include "ardour/audioengine.h"
82 #include "ardour/audiofilesource.h"
83 #include "ardour/audioregion.h"
84 #include "ardour/automation_control.h"
85 #include "ardour/butler.h"
86 #include "ardour/control_protocol_manager.h"
87 #include "ardour/directory_names.h"
88 #include "ardour/filename_extensions.h"
89 #include "ardour/graph.h"
90 #include "ardour/location.h"
91 #include "ardour/midi_model.h"
92 #include "ardour/midi_patch_manager.h"
93 #include "ardour/midi_region.h"
94 #include "ardour/midi_scene_changer.h"
95 #include "ardour/midi_source.h"
96 #include "ardour/midi_track.h"
97 #include "ardour/pannable.h"
98 #include "ardour/playlist_factory.h"
99 #include "ardour/playlist_source.h"
100 #include "ardour/port.h"
101 #include "ardour/processor.h"
102 #include "ardour/profile.h"
103 #include "ardour/proxy_controllable.h"
104 #include "ardour/recent_sessions.h"
105 #include "ardour/region_factory.h"
106 #include "ardour/route_group.h"
107 #include "ardour/send.h"
108 #include "ardour/session.h"
109 #include "ardour/session_directory.h"
110 #include "ardour/session_metadata.h"
111 #include "ardour/session_playlists.h"
112 #include "ardour/session_state_utils.h"
113 #include "ardour/silentfilesource.h"
114 #include "ardour/sndfilesource.h"
115 #include "ardour/source_factory.h"
116 #include "ardour/speakers.h"
117 #include "ardour/template_utils.h"
118 #include "ardour/tempo.h"
119 #include "ardour/ticker.h"
120 #include "ardour/user_bundle.h"
122 #include "control_protocol/control_protocol.h"
128 using namespace ARDOUR;
131 #define DEBUG_UNDO_HISTORY(msg) DEBUG_TRACE (PBD::DEBUG::UndoHistory, string_compose ("%1: %2\n", __LINE__, msg));
134 Session::pre_engine_init (string fullpath)
136 if (fullpath.empty()) {
138 throw failed_constructor();
141 /* discover canonical fullpath */
143 _path = canonical_path(fullpath);
146 if (Profile->get_trx() ) {
147 // Waves TracksLive has a usecase of session replacement with a new one.
148 // We should check session state file (<session_name>.ardour) existance
149 // to determine if the session is new or not
151 string full_session_name = Glib::build_filename( fullpath, _name );
152 full_session_name += statefile_suffix;
154 _is_new = !Glib::file_test (full_session_name, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
156 _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
159 /* finish initialization that can't be done in a normal C++ constructor
163 timerclear (&last_mmc_step);
164 g_atomic_int_set (&processing_prohibited, 0);
165 g_atomic_int_set (&_record_status, Disabled);
166 g_atomic_int_set (&_playback_load, 100);
167 g_atomic_int_set (&_capture_load, 100);
169 _all_route_group->set_active (true, this);
170 interpolation.add_channel_to (0, 0);
172 if (config.get_use_video_sync()) {
173 waiting_for_sync_offset = true;
175 waiting_for_sync_offset = false;
178 last_rr_session_dir = session_dirs.begin();
180 set_history_depth (Config->get_history_depth());
182 /* default: assume simple stereo speaker configuration */
184 _speakers->setup_default_speakers (2);
186 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
187 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
188 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
189 add_controllable (_solo_cut_control);
191 /* These are all static "per-class" signals */
193 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
194 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
195 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
196 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
197 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
199 /* stop IO objects from doing stuff until we're ready for them */
201 Delivery::disable_panners ();
202 IO::disable_connecting ();
206 Session::post_engine_init ()
208 BootMessage (_("Set block size and sample rate"));
210 set_block_size (_engine.samples_per_cycle());
211 set_frame_rate (_engine.sample_rate());
213 BootMessage (_("Using configuration"));
215 _midi_ports = new MidiPortManager;
217 MIDISceneChanger* msc;
219 _scene_changer = msc = new MIDISceneChanger (*this);
220 msc->set_input_port (scene_input_port());
221 msc->set_output_port (scene_out());
223 boost::function<framecnt_t(void)> timer_func (boost::bind (&Session::audible_frame, this));
224 boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_in())->set_timer (timer_func);
226 setup_midi_machine_control ();
228 if (_butler->start_thread()) {
232 if (start_midi_thread ()) {
236 setup_click_sounds (0);
237 setup_midi_control ();
239 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
240 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
243 /* tempo map requires sample rate knowledge */
246 _tempo_map = new TempoMap (_current_frame_rate);
247 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
249 /* MidiClock requires a tempo map */
251 midi_clock = new MidiClockTicker ();
252 midi_clock->set_session (this);
254 /* crossfades require sample rate knowledge */
256 SndFileSource::setup_standard_crossfades (*this, frame_rate());
257 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
259 AudioDiskstream::allocate_working_buffers();
260 refresh_disk_space ();
262 /* we're finally ready to call set_state() ... all objects have
263 * been created, the engine is running.
267 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
271 // set_state() will call setup_raid_path(), but if it's a new session we need
272 // to call setup_raid_path() here.
273 setup_raid_path (_path);
278 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
279 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
281 Config->map_parameters (ff);
282 config.map_parameters (ft);
283 _butler->map_parameters ();
285 /* Reset all panners */
287 Delivery::reset_panners ();
289 /* this will cause the CPM to instantiate any protocols that are in use
290 * (or mandatory), which will pass it this Session, and then call
291 * set_state() on each instantiated protocol to match stored state.
294 ControlProtocolManager::instance().set_session (this);
296 /* This must be done after the ControlProtocolManager set_session above,
297 as it will set states for ports which the ControlProtocolManager creates.
300 // XXX set state of MIDI::Port's
301 // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
303 /* And this must be done after the MIDI::Manager::set_port_states as
304 * it will try to make connections whose details are loaded by set_port_states.
309 /* Let control protocols know that we are now all connected, so they
310 * could start talking to surfaces if they want to.
313 ControlProtocolManager::instance().midi_connectivity_established ();
315 if (_is_new && !no_auto_connect()) {
316 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
317 auto_connect_master_bus ();
320 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
322 /* update latencies */
324 initialize_latencies ();
326 _locations->added.connect_same_thread (*this, boost::bind (&Session::location_added, this, _1));
327 _locations->removed.connect_same_thread (*this, boost::bind (&Session::location_removed, this, _1));
328 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
330 } catch (AudioEngine::PortRegistrationFailure& err) {
331 /* handle this one in a different way than all others, so that its clear what happened */
332 error << err.what() << endmsg;
338 BootMessage (_("Reset Remote Controls"));
340 // send_full_time_code (0);
341 _engine.transport_locate (0);
343 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
344 send_immediate_mmc (MIDI::MachineControlCommand (Timecode::Time ()));
346 MIDI::Name::MidiPatchManager::instance().set_session (this);
349 /* initial program change will be delivered later; see ::config_changed() */
351 _state_of_the_state = Clean;
353 Port::set_connecting_blocked (false);
355 DirtyChanged (); /* EMIT SIGNAL */
359 } else if (state_was_pending) {
361 remove_pending_capture_state ();
362 state_was_pending = false;
365 /* Now, finally, we can fill the playback buffers */
367 BootMessage (_("Filling playback buffers"));
369 boost::shared_ptr<RouteList> rl = routes.reader();
370 for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
371 boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<Track> (*r);
372 if (trk && !trk->hidden()) {
373 trk->seek (_transport_frame, true);
381 Session::session_loaded ()
385 _state_of_the_state = Clean;
387 DirtyChanged (); /* EMIT SIGNAL */
391 } else if (state_was_pending) {
393 remove_pending_capture_state ();
394 state_was_pending = false;
397 /* Now, finally, we can fill the playback buffers */
399 BootMessage (_("Filling playback buffers"));
400 force_locate (_transport_frame, false);
404 Session::raid_path () const
406 Searchpath raid_search_path;
408 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
409 raid_search_path += (*i).path;
412 return raid_search_path.to_string ();
416 Session::setup_raid_path (string path)
425 session_dirs.clear ();
427 Searchpath search_path(path);
428 Searchpath sound_search_path;
429 Searchpath midi_search_path;
431 for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
433 sp.blocks = 0; // not needed
434 session_dirs.push_back (sp);
436 SessionDirectory sdir(sp.path);
438 sound_search_path += sdir.sound_path ();
439 midi_search_path += sdir.midi_path ();
442 // reset the round-robin soundfile path thingie
443 last_rr_session_dir = session_dirs.begin();
447 Session::path_is_within_session (const std::string& path)
449 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
450 if (PBD::path_is_within (i->path, path)) {
458 Session::ensure_subdirs ()
462 dir = session_directory().peak_path();
464 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
465 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
469 dir = session_directory().sound_path();
471 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
472 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
476 dir = session_directory().midi_path();
478 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
479 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
483 dir = session_directory().dead_path();
485 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
486 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
490 dir = session_directory().export_path();
492 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
493 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
497 dir = analysis_dir ();
499 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
500 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
504 dir = plugins_dir ();
506 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
507 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
511 dir = externals_dir ();
513 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
514 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
521 /** @param session_template directory containing session template, or empty.
522 * Caller must not hold process lock.
525 Session::create (const string& session_template, BusProfile* bus_profile)
527 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
528 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
532 if (ensure_subdirs ()) {
536 _writable = exists_and_writable (_path);
538 if (!session_template.empty()) {
539 string in_path = (ARDOUR::Profile->get_trx () ? session_template : session_template_dir_to_file (session_template));
541 FILE* in = g_fopen (in_path.c_str(), "rb");
544 /* no need to call legalize_for_path() since the string
545 * in session_template is already a legal path name
547 string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
549 FILE* out = g_fopen (out_path.c_str(), "wb");
553 stringstream new_session;
556 size_t charsRead = fread (buf, sizeof(char), 1024, in);
559 error << string_compose (_("Error reading session template file %1 (%2)"), in_path, strerror (errno)) << endmsg;
564 if (charsRead == 0) {
567 new_session.write (buf, charsRead);
571 string file_contents = new_session.str();
572 size_t writeSize = file_contents.length();
573 if (fwrite (file_contents.c_str(), sizeof(char), writeSize, out) != writeSize) {
574 error << string_compose (_("Error writing session template file %1 (%2)"), out_path, strerror (errno)) << endmsg;
582 if (!ARDOUR::Profile->get_trx()) {
583 /* Copy plugin state files from template to new session */
584 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
585 copy_recurse (template_plugins, plugins_dir ());
591 error << string_compose (_("Could not open %1 for writing session template"), out_path)
598 error << string_compose (_("Could not open session template %1 for reading"), in_path)
605 if (Profile->get_trx()) {
607 /* set initial start + end point : ARDOUR::Session::session_end_shift long.
608 Remember that this is a brand new session. Sessions
609 loaded from saved state will get this range from the saved state.
612 set_session_range_location (0, 0);
614 /* Initial loop location, from absolute zero, length 10 seconds */
616 Location* loc = new Location (*this, 0, 10.0 * _engine.sample_rate(), _("Loop"), Location::IsAutoLoop);
617 _locations->add (loc, true);
618 set_auto_loop_location (loc);
621 _state_of_the_state = Clean;
623 /* set up Master Out and Control Out if necessary */
628 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
630 // Waves Tracks: always create master bus for Tracks
631 if (ARDOUR::Profile->get_trx() || bus_profile->master_out_channels) {
632 boost::shared_ptr<Route> r (new Route (*this, _("Master"), Route::MasterOut, DataType::AUDIO));
636 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
637 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
640 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
641 r->input()->ensure_io (count, false, this);
642 r->output()->ensure_io (count, false, this);
648 /* prohibit auto-connect to master, because there isn't one */
649 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
653 add_routes (rl, false, false, false);
656 // Waves Tracks: Skip this. Always use autoconnection for Tracks
657 if (!ARDOUR::Profile->get_trx()) {
659 /* this allows the user to override settings with an environment variable.
662 if (no_auto_connect()) {
663 bus_profile->input_ac = AutoConnectOption (0);
664 bus_profile->output_ac = AutoConnectOption (0);
667 Config->set_input_auto_connect (bus_profile->input_ac);
668 Config->set_output_auto_connect (bus_profile->output_ac);
672 if (Config->get_use_monitor_bus() && bus_profile) {
673 add_monitor_section ();
680 Session::maybe_write_autosave()
682 if (dirty() && record_status() != Recording) {
683 save_state("", true);
688 Session::remove_pending_capture_state ()
690 std::string pending_state_file_path(_session_dir->root_path());
692 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
694 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
696 if (g_remove (pending_state_file_path.c_str()) != 0) {
697 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
698 pending_state_file_path, g_strerror (errno)) << endmsg;
702 /** Rename a state file.
703 * @param old_name Old snapshot name.
704 * @param new_name New snapshot name.
707 Session::rename_state (string old_name, string new_name)
709 if (old_name == _current_snapshot_name || old_name == _name) {
710 /* refuse to rename the current snapshot or the "main" one */
714 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
715 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
717 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
718 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
720 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
721 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
722 old_name, new_name, g_strerror(errno)) << endmsg;
726 /** Remove a state file.
727 * @param snapshot_name Snapshot name.
730 Session::remove_state (string snapshot_name)
732 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
733 // refuse to remove the current snapshot or the "main" one
737 std::string xml_path(_session_dir->root_path());
739 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
741 if (!create_backup_file (xml_path)) {
742 // don't remove it if a backup can't be made
743 // create_backup_file will log the error.
748 if (g_remove (xml_path.c_str()) != 0) {
749 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
750 xml_path, g_strerror (errno)) << endmsg;
754 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
756 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot, bool template_only)
759 std::string xml_path(_session_dir->root_path());
761 /* prevent concurrent saves from different threads */
763 Glib::Threads::Mutex::Lock lm (save_state_lock);
765 if (!_writable || (_state_of_the_state & CannotSave)) {
769 if (g_atomic_int_get(&_suspend_save)) {
773 _save_queued = false;
775 if (!_engine.connected ()) {
776 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
782 /* tell sources we're saving first, in case they write out to a new file
783 * which should be saved with the state rather than the old one */
784 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
786 i->second->session_saved();
787 } catch (Evoral::SMF::FileError& e) {
788 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
792 SessionSaveUnderway (); /* EMIT SIGNAL */
794 bool mark_as_clean = true;
796 if (!snapshot_name.empty() && !switch_to_snapshot) {
797 mark_as_clean = false;
801 mark_as_clean = false;
802 tree.set_root (&get_template());
804 tree.set_root (&get_state());
807 if (snapshot_name.empty()) {
808 snapshot_name = _current_snapshot_name;
809 } else if (switch_to_snapshot) {
810 _current_snapshot_name = snapshot_name;
813 assert (!snapshot_name.empty());
817 /* proper save: use statefile_suffix (.ardour in English) */
819 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
821 /* make a backup copy of the old file */
823 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
824 // create_backup_file will log the error
830 /* pending save: use pending_suffix (.pending in English) */
831 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
834 std::string tmp_path(_session_dir->root_path());
835 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
837 cerr << "actually writing state to " << tmp_path << endl;
839 if (!tree.write (tmp_path)) {
840 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
841 if (g_remove (tmp_path.c_str()) != 0) {
842 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
843 tmp_path, g_strerror (errno)) << endmsg;
849 cerr << "renaming state to " << xml_path << endl;
851 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
852 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
853 tmp_path, xml_path, g_strerror(errno)) << endmsg;
854 if (g_remove (tmp_path.c_str()) != 0) {
855 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
856 tmp_path, g_strerror (errno)) << endmsg;
864 save_history (snapshot_name);
867 bool was_dirty = dirty();
869 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
872 DirtyChanged (); /* EMIT SIGNAL */
876 StateSaved (snapshot_name); /* EMIT SIGNAL */
883 Session::restore_state (string snapshot_name)
885 if (load_state (snapshot_name) == 0) {
886 set_state (*state_tree->root(), Stateful::loading_state_version);
893 Session::load_state (string snapshot_name)
898 state_was_pending = false;
900 /* check for leftover pending state from a crashed capture attempt */
902 std::string xmlpath(_session_dir->root_path());
903 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
905 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
907 /* there is pending state from a crashed capture attempt */
909 boost::optional<int> r = AskAboutPendingState();
910 if (r.get_value_or (1)) {
911 state_was_pending = true;
915 if (!state_was_pending) {
916 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
919 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
920 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
921 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
922 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
927 state_tree = new XMLTree;
931 _writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
933 if (!state_tree->read (xmlpath)) {
934 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
940 XMLNode& root (*state_tree->root());
942 if (root.name() != X_("Session")) {
943 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
949 const XMLProperty* prop;
951 if ((prop = root.property ("version")) == 0) {
952 /* no version implies very old version of Ardour */
953 Stateful::loading_state_version = 1000;
955 if (prop->value().find ('.') != string::npos) {
956 /* old school version format */
957 if (prop->value()[0] == '2') {
958 Stateful::loading_state_version = 2000;
960 Stateful::loading_state_version = 3000;
963 Stateful::loading_state_version = atoi (prop->value());
967 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
969 std::string backup_path(_session_dir->root_path());
970 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
971 backup_path = Glib::build_filename (backup_path, backup_filename);
973 // only create a backup for a given statefile version once
975 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
977 VersionMismatch (xmlpath, backup_path);
979 if (!copy_file (xmlpath, backup_path)) {;
989 Session::load_options (const XMLNode& node)
991 LocaleGuard lg (X_("C"));
992 config.set_variables (node);
997 Session::save_default_options ()
999 return config.save_state();
1003 Session::get_state()
1009 Session::get_template()
1011 /* if we don't disable rec-enable, diskstreams
1012 will believe they need to store their capture
1013 sources in their state node.
1016 disable_record (false);
1018 return state(false);
1022 Session::state (bool full_state)
1024 XMLNode* node = new XMLNode("Session");
1028 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
1029 node->add_property("version", buf);
1031 /* store configuration settings */
1035 node->add_property ("name", _name);
1036 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
1037 node->add_property ("sample-rate", buf);
1039 if (session_dirs.size() > 1) {
1043 vector<space_and_path>::iterator i = session_dirs.begin();
1044 vector<space_and_path>::iterator next;
1046 ++i; /* skip the first one */
1050 while (i != session_dirs.end()) {
1054 if (next != session_dirs.end()) {
1055 p += G_SEARCHPATH_SEPARATOR;
1064 child = node->add_child ("Path");
1065 child->add_content (p);
1069 /* save the ID counter */
1071 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1072 node->add_property ("id-counter", buf);
1074 /* save the event ID counter */
1076 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1077 node->add_property ("event-counter", buf);
1079 /* various options */
1081 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
1082 if (!midi_port_nodes.empty()) {
1083 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
1084 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
1085 midi_port_stuff->add_child_nocopy (**n);
1087 node->add_child_nocopy (*midi_port_stuff);
1090 node->add_child_nocopy (config.get_variables ());
1092 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1094 child = node->add_child ("Sources");
1097 Glib::Threads::Mutex::Lock sl (source_lock);
1099 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1101 /* Don't save information about non-file Sources, or
1102 * about non-destructive file sources that are empty
1103 * and unused by any regions.
1106 boost::shared_ptr<FileSource> fs;
1108 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1110 if (!fs->destructive()) {
1111 if (fs->empty() && !fs->used()) {
1116 child->add_child_nocopy (siter->second->get_state());
1121 child = node->add_child ("Regions");
1124 Glib::Threads::Mutex::Lock rl (region_lock);
1125 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1126 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1127 boost::shared_ptr<Region> r = i->second;
1128 /* only store regions not attached to playlists */
1129 if (r->playlist() == 0) {
1130 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1131 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1133 child->add_child_nocopy (r->get_state ());
1138 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1140 if (!cassocs.empty()) {
1141 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1143 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1145 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1146 i->first->id().print (buf, sizeof (buf));
1147 can->add_property (X_("copy"), buf);
1148 i->second->id().print (buf, sizeof (buf));
1149 can->add_property (X_("original"), buf);
1150 ca->add_child_nocopy (*can);
1160 node->add_child_nocopy (_locations->get_state());
1163 Locations loc (*this);
1164 // for a template, just create a new Locations, populate it
1165 // with the default start and end, and get the state for that.
1166 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1167 range->set (max_framepos, 0);
1169 XMLNode& locations_state = loc.get_state();
1171 if (ARDOUR::Profile->get_trx() && _locations) {
1172 // For tracks we need stored the Auto Loop Range and all MIDI markers.
1173 for (Locations::LocationList::const_iterator i = _locations->list ().begin (); i != _locations->list ().end (); ++i) {
1174 if ((*i)->is_mark () || (*i)->is_auto_loop ()) {
1175 locations_state.add_child_nocopy ((*i)->get_state ());
1179 node->add_child_nocopy (locations_state);
1182 child = node->add_child ("Bundles");
1184 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1185 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1186 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1188 child->add_child_nocopy (b->get_state());
1193 child = node->add_child ("Routes");
1195 boost::shared_ptr<RouteList> r = routes.reader ();
1197 RoutePublicOrderSorter cmp;
1198 RouteList public_order (*r);
1199 public_order.sort (cmp);
1201 /* the sort should have put control outs first */
1204 assert (_monitor_out == public_order.front());
1207 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1208 if (!(*i)->is_auditioner()) {
1210 child->add_child_nocopy ((*i)->get_state());
1212 child->add_child_nocopy ((*i)->get_template());
1218 playlists->add_state (node, full_state);
1220 child = node->add_child ("RouteGroups");
1221 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1222 child->add_child_nocopy ((*i)->get_state());
1226 XMLNode* gain_child = node->add_child ("Click");
1227 gain_child->add_child_nocopy (_click_io->state (full_state));
1228 gain_child->add_child_nocopy (_click_gain->state (full_state));
1232 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1233 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1237 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1238 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1241 node->add_child_nocopy (_speakers->get_state());
1242 node->add_child_nocopy (_tempo_map->get_state());
1243 node->add_child_nocopy (get_control_protocol_state());
1246 node->add_child_copy (*_extra_xml);
1253 Session::get_control_protocol_state ()
1255 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1256 return cpm.get_state();
1260 Session::set_state (const XMLNode& node, int version)
1264 const XMLProperty* prop;
1267 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1269 if (node.name() != X_("Session")) {
1270 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1274 if ((prop = node.property ("name")) != 0) {
1275 _name = prop->value ();
1278 if ((prop = node.property (X_("sample-rate"))) != 0) {
1280 _nominal_frame_rate = atoi (prop->value());
1282 if (_nominal_frame_rate != _current_frame_rate) {
1283 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1284 if (r.get_value_or (0)) {
1290 setup_raid_path(_session_dir->root_path());
1292 if ((prop = node.property (X_("id-counter"))) != 0) {
1294 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1295 ID::init_counter (x);
1297 /* old sessions used a timebased counter, so fake
1298 the startup ID counter based on a standard
1303 ID::init_counter (now);
1306 if ((prop = node.property (X_("event-counter"))) != 0) {
1307 Evoral::init_event_id_counter (atoi (prop->value()));
1311 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1312 _midi_ports->set_midi_port_states (child->children());
1315 IO::disable_connecting ();
1317 Stateful::save_extra_xml (node);
1319 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1320 load_options (*child);
1321 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1322 load_options (*child);
1324 error << _("Session: XML state has no options section") << endmsg;
1327 if (version >= 3000) {
1328 if ((child = find_named_node (node, "Metadata")) == 0) {
1329 warning << _("Session: XML state has no metadata section") << endmsg;
1330 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1335 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1336 _speakers->set_state (*child, version);
1339 if ((child = find_named_node (node, "Sources")) == 0) {
1340 error << _("Session: XML state has no sources section") << endmsg;
1342 } else if (load_sources (*child)) {
1346 if ((child = find_named_node (node, "TempoMap")) == 0) {
1347 error << _("Session: XML state has no Tempo Map section") << endmsg;
1349 } else if (_tempo_map->set_state (*child, version)) {
1353 if ((child = find_named_node (node, "Locations")) == 0) {
1354 error << _("Session: XML state has no locations section") << endmsg;
1356 } else if (_locations->set_state (*child, version)) {
1360 locations_changed ();
1362 if (_session_range_location) {
1363 AudioFileSource::set_header_position_offset (_session_range_location->start());
1366 if ((child = find_named_node (node, "Regions")) == 0) {
1367 error << _("Session: XML state has no Regions section") << endmsg;
1369 } else if (load_regions (*child)) {
1373 if ((child = find_named_node (node, "Playlists")) == 0) {
1374 error << _("Session: XML state has no playlists section") << endmsg;
1376 } else if (playlists->load (*this, *child)) {
1380 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1382 } else if (playlists->load_unused (*this, *child)) {
1386 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1387 if (load_compounds (*child)) {
1392 if (version >= 3000) {
1393 if ((child = find_named_node (node, "Bundles")) == 0) {
1394 warning << _("Session: XML state has no bundles section") << endmsg;
1397 /* We can't load Bundles yet as they need to be able
1398 to convert from port names to Port objects, which can't happen until
1400 _bundle_xml_node = new XMLNode (*child);
1404 if (version < 3000) {
1405 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1406 error << _("Session: XML state has no diskstreams section") << endmsg;
1408 } else if (load_diskstreams_2X (*child, version)) {
1413 if ((child = find_named_node (node, "Routes")) == 0) {
1414 error << _("Session: XML state has no routes section") << endmsg;
1416 } else if (load_routes (*child, version)) {
1420 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1421 _diskstreams_2X.clear ();
1423 if (version >= 3000) {
1425 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1426 error << _("Session: XML state has no route groups section") << endmsg;
1428 } else if (load_route_groups (*child, version)) {
1432 } else if (version < 3000) {
1434 if ((child = find_named_node (node, "EditGroups")) == 0) {
1435 error << _("Session: XML state has no edit groups section") << endmsg;
1437 } else if (load_route_groups (*child, version)) {
1441 if ((child = find_named_node (node, "MixGroups")) == 0) {
1442 error << _("Session: XML state has no mix groups section") << endmsg;
1444 } else if (load_route_groups (*child, version)) {
1449 if ((child = find_named_node (node, "Click")) == 0) {
1450 warning << _("Session: XML state has no click section") << endmsg;
1451 } else if (_click_io) {
1452 setup_click_state (&node);
1455 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1456 ControlProtocolManager::instance().set_state (*child, version);
1459 update_route_record_state ();
1461 /* here beginneth the second phase ... */
1463 StateReady (); /* EMIT SIGNAL */
1476 Session::load_routes (const XMLNode& node, int version)
1479 XMLNodeConstIterator niter;
1480 RouteList new_routes;
1482 nlist = node.children();
1486 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1488 boost::shared_ptr<Route> route;
1489 if (version < 3000) {
1490 route = XMLRouteFactory_2X (**niter, version);
1492 route = XMLRouteFactory (**niter, version);
1496 error << _("Session: cannot create Route from XML description.") << endmsg;
1500 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1502 new_routes.push_back (route);
1505 BootMessage (_("Tracks/busses loaded; Adding to Session"));
1507 add_routes (new_routes, false, false, false);
1509 BootMessage (_("Finished adding tracks/busses"));
1514 boost::shared_ptr<Route>
1515 Session::XMLRouteFactory (const XMLNode& node, int version)
1517 boost::shared_ptr<Route> ret;
1519 if (node.name() != "Route") {
1523 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1525 DataType type = DataType::AUDIO;
1526 const XMLProperty* prop = node.property("default-type");
1529 type = DataType (prop->value());
1532 assert (type != DataType::NIL);
1536 boost::shared_ptr<Track> track;
1538 if (type == DataType::AUDIO) {
1539 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1541 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1544 if (track->init()) {
1548 if (track->set_state (node, version)) {
1552 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1553 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1558 enum Route::Flag flags = Route::Flag(0);
1559 const XMLProperty* prop = node.property("flags");
1561 flags = Route::Flag (string_2_enum (prop->value(), flags));
1564 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1566 if (r->init () == 0 && r->set_state (node, version) == 0) {
1567 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1568 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1577 boost::shared_ptr<Route>
1578 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1580 boost::shared_ptr<Route> ret;
1582 if (node.name() != "Route") {
1586 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1588 ds_prop = node.property (X_("diskstream"));
1591 DataType type = DataType::AUDIO;
1592 const XMLProperty* prop = node.property("default-type");
1595 type = DataType (prop->value());
1598 assert (type != DataType::NIL);
1602 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1603 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1607 if (i == _diskstreams_2X.end()) {
1608 error << _("Could not find diskstream for route") << endmsg;
1609 return boost::shared_ptr<Route> ();
1612 boost::shared_ptr<Track> track;
1614 if (type == DataType::AUDIO) {
1615 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1617 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1620 if (track->init()) {
1624 if (track->set_state (node, version)) {
1628 track->set_diskstream (*i);
1630 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1631 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1636 enum Route::Flag flags = Route::Flag(0);
1637 const XMLProperty* prop = node.property("flags");
1639 flags = Route::Flag (string_2_enum (prop->value(), flags));
1642 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1644 if (r->init () == 0 && r->set_state (node, version) == 0) {
1645 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1646 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1656 Session::load_regions (const XMLNode& node)
1659 XMLNodeConstIterator niter;
1660 boost::shared_ptr<Region> region;
1662 nlist = node.children();
1666 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1667 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1668 error << _("Session: cannot create Region from XML description.");
1669 const XMLProperty *name = (**niter).property("name");
1672 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1683 Session::load_compounds (const XMLNode& node)
1685 XMLNodeList calist = node.children();
1686 XMLNodeConstIterator caiter;
1687 XMLProperty *caprop;
1689 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1690 XMLNode* ca = *caiter;
1694 if ((caprop = ca->property (X_("original"))) == 0) {
1697 orig_id = caprop->value();
1699 if ((caprop = ca->property (X_("copy"))) == 0) {
1702 copy_id = caprop->value();
1704 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1705 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1707 if (!orig || !copy) {
1708 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1714 RegionFactory::add_compound_association (orig, copy);
1721 Session::load_nested_sources (const XMLNode& node)
1724 XMLNodeConstIterator niter;
1726 nlist = node.children();
1728 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1729 if ((*niter)->name() == "Source") {
1731 /* it may already exist, so don't recreate it unnecessarily
1734 XMLProperty* prop = (*niter)->property (X_("id"));
1736 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1740 ID source_id (prop->value());
1742 if (!source_by_id (source_id)) {
1745 SourceFactory::create (*this, **niter, true);
1747 catch (failed_constructor& err) {
1748 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1755 boost::shared_ptr<Region>
1756 Session::XMLRegionFactory (const XMLNode& node, bool full)
1758 const XMLProperty* type = node.property("type");
1762 const XMLNodeList& nlist = node.children();
1764 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1765 XMLNode *child = (*niter);
1766 if (child->name() == "NestedSource") {
1767 load_nested_sources (*child);
1771 if (!type || type->value() == "audio") {
1772 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1773 } else if (type->value() == "midi") {
1774 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1777 } catch (failed_constructor& err) {
1778 return boost::shared_ptr<Region> ();
1781 return boost::shared_ptr<Region> ();
1784 boost::shared_ptr<AudioRegion>
1785 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1787 const XMLProperty* prop;
1788 boost::shared_ptr<Source> source;
1789 boost::shared_ptr<AudioSource> as;
1791 SourceList master_sources;
1792 uint32_t nchans = 1;
1795 if (node.name() != X_("Region")) {
1796 return boost::shared_ptr<AudioRegion>();
1799 if ((prop = node.property (X_("channels"))) != 0) {
1800 nchans = atoi (prop->value().c_str());
1803 if ((prop = node.property ("name")) == 0) {
1804 cerr << "no name for this region\n";
1808 if ((prop = node.property (X_("source-0"))) == 0) {
1809 if ((prop = node.property ("source")) == 0) {
1810 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1811 return boost::shared_ptr<AudioRegion>();
1815 PBD::ID s_id (prop->value());
1817 if ((source = source_by_id (s_id)) == 0) {
1818 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << 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"), s_id) << endmsg;
1825 return boost::shared_ptr<AudioRegion>();
1828 sources.push_back (as);
1830 /* pickup other channels */
1832 for (uint32_t n=1; n < nchans; ++n) {
1833 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1834 if ((prop = node.property (buf)) != 0) {
1836 PBD::ID id2 (prop->value());
1838 if ((source = source_by_id (id2)) == 0) {
1839 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1840 return boost::shared_ptr<AudioRegion>();
1843 as = boost::dynamic_pointer_cast<AudioSource>(source);
1845 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1846 return boost::shared_ptr<AudioRegion>();
1848 sources.push_back (as);
1852 for (uint32_t n = 0; n < nchans; ++n) {
1853 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1854 if ((prop = node.property (buf)) != 0) {
1856 PBD::ID id2 (prop->value());
1858 if ((source = source_by_id (id2)) == 0) {
1859 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1860 return boost::shared_ptr<AudioRegion>();
1863 as = boost::dynamic_pointer_cast<AudioSource>(source);
1865 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1866 return boost::shared_ptr<AudioRegion>();
1868 master_sources.push_back (as);
1873 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1875 /* a final detail: this is the one and only place that we know how long missing files are */
1877 if (region->whole_file()) {
1878 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1879 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1881 sfp->set_length (region->length());
1886 if (!master_sources.empty()) {
1887 if (master_sources.size() != nchans) {
1888 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1890 region->set_master_sources (master_sources);
1898 catch (failed_constructor& err) {
1899 return boost::shared_ptr<AudioRegion>();
1903 boost::shared_ptr<MidiRegion>
1904 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1906 const XMLProperty* prop;
1907 boost::shared_ptr<Source> source;
1908 boost::shared_ptr<MidiSource> ms;
1911 if (node.name() != X_("Region")) {
1912 return boost::shared_ptr<MidiRegion>();
1915 if ((prop = node.property ("name")) == 0) {
1916 cerr << "no name for this region\n";
1920 if ((prop = node.property (X_("source-0"))) == 0) {
1921 if ((prop = node.property ("source")) == 0) {
1922 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1923 return boost::shared_ptr<MidiRegion>();
1927 PBD::ID s_id (prop->value());
1929 if ((source = source_by_id (s_id)) == 0) {
1930 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1931 return boost::shared_ptr<MidiRegion>();
1934 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1936 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1937 return boost::shared_ptr<MidiRegion>();
1940 sources.push_back (ms);
1943 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1944 /* a final detail: this is the one and only place that we know how long missing files are */
1946 if (region->whole_file()) {
1947 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1948 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1950 sfp->set_length (region->length());
1958 catch (failed_constructor& err) {
1959 return boost::shared_ptr<MidiRegion>();
1964 Session::get_sources_as_xml ()
1967 XMLNode* node = new XMLNode (X_("Sources"));
1968 Glib::Threads::Mutex::Lock lm (source_lock);
1970 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1971 node->add_child_nocopy (i->second->get_state());
1978 Session::reset_write_sources (bool mark_write_complete, bool force)
1980 boost::shared_ptr<RouteList> rl = routes.reader();
1981 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1982 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1984 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
1985 tr->reset_write_sources(mark_write_complete, force);
1986 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
1992 Session::load_sources (const XMLNode& node)
1995 XMLNodeConstIterator niter;
1996 boost::shared_ptr<Source> source; /* don't need this but it stops some
1997 * versions of gcc complaining about
1998 * discarded return values.
2001 nlist = node.children();
2005 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2008 if ((source = XMLSourceFactory (**niter)) == 0) {
2009 error << _("Session: cannot create Source from XML description.") << endmsg;
2012 } catch (MissingSource& err) {
2016 if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
2017 error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
2018 PROGRAM_NAME) << endmsg;
2022 if (!no_questions_about_missing_files) {
2023 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
2028 switch (user_choice) {
2030 /* user added a new search location, so try again */
2035 /* user asked to quit the entire session load
2040 no_questions_about_missing_files = true;
2044 no_questions_about_missing_files = true;
2051 case DataType::AUDIO:
2052 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
2055 case DataType::MIDI:
2056 /* The MIDI file is actually missing so
2057 * just create a new one in the same
2058 * location. Do not announce its
2062 if (!Glib::path_is_absolute (err.path)) {
2063 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
2065 /* this should be an unrecoverable error: we would be creating a MIDI file outside
2070 /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
2071 source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
2072 /* reset ID to match the missing one */
2073 source->set_id (**niter);
2074 /* Now we can announce it */
2075 SourceFactory::SourceCreated (source);
2086 boost::shared_ptr<Source>
2087 Session::XMLSourceFactory (const XMLNode& node)
2089 if (node.name() != "Source") {
2090 return boost::shared_ptr<Source>();
2094 /* note: do peak building in another thread when loading session state */
2095 return SourceFactory::create (*this, node, true);
2098 catch (failed_constructor& err) {
2099 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
2100 return boost::shared_ptr<Source>();
2105 Session::save_template (string template_name)
2107 if ((_state_of_the_state & CannotSave) || template_name.empty ()) {
2111 bool absolute_path = Glib::path_is_absolute (template_name);
2113 /* directory to put the template in */
2114 std::string template_dir_path;
2116 if (!absolute_path) {
2117 std::string user_template_dir(user_template_directory());
2119 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2120 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2121 user_template_dir, g_strerror (errno)) << endmsg;
2125 template_dir_path = Glib::build_filename (user_template_dir, template_name);
2127 template_dir_path = template_name;
2130 if (!ARDOUR::Profile->get_trx()) {
2131 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2132 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2133 template_dir_path) << endmsg;
2137 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2138 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2139 template_dir_path, g_strerror (errno)) << endmsg;
2145 std::string template_file_path;
2147 if (ARDOUR::Profile->get_trx()) {
2148 template_file_path = template_name;
2150 if (absolute_path) {
2151 template_file_path = Glib::build_filename (template_dir_path, Glib::path_get_basename (template_dir_path) + template_suffix);
2153 template_file_path = Glib::build_filename (template_dir_path, template_name + template_suffix);
2157 SessionSaveUnderway (); /* EMIT SIGNAL */
2161 tree.set_root (&get_template());
2162 if (!tree.write (template_file_path)) {
2163 error << _("template not saved") << endmsg;
2167 if (!ARDOUR::Profile->get_trx()) {
2168 /* copy plugin state directory */
2170 std::string template_plugin_state_path (Glib::build_filename (template_dir_path, X_("plugins")));
2172 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
2173 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
2174 template_plugin_state_path, g_strerror (errno)) << endmsg;
2177 copy_files (plugins_dir(), template_plugin_state_path);
2180 store_recent_templates (template_file_path);
2186 Session::refresh_disk_space ()
2188 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2190 Glib::Threads::Mutex::Lock lm (space_lock);
2192 /* get freespace on every FS that is part of the session path */
2194 _total_free_4k_blocks = 0;
2195 _total_free_4k_blocks_uncertain = false;
2197 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2199 struct statfs statfsbuf;
2200 statfs (i->path.c_str(), &statfsbuf);
2202 double const scale = statfsbuf.f_bsize / 4096.0;
2204 /* See if this filesystem is read-only */
2205 struct statvfs statvfsbuf;
2206 statvfs (i->path.c_str(), &statvfsbuf);
2208 /* f_bavail can be 0 if it is undefined for whatever
2209 filesystem we are looking at; Samba shares mounted
2210 via GVFS are an example of this.
2212 if (statfsbuf.f_bavail == 0) {
2213 /* block count unknown */
2215 i->blocks_unknown = true;
2216 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2217 /* read-only filesystem */
2219 i->blocks_unknown = false;
2221 /* read/write filesystem with known space */
2222 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2223 i->blocks_unknown = false;
2226 _total_free_4k_blocks += i->blocks;
2227 if (i->blocks_unknown) {
2228 _total_free_4k_blocks_uncertain = true;
2231 #elif defined PLATFORM_WINDOWS
2232 vector<string> scanned_volumes;
2233 vector<string>::iterator j;
2234 vector<space_and_path>::iterator i;
2235 DWORD nSectorsPerCluster, nBytesPerSector,
2236 nFreeClusters, nTotalClusters;
2240 _total_free_4k_blocks = 0;
2242 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2243 strncpy (disk_drive, (*i).path.c_str(), 3);
2247 volume_found = false;
2248 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2250 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2251 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2252 i->blocks = (uint32_t)(nFreeBytes / 4096);
2254 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2255 if (0 == j->compare(disk_drive)) {
2256 volume_found = true;
2261 if (!volume_found) {
2262 scanned_volumes.push_back(disk_drive);
2263 _total_free_4k_blocks += i->blocks;
2268 if (0 == _total_free_4k_blocks) {
2269 strncpy (disk_drive, path().c_str(), 3);
2272 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2274 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2275 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2276 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2283 Session::get_best_session_directory_for_new_audio ()
2285 vector<space_and_path>::iterator i;
2286 string result = _session_dir->root_path();
2288 /* handle common case without system calls */
2290 if (session_dirs.size() == 1) {
2294 /* OK, here's the algorithm we're following here:
2296 We want to select which directory to use for
2297 the next file source to be created. Ideally,
2298 we'd like to use a round-robin process so as to
2299 get maximum performance benefits from splitting
2300 the files across multiple disks.
2302 However, in situations without much diskspace, an
2303 RR approach may end up filling up a filesystem
2304 with new files while others still have space.
2305 Its therefore important to pay some attention to
2306 the freespace in the filesystem holding each
2307 directory as well. However, if we did that by
2308 itself, we'd keep creating new files in the file
2309 system with the most space until it was as full
2310 as all others, thus negating any performance
2311 benefits of this RAID-1 like approach.
2313 So, we use a user-configurable space threshold. If
2314 there are at least 2 filesystems with more than this
2315 much space available, we use RR selection between them.
2316 If not, then we pick the filesystem with the most space.
2318 This gets a good balance between the two
2322 refresh_disk_space ();
2324 int free_enough = 0;
2326 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2327 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2332 if (free_enough >= 2) {
2333 /* use RR selection process, ensuring that the one
2337 i = last_rr_session_dir;
2340 if (++i == session_dirs.end()) {
2341 i = session_dirs.begin();
2344 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2345 SessionDirectory sdir(i->path);
2346 if (sdir.create ()) {
2348 last_rr_session_dir = i;
2353 } while (i != last_rr_session_dir);
2357 /* pick FS with the most freespace (and that
2358 seems to actually work ...)
2361 vector<space_and_path> sorted;
2362 space_and_path_ascending_cmp cmp;
2364 sorted = session_dirs;
2365 sort (sorted.begin(), sorted.end(), cmp);
2367 for (i = sorted.begin(); i != sorted.end(); ++i) {
2368 SessionDirectory sdir(i->path);
2369 if (sdir.create ()) {
2371 last_rr_session_dir = i;
2381 Session::automation_dir () const
2383 return Glib::build_filename (_path, automation_dir_name);
2387 Session::analysis_dir () const
2389 return Glib::build_filename (_path, analysis_dir_name);
2393 Session::plugins_dir () const
2395 return Glib::build_filename (_path, plugins_dir_name);
2399 Session::externals_dir () const
2401 return Glib::build_filename (_path, externals_dir_name);
2405 Session::load_bundles (XMLNode const & node)
2407 XMLNodeList nlist = node.children();
2408 XMLNodeConstIterator niter;
2412 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2413 if ((*niter)->name() == "InputBundle") {
2414 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2415 } else if ((*niter)->name() == "OutputBundle") {
2416 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2418 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2427 Session::load_route_groups (const XMLNode& node, int version)
2429 XMLNodeList nlist = node.children();
2430 XMLNodeConstIterator niter;
2434 if (version >= 3000) {
2436 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2437 if ((*niter)->name() == "RouteGroup") {
2438 RouteGroup* rg = new RouteGroup (*this, "");
2439 add_route_group (rg);
2440 rg->set_state (**niter, version);
2444 } else if (version < 3000) {
2446 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2447 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2448 RouteGroup* rg = new RouteGroup (*this, "");
2449 add_route_group (rg);
2450 rg->set_state (**niter, version);
2459 state_file_filter (const string &str, void* /*arg*/)
2461 return (str.length() > strlen(statefile_suffix) &&
2462 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2466 remove_end(string state)
2468 string statename(state);
2470 string::size_type start,end;
2471 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2472 statename = statename.substr (start+1);
2475 if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2476 end = statename.length();
2479 return string(statename.substr (0, end));
2483 Session::possible_states (string path)
2485 vector<string> states;
2486 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2488 transform(states.begin(), states.end(), states.begin(), remove_end);
2490 sort (states.begin(), states.end());
2496 Session::possible_states () const
2498 return possible_states(_path);
2502 Session::add_route_group (RouteGroup* g)
2504 _route_groups.push_back (g);
2505 route_group_added (g); /* EMIT SIGNAL */
2507 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2508 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2509 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2515 Session::remove_route_group (RouteGroup& rg)
2517 list<RouteGroup*>::iterator i;
2519 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2520 _route_groups.erase (i);
2523 route_group_removed (); /* EMIT SIGNAL */
2527 /** Set a new order for our route groups, without adding or removing any.
2528 * @param groups Route group list in the new order.
2531 Session::reorder_route_groups (list<RouteGroup*> groups)
2533 _route_groups = groups;
2535 route_groups_reordered (); /* EMIT SIGNAL */
2541 Session::route_group_by_name (string name)
2543 list<RouteGroup *>::iterator i;
2545 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2546 if ((*i)->name() == name) {
2554 Session::all_route_group() const
2556 return *_all_route_group;
2560 Session::add_commands (vector<Command*> const & cmds)
2562 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2568 Session::add_command (Command* const cmd)
2570 assert (_current_trans);
2571 DEBUG_UNDO_HISTORY (
2572 string_compose ("Current Undo Transaction %1, adding command: %2",
2573 _current_trans->name (),
2575 _current_trans->add_command (cmd);
2578 Session::begin_reversible_command (const string& name)
2580 begin_reversible_command (g_quark_from_string (name.c_str ()));
2583 /** Begin a reversible command using a GQuark to identify it.
2584 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2585 * but there must be as many begin...()s as there are commit...()s.
2588 Session::begin_reversible_command (GQuark q)
2590 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2591 to hold all the commands that are committed. This keeps the order of
2592 commands correct in the history.
2595 if (_current_trans == 0) {
2596 DEBUG_UNDO_HISTORY (string_compose (
2597 "Begin Reversible Command, new transaction: %1", g_quark_to_string (q)));
2599 /* start a new transaction */
2600 assert (_current_trans_quarks.empty ());
2601 _current_trans = new UndoTransaction();
2602 _current_trans->set_name (g_quark_to_string (q));
2604 DEBUG_UNDO_HISTORY (
2605 string_compose ("Begin Reversible Command, current transaction: %1",
2606 _current_trans->name ()));
2609 _current_trans_quarks.push_front (q);
2613 Session::abort_reversible_command ()
2615 if (_current_trans != 0) {
2616 DEBUG_UNDO_HISTORY (
2617 string_compose ("Abort Reversible Command: %1", _current_trans->name ()));
2618 _current_trans->clear();
2619 delete _current_trans;
2621 _current_trans_quarks.clear();
2626 Session::commit_reversible_command (Command *cmd)
2628 assert (_current_trans);
2629 assert (!_current_trans_quarks.empty ());
2634 DEBUG_UNDO_HISTORY (
2635 string_compose ("Current Undo Transaction %1, adding command: %2",
2636 _current_trans->name (),
2638 _current_trans->add_command (cmd);
2641 DEBUG_UNDO_HISTORY (
2642 string_compose ("Commit Reversible Command, current transaction: %1",
2643 _current_trans->name ()));
2645 _current_trans_quarks.pop_front ();
2647 if (!_current_trans_quarks.empty ()) {
2648 DEBUG_UNDO_HISTORY (
2649 string_compose ("Commit Reversible Command, transaction is not "
2650 "top-level, current transaction: %1",
2651 _current_trans->name ()));
2652 /* the transaction we're committing is not the top-level one */
2656 if (_current_trans->empty()) {
2657 /* no commands were added to the transaction, so just get rid of it */
2658 DEBUG_UNDO_HISTORY (
2659 string_compose ("Commit Reversible Command, No commands were "
2660 "added to current transaction: %1",
2661 _current_trans->name ()));
2662 delete _current_trans;
2667 gettimeofday (&now, 0);
2668 _current_trans->set_timestamp (now);
2670 _history.add (_current_trans);
2675 accept_all_audio_files (const string& path, void* /*arg*/)
2677 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2681 if (!AudioFileSource::safe_audio_file_extension (path)) {
2689 accept_all_midi_files (const string& path, void* /*arg*/)
2691 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2695 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2696 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2697 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2701 accept_all_state_files (const string& path, void* /*arg*/)
2703 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2707 std::string const statefile_ext (statefile_suffix);
2708 if (path.length() >= statefile_ext.length()) {
2709 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2716 Session::find_all_sources (string path, set<string>& result)
2721 if (!tree.read (path)) {
2725 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2730 XMLNodeConstIterator niter;
2732 nlist = node->children();
2736 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2740 if ((prop = (*niter)->property (X_("type"))) == 0) {
2744 DataType type (prop->value());
2746 if ((prop = (*niter)->property (X_("name"))) == 0) {
2750 if (Glib::path_is_absolute (prop->value())) {
2751 /* external file, ignore */
2759 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2760 result.insert (found_path);
2768 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2770 vector<string> state_files;
2772 string this_snapshot_path;
2778 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2779 ripped = ripped.substr (0, ripped.length() - 1);
2782 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2784 if (state_files.empty()) {
2789 this_snapshot_path = _path;
2790 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2791 this_snapshot_path += statefile_suffix;
2793 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2795 if (exclude_this_snapshot && *i == this_snapshot_path) {
2799 if (find_all_sources (*i, result) < 0) {
2807 struct RegionCounter {
2808 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2809 AudioSourceList::iterator iter;
2810 boost::shared_ptr<Region> region;
2813 RegionCounter() : count (0) {}
2817 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2819 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2820 return r.get_value_or (1);
2824 Session::cleanup_regions ()
2826 bool removed = false;
2827 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2829 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2831 uint32_t used = playlists->region_use_count (i->second);
2833 if (used == 0 && !i->second->automatic ()) {
2834 boost::weak_ptr<Region> w = i->second;
2837 RegionFactory::map_remove (w);
2844 // re-check to remove parent references of compound regions
2845 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2846 if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2850 assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2851 if (0 == playlists->region_use_count (i->second)) {
2852 boost::weak_ptr<Region> w = i->second;
2854 RegionFactory::map_remove (w);
2861 /* dump the history list */
2868 Session::can_cleanup_peakfiles () const
2870 if (deletion_in_progress()) {
2873 if (!_writable || (_state_of_the_state & CannotSave)) {
2874 warning << _("Cannot cleanup peak-files for read-only session.") << endmsg;
2877 if (record_status() == Recording) {
2878 error << _("Cannot cleanup peak-files while recording") << endmsg;
2885 Session::cleanup_peakfiles ()
2887 Glib::Threads::Mutex::Lock lm (peak_cleanup_lock, Glib::Threads::TRY_LOCK);
2892 assert (can_cleanup_peakfiles ());
2893 assert (!peaks_cleanup_in_progres());
2895 _state_of_the_state = StateOfTheState (_state_of_the_state | PeakCleanup);
2897 int timeout = 5000; // 5 seconds
2898 while (!SourceFactory::files_with_peaks.empty()) {
2899 Glib::usleep (1000);
2900 if (--timeout < 0) {
2901 warning << _("Timeout waiting for peak-file creation to terminate before cleanup, please try again later.") << endmsg;
2902 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
2907 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2908 boost::shared_ptr<AudioSource> as;
2909 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
2910 as->close_peakfile();
2914 PBD::clear_directory (session_directory().peak_path());
2916 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
2918 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2919 boost::shared_ptr<AudioSource> as;
2920 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
2921 SourceFactory::setup_peakfile(as, true);
2928 Session::cleanup_sources (CleanupReport& rep)
2930 // FIXME: needs adaptation to midi
2932 vector<boost::shared_ptr<Source> > dead_sources;
2935 vector<string> candidates;
2936 vector<string> unused;
2937 set<string> all_sources;
2946 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2948 /* this is mostly for windows which doesn't allow file
2949 * renaming if the file is in use. But we don't special
2950 * case it because we need to know if this causes
2951 * problems, and the easiest way to notice that is to
2952 * keep it in place for all platforms.
2955 request_stop (false);
2957 _butler->wait_until_finished ();
2959 /* consider deleting all unused playlists */
2961 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2966 /* sync the "all regions" property of each playlist with its current state
2969 playlists->sync_all_regions_with_regions ();
2971 /* find all un-used sources */
2976 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2978 SourceMap::iterator tmp;
2983 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2987 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2988 dead_sources.push_back (i->second);
2989 i->second->drop_references ();
2995 /* build a list of all the possible audio directories for the session */
2997 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2998 SessionDirectory sdir ((*i).path);
2999 asp += sdir.sound_path();
3001 audio_path += asp.to_string();
3004 /* build a list of all the possible midi directories for the session */
3006 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3007 SessionDirectory sdir ((*i).path);
3008 msp += sdir.midi_path();
3010 midi_path += msp.to_string();
3012 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
3013 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
3015 /* find all sources, but don't use this snapshot because the
3016 state file on disk still references sources we may have already
3020 find_all_sources_across_snapshots (all_sources, true);
3022 /* add our current source list
3025 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3026 boost::shared_ptr<FileSource> fs;
3027 SourceMap::iterator tmp = i;
3030 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
3032 /* this is mostly for windows which doesn't allow file
3033 * renaming if the file is in use. But we don't special
3034 * case it because we need to know if this causes
3035 * problems, and the easiest way to notice that is to
3036 * keep it in place for all platforms.
3041 if (!fs->is_stub()) {
3043 if (playlists->source_use_count (fs) != 0) {
3044 all_sources.insert (fs->path());
3047 /* we might not remove this source from disk, because it may be used
3048 by other snapshots, but its not being used in this version
3049 so lets get rid of it now, along with any representative regions
3053 RegionFactory::remove_regions_using_source (i->second);
3055 // also remove source from all_sources
3057 for (set<string>::iterator j = all_sources.begin(); j != all_sources.end(); ++j) {
3058 spath = Glib::path_get_basename (*j);
3059 if (spath == i->second->name()) {
3060 all_sources.erase (j);
3073 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
3078 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
3080 tmppath1 = canonical_path (spath);
3081 tmppath2 = canonical_path ((*i));
3083 if (tmppath1 == tmppath2) {
3090 unused.push_back (spath);
3094 /* now try to move all unused files into the "dead" directory(ies) */
3096 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
3101 /* don't move the file across filesystems, just
3102 stick it in the `dead_dir_name' directory
3103 on whichever filesystem it was already on.
3106 if ((*x).find ("/sounds/") != string::npos) {
3108 /* old school, go up 1 level */
3110 newpath = Glib::path_get_dirname (*x); // "sounds"
3111 newpath = Glib::path_get_dirname (newpath); // "session-name"
3115 /* new school, go up 4 levels */
3117 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
3118 newpath = Glib::path_get_dirname (newpath); // "session-name"
3119 newpath = Glib::path_get_dirname (newpath); // "interchange"
3120 newpath = Glib::path_get_dirname (newpath); // "session-dir"
3123 newpath = Glib::build_filename (newpath, dead_dir_name);
3125 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
3126 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
3130 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
3132 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
3134 /* the new path already exists, try versioning */
3136 char buf[PATH_MAX+1];
3140 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3143 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
3144 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3148 if (version == 999) {
3149 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3153 newpath = newpath_v;
3158 /* it doesn't exist, or we can't read it or something */
3162 g_stat ((*x).c_str(), &statbuf);
3164 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3165 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
3166 (*x), newpath, strerror (errno))
3171 /* see if there an easy to find peakfile for this file, and remove it.
3174 string base = Glib::path_get_basename (*x);
3175 base += "%A"; /* this is what we add for the channel suffix of all native files,
3176 or for the first channel of embedded files. it will miss
3177 some peakfiles for other channels
3179 string peakpath = construct_peak_filepath (base);
3181 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
3182 if (::g_unlink (peakpath.c_str()) != 0) {
3183 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3184 peakpath, _path, strerror (errno))
3186 /* try to back out */
3187 ::rename (newpath.c_str(), _path.c_str());
3192 rep.paths.push_back (*x);
3193 rep.space += statbuf.st_size;
3196 /* dump the history list */
3200 /* save state so we don't end up a session file
3201 referring to non-existent sources.
3208 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3214 Session::cleanup_trash_sources (CleanupReport& rep)
3216 // FIXME: needs adaptation for MIDI
3218 vector<space_and_path>::iterator i;
3224 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3226 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
3228 clear_directory (dead_dir, &rep.space, &rep.paths);
3235 Session::set_dirty ()
3237 /* never mark session dirty during loading */
3239 if (_state_of_the_state & Loading) {
3243 bool was_dirty = dirty();
3245 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3249 DirtyChanged(); /* EMIT SIGNAL */
3255 Session::set_clean ()
3257 bool was_dirty = dirty();
3259 _state_of_the_state = Clean;
3263 DirtyChanged(); /* EMIT SIGNAL */
3268 Session::set_deletion_in_progress ()
3270 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3274 Session::clear_deletion_in_progress ()
3276 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3280 Session::add_controllable (boost::shared_ptr<Controllable> c)
3282 /* this adds a controllable to the list managed by the Session.
3283 this is a subset of those managed by the Controllable class
3284 itself, and represents the only ones whose state will be saved
3285 as part of the session.
3288 Glib::Threads::Mutex::Lock lm (controllables_lock);
3289 controllables.insert (c);
3292 struct null_deleter { void operator()(void const *) const {} };
3295 Session::remove_controllable (Controllable* c)
3297 if (_state_of_the_state & Deletion) {
3301 Glib::Threads::Mutex::Lock lm (controllables_lock);
3303 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3305 if (x != controllables.end()) {
3306 controllables.erase (x);
3310 boost::shared_ptr<Controllable>
3311 Session::controllable_by_id (const PBD::ID& id)
3313 Glib::Threads::Mutex::Lock lm (controllables_lock);
3315 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3316 if ((*i)->id() == id) {
3321 return boost::shared_ptr<Controllable>();
3324 boost::shared_ptr<Controllable>
3325 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3327 boost::shared_ptr<Controllable> c;
3328 boost::shared_ptr<Route> r;
3330 switch (desc.top_level_type()) {
3331 case ControllableDescriptor::NamedRoute:
3333 std::string str = desc.top_level_name();
3334 if (str == "Master" || str == "master") {
3336 } else if (str == "control" || str == "listen") {
3339 r = route_by_name (desc.top_level_name());
3344 case ControllableDescriptor::RemoteControlID:
3345 r = route_by_remote_id (desc.rid());
3353 switch (desc.subtype()) {
3354 case ControllableDescriptor::Gain:
3355 c = r->gain_control ();
3358 case ControllableDescriptor::Trim:
3359 c = r->trim()->gain_control ();
3362 case ControllableDescriptor::Solo:
3363 c = r->solo_control();
3366 case ControllableDescriptor::Mute:
3367 c = r->mute_control();
3370 case ControllableDescriptor::Recenable:
3372 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3375 c = t->rec_enable_control ();
3380 case ControllableDescriptor::PanDirection:
3382 c = r->pannable()->pan_azimuth_control;
3386 case ControllableDescriptor::PanWidth:
3388 c = r->pannable()->pan_width_control;
3392 case ControllableDescriptor::PanElevation:
3394 c = r->pannable()->pan_elevation_control;
3398 case ControllableDescriptor::Balance:
3399 /* XXX simple pan control */
3402 case ControllableDescriptor::PluginParameter:
3404 uint32_t plugin = desc.target (0);
3405 uint32_t parameter_index = desc.target (1);
3407 /* revert to zero based counting */
3413 if (parameter_index > 0) {
3417 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3420 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3421 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3426 case ControllableDescriptor::SendGain:
3428 uint32_t send = desc.target (0);
3430 /* revert to zero-based counting */
3436 boost::shared_ptr<Processor> p = r->nth_send (send);
3439 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3440 boost::shared_ptr<Amp> a = s->amp();
3443 c = s->amp()->gain_control();
3450 /* relax and return a null pointer */
3458 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3461 Stateful::add_instant_xml (node, _path);
3464 if (write_to_config) {
3465 Config->add_instant_xml (node);
3470 Session::instant_xml (const string& node_name)
3472 return Stateful::instant_xml (node_name, _path);
3476 Session::save_history (string snapshot_name)
3484 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3485 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3489 if (snapshot_name.empty()) {
3490 snapshot_name = _current_snapshot_name;
3493 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3494 const string backup_filename = history_filename + backup_suffix;
3495 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3496 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3498 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3499 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3500 error << _("could not backup old history file, current history not saved") << endmsg;
3505 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3507 if (!tree.write (xml_path))
3509 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3511 if (g_remove (xml_path.c_str()) != 0) {
3512 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3513 xml_path, g_strerror (errno)) << endmsg;
3515 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3516 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3517 backup_path, g_strerror (errno)) << endmsg;
3527 Session::restore_history (string snapshot_name)
3531 if (snapshot_name.empty()) {
3532 snapshot_name = _current_snapshot_name;
3535 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3536 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3538 info << "Loading history from " << xml_path << endmsg;
3540 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3541 info << string_compose (_("%1: no history file \"%2\" for this session."),
3542 _name, xml_path) << endmsg;
3546 if (!tree.read (xml_path)) {
3547 error << string_compose (_("Could not understand session history file \"%1\""),
3548 xml_path) << endmsg;
3555 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3558 UndoTransaction* ut = new UndoTransaction ();
3561 ut->set_name(t->property("name")->value());
3562 stringstream ss(t->property("tv-sec")->value());
3564 ss.str(t->property("tv-usec")->value());
3566 ut->set_timestamp(tv);
3568 for (XMLNodeConstIterator child_it = t->children().begin();
3569 child_it != t->children().end(); child_it++)
3571 XMLNode *n = *child_it;
3574 if (n->name() == "MementoCommand" ||
3575 n->name() == "MementoUndoCommand" ||
3576 n->name() == "MementoRedoCommand") {
3578 if ((c = memento_command_factory(n))) {
3582 } else if (n->name() == "NoteDiffCommand") {
3583 PBD::ID id (n->property("midi-source")->value());
3584 boost::shared_ptr<MidiSource> midi_source =
3585 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3587 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3589 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3592 } else if (n->name() == "SysExDiffCommand") {
3594 PBD::ID id (n->property("midi-source")->value());
3595 boost::shared_ptr<MidiSource> midi_source =
3596 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3598 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3600 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3603 } else if (n->name() == "PatchChangeDiffCommand") {
3605 PBD::ID id (n->property("midi-source")->value());
3606 boost::shared_ptr<MidiSource> midi_source =
3607 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3609 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3611 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3614 } else if (n->name() == "StatefulDiffCommand") {
3615 if ((c = stateful_diff_command_factory (n))) {
3616 ut->add_command (c);
3619 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3630 Session::config_changed (std::string p, bool ours)
3636 if (p == "seamless-loop") {
3638 } else if (p == "rf-speed") {
3640 } else if (p == "auto-loop") {
3642 } else if (p == "auto-input") {
3644 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3645 /* auto-input only makes a difference if we're rolling */
3646 set_track_monitor_input_status (!config.get_auto_input());
3649 } else if (p == "punch-in") {
3653 if ((location = _locations->auto_punch_location()) != 0) {
3655 if (config.get_punch_in ()) {
3656 replace_event (SessionEvent::PunchIn, location->start());
3658 remove_event (location->start(), SessionEvent::PunchIn);
3662 } else if (p == "punch-out") {
3666 if ((location = _locations->auto_punch_location()) != 0) {
3668 if (config.get_punch_out()) {
3669 replace_event (SessionEvent::PunchOut, location->end());
3671 clear_events (SessionEvent::PunchOut);
3675 } else if (p == "edit-mode") {
3677 Glib::Threads::Mutex::Lock lm (playlists->lock);
3679 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3680 (*i)->set_edit_mode (Config->get_edit_mode ());
3683 } else if (p == "use-video-sync") {
3685 waiting_for_sync_offset = config.get_use_video_sync();
3687 } else if (p == "mmc-control") {
3689 //poke_midi_thread ();
3691 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3693 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3695 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3697 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3699 } else if (p == "midi-control") {
3701 //poke_midi_thread ();
3703 } else if (p == "raid-path") {
3705 setup_raid_path (config.get_raid_path());
3707 } else if (p == "timecode-format") {
3711 } else if (p == "video-pullup") {
3715 } else if (p == "seamless-loop") {
3717 if (play_loop && transport_rolling()) {
3718 // to reset diskstreams etc
3719 request_play_loop (true);
3722 } else if (p == "rf-speed") {
3724 cumulative_rf_motion = 0;
3727 } else if (p == "click-sound") {
3729 setup_click_sounds (1);
3731 } else if (p == "click-emphasis-sound") {
3733 setup_click_sounds (-1);
3735 } else if (p == "clicking") {
3737 if (Config->get_clicking()) {
3738 if (_click_io && click_data) { // don't require emphasis data
3745 } else if (p == "click-gain") {
3748 _click_gain->set_gain (Config->get_click_gain(), this);
3751 } else if (p == "send-mtc") {
3753 if (Config->get_send_mtc ()) {
3754 /* mark us ready to send */
3755 next_quarter_frame_to_send = 0;
3758 } else if (p == "send-mmc") {
3760 _mmc->enable_send (Config->get_send_mmc ());
3762 } else if (p == "midi-feedback") {
3764 session_midi_feedback = Config->get_midi_feedback();
3766 } else if (p == "jack-time-master") {
3768 engine().reset_timebase ();
3770 } else if (p == "native-file-header-format") {
3772 if (!first_file_header_format_reset) {
3773 reset_native_file_format ();
3776 first_file_header_format_reset = false;
3778 } else if (p == "native-file-data-format") {
3780 if (!first_file_data_format_reset) {
3781 reset_native_file_format ();
3784 first_file_data_format_reset = false;
3786 } else if (p == "external-sync") {
3787 if (!config.get_external_sync()) {
3788 drop_sync_source ();
3790 switch_to_sync_source (Config->get_sync_source());
3792 } else if (p == "denormal-model") {
3794 } else if (p == "history-depth") {
3795 set_history_depth (Config->get_history_depth());
3796 } else if (p == "remote-model") {
3797 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3800 } else if (p == "initial-program-change") {
3802 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3805 buf[0] = MIDI::program; // channel zero by default
3806 buf[1] = (Config->get_initial_program_change() & 0x7f);
3808 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3810 } else if (p == "solo-mute-override") {
3811 // catch_up_on_solo_mute_override ();
3812 } else if (p == "listen-position" || p == "pfl-position") {
3813 listen_position_changed ();
3814 } else if (p == "solo-control-is-listen-control") {
3815 solo_control_mode_changed ();
3816 } else if (p == "solo-mute-gain") {
3817 _solo_cut_control->Changed();
3818 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3819 last_timecode_valid = false;
3820 } else if (p == "playback-buffer-seconds") {
3821 AudioSource::allocate_working_buffers (frame_rate());
3822 } else if (p == "ltc-source-port") {
3823 reconnect_ltc_input ();
3824 } else if (p == "ltc-sink-port") {
3825 reconnect_ltc_output ();
3826 } else if (p == "timecode-generator-offset") {
3827 ltc_tx_parse_offset();
3828 } else if (p == "auto-return-target-list") {
3829 follow_playhead_priority ();
3836 Session::set_history_depth (uint32_t d)
3838 _history.set_depth (d);
3842 Session::load_diskstreams_2X (XMLNode const & node, int)
3845 XMLNodeConstIterator citer;
3847 clist = node.children();
3849 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3852 /* diskstreams added automatically by DiskstreamCreated handler */
3853 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3854 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3855 _diskstreams_2X.push_back (dsp);
3857 error << _("Session: unknown diskstream type in XML") << endmsg;
3861 catch (failed_constructor& err) {
3862 error << _("Session: could not load diskstream via XML state") << endmsg;
3870 /** Connect things to the MMC object */
3872 Session::setup_midi_machine_control ()
3874 _mmc = new MIDI::MachineControl;
3875 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3877 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3878 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3879 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3880 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3881 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3882 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3883 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3884 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3885 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3886 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3887 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3888 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3889 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3891 /* also handle MIDI SPP because its so common */
3893 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3894 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3895 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3898 boost::shared_ptr<Controllable>
3899 Session::solo_cut_control() const
3901 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3902 controls in Ardour that currently get presented to the user in the GUI that require
3903 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3905 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3906 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3910 return _solo_cut_control;
3914 Session::rename (const std::string& new_name)
3916 string legal_name = legalize_for_path (new_name);
3922 string const old_sources_root = _session_dir->sources_root();
3924 if (!_writable || (_state_of_the_state & CannotSave)) {
3925 error << _("Cannot rename read-only session.") << endmsg;
3926 return 0; // don't show "messed up" warning
3928 if (record_status() == Recording) {
3929 error << _("Cannot rename session while recording") << endmsg;
3930 return 0; // don't show "messed up" warning
3933 StateProtector stp (this);
3938 * interchange subdirectory
3942 * Backup files are left unchanged and not renamed.
3945 /* Windows requires that we close all files before attempting the
3946 * rename. This works on other platforms, but isn't necessary there.
3947 * Leave it in place for all platforms though, since it may help
3948 * catch issues that could arise if the way Source files work ever
3949 * change (since most developers are not using Windows).
3952 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
3953 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3959 /* pass one: not 100% safe check that the new directory names don't
3963 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3967 /* this is a stupid hack because Glib::path_get_dirname() is
3968 * lexical-only, and so passing it /a/b/c/ gives a different
3969 * result than passing it /a/b/c ...
3972 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3973 oldstr = oldstr.substr (0, oldstr.length() - 1);
3976 string base = Glib::path_get_dirname (oldstr);
3978 newstr = Glib::build_filename (base, legal_name);
3980 cerr << "Looking for " << newstr << endl;
3982 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3983 cerr << " exists\n";
3992 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3998 /* this is a stupid hack because Glib::path_get_dirname() is
3999 * lexical-only, and so passing it /a/b/c/ gives a different
4000 * result than passing it /a/b/c ...
4003 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4004 oldstr = oldstr.substr (0, oldstr.length() - 1);
4007 string base = Glib::path_get_dirname (oldstr);
4008 newstr = Glib::build_filename (base, legal_name);
4010 cerr << "for " << oldstr << " new dir = " << newstr << endl;
4012 cerr << "Rename " << oldstr << " => " << newstr << endl;
4013 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4014 cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4015 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4019 /* Reset path in "session dirs" */
4024 /* reset primary SessionDirectory object */
4027 (*_session_dir) = newstr;
4032 /* now rename directory below session_dir/interchange */
4034 string old_interchange_dir;
4035 string new_interchange_dir;
4037 /* use newstr here because we renamed the path
4038 * (folder/directory) that used to be oldstr to newstr above
4041 v.push_back (newstr);
4042 v.push_back (interchange_dir_name);
4043 v.push_back (Glib::path_get_basename (oldstr));
4045 old_interchange_dir = Glib::build_filename (v);
4048 v.push_back (newstr);
4049 v.push_back (interchange_dir_name);
4050 v.push_back (legal_name);
4052 new_interchange_dir = Glib::build_filename (v);
4054 cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
4056 if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
4057 cerr << string_compose (_("renaming %s as %2 failed (%3)"),
4058 old_interchange_dir, new_interchange_dir,
4061 error << string_compose (_("renaming %s as %2 failed (%3)"),
4062 old_interchange_dir, new_interchange_dir,
4071 oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
4072 newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
4074 cerr << "Rename " << oldstr << " => " << newstr << endl;
4076 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4077 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4078 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4084 oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
4086 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
4087 newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
4089 cerr << "Rename " << oldstr << " => " << newstr << endl;
4091 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4092 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4093 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4098 /* remove old name from recent sessions */
4099 remove_recent_sessions (_path);
4102 /* update file source paths */
4104 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
4105 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4107 string p = fs->path ();
4108 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
4110 SourceFactory::setup_peakfile(i->second, true);
4114 _current_snapshot_name = new_name;
4119 /* save state again to get everything just right */
4121 save_state (_current_snapshot_name);
4123 /* add to recent sessions */
4125 store_recent_sessions (new_name, _path);
4131 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
4133 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
4137 if (!tree.read (xmlpath)) {
4145 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
4148 bool found_sr = false;
4149 bool found_data_format = false;
4151 if (get_session_info_from_path (tree, xmlpath)) {
4157 const XMLProperty* prop;
4158 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
4159 sample_rate = atoi (prop->value());
4163 const XMLNodeList& children (tree.root()->children());
4164 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
4165 const XMLNode* child = *c;
4166 if (child->name() == "Config") {
4167 const XMLNodeList& options (child->children());
4168 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
4169 const XMLNode* option = *oc;
4170 const XMLProperty* name = option->property("name");
4176 if (name->value() == "native-file-data-format") {
4177 const XMLProperty* value = option->property ("value");
4179 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
4181 found_data_format = true;
4187 if (found_data_format) {
4192 return !(found_sr && found_data_format); // zero if they are both found
4195 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
4196 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
4199 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
4203 SourcePathMap source_path_map;
4205 boost::shared_ptr<AudioFileSource> afs;
4210 Glib::Threads::Mutex::Lock lm (source_lock);
4212 cerr << " total sources = " << sources.size();
4214 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4215 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4221 if (fs->within_session()) {
4225 if (source_path_map.find (fs->path()) != source_path_map.end()) {
4226 source_path_map[fs->path()].push_back (fs);
4228 SeveralFileSources v;
4230 source_path_map.insert (make_pair (fs->path(), v));
4236 cerr << " fsources = " << total << endl;
4238 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
4240 /* tell caller where we are */
4242 string old_path = i->first;
4244 callback (n, total, old_path);
4246 cerr << old_path << endl;
4250 switch (i->second.front()->type()) {
4251 case DataType::AUDIO:
4252 new_path = new_audio_source_path_for_embedded (old_path);
4255 case DataType::MIDI:
4256 /* XXX not implemented yet */
4260 if (new_path.empty()) {
4264 cerr << "Move " << old_path << " => " << new_path << endl;
4266 if (!copy_file (old_path, new_path)) {
4267 cerr << "failed !\n";
4271 /* make sure we stop looking in the external
4272 dir/folder. Remember, this is an all-or-nothing
4273 operations, it doesn't merge just some files.
4275 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
4277 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
4278 (*f)->set_path (new_path);
4283 save_state ("", false, false);
4289 bool accept_all_files (string const &, void *)
4295 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4297 /* 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.
4302 make_new_media_path (string old_path, string new_session_folder, string new_session_path)
4304 /* typedir is the "midifiles" or "audiofiles" etc. part of the path. */
4306 string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4308 v.push_back (new_session_folder); /* full path */
4309 v.push_back (interchange_dir_name);
4310 v.push_back (new_session_path); /* just one directory/folder */
4311 v.push_back (typedir);
4312 v.push_back (Glib::path_get_basename (old_path));
4314 return Glib::build_filename (v);
4318 Session::save_as (SaveAs& saveas)
4320 vector<string> files;
4321 string current_folder = Glib::path_get_dirname (_path);
4322 string new_folder = legalize_for_path (saveas.new_name);
4323 string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4324 int64_t total_bytes = 0;
4328 int32_t internal_file_cnt = 0;
4330 vector<string> do_not_copy_extensions;
4331 do_not_copy_extensions.push_back (statefile_suffix);
4332 do_not_copy_extensions.push_back (pending_suffix);
4333 do_not_copy_extensions.push_back (backup_suffix);
4334 do_not_copy_extensions.push_back (temp_suffix);
4335 do_not_copy_extensions.push_back (history_suffix);
4337 /* get total size */
4339 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4341 /* need to clear this because
4342 * find_files_matching_filter() is cumulative
4347 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4349 all += files.size();
4351 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4353 g_stat ((*i).c_str(), &gsb);
4354 total_bytes += gsb.st_size;
4358 /* save old values so we can switch back if we are not switching to the new session */
4360 string old_path = _path;
4361 string old_name = _name;
4362 string old_snapshot = _current_snapshot_name;
4363 string old_sd = _session_dir->root_path();
4364 vector<string> old_search_path[DataType::num_types];
4365 string old_config_search_path[DataType::num_types];
4367 old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4368 old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4369 old_config_search_path[DataType::AUDIO] = config.get_audio_search_path ();
4370 old_config_search_path[DataType::MIDI] = config.get_midi_search_path ();
4372 /* switch session directory */
4374 (*_session_dir) = to_dir;
4376 /* create new tree */
4378 if (!_session_dir->create()) {
4379 saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4384 /* copy all relevant files. Find each location in session_dirs,
4385 * and copy files from there to target.
4388 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4390 /* need to clear this because
4391 * find_files_matching_filter() is cumulative
4396 const size_t prefix_len = (*sd).path.size();
4398 /* Work just on the files within this session dir */
4400 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4402 /* add dir separator to protect against collisions with
4403 * track names (e.g. track named "audiofiles" or
4407 static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
4408 static const std::string midifile_dir_string = string (midi_dir_name) + G_DIR_SEPARATOR;
4409 static const std::string analysis_dir_string = analysis_dir() + G_DIR_SEPARATOR;
4411 /* copy all the files. Handling is different for media files
4412 than others because of the *silly* subtree we have below the interchange
4413 folder. That really was a bad idea, but I'm not fixing it as part of
4414 implementing ::save_as().
4417 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4419 std::string from = *i;
4422 string filename = Glib::path_get_basename (from);
4423 std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
4424 if (filename == ".DS_STORE") {
4429 if (from.find (audiofile_dir_string) != string::npos) {
4431 /* audio file: only copy if asked */
4433 if (saveas.include_media && saveas.copy_media) {
4435 string to = make_new_media_path (*i, to_dir, new_folder);
4437 info << "media file copying from " << from << " to " << to << endmsg;
4439 if (!copy_file (from, to)) {
4440 throw Glib::FileError (Glib::FileError::IO_ERROR,
4441 string_compose(_("\ncopying \"%1\" failed !"), from));
4445 /* we found media files inside the session folder */
4447 internal_file_cnt++;
4449 } else if (from.find (midifile_dir_string) != string::npos) {
4451 /* midi file: always copy unless
4452 * creating an empty new session
4455 if (saveas.include_media) {
4457 string to = make_new_media_path (*i, to_dir, new_folder);
4459 info << "media file copying from " << from << " to " << to << endmsg;
4461 if (!copy_file (from, to)) {
4462 throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4466 /* we found media files inside the session folder */
4468 internal_file_cnt++;
4470 } else if (from.find (analysis_dir_string) != string::npos) {
4472 /* make sure analysis dir exists in
4473 * new session folder, but we're not
4474 * copying analysis files here, see
4478 (void) g_mkdir_with_parents (analysis_dir().c_str(), 775);
4483 /* normal non-media file. Don't copy state, history, etc.
4486 bool do_copy = true;
4488 for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
4489 if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
4490 /* end of filename matches extension, do not copy file */
4496 if (!saveas.copy_media && from.find (peakfile_suffix) != string::npos) {
4497 /* don't copy peakfiles if
4498 * we're not copying media
4504 string to = Glib::build_filename (to_dir, from.substr (prefix_len));
4506 info << "attempting to make directory/folder " << to << endmsg;
4508 if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
4509 throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
4512 info << "attempting to copy " << from << " to " << to << endmsg;
4514 if (!copy_file (from, to)) {
4515 throw Glib::FileError (Glib::FileError::IO_ERROR,
4516 string_compose(_("\ncopying \"%1\" failed !"), from));
4521 /* measure file size even if we're not going to copy so that our Progress
4522 signals are correct, since we included these do-not-copy files
4523 in the computation of the total size and file count.
4527 g_stat (from.c_str(), &gsb);
4528 copied += gsb.st_size;
4531 double fraction = (double) copied / total_bytes;
4533 bool keep_going = true;
4535 if (saveas.copy_media) {
4537 /* no need or expectation of this if
4538 * media is not being copied, because
4539 * it will be fast(ish).
4542 /* tell someone "X percent, file M of N"; M is one-based */
4544 boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
4552 throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
4558 /* copy optional folders, if any */
4560 string old = plugins_dir ();
4561 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4562 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4563 copy_files (old, newdir);
4566 old = externals_dir ();
4567 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4568 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4569 copy_files (old, newdir);
4572 old = automation_dir ();
4573 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4574 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4575 copy_files (old, newdir);
4578 if (saveas.include_media) {
4580 if (saveas.copy_media) {
4581 #ifndef PLATFORM_WINDOWS
4582 /* There are problems with analysis files on
4583 * Windows, because they used a colon in their
4584 * names as late as 4.0. Colons are not legal
4585 * under Windows even if NTFS allows them.
4587 * This is a tricky problem to solve so for
4588 * just don't copy these files. They will be
4589 * regenerated as-needed anyway, subject to the
4590 * existing issue that the filenames will be
4591 * rejected by Windows, which is a separate
4592 * problem (though related).
4595 /* only needed if we are copying media, since the
4596 * analysis data refers to media data
4599 old = analysis_dir ();
4600 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4601 string newdir = Glib::build_filename (to_dir, "analysis");
4602 copy_files (old, newdir);
4604 #endif /* PLATFORM_WINDOWS */
4610 _current_snapshot_name = saveas.new_name;
4611 _name = saveas.new_name;
4613 if (saveas.include_media && !saveas.copy_media) {
4615 /* reset search paths of the new session (which we're pretending to be right now) to
4616 include the original session search path, so we can still find all audio.
4619 if (internal_file_cnt) {
4620 for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
4621 ensure_search_path_includes (*s, DataType::AUDIO);
4622 cerr << "be sure to include " << *s << " for audio" << endl;
4625 /* we do not do this for MIDI because we copy
4626 all MIDI files if saveas.include_media is
4632 bool was_dirty = dirty ();
4634 save_state ("", false, false, !saveas.include_media);
4635 save_default_options ();
4637 if (saveas.copy_media && saveas.copy_external) {
4638 if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
4639 throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
4643 saveas.final_session_folder_name = _path;
4645 store_recent_sessions (_name, _path);
4647 if (!saveas.switch_to) {
4649 /* switch back to the way things were */
4653 _current_snapshot_name = old_snapshot;
4655 (*_session_dir) = old_sd;
4661 if (internal_file_cnt) {
4662 /* reset these to their original values */
4663 config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
4664 config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
4669 /* prune session dirs, and update disk space statistics
4674 session_dirs.clear ();
4675 session_dirs.push_back (sp);
4676 refresh_disk_space ();
4678 /* ensure that all existing tracks reset their current capture source paths
4680 reset_write_sources (true, true);
4682 /* the copying above was based on actually discovering files, not just iterating over the sources list.
4683 But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
4686 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4687 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4693 if (fs->within_session()) {
4694 string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
4695 fs->set_path (newpath);
4700 } catch (Glib::FileError& e) {
4702 saveas.failure_message = e.what();
4704 /* recursively remove all the directories */
4706 remove_directory (to_dir);
4714 saveas.failure_message = _("unknown reason");
4716 /* recursively remove all the directories */
4718 remove_directory (to_dir);