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/revision.h"
110 #include "ardour/route_group.h"
111 #include "ardour/send.h"
112 #include "ardour/session.h"
113 #include "ardour/session_directory.h"
114 #include "ardour/session_metadata.h"
115 #include "ardour/session_playlists.h"
116 #include "ardour/session_state_utils.h"
117 #include "ardour/silentfilesource.h"
118 #include "ardour/sndfilesource.h"
119 #include "ardour/source_factory.h"
120 #include "ardour/speakers.h"
121 #include "ardour/template_utils.h"
122 #include "ardour/tempo.h"
123 #include "ardour/ticker.h"
124 #include "ardour/user_bundle.h"
125 #include "ardour/vca.h"
126 #include "ardour/vca_manager.h"
128 #include "control_protocol/control_protocol.h"
130 #include "LuaBridge/LuaBridge.h"
136 using namespace ARDOUR;
139 #define DEBUG_UNDO_HISTORY(msg) DEBUG_TRACE (PBD::DEBUG::UndoHistory, string_compose ("%1: %2\n", __LINE__, msg));
142 Session::pre_engine_init (string fullpath)
144 if (fullpath.empty()) {
146 throw failed_constructor();
149 /* discover canonical fullpath */
151 _path = canonical_path(fullpath);
154 if (Profile->get_trx() ) {
155 // Waves TracksLive has a usecase of session replacement with a new one.
156 // We should check session state file (<session_name>.ardour) existance
157 // to determine if the session is new or not
159 string full_session_name = Glib::build_filename( fullpath, _name );
160 full_session_name += statefile_suffix;
162 _is_new = !Glib::file_test (full_session_name, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
164 _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
167 /* finish initialization that can't be done in a normal C++ constructor
171 timerclear (&last_mmc_step);
172 g_atomic_int_set (&processing_prohibited, 0);
173 g_atomic_int_set (&_record_status, Disabled);
174 g_atomic_int_set (&_playback_load, 100);
175 g_atomic_int_set (&_capture_load, 100);
177 _all_route_group->set_active (true, this);
178 interpolation.add_channel_to (0, 0);
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 child = node->add_child ("ProgramVersion");
1055 child->add_property("created-with", created_with);
1057 std::string modified_with = string_compose ("%1 %2", PROGRAM_NAME, revision);
1058 child->add_property("modified-with", modified_with);
1060 /* store configuration settings */
1064 node->add_property ("name", _name);
1065 snprintf (buf, sizeof (buf), "%" PRId64, _base_frame_rate);
1066 node->add_property ("sample-rate", buf);
1068 if (session_dirs.size() > 1) {
1072 vector<space_and_path>::iterator i = session_dirs.begin();
1073 vector<space_and_path>::iterator next;
1075 ++i; /* skip the first one */
1079 while (i != session_dirs.end()) {
1083 if (next != session_dirs.end()) {
1084 p += G_SEARCHPATH_SEPARATOR;
1093 child = node->add_child ("Path");
1094 child->add_content (p);
1098 /* save the ID counter */
1100 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1101 node->add_property ("id-counter", buf);
1103 snprintf (buf, sizeof (buf), "%u", name_id_counter ());
1104 node->add_property ("name-counter", buf);
1106 /* save the event ID counter */
1108 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1109 node->add_property ("event-counter", buf);
1111 /* save the VCA counter */
1113 snprintf (buf, sizeof (buf), "%" PRIu32, VCA::get_next_vca_number());
1114 node->add_property ("vca-counter", buf);
1116 /* various options */
1118 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
1119 if (!midi_port_nodes.empty()) {
1120 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
1121 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
1122 midi_port_stuff->add_child_nocopy (**n);
1124 node->add_child_nocopy (*midi_port_stuff);
1127 node->add_child_nocopy (config.get_variables ());
1129 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1131 child = node->add_child ("Sources");
1134 Glib::Threads::Mutex::Lock sl (source_lock);
1136 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1138 /* Don't save information about non-file Sources, or
1139 * about non-destructive file sources that are empty
1140 * and unused by any regions.
1143 boost::shared_ptr<FileSource> fs;
1145 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1147 if (!fs->destructive()) {
1148 if (fs->empty() && !fs->used()) {
1153 child->add_child_nocopy (siter->second->get_state());
1158 child = node->add_child ("Regions");
1161 Glib::Threads::Mutex::Lock rl (region_lock);
1162 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1163 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1164 boost::shared_ptr<Region> r = i->second;
1165 /* only store regions not attached to playlists */
1166 if (r->playlist() == 0) {
1167 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1168 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1170 child->add_child_nocopy (r->get_state ());
1175 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1177 if (!cassocs.empty()) {
1178 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1180 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1182 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1183 i->first->id().print (buf, sizeof (buf));
1184 can->add_property (X_("copy"), buf);
1185 i->second->id().print (buf, sizeof (buf));
1186 can->add_property (X_("original"), buf);
1187 ca->add_child_nocopy (*can);
1197 node->add_child_nocopy (_locations->get_state());
1200 Locations loc (*this);
1201 // for a template, just create a new Locations, populate it
1202 // with the default start and end, and get the state for that.
1203 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1204 range->set (max_framepos, 0);
1206 XMLNode& locations_state = loc.get_state();
1208 if (ARDOUR::Profile->get_trx() && _locations) {
1209 // For tracks we need stored the Auto Loop Range and all MIDI markers.
1210 for (Locations::LocationList::const_iterator i = _locations->list ().begin (); i != _locations->list ().end (); ++i) {
1211 if ((*i)->is_mark () || (*i)->is_auto_loop ()) {
1212 locations_state.add_child_nocopy ((*i)->get_state ());
1216 node->add_child_nocopy (locations_state);
1219 child = node->add_child ("Bundles");
1221 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1222 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1223 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1225 child->add_child_nocopy (b->get_state());
1230 node->add_child_nocopy (_vca_manager->get_state());
1232 child = node->add_child ("Routes");
1234 boost::shared_ptr<RouteList> r = routes.reader ();
1236 RoutePublicOrderSorter cmp;
1237 RouteList public_order (*r);
1238 public_order.sort (cmp);
1240 /* the sort should have put the monitor out first */
1243 assert (_monitor_out == public_order.front());
1246 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1247 if (!(*i)->is_auditioner()) {
1249 child->add_child_nocopy ((*i)->get_state());
1251 child->add_child_nocopy ((*i)->get_template());
1257 playlists->add_state (node, full_state);
1259 child = node->add_child ("RouteGroups");
1260 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1261 child->add_child_nocopy ((*i)->get_state());
1265 XMLNode* gain_child = node->add_child ("Click");
1266 gain_child->add_child_nocopy (_click_io->state (full_state));
1267 gain_child->add_child_nocopy (_click_gain->state (full_state));
1271 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1272 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1276 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1277 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1280 node->add_child_nocopy (_speakers->get_state());
1281 node->add_child_nocopy (_tempo_map->get_state());
1282 node->add_child_nocopy (get_control_protocol_state());
1285 node->add_child_copy (*_extra_xml);
1289 Glib::Threads::Mutex::Lock lm (lua_lock);
1292 luabridge::LuaRef savedstate ((*_lua_save)());
1293 saved = savedstate.cast<std::string>();
1295 lua.collect_garbage ();
1298 gchar* b64 = g_base64_encode ((const guchar*)saved.c_str (), saved.size ());
1299 std::string b64s (b64);
1302 XMLNode* script_node = new XMLNode (X_("Script"));
1303 script_node->add_property (X_("lua"), LUA_VERSION);
1304 script_node->add_content (b64s);
1305 node->add_child_nocopy (*script_node);
1312 Session::get_control_protocol_state ()
1314 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1315 return cpm.get_state();
1319 Session::set_state (const XMLNode& node, int version)
1324 XMLProperty const * prop;
1327 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1329 if (node.name() != X_("Session")) {
1330 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1334 if ((prop = node.property ("name")) != 0) {
1335 _name = prop->value ();
1338 if ((prop = node.property (X_("sample-rate"))) != 0) {
1340 _base_frame_rate = atoi (prop->value());
1341 _nominal_frame_rate = _base_frame_rate;
1343 assert (AudioEngine::instance()->running ());
1344 if (_base_frame_rate != AudioEngine::instance()->sample_rate ()) {
1345 boost::optional<int> r = AskAboutSampleRateMismatch (_base_frame_rate, _current_frame_rate);
1346 if (r.get_value_or (0)) {
1352 created_with = "unknown";
1353 if ((child = find_named_node (node, "ProgramVersion")) != 0) {
1354 if ((prop = child->property (X_("created-with"))) != 0) {
1355 created_with = prop->value ();
1359 setup_raid_path(_session_dir->root_path());
1361 if ((prop = node.property (X_("id-counter"))) != 0) {
1363 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1364 ID::init_counter (x);
1366 /* old sessions used a timebased counter, so fake
1367 the startup ID counter based on a standard
1372 ID::init_counter (now);
1375 if ((prop = node.property (X_("name-counter"))) != 0) {
1376 init_name_id_counter (atoi (prop->value()));
1379 if ((prop = node.property (X_("event-counter"))) != 0) {
1380 Evoral::init_event_id_counter (atoi (prop->value()));
1383 if ((prop = node.property (X_("vca-counter"))) != 0) {
1385 sscanf (prop->value().c_str(), "%" PRIu32, &x);
1386 VCA::set_next_vca_number (x);
1388 VCA::set_next_vca_number (1);
1391 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1392 _midi_ports->set_midi_port_states (child->children());
1395 IO::disable_connecting ();
1397 Stateful::save_extra_xml (node);
1399 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1400 load_options (*child);
1401 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1402 load_options (*child);
1404 error << _("Session: XML state has no options section") << endmsg;
1407 if (version >= 3000) {
1408 if ((child = find_named_node (node, "Metadata")) == 0) {
1409 warning << _("Session: XML state has no metadata section") << endmsg;
1410 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1415 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1416 _speakers->set_state (*child, version);
1419 if ((child = find_named_node (node, "Sources")) == 0) {
1420 error << _("Session: XML state has no sources section") << endmsg;
1422 } else if (load_sources (*child)) {
1426 if ((child = find_named_node (node, "TempoMap")) == 0) {
1427 error << _("Session: XML state has no Tempo Map section") << endmsg;
1429 } else if (_tempo_map->set_state (*child, version)) {
1433 if ((child = find_named_node (node, "Locations")) == 0) {
1434 error << _("Session: XML state has no locations section") << endmsg;
1436 } else if (_locations->set_state (*child, version)) {
1440 locations_changed ();
1442 if (_session_range_location) {
1443 AudioFileSource::set_header_position_offset (_session_range_location->start());
1446 if ((child = find_named_node (node, "Regions")) == 0) {
1447 error << _("Session: XML state has no Regions section") << endmsg;
1449 } else if (load_regions (*child)) {
1453 if ((child = find_named_node (node, "Playlists")) == 0) {
1454 error << _("Session: XML state has no playlists section") << endmsg;
1456 } else if (playlists->load (*this, *child)) {
1460 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1462 } else if (playlists->load_unused (*this, *child)) {
1466 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1467 if (load_compounds (*child)) {
1472 if (version >= 3000) {
1473 if ((child = find_named_node (node, "Bundles")) == 0) {
1474 warning << _("Session: XML state has no bundles section") << endmsg;
1477 /* We can't load Bundles yet as they need to be able
1478 to convert from port names to Port objects, which can't happen until
1480 _bundle_xml_node = new XMLNode (*child);
1484 if (version < 3000) {
1485 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1486 error << _("Session: XML state has no diskstreams section") << endmsg;
1488 } else if (load_diskstreams_2X (*child, version)) {
1493 if ((child = find_named_node (node, VCAManager::xml_node_name)) != 0) {
1494 _vca_manager->set_state (*child, version);
1497 if ((child = find_named_node (node, "Routes")) == 0) {
1498 error << _("Session: XML state has no routes section") << endmsg;
1500 } else if (load_routes (*child, version)) {
1504 /* Now that we have Routes and masters loaded, connect them if appropriate */
1506 Slavable::Assign (_vca_manager); /* EMIT SIGNAL */
1508 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1509 _diskstreams_2X.clear ();
1511 if (version >= 3000) {
1513 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1514 error << _("Session: XML state has no route groups section") << endmsg;
1516 } else if (load_route_groups (*child, version)) {
1520 } else if (version < 3000) {
1522 if ((child = find_named_node (node, "EditGroups")) == 0) {
1523 error << _("Session: XML state has no edit groups section") << endmsg;
1525 } else if (load_route_groups (*child, version)) {
1529 if ((child = find_named_node (node, "MixGroups")) == 0) {
1530 error << _("Session: XML state has no mix groups section") << endmsg;
1532 } else if (load_route_groups (*child, version)) {
1537 if ((child = find_named_node (node, "Click")) == 0) {
1538 warning << _("Session: XML state has no click section") << endmsg;
1539 } else if (_click_io) {
1540 setup_click_state (&node);
1543 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1544 ControlProtocolManager::instance().set_state (*child, version);
1547 if ((child = find_named_node (node, "Script"))) {
1548 for (XMLNodeList::const_iterator n = child->children ().begin (); n != child->children ().end (); ++n) {
1549 if (!(*n)->is_content ()) { continue; }
1551 guchar* buf = g_base64_decode ((*n)->content ().c_str (), &size);
1553 Glib::Threads::Mutex::Lock lm (lua_lock);
1554 (*_lua_load)(std::string ((const char*)buf, size));
1555 } catch (luabridge::LuaException const& e) {
1556 cerr << "LuaException:" << e.what () << endl;
1562 update_route_record_state ();
1564 /* here beginneth the second phase ... */
1565 set_snapshot_name (_current_snapshot_name);
1567 StateReady (); /* EMIT SIGNAL */
1580 Session::load_routes (const XMLNode& node, int version)
1583 XMLNodeConstIterator niter;
1584 RouteList new_routes;
1586 nlist = node.children();
1590 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1592 boost::shared_ptr<Route> route;
1593 if (version < 3000) {
1594 route = XMLRouteFactory_2X (**niter, version);
1596 route = XMLRouteFactory (**niter, version);
1600 error << _("Session: cannot create Route from XML description.") << endmsg;
1604 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1606 new_routes.push_back (route);
1609 BootMessage (_("Tracks/busses loaded; Adding to Session"));
1611 add_routes (new_routes, false, false, false, PresentationInfo::max_order);
1613 BootMessage (_("Finished adding tracks/busses"));
1618 boost::shared_ptr<Route>
1619 Session::XMLRouteFactory (const XMLNode& node, int version)
1621 boost::shared_ptr<Route> ret;
1623 if (node.name() != "Route") {
1627 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1629 DataType type = DataType::AUDIO;
1630 XMLProperty const * prop = node.property("default-type");
1633 type = DataType (prop->value());
1636 assert (type != DataType::NIL);
1640 boost::shared_ptr<Track> track;
1642 if (type == DataType::AUDIO) {
1643 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1645 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1648 if (track->init()) {
1652 if (track->set_state (node, version)) {
1656 BOOST_MARK_TRACK (track);
1660 PresentationInfo::Flag flags = PresentationInfo::get_flags (node);
1661 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1663 if (r->init () == 0 && r->set_state (node, version) == 0) {
1664 BOOST_MARK_ROUTE (r);
1672 boost::shared_ptr<Route>
1673 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1675 boost::shared_ptr<Route> ret;
1677 if (node.name() != "Route") {
1681 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1683 ds_prop = node.property (X_("diskstream"));
1686 DataType type = DataType::AUDIO;
1687 XMLProperty const * prop = node.property("default-type");
1690 type = DataType (prop->value());
1693 assert (type != DataType::NIL);
1697 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1698 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1702 if (i == _diskstreams_2X.end()) {
1703 error << _("Could not find diskstream for route") << endmsg;
1704 return boost::shared_ptr<Route> ();
1707 boost::shared_ptr<Track> track;
1709 if (type == DataType::AUDIO) {
1710 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1712 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1715 if (track->init()) {
1719 if (track->set_state (node, version)) {
1723 track->set_diskstream (*i);
1725 BOOST_MARK_TRACK (track);
1729 PresentationInfo::Flag flags = PresentationInfo::get_flags (node);
1730 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1732 if (r->init () == 0 && r->set_state (node, version) == 0) {
1733 BOOST_MARK_ROUTE (r);
1742 Session::load_regions (const XMLNode& node)
1745 XMLNodeConstIterator niter;
1746 boost::shared_ptr<Region> region;
1748 nlist = node.children();
1752 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1753 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1754 error << _("Session: cannot create Region from XML description.");
1755 XMLProperty const * name = (**niter).property("name");
1758 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1769 Session::load_compounds (const XMLNode& node)
1771 XMLNodeList calist = node.children();
1772 XMLNodeConstIterator caiter;
1773 XMLProperty const * caprop;
1775 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1776 XMLNode* ca = *caiter;
1780 if ((caprop = ca->property (X_("original"))) == 0) {
1783 orig_id = caprop->value();
1785 if ((caprop = ca->property (X_("copy"))) == 0) {
1788 copy_id = caprop->value();
1790 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1791 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1793 if (!orig || !copy) {
1794 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1800 RegionFactory::add_compound_association (orig, copy);
1807 Session::load_nested_sources (const XMLNode& node)
1810 XMLNodeConstIterator niter;
1812 nlist = node.children();
1814 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1815 if ((*niter)->name() == "Source") {
1817 /* it may already exist, so don't recreate it unnecessarily
1820 XMLProperty const * prop = (*niter)->property (X_("id"));
1822 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1826 ID source_id (prop->value());
1828 if (!source_by_id (source_id)) {
1831 SourceFactory::create (*this, **niter, true);
1833 catch (failed_constructor& err) {
1834 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1841 boost::shared_ptr<Region>
1842 Session::XMLRegionFactory (const XMLNode& node, bool full)
1844 XMLProperty const * type = node.property("type");
1848 const XMLNodeList& nlist = node.children();
1850 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1851 XMLNode *child = (*niter);
1852 if (child->name() == "NestedSource") {
1853 load_nested_sources (*child);
1857 if (!type || type->value() == "audio") {
1858 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1859 } else if (type->value() == "midi") {
1860 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1863 } catch (failed_constructor& err) {
1864 return boost::shared_ptr<Region> ();
1867 return boost::shared_ptr<Region> ();
1870 boost::shared_ptr<AudioRegion>
1871 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1873 XMLProperty const * prop;
1874 boost::shared_ptr<Source> source;
1875 boost::shared_ptr<AudioSource> as;
1877 SourceList master_sources;
1878 uint32_t nchans = 1;
1881 if (node.name() != X_("Region")) {
1882 return boost::shared_ptr<AudioRegion>();
1885 if ((prop = node.property (X_("channels"))) != 0) {
1886 nchans = atoi (prop->value().c_str());
1889 if ((prop = node.property ("name")) == 0) {
1890 cerr << "no name for this region\n";
1894 if ((prop = node.property (X_("source-0"))) == 0) {
1895 if ((prop = node.property ("source")) == 0) {
1896 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1897 return boost::shared_ptr<AudioRegion>();
1901 PBD::ID s_id (prop->value());
1903 if ((source = source_by_id (s_id)) == 0) {
1904 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1905 return boost::shared_ptr<AudioRegion>();
1908 as = boost::dynamic_pointer_cast<AudioSource>(source);
1910 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1911 return boost::shared_ptr<AudioRegion>();
1914 sources.push_back (as);
1916 /* pickup other channels */
1918 for (uint32_t n=1; n < nchans; ++n) {
1919 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1920 if ((prop = node.property (buf)) != 0) {
1922 PBD::ID id2 (prop->value());
1924 if ((source = source_by_id (id2)) == 0) {
1925 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1926 return boost::shared_ptr<AudioRegion>();
1929 as = boost::dynamic_pointer_cast<AudioSource>(source);
1931 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1932 return boost::shared_ptr<AudioRegion>();
1934 sources.push_back (as);
1938 for (uint32_t n = 0; n < nchans; ++n) {
1939 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1940 if ((prop = node.property (buf)) != 0) {
1942 PBD::ID id2 (prop->value());
1944 if ((source = source_by_id (id2)) == 0) {
1945 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1946 return boost::shared_ptr<AudioRegion>();
1949 as = boost::dynamic_pointer_cast<AudioSource>(source);
1951 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1952 return boost::shared_ptr<AudioRegion>();
1954 master_sources.push_back (as);
1959 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1961 /* a final detail: this is the one and only place that we know how long missing files are */
1963 if (region->whole_file()) {
1964 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1965 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1967 sfp->set_length (region->length());
1972 if (!master_sources.empty()) {
1973 if (master_sources.size() != nchans) {
1974 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1976 region->set_master_sources (master_sources);
1984 catch (failed_constructor& err) {
1985 return boost::shared_ptr<AudioRegion>();
1989 boost::shared_ptr<MidiRegion>
1990 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1992 XMLProperty const * prop;
1993 boost::shared_ptr<Source> source;
1994 boost::shared_ptr<MidiSource> ms;
1997 if (node.name() != X_("Region")) {
1998 return boost::shared_ptr<MidiRegion>();
2001 if ((prop = node.property ("name")) == 0) {
2002 cerr << "no name for this region\n";
2006 if ((prop = node.property (X_("source-0"))) == 0) {
2007 if ((prop = node.property ("source")) == 0) {
2008 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
2009 return boost::shared_ptr<MidiRegion>();
2013 PBD::ID s_id (prop->value());
2015 if ((source = source_by_id (s_id)) == 0) {
2016 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
2017 return boost::shared_ptr<MidiRegion>();
2020 ms = boost::dynamic_pointer_cast<MidiSource>(source);
2022 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
2023 return boost::shared_ptr<MidiRegion>();
2026 sources.push_back (ms);
2029 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
2030 /* a final detail: this is the one and only place that we know how long missing files are */
2032 if (region->whole_file()) {
2033 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
2034 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
2036 sfp->set_length (region->length());
2044 catch (failed_constructor& err) {
2045 return boost::shared_ptr<MidiRegion>();
2050 Session::get_sources_as_xml ()
2053 XMLNode* node = new XMLNode (X_("Sources"));
2054 Glib::Threads::Mutex::Lock lm (source_lock);
2056 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2057 node->add_child_nocopy (i->second->get_state());
2064 Session::reset_write_sources (bool mark_write_complete, bool force)
2066 boost::shared_ptr<RouteList> rl = routes.reader();
2067 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
2068 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
2070 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
2071 tr->reset_write_sources(mark_write_complete, force);
2072 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
2078 Session::load_sources (const XMLNode& node)
2081 XMLNodeConstIterator niter;
2082 boost::shared_ptr<Source> source; /* don't need this but it stops some
2083 * versions of gcc complaining about
2084 * discarded return values.
2087 nlist = node.children();
2091 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2094 if ((source = XMLSourceFactory (**niter)) == 0) {
2095 error << _("Session: cannot create Source from XML description.") << endmsg;
2098 } catch (MissingSource& err) {
2102 if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
2103 error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
2104 PROGRAM_NAME) << endmsg;
2108 if (!no_questions_about_missing_files) {
2109 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
2114 switch (user_choice) {
2116 /* user added a new search location, so try again */
2121 /* user asked to quit the entire session load
2126 no_questions_about_missing_files = true;
2130 no_questions_about_missing_files = true;
2137 case DataType::AUDIO:
2138 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
2141 case DataType::MIDI:
2142 /* The MIDI file is actually missing so
2143 * just create a new one in the same
2144 * location. Do not announce its
2148 if (!Glib::path_is_absolute (err.path)) {
2149 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
2151 /* this should be an unrecoverable error: we would be creating a MIDI file outside
2156 /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
2157 source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
2158 /* reset ID to match the missing one */
2159 source->set_id (**niter);
2160 /* Now we can announce it */
2161 SourceFactory::SourceCreated (source);
2172 boost::shared_ptr<Source>
2173 Session::XMLSourceFactory (const XMLNode& node)
2175 if (node.name() != "Source") {
2176 return boost::shared_ptr<Source>();
2180 /* note: do peak building in another thread when loading session state */
2181 return SourceFactory::create (*this, node, true);
2184 catch (failed_constructor& err) {
2185 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
2186 return boost::shared_ptr<Source>();
2191 Session::save_template (string template_name, bool replace_existing)
2193 if ((_state_of_the_state & CannotSave) || template_name.empty ()) {
2197 bool absolute_path = Glib::path_is_absolute (template_name);
2199 /* directory to put the template in */
2200 std::string template_dir_path;
2202 if (!absolute_path) {
2203 std::string user_template_dir(user_template_directory());
2205 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2206 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2207 user_template_dir, g_strerror (errno)) << endmsg;
2211 template_dir_path = Glib::build_filename (user_template_dir, template_name);
2213 template_dir_path = template_name;
2216 if (!ARDOUR::Profile->get_trx()) {
2217 if (!replace_existing && Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2218 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2219 template_dir_path) << endmsg;
2223 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2224 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2225 template_dir_path, g_strerror (errno)) << endmsg;
2231 std::string template_file_path;
2233 if (ARDOUR::Profile->get_trx()) {
2234 template_file_path = template_name;
2236 if (absolute_path) {
2237 template_file_path = Glib::build_filename (template_dir_path, Glib::path_get_basename (template_dir_path) + template_suffix);
2239 template_file_path = Glib::build_filename (template_dir_path, template_name + template_suffix);
2243 SessionSaveUnderway (); /* EMIT SIGNAL */
2248 PBD::Unwinder<std::string> uw (_template_state_dir, template_dir_path);
2249 tree.set_root (&get_template());
2252 if (!tree.write (template_file_path)) {
2253 error << _("template not saved") << endmsg;
2257 store_recent_templates (template_file_path);
2263 Session::refresh_disk_space ()
2265 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2267 Glib::Threads::Mutex::Lock lm (space_lock);
2269 /* get freespace on every FS that is part of the session path */
2271 _total_free_4k_blocks = 0;
2272 _total_free_4k_blocks_uncertain = false;
2274 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2276 struct statfs statfsbuf;
2277 statfs (i->path.c_str(), &statfsbuf);
2279 double const scale = statfsbuf.f_bsize / 4096.0;
2281 /* See if this filesystem is read-only */
2282 struct statvfs statvfsbuf;
2283 statvfs (i->path.c_str(), &statvfsbuf);
2285 /* f_bavail can be 0 if it is undefined for whatever
2286 filesystem we are looking at; Samba shares mounted
2287 via GVFS are an example of this.
2289 if (statfsbuf.f_bavail == 0) {
2290 /* block count unknown */
2292 i->blocks_unknown = true;
2293 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2294 /* read-only filesystem */
2296 i->blocks_unknown = false;
2298 /* read/write filesystem with known space */
2299 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2300 i->blocks_unknown = false;
2303 _total_free_4k_blocks += i->blocks;
2304 if (i->blocks_unknown) {
2305 _total_free_4k_blocks_uncertain = true;
2308 #elif defined PLATFORM_WINDOWS
2309 vector<string> scanned_volumes;
2310 vector<string>::iterator j;
2311 vector<space_and_path>::iterator i;
2312 DWORD nSectorsPerCluster, nBytesPerSector,
2313 nFreeClusters, nTotalClusters;
2317 _total_free_4k_blocks = 0;
2319 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2320 strncpy (disk_drive, (*i).path.c_str(), 3);
2324 volume_found = false;
2325 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2327 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2328 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2329 i->blocks = (uint32_t)(nFreeBytes / 4096);
2331 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2332 if (0 == j->compare(disk_drive)) {
2333 volume_found = true;
2338 if (!volume_found) {
2339 scanned_volumes.push_back(disk_drive);
2340 _total_free_4k_blocks += i->blocks;
2345 if (0 == _total_free_4k_blocks) {
2346 strncpy (disk_drive, path().c_str(), 3);
2349 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2351 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2352 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2353 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2360 Session::get_best_session_directory_for_new_audio ()
2362 vector<space_and_path>::iterator i;
2363 string result = _session_dir->root_path();
2365 /* handle common case without system calls */
2367 if (session_dirs.size() == 1) {
2371 /* OK, here's the algorithm we're following here:
2373 We want to select which directory to use for
2374 the next file source to be created. Ideally,
2375 we'd like to use a round-robin process so as to
2376 get maximum performance benefits from splitting
2377 the files across multiple disks.
2379 However, in situations without much diskspace, an
2380 RR approach may end up filling up a filesystem
2381 with new files while others still have space.
2382 Its therefore important to pay some attention to
2383 the freespace in the filesystem holding each
2384 directory as well. However, if we did that by
2385 itself, we'd keep creating new files in the file
2386 system with the most space until it was as full
2387 as all others, thus negating any performance
2388 benefits of this RAID-1 like approach.
2390 So, we use a user-configurable space threshold. If
2391 there are at least 2 filesystems with more than this
2392 much space available, we use RR selection between them.
2393 If not, then we pick the filesystem with the most space.
2395 This gets a good balance between the two
2399 refresh_disk_space ();
2401 int free_enough = 0;
2403 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2404 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2409 if (free_enough >= 2) {
2410 /* use RR selection process, ensuring that the one
2414 i = last_rr_session_dir;
2417 if (++i == session_dirs.end()) {
2418 i = session_dirs.begin();
2421 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2422 SessionDirectory sdir(i->path);
2423 if (sdir.create ()) {
2425 last_rr_session_dir = i;
2430 } while (i != last_rr_session_dir);
2434 /* pick FS with the most freespace (and that
2435 seems to actually work ...)
2438 vector<space_and_path> sorted;
2439 space_and_path_ascending_cmp cmp;
2441 sorted = session_dirs;
2442 sort (sorted.begin(), sorted.end(), cmp);
2444 for (i = sorted.begin(); i != sorted.end(); ++i) {
2445 SessionDirectory sdir(i->path);
2446 if (sdir.create ()) {
2448 last_rr_session_dir = i;
2458 Session::automation_dir () const
2460 return Glib::build_filename (_path, automation_dir_name);
2464 Session::analysis_dir () const
2466 return Glib::build_filename (_path, analysis_dir_name);
2470 Session::plugins_dir () const
2472 return Glib::build_filename (_path, plugins_dir_name);
2476 Session::externals_dir () const
2478 return Glib::build_filename (_path, externals_dir_name);
2482 Session::load_bundles (XMLNode const & node)
2484 XMLNodeList nlist = node.children();
2485 XMLNodeConstIterator niter;
2489 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2490 if ((*niter)->name() == "InputBundle") {
2491 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2492 } else if ((*niter)->name() == "OutputBundle") {
2493 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2495 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2504 Session::load_route_groups (const XMLNode& node, int version)
2506 XMLNodeList nlist = node.children();
2507 XMLNodeConstIterator niter;
2511 if (version >= 3000) {
2513 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2514 if ((*niter)->name() == "RouteGroup") {
2515 RouteGroup* rg = new RouteGroup (*this, "");
2516 add_route_group (rg);
2517 rg->set_state (**niter, version);
2521 } else if (version < 3000) {
2523 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2524 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2525 RouteGroup* rg = new RouteGroup (*this, "");
2526 add_route_group (rg);
2527 rg->set_state (**niter, version);
2536 state_file_filter (const string &str, void* /*arg*/)
2538 return (str.length() > strlen(statefile_suffix) &&
2539 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2543 remove_end(string state)
2545 string statename(state);
2547 string::size_type start,end;
2548 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2549 statename = statename.substr (start+1);
2552 if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2553 end = statename.length();
2556 return string(statename.substr (0, end));
2560 Session::possible_states (string path)
2562 vector<string> states;
2563 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2565 transform(states.begin(), states.end(), states.begin(), remove_end);
2567 sort (states.begin(), states.end());
2573 Session::possible_states () const
2575 return possible_states(_path);
2579 Session::add_route_group (RouteGroup* g)
2581 _route_groups.push_back (g);
2582 route_group_added (g); /* EMIT SIGNAL */
2584 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2585 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2586 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2592 Session::remove_route_group (RouteGroup& rg)
2594 list<RouteGroup*>::iterator i;
2596 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2597 _route_groups.erase (i);
2600 route_group_removed (); /* EMIT SIGNAL */
2604 /** Set a new order for our route groups, without adding or removing any.
2605 * @param groups Route group list in the new order.
2608 Session::reorder_route_groups (list<RouteGroup*> groups)
2610 _route_groups = groups;
2612 route_groups_reordered (); /* EMIT SIGNAL */
2618 Session::route_group_by_name (string name)
2620 list<RouteGroup *>::iterator i;
2622 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2623 if ((*i)->name() == name) {
2631 Session::all_route_group() const
2633 return *_all_route_group;
2637 Session::add_commands (vector<Command*> const & cmds)
2639 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2645 Session::add_command (Command* const cmd)
2647 assert (_current_trans);
2648 DEBUG_UNDO_HISTORY (
2649 string_compose ("Current Undo Transaction %1, adding command: %2",
2650 _current_trans->name (),
2652 _current_trans->add_command (cmd);
2655 PBD::StatefulDiffCommand*
2656 Session::add_stateful_diff_command (boost::shared_ptr<PBD::StatefulDestructible> sfd)
2658 PBD::StatefulDiffCommand* cmd = new PBD::StatefulDiffCommand (sfd);
2664 Session::begin_reversible_command (const string& name)
2666 begin_reversible_command (g_quark_from_string (name.c_str ()));
2669 /** Begin a reversible command using a GQuark to identify it.
2670 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2671 * but there must be as many begin...()s as there are commit...()s.
2674 Session::begin_reversible_command (GQuark q)
2676 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2677 to hold all the commands that are committed. This keeps the order of
2678 commands correct in the history.
2681 if (_current_trans == 0) {
2682 DEBUG_UNDO_HISTORY (string_compose (
2683 "Begin Reversible Command, new transaction: %1", g_quark_to_string (q)));
2685 /* start a new transaction */
2686 assert (_current_trans_quarks.empty ());
2687 _current_trans = new UndoTransaction();
2688 _current_trans->set_name (g_quark_to_string (q));
2690 DEBUG_UNDO_HISTORY (
2691 string_compose ("Begin Reversible Command, current transaction: %1",
2692 _current_trans->name ()));
2695 _current_trans_quarks.push_front (q);
2699 Session::abort_reversible_command ()
2701 if (_current_trans != 0) {
2702 DEBUG_UNDO_HISTORY (
2703 string_compose ("Abort Reversible Command: %1", _current_trans->name ()));
2704 _current_trans->clear();
2705 delete _current_trans;
2707 _current_trans_quarks.clear();
2712 Session::commit_reversible_command (Command *cmd)
2714 assert (_current_trans);
2715 assert (!_current_trans_quarks.empty ());
2720 DEBUG_UNDO_HISTORY (
2721 string_compose ("Current Undo Transaction %1, adding command: %2",
2722 _current_trans->name (),
2724 _current_trans->add_command (cmd);
2727 DEBUG_UNDO_HISTORY (
2728 string_compose ("Commit Reversible Command, current transaction: %1",
2729 _current_trans->name ()));
2731 _current_trans_quarks.pop_front ();
2733 if (!_current_trans_quarks.empty ()) {
2734 DEBUG_UNDO_HISTORY (
2735 string_compose ("Commit Reversible Command, transaction is not "
2736 "top-level, current transaction: %1",
2737 _current_trans->name ()));
2738 /* the transaction we're committing is not the top-level one */
2742 if (_current_trans->empty()) {
2743 /* no commands were added to the transaction, so just get rid of it */
2744 DEBUG_UNDO_HISTORY (
2745 string_compose ("Commit Reversible Command, No commands were "
2746 "added to current transaction: %1",
2747 _current_trans->name ()));
2748 delete _current_trans;
2753 gettimeofday (&now, 0);
2754 _current_trans->set_timestamp (now);
2756 _history.add (_current_trans);
2761 accept_all_audio_files (const string& path, void* /*arg*/)
2763 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2767 if (!AudioFileSource::safe_audio_file_extension (path)) {
2775 accept_all_midi_files (const string& path, void* /*arg*/)
2777 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2781 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2782 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2783 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2787 accept_all_state_files (const string& path, void* /*arg*/)
2789 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2793 std::string const statefile_ext (statefile_suffix);
2794 if (path.length() >= statefile_ext.length()) {
2795 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2802 Session::find_all_sources (string path, set<string>& result)
2807 if (!tree.read (path)) {
2811 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2816 XMLNodeConstIterator niter;
2818 nlist = node->children();
2822 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2824 XMLProperty const * prop;
2826 if ((prop = (*niter)->property (X_("type"))) == 0) {
2830 DataType type (prop->value());
2832 if ((prop = (*niter)->property (X_("name"))) == 0) {
2836 if (Glib::path_is_absolute (prop->value())) {
2837 /* external file, ignore */
2845 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2846 result.insert (found_path);
2854 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2856 vector<string> state_files;
2858 string this_snapshot_path;
2864 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2865 ripped = ripped.substr (0, ripped.length() - 1);
2868 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2870 if (state_files.empty()) {
2875 this_snapshot_path = _path;
2876 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2877 this_snapshot_path += statefile_suffix;
2879 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2881 if (exclude_this_snapshot && *i == this_snapshot_path) {
2885 if (find_all_sources (*i, result) < 0) {
2893 struct RegionCounter {
2894 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2895 AudioSourceList::iterator iter;
2896 boost::shared_ptr<Region> region;
2899 RegionCounter() : count (0) {}
2903 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2905 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2906 return r.get_value_or (1);
2910 Session::cleanup_regions ()
2912 bool removed = false;
2913 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2915 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2917 uint32_t used = playlists->region_use_count (i->second);
2919 if (used == 0 && !i->second->automatic ()) {
2920 boost::weak_ptr<Region> w = i->second;
2923 RegionFactory::map_remove (w);
2930 // re-check to remove parent references of compound regions
2931 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2932 if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2936 assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2937 if (0 == playlists->region_use_count (i->second)) {
2938 boost::weak_ptr<Region> w = i->second;
2940 RegionFactory::map_remove (w);
2947 /* dump the history list */
2954 Session::can_cleanup_peakfiles () const
2956 if (deletion_in_progress()) {
2959 if (!_writable || (_state_of_the_state & CannotSave)) {
2960 warning << _("Cannot cleanup peak-files for read-only session.") << endmsg;
2963 if (record_status() == Recording) {
2964 error << _("Cannot cleanup peak-files while recording") << endmsg;
2971 Session::cleanup_peakfiles ()
2973 Glib::Threads::Mutex::Lock lm (peak_cleanup_lock, Glib::Threads::TRY_LOCK);
2978 assert (can_cleanup_peakfiles ());
2979 assert (!peaks_cleanup_in_progres());
2981 _state_of_the_state = StateOfTheState (_state_of_the_state | PeakCleanup);
2983 int timeout = 5000; // 5 seconds
2984 while (!SourceFactory::files_with_peaks.empty()) {
2985 Glib::usleep (1000);
2986 if (--timeout < 0) {
2987 warning << _("Timeout waiting for peak-file creation to terminate before cleanup, please try again later.") << endmsg;
2988 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
2993 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2994 boost::shared_ptr<AudioSource> as;
2995 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
2996 as->close_peakfile();
3000 PBD::clear_directory (session_directory().peak_path());
3002 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
3004 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3005 boost::shared_ptr<AudioSource> as;
3006 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
3007 SourceFactory::setup_peakfile(as, true);
3014 Session::cleanup_sources (CleanupReport& rep)
3016 // FIXME: needs adaptation to midi
3018 vector<boost::shared_ptr<Source> > dead_sources;
3021 vector<string> candidates;
3022 vector<string> unused;
3023 set<string> all_sources;
3032 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
3034 /* this is mostly for windows which doesn't allow file
3035 * renaming if the file is in use. But we don't special
3036 * case it because we need to know if this causes
3037 * problems, and the easiest way to notice that is to
3038 * keep it in place for all platforms.
3041 request_stop (false);
3043 _butler->wait_until_finished ();
3045 /* consider deleting all unused playlists */
3047 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
3052 /* sync the "all regions" property of each playlist with its current state
3055 playlists->sync_all_regions_with_regions ();
3057 /* find all un-used sources */
3062 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3064 SourceMap::iterator tmp;
3069 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
3073 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
3074 dead_sources.push_back (i->second);
3075 i->second->drop_references ();
3081 /* build a list of all the possible audio directories for the session */
3083 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3084 SessionDirectory sdir ((*i).path);
3085 asp += sdir.sound_path();
3087 audio_path += asp.to_string();
3090 /* build a list of all the possible midi directories for the session */
3092 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3093 SessionDirectory sdir ((*i).path);
3094 msp += sdir.midi_path();
3096 midi_path += msp.to_string();
3098 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
3099 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
3101 /* find all sources, but don't use this snapshot because the
3102 state file on disk still references sources we may have already
3106 find_all_sources_across_snapshots (all_sources, true);
3108 /* add our current source list
3111 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3112 boost::shared_ptr<FileSource> fs;
3113 SourceMap::iterator tmp = i;
3116 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
3118 /* this is mostly for windows which doesn't allow file
3119 * renaming if the file is in use. But we don't special
3120 * case it because we need to know if this causes
3121 * problems, and the easiest way to notice that is to
3122 * keep it in place for all platforms.
3127 if (!fs->is_stub()) {
3129 if (playlists->source_use_count (fs) != 0) {
3130 all_sources.insert (fs->path());
3133 /* we might not remove this source from disk, because it may be used
3134 by other snapshots, but its not being used in this version
3135 so lets get rid of it now, along with any representative regions
3139 RegionFactory::remove_regions_using_source (i->second);
3141 // also remove source from all_sources
3143 for (set<string>::iterator j = all_sources.begin(); j != all_sources.end(); ++j) {
3144 spath = Glib::path_get_basename (*j);
3145 if (spath == i->second->name()) {
3146 all_sources.erase (j);
3159 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
3164 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
3166 tmppath1 = canonical_path (spath);
3167 tmppath2 = canonical_path ((*i));
3169 if (tmppath1 == tmppath2) {
3176 unused.push_back (spath);
3180 /* now try to move all unused files into the "dead" directory(ies) */
3182 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
3187 /* don't move the file across filesystems, just
3188 stick it in the `dead_dir_name' directory
3189 on whichever filesystem it was already on.
3192 if ((*x).find ("/sounds/") != string::npos) {
3194 /* old school, go up 1 level */
3196 newpath = Glib::path_get_dirname (*x); // "sounds"
3197 newpath = Glib::path_get_dirname (newpath); // "session-name"
3201 /* new school, go up 4 levels */
3203 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
3204 newpath = Glib::path_get_dirname (newpath); // "session-name"
3205 newpath = Glib::path_get_dirname (newpath); // "interchange"
3206 newpath = Glib::path_get_dirname (newpath); // "session-dir"
3209 newpath = Glib::build_filename (newpath, dead_dir_name);
3211 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
3212 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
3216 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
3218 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
3220 /* the new path already exists, try versioning */
3222 char buf[PATH_MAX+1];
3226 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3229 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
3230 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3234 if (version == 999) {
3235 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3239 newpath = newpath_v;
3244 /* it doesn't exist, or we can't read it or something */
3248 g_stat ((*x).c_str(), &statbuf);
3250 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3251 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
3252 (*x), newpath, strerror (errno))
3257 /* see if there an easy to find peakfile for this file, and remove it.
3260 string base = Glib::path_get_basename (*x);
3261 base += "%A"; /* this is what we add for the channel suffix of all native files,
3262 or for the first channel of embedded files. it will miss
3263 some peakfiles for other channels
3265 string peakpath = construct_peak_filepath (base);
3267 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
3268 if (::g_unlink (peakpath.c_str()) != 0) {
3269 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3270 peakpath, _path, strerror (errno))
3272 /* try to back out */
3273 ::rename (newpath.c_str(), _path.c_str());
3278 rep.paths.push_back (*x);
3279 rep.space += statbuf.st_size;
3282 /* dump the history list */
3286 /* save state so we don't end up a session file
3287 referring to non-existent sources.
3294 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3300 Session::cleanup_trash_sources (CleanupReport& rep)
3302 // FIXME: needs adaptation for MIDI
3304 vector<space_and_path>::iterator i;
3310 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3312 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
3314 clear_directory (dead_dir, &rep.space, &rep.paths);
3321 Session::set_dirty ()
3323 /* never mark session dirty during loading */
3325 if (_state_of_the_state & Loading) {
3329 bool was_dirty = dirty();
3331 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3335 DirtyChanged(); /* EMIT SIGNAL */
3341 Session::set_clean ()
3343 bool was_dirty = dirty();
3345 _state_of_the_state = Clean;
3349 DirtyChanged(); /* EMIT SIGNAL */
3354 Session::set_deletion_in_progress ()
3356 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3360 Session::clear_deletion_in_progress ()
3362 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3366 Session::add_controllable (boost::shared_ptr<Controllable> c)
3368 /* this adds a controllable to the list managed by the Session.
3369 this is a subset of those managed by the Controllable class
3370 itself, and represents the only ones whose state will be saved
3371 as part of the session.
3374 Glib::Threads::Mutex::Lock lm (controllables_lock);
3375 controllables.insert (c);
3378 struct null_deleter { void operator()(void const *) const {} };
3381 Session::remove_controllable (Controllable* c)
3383 if (_state_of_the_state & Deletion) {
3387 Glib::Threads::Mutex::Lock lm (controllables_lock);
3389 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3391 if (x != controllables.end()) {
3392 controllables.erase (x);
3396 boost::shared_ptr<Controllable>
3397 Session::controllable_by_id (const PBD::ID& id)
3399 Glib::Threads::Mutex::Lock lm (controllables_lock);
3401 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3402 if ((*i)->id() == id) {
3407 return boost::shared_ptr<Controllable>();
3410 boost::shared_ptr<Controllable>
3411 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3413 boost::shared_ptr<Controllable> c;
3414 boost::shared_ptr<Stripable> s;
3415 boost::shared_ptr<Route> r;
3417 switch (desc.top_level_type()) {
3418 case ControllableDescriptor::NamedRoute:
3420 std::string str = desc.top_level_name();
3422 if (str == "Master" || str == "master") {
3424 } else if (str == "control" || str == "listen" || str == "monitor" || str == "Monitor") {
3426 } else if (str == "auditioner") {
3429 s = route_by_name (desc.top_level_name());
3435 case ControllableDescriptor::PresentationOrderRoute:
3436 s = get_remote_nth_stripable (desc.presentation_order(), PresentationInfo::Route);
3439 case ControllableDescriptor::PresentationOrderTrack:
3440 s = get_remote_nth_stripable (desc.presentation_order(), PresentationInfo::Track);
3443 case ControllableDescriptor::PresentationOrderBus:
3444 s = get_remote_nth_stripable (desc.presentation_order(), PresentationInfo::Bus);
3447 case ControllableDescriptor::PresentationOrderVCA:
3448 s = get_remote_nth_stripable (desc.presentation_order(), PresentationInfo::VCA);
3451 case ControllableDescriptor::SelectionCount:
3452 s = route_by_selected_count (desc.selection_id());
3460 r = boost::dynamic_pointer_cast<Route> (s);
3462 switch (desc.subtype()) {
3463 case ControllableDescriptor::Gain:
3464 c = s->gain_control ();
3467 case ControllableDescriptor::Trim:
3468 c = s->trim_control ();
3471 case ControllableDescriptor::Solo:
3472 c = s->solo_control();
3475 case ControllableDescriptor::Mute:
3476 c = s->mute_control();
3479 case ControllableDescriptor::Recenable:
3480 c = s->rec_enable_control ();
3483 case ControllableDescriptor::PanDirection:
3484 c = s->pan_azimuth_control();
3487 case ControllableDescriptor::PanWidth:
3488 c = s->pan_width_control();
3491 case ControllableDescriptor::PanElevation:
3492 c = s->pan_elevation_control();
3495 case ControllableDescriptor::Balance:
3496 /* XXX simple pan control */
3499 case ControllableDescriptor::PluginParameter:
3501 uint32_t plugin = desc.target (0);
3502 uint32_t parameter_index = desc.target (1);
3504 /* revert to zero based counting */
3510 if (parameter_index > 0) {
3518 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3521 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3522 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3527 case ControllableDescriptor::SendGain: {
3528 uint32_t send = desc.target (0);
3535 c = r->send_level_controllable (send);
3540 /* relax and return a null pointer */
3548 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3551 Stateful::add_instant_xml (node, _path);
3554 if (write_to_config) {
3555 Config->add_instant_xml (node);
3560 Session::instant_xml (const string& node_name)
3562 return Stateful::instant_xml (node_name, _path);
3566 Session::save_history (string snapshot_name)
3574 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3575 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3579 if (snapshot_name.empty()) {
3580 snapshot_name = _current_snapshot_name;
3583 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3584 const string backup_filename = history_filename + backup_suffix;
3585 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3586 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3588 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3589 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3590 error << _("could not backup old history file, current history not saved") << endmsg;
3595 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3597 if (!tree.write (xml_path))
3599 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3601 if (g_remove (xml_path.c_str()) != 0) {
3602 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3603 xml_path, g_strerror (errno)) << endmsg;
3605 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3606 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3607 backup_path, g_strerror (errno)) << endmsg;
3617 Session::restore_history (string snapshot_name)
3621 if (snapshot_name.empty()) {
3622 snapshot_name = _current_snapshot_name;
3625 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3626 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3628 info << "Loading history from " << xml_path << endmsg;
3630 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3631 info << string_compose (_("%1: no history file \"%2\" for this session."),
3632 _name, xml_path) << endmsg;
3636 if (!tree.read (xml_path)) {
3637 error << string_compose (_("Could not understand session history file \"%1\""),
3638 xml_path) << endmsg;
3645 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3648 UndoTransaction* ut = new UndoTransaction ();
3651 ut->set_name(t->property("name")->value());
3652 stringstream ss(t->property("tv-sec")->value());
3654 ss.str(t->property("tv-usec")->value());
3656 ut->set_timestamp(tv);
3658 for (XMLNodeConstIterator child_it = t->children().begin();
3659 child_it != t->children().end(); child_it++)
3661 XMLNode *n = *child_it;
3664 if (n->name() == "MementoCommand" ||
3665 n->name() == "MementoUndoCommand" ||
3666 n->name() == "MementoRedoCommand") {
3668 if ((c = memento_command_factory(n))) {
3672 } else if (n->name() == "NoteDiffCommand") {
3673 PBD::ID id (n->property("midi-source")->value());
3674 boost::shared_ptr<MidiSource> midi_source =
3675 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3677 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3679 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3682 } else if (n->name() == "SysExDiffCommand") {
3684 PBD::ID id (n->property("midi-source")->value());
3685 boost::shared_ptr<MidiSource> midi_source =
3686 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3688 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3690 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3693 } else if (n->name() == "PatchChangeDiffCommand") {
3695 PBD::ID id (n->property("midi-source")->value());
3696 boost::shared_ptr<MidiSource> midi_source =
3697 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3699 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3701 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3704 } else if (n->name() == "StatefulDiffCommand") {
3705 if ((c = stateful_diff_command_factory (n))) {
3706 ut->add_command (c);
3709 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3720 Session::config_changed (std::string p, bool ours)
3726 if (p == "seamless-loop") {
3728 } else if (p == "rf-speed") {
3730 } else if (p == "auto-loop") {
3732 } else if (p == "auto-input") {
3734 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3735 /* auto-input only makes a difference if we're rolling */
3736 set_track_monitor_input_status (!config.get_auto_input());
3739 } else if (p == "punch-in") {
3743 if ((location = _locations->auto_punch_location()) != 0) {
3745 if (config.get_punch_in ()) {
3746 replace_event (SessionEvent::PunchIn, location->start());
3748 remove_event (location->start(), SessionEvent::PunchIn);
3752 } else if (p == "punch-out") {
3756 if ((location = _locations->auto_punch_location()) != 0) {
3758 if (config.get_punch_out()) {
3759 replace_event (SessionEvent::PunchOut, location->end());
3761 clear_events (SessionEvent::PunchOut);
3765 } else if (p == "edit-mode") {
3767 Glib::Threads::Mutex::Lock lm (playlists->lock);
3769 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3770 (*i)->set_edit_mode (Config->get_edit_mode ());
3773 } else if (p == "use-video-sync") {
3775 waiting_for_sync_offset = config.get_use_video_sync();
3777 } else if (p == "mmc-control") {
3779 //poke_midi_thread ();
3781 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3783 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3785 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3787 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3789 } else if (p == "midi-control") {
3791 //poke_midi_thread ();
3793 } else if (p == "raid-path") {
3795 setup_raid_path (config.get_raid_path());
3797 } else if (p == "timecode-format") {
3801 } else if (p == "video-pullup") {
3805 } else if (p == "seamless-loop") {
3807 if (play_loop && transport_rolling()) {
3808 // to reset diskstreams etc
3809 request_play_loop (true);
3812 } else if (p == "rf-speed") {
3814 cumulative_rf_motion = 0;
3817 } else if (p == "click-sound") {
3819 setup_click_sounds (1);
3821 } else if (p == "click-emphasis-sound") {
3823 setup_click_sounds (-1);
3825 } else if (p == "clicking") {
3827 if (Config->get_clicking()) {
3828 if (_click_io && click_data) { // don't require emphasis data
3835 } else if (p == "click-gain") {
3838 _click_gain->gain_control()->set_value (Config->get_click_gain(), Controllable::NoGroup);
3841 } else if (p == "send-mtc") {
3843 if (Config->get_send_mtc ()) {
3844 /* mark us ready to send */
3845 next_quarter_frame_to_send = 0;
3848 } else if (p == "send-mmc") {
3850 _mmc->enable_send (Config->get_send_mmc ());
3852 } else if (p == "midi-feedback") {
3854 session_midi_feedback = Config->get_midi_feedback();
3856 } else if (p == "jack-time-master") {
3858 engine().reset_timebase ();
3860 } else if (p == "native-file-header-format") {
3862 if (!first_file_header_format_reset) {
3863 reset_native_file_format ();
3866 first_file_header_format_reset = false;
3868 } else if (p == "native-file-data-format") {
3870 if (!first_file_data_format_reset) {
3871 reset_native_file_format ();
3874 first_file_data_format_reset = false;
3876 } else if (p == "external-sync") {
3877 if (!config.get_external_sync()) {
3878 drop_sync_source ();
3880 switch_to_sync_source (Config->get_sync_source());
3882 } else if (p == "denormal-model") {
3884 } else if (p == "history-depth") {
3885 set_history_depth (Config->get_history_depth());
3886 } else if (p == "remote-model") {
3887 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3890 } else if (p == "initial-program-change") {
3892 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3895 buf[0] = MIDI::program; // channel zero by default
3896 buf[1] = (Config->get_initial_program_change() & 0x7f);
3898 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3900 } else if (p == "solo-mute-override") {
3901 // catch_up_on_solo_mute_override ();
3902 } else if (p == "listen-position" || p == "pfl-position") {
3903 listen_position_changed ();
3904 } else if (p == "solo-control-is-listen-control") {
3905 solo_control_mode_changed ();
3906 } else if (p == "solo-mute-gain") {
3907 _solo_cut_control->Changed (true, Controllable::NoGroup);
3908 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3909 last_timecode_valid = false;
3910 } else if (p == "playback-buffer-seconds") {
3911 AudioSource::allocate_working_buffers (frame_rate());
3912 } else if (p == "ltc-source-port") {
3913 reconnect_ltc_input ();
3914 } else if (p == "ltc-sink-port") {
3915 reconnect_ltc_output ();
3916 } else if (p == "timecode-generator-offset") {
3917 ltc_tx_parse_offset();
3918 } else if (p == "auto-return-target-list") {
3919 follow_playhead_priority ();
3926 Session::set_history_depth (uint32_t d)
3928 _history.set_depth (d);
3932 Session::load_diskstreams_2X (XMLNode const & node, int)
3935 XMLNodeConstIterator citer;
3937 clist = node.children();
3939 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3942 /* diskstreams added automatically by DiskstreamCreated handler */
3943 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3944 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3945 _diskstreams_2X.push_back (dsp);
3947 error << _("Session: unknown diskstream type in XML") << endmsg;
3951 catch (failed_constructor& err) {
3952 error << _("Session: could not load diskstream via XML state") << endmsg;
3960 /** Connect things to the MMC object */
3962 Session::setup_midi_machine_control ()
3964 _mmc = new MIDI::MachineControl;
3966 boost::shared_ptr<AsyncMIDIPort> async_in = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_input_port());
3967 boost::shared_ptr<AsyncMIDIPort> async_out = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_output_port());
3969 if (!async_out || !async_out) {
3973 /* XXXX argh, passing raw pointers back into libmidi++ */
3975 MIDI::Port* mmc_in = async_in.get();
3976 MIDI::Port* mmc_out = async_out.get();
3978 _mmc->set_ports (mmc_in, mmc_out);
3980 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3981 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3982 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3983 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3984 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3985 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3986 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3987 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3988 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3989 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3990 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3991 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3992 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3994 /* also handle MIDI SPP because its so common */
3996 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3997 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3998 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
4001 boost::shared_ptr<Controllable>
4002 Session::solo_cut_control() const
4004 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
4005 controls in Ardour that currently get presented to the user in the GUI that require
4006 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
4008 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
4009 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
4013 return _solo_cut_control;
4017 Session::save_snapshot_name (const std::string & n)
4019 /* assure Stateful::_instant_xml is loaded
4020 * add_instant_xml() only adds to existing data and defaults
4021 * to use an empty Tree otherwise
4023 instant_xml ("LastUsedSnapshot");
4025 XMLNode* last_used_snapshot = new XMLNode ("LastUsedSnapshot");
4026 last_used_snapshot->add_property ("name", string(n));
4027 add_instant_xml (*last_used_snapshot, false);
4031 Session::set_snapshot_name (const std::string & n)
4033 _current_snapshot_name = n;
4034 save_snapshot_name (n);
4038 Session::rename (const std::string& new_name)
4040 string legal_name = legalize_for_path (new_name);
4046 string const old_sources_root = _session_dir->sources_root();
4048 if (!_writable || (_state_of_the_state & CannotSave)) {
4049 error << _("Cannot rename read-only session.") << endmsg;
4050 return 0; // don't show "messed up" warning
4052 if (record_status() == Recording) {
4053 error << _("Cannot rename session while recording") << endmsg;
4054 return 0; // don't show "messed up" warning
4057 StateProtector stp (this);
4062 * interchange subdirectory
4066 * Backup files are left unchanged and not renamed.
4069 /* Windows requires that we close all files before attempting the
4070 * rename. This works on other platforms, but isn't necessary there.
4071 * Leave it in place for all platforms though, since it may help
4072 * catch issues that could arise if the way Source files work ever
4073 * change (since most developers are not using Windows).
4076 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4077 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4083 /* pass one: not 100% safe check that the new directory names don't
4087 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4091 /* this is a stupid hack because Glib::path_get_dirname() is
4092 * lexical-only, and so passing it /a/b/c/ gives a different
4093 * result than passing it /a/b/c ...
4096 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4097 oldstr = oldstr.substr (0, oldstr.length() - 1);
4100 string base = Glib::path_get_dirname (oldstr);
4102 newstr = Glib::build_filename (base, legal_name);
4104 cerr << "Looking for " << newstr << endl;
4106 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
4107 cerr << " exists\n";
4116 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4122 /* this is a stupid hack because Glib::path_get_dirname() is
4123 * lexical-only, and so passing it /a/b/c/ gives a different
4124 * result than passing it /a/b/c ...
4127 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4128 oldstr = oldstr.substr (0, oldstr.length() - 1);
4131 string base = Glib::path_get_dirname (oldstr);
4132 newstr = Glib::build_filename (base, legal_name);
4134 cerr << "for " << oldstr << " new dir = " << newstr << endl;
4136 cerr << "Rename " << oldstr << " => " << newstr << endl;
4137 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4138 cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4139 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4143 /* Reset path in "session dirs" */
4148 /* reset primary SessionDirectory object */
4151 (*_session_dir) = newstr;
4156 /* now rename directory below session_dir/interchange */
4158 string old_interchange_dir;
4159 string new_interchange_dir;
4161 /* use newstr here because we renamed the path
4162 * (folder/directory) that used to be oldstr to newstr above
4165 v.push_back (newstr);
4166 v.push_back (interchange_dir_name);
4167 v.push_back (Glib::path_get_basename (oldstr));
4169 old_interchange_dir = Glib::build_filename (v);
4172 v.push_back (newstr);
4173 v.push_back (interchange_dir_name);
4174 v.push_back (legal_name);
4176 new_interchange_dir = Glib::build_filename (v);
4178 cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
4180 if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
4181 cerr << string_compose (_("renaming %s as %2 failed (%3)"),
4182 old_interchange_dir, new_interchange_dir,
4185 error << string_compose (_("renaming %s as %2 failed (%3)"),
4186 old_interchange_dir, new_interchange_dir,
4195 oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
4196 newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
4198 cerr << "Rename " << oldstr << " => " << newstr << endl;
4200 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4201 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4202 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4208 oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
4210 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
4211 newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
4213 cerr << "Rename " << oldstr << " => " << newstr << endl;
4215 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4216 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4217 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4222 /* remove old name from recent sessions */
4223 remove_recent_sessions (_path);
4226 /* update file source paths */
4228 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
4229 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4231 string p = fs->path ();
4232 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
4234 SourceFactory::setup_peakfile(i->second, true);
4238 set_snapshot_name (new_name);
4243 /* save state again to get everything just right */
4245 save_state (_current_snapshot_name);
4247 /* add to recent sessions */
4249 store_recent_sessions (new_name, _path);
4255 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
4257 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
4261 if (!tree.read (xmlpath)) {
4269 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
4272 bool found_sr = false;
4273 bool found_data_format = false;
4275 if (get_session_info_from_path (tree, xmlpath)) {
4281 XMLProperty const * prop;
4282 XMLNode const * root (tree.root());
4284 if ((prop = root->property (X_("sample-rate"))) != 0) {
4285 sample_rate = atoi (prop->value());
4289 const XMLNodeList& children (root->children());
4290 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
4291 const XMLNode* child = *c;
4292 if (child->name() == "Config") {
4293 const XMLNodeList& options (child->children());
4294 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
4295 XMLNode const * option = *oc;
4296 XMLProperty const * name = option->property("name");
4302 if (name->value() == "native-file-data-format") {
4303 XMLProperty const * value = option->property ("value");
4305 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
4307 found_data_format = true;
4313 if (found_data_format) {
4318 return !(found_sr && found_data_format); // zero if they are both found
4322 Session::get_snapshot_from_instant (const std::string& session_dir)
4324 std::string instant_xml_path = Glib::build_filename (session_dir, "instant.xml");
4326 if (!Glib::file_test (instant_xml_path, Glib::FILE_TEST_EXISTS)) {
4331 if (!tree.read (instant_xml_path)) {
4335 XMLProperty const * prop;
4336 XMLNode *last_used_snapshot = tree.root()->child("LastUsedSnapshot");
4337 if (last_used_snapshot && (prop = last_used_snapshot->property ("name")) != 0) {
4338 return prop->value();
4344 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
4345 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
4348 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
4352 SourcePathMap source_path_map;
4354 boost::shared_ptr<AudioFileSource> afs;
4359 Glib::Threads::Mutex::Lock lm (source_lock);
4361 cerr << " total sources = " << sources.size();
4363 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4364 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4370 if (fs->within_session()) {
4374 if (source_path_map.find (fs->path()) != source_path_map.end()) {
4375 source_path_map[fs->path()].push_back (fs);
4377 SeveralFileSources v;
4379 source_path_map.insert (make_pair (fs->path(), v));
4385 cerr << " fsources = " << total << endl;
4387 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
4389 /* tell caller where we are */
4391 string old_path = i->first;
4393 callback (n, total, old_path);
4395 cerr << old_path << endl;
4399 switch (i->second.front()->type()) {
4400 case DataType::AUDIO:
4401 new_path = new_audio_source_path_for_embedded (old_path);
4404 case DataType::MIDI:
4405 /* XXX not implemented yet */
4409 if (new_path.empty()) {
4413 cerr << "Move " << old_path << " => " << new_path << endl;
4415 if (!copy_file (old_path, new_path)) {
4416 cerr << "failed !\n";
4420 /* make sure we stop looking in the external
4421 dir/folder. Remember, this is an all-or-nothing
4422 operations, it doesn't merge just some files.
4424 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
4426 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
4427 (*f)->set_path (new_path);
4432 save_state ("", false, false);
4438 bool accept_all_files (string const &, void *)
4444 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4446 /* 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.
4451 make_new_media_path (string old_path, string new_session_folder, string new_session_path)
4453 /* typedir is the "midifiles" or "audiofiles" etc. part of the path. */
4455 string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4457 v.push_back (new_session_folder); /* full path */
4458 v.push_back (interchange_dir_name);
4459 v.push_back (new_session_path); /* just one directory/folder */
4460 v.push_back (typedir);
4461 v.push_back (Glib::path_get_basename (old_path));
4463 return Glib::build_filename (v);
4467 Session::save_as (SaveAs& saveas)
4469 vector<string> files;
4470 string current_folder = Glib::path_get_dirname (_path);
4471 string new_folder = legalize_for_path (saveas.new_name);
4472 string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4473 int64_t total_bytes = 0;
4477 int32_t internal_file_cnt = 0;
4479 vector<string> do_not_copy_extensions;
4480 do_not_copy_extensions.push_back (statefile_suffix);
4481 do_not_copy_extensions.push_back (pending_suffix);
4482 do_not_copy_extensions.push_back (backup_suffix);
4483 do_not_copy_extensions.push_back (temp_suffix);
4484 do_not_copy_extensions.push_back (history_suffix);
4486 /* get total size */
4488 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4490 /* need to clear this because
4491 * find_files_matching_filter() is cumulative
4496 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4498 all += files.size();
4500 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4502 g_stat ((*i).c_str(), &gsb);
4503 total_bytes += gsb.st_size;
4507 /* save old values so we can switch back if we are not switching to the new session */
4509 string old_path = _path;
4510 string old_name = _name;
4511 string old_snapshot = _current_snapshot_name;
4512 string old_sd = _session_dir->root_path();
4513 vector<string> old_search_path[DataType::num_types];
4514 string old_config_search_path[DataType::num_types];
4516 old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4517 old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4518 old_config_search_path[DataType::AUDIO] = config.get_audio_search_path ();
4519 old_config_search_path[DataType::MIDI] = config.get_midi_search_path ();
4521 /* switch session directory */
4523 (*_session_dir) = to_dir;
4525 /* create new tree */
4527 if (!_session_dir->create()) {
4528 saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4533 /* copy all relevant files. Find each location in session_dirs,
4534 * and copy files from there to target.
4537 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4539 /* need to clear this because
4540 * find_files_matching_filter() is cumulative
4545 const size_t prefix_len = (*sd).path.size();
4547 /* Work just on the files within this session dir */
4549 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4551 /* add dir separator to protect against collisions with
4552 * track names (e.g. track named "audiofiles" or
4556 static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
4557 static const std::string midifile_dir_string = string (midi_dir_name) + G_DIR_SEPARATOR;
4558 static const std::string analysis_dir_string = analysis_dir() + G_DIR_SEPARATOR;
4560 /* copy all the files. Handling is different for media files
4561 than others because of the *silly* subtree we have below the interchange
4562 folder. That really was a bad idea, but I'm not fixing it as part of
4563 implementing ::save_as().
4566 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4568 std::string from = *i;
4571 string filename = Glib::path_get_basename (from);
4572 std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
4573 if (filename == ".DS_STORE") {
4578 if (from.find (audiofile_dir_string) != string::npos) {
4580 /* audio file: only copy if asked */
4582 if (saveas.include_media && saveas.copy_media) {
4584 string to = make_new_media_path (*i, to_dir, new_folder);
4586 info << "media file copying from " << from << " to " << to << endmsg;
4588 if (!copy_file (from, to)) {
4589 throw Glib::FileError (Glib::FileError::IO_ERROR,
4590 string_compose(_("\ncopying \"%1\" failed !"), from));
4594 /* we found media files inside the session folder */
4596 internal_file_cnt++;
4598 } else if (from.find (midifile_dir_string) != string::npos) {
4600 /* midi file: always copy unless
4601 * creating an empty new session
4604 if (saveas.include_media) {
4606 string to = make_new_media_path (*i, to_dir, new_folder);
4608 info << "media file copying from " << from << " to " << to << endmsg;
4610 if (!copy_file (from, to)) {
4611 throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4615 /* we found media files inside the session folder */
4617 internal_file_cnt++;
4619 } else if (from.find (analysis_dir_string) != string::npos) {
4621 /* make sure analysis dir exists in
4622 * new session folder, but we're not
4623 * copying analysis files here, see
4627 (void) g_mkdir_with_parents (analysis_dir().c_str(), 775);
4632 /* normal non-media file. Don't copy state, history, etc.
4635 bool do_copy = true;
4637 for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
4638 if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
4639 /* end of filename matches extension, do not copy file */
4645 if (!saveas.copy_media && from.find (peakfile_suffix) != string::npos) {
4646 /* don't copy peakfiles if
4647 * we're not copying media
4653 string to = Glib::build_filename (to_dir, from.substr (prefix_len));
4655 info << "attempting to make directory/folder " << to << endmsg;
4657 if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
4658 throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
4661 info << "attempting to copy " << from << " to " << to << endmsg;
4663 if (!copy_file (from, to)) {
4664 throw Glib::FileError (Glib::FileError::IO_ERROR,
4665 string_compose(_("\ncopying \"%1\" failed !"), from));
4670 /* measure file size even if we're not going to copy so that our Progress
4671 signals are correct, since we included these do-not-copy files
4672 in the computation of the total size and file count.
4676 g_stat (from.c_str(), &gsb);
4677 copied += gsb.st_size;
4680 double fraction = (double) copied / total_bytes;
4682 bool keep_going = true;
4684 if (saveas.copy_media) {
4686 /* no need or expectation of this if
4687 * media is not being copied, because
4688 * it will be fast(ish).
4691 /* tell someone "X percent, file M of N"; M is one-based */
4693 boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
4701 throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
4707 /* copy optional folders, if any */
4709 string old = plugins_dir ();
4710 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4711 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4712 copy_files (old, newdir);
4715 old = externals_dir ();
4716 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4717 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4718 copy_files (old, newdir);
4721 old = automation_dir ();
4722 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4723 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4724 copy_files (old, newdir);
4727 if (saveas.include_media) {
4729 if (saveas.copy_media) {
4730 #ifndef PLATFORM_WINDOWS
4731 /* There are problems with analysis files on
4732 * Windows, because they used a colon in their
4733 * names as late as 4.0. Colons are not legal
4734 * under Windows even if NTFS allows them.
4736 * This is a tricky problem to solve so for
4737 * just don't copy these files. They will be
4738 * regenerated as-needed anyway, subject to the
4739 * existing issue that the filenames will be
4740 * rejected by Windows, which is a separate
4741 * problem (though related).
4744 /* only needed if we are copying media, since the
4745 * analysis data refers to media data
4748 old = analysis_dir ();
4749 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4750 string newdir = Glib::build_filename (to_dir, "analysis");
4751 copy_files (old, newdir);
4753 #endif /* PLATFORM_WINDOWS */
4759 set_snapshot_name (saveas.new_name);
4760 _name = saveas.new_name;
4762 if (saveas.include_media && !saveas.copy_media) {
4764 /* reset search paths of the new session (which we're pretending to be right now) to
4765 include the original session search path, so we can still find all audio.
4768 if (internal_file_cnt) {
4769 for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
4770 ensure_search_path_includes (*s, DataType::AUDIO);
4771 cerr << "be sure to include " << *s << " for audio" << endl;
4774 /* we do not do this for MIDI because we copy
4775 all MIDI files if saveas.include_media is
4781 bool was_dirty = dirty ();
4783 save_state ("", false, false, !saveas.include_media);
4784 save_default_options ();
4786 if (saveas.copy_media && saveas.copy_external) {
4787 if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
4788 throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
4792 saveas.final_session_folder_name = _path;
4794 store_recent_sessions (_name, _path);
4796 if (!saveas.switch_to) {
4798 /* switch back to the way things were */
4802 set_snapshot_name (old_snapshot);
4804 (*_session_dir) = old_sd;
4810 if (internal_file_cnt) {
4811 /* reset these to their original values */
4812 config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
4813 config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
4818 /* prune session dirs, and update disk space statistics
4823 session_dirs.clear ();
4824 session_dirs.push_back (sp);
4825 refresh_disk_space ();
4827 /* ensure that all existing tracks reset their current capture source paths
4829 reset_write_sources (true, true);
4831 /* the copying above was based on actually discovering files, not just iterating over the sources list.
4832 But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
4835 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4836 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4842 if (fs->within_session()) {
4843 string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
4844 fs->set_path (newpath);
4849 } catch (Glib::FileError& e) {
4851 saveas.failure_message = e.what();
4853 /* recursively remove all the directories */
4855 remove_directory (to_dir);
4863 saveas.failure_message = _("unknown reason");
4865 /* recursively remove all the directories */
4867 remove_directory (to_dir);