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().add_search_path (session_directory().midi_patch_path() );
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 set_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)) {;
985 save_snapshot_name (snapshot_name);
991 Session::load_options (const XMLNode& node)
993 LocaleGuard lg (X_("C"));
994 config.set_variables (node);
999 Session::save_default_options ()
1001 return config.save_state();
1005 Session::get_state()
1011 Session::get_template()
1013 /* if we don't disable rec-enable, diskstreams
1014 will believe they need to store their capture
1015 sources in their state node.
1018 disable_record (false);
1020 return state(false);
1024 Session::state (bool full_state)
1026 XMLNode* node = new XMLNode("Session");
1030 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
1031 node->add_property("version", buf);
1033 /* store configuration settings */
1037 node->add_property ("name", _name);
1038 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
1039 node->add_property ("sample-rate", buf);
1041 if (session_dirs.size() > 1) {
1045 vector<space_and_path>::iterator i = session_dirs.begin();
1046 vector<space_and_path>::iterator next;
1048 ++i; /* skip the first one */
1052 while (i != session_dirs.end()) {
1056 if (next != session_dirs.end()) {
1057 p += G_SEARCHPATH_SEPARATOR;
1066 child = node->add_child ("Path");
1067 child->add_content (p);
1071 /* save the ID counter */
1073 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1074 node->add_property ("id-counter", buf);
1076 /* save the event ID counter */
1078 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1079 node->add_property ("event-counter", buf);
1081 /* various options */
1083 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
1084 if (!midi_port_nodes.empty()) {
1085 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
1086 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
1087 midi_port_stuff->add_child_nocopy (**n);
1089 node->add_child_nocopy (*midi_port_stuff);
1092 node->add_child_nocopy (config.get_variables ());
1094 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1096 child = node->add_child ("Sources");
1099 Glib::Threads::Mutex::Lock sl (source_lock);
1101 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1103 /* Don't save information about non-file Sources, or
1104 * about non-destructive file sources that are empty
1105 * and unused by any regions.
1108 boost::shared_ptr<FileSource> fs;
1110 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1112 if (!fs->destructive()) {
1113 if (fs->empty() && !fs->used()) {
1118 child->add_child_nocopy (siter->second->get_state());
1123 child = node->add_child ("Regions");
1126 Glib::Threads::Mutex::Lock rl (region_lock);
1127 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1128 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1129 boost::shared_ptr<Region> r = i->second;
1130 /* only store regions not attached to playlists */
1131 if (r->playlist() == 0) {
1132 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1133 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1135 child->add_child_nocopy (r->get_state ());
1140 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1142 if (!cassocs.empty()) {
1143 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1145 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1147 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1148 i->first->id().print (buf, sizeof (buf));
1149 can->add_property (X_("copy"), buf);
1150 i->second->id().print (buf, sizeof (buf));
1151 can->add_property (X_("original"), buf);
1152 ca->add_child_nocopy (*can);
1162 node->add_child_nocopy (_locations->get_state());
1165 Locations loc (*this);
1166 // for a template, just create a new Locations, populate it
1167 // with the default start and end, and get the state for that.
1168 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1169 range->set (max_framepos, 0);
1171 XMLNode& locations_state = loc.get_state();
1173 if (ARDOUR::Profile->get_trx() && _locations) {
1174 // For tracks we need stored the Auto Loop Range and all MIDI markers.
1175 for (Locations::LocationList::const_iterator i = _locations->list ().begin (); i != _locations->list ().end (); ++i) {
1176 if ((*i)->is_mark () || (*i)->is_auto_loop ()) {
1177 locations_state.add_child_nocopy ((*i)->get_state ());
1181 node->add_child_nocopy (locations_state);
1184 child = node->add_child ("Bundles");
1186 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1187 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1188 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1190 child->add_child_nocopy (b->get_state());
1195 child = node->add_child ("Routes");
1197 boost::shared_ptr<RouteList> r = routes.reader ();
1199 RoutePublicOrderSorter cmp;
1200 RouteList public_order (*r);
1201 public_order.sort (cmp);
1203 /* the sort should have put control outs first */
1206 assert (_monitor_out == public_order.front());
1209 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1210 if (!(*i)->is_auditioner()) {
1212 child->add_child_nocopy ((*i)->get_state());
1214 child->add_child_nocopy ((*i)->get_template());
1220 playlists->add_state (node, full_state);
1222 child = node->add_child ("RouteGroups");
1223 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1224 child->add_child_nocopy ((*i)->get_state());
1228 XMLNode* gain_child = node->add_child ("Click");
1229 gain_child->add_child_nocopy (_click_io->state (full_state));
1230 gain_child->add_child_nocopy (_click_gain->state (full_state));
1234 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1235 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1239 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1240 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1243 node->add_child_nocopy (_speakers->get_state());
1244 node->add_child_nocopy (_tempo_map->get_state());
1245 node->add_child_nocopy (get_control_protocol_state());
1248 node->add_child_copy (*_extra_xml);
1255 Session::get_control_protocol_state ()
1257 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1258 return cpm.get_state();
1262 Session::set_state (const XMLNode& node, int version)
1266 const XMLProperty* prop;
1269 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1271 if (node.name() != X_("Session")) {
1272 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1276 if ((prop = node.property ("name")) != 0) {
1277 _name = prop->value ();
1280 if ((prop = node.property (X_("sample-rate"))) != 0) {
1282 _nominal_frame_rate = atoi (prop->value());
1284 if (_nominal_frame_rate != _current_frame_rate) {
1285 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1286 if (r.get_value_or (0)) {
1292 setup_raid_path(_session_dir->root_path());
1294 if ((prop = node.property (X_("id-counter"))) != 0) {
1296 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1297 ID::init_counter (x);
1299 /* old sessions used a timebased counter, so fake
1300 the startup ID counter based on a standard
1305 ID::init_counter (now);
1308 if ((prop = node.property (X_("event-counter"))) != 0) {
1309 Evoral::init_event_id_counter (atoi (prop->value()));
1313 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1314 _midi_ports->set_midi_port_states (child->children());
1317 IO::disable_connecting ();
1319 Stateful::save_extra_xml (node);
1321 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1322 load_options (*child);
1323 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1324 load_options (*child);
1326 error << _("Session: XML state has no options section") << endmsg;
1329 if (version >= 3000) {
1330 if ((child = find_named_node (node, "Metadata")) == 0) {
1331 warning << _("Session: XML state has no metadata section") << endmsg;
1332 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1337 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1338 _speakers->set_state (*child, version);
1341 if ((child = find_named_node (node, "Sources")) == 0) {
1342 error << _("Session: XML state has no sources section") << endmsg;
1344 } else if (load_sources (*child)) {
1348 if ((child = find_named_node (node, "TempoMap")) == 0) {
1349 error << _("Session: XML state has no Tempo Map section") << endmsg;
1351 } else if (_tempo_map->set_state (*child, version)) {
1355 if ((child = find_named_node (node, "Locations")) == 0) {
1356 error << _("Session: XML state has no locations section") << endmsg;
1358 } else if (_locations->set_state (*child, version)) {
1362 locations_changed ();
1364 if (_session_range_location) {
1365 AudioFileSource::set_header_position_offset (_session_range_location->start());
1368 if ((child = find_named_node (node, "Regions")) == 0) {
1369 error << _("Session: XML state has no Regions section") << endmsg;
1371 } else if (load_regions (*child)) {
1375 if ((child = find_named_node (node, "Playlists")) == 0) {
1376 error << _("Session: XML state has no playlists section") << endmsg;
1378 } else if (playlists->load (*this, *child)) {
1382 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1384 } else if (playlists->load_unused (*this, *child)) {
1388 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1389 if (load_compounds (*child)) {
1394 if (version >= 3000) {
1395 if ((child = find_named_node (node, "Bundles")) == 0) {
1396 warning << _("Session: XML state has no bundles section") << endmsg;
1399 /* We can't load Bundles yet as they need to be able
1400 to convert from port names to Port objects, which can't happen until
1402 _bundle_xml_node = new XMLNode (*child);
1406 if (version < 3000) {
1407 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1408 error << _("Session: XML state has no diskstreams section") << endmsg;
1410 } else if (load_diskstreams_2X (*child, version)) {
1415 if ((child = find_named_node (node, "Routes")) == 0) {
1416 error << _("Session: XML state has no routes section") << endmsg;
1418 } else if (load_routes (*child, version)) {
1422 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1423 _diskstreams_2X.clear ();
1425 if (version >= 3000) {
1427 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1428 error << _("Session: XML state has no route groups section") << endmsg;
1430 } else if (load_route_groups (*child, version)) {
1434 } else if (version < 3000) {
1436 if ((child = find_named_node (node, "EditGroups")) == 0) {
1437 error << _("Session: XML state has no edit groups section") << endmsg;
1439 } else if (load_route_groups (*child, version)) {
1443 if ((child = find_named_node (node, "MixGroups")) == 0) {
1444 error << _("Session: XML state has no mix groups section") << endmsg;
1446 } else if (load_route_groups (*child, version)) {
1451 if ((child = find_named_node (node, "Click")) == 0) {
1452 warning << _("Session: XML state has no click section") << endmsg;
1453 } else if (_click_io) {
1454 setup_click_state (&node);
1457 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1458 ControlProtocolManager::instance().set_state (*child, version);
1461 update_route_record_state ();
1463 /* here beginneth the second phase ... */
1464 set_snapshot_name (_current_snapshot_name);
1466 StateReady (); /* EMIT SIGNAL */
1479 Session::load_routes (const XMLNode& node, int version)
1482 XMLNodeConstIterator niter;
1483 RouteList new_routes;
1485 nlist = node.children();
1489 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1491 boost::shared_ptr<Route> route;
1492 if (version < 3000) {
1493 route = XMLRouteFactory_2X (**niter, version);
1495 route = XMLRouteFactory (**niter, version);
1499 error << _("Session: cannot create Route from XML description.") << endmsg;
1503 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1505 new_routes.push_back (route);
1508 BootMessage (_("Tracks/busses loaded; Adding to Session"));
1510 add_routes (new_routes, false, false, false);
1512 BootMessage (_("Finished adding tracks/busses"));
1517 boost::shared_ptr<Route>
1518 Session::XMLRouteFactory (const XMLNode& node, int version)
1520 boost::shared_ptr<Route> ret;
1522 if (node.name() != "Route") {
1526 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1528 DataType type = DataType::AUDIO;
1529 const XMLProperty* prop = node.property("default-type");
1532 type = DataType (prop->value());
1535 assert (type != DataType::NIL);
1539 boost::shared_ptr<Track> track;
1541 if (type == DataType::AUDIO) {
1542 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1544 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1547 if (track->init()) {
1551 if (track->set_state (node, version)) {
1555 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1556 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1561 enum Route::Flag flags = Route::Flag(0);
1562 const XMLProperty* prop = node.property("flags");
1564 flags = Route::Flag (string_2_enum (prop->value(), flags));
1567 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1569 if (r->init () == 0 && r->set_state (node, version) == 0) {
1570 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1571 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1580 boost::shared_ptr<Route>
1581 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1583 boost::shared_ptr<Route> ret;
1585 if (node.name() != "Route") {
1589 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1591 ds_prop = node.property (X_("diskstream"));
1594 DataType type = DataType::AUDIO;
1595 const XMLProperty* prop = node.property("default-type");
1598 type = DataType (prop->value());
1601 assert (type != DataType::NIL);
1605 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1606 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1610 if (i == _diskstreams_2X.end()) {
1611 error << _("Could not find diskstream for route") << endmsg;
1612 return boost::shared_ptr<Route> ();
1615 boost::shared_ptr<Track> track;
1617 if (type == DataType::AUDIO) {
1618 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1620 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1623 if (track->init()) {
1627 if (track->set_state (node, version)) {
1631 track->set_diskstream (*i);
1633 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1634 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1639 enum Route::Flag flags = Route::Flag(0);
1640 const XMLProperty* prop = node.property("flags");
1642 flags = Route::Flag (string_2_enum (prop->value(), flags));
1645 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1647 if (r->init () == 0 && r->set_state (node, version) == 0) {
1648 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1649 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1659 Session::load_regions (const XMLNode& node)
1662 XMLNodeConstIterator niter;
1663 boost::shared_ptr<Region> region;
1665 nlist = node.children();
1669 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1670 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1671 error << _("Session: cannot create Region from XML description.");
1672 const XMLProperty *name = (**niter).property("name");
1675 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1686 Session::load_compounds (const XMLNode& node)
1688 XMLNodeList calist = node.children();
1689 XMLNodeConstIterator caiter;
1690 XMLProperty *caprop;
1692 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1693 XMLNode* ca = *caiter;
1697 if ((caprop = ca->property (X_("original"))) == 0) {
1700 orig_id = caprop->value();
1702 if ((caprop = ca->property (X_("copy"))) == 0) {
1705 copy_id = caprop->value();
1707 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1708 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1710 if (!orig || !copy) {
1711 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1717 RegionFactory::add_compound_association (orig, copy);
1724 Session::load_nested_sources (const XMLNode& node)
1727 XMLNodeConstIterator niter;
1729 nlist = node.children();
1731 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1732 if ((*niter)->name() == "Source") {
1734 /* it may already exist, so don't recreate it unnecessarily
1737 XMLProperty* prop = (*niter)->property (X_("id"));
1739 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1743 ID source_id (prop->value());
1745 if (!source_by_id (source_id)) {
1748 SourceFactory::create (*this, **niter, true);
1750 catch (failed_constructor& err) {
1751 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1758 boost::shared_ptr<Region>
1759 Session::XMLRegionFactory (const XMLNode& node, bool full)
1761 const XMLProperty* type = node.property("type");
1765 const XMLNodeList& nlist = node.children();
1767 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1768 XMLNode *child = (*niter);
1769 if (child->name() == "NestedSource") {
1770 load_nested_sources (*child);
1774 if (!type || type->value() == "audio") {
1775 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1776 } else if (type->value() == "midi") {
1777 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1780 } catch (failed_constructor& err) {
1781 return boost::shared_ptr<Region> ();
1784 return boost::shared_ptr<Region> ();
1787 boost::shared_ptr<AudioRegion>
1788 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1790 const XMLProperty* prop;
1791 boost::shared_ptr<Source> source;
1792 boost::shared_ptr<AudioSource> as;
1794 SourceList master_sources;
1795 uint32_t nchans = 1;
1798 if (node.name() != X_("Region")) {
1799 return boost::shared_ptr<AudioRegion>();
1802 if ((prop = node.property (X_("channels"))) != 0) {
1803 nchans = atoi (prop->value().c_str());
1806 if ((prop = node.property ("name")) == 0) {
1807 cerr << "no name for this region\n";
1811 if ((prop = node.property (X_("source-0"))) == 0) {
1812 if ((prop = node.property ("source")) == 0) {
1813 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1814 return boost::shared_ptr<AudioRegion>();
1818 PBD::ID s_id (prop->value());
1820 if ((source = source_by_id (s_id)) == 0) {
1821 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1822 return boost::shared_ptr<AudioRegion>();
1825 as = boost::dynamic_pointer_cast<AudioSource>(source);
1827 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1828 return boost::shared_ptr<AudioRegion>();
1831 sources.push_back (as);
1833 /* pickup other channels */
1835 for (uint32_t n=1; n < nchans; ++n) {
1836 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1837 if ((prop = node.property (buf)) != 0) {
1839 PBD::ID id2 (prop->value());
1841 if ((source = source_by_id (id2)) == 0) {
1842 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1843 return boost::shared_ptr<AudioRegion>();
1846 as = boost::dynamic_pointer_cast<AudioSource>(source);
1848 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1849 return boost::shared_ptr<AudioRegion>();
1851 sources.push_back (as);
1855 for (uint32_t n = 0; n < nchans; ++n) {
1856 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1857 if ((prop = node.property (buf)) != 0) {
1859 PBD::ID id2 (prop->value());
1861 if ((source = source_by_id (id2)) == 0) {
1862 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1863 return boost::shared_ptr<AudioRegion>();
1866 as = boost::dynamic_pointer_cast<AudioSource>(source);
1868 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1869 return boost::shared_ptr<AudioRegion>();
1871 master_sources.push_back (as);
1876 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1878 /* a final detail: this is the one and only place that we know how long missing files are */
1880 if (region->whole_file()) {
1881 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1882 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1884 sfp->set_length (region->length());
1889 if (!master_sources.empty()) {
1890 if (master_sources.size() != nchans) {
1891 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1893 region->set_master_sources (master_sources);
1901 catch (failed_constructor& err) {
1902 return boost::shared_ptr<AudioRegion>();
1906 boost::shared_ptr<MidiRegion>
1907 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1909 const XMLProperty* prop;
1910 boost::shared_ptr<Source> source;
1911 boost::shared_ptr<MidiSource> ms;
1914 if (node.name() != X_("Region")) {
1915 return boost::shared_ptr<MidiRegion>();
1918 if ((prop = node.property ("name")) == 0) {
1919 cerr << "no name for this region\n";
1923 if ((prop = node.property (X_("source-0"))) == 0) {
1924 if ((prop = node.property ("source")) == 0) {
1925 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1926 return boost::shared_ptr<MidiRegion>();
1930 PBD::ID s_id (prop->value());
1932 if ((source = source_by_id (s_id)) == 0) {
1933 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1934 return boost::shared_ptr<MidiRegion>();
1937 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1939 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1940 return boost::shared_ptr<MidiRegion>();
1943 sources.push_back (ms);
1946 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1947 /* a final detail: this is the one and only place that we know how long missing files are */
1949 if (region->whole_file()) {
1950 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1951 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1953 sfp->set_length (region->length());
1961 catch (failed_constructor& err) {
1962 return boost::shared_ptr<MidiRegion>();
1967 Session::get_sources_as_xml ()
1970 XMLNode* node = new XMLNode (X_("Sources"));
1971 Glib::Threads::Mutex::Lock lm (source_lock);
1973 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1974 node->add_child_nocopy (i->second->get_state());
1981 Session::reset_write_sources (bool mark_write_complete, bool force)
1983 boost::shared_ptr<RouteList> rl = routes.reader();
1984 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1985 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1987 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
1988 tr->reset_write_sources(mark_write_complete, force);
1989 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
1995 Session::load_sources (const XMLNode& node)
1998 XMLNodeConstIterator niter;
1999 boost::shared_ptr<Source> source; /* don't need this but it stops some
2000 * versions of gcc complaining about
2001 * discarded return values.
2004 nlist = node.children();
2008 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2011 if ((source = XMLSourceFactory (**niter)) == 0) {
2012 error << _("Session: cannot create Source from XML description.") << endmsg;
2015 } catch (MissingSource& err) {
2019 if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
2020 error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
2021 PROGRAM_NAME) << endmsg;
2025 if (!no_questions_about_missing_files) {
2026 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
2031 switch (user_choice) {
2033 /* user added a new search location, so try again */
2038 /* user asked to quit the entire session load
2043 no_questions_about_missing_files = true;
2047 no_questions_about_missing_files = true;
2054 case DataType::AUDIO:
2055 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
2058 case DataType::MIDI:
2059 /* The MIDI file is actually missing so
2060 * just create a new one in the same
2061 * location. Do not announce its
2065 if (!Glib::path_is_absolute (err.path)) {
2066 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
2068 /* this should be an unrecoverable error: we would be creating a MIDI file outside
2073 /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
2074 source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
2075 /* reset ID to match the missing one */
2076 source->set_id (**niter);
2077 /* Now we can announce it */
2078 SourceFactory::SourceCreated (source);
2089 boost::shared_ptr<Source>
2090 Session::XMLSourceFactory (const XMLNode& node)
2092 if (node.name() != "Source") {
2093 return boost::shared_ptr<Source>();
2097 /* note: do peak building in another thread when loading session state */
2098 return SourceFactory::create (*this, node, true);
2101 catch (failed_constructor& err) {
2102 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
2103 return boost::shared_ptr<Source>();
2108 Session::save_template (string template_name, bool replace_existing)
2110 if ((_state_of_the_state & CannotSave) || template_name.empty ()) {
2114 bool absolute_path = Glib::path_is_absolute (template_name);
2116 /* directory to put the template in */
2117 std::string template_dir_path;
2119 if (!absolute_path) {
2120 std::string user_template_dir(user_template_directory());
2122 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2123 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2124 user_template_dir, g_strerror (errno)) << endmsg;
2128 template_dir_path = Glib::build_filename (user_template_dir, template_name);
2130 template_dir_path = template_name;
2133 if (!ARDOUR::Profile->get_trx()) {
2134 if (!replace_existing && Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2135 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2136 template_dir_path) << endmsg;
2140 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2141 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2142 template_dir_path, g_strerror (errno)) << endmsg;
2148 std::string template_file_path;
2150 if (ARDOUR::Profile->get_trx()) {
2151 template_file_path = template_name;
2153 if (absolute_path) {
2154 template_file_path = Glib::build_filename (template_dir_path, Glib::path_get_basename (template_dir_path) + template_suffix);
2156 template_file_path = Glib::build_filename (template_dir_path, template_name + template_suffix);
2160 SessionSaveUnderway (); /* EMIT SIGNAL */
2164 tree.set_root (&get_template());
2165 if (!tree.write (template_file_path)) {
2166 error << _("template not saved") << endmsg;
2170 if (!ARDOUR::Profile->get_trx()) {
2171 /* copy plugin state directory */
2173 std::string template_plugin_state_path (Glib::build_filename (template_dir_path, X_("plugins")));
2175 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
2176 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
2177 template_plugin_state_path, g_strerror (errno)) << endmsg;
2180 copy_files (plugins_dir(), template_plugin_state_path);
2183 store_recent_templates (template_file_path);
2189 Session::refresh_disk_space ()
2191 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2193 Glib::Threads::Mutex::Lock lm (space_lock);
2195 /* get freespace on every FS that is part of the session path */
2197 _total_free_4k_blocks = 0;
2198 _total_free_4k_blocks_uncertain = false;
2200 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2202 struct statfs statfsbuf;
2203 statfs (i->path.c_str(), &statfsbuf);
2205 double const scale = statfsbuf.f_bsize / 4096.0;
2207 /* See if this filesystem is read-only */
2208 struct statvfs statvfsbuf;
2209 statvfs (i->path.c_str(), &statvfsbuf);
2211 /* f_bavail can be 0 if it is undefined for whatever
2212 filesystem we are looking at; Samba shares mounted
2213 via GVFS are an example of this.
2215 if (statfsbuf.f_bavail == 0) {
2216 /* block count unknown */
2218 i->blocks_unknown = true;
2219 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2220 /* read-only filesystem */
2222 i->blocks_unknown = false;
2224 /* read/write filesystem with known space */
2225 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2226 i->blocks_unknown = false;
2229 _total_free_4k_blocks += i->blocks;
2230 if (i->blocks_unknown) {
2231 _total_free_4k_blocks_uncertain = true;
2234 #elif defined PLATFORM_WINDOWS
2235 vector<string> scanned_volumes;
2236 vector<string>::iterator j;
2237 vector<space_and_path>::iterator i;
2238 DWORD nSectorsPerCluster, nBytesPerSector,
2239 nFreeClusters, nTotalClusters;
2243 _total_free_4k_blocks = 0;
2245 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2246 strncpy (disk_drive, (*i).path.c_str(), 3);
2250 volume_found = false;
2251 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2253 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2254 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2255 i->blocks = (uint32_t)(nFreeBytes / 4096);
2257 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2258 if (0 == j->compare(disk_drive)) {
2259 volume_found = true;
2264 if (!volume_found) {
2265 scanned_volumes.push_back(disk_drive);
2266 _total_free_4k_blocks += i->blocks;
2271 if (0 == _total_free_4k_blocks) {
2272 strncpy (disk_drive, path().c_str(), 3);
2275 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2277 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2278 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2279 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2286 Session::get_best_session_directory_for_new_audio ()
2288 vector<space_and_path>::iterator i;
2289 string result = _session_dir->root_path();
2291 /* handle common case without system calls */
2293 if (session_dirs.size() == 1) {
2297 /* OK, here's the algorithm we're following here:
2299 We want to select which directory to use for
2300 the next file source to be created. Ideally,
2301 we'd like to use a round-robin process so as to
2302 get maximum performance benefits from splitting
2303 the files across multiple disks.
2305 However, in situations without much diskspace, an
2306 RR approach may end up filling up a filesystem
2307 with new files while others still have space.
2308 Its therefore important to pay some attention to
2309 the freespace in the filesystem holding each
2310 directory as well. However, if we did that by
2311 itself, we'd keep creating new files in the file
2312 system with the most space until it was as full
2313 as all others, thus negating any performance
2314 benefits of this RAID-1 like approach.
2316 So, we use a user-configurable space threshold. If
2317 there are at least 2 filesystems with more than this
2318 much space available, we use RR selection between them.
2319 If not, then we pick the filesystem with the most space.
2321 This gets a good balance between the two
2325 refresh_disk_space ();
2327 int free_enough = 0;
2329 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2330 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2335 if (free_enough >= 2) {
2336 /* use RR selection process, ensuring that the one
2340 i = last_rr_session_dir;
2343 if (++i == session_dirs.end()) {
2344 i = session_dirs.begin();
2347 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2348 SessionDirectory sdir(i->path);
2349 if (sdir.create ()) {
2351 last_rr_session_dir = i;
2356 } while (i != last_rr_session_dir);
2360 /* pick FS with the most freespace (and that
2361 seems to actually work ...)
2364 vector<space_and_path> sorted;
2365 space_and_path_ascending_cmp cmp;
2367 sorted = session_dirs;
2368 sort (sorted.begin(), sorted.end(), cmp);
2370 for (i = sorted.begin(); i != sorted.end(); ++i) {
2371 SessionDirectory sdir(i->path);
2372 if (sdir.create ()) {
2374 last_rr_session_dir = i;
2384 Session::automation_dir () const
2386 return Glib::build_filename (_path, automation_dir_name);
2390 Session::analysis_dir () const
2392 return Glib::build_filename (_path, analysis_dir_name);
2396 Session::plugins_dir () const
2398 return Glib::build_filename (_path, plugins_dir_name);
2402 Session::externals_dir () const
2404 return Glib::build_filename (_path, externals_dir_name);
2408 Session::load_bundles (XMLNode const & node)
2410 XMLNodeList nlist = node.children();
2411 XMLNodeConstIterator niter;
2415 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2416 if ((*niter)->name() == "InputBundle") {
2417 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2418 } else if ((*niter)->name() == "OutputBundle") {
2419 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2421 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2430 Session::load_route_groups (const XMLNode& node, int version)
2432 XMLNodeList nlist = node.children();
2433 XMLNodeConstIterator niter;
2437 if (version >= 3000) {
2439 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2440 if ((*niter)->name() == "RouteGroup") {
2441 RouteGroup* rg = new RouteGroup (*this, "");
2442 add_route_group (rg);
2443 rg->set_state (**niter, version);
2447 } else if (version < 3000) {
2449 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2450 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2451 RouteGroup* rg = new RouteGroup (*this, "");
2452 add_route_group (rg);
2453 rg->set_state (**niter, version);
2462 state_file_filter (const string &str, void* /*arg*/)
2464 return (str.length() > strlen(statefile_suffix) &&
2465 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2469 remove_end(string state)
2471 string statename(state);
2473 string::size_type start,end;
2474 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2475 statename = statename.substr (start+1);
2478 if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2479 end = statename.length();
2482 return string(statename.substr (0, end));
2486 Session::possible_states (string path)
2488 vector<string> states;
2489 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2491 transform(states.begin(), states.end(), states.begin(), remove_end);
2493 sort (states.begin(), states.end());
2499 Session::possible_states () const
2501 return possible_states(_path);
2505 Session::add_route_group (RouteGroup* g)
2507 _route_groups.push_back (g);
2508 route_group_added (g); /* EMIT SIGNAL */
2510 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2511 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2512 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2518 Session::remove_route_group (RouteGroup& rg)
2520 list<RouteGroup*>::iterator i;
2522 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2523 _route_groups.erase (i);
2526 route_group_removed (); /* EMIT SIGNAL */
2530 /** Set a new order for our route groups, without adding or removing any.
2531 * @param groups Route group list in the new order.
2534 Session::reorder_route_groups (list<RouteGroup*> groups)
2536 _route_groups = groups;
2538 route_groups_reordered (); /* EMIT SIGNAL */
2544 Session::route_group_by_name (string name)
2546 list<RouteGroup *>::iterator i;
2548 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2549 if ((*i)->name() == name) {
2557 Session::all_route_group() const
2559 return *_all_route_group;
2563 Session::add_commands (vector<Command*> const & cmds)
2565 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2571 Session::add_command (Command* const cmd)
2573 assert (_current_trans);
2574 DEBUG_UNDO_HISTORY (
2575 string_compose ("Current Undo Transaction %1, adding command: %2",
2576 _current_trans->name (),
2578 _current_trans->add_command (cmd);
2581 Session::begin_reversible_command (const string& name)
2583 begin_reversible_command (g_quark_from_string (name.c_str ()));
2586 /** Begin a reversible command using a GQuark to identify it.
2587 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2588 * but there must be as many begin...()s as there are commit...()s.
2591 Session::begin_reversible_command (GQuark q)
2593 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2594 to hold all the commands that are committed. This keeps the order of
2595 commands correct in the history.
2598 if (_current_trans == 0) {
2599 DEBUG_UNDO_HISTORY (string_compose (
2600 "Begin Reversible Command, new transaction: %1", g_quark_to_string (q)));
2602 /* start a new transaction */
2603 assert (_current_trans_quarks.empty ());
2604 _current_trans = new UndoTransaction();
2605 _current_trans->set_name (g_quark_to_string (q));
2607 DEBUG_UNDO_HISTORY (
2608 string_compose ("Begin Reversible Command, current transaction: %1",
2609 _current_trans->name ()));
2612 _current_trans_quarks.push_front (q);
2616 Session::abort_reversible_command ()
2618 if (_current_trans != 0) {
2619 DEBUG_UNDO_HISTORY (
2620 string_compose ("Abort Reversible Command: %1", _current_trans->name ()));
2621 _current_trans->clear();
2622 delete _current_trans;
2624 _current_trans_quarks.clear();
2629 Session::commit_reversible_command (Command *cmd)
2631 assert (_current_trans);
2632 assert (!_current_trans_quarks.empty ());
2637 DEBUG_UNDO_HISTORY (
2638 string_compose ("Current Undo Transaction %1, adding command: %2",
2639 _current_trans->name (),
2641 _current_trans->add_command (cmd);
2644 DEBUG_UNDO_HISTORY (
2645 string_compose ("Commit Reversible Command, current transaction: %1",
2646 _current_trans->name ()));
2648 _current_trans_quarks.pop_front ();
2650 if (!_current_trans_quarks.empty ()) {
2651 DEBUG_UNDO_HISTORY (
2652 string_compose ("Commit Reversible Command, transaction is not "
2653 "top-level, current transaction: %1",
2654 _current_trans->name ()));
2655 /* the transaction we're committing is not the top-level one */
2659 if (_current_trans->empty()) {
2660 /* no commands were added to the transaction, so just get rid of it */
2661 DEBUG_UNDO_HISTORY (
2662 string_compose ("Commit Reversible Command, No commands were "
2663 "added to current transaction: %1",
2664 _current_trans->name ()));
2665 delete _current_trans;
2670 gettimeofday (&now, 0);
2671 _current_trans->set_timestamp (now);
2673 _history.add (_current_trans);
2678 accept_all_audio_files (const string& path, void* /*arg*/)
2680 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2684 if (!AudioFileSource::safe_audio_file_extension (path)) {
2692 accept_all_midi_files (const string& path, void* /*arg*/)
2694 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2698 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2699 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2700 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2704 accept_all_state_files (const string& path, void* /*arg*/)
2706 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2710 std::string const statefile_ext (statefile_suffix);
2711 if (path.length() >= statefile_ext.length()) {
2712 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2719 Session::find_all_sources (string path, set<string>& result)
2724 if (!tree.read (path)) {
2728 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2733 XMLNodeConstIterator niter;
2735 nlist = node->children();
2739 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2743 if ((prop = (*niter)->property (X_("type"))) == 0) {
2747 DataType type (prop->value());
2749 if ((prop = (*niter)->property (X_("name"))) == 0) {
2753 if (Glib::path_is_absolute (prop->value())) {
2754 /* external file, ignore */
2762 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2763 result.insert (found_path);
2771 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2773 vector<string> state_files;
2775 string this_snapshot_path;
2781 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2782 ripped = ripped.substr (0, ripped.length() - 1);
2785 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2787 if (state_files.empty()) {
2792 this_snapshot_path = _path;
2793 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2794 this_snapshot_path += statefile_suffix;
2796 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2798 if (exclude_this_snapshot && *i == this_snapshot_path) {
2802 if (find_all_sources (*i, result) < 0) {
2810 struct RegionCounter {
2811 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2812 AudioSourceList::iterator iter;
2813 boost::shared_ptr<Region> region;
2816 RegionCounter() : count (0) {}
2820 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2822 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2823 return r.get_value_or (1);
2827 Session::cleanup_regions ()
2829 bool removed = false;
2830 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2832 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2834 uint32_t used = playlists->region_use_count (i->second);
2836 if (used == 0 && !i->second->automatic ()) {
2837 boost::weak_ptr<Region> w = i->second;
2840 RegionFactory::map_remove (w);
2847 // re-check to remove parent references of compound regions
2848 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2849 if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2853 assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2854 if (0 == playlists->region_use_count (i->second)) {
2855 boost::weak_ptr<Region> w = i->second;
2857 RegionFactory::map_remove (w);
2864 /* dump the history list */
2871 Session::can_cleanup_peakfiles () const
2873 if (deletion_in_progress()) {
2876 if (!_writable || (_state_of_the_state & CannotSave)) {
2877 warning << _("Cannot cleanup peak-files for read-only session.") << endmsg;
2880 if (record_status() == Recording) {
2881 error << _("Cannot cleanup peak-files while recording") << endmsg;
2888 Session::cleanup_peakfiles ()
2890 Glib::Threads::Mutex::Lock lm (peak_cleanup_lock, Glib::Threads::TRY_LOCK);
2895 assert (can_cleanup_peakfiles ());
2896 assert (!peaks_cleanup_in_progres());
2898 _state_of_the_state = StateOfTheState (_state_of_the_state | PeakCleanup);
2900 int timeout = 5000; // 5 seconds
2901 while (!SourceFactory::files_with_peaks.empty()) {
2902 Glib::usleep (1000);
2903 if (--timeout < 0) {
2904 warning << _("Timeout waiting for peak-file creation to terminate before cleanup, please try again later.") << endmsg;
2905 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
2910 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2911 boost::shared_ptr<AudioSource> as;
2912 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
2913 as->close_peakfile();
2917 PBD::clear_directory (session_directory().peak_path());
2919 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
2921 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2922 boost::shared_ptr<AudioSource> as;
2923 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
2924 SourceFactory::setup_peakfile(as, true);
2931 Session::cleanup_sources (CleanupReport& rep)
2933 // FIXME: needs adaptation to midi
2935 vector<boost::shared_ptr<Source> > dead_sources;
2938 vector<string> candidates;
2939 vector<string> unused;
2940 set<string> all_sources;
2949 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2951 /* this is mostly for windows which doesn't allow file
2952 * renaming if the file is in use. But we don't special
2953 * case it because we need to know if this causes
2954 * problems, and the easiest way to notice that is to
2955 * keep it in place for all platforms.
2958 request_stop (false);
2960 _butler->wait_until_finished ();
2962 /* consider deleting all unused playlists */
2964 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2969 /* sync the "all regions" property of each playlist with its current state
2972 playlists->sync_all_regions_with_regions ();
2974 /* find all un-used sources */
2979 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2981 SourceMap::iterator tmp;
2986 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2990 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2991 dead_sources.push_back (i->second);
2992 i->second->drop_references ();
2998 /* build a list of all the possible audio directories for the session */
3000 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3001 SessionDirectory sdir ((*i).path);
3002 asp += sdir.sound_path();
3004 audio_path += asp.to_string();
3007 /* build a list of all the possible midi directories for the session */
3009 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3010 SessionDirectory sdir ((*i).path);
3011 msp += sdir.midi_path();
3013 midi_path += msp.to_string();
3015 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
3016 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
3018 /* find all sources, but don't use this snapshot because the
3019 state file on disk still references sources we may have already
3023 find_all_sources_across_snapshots (all_sources, true);
3025 /* add our current source list
3028 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3029 boost::shared_ptr<FileSource> fs;
3030 SourceMap::iterator tmp = i;
3033 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
3035 /* this is mostly for windows which doesn't allow file
3036 * renaming if the file is in use. But we don't special
3037 * case it because we need to know if this causes
3038 * problems, and the easiest way to notice that is to
3039 * keep it in place for all platforms.
3044 if (!fs->is_stub()) {
3046 if (playlists->source_use_count (fs) != 0) {
3047 all_sources.insert (fs->path());
3050 /* we might not remove this source from disk, because it may be used
3051 by other snapshots, but its not being used in this version
3052 so lets get rid of it now, along with any representative regions
3056 RegionFactory::remove_regions_using_source (i->second);
3058 // also remove source from all_sources
3060 for (set<string>::iterator j = all_sources.begin(); j != all_sources.end(); ++j) {
3061 spath = Glib::path_get_basename (*j);
3062 if (spath == i->second->name()) {
3063 all_sources.erase (j);
3076 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
3081 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
3083 tmppath1 = canonical_path (spath);
3084 tmppath2 = canonical_path ((*i));
3086 if (tmppath1 == tmppath2) {
3093 unused.push_back (spath);
3097 /* now try to move all unused files into the "dead" directory(ies) */
3099 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
3104 /* don't move the file across filesystems, just
3105 stick it in the `dead_dir_name' directory
3106 on whichever filesystem it was already on.
3109 if ((*x).find ("/sounds/") != string::npos) {
3111 /* old school, go up 1 level */
3113 newpath = Glib::path_get_dirname (*x); // "sounds"
3114 newpath = Glib::path_get_dirname (newpath); // "session-name"
3118 /* new school, go up 4 levels */
3120 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
3121 newpath = Glib::path_get_dirname (newpath); // "session-name"
3122 newpath = Glib::path_get_dirname (newpath); // "interchange"
3123 newpath = Glib::path_get_dirname (newpath); // "session-dir"
3126 newpath = Glib::build_filename (newpath, dead_dir_name);
3128 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
3129 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
3133 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
3135 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
3137 /* the new path already exists, try versioning */
3139 char buf[PATH_MAX+1];
3143 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3146 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
3147 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3151 if (version == 999) {
3152 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3156 newpath = newpath_v;
3161 /* it doesn't exist, or we can't read it or something */
3165 g_stat ((*x).c_str(), &statbuf);
3167 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3168 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
3169 (*x), newpath, strerror (errno))
3174 /* see if there an easy to find peakfile for this file, and remove it.
3177 string base = Glib::path_get_basename (*x);
3178 base += "%A"; /* this is what we add for the channel suffix of all native files,
3179 or for the first channel of embedded files. it will miss
3180 some peakfiles for other channels
3182 string peakpath = construct_peak_filepath (base);
3184 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
3185 if (::g_unlink (peakpath.c_str()) != 0) {
3186 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3187 peakpath, _path, strerror (errno))
3189 /* try to back out */
3190 ::rename (newpath.c_str(), _path.c_str());
3195 rep.paths.push_back (*x);
3196 rep.space += statbuf.st_size;
3199 /* dump the history list */
3203 /* save state so we don't end up a session file
3204 referring to non-existent sources.
3211 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3217 Session::cleanup_trash_sources (CleanupReport& rep)
3219 // FIXME: needs adaptation for MIDI
3221 vector<space_and_path>::iterator i;
3227 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3229 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
3231 clear_directory (dead_dir, &rep.space, &rep.paths);
3238 Session::set_dirty ()
3240 /* never mark session dirty during loading */
3242 if (_state_of_the_state & Loading) {
3246 bool was_dirty = dirty();
3248 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3252 DirtyChanged(); /* EMIT SIGNAL */
3258 Session::set_clean ()
3260 bool was_dirty = dirty();
3262 _state_of_the_state = Clean;
3266 DirtyChanged(); /* EMIT SIGNAL */
3271 Session::set_deletion_in_progress ()
3273 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3277 Session::clear_deletion_in_progress ()
3279 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3283 Session::add_controllable (boost::shared_ptr<Controllable> c)
3285 /* this adds a controllable to the list managed by the Session.
3286 this is a subset of those managed by the Controllable class
3287 itself, and represents the only ones whose state will be saved
3288 as part of the session.
3291 Glib::Threads::Mutex::Lock lm (controllables_lock);
3292 controllables.insert (c);
3295 struct null_deleter { void operator()(void const *) const {} };
3298 Session::remove_controllable (Controllable* c)
3300 if (_state_of_the_state & Deletion) {
3304 Glib::Threads::Mutex::Lock lm (controllables_lock);
3306 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3308 if (x != controllables.end()) {
3309 controllables.erase (x);
3313 boost::shared_ptr<Controllable>
3314 Session::controllable_by_id (const PBD::ID& id)
3316 Glib::Threads::Mutex::Lock lm (controllables_lock);
3318 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3319 if ((*i)->id() == id) {
3324 return boost::shared_ptr<Controllable>();
3327 boost::shared_ptr<Controllable>
3328 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3330 boost::shared_ptr<Controllable> c;
3331 boost::shared_ptr<Route> r;
3333 switch (desc.top_level_type()) {
3334 case ControllableDescriptor::NamedRoute:
3336 std::string str = desc.top_level_name();
3337 if (str == "Master" || str == "master") {
3339 } else if (str == "control" || str == "listen") {
3342 r = route_by_name (desc.top_level_name());
3347 case ControllableDescriptor::RemoteControlID:
3348 r = route_by_remote_id (desc.rid());
3356 switch (desc.subtype()) {
3357 case ControllableDescriptor::Gain:
3358 c = r->gain_control ();
3361 case ControllableDescriptor::Trim:
3362 c = r->trim()->gain_control ();
3365 case ControllableDescriptor::Solo:
3366 c = r->solo_control();
3369 case ControllableDescriptor::Mute:
3370 c = r->mute_control();
3373 case ControllableDescriptor::Recenable:
3375 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3378 c = t->rec_enable_control ();
3383 case ControllableDescriptor::PanDirection:
3385 c = r->pannable()->pan_azimuth_control;
3389 case ControllableDescriptor::PanWidth:
3391 c = r->pannable()->pan_width_control;
3395 case ControllableDescriptor::PanElevation:
3397 c = r->pannable()->pan_elevation_control;
3401 case ControllableDescriptor::Balance:
3402 /* XXX simple pan control */
3405 case ControllableDescriptor::PluginParameter:
3407 uint32_t plugin = desc.target (0);
3408 uint32_t parameter_index = desc.target (1);
3410 /* revert to zero based counting */
3416 if (parameter_index > 0) {
3420 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3423 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3424 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3429 case ControllableDescriptor::SendGain:
3431 uint32_t send = desc.target (0);
3433 /* revert to zero-based counting */
3439 boost::shared_ptr<Processor> p = r->nth_send (send);
3442 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3443 boost::shared_ptr<Amp> a = s->amp();
3446 c = s->amp()->gain_control();
3453 /* relax and return a null pointer */
3461 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3464 Stateful::add_instant_xml (node, _path);
3467 if (write_to_config) {
3468 Config->add_instant_xml (node);
3473 Session::instant_xml (const string& node_name)
3475 return Stateful::instant_xml (node_name, _path);
3479 Session::save_history (string snapshot_name)
3487 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3488 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3492 if (snapshot_name.empty()) {
3493 snapshot_name = _current_snapshot_name;
3496 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3497 const string backup_filename = history_filename + backup_suffix;
3498 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3499 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3501 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3502 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3503 error << _("could not backup old history file, current history not saved") << endmsg;
3508 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3510 if (!tree.write (xml_path))
3512 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3514 if (g_remove (xml_path.c_str()) != 0) {
3515 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3516 xml_path, g_strerror (errno)) << endmsg;
3518 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3519 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3520 backup_path, g_strerror (errno)) << endmsg;
3530 Session::restore_history (string snapshot_name)
3534 if (snapshot_name.empty()) {
3535 snapshot_name = _current_snapshot_name;
3538 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3539 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3541 info << "Loading history from " << xml_path << endmsg;
3543 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3544 info << string_compose (_("%1: no history file \"%2\" for this session."),
3545 _name, xml_path) << endmsg;
3549 if (!tree.read (xml_path)) {
3550 error << string_compose (_("Could not understand session history file \"%1\""),
3551 xml_path) << endmsg;
3558 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3561 UndoTransaction* ut = new UndoTransaction ();
3564 ut->set_name(t->property("name")->value());
3565 stringstream ss(t->property("tv-sec")->value());
3567 ss.str(t->property("tv-usec")->value());
3569 ut->set_timestamp(tv);
3571 for (XMLNodeConstIterator child_it = t->children().begin();
3572 child_it != t->children().end(); child_it++)
3574 XMLNode *n = *child_it;
3577 if (n->name() == "MementoCommand" ||
3578 n->name() == "MementoUndoCommand" ||
3579 n->name() == "MementoRedoCommand") {
3581 if ((c = memento_command_factory(n))) {
3585 } else if (n->name() == "NoteDiffCommand") {
3586 PBD::ID id (n->property("midi-source")->value());
3587 boost::shared_ptr<MidiSource> midi_source =
3588 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3590 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3592 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3595 } else if (n->name() == "SysExDiffCommand") {
3597 PBD::ID id (n->property("midi-source")->value());
3598 boost::shared_ptr<MidiSource> midi_source =
3599 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3601 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3603 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3606 } else if (n->name() == "PatchChangeDiffCommand") {
3608 PBD::ID id (n->property("midi-source")->value());
3609 boost::shared_ptr<MidiSource> midi_source =
3610 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3612 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3614 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3617 } else if (n->name() == "StatefulDiffCommand") {
3618 if ((c = stateful_diff_command_factory (n))) {
3619 ut->add_command (c);
3622 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3633 Session::config_changed (std::string p, bool ours)
3639 if (p == "seamless-loop") {
3641 } else if (p == "rf-speed") {
3643 } else if (p == "auto-loop") {
3645 } else if (p == "auto-input") {
3647 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3648 /* auto-input only makes a difference if we're rolling */
3649 set_track_monitor_input_status (!config.get_auto_input());
3652 } else if (p == "punch-in") {
3656 if ((location = _locations->auto_punch_location()) != 0) {
3658 if (config.get_punch_in ()) {
3659 replace_event (SessionEvent::PunchIn, location->start());
3661 remove_event (location->start(), SessionEvent::PunchIn);
3665 } else if (p == "punch-out") {
3669 if ((location = _locations->auto_punch_location()) != 0) {
3671 if (config.get_punch_out()) {
3672 replace_event (SessionEvent::PunchOut, location->end());
3674 clear_events (SessionEvent::PunchOut);
3678 } else if (p == "edit-mode") {
3680 Glib::Threads::Mutex::Lock lm (playlists->lock);
3682 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3683 (*i)->set_edit_mode (Config->get_edit_mode ());
3686 } else if (p == "use-video-sync") {
3688 waiting_for_sync_offset = config.get_use_video_sync();
3690 } else if (p == "mmc-control") {
3692 //poke_midi_thread ();
3694 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3696 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3698 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3700 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3702 } else if (p == "midi-control") {
3704 //poke_midi_thread ();
3706 } else if (p == "raid-path") {
3708 setup_raid_path (config.get_raid_path());
3710 } else if (p == "timecode-format") {
3714 } else if (p == "video-pullup") {
3718 } else if (p == "seamless-loop") {
3720 if (play_loop && transport_rolling()) {
3721 // to reset diskstreams etc
3722 request_play_loop (true);
3725 } else if (p == "rf-speed") {
3727 cumulative_rf_motion = 0;
3730 } else if (p == "click-sound") {
3732 setup_click_sounds (1);
3734 } else if (p == "click-emphasis-sound") {
3736 setup_click_sounds (-1);
3738 } else if (p == "clicking") {
3740 if (Config->get_clicking()) {
3741 if (_click_io && click_data) { // don't require emphasis data
3748 } else if (p == "click-gain") {
3751 _click_gain->set_gain (Config->get_click_gain(), this);
3754 } else if (p == "send-mtc") {
3756 if (Config->get_send_mtc ()) {
3757 /* mark us ready to send */
3758 next_quarter_frame_to_send = 0;
3761 } else if (p == "send-mmc") {
3763 _mmc->enable_send (Config->get_send_mmc ());
3765 } else if (p == "midi-feedback") {
3767 session_midi_feedback = Config->get_midi_feedback();
3769 } else if (p == "jack-time-master") {
3771 engine().reset_timebase ();
3773 } else if (p == "native-file-header-format") {
3775 if (!first_file_header_format_reset) {
3776 reset_native_file_format ();
3779 first_file_header_format_reset = false;
3781 } else if (p == "native-file-data-format") {
3783 if (!first_file_data_format_reset) {
3784 reset_native_file_format ();
3787 first_file_data_format_reset = false;
3789 } else if (p == "external-sync") {
3790 if (!config.get_external_sync()) {
3791 drop_sync_source ();
3793 switch_to_sync_source (Config->get_sync_source());
3795 } else if (p == "denormal-model") {
3797 } else if (p == "history-depth") {
3798 set_history_depth (Config->get_history_depth());
3799 } else if (p == "remote-model") {
3800 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3803 } else if (p == "initial-program-change") {
3805 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3808 buf[0] = MIDI::program; // channel zero by default
3809 buf[1] = (Config->get_initial_program_change() & 0x7f);
3811 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3813 } else if (p == "solo-mute-override") {
3814 // catch_up_on_solo_mute_override ();
3815 } else if (p == "listen-position" || p == "pfl-position") {
3816 listen_position_changed ();
3817 } else if (p == "solo-control-is-listen-control") {
3818 solo_control_mode_changed ();
3819 } else if (p == "solo-mute-gain") {
3820 _solo_cut_control->Changed();
3821 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3822 last_timecode_valid = false;
3823 } else if (p == "playback-buffer-seconds") {
3824 AudioSource::allocate_working_buffers (frame_rate());
3825 } else if (p == "ltc-source-port") {
3826 reconnect_ltc_input ();
3827 } else if (p == "ltc-sink-port") {
3828 reconnect_ltc_output ();
3829 } else if (p == "timecode-generator-offset") {
3830 ltc_tx_parse_offset();
3831 } else if (p == "auto-return-target-list") {
3832 follow_playhead_priority ();
3839 Session::set_history_depth (uint32_t d)
3841 _history.set_depth (d);
3845 Session::load_diskstreams_2X (XMLNode const & node, int)
3848 XMLNodeConstIterator citer;
3850 clist = node.children();
3852 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3855 /* diskstreams added automatically by DiskstreamCreated handler */
3856 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3857 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3858 _diskstreams_2X.push_back (dsp);
3860 error << _("Session: unknown diskstream type in XML") << endmsg;
3864 catch (failed_constructor& err) {
3865 error << _("Session: could not load diskstream via XML state") << endmsg;
3873 /** Connect things to the MMC object */
3875 Session::setup_midi_machine_control ()
3877 _mmc = new MIDI::MachineControl;
3878 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3880 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3881 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3882 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3883 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3884 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3885 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3886 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3887 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3888 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3889 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3890 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3891 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3892 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3894 /* also handle MIDI SPP because its so common */
3896 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3897 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3898 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3901 boost::shared_ptr<Controllable>
3902 Session::solo_cut_control() const
3904 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3905 controls in Ardour that currently get presented to the user in the GUI that require
3906 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3908 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3909 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3913 return _solo_cut_control;
3917 Session::save_snapshot_name (const std::string & n)
3919 /* assure Stateful::_instant_xml is loaded
3920 * add_instant_xml() only adds to existing data and defaults
3921 * to use an empty Tree otherwise
3923 instant_xml ("LastUsedSnapshot");
3925 XMLNode* last_used_snapshot = new XMLNode ("LastUsedSnapshot");
3926 last_used_snapshot->add_property ("name", string(n));
3927 add_instant_xml (*last_used_snapshot, false);
3931 Session::set_snapshot_name (const std::string & n)
3933 _current_snapshot_name = n;
3934 save_snapshot_name (n);
3938 Session::rename (const std::string& new_name)
3940 string legal_name = legalize_for_path (new_name);
3946 string const old_sources_root = _session_dir->sources_root();
3948 if (!_writable || (_state_of_the_state & CannotSave)) {
3949 error << _("Cannot rename read-only session.") << endmsg;
3950 return 0; // don't show "messed up" warning
3952 if (record_status() == Recording) {
3953 error << _("Cannot rename session while recording") << endmsg;
3954 return 0; // don't show "messed up" warning
3957 StateProtector stp (this);
3962 * interchange subdirectory
3966 * Backup files are left unchanged and not renamed.
3969 /* Windows requires that we close all files before attempting the
3970 * rename. This works on other platforms, but isn't necessary there.
3971 * Leave it in place for all platforms though, since it may help
3972 * catch issues that could arise if the way Source files work ever
3973 * change (since most developers are not using Windows).
3976 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
3977 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3983 /* pass one: not 100% safe check that the new directory names don't
3987 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3991 /* this is a stupid hack because Glib::path_get_dirname() is
3992 * lexical-only, and so passing it /a/b/c/ gives a different
3993 * result than passing it /a/b/c ...
3996 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3997 oldstr = oldstr.substr (0, oldstr.length() - 1);
4000 string base = Glib::path_get_dirname (oldstr);
4002 newstr = Glib::build_filename (base, legal_name);
4004 cerr << "Looking for " << newstr << endl;
4006 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
4007 cerr << " exists\n";
4016 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4022 /* this is a stupid hack because Glib::path_get_dirname() is
4023 * lexical-only, and so passing it /a/b/c/ gives a different
4024 * result than passing it /a/b/c ...
4027 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4028 oldstr = oldstr.substr (0, oldstr.length() - 1);
4031 string base = Glib::path_get_dirname (oldstr);
4032 newstr = Glib::build_filename (base, legal_name);
4034 cerr << "for " << oldstr << " new dir = " << newstr << endl;
4036 cerr << "Rename " << oldstr << " => " << newstr << endl;
4037 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4038 cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4039 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4043 /* Reset path in "session dirs" */
4048 /* reset primary SessionDirectory object */
4051 (*_session_dir) = newstr;
4056 /* now rename directory below session_dir/interchange */
4058 string old_interchange_dir;
4059 string new_interchange_dir;
4061 /* use newstr here because we renamed the path
4062 * (folder/directory) that used to be oldstr to newstr above
4065 v.push_back (newstr);
4066 v.push_back (interchange_dir_name);
4067 v.push_back (Glib::path_get_basename (oldstr));
4069 old_interchange_dir = Glib::build_filename (v);
4072 v.push_back (newstr);
4073 v.push_back (interchange_dir_name);
4074 v.push_back (legal_name);
4076 new_interchange_dir = Glib::build_filename (v);
4078 cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
4080 if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
4081 cerr << string_compose (_("renaming %s as %2 failed (%3)"),
4082 old_interchange_dir, new_interchange_dir,
4085 error << string_compose (_("renaming %s as %2 failed (%3)"),
4086 old_interchange_dir, new_interchange_dir,
4095 oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
4096 newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
4098 cerr << "Rename " << oldstr << " => " << newstr << endl;
4100 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4101 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4102 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4108 oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
4110 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
4111 newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
4113 cerr << "Rename " << oldstr << " => " << newstr << endl;
4115 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4116 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4117 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4122 /* remove old name from recent sessions */
4123 remove_recent_sessions (_path);
4126 /* update file source paths */
4128 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
4129 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4131 string p = fs->path ();
4132 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
4134 SourceFactory::setup_peakfile(i->second, true);
4138 set_snapshot_name (new_name);
4143 /* save state again to get everything just right */
4145 save_state (_current_snapshot_name);
4147 /* add to recent sessions */
4149 store_recent_sessions (new_name, _path);
4155 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
4157 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
4161 if (!tree.read (xmlpath)) {
4169 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
4172 bool found_sr = false;
4173 bool found_data_format = false;
4175 if (get_session_info_from_path (tree, xmlpath)) {
4181 const XMLProperty* prop;
4182 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
4183 sample_rate = atoi (prop->value());
4187 const XMLNodeList& children (tree.root()->children());
4188 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
4189 const XMLNode* child = *c;
4190 if (child->name() == "Config") {
4191 const XMLNodeList& options (child->children());
4192 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
4193 const XMLNode* option = *oc;
4194 const XMLProperty* name = option->property("name");
4200 if (name->value() == "native-file-data-format") {
4201 const XMLProperty* value = option->property ("value");
4203 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
4205 found_data_format = true;
4211 if (found_data_format) {
4216 return !(found_sr && found_data_format); // zero if they are both found
4220 Session::get_snapshot_from_instant (const std::string& session_dir)
4222 std::string instant_xml_path = Glib::build_filename (session_dir, "instant.xml");
4224 if (!Glib::file_test (instant_xml_path, Glib::FILE_TEST_EXISTS)) {
4229 if (!tree.read (instant_xml_path)) {
4233 const XMLProperty* prop;
4234 XMLNode *last_used_snapshot = tree.root()->child("LastUsedSnapshot");
4235 if (last_used_snapshot && (prop = last_used_snapshot->property ("name")) != 0) {
4236 return prop->value();
4242 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
4243 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
4246 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
4250 SourcePathMap source_path_map;
4252 boost::shared_ptr<AudioFileSource> afs;
4257 Glib::Threads::Mutex::Lock lm (source_lock);
4259 cerr << " total sources = " << sources.size();
4261 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4262 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4268 if (fs->within_session()) {
4272 if (source_path_map.find (fs->path()) != source_path_map.end()) {
4273 source_path_map[fs->path()].push_back (fs);
4275 SeveralFileSources v;
4277 source_path_map.insert (make_pair (fs->path(), v));
4283 cerr << " fsources = " << total << endl;
4285 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
4287 /* tell caller where we are */
4289 string old_path = i->first;
4291 callback (n, total, old_path);
4293 cerr << old_path << endl;
4297 switch (i->second.front()->type()) {
4298 case DataType::AUDIO:
4299 new_path = new_audio_source_path_for_embedded (old_path);
4302 case DataType::MIDI:
4303 /* XXX not implemented yet */
4307 if (new_path.empty()) {
4311 cerr << "Move " << old_path << " => " << new_path << endl;
4313 if (!copy_file (old_path, new_path)) {
4314 cerr << "failed !\n";
4318 /* make sure we stop looking in the external
4319 dir/folder. Remember, this is an all-or-nothing
4320 operations, it doesn't merge just some files.
4322 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
4324 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
4325 (*f)->set_path (new_path);
4330 save_state ("", false, false);
4336 bool accept_all_files (string const &, void *)
4342 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4344 /* 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.
4349 make_new_media_path (string old_path, string new_session_folder, string new_session_path)
4351 /* typedir is the "midifiles" or "audiofiles" etc. part of the path. */
4353 string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4355 v.push_back (new_session_folder); /* full path */
4356 v.push_back (interchange_dir_name);
4357 v.push_back (new_session_path); /* just one directory/folder */
4358 v.push_back (typedir);
4359 v.push_back (Glib::path_get_basename (old_path));
4361 return Glib::build_filename (v);
4365 Session::save_as (SaveAs& saveas)
4367 vector<string> files;
4368 string current_folder = Glib::path_get_dirname (_path);
4369 string new_folder = legalize_for_path (saveas.new_name);
4370 string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4371 int64_t total_bytes = 0;
4375 int32_t internal_file_cnt = 0;
4377 vector<string> do_not_copy_extensions;
4378 do_not_copy_extensions.push_back (statefile_suffix);
4379 do_not_copy_extensions.push_back (pending_suffix);
4380 do_not_copy_extensions.push_back (backup_suffix);
4381 do_not_copy_extensions.push_back (temp_suffix);
4382 do_not_copy_extensions.push_back (history_suffix);
4384 /* get total size */
4386 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4388 /* need to clear this because
4389 * find_files_matching_filter() is cumulative
4394 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4396 all += files.size();
4398 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4400 g_stat ((*i).c_str(), &gsb);
4401 total_bytes += gsb.st_size;
4405 /* save old values so we can switch back if we are not switching to the new session */
4407 string old_path = _path;
4408 string old_name = _name;
4409 string old_snapshot = _current_snapshot_name;
4410 string old_sd = _session_dir->root_path();
4411 vector<string> old_search_path[DataType::num_types];
4412 string old_config_search_path[DataType::num_types];
4414 old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4415 old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4416 old_config_search_path[DataType::AUDIO] = config.get_audio_search_path ();
4417 old_config_search_path[DataType::MIDI] = config.get_midi_search_path ();
4419 /* switch session directory */
4421 (*_session_dir) = to_dir;
4423 /* create new tree */
4425 if (!_session_dir->create()) {
4426 saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4431 /* copy all relevant files. Find each location in session_dirs,
4432 * and copy files from there to target.
4435 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4437 /* need to clear this because
4438 * find_files_matching_filter() is cumulative
4443 const size_t prefix_len = (*sd).path.size();
4445 /* Work just on the files within this session dir */
4447 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4449 /* add dir separator to protect against collisions with
4450 * track names (e.g. track named "audiofiles" or
4454 static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
4455 static const std::string midifile_dir_string = string (midi_dir_name) + G_DIR_SEPARATOR;
4456 static const std::string analysis_dir_string = analysis_dir() + G_DIR_SEPARATOR;
4458 /* copy all the files. Handling is different for media files
4459 than others because of the *silly* subtree we have below the interchange
4460 folder. That really was a bad idea, but I'm not fixing it as part of
4461 implementing ::save_as().
4464 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4466 std::string from = *i;
4469 string filename = Glib::path_get_basename (from);
4470 std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
4471 if (filename == ".DS_STORE") {
4476 if (from.find (audiofile_dir_string) != string::npos) {
4478 /* audio file: only copy if asked */
4480 if (saveas.include_media && saveas.copy_media) {
4482 string to = make_new_media_path (*i, to_dir, new_folder);
4484 info << "media file copying from " << from << " to " << to << endmsg;
4486 if (!copy_file (from, to)) {
4487 throw Glib::FileError (Glib::FileError::IO_ERROR,
4488 string_compose(_("\ncopying \"%1\" failed !"), from));
4492 /* we found media files inside the session folder */
4494 internal_file_cnt++;
4496 } else if (from.find (midifile_dir_string) != string::npos) {
4498 /* midi file: always copy unless
4499 * creating an empty new session
4502 if (saveas.include_media) {
4504 string to = make_new_media_path (*i, to_dir, new_folder);
4506 info << "media file copying from " << from << " to " << to << endmsg;
4508 if (!copy_file (from, to)) {
4509 throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4513 /* we found media files inside the session folder */
4515 internal_file_cnt++;
4517 } else if (from.find (analysis_dir_string) != string::npos) {
4519 /* make sure analysis dir exists in
4520 * new session folder, but we're not
4521 * copying analysis files here, see
4525 (void) g_mkdir_with_parents (analysis_dir().c_str(), 775);
4530 /* normal non-media file. Don't copy state, history, etc.
4533 bool do_copy = true;
4535 for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
4536 if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
4537 /* end of filename matches extension, do not copy file */
4543 if (!saveas.copy_media && from.find (peakfile_suffix) != string::npos) {
4544 /* don't copy peakfiles if
4545 * we're not copying media
4551 string to = Glib::build_filename (to_dir, from.substr (prefix_len));
4553 info << "attempting to make directory/folder " << to << endmsg;
4555 if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
4556 throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
4559 info << "attempting to copy " << from << " to " << to << endmsg;
4561 if (!copy_file (from, to)) {
4562 throw Glib::FileError (Glib::FileError::IO_ERROR,
4563 string_compose(_("\ncopying \"%1\" failed !"), from));
4568 /* measure file size even if we're not going to copy so that our Progress
4569 signals are correct, since we included these do-not-copy files
4570 in the computation of the total size and file count.
4574 g_stat (from.c_str(), &gsb);
4575 copied += gsb.st_size;
4578 double fraction = (double) copied / total_bytes;
4580 bool keep_going = true;
4582 if (saveas.copy_media) {
4584 /* no need or expectation of this if
4585 * media is not being copied, because
4586 * it will be fast(ish).
4589 /* tell someone "X percent, file M of N"; M is one-based */
4591 boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
4599 throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
4605 /* copy optional folders, if any */
4607 string old = plugins_dir ();
4608 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4609 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4610 copy_files (old, newdir);
4613 old = externals_dir ();
4614 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4615 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4616 copy_files (old, newdir);
4619 old = automation_dir ();
4620 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4621 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4622 copy_files (old, newdir);
4625 if (saveas.include_media) {
4627 if (saveas.copy_media) {
4628 #ifndef PLATFORM_WINDOWS
4629 /* There are problems with analysis files on
4630 * Windows, because they used a colon in their
4631 * names as late as 4.0. Colons are not legal
4632 * under Windows even if NTFS allows them.
4634 * This is a tricky problem to solve so for
4635 * just don't copy these files. They will be
4636 * regenerated as-needed anyway, subject to the
4637 * existing issue that the filenames will be
4638 * rejected by Windows, which is a separate
4639 * problem (though related).
4642 /* only needed if we are copying media, since the
4643 * analysis data refers to media data
4646 old = analysis_dir ();
4647 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4648 string newdir = Glib::build_filename (to_dir, "analysis");
4649 copy_files (old, newdir);
4651 #endif /* PLATFORM_WINDOWS */
4657 set_snapshot_name (saveas.new_name);
4658 _name = saveas.new_name;
4660 if (saveas.include_media && !saveas.copy_media) {
4662 /* reset search paths of the new session (which we're pretending to be right now) to
4663 include the original session search path, so we can still find all audio.
4666 if (internal_file_cnt) {
4667 for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
4668 ensure_search_path_includes (*s, DataType::AUDIO);
4669 cerr << "be sure to include " << *s << " for audio" << endl;
4672 /* we do not do this for MIDI because we copy
4673 all MIDI files if saveas.include_media is
4679 bool was_dirty = dirty ();
4681 save_state ("", false, false, !saveas.include_media);
4682 save_default_options ();
4684 if (saveas.copy_media && saveas.copy_external) {
4685 if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
4686 throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
4690 saveas.final_session_folder_name = _path;
4692 store_recent_sessions (_name, _path);
4694 if (!saveas.switch_to) {
4696 /* switch back to the way things were */
4700 set_snapshot_name (old_snapshot);
4702 (*_session_dir) = old_sd;
4708 if (internal_file_cnt) {
4709 /* reset these to their original values */
4710 config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
4711 config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
4716 /* prune session dirs, and update disk space statistics
4721 session_dirs.clear ();
4722 session_dirs.push_back (sp);
4723 refresh_disk_space ();
4725 /* ensure that all existing tracks reset their current capture source paths
4727 reset_write_sources (true, true);
4729 /* the copying above was based on actually discovering files, not just iterating over the sources list.
4730 But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
4733 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4734 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4740 if (fs->within_session()) {
4741 string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
4742 fs->set_path (newpath);
4747 } catch (Glib::FileError& e) {
4749 saveas.failure_message = e.what();
4751 /* recursively remove all the directories */
4753 remove_directory (to_dir);
4761 saveas.failure_message = _("unknown reason");
4763 /* recursively remove all the directories */
4765 remove_directory (to_dir);