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/basename.h"
65 #include "pbd/controllable_descriptor.h"
66 #include "pbd/debug.h"
67 #include "pbd/enumwriter.h"
68 #include "pbd/error.h"
69 #include "pbd/file_utils.h"
70 #include "pbd/pathexpand.h"
71 #include "pbd/pthread_utils.h"
72 #include "pbd/stacktrace.h"
73 #include "pbd/convert.h"
74 #include "pbd/localtime_r.h"
75 #include "pbd/unwind.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/boost_debug.h"
86 #include "ardour/butler.h"
87 #include "ardour/control_protocol_manager.h"
88 #include "ardour/directory_names.h"
89 #include "ardour/filename_extensions.h"
90 #include "ardour/graph.h"
91 #include "ardour/location.h"
92 #include "ardour/midi_model.h"
93 #include "ardour/midi_patch_manager.h"
94 #include "ardour/midi_region.h"
95 #include "ardour/midi_scene_changer.h"
96 #include "ardour/midi_source.h"
97 #include "ardour/midi_track.h"
98 #include "ardour/pannable.h"
99 #include "ardour/playlist_factory.h"
100 #include "ardour/playlist_source.h"
101 #include "ardour/port.h"
102 #include "ardour/processor.h"
103 #include "ardour/profile.h"
104 #include "ardour/proxy_controllable.h"
105 #include "ardour/recent_sessions.h"
106 #include "ardour/region_factory.h"
107 #include "ardour/route_group.h"
108 #include "ardour/send.h"
109 #include "ardour/session.h"
110 #include "ardour/session_directory.h"
111 #include "ardour/session_metadata.h"
112 #include "ardour/session_playlists.h"
113 #include "ardour/session_state_utils.h"
114 #include "ardour/silentfilesource.h"
115 #include "ardour/sndfilesource.h"
116 #include "ardour/source_factory.h"
117 #include "ardour/speakers.h"
118 #include "ardour/template_utils.h"
119 #include "ardour/tempo.h"
120 #include "ardour/ticker.h"
121 #include "ardour/user_bundle.h"
123 #include "control_protocol/control_protocol.h"
125 #include "LuaBridge/LuaBridge.h"
131 using namespace ARDOUR;
134 #define DEBUG_UNDO_HISTORY(msg) DEBUG_TRACE (PBD::DEBUG::UndoHistory, string_compose ("%1: %2\n", __LINE__, msg));
137 Session::pre_engine_init (string fullpath)
139 if (fullpath.empty()) {
141 throw failed_constructor();
144 /* discover canonical fullpath */
146 _path = canonical_path(fullpath);
149 if (Profile->get_trx() ) {
150 // Waves TracksLive has a usecase of session replacement with a new one.
151 // We should check session state file (<session_name>.ardour) existance
152 // to determine if the session is new or not
154 string full_session_name = Glib::build_filename( fullpath, _name );
155 full_session_name += statefile_suffix;
157 _is_new = !Glib::file_test (full_session_name, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
159 _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
162 /* finish initialization that can't be done in a normal C++ constructor
166 timerclear (&last_mmc_step);
167 g_atomic_int_set (&processing_prohibited, 0);
168 g_atomic_int_set (&_record_status, Disabled);
169 g_atomic_int_set (&_playback_load, 100);
170 g_atomic_int_set (&_capture_load, 100);
172 _all_route_group->set_active (true, this);
173 interpolation.add_channel_to (0, 0);
175 if (config.get_use_video_sync()) {
176 waiting_for_sync_offset = true;
178 waiting_for_sync_offset = false;
181 last_rr_session_dir = session_dirs.begin();
183 set_history_depth (Config->get_history_depth());
185 /* default: assume simple stereo speaker configuration */
187 _speakers->setup_default_speakers (2);
189 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
190 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
191 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
192 add_controllable (_solo_cut_control);
194 /* These are all static "per-class" signals */
196 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
197 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
198 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
199 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
200 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
202 /* stop IO objects from doing stuff until we're ready for them */
204 Delivery::disable_panners ();
205 IO::disable_connecting ();
209 Session::post_engine_init ()
211 BootMessage (_("Set block size and sample rate"));
213 set_block_size (_engine.samples_per_cycle());
214 set_frame_rate (_engine.sample_rate());
216 BootMessage (_("Using configuration"));
218 _midi_ports = new MidiPortManager;
220 MIDISceneChanger* msc;
222 _scene_changer = msc = new MIDISceneChanger (*this);
223 msc->set_input_port (boost::dynamic_pointer_cast<MidiPort>(scene_input_port()));
224 msc->set_output_port (boost::dynamic_pointer_cast<MidiPort>(scene_output_port()));
226 boost::function<framecnt_t(void)> timer_func (boost::bind (&Session::audible_frame, this));
227 boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_input_port())->set_timer (timer_func);
229 setup_midi_machine_control ();
231 if (_butler->start_thread()) {
235 if (start_midi_thread ()) {
239 setup_click_sounds (0);
240 setup_midi_control ();
242 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
243 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
246 /* tempo map requires sample rate knowledge */
249 _tempo_map = new TempoMap (_current_frame_rate);
250 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
252 /* MidiClock requires a tempo map */
255 midi_clock = new MidiClockTicker ();
256 midi_clock->set_session (this);
258 /* crossfades require sample rate knowledge */
260 SndFileSource::setup_standard_crossfades (*this, frame_rate());
261 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
263 AudioDiskstream::allocate_working_buffers();
264 refresh_disk_space ();
266 /* we're finally ready to call set_state() ... all objects have
267 * been created, the engine is running.
271 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
275 // set_state() will call setup_raid_path(), but if it's a new session we need
276 // to call setup_raid_path() here.
277 setup_raid_path (_path);
282 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
283 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
285 Config->map_parameters (ff);
286 config.map_parameters (ft);
287 _butler->map_parameters ();
289 /* Reset all panners */
291 Delivery::reset_panners ();
293 /* this will cause the CPM to instantiate any protocols that are in use
294 * (or mandatory), which will pass it this Session, and then call
295 * set_state() on each instantiated protocol to match stored state.
298 ControlProtocolManager::instance().set_session (this);
300 /* This must be done after the ControlProtocolManager set_session above,
301 as it will set states for ports which the ControlProtocolManager creates.
304 // XXX set state of MIDI::Port's
305 // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
307 /* And this must be done after the MIDI::Manager::set_port_states as
308 * it will try to make connections whose details are loaded by set_port_states.
313 /* Let control protocols know that we are now all connected, so they
314 * could start talking to surfaces if they want to.
317 ControlProtocolManager::instance().midi_connectivity_established ();
319 if (_is_new && !no_auto_connect()) {
320 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
321 auto_connect_master_bus ();
324 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
326 /* update latencies */
328 initialize_latencies ();
330 _locations->added.connect_same_thread (*this, boost::bind (&Session::location_added, this, _1));
331 _locations->removed.connect_same_thread (*this, boost::bind (&Session::location_removed, this, _1));
332 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
334 } catch (AudioEngine::PortRegistrationFailure& err) {
335 /* handle this one in a different way than all others, so that its clear what happened */
336 error << err.what() << endmsg;
342 BootMessage (_("Reset Remote Controls"));
344 // send_full_time_code (0);
345 _engine.transport_locate (0);
347 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
348 send_immediate_mmc (MIDI::MachineControlCommand (Timecode::Time ()));
350 MIDI::Name::MidiPatchManager::instance().add_search_path (session_directory().midi_patch_path() );
353 /* initial program change will be delivered later; see ::config_changed() */
355 _state_of_the_state = Clean;
357 Port::set_connecting_blocked (false);
359 DirtyChanged (); /* EMIT SIGNAL */
363 } else if (state_was_pending) {
365 remove_pending_capture_state ();
366 state_was_pending = false;
369 /* Now, finally, we can fill the playback buffers */
371 BootMessage (_("Filling playback buffers"));
373 boost::shared_ptr<RouteList> rl = routes.reader();
374 for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
375 boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<Track> (*r);
376 if (trk && !trk->hidden()) {
377 trk->seek (_transport_frame, true);
385 Session::session_loaded ()
389 _state_of_the_state = Clean;
391 DirtyChanged (); /* EMIT SIGNAL */
395 } else if (state_was_pending) {
397 remove_pending_capture_state ();
398 state_was_pending = false;
401 /* Now, finally, we can fill the playback buffers */
403 BootMessage (_("Filling playback buffers"));
404 force_locate (_transport_frame, false);
408 Session::raid_path () const
410 Searchpath raid_search_path;
412 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
413 raid_search_path += (*i).path;
416 return raid_search_path.to_string ();
420 Session::setup_raid_path (string path)
429 session_dirs.clear ();
431 Searchpath search_path(path);
432 Searchpath sound_search_path;
433 Searchpath midi_search_path;
435 for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
437 sp.blocks = 0; // not needed
438 session_dirs.push_back (sp);
440 SessionDirectory sdir(sp.path);
442 sound_search_path += sdir.sound_path ();
443 midi_search_path += sdir.midi_path ();
446 // reset the round-robin soundfile path thingie
447 last_rr_session_dir = session_dirs.begin();
451 Session::path_is_within_session (const std::string& path)
453 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
454 if (PBD::path_is_within (i->path, path)) {
462 Session::ensure_subdirs ()
466 dir = session_directory().peak_path();
468 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
469 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
473 dir = session_directory().sound_path();
475 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
476 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
480 dir = session_directory().midi_path();
482 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
483 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
487 dir = session_directory().dead_path();
489 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
490 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
494 dir = session_directory().export_path();
496 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
497 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
501 dir = analysis_dir ();
503 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
504 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
508 dir = plugins_dir ();
510 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
511 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
515 dir = externals_dir ();
517 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
518 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
525 /** @param session_template directory containing session template, or empty.
526 * Caller must not hold process lock.
529 Session::create (const string& session_template, BusProfile* bus_profile)
531 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
532 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
536 if (ensure_subdirs ()) {
540 _writable = exists_and_writable (_path);
542 if (!session_template.empty()) {
543 string in_path = (ARDOUR::Profile->get_trx () ? session_template : session_template_dir_to_file (session_template));
545 FILE* in = g_fopen (in_path.c_str(), "rb");
548 /* no need to call legalize_for_path() since the string
549 * in session_template is already a legal path name
551 string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
553 FILE* out = g_fopen (out_path.c_str(), "wb");
557 stringstream new_session;
560 size_t charsRead = fread (buf, sizeof(char), 1024, in);
563 error << string_compose (_("Error reading session template file %1 (%2)"), in_path, strerror (errno)) << endmsg;
568 if (charsRead == 0) {
571 new_session.write (buf, charsRead);
575 string file_contents = new_session.str();
576 size_t writeSize = file_contents.length();
577 if (fwrite (file_contents.c_str(), sizeof(char), writeSize, out) != writeSize) {
578 error << string_compose (_("Error writing session template file %1 (%2)"), out_path, strerror (errno)) << endmsg;
586 if (!ARDOUR::Profile->get_trx()) {
587 /* Copy plugin state files from template to new session */
588 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
589 copy_recurse (template_plugins, plugins_dir ());
595 error << string_compose (_("Could not open %1 for writing session template"), out_path)
602 error << string_compose (_("Could not open session template %1 for reading"), in_path)
609 if (Profile->get_trx()) {
611 /* set initial start + end point : ARDOUR::Session::session_end_shift long.
612 Remember that this is a brand new session. Sessions
613 loaded from saved state will get this range from the saved state.
616 set_session_range_location (0, 0);
618 /* Initial loop location, from absolute zero, length 10 seconds */
620 Location* loc = new Location (*this, 0, 10.0 * _engine.sample_rate(), _("Loop"), Location::IsAutoLoop);
621 _locations->add (loc, true);
622 set_auto_loop_location (loc);
625 _state_of_the_state = Clean;
627 /* set up Master Out and Control Out if necessary */
632 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
634 // Waves Tracks: always create master bus for Tracks
635 if (ARDOUR::Profile->get_trx() || bus_profile->master_out_channels) {
636 boost::shared_ptr<Route> r (new Route (*this, _("Master"), Route::MasterOut, DataType::AUDIO));
644 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
645 r->input()->ensure_io (count, false, this);
646 r->output()->ensure_io (count, false, this);
652 /* prohibit auto-connect to master, because there isn't one */
653 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
657 add_routes (rl, false, false, false);
660 // Waves Tracks: Skip this. Always use autoconnection for Tracks
661 if (!ARDOUR::Profile->get_trx()) {
663 /* this allows the user to override settings with an environment variable.
666 if (no_auto_connect()) {
667 bus_profile->input_ac = AutoConnectOption (0);
668 bus_profile->output_ac = AutoConnectOption (0);
671 Config->set_input_auto_connect (bus_profile->input_ac);
672 Config->set_output_auto_connect (bus_profile->output_ac);
676 if (Config->get_use_monitor_bus() && bus_profile) {
677 add_monitor_section ();
684 Session::maybe_write_autosave()
686 if (dirty() && record_status() != Recording) {
687 save_state("", true);
692 Session::remove_pending_capture_state ()
694 std::string pending_state_file_path(_session_dir->root_path());
696 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
698 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
700 if (g_remove (pending_state_file_path.c_str()) != 0) {
701 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
702 pending_state_file_path, g_strerror (errno)) << endmsg;
706 /** Rename a state file.
707 * @param old_name Old snapshot name.
708 * @param new_name New snapshot name.
711 Session::rename_state (string old_name, string new_name)
713 if (old_name == _current_snapshot_name || old_name == _name) {
714 /* refuse to rename the current snapshot or the "main" one */
718 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
719 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
721 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
722 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
724 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
725 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
726 old_name, new_name, g_strerror(errno)) << endmsg;
730 /** Remove a state file.
731 * @param snapshot_name Snapshot name.
734 Session::remove_state (string snapshot_name)
736 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
737 // refuse to remove the current snapshot or the "main" one
741 std::string xml_path(_session_dir->root_path());
743 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
745 if (!create_backup_file (xml_path)) {
746 // don't remove it if a backup can't be made
747 // create_backup_file will log the error.
752 if (g_remove (xml_path.c_str()) != 0) {
753 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
754 xml_path, g_strerror (errno)) << endmsg;
758 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
760 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot, bool template_only)
762 DEBUG_TRACE (DEBUG::Locale, string_compose ("Session::save_state locale '%1'\n", setlocale (LC_NUMERIC, NULL)));
765 std::string xml_path(_session_dir->root_path());
767 /* prevent concurrent saves from different threads */
769 Glib::Threads::Mutex::Lock lm (save_state_lock);
771 if (!_writable || (_state_of_the_state & CannotSave)) {
775 if (g_atomic_int_get(&_suspend_save)) {
779 _save_queued = false;
781 if (!_engine.connected ()) {
782 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
789 const int64_t save_start_time = g_get_monotonic_time();
792 /* tell sources we're saving first, in case they write out to a new file
793 * which should be saved with the state rather than the old one */
794 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
796 i->second->session_saved();
797 } catch (Evoral::SMF::FileError& e) {
798 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
802 SessionSaveUnderway (); /* EMIT SIGNAL */
804 bool mark_as_clean = true;
806 if (!snapshot_name.empty() && !switch_to_snapshot) {
807 mark_as_clean = false;
811 mark_as_clean = false;
812 tree.set_root (&get_template());
814 tree.set_root (&get_state());
817 if (snapshot_name.empty()) {
818 snapshot_name = _current_snapshot_name;
819 } else if (switch_to_snapshot) {
820 set_snapshot_name (snapshot_name);
823 assert (!snapshot_name.empty());
827 /* proper save: use statefile_suffix (.ardour in English) */
829 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
831 /* make a backup copy of the old file */
833 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
834 // create_backup_file will log the error
840 /* pending save: use pending_suffix (.pending in English) */
841 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
844 std::string tmp_path(_session_dir->root_path());
845 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
847 cerr << "actually writing state to " << tmp_path << endl;
849 if (!tree.write (tmp_path)) {
850 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
851 if (g_remove (tmp_path.c_str()) != 0) {
852 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
853 tmp_path, g_strerror (errno)) << endmsg;
859 cerr << "renaming state to " << xml_path << endl;
861 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
862 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
863 tmp_path, xml_path, g_strerror(errno)) << endmsg;
864 if (g_remove (tmp_path.c_str()) != 0) {
865 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
866 tmp_path, g_strerror (errno)) << endmsg;
874 save_history (snapshot_name);
877 bool was_dirty = dirty();
879 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
882 DirtyChanged (); /* EMIT SIGNAL */
886 StateSaved (snapshot_name); /* EMIT SIGNAL */
890 const int64_t elapsed_time_us = g_get_monotonic_time() - save_start_time;
891 cerr << "saved state in " << fixed << setprecision (1) << elapsed_time_us / 1000. << " ms\n";
897 Session::restore_state (string snapshot_name)
899 if (load_state (snapshot_name) == 0) {
900 set_state (*state_tree->root(), Stateful::loading_state_version);
907 Session::load_state (string snapshot_name)
912 state_was_pending = false;
914 /* check for leftover pending state from a crashed capture attempt */
916 std::string xmlpath(_session_dir->root_path());
917 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
919 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
921 /* there is pending state from a crashed capture attempt */
923 boost::optional<int> r = AskAboutPendingState();
924 if (r.get_value_or (1)) {
925 state_was_pending = true;
929 if (!state_was_pending) {
930 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
933 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
934 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
935 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
936 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
941 state_tree = new XMLTree;
945 _writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
947 if (!state_tree->read (xmlpath)) {
948 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
954 XMLNode const & root (*state_tree->root());
956 if (root.name() != X_("Session")) {
957 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
963 XMLProperty const * prop;
965 if ((prop = root.property ("version")) == 0) {
966 /* no version implies very old version of Ardour */
967 Stateful::loading_state_version = 1000;
969 if (prop->value().find ('.') != string::npos) {
970 /* old school version format */
971 if (prop->value()[0] == '2') {
972 Stateful::loading_state_version = 2000;
974 Stateful::loading_state_version = 3000;
977 Stateful::loading_state_version = atoi (prop->value());
981 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
983 std::string backup_path(_session_dir->root_path());
984 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
985 backup_path = Glib::build_filename (backup_path, backup_filename);
987 // only create a backup for a given statefile version once
989 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
991 VersionMismatch (xmlpath, backup_path);
993 if (!copy_file (xmlpath, backup_path)) {;
999 save_snapshot_name (snapshot_name);
1005 Session::load_options (const XMLNode& node)
1008 config.set_variables (node);
1013 Session::save_default_options ()
1015 return config.save_state();
1019 Session::get_state()
1025 Session::get_template()
1027 /* if we don't disable rec-enable, diskstreams
1028 will believe they need to store their capture
1029 sources in their state node.
1032 disable_record (false);
1034 return state(false);
1038 Session::state (bool full_state)
1041 XMLNode* node = new XMLNode("Session");
1045 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
1046 node->add_property("version", buf);
1048 /* store configuration settings */
1052 node->add_property ("name", _name);
1053 snprintf (buf, sizeof (buf), "%" PRId64, _base_frame_rate);
1054 node->add_property ("sample-rate", buf);
1056 if (session_dirs.size() > 1) {
1060 vector<space_and_path>::iterator i = session_dirs.begin();
1061 vector<space_and_path>::iterator next;
1063 ++i; /* skip the first one */
1067 while (i != session_dirs.end()) {
1071 if (next != session_dirs.end()) {
1072 p += G_SEARCHPATH_SEPARATOR;
1081 child = node->add_child ("Path");
1082 child->add_content (p);
1086 /* save the ID counter */
1088 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1089 node->add_property ("id-counter", buf);
1091 snprintf (buf, sizeof (buf), "%u", name_id_counter ());
1092 node->add_property ("name-counter", buf);
1094 /* save the event ID counter */
1096 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1097 node->add_property ("event-counter", buf);
1099 /* various options */
1101 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
1102 if (!midi_port_nodes.empty()) {
1103 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
1104 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
1105 midi_port_stuff->add_child_nocopy (**n);
1107 node->add_child_nocopy (*midi_port_stuff);
1110 node->add_child_nocopy (config.get_variables ());
1112 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1114 child = node->add_child ("Sources");
1117 Glib::Threads::Mutex::Lock sl (source_lock);
1119 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1121 /* Don't save information about non-file Sources, or
1122 * about non-destructive file sources that are empty
1123 * and unused by any regions.
1126 boost::shared_ptr<FileSource> fs;
1128 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1130 if (!fs->destructive()) {
1131 if (fs->empty() && !fs->used()) {
1136 child->add_child_nocopy (siter->second->get_state());
1141 child = node->add_child ("Regions");
1144 Glib::Threads::Mutex::Lock rl (region_lock);
1145 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1146 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1147 boost::shared_ptr<Region> r = i->second;
1148 /* only store regions not attached to playlists */
1149 if (r->playlist() == 0) {
1150 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1151 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1153 child->add_child_nocopy (r->get_state ());
1158 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1160 if (!cassocs.empty()) {
1161 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1163 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1165 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1166 i->first->id().print (buf, sizeof (buf));
1167 can->add_property (X_("copy"), buf);
1168 i->second->id().print (buf, sizeof (buf));
1169 can->add_property (X_("original"), buf);
1170 ca->add_child_nocopy (*can);
1180 node->add_child_nocopy (_locations->get_state());
1183 Locations loc (*this);
1184 // for a template, just create a new Locations, populate it
1185 // with the default start and end, and get the state for that.
1186 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1187 range->set (max_framepos, 0);
1189 XMLNode& locations_state = loc.get_state();
1191 if (ARDOUR::Profile->get_trx() && _locations) {
1192 // For tracks we need stored the Auto Loop Range and all MIDI markers.
1193 for (Locations::LocationList::const_iterator i = _locations->list ().begin (); i != _locations->list ().end (); ++i) {
1194 if ((*i)->is_mark () || (*i)->is_auto_loop ()) {
1195 locations_state.add_child_nocopy ((*i)->get_state ());
1199 node->add_child_nocopy (locations_state);
1202 child = node->add_child ("Bundles");
1204 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1205 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1206 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1208 child->add_child_nocopy (b->get_state());
1213 child = node->add_child ("Routes");
1215 boost::shared_ptr<RouteList> r = routes.reader ();
1217 RoutePublicOrderSorter cmp;
1218 RouteList public_order (*r);
1219 public_order.sort (cmp);
1221 /* the sort should have put control outs first */
1224 assert (_monitor_out == public_order.front());
1227 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1228 if (!(*i)->is_auditioner()) {
1230 child->add_child_nocopy ((*i)->get_state());
1232 child->add_child_nocopy ((*i)->get_template());
1238 playlists->add_state (node, full_state);
1240 child = node->add_child ("RouteGroups");
1241 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1242 child->add_child_nocopy ((*i)->get_state());
1246 XMLNode* gain_child = node->add_child ("Click");
1247 gain_child->add_child_nocopy (_click_io->state (full_state));
1248 gain_child->add_child_nocopy (_click_gain->state (full_state));
1252 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1253 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1257 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1258 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1261 node->add_child_nocopy (_speakers->get_state());
1262 node->add_child_nocopy (_tempo_map->get_state());
1263 node->add_child_nocopy (get_control_protocol_state());
1266 node->add_child_copy (*_extra_xml);
1270 Glib::Threads::Mutex::Lock lm (lua_lock);
1273 luabridge::LuaRef savedstate ((*_lua_save)());
1274 saved = savedstate.cast<std::string>();
1276 lua.collect_garbage ();
1279 gchar* b64 = g_base64_encode ((const guchar*)saved.c_str (), saved.size ());
1280 std::string b64s (b64);
1283 XMLNode* script_node = new XMLNode (X_("Script"));
1284 script_node->add_property (X_("lua"), LUA_VERSION);
1285 script_node->add_content (b64s);
1286 node->add_child_nocopy (*script_node);
1293 Session::get_control_protocol_state ()
1295 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1296 return cpm.get_state();
1300 Session::set_state (const XMLNode& node, int version)
1305 XMLProperty const * prop;
1308 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1310 if (node.name() != X_("Session")) {
1311 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1315 if ((prop = node.property ("name")) != 0) {
1316 _name = prop->value ();
1319 if ((prop = node.property (X_("sample-rate"))) != 0) {
1321 _base_frame_rate = atoi (prop->value());
1322 _nominal_frame_rate = _base_frame_rate;
1324 assert (AudioEngine::instance()->running ());
1325 if (_base_frame_rate != AudioEngine::instance()->sample_rate ()) {
1326 boost::optional<int> r = AskAboutSampleRateMismatch (_base_frame_rate, _current_frame_rate);
1327 if (r.get_value_or (0)) {
1333 setup_raid_path(_session_dir->root_path());
1335 if ((prop = node.property (X_("id-counter"))) != 0) {
1337 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1338 ID::init_counter (x);
1340 /* old sessions used a timebased counter, so fake
1341 the startup ID counter based on a standard
1346 ID::init_counter (now);
1349 if ((prop = node.property (X_("name-counter"))) != 0) {
1350 init_name_id_counter (atoi (prop->value()));
1353 if ((prop = node.property (X_("event-counter"))) != 0) {
1354 Evoral::init_event_id_counter (atoi (prop->value()));
1357 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1358 _midi_ports->set_midi_port_states (child->children());
1361 IO::disable_connecting ();
1363 Stateful::save_extra_xml (node);
1365 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1366 load_options (*child);
1367 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1368 load_options (*child);
1370 error << _("Session: XML state has no options section") << endmsg;
1373 if (version >= 3000) {
1374 if ((child = find_named_node (node, "Metadata")) == 0) {
1375 warning << _("Session: XML state has no metadata section") << endmsg;
1376 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1381 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1382 _speakers->set_state (*child, version);
1385 if ((child = find_named_node (node, "Sources")) == 0) {
1386 error << _("Session: XML state has no sources section") << endmsg;
1388 } else if (load_sources (*child)) {
1392 if ((child = find_named_node (node, "TempoMap")) == 0) {
1393 error << _("Session: XML state has no Tempo Map section") << endmsg;
1395 } else if (_tempo_map->set_state (*child, version)) {
1399 if ((child = find_named_node (node, "Locations")) == 0) {
1400 error << _("Session: XML state has no locations section") << endmsg;
1402 } else if (_locations->set_state (*child, version)) {
1406 locations_changed ();
1408 if (_session_range_location) {
1409 AudioFileSource::set_header_position_offset (_session_range_location->start());
1412 if ((child = find_named_node (node, "Regions")) == 0) {
1413 error << _("Session: XML state has no Regions section") << endmsg;
1415 } else if (load_regions (*child)) {
1419 if ((child = find_named_node (node, "Playlists")) == 0) {
1420 error << _("Session: XML state has no playlists section") << endmsg;
1422 } else if (playlists->load (*this, *child)) {
1426 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1428 } else if (playlists->load_unused (*this, *child)) {
1432 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1433 if (load_compounds (*child)) {
1438 if (version >= 3000) {
1439 if ((child = find_named_node (node, "Bundles")) == 0) {
1440 warning << _("Session: XML state has no bundles section") << endmsg;
1443 /* We can't load Bundles yet as they need to be able
1444 to convert from port names to Port objects, which can't happen until
1446 _bundle_xml_node = new XMLNode (*child);
1450 if (version < 3000) {
1451 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1452 error << _("Session: XML state has no diskstreams section") << endmsg;
1454 } else if (load_diskstreams_2X (*child, version)) {
1459 if ((child = find_named_node (node, "Routes")) == 0) {
1460 error << _("Session: XML state has no routes section") << endmsg;
1462 } else if (load_routes (*child, version)) {
1466 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1467 _diskstreams_2X.clear ();
1469 if (version >= 3000) {
1471 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1472 error << _("Session: XML state has no route groups section") << endmsg;
1474 } else if (load_route_groups (*child, version)) {
1478 } else if (version < 3000) {
1480 if ((child = find_named_node (node, "EditGroups")) == 0) {
1481 error << _("Session: XML state has no edit groups section") << endmsg;
1483 } else if (load_route_groups (*child, version)) {
1487 if ((child = find_named_node (node, "MixGroups")) == 0) {
1488 error << _("Session: XML state has no mix groups section") << endmsg;
1490 } else if (load_route_groups (*child, version)) {
1495 if ((child = find_named_node (node, "Click")) == 0) {
1496 warning << _("Session: XML state has no click section") << endmsg;
1497 } else if (_click_io) {
1498 setup_click_state (&node);
1501 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1502 ControlProtocolManager::instance().set_state (*child, version);
1505 if ((child = find_named_node (node, "Script"))) {
1506 for (XMLNodeList::const_iterator n = child->children ().begin (); n != child->children ().end (); ++n) {
1507 if (!(*n)->is_content ()) { continue; }
1509 guchar* buf = g_base64_decode ((*n)->content ().c_str (), &size);
1511 Glib::Threads::Mutex::Lock lm (lua_lock);
1512 (*_lua_load)(std::string ((const char*)buf, size));
1513 } catch (luabridge::LuaException const& e) {
1514 cerr << "LuaException:" << e.what () << endl;
1520 update_route_record_state ();
1522 /* here beginneth the second phase ... */
1523 set_snapshot_name (_current_snapshot_name);
1525 StateReady (); /* EMIT SIGNAL */
1538 Session::load_routes (const XMLNode& node, int version)
1541 XMLNodeConstIterator niter;
1542 RouteList new_routes;
1544 nlist = node.children();
1548 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1550 boost::shared_ptr<Route> route;
1551 if (version < 3000) {
1552 route = XMLRouteFactory_2X (**niter, version);
1554 route = XMLRouteFactory (**niter, version);
1558 error << _("Session: cannot create Route from XML description.") << endmsg;
1562 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1564 new_routes.push_back (route);
1567 BootMessage (_("Tracks/busses loaded; Adding to Session"));
1569 add_routes (new_routes, false, false, false);
1571 BootMessage (_("Finished adding tracks/busses"));
1576 boost::shared_ptr<Route>
1577 Session::XMLRouteFactory (const XMLNode& node, int version)
1579 boost::shared_ptr<Route> ret;
1581 if (node.name() != "Route") {
1585 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1587 DataType type = DataType::AUDIO;
1588 XMLProperty const * prop = node.property("default-type");
1591 type = DataType (prop->value());
1594 assert (type != DataType::NIL);
1598 boost::shared_ptr<Track> track;
1600 if (type == DataType::AUDIO) {
1601 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1603 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1606 if (track->init()) {
1610 if (track->set_state (node, version)) {
1614 BOOST_MARK_TRACK (track);
1618 enum Route::Flag flags = Route::Flag(0);
1619 XMLProperty const * prop = node.property("flags");
1621 flags = Route::Flag (string_2_enum (prop->value(), flags));
1624 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1626 if (r->init () == 0 && r->set_state (node, version) == 0) {
1627 BOOST_MARK_ROUTE (r);
1635 boost::shared_ptr<Route>
1636 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1638 boost::shared_ptr<Route> ret;
1640 if (node.name() != "Route") {
1644 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1646 ds_prop = node.property (X_("diskstream"));
1649 DataType type = DataType::AUDIO;
1650 XMLProperty const * prop = node.property("default-type");
1653 type = DataType (prop->value());
1656 assert (type != DataType::NIL);
1660 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1661 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1665 if (i == _diskstreams_2X.end()) {
1666 error << _("Could not find diskstream for route") << endmsg;
1667 return boost::shared_ptr<Route> ();
1670 boost::shared_ptr<Track> track;
1672 if (type == DataType::AUDIO) {
1673 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1675 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1678 if (track->init()) {
1682 if (track->set_state (node, version)) {
1686 track->set_diskstream (*i);
1688 BOOST_MARK_TRACK (track);
1692 enum Route::Flag flags = Route::Flag(0);
1693 XMLProperty const * prop = node.property("flags");
1695 flags = Route::Flag (string_2_enum (prop->value(), flags));
1698 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1700 if (r->init () == 0 && r->set_state (node, version) == 0) {
1701 BOOST_MARK_ROUTE (r);
1710 Session::load_regions (const XMLNode& node)
1713 XMLNodeConstIterator niter;
1714 boost::shared_ptr<Region> region;
1716 nlist = node.children();
1720 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1721 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1722 error << _("Session: cannot create Region from XML description.");
1723 XMLProperty const * name = (**niter).property("name");
1726 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1737 Session::load_compounds (const XMLNode& node)
1739 XMLNodeList calist = node.children();
1740 XMLNodeConstIterator caiter;
1741 XMLProperty const * caprop;
1743 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1744 XMLNode* ca = *caiter;
1748 if ((caprop = ca->property (X_("original"))) == 0) {
1751 orig_id = caprop->value();
1753 if ((caprop = ca->property (X_("copy"))) == 0) {
1756 copy_id = caprop->value();
1758 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1759 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1761 if (!orig || !copy) {
1762 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1768 RegionFactory::add_compound_association (orig, copy);
1775 Session::load_nested_sources (const XMLNode& node)
1778 XMLNodeConstIterator niter;
1780 nlist = node.children();
1782 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1783 if ((*niter)->name() == "Source") {
1785 /* it may already exist, so don't recreate it unnecessarily
1788 XMLProperty const * prop = (*niter)->property (X_("id"));
1790 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1794 ID source_id (prop->value());
1796 if (!source_by_id (source_id)) {
1799 SourceFactory::create (*this, **niter, true);
1801 catch (failed_constructor& err) {
1802 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1809 boost::shared_ptr<Region>
1810 Session::XMLRegionFactory (const XMLNode& node, bool full)
1812 XMLProperty const * type = node.property("type");
1816 const XMLNodeList& nlist = node.children();
1818 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1819 XMLNode *child = (*niter);
1820 if (child->name() == "NestedSource") {
1821 load_nested_sources (*child);
1825 if (!type || type->value() == "audio") {
1826 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1827 } else if (type->value() == "midi") {
1828 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1831 } catch (failed_constructor& err) {
1832 return boost::shared_ptr<Region> ();
1835 return boost::shared_ptr<Region> ();
1838 boost::shared_ptr<AudioRegion>
1839 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1841 XMLProperty const * prop;
1842 boost::shared_ptr<Source> source;
1843 boost::shared_ptr<AudioSource> as;
1845 SourceList master_sources;
1846 uint32_t nchans = 1;
1849 if (node.name() != X_("Region")) {
1850 return boost::shared_ptr<AudioRegion>();
1853 if ((prop = node.property (X_("channels"))) != 0) {
1854 nchans = atoi (prop->value().c_str());
1857 if ((prop = node.property ("name")) == 0) {
1858 cerr << "no name for this region\n";
1862 if ((prop = node.property (X_("source-0"))) == 0) {
1863 if ((prop = node.property ("source")) == 0) {
1864 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1865 return boost::shared_ptr<AudioRegion>();
1869 PBD::ID s_id (prop->value());
1871 if ((source = source_by_id (s_id)) == 0) {
1872 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1873 return boost::shared_ptr<AudioRegion>();
1876 as = boost::dynamic_pointer_cast<AudioSource>(source);
1878 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1879 return boost::shared_ptr<AudioRegion>();
1882 sources.push_back (as);
1884 /* pickup other channels */
1886 for (uint32_t n=1; n < nchans; ++n) {
1887 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1888 if ((prop = node.property (buf)) != 0) {
1890 PBD::ID id2 (prop->value());
1892 if ((source = source_by_id (id2)) == 0) {
1893 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1894 return boost::shared_ptr<AudioRegion>();
1897 as = boost::dynamic_pointer_cast<AudioSource>(source);
1899 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1900 return boost::shared_ptr<AudioRegion>();
1902 sources.push_back (as);
1906 for (uint32_t n = 0; n < nchans; ++n) {
1907 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1908 if ((prop = node.property (buf)) != 0) {
1910 PBD::ID id2 (prop->value());
1912 if ((source = source_by_id (id2)) == 0) {
1913 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1914 return boost::shared_ptr<AudioRegion>();
1917 as = boost::dynamic_pointer_cast<AudioSource>(source);
1919 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1920 return boost::shared_ptr<AudioRegion>();
1922 master_sources.push_back (as);
1927 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1929 /* a final detail: this is the one and only place that we know how long missing files are */
1931 if (region->whole_file()) {
1932 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1933 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1935 sfp->set_length (region->length());
1940 if (!master_sources.empty()) {
1941 if (master_sources.size() != nchans) {
1942 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1944 region->set_master_sources (master_sources);
1952 catch (failed_constructor& err) {
1953 return boost::shared_ptr<AudioRegion>();
1957 boost::shared_ptr<MidiRegion>
1958 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1960 XMLProperty const * prop;
1961 boost::shared_ptr<Source> source;
1962 boost::shared_ptr<MidiSource> ms;
1965 if (node.name() != X_("Region")) {
1966 return boost::shared_ptr<MidiRegion>();
1969 if ((prop = node.property ("name")) == 0) {
1970 cerr << "no name for this region\n";
1974 if ((prop = node.property (X_("source-0"))) == 0) {
1975 if ((prop = node.property ("source")) == 0) {
1976 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1977 return boost::shared_ptr<MidiRegion>();
1981 PBD::ID s_id (prop->value());
1983 if ((source = source_by_id (s_id)) == 0) {
1984 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1985 return boost::shared_ptr<MidiRegion>();
1988 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1990 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1991 return boost::shared_ptr<MidiRegion>();
1994 sources.push_back (ms);
1997 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1998 /* a final detail: this is the one and only place that we know how long missing files are */
2000 if (region->whole_file()) {
2001 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
2002 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
2004 sfp->set_length (region->length());
2012 catch (failed_constructor& err) {
2013 return boost::shared_ptr<MidiRegion>();
2018 Session::get_sources_as_xml ()
2021 XMLNode* node = new XMLNode (X_("Sources"));
2022 Glib::Threads::Mutex::Lock lm (source_lock);
2024 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2025 node->add_child_nocopy (i->second->get_state());
2032 Session::reset_write_sources (bool mark_write_complete, bool force)
2034 boost::shared_ptr<RouteList> rl = routes.reader();
2035 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
2036 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
2038 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
2039 tr->reset_write_sources(mark_write_complete, force);
2040 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
2046 Session::load_sources (const XMLNode& node)
2049 XMLNodeConstIterator niter;
2050 boost::shared_ptr<Source> source; /* don't need this but it stops some
2051 * versions of gcc complaining about
2052 * discarded return values.
2055 nlist = node.children();
2059 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2062 if ((source = XMLSourceFactory (**niter)) == 0) {
2063 error << _("Session: cannot create Source from XML description.") << endmsg;
2066 } catch (MissingSource& err) {
2070 if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
2071 error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
2072 PROGRAM_NAME) << endmsg;
2076 if (!no_questions_about_missing_files) {
2077 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
2082 switch (user_choice) {
2084 /* user added a new search location, so try again */
2089 /* user asked to quit the entire session load
2094 no_questions_about_missing_files = true;
2098 no_questions_about_missing_files = true;
2105 case DataType::AUDIO:
2106 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
2109 case DataType::MIDI:
2110 /* The MIDI file is actually missing so
2111 * just create a new one in the same
2112 * location. Do not announce its
2116 if (!Glib::path_is_absolute (err.path)) {
2117 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
2119 /* this should be an unrecoverable error: we would be creating a MIDI file outside
2124 /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
2125 source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
2126 /* reset ID to match the missing one */
2127 source->set_id (**niter);
2128 /* Now we can announce it */
2129 SourceFactory::SourceCreated (source);
2140 boost::shared_ptr<Source>
2141 Session::XMLSourceFactory (const XMLNode& node)
2143 if (node.name() != "Source") {
2144 return boost::shared_ptr<Source>();
2148 /* note: do peak building in another thread when loading session state */
2149 return SourceFactory::create (*this, node, true);
2152 catch (failed_constructor& err) {
2153 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
2154 return boost::shared_ptr<Source>();
2159 Session::save_template (string template_name, bool replace_existing)
2161 if ((_state_of_the_state & CannotSave) || template_name.empty ()) {
2165 bool absolute_path = Glib::path_is_absolute (template_name);
2167 /* directory to put the template in */
2168 std::string template_dir_path;
2170 if (!absolute_path) {
2171 std::string user_template_dir(user_template_directory());
2173 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2174 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2175 user_template_dir, g_strerror (errno)) << endmsg;
2179 template_dir_path = Glib::build_filename (user_template_dir, template_name);
2181 template_dir_path = template_name;
2184 if (!ARDOUR::Profile->get_trx()) {
2185 if (!replace_existing && Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2186 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2187 template_dir_path) << endmsg;
2191 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2192 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2193 template_dir_path, g_strerror (errno)) << endmsg;
2199 std::string template_file_path;
2201 if (ARDOUR::Profile->get_trx()) {
2202 template_file_path = template_name;
2204 if (absolute_path) {
2205 template_file_path = Glib::build_filename (template_dir_path, Glib::path_get_basename (template_dir_path) + template_suffix);
2207 template_file_path = Glib::build_filename (template_dir_path, template_name + template_suffix);
2211 SessionSaveUnderway (); /* EMIT SIGNAL */
2216 PBD::Unwinder<std::string> uw (_template_state_dir, template_dir_path);
2217 tree.set_root (&get_template());
2220 if (!tree.write (template_file_path)) {
2221 error << _("template not saved") << endmsg;
2225 store_recent_templates (template_file_path);
2231 Session::refresh_disk_space ()
2233 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2235 Glib::Threads::Mutex::Lock lm (space_lock);
2237 /* get freespace on every FS that is part of the session path */
2239 _total_free_4k_blocks = 0;
2240 _total_free_4k_blocks_uncertain = false;
2242 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2244 struct statfs statfsbuf;
2245 statfs (i->path.c_str(), &statfsbuf);
2247 double const scale = statfsbuf.f_bsize / 4096.0;
2249 /* See if this filesystem is read-only */
2250 struct statvfs statvfsbuf;
2251 statvfs (i->path.c_str(), &statvfsbuf);
2253 /* f_bavail can be 0 if it is undefined for whatever
2254 filesystem we are looking at; Samba shares mounted
2255 via GVFS are an example of this.
2257 if (statfsbuf.f_bavail == 0) {
2258 /* block count unknown */
2260 i->blocks_unknown = true;
2261 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2262 /* read-only filesystem */
2264 i->blocks_unknown = false;
2266 /* read/write filesystem with known space */
2267 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2268 i->blocks_unknown = false;
2271 _total_free_4k_blocks += i->blocks;
2272 if (i->blocks_unknown) {
2273 _total_free_4k_blocks_uncertain = true;
2276 #elif defined PLATFORM_WINDOWS
2277 vector<string> scanned_volumes;
2278 vector<string>::iterator j;
2279 vector<space_and_path>::iterator i;
2280 DWORD nSectorsPerCluster, nBytesPerSector,
2281 nFreeClusters, nTotalClusters;
2285 _total_free_4k_blocks = 0;
2287 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2288 strncpy (disk_drive, (*i).path.c_str(), 3);
2292 volume_found = false;
2293 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2295 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2296 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2297 i->blocks = (uint32_t)(nFreeBytes / 4096);
2299 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2300 if (0 == j->compare(disk_drive)) {
2301 volume_found = true;
2306 if (!volume_found) {
2307 scanned_volumes.push_back(disk_drive);
2308 _total_free_4k_blocks += i->blocks;
2313 if (0 == _total_free_4k_blocks) {
2314 strncpy (disk_drive, path().c_str(), 3);
2317 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2319 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2320 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2321 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2328 Session::get_best_session_directory_for_new_audio ()
2330 vector<space_and_path>::iterator i;
2331 string result = _session_dir->root_path();
2333 /* handle common case without system calls */
2335 if (session_dirs.size() == 1) {
2339 /* OK, here's the algorithm we're following here:
2341 We want to select which directory to use for
2342 the next file source to be created. Ideally,
2343 we'd like to use a round-robin process so as to
2344 get maximum performance benefits from splitting
2345 the files across multiple disks.
2347 However, in situations without much diskspace, an
2348 RR approach may end up filling up a filesystem
2349 with new files while others still have space.
2350 Its therefore important to pay some attention to
2351 the freespace in the filesystem holding each
2352 directory as well. However, if we did that by
2353 itself, we'd keep creating new files in the file
2354 system with the most space until it was as full
2355 as all others, thus negating any performance
2356 benefits of this RAID-1 like approach.
2358 So, we use a user-configurable space threshold. If
2359 there are at least 2 filesystems with more than this
2360 much space available, we use RR selection between them.
2361 If not, then we pick the filesystem with the most space.
2363 This gets a good balance between the two
2367 refresh_disk_space ();
2369 int free_enough = 0;
2371 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2372 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2377 if (free_enough >= 2) {
2378 /* use RR selection process, ensuring that the one
2382 i = last_rr_session_dir;
2385 if (++i == session_dirs.end()) {
2386 i = session_dirs.begin();
2389 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2390 SessionDirectory sdir(i->path);
2391 if (sdir.create ()) {
2393 last_rr_session_dir = i;
2398 } while (i != last_rr_session_dir);
2402 /* pick FS with the most freespace (and that
2403 seems to actually work ...)
2406 vector<space_and_path> sorted;
2407 space_and_path_ascending_cmp cmp;
2409 sorted = session_dirs;
2410 sort (sorted.begin(), sorted.end(), cmp);
2412 for (i = sorted.begin(); i != sorted.end(); ++i) {
2413 SessionDirectory sdir(i->path);
2414 if (sdir.create ()) {
2416 last_rr_session_dir = i;
2426 Session::automation_dir () const
2428 return Glib::build_filename (_path, automation_dir_name);
2432 Session::analysis_dir () const
2434 return Glib::build_filename (_path, analysis_dir_name);
2438 Session::plugins_dir () const
2440 return Glib::build_filename (_path, plugins_dir_name);
2444 Session::externals_dir () const
2446 return Glib::build_filename (_path, externals_dir_name);
2450 Session::load_bundles (XMLNode const & node)
2452 XMLNodeList nlist = node.children();
2453 XMLNodeConstIterator niter;
2457 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2458 if ((*niter)->name() == "InputBundle") {
2459 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2460 } else if ((*niter)->name() == "OutputBundle") {
2461 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2463 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2472 Session::load_route_groups (const XMLNode& node, int version)
2474 XMLNodeList nlist = node.children();
2475 XMLNodeConstIterator niter;
2479 if (version >= 3000) {
2481 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2482 if ((*niter)->name() == "RouteGroup") {
2483 RouteGroup* rg = new RouteGroup (*this, "");
2484 add_route_group (rg);
2485 rg->set_state (**niter, version);
2489 } else if (version < 3000) {
2491 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2492 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2493 RouteGroup* rg = new RouteGroup (*this, "");
2494 add_route_group (rg);
2495 rg->set_state (**niter, version);
2504 state_file_filter (const string &str, void* /*arg*/)
2506 return (str.length() > strlen(statefile_suffix) &&
2507 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2511 remove_end(string state)
2513 string statename(state);
2515 string::size_type start,end;
2516 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2517 statename = statename.substr (start+1);
2520 if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2521 end = statename.length();
2524 return string(statename.substr (0, end));
2528 Session::possible_states (string path)
2530 vector<string> states;
2531 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2533 transform(states.begin(), states.end(), states.begin(), remove_end);
2535 sort (states.begin(), states.end());
2541 Session::possible_states () const
2543 return possible_states(_path);
2547 Session::add_route_group (RouteGroup* g)
2549 _route_groups.push_back (g);
2550 route_group_added (g); /* EMIT SIGNAL */
2552 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2553 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2554 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2560 Session::remove_route_group (RouteGroup& rg)
2562 list<RouteGroup*>::iterator i;
2564 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2565 _route_groups.erase (i);
2568 route_group_removed (); /* EMIT SIGNAL */
2572 /** Set a new order for our route groups, without adding or removing any.
2573 * @param groups Route group list in the new order.
2576 Session::reorder_route_groups (list<RouteGroup*> groups)
2578 _route_groups = groups;
2580 route_groups_reordered (); /* EMIT SIGNAL */
2586 Session::route_group_by_name (string name)
2588 list<RouteGroup *>::iterator i;
2590 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2591 if ((*i)->name() == name) {
2599 Session::all_route_group() const
2601 return *_all_route_group;
2605 Session::add_commands (vector<Command*> const & cmds)
2607 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2613 Session::add_command (Command* const cmd)
2615 assert (_current_trans);
2616 DEBUG_UNDO_HISTORY (
2617 string_compose ("Current Undo Transaction %1, adding command: %2",
2618 _current_trans->name (),
2620 _current_trans->add_command (cmd);
2623 PBD::StatefulDiffCommand*
2624 Session::add_stateful_diff_command (boost::shared_ptr<PBD::StatefulDestructible> sfd)
2626 PBD::StatefulDiffCommand* cmd = new PBD::StatefulDiffCommand (sfd);
2632 Session::begin_reversible_command (const string& name)
2634 begin_reversible_command (g_quark_from_string (name.c_str ()));
2637 /** Begin a reversible command using a GQuark to identify it.
2638 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2639 * but there must be as many begin...()s as there are commit...()s.
2642 Session::begin_reversible_command (GQuark q)
2644 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2645 to hold all the commands that are committed. This keeps the order of
2646 commands correct in the history.
2649 if (_current_trans == 0) {
2650 DEBUG_UNDO_HISTORY (string_compose (
2651 "Begin Reversible Command, new transaction: %1", g_quark_to_string (q)));
2653 /* start a new transaction */
2654 assert (_current_trans_quarks.empty ());
2655 _current_trans = new UndoTransaction();
2656 _current_trans->set_name (g_quark_to_string (q));
2658 DEBUG_UNDO_HISTORY (
2659 string_compose ("Begin Reversible Command, current transaction: %1",
2660 _current_trans->name ()));
2663 _current_trans_quarks.push_front (q);
2667 Session::abort_reversible_command ()
2669 if (_current_trans != 0) {
2670 DEBUG_UNDO_HISTORY (
2671 string_compose ("Abort Reversible Command: %1", _current_trans->name ()));
2672 _current_trans->clear();
2673 delete _current_trans;
2675 _current_trans_quarks.clear();
2680 Session::commit_reversible_command (Command *cmd)
2682 assert (_current_trans);
2683 assert (!_current_trans_quarks.empty ());
2688 DEBUG_UNDO_HISTORY (
2689 string_compose ("Current Undo Transaction %1, adding command: %2",
2690 _current_trans->name (),
2692 _current_trans->add_command (cmd);
2695 DEBUG_UNDO_HISTORY (
2696 string_compose ("Commit Reversible Command, current transaction: %1",
2697 _current_trans->name ()));
2699 _current_trans_quarks.pop_front ();
2701 if (!_current_trans_quarks.empty ()) {
2702 DEBUG_UNDO_HISTORY (
2703 string_compose ("Commit Reversible Command, transaction is not "
2704 "top-level, current transaction: %1",
2705 _current_trans->name ()));
2706 /* the transaction we're committing is not the top-level one */
2710 if (_current_trans->empty()) {
2711 /* no commands were added to the transaction, so just get rid of it */
2712 DEBUG_UNDO_HISTORY (
2713 string_compose ("Commit Reversible Command, No commands were "
2714 "added to current transaction: %1",
2715 _current_trans->name ()));
2716 delete _current_trans;
2721 gettimeofday (&now, 0);
2722 _current_trans->set_timestamp (now);
2724 _history.add (_current_trans);
2729 accept_all_audio_files (const string& path, void* /*arg*/)
2731 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2735 if (!AudioFileSource::safe_audio_file_extension (path)) {
2743 accept_all_midi_files (const string& path, void* /*arg*/)
2745 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2749 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2750 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2751 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2755 accept_all_state_files (const string& path, void* /*arg*/)
2757 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2761 std::string const statefile_ext (statefile_suffix);
2762 if (path.length() >= statefile_ext.length()) {
2763 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2770 Session::find_all_sources (string path, set<string>& result)
2775 if (!tree.read (path)) {
2779 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2784 XMLNodeConstIterator niter;
2786 nlist = node->children();
2790 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2792 XMLProperty const * prop;
2794 if ((prop = (*niter)->property (X_("type"))) == 0) {
2798 DataType type (prop->value());
2800 if ((prop = (*niter)->property (X_("name"))) == 0) {
2804 if (Glib::path_is_absolute (prop->value())) {
2805 /* external file, ignore */
2813 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2814 result.insert (found_path);
2822 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2824 vector<string> state_files;
2826 string this_snapshot_path;
2832 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2833 ripped = ripped.substr (0, ripped.length() - 1);
2836 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2838 if (state_files.empty()) {
2843 this_snapshot_path = _path;
2844 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2845 this_snapshot_path += statefile_suffix;
2847 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2849 if (exclude_this_snapshot && *i == this_snapshot_path) {
2853 if (find_all_sources (*i, result) < 0) {
2861 struct RegionCounter {
2862 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2863 AudioSourceList::iterator iter;
2864 boost::shared_ptr<Region> region;
2867 RegionCounter() : count (0) {}
2871 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2873 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2874 return r.get_value_or (1);
2878 Session::cleanup_regions ()
2880 bool removed = false;
2881 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2883 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2885 uint32_t used = playlists->region_use_count (i->second);
2887 if (used == 0 && !i->second->automatic ()) {
2888 boost::weak_ptr<Region> w = i->second;
2891 RegionFactory::map_remove (w);
2898 // re-check to remove parent references of compound regions
2899 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2900 if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2904 assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2905 if (0 == playlists->region_use_count (i->second)) {
2906 boost::weak_ptr<Region> w = i->second;
2908 RegionFactory::map_remove (w);
2915 /* dump the history list */
2922 Session::can_cleanup_peakfiles () const
2924 if (deletion_in_progress()) {
2927 if (!_writable || (_state_of_the_state & CannotSave)) {
2928 warning << _("Cannot cleanup peak-files for read-only session.") << endmsg;
2931 if (record_status() == Recording) {
2932 error << _("Cannot cleanup peak-files while recording") << endmsg;
2939 Session::cleanup_peakfiles ()
2941 Glib::Threads::Mutex::Lock lm (peak_cleanup_lock, Glib::Threads::TRY_LOCK);
2946 assert (can_cleanup_peakfiles ());
2947 assert (!peaks_cleanup_in_progres());
2949 _state_of_the_state = StateOfTheState (_state_of_the_state | PeakCleanup);
2951 int timeout = 5000; // 5 seconds
2952 while (!SourceFactory::files_with_peaks.empty()) {
2953 Glib::usleep (1000);
2954 if (--timeout < 0) {
2955 warning << _("Timeout waiting for peak-file creation to terminate before cleanup, please try again later.") << endmsg;
2956 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
2961 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2962 boost::shared_ptr<AudioSource> as;
2963 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
2964 as->close_peakfile();
2968 PBD::clear_directory (session_directory().peak_path());
2970 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
2972 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2973 boost::shared_ptr<AudioSource> as;
2974 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
2975 SourceFactory::setup_peakfile(as, true);
2982 Session::cleanup_sources (CleanupReport& rep)
2984 // FIXME: needs adaptation to midi
2986 vector<boost::shared_ptr<Source> > dead_sources;
2989 vector<string> candidates;
2990 vector<string> unused;
2991 set<string> all_sources;
3000 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
3002 /* this is mostly for windows which doesn't allow file
3003 * renaming if the file is in use. But we don't special
3004 * case it because we need to know if this causes
3005 * problems, and the easiest way to notice that is to
3006 * keep it in place for all platforms.
3009 request_stop (false);
3011 _butler->wait_until_finished ();
3013 /* consider deleting all unused playlists */
3015 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
3020 /* sync the "all regions" property of each playlist with its current state
3023 playlists->sync_all_regions_with_regions ();
3025 /* find all un-used sources */
3030 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3032 SourceMap::iterator tmp;
3037 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
3041 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
3042 dead_sources.push_back (i->second);
3043 i->second->drop_references ();
3049 /* build a list of all the possible audio directories for the session */
3051 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3052 SessionDirectory sdir ((*i).path);
3053 asp += sdir.sound_path();
3055 audio_path += asp.to_string();
3058 /* build a list of all the possible midi directories for the session */
3060 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3061 SessionDirectory sdir ((*i).path);
3062 msp += sdir.midi_path();
3064 midi_path += msp.to_string();
3066 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
3067 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
3069 /* find all sources, but don't use this snapshot because the
3070 state file on disk still references sources we may have already
3074 find_all_sources_across_snapshots (all_sources, true);
3076 /* add our current source list
3079 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3080 boost::shared_ptr<FileSource> fs;
3081 SourceMap::iterator tmp = i;
3084 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
3086 /* this is mostly for windows which doesn't allow file
3087 * renaming if the file is in use. But we don't special
3088 * case it because we need to know if this causes
3089 * problems, and the easiest way to notice that is to
3090 * keep it in place for all platforms.
3095 if (!fs->is_stub()) {
3097 if (playlists->source_use_count (fs) != 0) {
3098 all_sources.insert (fs->path());
3101 /* we might not remove this source from disk, because it may be used
3102 by other snapshots, but its not being used in this version
3103 so lets get rid of it now, along with any representative regions
3107 RegionFactory::remove_regions_using_source (i->second);
3109 // also remove source from all_sources
3111 for (set<string>::iterator j = all_sources.begin(); j != all_sources.end(); ++j) {
3112 spath = Glib::path_get_basename (*j);
3113 if (spath == i->second->name()) {
3114 all_sources.erase (j);
3127 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
3132 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
3134 tmppath1 = canonical_path (spath);
3135 tmppath2 = canonical_path ((*i));
3137 if (tmppath1 == tmppath2) {
3144 unused.push_back (spath);
3148 /* now try to move all unused files into the "dead" directory(ies) */
3150 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
3155 /* don't move the file across filesystems, just
3156 stick it in the `dead_dir_name' directory
3157 on whichever filesystem it was already on.
3160 if ((*x).find ("/sounds/") != string::npos) {
3162 /* old school, go up 1 level */
3164 newpath = Glib::path_get_dirname (*x); // "sounds"
3165 newpath = Glib::path_get_dirname (newpath); // "session-name"
3169 /* new school, go up 4 levels */
3171 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
3172 newpath = Glib::path_get_dirname (newpath); // "session-name"
3173 newpath = Glib::path_get_dirname (newpath); // "interchange"
3174 newpath = Glib::path_get_dirname (newpath); // "session-dir"
3177 newpath = Glib::build_filename (newpath, dead_dir_name);
3179 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
3180 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
3184 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
3186 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
3188 /* the new path already exists, try versioning */
3190 char buf[PATH_MAX+1];
3194 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3197 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
3198 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3202 if (version == 999) {
3203 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3207 newpath = newpath_v;
3212 /* it doesn't exist, or we can't read it or something */
3216 g_stat ((*x).c_str(), &statbuf);
3218 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3219 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
3220 (*x), newpath, strerror (errno))
3225 /* see if there an easy to find peakfile for this file, and remove it.
3228 string base = Glib::path_get_basename (*x);
3229 base += "%A"; /* this is what we add for the channel suffix of all native files,
3230 or for the first channel of embedded files. it will miss
3231 some peakfiles for other channels
3233 string peakpath = construct_peak_filepath (base);
3235 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
3236 if (::g_unlink (peakpath.c_str()) != 0) {
3237 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3238 peakpath, _path, strerror (errno))
3240 /* try to back out */
3241 ::rename (newpath.c_str(), _path.c_str());
3246 rep.paths.push_back (*x);
3247 rep.space += statbuf.st_size;
3250 /* dump the history list */
3254 /* save state so we don't end up a session file
3255 referring to non-existent sources.
3262 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3268 Session::cleanup_trash_sources (CleanupReport& rep)
3270 // FIXME: needs adaptation for MIDI
3272 vector<space_and_path>::iterator i;
3278 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3280 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
3282 clear_directory (dead_dir, &rep.space, &rep.paths);
3289 Session::set_dirty ()
3291 /* never mark session dirty during loading */
3293 if (_state_of_the_state & Loading) {
3297 bool was_dirty = dirty();
3299 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3303 DirtyChanged(); /* EMIT SIGNAL */
3309 Session::set_clean ()
3311 bool was_dirty = dirty();
3313 _state_of_the_state = Clean;
3317 DirtyChanged(); /* EMIT SIGNAL */
3322 Session::set_deletion_in_progress ()
3324 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3328 Session::clear_deletion_in_progress ()
3330 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3334 Session::add_controllable (boost::shared_ptr<Controllable> c)
3336 /* this adds a controllable to the list managed by the Session.
3337 this is a subset of those managed by the Controllable class
3338 itself, and represents the only ones whose state will be saved
3339 as part of the session.
3342 Glib::Threads::Mutex::Lock lm (controllables_lock);
3343 controllables.insert (c);
3346 struct null_deleter { void operator()(void const *) const {} };
3349 Session::remove_controllable (Controllable* c)
3351 if (_state_of_the_state & Deletion) {
3355 Glib::Threads::Mutex::Lock lm (controllables_lock);
3357 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3359 if (x != controllables.end()) {
3360 controllables.erase (x);
3364 boost::shared_ptr<Controllable>
3365 Session::controllable_by_id (const PBD::ID& id)
3367 Glib::Threads::Mutex::Lock lm (controllables_lock);
3369 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3370 if ((*i)->id() == id) {
3375 return boost::shared_ptr<Controllable>();
3378 boost::shared_ptr<Controllable>
3379 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3381 boost::shared_ptr<Controllable> c;
3382 boost::shared_ptr<Route> r;
3384 switch (desc.top_level_type()) {
3385 case ControllableDescriptor::NamedRoute:
3387 std::string str = desc.top_level_name();
3388 if (str == "Master" || str == "master") {
3390 } else if (str == "control" || str == "listen") {
3393 r = route_by_name (desc.top_level_name());
3398 case ControllableDescriptor::RemoteControlID:
3399 r = route_by_remote_id (desc.rid());
3402 case ControllableDescriptor::SelectionCount:
3403 r = route_by_selected_count (desc.selection_id());
3411 switch (desc.subtype()) {
3412 case ControllableDescriptor::Gain:
3413 c = r->gain_control ();
3416 case ControllableDescriptor::Trim:
3417 c = r->trim()->gain_control ();
3420 case ControllableDescriptor::Solo:
3421 c = r->solo_control();
3424 case ControllableDescriptor::Mute:
3425 c = r->mute_control();
3428 case ControllableDescriptor::Recenable:
3430 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3433 c = t->rec_enable_control ();
3438 case ControllableDescriptor::PanDirection:
3439 c = r->pan_azimuth_control();
3442 case ControllableDescriptor::PanWidth:
3443 c = r->pan_width_control();
3446 case ControllableDescriptor::PanElevation:
3447 c = r->pan_elevation_control();
3450 case ControllableDescriptor::Balance:
3451 /* XXX simple pan control */
3454 case ControllableDescriptor::PluginParameter:
3456 uint32_t plugin = desc.target (0);
3457 uint32_t parameter_index = desc.target (1);
3459 /* revert to zero based counting */
3465 if (parameter_index > 0) {
3469 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3472 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3473 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3478 case ControllableDescriptor::SendGain: {
3479 uint32_t send = desc.target (0);
3483 c = r->send_level_controllable (send);
3488 /* relax and return a null pointer */
3496 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3499 Stateful::add_instant_xml (node, _path);
3502 if (write_to_config) {
3503 Config->add_instant_xml (node);
3508 Session::instant_xml (const string& node_name)
3510 return Stateful::instant_xml (node_name, _path);
3514 Session::save_history (string snapshot_name)
3522 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3523 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3527 if (snapshot_name.empty()) {
3528 snapshot_name = _current_snapshot_name;
3531 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3532 const string backup_filename = history_filename + backup_suffix;
3533 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3534 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3536 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3537 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3538 error << _("could not backup old history file, current history not saved") << endmsg;
3543 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3545 if (!tree.write (xml_path))
3547 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3549 if (g_remove (xml_path.c_str()) != 0) {
3550 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3551 xml_path, g_strerror (errno)) << endmsg;
3553 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3554 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3555 backup_path, g_strerror (errno)) << endmsg;
3565 Session::restore_history (string snapshot_name)
3569 if (snapshot_name.empty()) {
3570 snapshot_name = _current_snapshot_name;
3573 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3574 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3576 info << "Loading history from " << xml_path << endmsg;
3578 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3579 info << string_compose (_("%1: no history file \"%2\" for this session."),
3580 _name, xml_path) << endmsg;
3584 if (!tree.read (xml_path)) {
3585 error << string_compose (_("Could not understand session history file \"%1\""),
3586 xml_path) << endmsg;
3593 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3596 UndoTransaction* ut = new UndoTransaction ();
3599 ut->set_name(t->property("name")->value());
3600 stringstream ss(t->property("tv-sec")->value());
3602 ss.str(t->property("tv-usec")->value());
3604 ut->set_timestamp(tv);
3606 for (XMLNodeConstIterator child_it = t->children().begin();
3607 child_it != t->children().end(); child_it++)
3609 XMLNode *n = *child_it;
3612 if (n->name() == "MementoCommand" ||
3613 n->name() == "MementoUndoCommand" ||
3614 n->name() == "MementoRedoCommand") {
3616 if ((c = memento_command_factory(n))) {
3620 } else if (n->name() == "NoteDiffCommand") {
3621 PBD::ID id (n->property("midi-source")->value());
3622 boost::shared_ptr<MidiSource> midi_source =
3623 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3625 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3627 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3630 } else if (n->name() == "SysExDiffCommand") {
3632 PBD::ID id (n->property("midi-source")->value());
3633 boost::shared_ptr<MidiSource> midi_source =
3634 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3636 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3638 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3641 } else if (n->name() == "PatchChangeDiffCommand") {
3643 PBD::ID id (n->property("midi-source")->value());
3644 boost::shared_ptr<MidiSource> midi_source =
3645 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3647 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3649 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3652 } else if (n->name() == "StatefulDiffCommand") {
3653 if ((c = stateful_diff_command_factory (n))) {
3654 ut->add_command (c);
3657 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3668 Session::config_changed (std::string p, bool ours)
3674 if (p == "seamless-loop") {
3676 } else if (p == "rf-speed") {
3678 } else if (p == "auto-loop") {
3680 } else if (p == "auto-input") {
3682 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3683 /* auto-input only makes a difference if we're rolling */
3684 set_track_monitor_input_status (!config.get_auto_input());
3687 } else if (p == "punch-in") {
3691 if ((location = _locations->auto_punch_location()) != 0) {
3693 if (config.get_punch_in ()) {
3694 replace_event (SessionEvent::PunchIn, location->start());
3696 remove_event (location->start(), SessionEvent::PunchIn);
3700 } else if (p == "punch-out") {
3704 if ((location = _locations->auto_punch_location()) != 0) {
3706 if (config.get_punch_out()) {
3707 replace_event (SessionEvent::PunchOut, location->end());
3709 clear_events (SessionEvent::PunchOut);
3713 } else if (p == "edit-mode") {
3715 Glib::Threads::Mutex::Lock lm (playlists->lock);
3717 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3718 (*i)->set_edit_mode (Config->get_edit_mode ());
3721 } else if (p == "use-video-sync") {
3723 waiting_for_sync_offset = config.get_use_video_sync();
3725 } else if (p == "mmc-control") {
3727 //poke_midi_thread ();
3729 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3731 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3733 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3735 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3737 } else if (p == "midi-control") {
3739 //poke_midi_thread ();
3741 } else if (p == "raid-path") {
3743 setup_raid_path (config.get_raid_path());
3745 } else if (p == "timecode-format") {
3749 } else if (p == "video-pullup") {
3753 } else if (p == "seamless-loop") {
3755 if (play_loop && transport_rolling()) {
3756 // to reset diskstreams etc
3757 request_play_loop (true);
3760 } else if (p == "rf-speed") {
3762 cumulative_rf_motion = 0;
3765 } else if (p == "click-sound") {
3767 setup_click_sounds (1);
3769 } else if (p == "click-emphasis-sound") {
3771 setup_click_sounds (-1);
3773 } else if (p == "clicking") {
3775 if (Config->get_clicking()) {
3776 if (_click_io && click_data) { // don't require emphasis data
3783 } else if (p == "click-gain") {
3786 _click_gain->gain_control()->set_value (Config->get_click_gain(), Controllable::NoGroup);
3789 } else if (p == "send-mtc") {
3791 if (Config->get_send_mtc ()) {
3792 /* mark us ready to send */
3793 next_quarter_frame_to_send = 0;
3796 } else if (p == "send-mmc") {
3798 _mmc->enable_send (Config->get_send_mmc ());
3800 } else if (p == "midi-feedback") {
3802 session_midi_feedback = Config->get_midi_feedback();
3804 } else if (p == "jack-time-master") {
3806 engine().reset_timebase ();
3808 } else if (p == "native-file-header-format") {
3810 if (!first_file_header_format_reset) {
3811 reset_native_file_format ();
3814 first_file_header_format_reset = false;
3816 } else if (p == "native-file-data-format") {
3818 if (!first_file_data_format_reset) {
3819 reset_native_file_format ();
3822 first_file_data_format_reset = false;
3824 } else if (p == "external-sync") {
3825 if (!config.get_external_sync()) {
3826 drop_sync_source ();
3828 switch_to_sync_source (Config->get_sync_source());
3830 } else if (p == "denormal-model") {
3832 } else if (p == "history-depth") {
3833 set_history_depth (Config->get_history_depth());
3834 } else if (p == "remote-model") {
3835 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3838 } else if (p == "initial-program-change") {
3840 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3843 buf[0] = MIDI::program; // channel zero by default
3844 buf[1] = (Config->get_initial_program_change() & 0x7f);
3846 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3848 } else if (p == "solo-mute-override") {
3849 // catch_up_on_solo_mute_override ();
3850 } else if (p == "listen-position" || p == "pfl-position") {
3851 listen_position_changed ();
3852 } else if (p == "solo-control-is-listen-control") {
3853 solo_control_mode_changed ();
3854 } else if (p == "solo-mute-gain") {
3855 _solo_cut_control->Changed();
3856 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3857 last_timecode_valid = false;
3858 } else if (p == "playback-buffer-seconds") {
3859 AudioSource::allocate_working_buffers (frame_rate());
3860 } else if (p == "ltc-source-port") {
3861 reconnect_ltc_input ();
3862 } else if (p == "ltc-sink-port") {
3863 reconnect_ltc_output ();
3864 } else if (p == "timecode-generator-offset") {
3865 ltc_tx_parse_offset();
3866 } else if (p == "auto-return-target-list") {
3867 follow_playhead_priority ();
3874 Session::set_history_depth (uint32_t d)
3876 _history.set_depth (d);
3880 Session::load_diskstreams_2X (XMLNode const & node, int)
3883 XMLNodeConstIterator citer;
3885 clist = node.children();
3887 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3890 /* diskstreams added automatically by DiskstreamCreated handler */
3891 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3892 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3893 _diskstreams_2X.push_back (dsp);
3895 error << _("Session: unknown diskstream type in XML") << endmsg;
3899 catch (failed_constructor& err) {
3900 error << _("Session: could not load diskstream via XML state") << endmsg;
3908 /** Connect things to the MMC object */
3910 Session::setup_midi_machine_control ()
3912 _mmc = new MIDI::MachineControl;
3914 boost::shared_ptr<AsyncMIDIPort> async_in = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_input_port());
3915 boost::shared_ptr<AsyncMIDIPort> async_out = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_output_port());
3917 if (!async_out || !async_out) {
3921 /* XXXX argh, passing raw pointers back into libmidi++ */
3923 MIDI::Port* mmc_in = async_in.get();
3924 MIDI::Port* mmc_out = async_out.get();
3926 _mmc->set_ports (mmc_in, mmc_out);
3928 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3929 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3930 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3931 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3932 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3933 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3934 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3935 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3936 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3937 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3938 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3939 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3940 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3942 /* also handle MIDI SPP because its so common */
3944 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3945 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3946 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3949 boost::shared_ptr<Controllable>
3950 Session::solo_cut_control() const
3952 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3953 controls in Ardour that currently get presented to the user in the GUI that require
3954 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3956 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3957 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3961 return _solo_cut_control;
3965 Session::save_snapshot_name (const std::string & n)
3967 /* assure Stateful::_instant_xml is loaded
3968 * add_instant_xml() only adds to existing data and defaults
3969 * to use an empty Tree otherwise
3971 instant_xml ("LastUsedSnapshot");
3973 XMLNode* last_used_snapshot = new XMLNode ("LastUsedSnapshot");
3974 last_used_snapshot->add_property ("name", string(n));
3975 add_instant_xml (*last_used_snapshot, false);
3979 Session::set_snapshot_name (const std::string & n)
3981 _current_snapshot_name = n;
3982 save_snapshot_name (n);
3986 Session::rename (const std::string& new_name)
3988 string legal_name = legalize_for_path (new_name);
3994 string const old_sources_root = _session_dir->sources_root();
3996 if (!_writable || (_state_of_the_state & CannotSave)) {
3997 error << _("Cannot rename read-only session.") << endmsg;
3998 return 0; // don't show "messed up" warning
4000 if (record_status() == Recording) {
4001 error << _("Cannot rename session while recording") << endmsg;
4002 return 0; // don't show "messed up" warning
4005 StateProtector stp (this);
4010 * interchange subdirectory
4014 * Backup files are left unchanged and not renamed.
4017 /* Windows requires that we close all files before attempting the
4018 * rename. This works on other platforms, but isn't necessary there.
4019 * Leave it in place for all platforms though, since it may help
4020 * catch issues that could arise if the way Source files work ever
4021 * change (since most developers are not using Windows).
4024 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4025 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4031 /* pass one: not 100% safe check that the new directory names don't
4035 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4039 /* this is a stupid hack because Glib::path_get_dirname() is
4040 * lexical-only, and so passing it /a/b/c/ gives a different
4041 * result than passing it /a/b/c ...
4044 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4045 oldstr = oldstr.substr (0, oldstr.length() - 1);
4048 string base = Glib::path_get_dirname (oldstr);
4050 newstr = Glib::build_filename (base, legal_name);
4052 cerr << "Looking for " << newstr << endl;
4054 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
4055 cerr << " exists\n";
4064 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4070 /* this is a stupid hack because Glib::path_get_dirname() is
4071 * lexical-only, and so passing it /a/b/c/ gives a different
4072 * result than passing it /a/b/c ...
4075 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4076 oldstr = oldstr.substr (0, oldstr.length() - 1);
4079 string base = Glib::path_get_dirname (oldstr);
4080 newstr = Glib::build_filename (base, legal_name);
4082 cerr << "for " << oldstr << " new dir = " << newstr << endl;
4084 cerr << "Rename " << oldstr << " => " << newstr << endl;
4085 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4086 cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4087 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4091 /* Reset path in "session dirs" */
4096 /* reset primary SessionDirectory object */
4099 (*_session_dir) = newstr;
4104 /* now rename directory below session_dir/interchange */
4106 string old_interchange_dir;
4107 string new_interchange_dir;
4109 /* use newstr here because we renamed the path
4110 * (folder/directory) that used to be oldstr to newstr above
4113 v.push_back (newstr);
4114 v.push_back (interchange_dir_name);
4115 v.push_back (Glib::path_get_basename (oldstr));
4117 old_interchange_dir = Glib::build_filename (v);
4120 v.push_back (newstr);
4121 v.push_back (interchange_dir_name);
4122 v.push_back (legal_name);
4124 new_interchange_dir = Glib::build_filename (v);
4126 cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
4128 if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
4129 cerr << string_compose (_("renaming %s as %2 failed (%3)"),
4130 old_interchange_dir, new_interchange_dir,
4133 error << string_compose (_("renaming %s as %2 failed (%3)"),
4134 old_interchange_dir, new_interchange_dir,
4143 oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
4144 newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
4146 cerr << "Rename " << oldstr << " => " << newstr << endl;
4148 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4149 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4150 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4156 oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
4158 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
4159 newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
4161 cerr << "Rename " << oldstr << " => " << newstr << endl;
4163 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4164 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4165 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4170 /* remove old name from recent sessions */
4171 remove_recent_sessions (_path);
4174 /* update file source paths */
4176 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
4177 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4179 string p = fs->path ();
4180 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
4182 SourceFactory::setup_peakfile(i->second, true);
4186 set_snapshot_name (new_name);
4191 /* save state again to get everything just right */
4193 save_state (_current_snapshot_name);
4195 /* add to recent sessions */
4197 store_recent_sessions (new_name, _path);
4203 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
4205 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
4209 if (!tree.read (xmlpath)) {
4217 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
4220 bool found_sr = false;
4221 bool found_data_format = false;
4223 if (get_session_info_from_path (tree, xmlpath)) {
4229 XMLProperty const * prop;
4230 XMLNode const * root (tree.root());
4232 if ((prop = root->property (X_("sample-rate"))) != 0) {
4233 sample_rate = atoi (prop->value());
4237 const XMLNodeList& children (root->children());
4238 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
4239 const XMLNode* child = *c;
4240 if (child->name() == "Config") {
4241 const XMLNodeList& options (child->children());
4242 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
4243 XMLNode const * option = *oc;
4244 XMLProperty const * name = option->property("name");
4250 if (name->value() == "native-file-data-format") {
4251 XMLProperty const * value = option->property ("value");
4253 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
4255 found_data_format = true;
4261 if (found_data_format) {
4266 return !(found_sr && found_data_format); // zero if they are both found
4270 Session::get_snapshot_from_instant (const std::string& session_dir)
4272 std::string instant_xml_path = Glib::build_filename (session_dir, "instant.xml");
4274 if (!Glib::file_test (instant_xml_path, Glib::FILE_TEST_EXISTS)) {
4279 if (!tree.read (instant_xml_path)) {
4283 XMLProperty const * prop;
4284 XMLNode *last_used_snapshot = tree.root()->child("LastUsedSnapshot");
4285 if (last_used_snapshot && (prop = last_used_snapshot->property ("name")) != 0) {
4286 return prop->value();
4292 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
4293 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
4296 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
4300 SourcePathMap source_path_map;
4302 boost::shared_ptr<AudioFileSource> afs;
4307 Glib::Threads::Mutex::Lock lm (source_lock);
4309 cerr << " total sources = " << sources.size();
4311 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4312 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4318 if (fs->within_session()) {
4322 if (source_path_map.find (fs->path()) != source_path_map.end()) {
4323 source_path_map[fs->path()].push_back (fs);
4325 SeveralFileSources v;
4327 source_path_map.insert (make_pair (fs->path(), v));
4333 cerr << " fsources = " << total << endl;
4335 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
4337 /* tell caller where we are */
4339 string old_path = i->first;
4341 callback (n, total, old_path);
4343 cerr << old_path << endl;
4347 switch (i->second.front()->type()) {
4348 case DataType::AUDIO:
4349 new_path = new_audio_source_path_for_embedded (old_path);
4352 case DataType::MIDI:
4353 /* XXX not implemented yet */
4357 if (new_path.empty()) {
4361 cerr << "Move " << old_path << " => " << new_path << endl;
4363 if (!copy_file (old_path, new_path)) {
4364 cerr << "failed !\n";
4368 /* make sure we stop looking in the external
4369 dir/folder. Remember, this is an all-or-nothing
4370 operations, it doesn't merge just some files.
4372 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
4374 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
4375 (*f)->set_path (new_path);
4380 save_state ("", false, false);
4386 bool accept_all_files (string const &, void *)
4392 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4394 /* 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.
4399 make_new_media_path (string old_path, string new_session_folder, string new_session_path)
4401 /* typedir is the "midifiles" or "audiofiles" etc. part of the path. */
4403 string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4405 v.push_back (new_session_folder); /* full path */
4406 v.push_back (interchange_dir_name);
4407 v.push_back (new_session_path); /* just one directory/folder */
4408 v.push_back (typedir);
4409 v.push_back (Glib::path_get_basename (old_path));
4411 return Glib::build_filename (v);
4415 Session::save_as (SaveAs& saveas)
4417 vector<string> files;
4418 string current_folder = Glib::path_get_dirname (_path);
4419 string new_folder = legalize_for_path (saveas.new_name);
4420 string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4421 int64_t total_bytes = 0;
4425 int32_t internal_file_cnt = 0;
4427 vector<string> do_not_copy_extensions;
4428 do_not_copy_extensions.push_back (statefile_suffix);
4429 do_not_copy_extensions.push_back (pending_suffix);
4430 do_not_copy_extensions.push_back (backup_suffix);
4431 do_not_copy_extensions.push_back (temp_suffix);
4432 do_not_copy_extensions.push_back (history_suffix);
4434 /* get total size */
4436 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4438 /* need to clear this because
4439 * find_files_matching_filter() is cumulative
4444 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4446 all += files.size();
4448 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4450 g_stat ((*i).c_str(), &gsb);
4451 total_bytes += gsb.st_size;
4455 /* save old values so we can switch back if we are not switching to the new session */
4457 string old_path = _path;
4458 string old_name = _name;
4459 string old_snapshot = _current_snapshot_name;
4460 string old_sd = _session_dir->root_path();
4461 vector<string> old_search_path[DataType::num_types];
4462 string old_config_search_path[DataType::num_types];
4464 old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4465 old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4466 old_config_search_path[DataType::AUDIO] = config.get_audio_search_path ();
4467 old_config_search_path[DataType::MIDI] = config.get_midi_search_path ();
4469 /* switch session directory */
4471 (*_session_dir) = to_dir;
4473 /* create new tree */
4475 if (!_session_dir->create()) {
4476 saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4481 /* copy all relevant files. Find each location in session_dirs,
4482 * and copy files from there to target.
4485 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4487 /* need to clear this because
4488 * find_files_matching_filter() is cumulative
4493 const size_t prefix_len = (*sd).path.size();
4495 /* Work just on the files within this session dir */
4497 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4499 /* add dir separator to protect against collisions with
4500 * track names (e.g. track named "audiofiles" or
4504 static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
4505 static const std::string midifile_dir_string = string (midi_dir_name) + G_DIR_SEPARATOR;
4506 static const std::string analysis_dir_string = analysis_dir() + G_DIR_SEPARATOR;
4508 /* copy all the files. Handling is different for media files
4509 than others because of the *silly* subtree we have below the interchange
4510 folder. That really was a bad idea, but I'm not fixing it as part of
4511 implementing ::save_as().
4514 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4516 std::string from = *i;
4519 string filename = Glib::path_get_basename (from);
4520 std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
4521 if (filename == ".DS_STORE") {
4526 if (from.find (audiofile_dir_string) != string::npos) {
4528 /* audio file: only copy if asked */
4530 if (saveas.include_media && saveas.copy_media) {
4532 string to = make_new_media_path (*i, to_dir, new_folder);
4534 info << "media file copying from " << from << " to " << to << endmsg;
4536 if (!copy_file (from, to)) {
4537 throw Glib::FileError (Glib::FileError::IO_ERROR,
4538 string_compose(_("\ncopying \"%1\" failed !"), from));
4542 /* we found media files inside the session folder */
4544 internal_file_cnt++;
4546 } else if (from.find (midifile_dir_string) != string::npos) {
4548 /* midi file: always copy unless
4549 * creating an empty new session
4552 if (saveas.include_media) {
4554 string to = make_new_media_path (*i, to_dir, new_folder);
4556 info << "media file copying from " << from << " to " << to << endmsg;
4558 if (!copy_file (from, to)) {
4559 throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4563 /* we found media files inside the session folder */
4565 internal_file_cnt++;
4567 } else if (from.find (analysis_dir_string) != string::npos) {
4569 /* make sure analysis dir exists in
4570 * new session folder, but we're not
4571 * copying analysis files here, see
4575 (void) g_mkdir_with_parents (analysis_dir().c_str(), 775);
4580 /* normal non-media file. Don't copy state, history, etc.
4583 bool do_copy = true;
4585 for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
4586 if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
4587 /* end of filename matches extension, do not copy file */
4593 if (!saveas.copy_media && from.find (peakfile_suffix) != string::npos) {
4594 /* don't copy peakfiles if
4595 * we're not copying media
4601 string to = Glib::build_filename (to_dir, from.substr (prefix_len));
4603 info << "attempting to make directory/folder " << to << endmsg;
4605 if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
4606 throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
4609 info << "attempting to copy " << from << " to " << to << endmsg;
4611 if (!copy_file (from, to)) {
4612 throw Glib::FileError (Glib::FileError::IO_ERROR,
4613 string_compose(_("\ncopying \"%1\" failed !"), from));
4618 /* measure file size even if we're not going to copy so that our Progress
4619 signals are correct, since we included these do-not-copy files
4620 in the computation of the total size and file count.
4624 g_stat (from.c_str(), &gsb);
4625 copied += gsb.st_size;
4628 double fraction = (double) copied / total_bytes;
4630 bool keep_going = true;
4632 if (saveas.copy_media) {
4634 /* no need or expectation of this if
4635 * media is not being copied, because
4636 * it will be fast(ish).
4639 /* tell someone "X percent, file M of N"; M is one-based */
4641 boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
4649 throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
4655 /* copy optional folders, if any */
4657 string old = plugins_dir ();
4658 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4659 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4660 copy_files (old, newdir);
4663 old = externals_dir ();
4664 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4665 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4666 copy_files (old, newdir);
4669 old = automation_dir ();
4670 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4671 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4672 copy_files (old, newdir);
4675 if (saveas.include_media) {
4677 if (saveas.copy_media) {
4678 #ifndef PLATFORM_WINDOWS
4679 /* There are problems with analysis files on
4680 * Windows, because they used a colon in their
4681 * names as late as 4.0. Colons are not legal
4682 * under Windows even if NTFS allows them.
4684 * This is a tricky problem to solve so for
4685 * just don't copy these files. They will be
4686 * regenerated as-needed anyway, subject to the
4687 * existing issue that the filenames will be
4688 * rejected by Windows, which is a separate
4689 * problem (though related).
4692 /* only needed if we are copying media, since the
4693 * analysis data refers to media data
4696 old = analysis_dir ();
4697 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4698 string newdir = Glib::build_filename (to_dir, "analysis");
4699 copy_files (old, newdir);
4701 #endif /* PLATFORM_WINDOWS */
4707 set_snapshot_name (saveas.new_name);
4708 _name = saveas.new_name;
4710 if (saveas.include_media && !saveas.copy_media) {
4712 /* reset search paths of the new session (which we're pretending to be right now) to
4713 include the original session search path, so we can still find all audio.
4716 if (internal_file_cnt) {
4717 for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
4718 ensure_search_path_includes (*s, DataType::AUDIO);
4719 cerr << "be sure to include " << *s << " for audio" << endl;
4722 /* we do not do this for MIDI because we copy
4723 all MIDI files if saveas.include_media is
4729 bool was_dirty = dirty ();
4731 save_state ("", false, false, !saveas.include_media);
4732 save_default_options ();
4734 if (saveas.copy_media && saveas.copy_external) {
4735 if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
4736 throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
4740 saveas.final_session_folder_name = _path;
4742 store_recent_sessions (_name, _path);
4744 if (!saveas.switch_to) {
4746 /* switch back to the way things were */
4750 set_snapshot_name (old_snapshot);
4752 (*_session_dir) = old_sd;
4758 if (internal_file_cnt) {
4759 /* reset these to their original values */
4760 config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
4761 config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
4766 /* prune session dirs, and update disk space statistics
4771 session_dirs.clear ();
4772 session_dirs.push_back (sp);
4773 refresh_disk_space ();
4775 /* ensure that all existing tracks reset their current capture source paths
4777 reset_write_sources (true, true);
4779 /* the copying above was based on actually discovering files, not just iterating over the sources list.
4780 But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
4783 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4784 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4790 if (fs->within_session()) {
4791 string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
4792 fs->set_path (newpath);
4797 } catch (Glib::FileError& e) {
4799 saveas.failure_message = e.what();
4801 /* recursively remove all the directories */
4803 remove_directory (to_dir);
4811 saveas.failure_message = _("unknown reason");
4813 /* recursively remove all the directories */
4815 remove_directory (to_dir);