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 */
43 #include <sys/param.h>
44 #include <sys/mount.h>
47 #ifdef HAVE_SYS_STATVFS_H
48 #include <sys/statvfs.h>
52 #include "pbd/gstdio_compat.h"
55 #include <glibmm/threads.h>
56 #include <glibmm/fileutils.h>
58 #include <boost/algorithm/string.hpp>
60 #include "midi++/mmc.h"
61 #include "midi++/port.h"
63 #include "evoral/SMF.hpp"
65 #include "pbd/basename.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/auditioner.h"
85 #include "ardour/automation_control.h"
86 #include "ardour/boost_debug.h"
87 #include "ardour/butler.h"
88 #include "ardour/controllable_descriptor.h"
89 #include "ardour/control_protocol_manager.h"
90 #include "ardour/directory_names.h"
91 #include "ardour/filename_extensions.h"
92 #include "ardour/graph.h"
93 #include "ardour/location.h"
94 #include "ardour/midi_model.h"
95 #include "ardour/midi_patch_manager.h"
96 #include "ardour/midi_region.h"
97 #include "ardour/midi_scene_changer.h"
98 #include "ardour/midi_source.h"
99 #include "ardour/midi_track.h"
100 #include "ardour/pannable.h"
101 #include "ardour/playlist_factory.h"
102 #include "ardour/playlist_source.h"
103 #include "ardour/port.h"
104 #include "ardour/processor.h"
105 #include "ardour/profile.h"
106 #include "ardour/proxy_controllable.h"
107 #include "ardour/recent_sessions.h"
108 #include "ardour/region_factory.h"
109 #include "ardour/route_group.h"
110 #include "ardour/send.h"
111 #include "ardour/session.h"
112 #include "ardour/session_directory.h"
113 #include "ardour/session_metadata.h"
114 #include "ardour/session_playlists.h"
115 #include "ardour/session_state_utils.h"
116 #include "ardour/silentfilesource.h"
117 #include "ardour/sndfilesource.h"
118 #include "ardour/source_factory.h"
119 #include "ardour/speakers.h"
120 #include "ardour/template_utils.h"
121 #include "ardour/tempo.h"
122 #include "ardour/ticker.h"
123 #include "ardour/user_bundle.h"
124 #include "ardour/vca.h"
125 #include "ardour/vca_manager.h"
127 #include "control_protocol/control_protocol.h"
129 #include "LuaBridge/LuaBridge.h"
135 using namespace ARDOUR;
138 #define DEBUG_UNDO_HISTORY(msg) DEBUG_TRACE (PBD::DEBUG::UndoHistory, string_compose ("%1: %2\n", __LINE__, msg));
141 Session::pre_engine_init (string fullpath)
143 if (fullpath.empty()) {
145 throw failed_constructor();
148 /* discover canonical fullpath */
150 _path = canonical_path(fullpath);
153 if (Profile->get_trx() ) {
154 // Waves TracksLive has a usecase of session replacement with a new one.
155 // We should check session state file (<session_name>.ardour) existance
156 // to determine if the session is new or not
158 string full_session_name = Glib::build_filename( fullpath, _name );
159 full_session_name += statefile_suffix;
161 _is_new = !Glib::file_test (full_session_name, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
163 _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
166 /* finish initialization that can't be done in a normal C++ constructor
170 timerclear (&last_mmc_step);
171 g_atomic_int_set (&processing_prohibited, 0);
172 g_atomic_int_set (&_record_status, Disabled);
173 g_atomic_int_set (&_playback_load, 100);
174 g_atomic_int_set (&_capture_load, 100);
176 _all_route_group->set_active (true, this);
177 interpolation.add_channel_to (0, 0);
178 _vca_manager = new VCAManager (*this);
180 if (config.get_use_video_sync()) {
181 waiting_for_sync_offset = true;
183 waiting_for_sync_offset = false;
186 last_rr_session_dir = session_dirs.begin();
188 set_history_depth (Config->get_history_depth());
190 /* default: assume simple stereo speaker configuration */
192 _speakers->setup_default_speakers (2);
194 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
195 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
196 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
197 add_controllable (_solo_cut_control);
199 /* These are all static "per-class" signals */
201 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
202 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
203 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
204 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
205 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
207 /* stop IO objects from doing stuff until we're ready for them */
209 Delivery::disable_panners ();
210 IO::disable_connecting ();
214 Session::post_engine_init ()
216 BootMessage (_("Set block size and sample rate"));
218 set_block_size (_engine.samples_per_cycle());
219 set_frame_rate (_engine.sample_rate());
221 BootMessage (_("Using configuration"));
223 _midi_ports = new MidiPortManager;
225 MIDISceneChanger* msc;
227 _scene_changer = msc = new MIDISceneChanger (*this);
228 msc->set_input_port (boost::dynamic_pointer_cast<MidiPort>(scene_input_port()));
229 msc->set_output_port (boost::dynamic_pointer_cast<MidiPort>(scene_output_port()));
231 boost::function<framecnt_t(void)> timer_func (boost::bind (&Session::audible_frame, this));
232 boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_input_port())->set_timer (timer_func);
234 setup_midi_machine_control ();
236 if (_butler->start_thread()) {
240 if (start_midi_thread ()) {
244 setup_click_sounds (0);
245 setup_midi_control ();
247 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
248 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
251 /* tempo map requires sample rate knowledge */
254 _tempo_map = new TempoMap (_current_frame_rate);
255 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
256 _tempo_map->MetricPositionChanged.connect_same_thread (*this, boost::bind (&Session::gui_tempo_map_changed, this));
258 /* MidiClock requires a tempo map */
261 midi_clock = new MidiClockTicker ();
262 midi_clock->set_session (this);
264 /* crossfades require sample rate knowledge */
266 SndFileSource::setup_standard_crossfades (*this, frame_rate());
267 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
269 AudioDiskstream::allocate_working_buffers();
270 refresh_disk_space ();
272 /* we're finally ready to call set_state() ... all objects have
273 * been created, the engine is running.
277 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
281 // set_state() will call setup_raid_path(), but if it's a new session we need
282 // to call setup_raid_path() here.
283 setup_raid_path (_path);
288 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
289 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
291 Config->map_parameters (ff);
292 config.map_parameters (ft);
293 _butler->map_parameters ();
295 /* Reset all panners */
297 Delivery::reset_panners ();
299 /* this will cause the CPM to instantiate any protocols that are in use
300 * (or mandatory), which will pass it this Session, and then call
301 * set_state() on each instantiated protocol to match stored state.
304 ControlProtocolManager::instance().set_session (this);
306 /* This must be done after the ControlProtocolManager set_session above,
307 as it will set states for ports which the ControlProtocolManager creates.
310 // XXX set state of MIDI::Port's
311 // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
313 /* And this must be done after the MIDI::Manager::set_port_states as
314 * it will try to make connections whose details are loaded by set_port_states.
319 /* Let control protocols know that we are now all connected, so they
320 * could start talking to surfaces if they want to.
323 ControlProtocolManager::instance().midi_connectivity_established ();
325 if (_is_new && !no_auto_connect()) {
326 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
327 auto_connect_master_bus ();
330 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
332 /* update latencies */
334 initialize_latencies ();
336 _locations->added.connect_same_thread (*this, boost::bind (&Session::location_added, this, _1));
337 _locations->removed.connect_same_thread (*this, boost::bind (&Session::location_removed, this, _1));
338 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
340 } catch (AudioEngine::PortRegistrationFailure& err) {
341 /* handle this one in a different way than all others, so that its clear what happened */
342 error << err.what() << endmsg;
348 BootMessage (_("Reset Remote Controls"));
350 // send_full_time_code (0);
351 _engine.transport_locate (0);
353 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
354 send_immediate_mmc (MIDI::MachineControlCommand (Timecode::Time ()));
356 MIDI::Name::MidiPatchManager::instance().add_search_path (session_directory().midi_patch_path() );
359 /* initial program change will be delivered later; see ::config_changed() */
361 _state_of_the_state = Clean;
363 Port::set_connecting_blocked (false);
365 DirtyChanged (); /* EMIT SIGNAL */
369 } else if (state_was_pending) {
371 remove_pending_capture_state ();
372 state_was_pending = false;
375 /* Now, finally, we can fill the playback buffers */
377 BootMessage (_("Filling playback buffers"));
379 boost::shared_ptr<RouteList> rl = routes.reader();
380 for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
381 boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<Track> (*r);
382 if (trk && !trk->hidden()) {
383 trk->seek (_transport_frame, true);
391 Session::session_loaded ()
395 _state_of_the_state = Clean;
397 DirtyChanged (); /* EMIT SIGNAL */
401 } else if (state_was_pending) {
403 remove_pending_capture_state ();
404 state_was_pending = false;
407 /* Now, finally, we can fill the playback buffers */
409 BootMessage (_("Filling playback buffers"));
410 force_locate (_transport_frame, false);
414 Session::raid_path () const
416 Searchpath raid_search_path;
418 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
419 raid_search_path += (*i).path;
422 return raid_search_path.to_string ();
426 Session::setup_raid_path (string path)
435 session_dirs.clear ();
437 Searchpath search_path(path);
438 Searchpath sound_search_path;
439 Searchpath midi_search_path;
441 for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
443 sp.blocks = 0; // not needed
444 session_dirs.push_back (sp);
446 SessionDirectory sdir(sp.path);
448 sound_search_path += sdir.sound_path ();
449 midi_search_path += sdir.midi_path ();
452 // reset the round-robin soundfile path thingie
453 last_rr_session_dir = session_dirs.begin();
457 Session::path_is_within_session (const std::string& path)
459 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
460 if (PBD::path_is_within (i->path, path)) {
468 Session::ensure_subdirs ()
472 dir = session_directory().peak_path();
474 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
475 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
479 dir = session_directory().sound_path();
481 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
482 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
486 dir = session_directory().midi_path();
488 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
489 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
493 dir = session_directory().dead_path();
495 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
496 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
500 dir = session_directory().export_path();
502 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
503 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
507 dir = analysis_dir ();
509 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
510 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
514 dir = plugins_dir ();
516 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
517 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
521 dir = externals_dir ();
523 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
524 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
531 /** @param session_template directory containing session template, or empty.
532 * Caller must not hold process lock.
535 Session::create (const string& session_template, BusProfile* bus_profile)
537 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
538 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
542 if (ensure_subdirs ()) {
546 _writable = exists_and_writable (_path);
548 if (!session_template.empty()) {
549 string in_path = (ARDOUR::Profile->get_trx () ? session_template : session_template_dir_to_file (session_template));
551 FILE* in = g_fopen (in_path.c_str(), "rb");
554 /* no need to call legalize_for_path() since the string
555 * in session_template is already a legal path name
557 string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
559 FILE* out = g_fopen (out_path.c_str(), "wb");
563 stringstream new_session;
566 size_t charsRead = fread (buf, sizeof(char), 1024, in);
569 error << string_compose (_("Error reading session template file %1 (%2)"), in_path, strerror (errno)) << endmsg;
574 if (charsRead == 0) {
577 new_session.write (buf, charsRead);
581 string file_contents = new_session.str();
582 size_t writeSize = file_contents.length();
583 if (fwrite (file_contents.c_str(), sizeof(char), writeSize, out) != writeSize) {
584 error << string_compose (_("Error writing session template file %1 (%2)"), out_path, strerror (errno)) << endmsg;
592 if (!ARDOUR::Profile->get_trx()) {
593 /* Copy plugin state files from template to new session */
594 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
595 copy_recurse (template_plugins, plugins_dir ());
601 error << string_compose (_("Could not open %1 for writing session template"), out_path)
608 error << string_compose (_("Could not open session template %1 for reading"), in_path)
615 if (Profile->get_trx()) {
617 /* set initial start + end point : ARDOUR::Session::session_end_shift long.
618 Remember that this is a brand new session. Sessions
619 loaded from saved state will get this range from the saved state.
622 set_session_range_location (0, 0);
624 /* Initial loop location, from absolute zero, length 10 seconds */
626 Location* loc = new Location (*this, 0, 10.0 * _engine.sample_rate(), _("Loop"), Location::IsAutoLoop);
627 _locations->add (loc, true);
628 set_auto_loop_location (loc);
631 _state_of_the_state = Clean;
633 /* set up Master Out and Monitor Out if necessary */
638 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
640 // Waves Tracks: always create master bus for Tracks
641 if (ARDOUR::Profile->get_trx() || bus_profile->master_out_channels) {
642 boost::shared_ptr<Route> r (new Route (*this, _("Master"), PresentationInfo::MasterOut, DataType::AUDIO));
650 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
651 r->input()->ensure_io (count, false, this);
652 r->output()->ensure_io (count, false, this);
658 /* prohibit auto-connect to master, because there isn't one */
659 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
663 add_routes (rl, false, false, false, PresentationInfo::max_order);
666 // Waves Tracks: Skip this. Always use autoconnection for Tracks
667 if (!ARDOUR::Profile->get_trx()) {
669 /* this allows the user to override settings with an environment variable.
672 if (no_auto_connect()) {
673 bus_profile->input_ac = AutoConnectOption (0);
674 bus_profile->output_ac = AutoConnectOption (0);
677 Config->set_input_auto_connect (bus_profile->input_ac);
678 Config->set_output_auto_connect (bus_profile->output_ac);
682 if (Config->get_use_monitor_bus() && bus_profile) {
683 add_monitor_section ();
690 Session::maybe_write_autosave()
692 if (dirty() && record_status() != Recording) {
693 save_state("", true);
698 Session::remove_pending_capture_state ()
700 std::string pending_state_file_path(_session_dir->root_path());
702 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
704 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
706 if (g_remove (pending_state_file_path.c_str()) != 0) {
707 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
708 pending_state_file_path, g_strerror (errno)) << endmsg;
712 /** Rename a state file.
713 * @param old_name Old snapshot name.
714 * @param new_name New snapshot name.
717 Session::rename_state (string old_name, string new_name)
719 if (old_name == _current_snapshot_name || old_name == _name) {
720 /* refuse to rename the current snapshot or the "main" one */
724 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
725 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
727 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
728 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
730 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
731 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
732 old_name, new_name, g_strerror(errno)) << endmsg;
736 /** Remove a state file.
737 * @param snapshot_name Snapshot name.
740 Session::remove_state (string snapshot_name)
742 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
743 // refuse to remove the current snapshot or the "main" one
747 std::string xml_path(_session_dir->root_path());
749 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
751 if (!create_backup_file (xml_path)) {
752 // don't remove it if a backup can't be made
753 // create_backup_file will log the error.
758 if (g_remove (xml_path.c_str()) != 0) {
759 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
760 xml_path, g_strerror (errno)) << endmsg;
764 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
766 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot, bool template_only)
768 DEBUG_TRACE (DEBUG::Locale, string_compose ("Session::save_state locale '%1'\n", setlocale (LC_NUMERIC, NULL)));
771 std::string xml_path(_session_dir->root_path());
773 /* prevent concurrent saves from different threads */
775 Glib::Threads::Mutex::Lock lm (save_state_lock);
777 if (!_writable || (_state_of_the_state & CannotSave)) {
781 if (g_atomic_int_get(&_suspend_save)) {
785 _save_queued = false;
787 if (!_engine.connected ()) {
788 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
795 const int64_t save_start_time = g_get_monotonic_time();
798 /* tell sources we're saving first, in case they write out to a new file
799 * which should be saved with the state rather than the old one */
800 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
802 i->second->session_saved();
803 } catch (Evoral::SMF::FileError& e) {
804 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
808 SessionSaveUnderway (); /* EMIT SIGNAL */
810 bool mark_as_clean = true;
812 if (!snapshot_name.empty() && !switch_to_snapshot) {
813 mark_as_clean = false;
817 mark_as_clean = false;
818 tree.set_root (&get_template());
820 tree.set_root (&get_state());
823 if (snapshot_name.empty()) {
824 snapshot_name = _current_snapshot_name;
825 } else if (switch_to_snapshot) {
826 set_snapshot_name (snapshot_name);
829 assert (!snapshot_name.empty());
833 /* proper save: use statefile_suffix (.ardour in English) */
835 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
837 /* make a backup copy of the old file */
839 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
840 // create_backup_file will log the error
846 /* pending save: use pending_suffix (.pending in English) */
847 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
850 std::string tmp_path(_session_dir->root_path());
851 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
853 cerr << "actually writing state to " << tmp_path << endl;
855 if (!tree.write (tmp_path)) {
856 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
857 if (g_remove (tmp_path.c_str()) != 0) {
858 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
859 tmp_path, g_strerror (errno)) << endmsg;
865 cerr << "renaming state to " << xml_path << endl;
867 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
868 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
869 tmp_path, xml_path, g_strerror(errno)) << endmsg;
870 if (g_remove (tmp_path.c_str()) != 0) {
871 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
872 tmp_path, g_strerror (errno)) << endmsg;
880 save_history (snapshot_name);
883 bool was_dirty = dirty();
885 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
888 DirtyChanged (); /* EMIT SIGNAL */
892 StateSaved (snapshot_name); /* EMIT SIGNAL */
896 const int64_t elapsed_time_us = g_get_monotonic_time() - save_start_time;
897 cerr << "saved state in " << fixed << setprecision (1) << elapsed_time_us / 1000. << " ms\n";
903 Session::restore_state (string snapshot_name)
905 if (load_state (snapshot_name) == 0) {
906 set_state (*state_tree->root(), Stateful::loading_state_version);
913 Session::load_state (string snapshot_name)
918 state_was_pending = false;
920 /* check for leftover pending state from a crashed capture attempt */
922 std::string xmlpath(_session_dir->root_path());
923 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
925 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
927 /* there is pending state from a crashed capture attempt */
929 boost::optional<int> r = AskAboutPendingState();
930 if (r.get_value_or (1)) {
931 state_was_pending = true;
935 if (!state_was_pending) {
936 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
939 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
940 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
941 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
942 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
947 state_tree = new XMLTree;
951 _writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
953 if (!state_tree->read (xmlpath)) {
954 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
960 XMLNode const & root (*state_tree->root());
962 if (root.name() != X_("Session")) {
963 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
969 XMLProperty const * prop;
971 if ((prop = root.property ("version")) == 0) {
972 /* no version implies very old version of Ardour */
973 Stateful::loading_state_version = 1000;
975 if (prop->value().find ('.') != string::npos) {
976 /* old school version format */
977 if (prop->value()[0] == '2') {
978 Stateful::loading_state_version = 2000;
980 Stateful::loading_state_version = 3000;
983 Stateful::loading_state_version = atoi (prop->value());
987 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
989 std::string backup_path(_session_dir->root_path());
990 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
991 backup_path = Glib::build_filename (backup_path, backup_filename);
993 // only create a backup for a given statefile version once
995 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
997 VersionMismatch (xmlpath, backup_path);
999 if (!copy_file (xmlpath, backup_path)) {;
1005 save_snapshot_name (snapshot_name);
1011 Session::load_options (const XMLNode& node)
1014 config.set_variables (node);
1019 Session::save_default_options ()
1021 return config.save_state();
1025 Session::get_state()
1031 Session::get_template()
1033 /* if we don't disable rec-enable, diskstreams
1034 will believe they need to store their capture
1035 sources in their state node.
1038 disable_record (false);
1040 return state(false);
1044 Session::state (bool full_state)
1047 XMLNode* node = new XMLNode("Session");
1051 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
1052 node->add_property("version", buf);
1054 /* store configuration settings */
1058 node->add_property ("name", _name);
1059 snprintf (buf, sizeof (buf), "%" PRId64, _base_frame_rate);
1060 node->add_property ("sample-rate", buf);
1062 if (session_dirs.size() > 1) {
1066 vector<space_and_path>::iterator i = session_dirs.begin();
1067 vector<space_and_path>::iterator next;
1069 ++i; /* skip the first one */
1073 while (i != session_dirs.end()) {
1077 if (next != session_dirs.end()) {
1078 p += G_SEARCHPATH_SEPARATOR;
1087 child = node->add_child ("Path");
1088 child->add_content (p);
1092 /* save the ID counter */
1094 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1095 node->add_property ("id-counter", buf);
1097 snprintf (buf, sizeof (buf), "%u", name_id_counter ());
1098 node->add_property ("name-counter", buf);
1100 /* save the event ID counter */
1102 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1103 node->add_property ("event-counter", buf);
1105 /* save the VCA counter */
1107 snprintf (buf, sizeof (buf), "%" PRIu32, VCA::get_next_vca_number());
1108 node->add_property ("vca-counter", buf);
1110 /* various options */
1112 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
1113 if (!midi_port_nodes.empty()) {
1114 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
1115 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
1116 midi_port_stuff->add_child_nocopy (**n);
1118 node->add_child_nocopy (*midi_port_stuff);
1121 node->add_child_nocopy (config.get_variables ());
1123 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1125 child = node->add_child ("Sources");
1128 Glib::Threads::Mutex::Lock sl (source_lock);
1130 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1132 /* Don't save information about non-file Sources, or
1133 * about non-destructive file sources that are empty
1134 * and unused by any regions.
1137 boost::shared_ptr<FileSource> fs;
1139 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1141 if (!fs->destructive()) {
1142 if (fs->empty() && !fs->used()) {
1147 child->add_child_nocopy (siter->second->get_state());
1152 child = node->add_child ("Regions");
1155 Glib::Threads::Mutex::Lock rl (region_lock);
1156 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1157 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1158 boost::shared_ptr<Region> r = i->second;
1159 /* only store regions not attached to playlists */
1160 if (r->playlist() == 0) {
1161 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1162 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1164 child->add_child_nocopy (r->get_state ());
1169 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1171 if (!cassocs.empty()) {
1172 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1174 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1176 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1177 i->first->id().print (buf, sizeof (buf));
1178 can->add_property (X_("copy"), buf);
1179 i->second->id().print (buf, sizeof (buf));
1180 can->add_property (X_("original"), buf);
1181 ca->add_child_nocopy (*can);
1191 node->add_child_nocopy (_locations->get_state());
1194 Locations loc (*this);
1195 // for a template, just create a new Locations, populate it
1196 // with the default start and end, and get the state for that.
1197 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1198 range->set (max_framepos, 0);
1200 XMLNode& locations_state = loc.get_state();
1202 if (ARDOUR::Profile->get_trx() && _locations) {
1203 // For tracks we need stored the Auto Loop Range and all MIDI markers.
1204 for (Locations::LocationList::const_iterator i = _locations->list ().begin (); i != _locations->list ().end (); ++i) {
1205 if ((*i)->is_mark () || (*i)->is_auto_loop ()) {
1206 locations_state.add_child_nocopy ((*i)->get_state ());
1210 node->add_child_nocopy (locations_state);
1213 child = node->add_child ("Bundles");
1215 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1216 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1217 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1219 child->add_child_nocopy (b->get_state());
1224 node->add_child_nocopy (_vca_manager->get_state());
1226 child = node->add_child ("Routes");
1228 boost::shared_ptr<RouteList> r = routes.reader ();
1230 RoutePublicOrderSorter cmp;
1231 RouteList public_order (*r);
1232 public_order.sort (cmp);
1234 /* the sort should have put control outs first */
1237 assert (_monitor_out == public_order.front());
1240 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1241 if (!(*i)->is_auditioner()) {
1243 child->add_child_nocopy ((*i)->get_state());
1245 child->add_child_nocopy ((*i)->get_template());
1251 playlists->add_state (node, full_state);
1253 child = node->add_child ("RouteGroups");
1254 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1255 child->add_child_nocopy ((*i)->get_state());
1259 XMLNode* gain_child = node->add_child ("Click");
1260 gain_child->add_child_nocopy (_click_io->state (full_state));
1261 gain_child->add_child_nocopy (_click_gain->state (full_state));
1265 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1266 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1270 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1271 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1274 node->add_child_nocopy (_speakers->get_state());
1275 node->add_child_nocopy (_tempo_map->get_state());
1276 node->add_child_nocopy (get_control_protocol_state());
1279 node->add_child_copy (*_extra_xml);
1283 Glib::Threads::Mutex::Lock lm (lua_lock);
1286 luabridge::LuaRef savedstate ((*_lua_save)());
1287 saved = savedstate.cast<std::string>();
1289 lua.collect_garbage ();
1292 gchar* b64 = g_base64_encode ((const guchar*)saved.c_str (), saved.size ());
1293 std::string b64s (b64);
1296 XMLNode* script_node = new XMLNode (X_("Script"));
1297 script_node->add_property (X_("lua"), LUA_VERSION);
1298 script_node->add_content (b64s);
1299 node->add_child_nocopy (*script_node);
1306 Session::get_control_protocol_state ()
1308 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1309 return cpm.get_state();
1313 Session::set_state (const XMLNode& node, int version)
1318 XMLProperty const * prop;
1321 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1323 if (node.name() != X_("Session")) {
1324 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1328 if ((prop = node.property ("name")) != 0) {
1329 _name = prop->value ();
1332 if ((prop = node.property (X_("sample-rate"))) != 0) {
1334 _base_frame_rate = atoi (prop->value());
1335 _nominal_frame_rate = _base_frame_rate;
1337 assert (AudioEngine::instance()->running ());
1338 if (_base_frame_rate != AudioEngine::instance()->sample_rate ()) {
1339 boost::optional<int> r = AskAboutSampleRateMismatch (_base_frame_rate, _current_frame_rate);
1340 if (r.get_value_or (0)) {
1346 setup_raid_path(_session_dir->root_path());
1348 if ((prop = node.property (X_("id-counter"))) != 0) {
1350 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1351 ID::init_counter (x);
1353 /* old sessions used a timebased counter, so fake
1354 the startup ID counter based on a standard
1359 ID::init_counter (now);
1362 if ((prop = node.property (X_("name-counter"))) != 0) {
1363 init_name_id_counter (atoi (prop->value()));
1366 if ((prop = node.property (X_("event-counter"))) != 0) {
1367 Evoral::init_event_id_counter (atoi (prop->value()));
1370 if ((prop = node.property (X_("vca-counter"))) != 0) {
1372 sscanf (prop->value().c_str(), "%" PRIu32, &x);
1373 VCA::set_next_vca_number (x);
1375 VCA::set_next_vca_number (1);
1378 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1379 _midi_ports->set_midi_port_states (child->children());
1382 IO::disable_connecting ();
1384 Stateful::save_extra_xml (node);
1386 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1387 load_options (*child);
1388 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1389 load_options (*child);
1391 error << _("Session: XML state has no options section") << endmsg;
1394 if (version >= 3000) {
1395 if ((child = find_named_node (node, "Metadata")) == 0) {
1396 warning << _("Session: XML state has no metadata section") << endmsg;
1397 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1402 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1403 _speakers->set_state (*child, version);
1406 if ((child = find_named_node (node, "Sources")) == 0) {
1407 error << _("Session: XML state has no sources section") << endmsg;
1409 } else if (load_sources (*child)) {
1413 if ((child = find_named_node (node, "TempoMap")) == 0) {
1414 error << _("Session: XML state has no Tempo Map section") << endmsg;
1416 } else if (_tempo_map->set_state (*child, version)) {
1420 if ((child = find_named_node (node, "Locations")) == 0) {
1421 error << _("Session: XML state has no locations section") << endmsg;
1423 } else if (_locations->set_state (*child, version)) {
1427 locations_changed ();
1429 if (_session_range_location) {
1430 AudioFileSource::set_header_position_offset (_session_range_location->start());
1433 if ((child = find_named_node (node, "Regions")) == 0) {
1434 error << _("Session: XML state has no Regions section") << endmsg;
1436 } else if (load_regions (*child)) {
1440 if ((child = find_named_node (node, "Playlists")) == 0) {
1441 error << _("Session: XML state has no playlists section") << endmsg;
1443 } else if (playlists->load (*this, *child)) {
1447 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1449 } else if (playlists->load_unused (*this, *child)) {
1453 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1454 if (load_compounds (*child)) {
1459 if (version >= 3000) {
1460 if ((child = find_named_node (node, "Bundles")) == 0) {
1461 warning << _("Session: XML state has no bundles section") << endmsg;
1464 /* We can't load Bundles yet as they need to be able
1465 to convert from port names to Port objects, which can't happen until
1467 _bundle_xml_node = new XMLNode (*child);
1471 if (version < 3000) {
1472 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1473 error << _("Session: XML state has no diskstreams section") << endmsg;
1475 } else if (load_diskstreams_2X (*child, version)) {
1480 if ((child = find_named_node (node, VCAManager::xml_node_name)) != 0) {
1481 _vca_manager->set_state (*child, version);
1484 if ((child = find_named_node (node, "Routes")) == 0) {
1485 error << _("Session: XML state has no routes section") << endmsg;
1487 } else if (load_routes (*child, version)) {
1491 /* Now that we have Routes and masters loaded, connect them if appropriate */
1493 Slavable::Assign (_vca_manager); /* EMIT SIGNAL */
1495 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1496 _diskstreams_2X.clear ();
1498 if (version >= 3000) {
1500 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1501 error << _("Session: XML state has no route groups section") << endmsg;
1503 } else if (load_route_groups (*child, version)) {
1507 } else if (version < 3000) {
1509 if ((child = find_named_node (node, "EditGroups")) == 0) {
1510 error << _("Session: XML state has no edit groups section") << endmsg;
1512 } else if (load_route_groups (*child, version)) {
1516 if ((child = find_named_node (node, "MixGroups")) == 0) {
1517 error << _("Session: XML state has no mix groups section") << endmsg;
1519 } else if (load_route_groups (*child, version)) {
1524 if ((child = find_named_node (node, "Click")) == 0) {
1525 warning << _("Session: XML state has no click section") << endmsg;
1526 } else if (_click_io) {
1527 setup_click_state (&node);
1530 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1531 ControlProtocolManager::instance().set_state (*child, version);
1534 if ((child = find_named_node (node, "Script"))) {
1535 for (XMLNodeList::const_iterator n = child->children ().begin (); n != child->children ().end (); ++n) {
1536 if (!(*n)->is_content ()) { continue; }
1538 guchar* buf = g_base64_decode ((*n)->content ().c_str (), &size);
1540 Glib::Threads::Mutex::Lock lm (lua_lock);
1541 (*_lua_load)(std::string ((const char*)buf, size));
1542 } catch (luabridge::LuaException const& e) {
1543 cerr << "LuaException:" << e.what () << endl;
1549 update_route_record_state ();
1551 /* here beginneth the second phase ... */
1552 set_snapshot_name (_current_snapshot_name);
1554 StateReady (); /* EMIT SIGNAL */
1567 Session::load_routes (const XMLNode& node, int version)
1570 XMLNodeConstIterator niter;
1571 RouteList new_routes;
1573 nlist = node.children();
1577 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1579 boost::shared_ptr<Route> route;
1580 if (version < 3000) {
1581 route = XMLRouteFactory_2X (**niter, version);
1583 route = XMLRouteFactory (**niter, version);
1587 error << _("Session: cannot create Route from XML description.") << endmsg;
1591 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1593 new_routes.push_back (route);
1596 BootMessage (_("Tracks/busses loaded; Adding to Session"));
1598 add_routes (new_routes, false, false, false, PresentationInfo::max_order);
1600 BootMessage (_("Finished adding tracks/busses"));
1605 boost::shared_ptr<Route>
1606 Session::XMLRouteFactory (const XMLNode& node, int version)
1608 boost::shared_ptr<Route> ret;
1610 if (node.name() != "Route") {
1614 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1616 DataType type = DataType::AUDIO;
1617 XMLProperty const * prop = node.property("default-type");
1620 type = DataType (prop->value());
1623 assert (type != DataType::NIL);
1627 boost::shared_ptr<Track> track;
1629 if (type == DataType::AUDIO) {
1630 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1632 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1635 if (track->init()) {
1639 if (track->set_state (node, version)) {
1643 BOOST_MARK_TRACK (track);
1647 PresentationInfo::Flag flags = PresentationInfo::get_flags (node);
1648 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1650 if (r->init () == 0 && r->set_state (node, version) == 0) {
1651 BOOST_MARK_ROUTE (r);
1659 boost::shared_ptr<Route>
1660 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1662 boost::shared_ptr<Route> ret;
1664 if (node.name() != "Route") {
1668 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1670 ds_prop = node.property (X_("diskstream"));
1673 DataType type = DataType::AUDIO;
1674 XMLProperty const * prop = node.property("default-type");
1677 type = DataType (prop->value());
1680 assert (type != DataType::NIL);
1684 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1685 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1689 if (i == _diskstreams_2X.end()) {
1690 error << _("Could not find diskstream for route") << endmsg;
1691 return boost::shared_ptr<Route> ();
1694 boost::shared_ptr<Track> track;
1696 if (type == DataType::AUDIO) {
1697 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1699 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1702 if (track->init()) {
1706 if (track->set_state (node, version)) {
1710 track->set_diskstream (*i);
1712 BOOST_MARK_TRACK (track);
1716 PresentationInfo::Flag flags = PresentationInfo::get_flags (node);
1717 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1719 if (r->init () == 0 && r->set_state (node, version) == 0) {
1720 BOOST_MARK_ROUTE (r);
1729 Session::load_regions (const XMLNode& node)
1732 XMLNodeConstIterator niter;
1733 boost::shared_ptr<Region> region;
1735 nlist = node.children();
1739 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1740 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1741 error << _("Session: cannot create Region from XML description.");
1742 XMLProperty const * name = (**niter).property("name");
1745 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1756 Session::load_compounds (const XMLNode& node)
1758 XMLNodeList calist = node.children();
1759 XMLNodeConstIterator caiter;
1760 XMLProperty const * caprop;
1762 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1763 XMLNode* ca = *caiter;
1767 if ((caprop = ca->property (X_("original"))) == 0) {
1770 orig_id = caprop->value();
1772 if ((caprop = ca->property (X_("copy"))) == 0) {
1775 copy_id = caprop->value();
1777 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1778 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1780 if (!orig || !copy) {
1781 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1787 RegionFactory::add_compound_association (orig, copy);
1794 Session::load_nested_sources (const XMLNode& node)
1797 XMLNodeConstIterator niter;
1799 nlist = node.children();
1801 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1802 if ((*niter)->name() == "Source") {
1804 /* it may already exist, so don't recreate it unnecessarily
1807 XMLProperty const * prop = (*niter)->property (X_("id"));
1809 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1813 ID source_id (prop->value());
1815 if (!source_by_id (source_id)) {
1818 SourceFactory::create (*this, **niter, true);
1820 catch (failed_constructor& err) {
1821 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1828 boost::shared_ptr<Region>
1829 Session::XMLRegionFactory (const XMLNode& node, bool full)
1831 XMLProperty const * type = node.property("type");
1835 const XMLNodeList& nlist = node.children();
1837 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1838 XMLNode *child = (*niter);
1839 if (child->name() == "NestedSource") {
1840 load_nested_sources (*child);
1844 if (!type || type->value() == "audio") {
1845 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1846 } else if (type->value() == "midi") {
1847 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1850 } catch (failed_constructor& err) {
1851 return boost::shared_ptr<Region> ();
1854 return boost::shared_ptr<Region> ();
1857 boost::shared_ptr<AudioRegion>
1858 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1860 XMLProperty const * prop;
1861 boost::shared_ptr<Source> source;
1862 boost::shared_ptr<AudioSource> as;
1864 SourceList master_sources;
1865 uint32_t nchans = 1;
1868 if (node.name() != X_("Region")) {
1869 return boost::shared_ptr<AudioRegion>();
1872 if ((prop = node.property (X_("channels"))) != 0) {
1873 nchans = atoi (prop->value().c_str());
1876 if ((prop = node.property ("name")) == 0) {
1877 cerr << "no name for this region\n";
1881 if ((prop = node.property (X_("source-0"))) == 0) {
1882 if ((prop = node.property ("source")) == 0) {
1883 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1884 return boost::shared_ptr<AudioRegion>();
1888 PBD::ID s_id (prop->value());
1890 if ((source = source_by_id (s_id)) == 0) {
1891 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1892 return boost::shared_ptr<AudioRegion>();
1895 as = boost::dynamic_pointer_cast<AudioSource>(source);
1897 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1898 return boost::shared_ptr<AudioRegion>();
1901 sources.push_back (as);
1903 /* pickup other channels */
1905 for (uint32_t n=1; n < nchans; ++n) {
1906 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1907 if ((prop = node.property (buf)) != 0) {
1909 PBD::ID id2 (prop->value());
1911 if ((source = source_by_id (id2)) == 0) {
1912 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1913 return boost::shared_ptr<AudioRegion>();
1916 as = boost::dynamic_pointer_cast<AudioSource>(source);
1918 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1919 return boost::shared_ptr<AudioRegion>();
1921 sources.push_back (as);
1925 for (uint32_t n = 0; n < nchans; ++n) {
1926 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1927 if ((prop = node.property (buf)) != 0) {
1929 PBD::ID id2 (prop->value());
1931 if ((source = source_by_id (id2)) == 0) {
1932 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1933 return boost::shared_ptr<AudioRegion>();
1936 as = boost::dynamic_pointer_cast<AudioSource>(source);
1938 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1939 return boost::shared_ptr<AudioRegion>();
1941 master_sources.push_back (as);
1946 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1948 /* a final detail: this is the one and only place that we know how long missing files are */
1950 if (region->whole_file()) {
1951 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1952 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1954 sfp->set_length (region->length());
1959 if (!master_sources.empty()) {
1960 if (master_sources.size() != nchans) {
1961 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1963 region->set_master_sources (master_sources);
1971 catch (failed_constructor& err) {
1972 return boost::shared_ptr<AudioRegion>();
1976 boost::shared_ptr<MidiRegion>
1977 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1979 XMLProperty const * prop;
1980 boost::shared_ptr<Source> source;
1981 boost::shared_ptr<MidiSource> ms;
1984 if (node.name() != X_("Region")) {
1985 return boost::shared_ptr<MidiRegion>();
1988 if ((prop = node.property ("name")) == 0) {
1989 cerr << "no name for this region\n";
1993 if ((prop = node.property (X_("source-0"))) == 0) {
1994 if ((prop = node.property ("source")) == 0) {
1995 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1996 return boost::shared_ptr<MidiRegion>();
2000 PBD::ID s_id (prop->value());
2002 if ((source = source_by_id (s_id)) == 0) {
2003 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
2004 return boost::shared_ptr<MidiRegion>();
2007 ms = boost::dynamic_pointer_cast<MidiSource>(source);
2009 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
2010 return boost::shared_ptr<MidiRegion>();
2013 sources.push_back (ms);
2016 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
2017 /* a final detail: this is the one and only place that we know how long missing files are */
2019 if (region->whole_file()) {
2020 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
2021 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
2023 sfp->set_length (region->length());
2031 catch (failed_constructor& err) {
2032 return boost::shared_ptr<MidiRegion>();
2037 Session::get_sources_as_xml ()
2040 XMLNode* node = new XMLNode (X_("Sources"));
2041 Glib::Threads::Mutex::Lock lm (source_lock);
2043 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2044 node->add_child_nocopy (i->second->get_state());
2051 Session::reset_write_sources (bool mark_write_complete, bool force)
2053 boost::shared_ptr<RouteList> rl = routes.reader();
2054 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
2055 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
2057 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
2058 tr->reset_write_sources(mark_write_complete, force);
2059 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
2065 Session::load_sources (const XMLNode& node)
2068 XMLNodeConstIterator niter;
2069 boost::shared_ptr<Source> source; /* don't need this but it stops some
2070 * versions of gcc complaining about
2071 * discarded return values.
2074 nlist = node.children();
2078 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2081 if ((source = XMLSourceFactory (**niter)) == 0) {
2082 error << _("Session: cannot create Source from XML description.") << endmsg;
2085 } catch (MissingSource& err) {
2089 if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
2090 error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
2091 PROGRAM_NAME) << endmsg;
2095 if (!no_questions_about_missing_files) {
2096 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
2101 switch (user_choice) {
2103 /* user added a new search location, so try again */
2108 /* user asked to quit the entire session load
2113 no_questions_about_missing_files = true;
2117 no_questions_about_missing_files = true;
2124 case DataType::AUDIO:
2125 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
2128 case DataType::MIDI:
2129 /* The MIDI file is actually missing so
2130 * just create a new one in the same
2131 * location. Do not announce its
2135 if (!Glib::path_is_absolute (err.path)) {
2136 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
2138 /* this should be an unrecoverable error: we would be creating a MIDI file outside
2143 /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
2144 source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
2145 /* reset ID to match the missing one */
2146 source->set_id (**niter);
2147 /* Now we can announce it */
2148 SourceFactory::SourceCreated (source);
2159 boost::shared_ptr<Source>
2160 Session::XMLSourceFactory (const XMLNode& node)
2162 if (node.name() != "Source") {
2163 return boost::shared_ptr<Source>();
2167 /* note: do peak building in another thread when loading session state */
2168 return SourceFactory::create (*this, node, true);
2171 catch (failed_constructor& err) {
2172 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
2173 return boost::shared_ptr<Source>();
2178 Session::save_template (string template_name, bool replace_existing)
2180 if ((_state_of_the_state & CannotSave) || template_name.empty ()) {
2184 bool absolute_path = Glib::path_is_absolute (template_name);
2186 /* directory to put the template in */
2187 std::string template_dir_path;
2189 if (!absolute_path) {
2190 std::string user_template_dir(user_template_directory());
2192 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2193 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2194 user_template_dir, g_strerror (errno)) << endmsg;
2198 template_dir_path = Glib::build_filename (user_template_dir, template_name);
2200 template_dir_path = template_name;
2203 if (!ARDOUR::Profile->get_trx()) {
2204 if (!replace_existing && Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2205 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2206 template_dir_path) << endmsg;
2210 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2211 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2212 template_dir_path, g_strerror (errno)) << endmsg;
2218 std::string template_file_path;
2220 if (ARDOUR::Profile->get_trx()) {
2221 template_file_path = template_name;
2223 if (absolute_path) {
2224 template_file_path = Glib::build_filename (template_dir_path, Glib::path_get_basename (template_dir_path) + template_suffix);
2226 template_file_path = Glib::build_filename (template_dir_path, template_name + template_suffix);
2230 SessionSaveUnderway (); /* EMIT SIGNAL */
2235 PBD::Unwinder<std::string> uw (_template_state_dir, template_dir_path);
2236 tree.set_root (&get_template());
2239 if (!tree.write (template_file_path)) {
2240 error << _("template not saved") << endmsg;
2244 store_recent_templates (template_file_path);
2250 Session::refresh_disk_space ()
2252 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2254 Glib::Threads::Mutex::Lock lm (space_lock);
2256 /* get freespace on every FS that is part of the session path */
2258 _total_free_4k_blocks = 0;
2259 _total_free_4k_blocks_uncertain = false;
2261 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2263 struct statfs statfsbuf;
2264 statfs (i->path.c_str(), &statfsbuf);
2266 double const scale = statfsbuf.f_bsize / 4096.0;
2268 /* See if this filesystem is read-only */
2269 struct statvfs statvfsbuf;
2270 statvfs (i->path.c_str(), &statvfsbuf);
2272 /* f_bavail can be 0 if it is undefined for whatever
2273 filesystem we are looking at; Samba shares mounted
2274 via GVFS are an example of this.
2276 if (statfsbuf.f_bavail == 0) {
2277 /* block count unknown */
2279 i->blocks_unknown = true;
2280 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2281 /* read-only filesystem */
2283 i->blocks_unknown = false;
2285 /* read/write filesystem with known space */
2286 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2287 i->blocks_unknown = false;
2290 _total_free_4k_blocks += i->blocks;
2291 if (i->blocks_unknown) {
2292 _total_free_4k_blocks_uncertain = true;
2295 #elif defined PLATFORM_WINDOWS
2296 vector<string> scanned_volumes;
2297 vector<string>::iterator j;
2298 vector<space_and_path>::iterator i;
2299 DWORD nSectorsPerCluster, nBytesPerSector,
2300 nFreeClusters, nTotalClusters;
2304 _total_free_4k_blocks = 0;
2306 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2307 strncpy (disk_drive, (*i).path.c_str(), 3);
2311 volume_found = false;
2312 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2314 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2315 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2316 i->blocks = (uint32_t)(nFreeBytes / 4096);
2318 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2319 if (0 == j->compare(disk_drive)) {
2320 volume_found = true;
2325 if (!volume_found) {
2326 scanned_volumes.push_back(disk_drive);
2327 _total_free_4k_blocks += i->blocks;
2332 if (0 == _total_free_4k_blocks) {
2333 strncpy (disk_drive, path().c_str(), 3);
2336 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2338 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2339 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2340 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2347 Session::get_best_session_directory_for_new_audio ()
2349 vector<space_and_path>::iterator i;
2350 string result = _session_dir->root_path();
2352 /* handle common case without system calls */
2354 if (session_dirs.size() == 1) {
2358 /* OK, here's the algorithm we're following here:
2360 We want to select which directory to use for
2361 the next file source to be created. Ideally,
2362 we'd like to use a round-robin process so as to
2363 get maximum performance benefits from splitting
2364 the files across multiple disks.
2366 However, in situations without much diskspace, an
2367 RR approach may end up filling up a filesystem
2368 with new files while others still have space.
2369 Its therefore important to pay some attention to
2370 the freespace in the filesystem holding each
2371 directory as well. However, if we did that by
2372 itself, we'd keep creating new files in the file
2373 system with the most space until it was as full
2374 as all others, thus negating any performance
2375 benefits of this RAID-1 like approach.
2377 So, we use a user-configurable space threshold. If
2378 there are at least 2 filesystems with more than this
2379 much space available, we use RR selection between them.
2380 If not, then we pick the filesystem with the most space.
2382 This gets a good balance between the two
2386 refresh_disk_space ();
2388 int free_enough = 0;
2390 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2391 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2396 if (free_enough >= 2) {
2397 /* use RR selection process, ensuring that the one
2401 i = last_rr_session_dir;
2404 if (++i == session_dirs.end()) {
2405 i = session_dirs.begin();
2408 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2409 SessionDirectory sdir(i->path);
2410 if (sdir.create ()) {
2412 last_rr_session_dir = i;
2417 } while (i != last_rr_session_dir);
2421 /* pick FS with the most freespace (and that
2422 seems to actually work ...)
2425 vector<space_and_path> sorted;
2426 space_and_path_ascending_cmp cmp;
2428 sorted = session_dirs;
2429 sort (sorted.begin(), sorted.end(), cmp);
2431 for (i = sorted.begin(); i != sorted.end(); ++i) {
2432 SessionDirectory sdir(i->path);
2433 if (sdir.create ()) {
2435 last_rr_session_dir = i;
2445 Session::automation_dir () const
2447 return Glib::build_filename (_path, automation_dir_name);
2451 Session::analysis_dir () const
2453 return Glib::build_filename (_path, analysis_dir_name);
2457 Session::plugins_dir () const
2459 return Glib::build_filename (_path, plugins_dir_name);
2463 Session::externals_dir () const
2465 return Glib::build_filename (_path, externals_dir_name);
2469 Session::load_bundles (XMLNode const & node)
2471 XMLNodeList nlist = node.children();
2472 XMLNodeConstIterator niter;
2476 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2477 if ((*niter)->name() == "InputBundle") {
2478 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2479 } else if ((*niter)->name() == "OutputBundle") {
2480 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2482 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2491 Session::load_route_groups (const XMLNode& node, int version)
2493 XMLNodeList nlist = node.children();
2494 XMLNodeConstIterator niter;
2498 if (version >= 3000) {
2500 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2501 if ((*niter)->name() == "RouteGroup") {
2502 RouteGroup* rg = new RouteGroup (*this, "");
2503 add_route_group (rg);
2504 rg->set_state (**niter, version);
2508 } else if (version < 3000) {
2510 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2511 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2512 RouteGroup* rg = new RouteGroup (*this, "");
2513 add_route_group (rg);
2514 rg->set_state (**niter, version);
2523 state_file_filter (const string &str, void* /*arg*/)
2525 return (str.length() > strlen(statefile_suffix) &&
2526 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2530 remove_end(string state)
2532 string statename(state);
2534 string::size_type start,end;
2535 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2536 statename = statename.substr (start+1);
2539 if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2540 end = statename.length();
2543 return string(statename.substr (0, end));
2547 Session::possible_states (string path)
2549 vector<string> states;
2550 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2552 transform(states.begin(), states.end(), states.begin(), remove_end);
2554 sort (states.begin(), states.end());
2560 Session::possible_states () const
2562 return possible_states(_path);
2566 Session::add_route_group (RouteGroup* g)
2568 _route_groups.push_back (g);
2569 route_group_added (g); /* EMIT SIGNAL */
2571 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2572 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2573 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2579 Session::remove_route_group (RouteGroup& rg)
2581 list<RouteGroup*>::iterator i;
2583 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2584 _route_groups.erase (i);
2587 route_group_removed (); /* EMIT SIGNAL */
2591 /** Set a new order for our route groups, without adding or removing any.
2592 * @param groups Route group list in the new order.
2595 Session::reorder_route_groups (list<RouteGroup*> groups)
2597 _route_groups = groups;
2599 route_groups_reordered (); /* EMIT SIGNAL */
2605 Session::route_group_by_name (string name)
2607 list<RouteGroup *>::iterator i;
2609 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2610 if ((*i)->name() == name) {
2618 Session::all_route_group() const
2620 return *_all_route_group;
2624 Session::add_commands (vector<Command*> const & cmds)
2626 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2632 Session::add_command (Command* const cmd)
2634 assert (_current_trans);
2635 DEBUG_UNDO_HISTORY (
2636 string_compose ("Current Undo Transaction %1, adding command: %2",
2637 _current_trans->name (),
2639 _current_trans->add_command (cmd);
2642 PBD::StatefulDiffCommand*
2643 Session::add_stateful_diff_command (boost::shared_ptr<PBD::StatefulDestructible> sfd)
2645 PBD::StatefulDiffCommand* cmd = new PBD::StatefulDiffCommand (sfd);
2651 Session::begin_reversible_command (const string& name)
2653 begin_reversible_command (g_quark_from_string (name.c_str ()));
2656 /** Begin a reversible command using a GQuark to identify it.
2657 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2658 * but there must be as many begin...()s as there are commit...()s.
2661 Session::begin_reversible_command (GQuark q)
2663 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2664 to hold all the commands that are committed. This keeps the order of
2665 commands correct in the history.
2668 if (_current_trans == 0) {
2669 DEBUG_UNDO_HISTORY (string_compose (
2670 "Begin Reversible Command, new transaction: %1", g_quark_to_string (q)));
2672 /* start a new transaction */
2673 assert (_current_trans_quarks.empty ());
2674 _current_trans = new UndoTransaction();
2675 _current_trans->set_name (g_quark_to_string (q));
2677 DEBUG_UNDO_HISTORY (
2678 string_compose ("Begin Reversible Command, current transaction: %1",
2679 _current_trans->name ()));
2682 _current_trans_quarks.push_front (q);
2686 Session::abort_reversible_command ()
2688 if (_current_trans != 0) {
2689 DEBUG_UNDO_HISTORY (
2690 string_compose ("Abort Reversible Command: %1", _current_trans->name ()));
2691 _current_trans->clear();
2692 delete _current_trans;
2694 _current_trans_quarks.clear();
2699 Session::commit_reversible_command (Command *cmd)
2701 assert (_current_trans);
2702 assert (!_current_trans_quarks.empty ());
2707 DEBUG_UNDO_HISTORY (
2708 string_compose ("Current Undo Transaction %1, adding command: %2",
2709 _current_trans->name (),
2711 _current_trans->add_command (cmd);
2714 DEBUG_UNDO_HISTORY (
2715 string_compose ("Commit Reversible Command, current transaction: %1",
2716 _current_trans->name ()));
2718 _current_trans_quarks.pop_front ();
2720 if (!_current_trans_quarks.empty ()) {
2721 DEBUG_UNDO_HISTORY (
2722 string_compose ("Commit Reversible Command, transaction is not "
2723 "top-level, current transaction: %1",
2724 _current_trans->name ()));
2725 /* the transaction we're committing is not the top-level one */
2729 if (_current_trans->empty()) {
2730 /* no commands were added to the transaction, so just get rid of it */
2731 DEBUG_UNDO_HISTORY (
2732 string_compose ("Commit Reversible Command, No commands were "
2733 "added to current transaction: %1",
2734 _current_trans->name ()));
2735 delete _current_trans;
2740 gettimeofday (&now, 0);
2741 _current_trans->set_timestamp (now);
2743 _history.add (_current_trans);
2748 accept_all_audio_files (const string& path, void* /*arg*/)
2750 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2754 if (!AudioFileSource::safe_audio_file_extension (path)) {
2762 accept_all_midi_files (const string& path, void* /*arg*/)
2764 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2768 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2769 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2770 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2774 accept_all_state_files (const string& path, void* /*arg*/)
2776 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2780 std::string const statefile_ext (statefile_suffix);
2781 if (path.length() >= statefile_ext.length()) {
2782 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2789 Session::find_all_sources (string path, set<string>& result)
2794 if (!tree.read (path)) {
2798 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2803 XMLNodeConstIterator niter;
2805 nlist = node->children();
2809 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2811 XMLProperty const * prop;
2813 if ((prop = (*niter)->property (X_("type"))) == 0) {
2817 DataType type (prop->value());
2819 if ((prop = (*niter)->property (X_("name"))) == 0) {
2823 if (Glib::path_is_absolute (prop->value())) {
2824 /* external file, ignore */
2832 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2833 result.insert (found_path);
2841 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2843 vector<string> state_files;
2845 string this_snapshot_path;
2851 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2852 ripped = ripped.substr (0, ripped.length() - 1);
2855 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2857 if (state_files.empty()) {
2862 this_snapshot_path = _path;
2863 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2864 this_snapshot_path += statefile_suffix;
2866 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2868 if (exclude_this_snapshot && *i == this_snapshot_path) {
2872 if (find_all_sources (*i, result) < 0) {
2880 struct RegionCounter {
2881 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2882 AudioSourceList::iterator iter;
2883 boost::shared_ptr<Region> region;
2886 RegionCounter() : count (0) {}
2890 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2892 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2893 return r.get_value_or (1);
2897 Session::cleanup_regions ()
2899 bool removed = false;
2900 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2902 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2904 uint32_t used = playlists->region_use_count (i->second);
2906 if (used == 0 && !i->second->automatic ()) {
2907 boost::weak_ptr<Region> w = i->second;
2910 RegionFactory::map_remove (w);
2917 // re-check to remove parent references of compound regions
2918 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2919 if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2923 assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2924 if (0 == playlists->region_use_count (i->second)) {
2925 boost::weak_ptr<Region> w = i->second;
2927 RegionFactory::map_remove (w);
2934 /* dump the history list */
2941 Session::can_cleanup_peakfiles () const
2943 if (deletion_in_progress()) {
2946 if (!_writable || (_state_of_the_state & CannotSave)) {
2947 warning << _("Cannot cleanup peak-files for read-only session.") << endmsg;
2950 if (record_status() == Recording) {
2951 error << _("Cannot cleanup peak-files while recording") << endmsg;
2958 Session::cleanup_peakfiles ()
2960 Glib::Threads::Mutex::Lock lm (peak_cleanup_lock, Glib::Threads::TRY_LOCK);
2965 assert (can_cleanup_peakfiles ());
2966 assert (!peaks_cleanup_in_progres());
2968 _state_of_the_state = StateOfTheState (_state_of_the_state | PeakCleanup);
2970 int timeout = 5000; // 5 seconds
2971 while (!SourceFactory::files_with_peaks.empty()) {
2972 Glib::usleep (1000);
2973 if (--timeout < 0) {
2974 warning << _("Timeout waiting for peak-file creation to terminate before cleanup, please try again later.") << endmsg;
2975 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
2980 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2981 boost::shared_ptr<AudioSource> as;
2982 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
2983 as->close_peakfile();
2987 PBD::clear_directory (session_directory().peak_path());
2989 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
2991 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2992 boost::shared_ptr<AudioSource> as;
2993 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
2994 SourceFactory::setup_peakfile(as, true);
3001 Session::cleanup_sources (CleanupReport& rep)
3003 // FIXME: needs adaptation to midi
3005 vector<boost::shared_ptr<Source> > dead_sources;
3008 vector<string> candidates;
3009 vector<string> unused;
3010 set<string> all_sources;
3019 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
3021 /* this is mostly for windows which doesn't allow file
3022 * renaming if the file is in use. But we don't special
3023 * case it because we need to know if this causes
3024 * problems, and the easiest way to notice that is to
3025 * keep it in place for all platforms.
3028 request_stop (false);
3030 _butler->wait_until_finished ();
3032 /* consider deleting all unused playlists */
3034 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
3039 /* sync the "all regions" property of each playlist with its current state
3042 playlists->sync_all_regions_with_regions ();
3044 /* find all un-used sources */
3049 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3051 SourceMap::iterator tmp;
3056 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
3060 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
3061 dead_sources.push_back (i->second);
3062 i->second->drop_references ();
3068 /* build a list of all the possible audio directories for the session */
3070 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3071 SessionDirectory sdir ((*i).path);
3072 asp += sdir.sound_path();
3074 audio_path += asp.to_string();
3077 /* build a list of all the possible midi directories for the session */
3079 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3080 SessionDirectory sdir ((*i).path);
3081 msp += sdir.midi_path();
3083 midi_path += msp.to_string();
3085 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
3086 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
3088 /* find all sources, but don't use this snapshot because the
3089 state file on disk still references sources we may have already
3093 find_all_sources_across_snapshots (all_sources, true);
3095 /* add our current source list
3098 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3099 boost::shared_ptr<FileSource> fs;
3100 SourceMap::iterator tmp = i;
3103 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
3105 /* this is mostly for windows which doesn't allow file
3106 * renaming if the file is in use. But we don't special
3107 * case it because we need to know if this causes
3108 * problems, and the easiest way to notice that is to
3109 * keep it in place for all platforms.
3114 if (!fs->is_stub()) {
3116 if (playlists->source_use_count (fs) != 0) {
3117 all_sources.insert (fs->path());
3120 /* we might not remove this source from disk, because it may be used
3121 by other snapshots, but its not being used in this version
3122 so lets get rid of it now, along with any representative regions
3126 RegionFactory::remove_regions_using_source (i->second);
3128 // also remove source from all_sources
3130 for (set<string>::iterator j = all_sources.begin(); j != all_sources.end(); ++j) {
3131 spath = Glib::path_get_basename (*j);
3132 if (spath == i->second->name()) {
3133 all_sources.erase (j);
3146 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
3151 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
3153 tmppath1 = canonical_path (spath);
3154 tmppath2 = canonical_path ((*i));
3156 if (tmppath1 == tmppath2) {
3163 unused.push_back (spath);
3167 /* now try to move all unused files into the "dead" directory(ies) */
3169 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
3174 /* don't move the file across filesystems, just
3175 stick it in the `dead_dir_name' directory
3176 on whichever filesystem it was already on.
3179 if ((*x).find ("/sounds/") != string::npos) {
3181 /* old school, go up 1 level */
3183 newpath = Glib::path_get_dirname (*x); // "sounds"
3184 newpath = Glib::path_get_dirname (newpath); // "session-name"
3188 /* new school, go up 4 levels */
3190 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
3191 newpath = Glib::path_get_dirname (newpath); // "session-name"
3192 newpath = Glib::path_get_dirname (newpath); // "interchange"
3193 newpath = Glib::path_get_dirname (newpath); // "session-dir"
3196 newpath = Glib::build_filename (newpath, dead_dir_name);
3198 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
3199 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
3203 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
3205 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
3207 /* the new path already exists, try versioning */
3209 char buf[PATH_MAX+1];
3213 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3216 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
3217 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3221 if (version == 999) {
3222 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3226 newpath = newpath_v;
3231 /* it doesn't exist, or we can't read it or something */
3235 g_stat ((*x).c_str(), &statbuf);
3237 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3238 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
3239 (*x), newpath, strerror (errno))
3244 /* see if there an easy to find peakfile for this file, and remove it.
3247 string base = Glib::path_get_basename (*x);
3248 base += "%A"; /* this is what we add for the channel suffix of all native files,
3249 or for the first channel of embedded files. it will miss
3250 some peakfiles for other channels
3252 string peakpath = construct_peak_filepath (base);
3254 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
3255 if (::g_unlink (peakpath.c_str()) != 0) {
3256 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3257 peakpath, _path, strerror (errno))
3259 /* try to back out */
3260 ::rename (newpath.c_str(), _path.c_str());
3265 rep.paths.push_back (*x);
3266 rep.space += statbuf.st_size;
3269 /* dump the history list */
3273 /* save state so we don't end up a session file
3274 referring to non-existent sources.
3281 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3287 Session::cleanup_trash_sources (CleanupReport& rep)
3289 // FIXME: needs adaptation for MIDI
3291 vector<space_and_path>::iterator i;
3297 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3299 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
3301 clear_directory (dead_dir, &rep.space, &rep.paths);
3308 Session::set_dirty ()
3310 /* never mark session dirty during loading */
3312 if (_state_of_the_state & Loading) {
3316 bool was_dirty = dirty();
3318 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3322 DirtyChanged(); /* EMIT SIGNAL */
3328 Session::set_clean ()
3330 bool was_dirty = dirty();
3332 _state_of_the_state = Clean;
3336 DirtyChanged(); /* EMIT SIGNAL */
3341 Session::set_deletion_in_progress ()
3343 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3347 Session::clear_deletion_in_progress ()
3349 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3353 Session::add_controllable (boost::shared_ptr<Controllable> c)
3355 /* this adds a controllable to the list managed by the Session.
3356 this is a subset of those managed by the Controllable class
3357 itself, and represents the only ones whose state will be saved
3358 as part of the session.
3361 Glib::Threads::Mutex::Lock lm (controllables_lock);
3362 controllables.insert (c);
3365 struct null_deleter { void operator()(void const *) const {} };
3368 Session::remove_controllable (Controllable* c)
3370 if (_state_of_the_state & Deletion) {
3374 Glib::Threads::Mutex::Lock lm (controllables_lock);
3376 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3378 if (x != controllables.end()) {
3379 controllables.erase (x);
3383 boost::shared_ptr<Controllable>
3384 Session::controllable_by_id (const PBD::ID& id)
3386 Glib::Threads::Mutex::Lock lm (controllables_lock);
3388 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3389 if ((*i)->id() == id) {
3394 return boost::shared_ptr<Controllable>();
3397 boost::shared_ptr<Controllable>
3398 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3400 boost::shared_ptr<Controllable> c;
3401 boost::shared_ptr<Stripable> s;
3402 boost::shared_ptr<Route> r;
3404 switch (desc.top_level_type()) {
3405 case ControllableDescriptor::NamedRoute:
3407 std::string str = desc.top_level_name();
3409 if (str == "Master" || str == "master") {
3411 } else if (str == "control" || str == "listen" || str == "monitor" || str == "Monitor") {
3413 } else if (str == "auditioner") {
3416 s = route_by_name (desc.top_level_name());
3422 case ControllableDescriptor::PresentationOrderRoute:
3423 s = get_remote_nth_stripable (desc.presentation_order(), PresentationInfo::Route);
3426 case ControllableDescriptor::PresentationOrderTrack:
3427 s = get_remote_nth_stripable (desc.presentation_order(), PresentationInfo::Track);
3430 case ControllableDescriptor::PresentationOrderBus:
3431 s = get_remote_nth_stripable (desc.presentation_order(), PresentationInfo::Bus);
3434 case ControllableDescriptor::PresentationOrderVCA:
3435 s = get_remote_nth_stripable (desc.presentation_order(), PresentationInfo::VCA);
3438 case ControllableDescriptor::SelectionCount:
3439 s = route_by_selected_count (desc.selection_id());
3447 r = boost::dynamic_pointer_cast<Route> (s);
3449 switch (desc.subtype()) {
3450 case ControllableDescriptor::Gain:
3451 c = s->gain_control ();
3454 case ControllableDescriptor::Trim:
3455 c = s->trim_control ();
3458 case ControllableDescriptor::Solo:
3459 c = s->solo_control();
3462 case ControllableDescriptor::Mute:
3463 c = s->mute_control();
3466 case ControllableDescriptor::Recenable:
3467 c = s->rec_enable_control ();
3470 case ControllableDescriptor::PanDirection:
3471 c = s->pan_azimuth_control();
3474 case ControllableDescriptor::PanWidth:
3475 c = s->pan_width_control();
3478 case ControllableDescriptor::PanElevation:
3479 c = s->pan_elevation_control();
3482 case ControllableDescriptor::Balance:
3483 /* XXX simple pan control */
3486 case ControllableDescriptor::PluginParameter:
3488 uint32_t plugin = desc.target (0);
3489 uint32_t parameter_index = desc.target (1);
3491 /* revert to zero based counting */
3497 if (parameter_index > 0) {
3505 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3508 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3509 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3514 case ControllableDescriptor::SendGain: {
3515 uint32_t send = desc.target (0);
3522 c = r->send_level_controllable (send);
3527 /* relax and return a null pointer */
3535 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3538 Stateful::add_instant_xml (node, _path);
3541 if (write_to_config) {
3542 Config->add_instant_xml (node);
3547 Session::instant_xml (const string& node_name)
3549 return Stateful::instant_xml (node_name, _path);
3553 Session::save_history (string snapshot_name)
3561 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3562 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3566 if (snapshot_name.empty()) {
3567 snapshot_name = _current_snapshot_name;
3570 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3571 const string backup_filename = history_filename + backup_suffix;
3572 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3573 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3575 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3576 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3577 error << _("could not backup old history file, current history not saved") << endmsg;
3582 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3584 if (!tree.write (xml_path))
3586 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3588 if (g_remove (xml_path.c_str()) != 0) {
3589 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3590 xml_path, g_strerror (errno)) << endmsg;
3592 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3593 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3594 backup_path, g_strerror (errno)) << endmsg;
3604 Session::restore_history (string snapshot_name)
3608 if (snapshot_name.empty()) {
3609 snapshot_name = _current_snapshot_name;
3612 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3613 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3615 info << "Loading history from " << xml_path << endmsg;
3617 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3618 info << string_compose (_("%1: no history file \"%2\" for this session."),
3619 _name, xml_path) << endmsg;
3623 if (!tree.read (xml_path)) {
3624 error << string_compose (_("Could not understand session history file \"%1\""),
3625 xml_path) << endmsg;
3632 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3635 UndoTransaction* ut = new UndoTransaction ();
3638 ut->set_name(t->property("name")->value());
3639 stringstream ss(t->property("tv-sec")->value());
3641 ss.str(t->property("tv-usec")->value());
3643 ut->set_timestamp(tv);
3645 for (XMLNodeConstIterator child_it = t->children().begin();
3646 child_it != t->children().end(); child_it++)
3648 XMLNode *n = *child_it;
3651 if (n->name() == "MementoCommand" ||
3652 n->name() == "MementoUndoCommand" ||
3653 n->name() == "MementoRedoCommand") {
3655 if ((c = memento_command_factory(n))) {
3659 } else if (n->name() == "NoteDiffCommand") {
3660 PBD::ID id (n->property("midi-source")->value());
3661 boost::shared_ptr<MidiSource> midi_source =
3662 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3664 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3666 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3669 } else if (n->name() == "SysExDiffCommand") {
3671 PBD::ID id (n->property("midi-source")->value());
3672 boost::shared_ptr<MidiSource> midi_source =
3673 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3675 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3677 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3680 } else if (n->name() == "PatchChangeDiffCommand") {
3682 PBD::ID id (n->property("midi-source")->value());
3683 boost::shared_ptr<MidiSource> midi_source =
3684 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3686 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3688 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3691 } else if (n->name() == "StatefulDiffCommand") {
3692 if ((c = stateful_diff_command_factory (n))) {
3693 ut->add_command (c);
3696 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3707 Session::config_changed (std::string p, bool ours)
3713 if (p == "seamless-loop") {
3715 } else if (p == "rf-speed") {
3717 } else if (p == "auto-loop") {
3719 } else if (p == "auto-input") {
3721 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3722 /* auto-input only makes a difference if we're rolling */
3723 set_track_monitor_input_status (!config.get_auto_input());
3726 } else if (p == "punch-in") {
3730 if ((location = _locations->auto_punch_location()) != 0) {
3732 if (config.get_punch_in ()) {
3733 replace_event (SessionEvent::PunchIn, location->start());
3735 remove_event (location->start(), SessionEvent::PunchIn);
3739 } else if (p == "punch-out") {
3743 if ((location = _locations->auto_punch_location()) != 0) {
3745 if (config.get_punch_out()) {
3746 replace_event (SessionEvent::PunchOut, location->end());
3748 clear_events (SessionEvent::PunchOut);
3752 } else if (p == "edit-mode") {
3754 Glib::Threads::Mutex::Lock lm (playlists->lock);
3756 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3757 (*i)->set_edit_mode (Config->get_edit_mode ());
3760 } else if (p == "use-video-sync") {
3762 waiting_for_sync_offset = config.get_use_video_sync();
3764 } else if (p == "mmc-control") {
3766 //poke_midi_thread ();
3768 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3770 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3772 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3774 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3776 } else if (p == "midi-control") {
3778 //poke_midi_thread ();
3780 } else if (p == "raid-path") {
3782 setup_raid_path (config.get_raid_path());
3784 } else if (p == "timecode-format") {
3788 } else if (p == "video-pullup") {
3792 } else if (p == "seamless-loop") {
3794 if (play_loop && transport_rolling()) {
3795 // to reset diskstreams etc
3796 request_play_loop (true);
3799 } else if (p == "rf-speed") {
3801 cumulative_rf_motion = 0;
3804 } else if (p == "click-sound") {
3806 setup_click_sounds (1);
3808 } else if (p == "click-emphasis-sound") {
3810 setup_click_sounds (-1);
3812 } else if (p == "clicking") {
3814 if (Config->get_clicking()) {
3815 if (_click_io && click_data) { // don't require emphasis data
3822 } else if (p == "click-gain") {
3825 _click_gain->gain_control()->set_value (Config->get_click_gain(), Controllable::NoGroup);
3828 } else if (p == "send-mtc") {
3830 if (Config->get_send_mtc ()) {
3831 /* mark us ready to send */
3832 next_quarter_frame_to_send = 0;
3835 } else if (p == "send-mmc") {
3837 _mmc->enable_send (Config->get_send_mmc ());
3839 } else if (p == "midi-feedback") {
3841 session_midi_feedback = Config->get_midi_feedback();
3843 } else if (p == "jack-time-master") {
3845 engine().reset_timebase ();
3847 } else if (p == "native-file-header-format") {
3849 if (!first_file_header_format_reset) {
3850 reset_native_file_format ();
3853 first_file_header_format_reset = false;
3855 } else if (p == "native-file-data-format") {
3857 if (!first_file_data_format_reset) {
3858 reset_native_file_format ();
3861 first_file_data_format_reset = false;
3863 } else if (p == "external-sync") {
3864 if (!config.get_external_sync()) {
3865 drop_sync_source ();
3867 switch_to_sync_source (Config->get_sync_source());
3869 } else if (p == "denormal-model") {
3871 } else if (p == "history-depth") {
3872 set_history_depth (Config->get_history_depth());
3873 } else if (p == "remote-model") {
3874 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3877 } else if (p == "initial-program-change") {
3879 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3882 buf[0] = MIDI::program; // channel zero by default
3883 buf[1] = (Config->get_initial_program_change() & 0x7f);
3885 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3887 } else if (p == "solo-mute-override") {
3888 // catch_up_on_solo_mute_override ();
3889 } else if (p == "listen-position" || p == "pfl-position") {
3890 listen_position_changed ();
3891 } else if (p == "solo-control-is-listen-control") {
3892 solo_control_mode_changed ();
3893 } else if (p == "solo-mute-gain") {
3894 _solo_cut_control->Changed (true, Controllable::NoGroup);
3895 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3896 last_timecode_valid = false;
3897 } else if (p == "playback-buffer-seconds") {
3898 AudioSource::allocate_working_buffers (frame_rate());
3899 } else if (p == "ltc-source-port") {
3900 reconnect_ltc_input ();
3901 } else if (p == "ltc-sink-port") {
3902 reconnect_ltc_output ();
3903 } else if (p == "timecode-generator-offset") {
3904 ltc_tx_parse_offset();
3905 } else if (p == "auto-return-target-list") {
3906 follow_playhead_priority ();
3913 Session::set_history_depth (uint32_t d)
3915 _history.set_depth (d);
3919 Session::load_diskstreams_2X (XMLNode const & node, int)
3922 XMLNodeConstIterator citer;
3924 clist = node.children();
3926 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3929 /* diskstreams added automatically by DiskstreamCreated handler */
3930 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3931 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3932 _diskstreams_2X.push_back (dsp);
3934 error << _("Session: unknown diskstream type in XML") << endmsg;
3938 catch (failed_constructor& err) {
3939 error << _("Session: could not load diskstream via XML state") << endmsg;
3947 /** Connect things to the MMC object */
3949 Session::setup_midi_machine_control ()
3951 _mmc = new MIDI::MachineControl;
3953 boost::shared_ptr<AsyncMIDIPort> async_in = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_input_port());
3954 boost::shared_ptr<AsyncMIDIPort> async_out = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_output_port());
3956 if (!async_out || !async_out) {
3960 /* XXXX argh, passing raw pointers back into libmidi++ */
3962 MIDI::Port* mmc_in = async_in.get();
3963 MIDI::Port* mmc_out = async_out.get();
3965 _mmc->set_ports (mmc_in, mmc_out);
3967 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3968 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3969 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3970 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3971 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3972 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3973 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3974 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3975 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3976 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3977 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3978 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3979 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3981 /* also handle MIDI SPP because its so common */
3983 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3984 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3985 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3988 boost::shared_ptr<Controllable>
3989 Session::solo_cut_control() const
3991 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3992 controls in Ardour that currently get presented to the user in the GUI that require
3993 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3995 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3996 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
4000 return _solo_cut_control;
4004 Session::save_snapshot_name (const std::string & n)
4006 /* assure Stateful::_instant_xml is loaded
4007 * add_instant_xml() only adds to existing data and defaults
4008 * to use an empty Tree otherwise
4010 instant_xml ("LastUsedSnapshot");
4012 XMLNode* last_used_snapshot = new XMLNode ("LastUsedSnapshot");
4013 last_used_snapshot->add_property ("name", string(n));
4014 add_instant_xml (*last_used_snapshot, false);
4018 Session::set_snapshot_name (const std::string & n)
4020 _current_snapshot_name = n;
4021 save_snapshot_name (n);
4025 Session::rename (const std::string& new_name)
4027 string legal_name = legalize_for_path (new_name);
4033 string const old_sources_root = _session_dir->sources_root();
4035 if (!_writable || (_state_of_the_state & CannotSave)) {
4036 error << _("Cannot rename read-only session.") << endmsg;
4037 return 0; // don't show "messed up" warning
4039 if (record_status() == Recording) {
4040 error << _("Cannot rename session while recording") << endmsg;
4041 return 0; // don't show "messed up" warning
4044 StateProtector stp (this);
4049 * interchange subdirectory
4053 * Backup files are left unchanged and not renamed.
4056 /* Windows requires that we close all files before attempting the
4057 * rename. This works on other platforms, but isn't necessary there.
4058 * Leave it in place for all platforms though, since it may help
4059 * catch issues that could arise if the way Source files work ever
4060 * change (since most developers are not using Windows).
4063 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4064 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4070 /* pass one: not 100% safe check that the new directory names don't
4074 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4078 /* this is a stupid hack because Glib::path_get_dirname() is
4079 * lexical-only, and so passing it /a/b/c/ gives a different
4080 * result than passing it /a/b/c ...
4083 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4084 oldstr = oldstr.substr (0, oldstr.length() - 1);
4087 string base = Glib::path_get_dirname (oldstr);
4089 newstr = Glib::build_filename (base, legal_name);
4091 cerr << "Looking for " << newstr << endl;
4093 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
4094 cerr << " exists\n";
4103 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4109 /* this is a stupid hack because Glib::path_get_dirname() is
4110 * lexical-only, and so passing it /a/b/c/ gives a different
4111 * result than passing it /a/b/c ...
4114 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4115 oldstr = oldstr.substr (0, oldstr.length() - 1);
4118 string base = Glib::path_get_dirname (oldstr);
4119 newstr = Glib::build_filename (base, legal_name);
4121 cerr << "for " << oldstr << " new dir = " << newstr << endl;
4123 cerr << "Rename " << oldstr << " => " << newstr << endl;
4124 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4125 cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4126 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4130 /* Reset path in "session dirs" */
4135 /* reset primary SessionDirectory object */
4138 (*_session_dir) = newstr;
4143 /* now rename directory below session_dir/interchange */
4145 string old_interchange_dir;
4146 string new_interchange_dir;
4148 /* use newstr here because we renamed the path
4149 * (folder/directory) that used to be oldstr to newstr above
4152 v.push_back (newstr);
4153 v.push_back (interchange_dir_name);
4154 v.push_back (Glib::path_get_basename (oldstr));
4156 old_interchange_dir = Glib::build_filename (v);
4159 v.push_back (newstr);
4160 v.push_back (interchange_dir_name);
4161 v.push_back (legal_name);
4163 new_interchange_dir = Glib::build_filename (v);
4165 cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
4167 if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
4168 cerr << string_compose (_("renaming %s as %2 failed (%3)"),
4169 old_interchange_dir, new_interchange_dir,
4172 error << string_compose (_("renaming %s as %2 failed (%3)"),
4173 old_interchange_dir, new_interchange_dir,
4182 oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
4183 newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
4185 cerr << "Rename " << oldstr << " => " << newstr << endl;
4187 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4188 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4189 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4195 oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
4197 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
4198 newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
4200 cerr << "Rename " << oldstr << " => " << newstr << endl;
4202 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4203 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4204 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4209 /* remove old name from recent sessions */
4210 remove_recent_sessions (_path);
4213 /* update file source paths */
4215 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
4216 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4218 string p = fs->path ();
4219 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
4221 SourceFactory::setup_peakfile(i->second, true);
4225 set_snapshot_name (new_name);
4230 /* save state again to get everything just right */
4232 save_state (_current_snapshot_name);
4234 /* add to recent sessions */
4236 store_recent_sessions (new_name, _path);
4242 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
4244 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
4248 if (!tree.read (xmlpath)) {
4256 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
4259 bool found_sr = false;
4260 bool found_data_format = false;
4262 if (get_session_info_from_path (tree, xmlpath)) {
4268 XMLProperty const * prop;
4269 XMLNode const * root (tree.root());
4271 if ((prop = root->property (X_("sample-rate"))) != 0) {
4272 sample_rate = atoi (prop->value());
4276 const XMLNodeList& children (root->children());
4277 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
4278 const XMLNode* child = *c;
4279 if (child->name() == "Config") {
4280 const XMLNodeList& options (child->children());
4281 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
4282 XMLNode const * option = *oc;
4283 XMLProperty const * name = option->property("name");
4289 if (name->value() == "native-file-data-format") {
4290 XMLProperty const * value = option->property ("value");
4292 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
4294 found_data_format = true;
4300 if (found_data_format) {
4305 return !(found_sr && found_data_format); // zero if they are both found
4309 Session::get_snapshot_from_instant (const std::string& session_dir)
4311 std::string instant_xml_path = Glib::build_filename (session_dir, "instant.xml");
4313 if (!Glib::file_test (instant_xml_path, Glib::FILE_TEST_EXISTS)) {
4318 if (!tree.read (instant_xml_path)) {
4322 XMLProperty const * prop;
4323 XMLNode *last_used_snapshot = tree.root()->child("LastUsedSnapshot");
4324 if (last_used_snapshot && (prop = last_used_snapshot->property ("name")) != 0) {
4325 return prop->value();
4331 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
4332 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
4335 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
4339 SourcePathMap source_path_map;
4341 boost::shared_ptr<AudioFileSource> afs;
4346 Glib::Threads::Mutex::Lock lm (source_lock);
4348 cerr << " total sources = " << sources.size();
4350 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4351 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4357 if (fs->within_session()) {
4361 if (source_path_map.find (fs->path()) != source_path_map.end()) {
4362 source_path_map[fs->path()].push_back (fs);
4364 SeveralFileSources v;
4366 source_path_map.insert (make_pair (fs->path(), v));
4372 cerr << " fsources = " << total << endl;
4374 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
4376 /* tell caller where we are */
4378 string old_path = i->first;
4380 callback (n, total, old_path);
4382 cerr << old_path << endl;
4386 switch (i->second.front()->type()) {
4387 case DataType::AUDIO:
4388 new_path = new_audio_source_path_for_embedded (old_path);
4391 case DataType::MIDI:
4392 /* XXX not implemented yet */
4396 if (new_path.empty()) {
4400 cerr << "Move " << old_path << " => " << new_path << endl;
4402 if (!copy_file (old_path, new_path)) {
4403 cerr << "failed !\n";
4407 /* make sure we stop looking in the external
4408 dir/folder. Remember, this is an all-or-nothing
4409 operations, it doesn't merge just some files.
4411 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
4413 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
4414 (*f)->set_path (new_path);
4419 save_state ("", false, false);
4425 bool accept_all_files (string const &, void *)
4431 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4433 /* 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.
4438 make_new_media_path (string old_path, string new_session_folder, string new_session_path)
4440 /* typedir is the "midifiles" or "audiofiles" etc. part of the path. */
4442 string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4444 v.push_back (new_session_folder); /* full path */
4445 v.push_back (interchange_dir_name);
4446 v.push_back (new_session_path); /* just one directory/folder */
4447 v.push_back (typedir);
4448 v.push_back (Glib::path_get_basename (old_path));
4450 return Glib::build_filename (v);
4454 Session::save_as (SaveAs& saveas)
4456 vector<string> files;
4457 string current_folder = Glib::path_get_dirname (_path);
4458 string new_folder = legalize_for_path (saveas.new_name);
4459 string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4460 int64_t total_bytes = 0;
4464 int32_t internal_file_cnt = 0;
4466 vector<string> do_not_copy_extensions;
4467 do_not_copy_extensions.push_back (statefile_suffix);
4468 do_not_copy_extensions.push_back (pending_suffix);
4469 do_not_copy_extensions.push_back (backup_suffix);
4470 do_not_copy_extensions.push_back (temp_suffix);
4471 do_not_copy_extensions.push_back (history_suffix);
4473 /* get total size */
4475 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4477 /* need to clear this because
4478 * find_files_matching_filter() is cumulative
4483 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4485 all += files.size();
4487 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4489 g_stat ((*i).c_str(), &gsb);
4490 total_bytes += gsb.st_size;
4494 /* save old values so we can switch back if we are not switching to the new session */
4496 string old_path = _path;
4497 string old_name = _name;
4498 string old_snapshot = _current_snapshot_name;
4499 string old_sd = _session_dir->root_path();
4500 vector<string> old_search_path[DataType::num_types];
4501 string old_config_search_path[DataType::num_types];
4503 old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4504 old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4505 old_config_search_path[DataType::AUDIO] = config.get_audio_search_path ();
4506 old_config_search_path[DataType::MIDI] = config.get_midi_search_path ();
4508 /* switch session directory */
4510 (*_session_dir) = to_dir;
4512 /* create new tree */
4514 if (!_session_dir->create()) {
4515 saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4520 /* copy all relevant files. Find each location in session_dirs,
4521 * and copy files from there to target.
4524 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4526 /* need to clear this because
4527 * find_files_matching_filter() is cumulative
4532 const size_t prefix_len = (*sd).path.size();
4534 /* Work just on the files within this session dir */
4536 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4538 /* add dir separator to protect against collisions with
4539 * track names (e.g. track named "audiofiles" or
4543 static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
4544 static const std::string midifile_dir_string = string (midi_dir_name) + G_DIR_SEPARATOR;
4545 static const std::string analysis_dir_string = analysis_dir() + G_DIR_SEPARATOR;
4547 /* copy all the files. Handling is different for media files
4548 than others because of the *silly* subtree we have below the interchange
4549 folder. That really was a bad idea, but I'm not fixing it as part of
4550 implementing ::save_as().
4553 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4555 std::string from = *i;
4558 string filename = Glib::path_get_basename (from);
4559 std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
4560 if (filename == ".DS_STORE") {
4565 if (from.find (audiofile_dir_string) != string::npos) {
4567 /* audio file: only copy if asked */
4569 if (saveas.include_media && saveas.copy_media) {
4571 string to = make_new_media_path (*i, to_dir, new_folder);
4573 info << "media file copying from " << from << " to " << to << endmsg;
4575 if (!copy_file (from, to)) {
4576 throw Glib::FileError (Glib::FileError::IO_ERROR,
4577 string_compose(_("\ncopying \"%1\" failed !"), from));
4581 /* we found media files inside the session folder */
4583 internal_file_cnt++;
4585 } else if (from.find (midifile_dir_string) != string::npos) {
4587 /* midi file: always copy unless
4588 * creating an empty new session
4591 if (saveas.include_media) {
4593 string to = make_new_media_path (*i, to_dir, new_folder);
4595 info << "media file copying from " << from << " to " << to << endmsg;
4597 if (!copy_file (from, to)) {
4598 throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4602 /* we found media files inside the session folder */
4604 internal_file_cnt++;
4606 } else if (from.find (analysis_dir_string) != string::npos) {
4608 /* make sure analysis dir exists in
4609 * new session folder, but we're not
4610 * copying analysis files here, see
4614 (void) g_mkdir_with_parents (analysis_dir().c_str(), 775);
4619 /* normal non-media file. Don't copy state, history, etc.
4622 bool do_copy = true;
4624 for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
4625 if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
4626 /* end of filename matches extension, do not copy file */
4632 if (!saveas.copy_media && from.find (peakfile_suffix) != string::npos) {
4633 /* don't copy peakfiles if
4634 * we're not copying media
4640 string to = Glib::build_filename (to_dir, from.substr (prefix_len));
4642 info << "attempting to make directory/folder " << to << endmsg;
4644 if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
4645 throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
4648 info << "attempting to copy " << from << " to " << to << endmsg;
4650 if (!copy_file (from, to)) {
4651 throw Glib::FileError (Glib::FileError::IO_ERROR,
4652 string_compose(_("\ncopying \"%1\" failed !"), from));
4657 /* measure file size even if we're not going to copy so that our Progress
4658 signals are correct, since we included these do-not-copy files
4659 in the computation of the total size and file count.
4663 g_stat (from.c_str(), &gsb);
4664 copied += gsb.st_size;
4667 double fraction = (double) copied / total_bytes;
4669 bool keep_going = true;
4671 if (saveas.copy_media) {
4673 /* no need or expectation of this if
4674 * media is not being copied, because
4675 * it will be fast(ish).
4678 /* tell someone "X percent, file M of N"; M is one-based */
4680 boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
4688 throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
4694 /* copy optional folders, if any */
4696 string old = plugins_dir ();
4697 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4698 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4699 copy_files (old, newdir);
4702 old = externals_dir ();
4703 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4704 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4705 copy_files (old, newdir);
4708 old = automation_dir ();
4709 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4710 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4711 copy_files (old, newdir);
4714 if (saveas.include_media) {
4716 if (saveas.copy_media) {
4717 #ifndef PLATFORM_WINDOWS
4718 /* There are problems with analysis files on
4719 * Windows, because they used a colon in their
4720 * names as late as 4.0. Colons are not legal
4721 * under Windows even if NTFS allows them.
4723 * This is a tricky problem to solve so for
4724 * just don't copy these files. They will be
4725 * regenerated as-needed anyway, subject to the
4726 * existing issue that the filenames will be
4727 * rejected by Windows, which is a separate
4728 * problem (though related).
4731 /* only needed if we are copying media, since the
4732 * analysis data refers to media data
4735 old = analysis_dir ();
4736 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4737 string newdir = Glib::build_filename (to_dir, "analysis");
4738 copy_files (old, newdir);
4740 #endif /* PLATFORM_WINDOWS */
4746 set_snapshot_name (saveas.new_name);
4747 _name = saveas.new_name;
4749 if (saveas.include_media && !saveas.copy_media) {
4751 /* reset search paths of the new session (which we're pretending to be right now) to
4752 include the original session search path, so we can still find all audio.
4755 if (internal_file_cnt) {
4756 for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
4757 ensure_search_path_includes (*s, DataType::AUDIO);
4758 cerr << "be sure to include " << *s << " for audio" << endl;
4761 /* we do not do this for MIDI because we copy
4762 all MIDI files if saveas.include_media is
4768 bool was_dirty = dirty ();
4770 save_state ("", false, false, !saveas.include_media);
4771 save_default_options ();
4773 if (saveas.copy_media && saveas.copy_external) {
4774 if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
4775 throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
4779 saveas.final_session_folder_name = _path;
4781 store_recent_sessions (_name, _path);
4783 if (!saveas.switch_to) {
4785 /* switch back to the way things were */
4789 set_snapshot_name (old_snapshot);
4791 (*_session_dir) = old_sd;
4797 if (internal_file_cnt) {
4798 /* reset these to their original values */
4799 config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
4800 config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
4805 /* prune session dirs, and update disk space statistics
4810 session_dirs.clear ();
4811 session_dirs.push_back (sp);
4812 refresh_disk_space ();
4814 /* ensure that all existing tracks reset their current capture source paths
4816 reset_write_sources (true, true);
4818 /* the copying above was based on actually discovering files, not just iterating over the sources list.
4819 But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
4822 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4823 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4829 if (fs->within_session()) {
4830 string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
4831 fs->set_path (newpath);
4836 } catch (Glib::FileError& e) {
4838 saveas.failure_message = e.what();
4840 /* recursively remove all the directories */
4842 remove_directory (to_dir);
4850 saveas.failure_message = _("unknown reason");
4852 /* recursively remove all the directories */
4854 remove_directory (to_dir);