2 Copyright (C) 1999-2013 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "libardour-config.h"
30 #include <cstdio> /* snprintf(3) ... grrr */
42 #if defined(__APPLE__) || defined(__FreeBSD__)
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"
132 #include "pbd/i18n.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 node->add_property ("end-is-free", _session_range_end_is_free ? X_("yes") : X_("no"));
1100 /* save the ID counter */
1102 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1103 node->add_property ("id-counter", buf);
1105 snprintf (buf, sizeof (buf), "%u", name_id_counter ());
1106 node->add_property ("name-counter", buf);
1108 /* save the event ID counter */
1110 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1111 node->add_property ("event-counter", buf);
1113 /* save the VCA counter */
1115 snprintf (buf, sizeof (buf), "%" PRIu32, VCA::get_next_vca_number());
1116 node->add_property ("vca-counter", buf);
1118 /* various options */
1120 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
1121 if (!midi_port_nodes.empty()) {
1122 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
1123 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
1124 midi_port_stuff->add_child_nocopy (**n);
1126 node->add_child_nocopy (*midi_port_stuff);
1129 node->add_child_nocopy (config.get_variables ());
1131 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1133 child = node->add_child ("Sources");
1136 Glib::Threads::Mutex::Lock sl (source_lock);
1138 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1140 /* Don't save information about non-file Sources, or
1141 * about non-destructive file sources that are empty
1142 * and unused by any regions.
1145 boost::shared_ptr<FileSource> fs;
1147 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1149 if (!fs->destructive()) {
1150 if (fs->empty() && !fs->used()) {
1155 child->add_child_nocopy (siter->second->get_state());
1160 child = node->add_child ("Regions");
1163 Glib::Threads::Mutex::Lock rl (region_lock);
1164 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1165 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1166 boost::shared_ptr<Region> r = i->second;
1167 /* only store regions not attached to playlists */
1168 if (r->playlist() == 0) {
1169 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1170 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1172 child->add_child_nocopy (r->get_state ());
1177 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1179 if (!cassocs.empty()) {
1180 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1182 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1184 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1185 i->first->id().print (buf, sizeof (buf));
1186 can->add_property (X_("copy"), buf);
1187 i->second->id().print (buf, sizeof (buf));
1188 can->add_property (X_("original"), buf);
1189 ca->add_child_nocopy (*can);
1199 node->add_child_nocopy (_locations->get_state());
1202 Locations loc (*this);
1203 // for a template, just create a new Locations, populate it
1204 // with the default start and end, and get the state for that.
1205 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1206 range->set (max_framepos, 0);
1208 XMLNode& locations_state = loc.get_state();
1210 if (ARDOUR::Profile->get_trx() && _locations) {
1211 // For tracks we need stored the Auto Loop Range and all MIDI markers.
1212 for (Locations::LocationList::const_iterator i = _locations->list ().begin (); i != _locations->list ().end (); ++i) {
1213 if ((*i)->is_mark () || (*i)->is_auto_loop ()) {
1214 locations_state.add_child_nocopy ((*i)->get_state ());
1218 node->add_child_nocopy (locations_state);
1221 child = node->add_child ("Bundles");
1223 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1224 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1225 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1227 child->add_child_nocopy (b->get_state());
1232 node->add_child_nocopy (_vca_manager->get_state());
1234 child = node->add_child ("Routes");
1236 boost::shared_ptr<RouteList> r = routes.reader ();
1238 RoutePublicOrderSorter cmp;
1239 RouteList public_order (*r);
1240 public_order.sort (cmp);
1242 /* the sort should have put the monitor out first */
1245 assert (_monitor_out == public_order.front());
1248 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1249 if (!(*i)->is_auditioner()) {
1251 child->add_child_nocopy ((*i)->get_state());
1253 child->add_child_nocopy ((*i)->get_template());
1259 playlists->add_state (node, full_state);
1261 child = node->add_child ("RouteGroups");
1262 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1263 child->add_child_nocopy ((*i)->get_state());
1267 XMLNode* gain_child = node->add_child ("Click");
1268 gain_child->add_child_nocopy (_click_io->state (full_state));
1269 gain_child->add_child_nocopy (_click_gain->state (full_state));
1273 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1274 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1278 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1279 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1282 node->add_child_nocopy (_speakers->get_state());
1283 node->add_child_nocopy (_tempo_map->get_state());
1284 node->add_child_nocopy (get_control_protocol_state());
1287 node->add_child_copy (*_extra_xml);
1291 Glib::Threads::Mutex::Lock lm (lua_lock);
1294 luabridge::LuaRef savedstate ((*_lua_save)());
1295 saved = savedstate.cast<std::string>();
1297 lua.collect_garbage ();
1300 gchar* b64 = g_base64_encode ((const guchar*)saved.c_str (), saved.size ());
1301 std::string b64s (b64);
1304 XMLNode* script_node = new XMLNode (X_("Script"));
1305 script_node->add_property (X_("lua"), LUA_VERSION);
1306 script_node->add_content (b64s);
1307 node->add_child_nocopy (*script_node);
1314 Session::get_control_protocol_state ()
1316 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1317 return cpm.get_state();
1321 Session::set_state (const XMLNode& node, int version)
1326 XMLProperty const * prop;
1329 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1331 if (node.name() != X_("Session")) {
1332 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1336 if ((prop = node.property ("name")) != 0) {
1337 _name = prop->value ();
1340 if ((prop = node.property (X_("sample-rate"))) != 0) {
1342 _base_frame_rate = atoi (prop->value());
1343 _nominal_frame_rate = _base_frame_rate;
1345 assert (AudioEngine::instance()->running ());
1346 if (_base_frame_rate != AudioEngine::instance()->sample_rate ()) {
1347 boost::optional<int> r = AskAboutSampleRateMismatch (_base_frame_rate, _current_frame_rate);
1348 if (r.get_value_or (0)) {
1354 created_with = "unknown";
1355 if ((child = find_named_node (node, "ProgramVersion")) != 0) {
1356 if ((prop = child->property (X_("created-with"))) != 0) {
1357 created_with = prop->value ();
1361 setup_raid_path(_session_dir->root_path());
1363 if ((prop = node.property (X_("end-is-free"))) != 0) {
1364 _session_range_end_is_free = string_is_affirmative (prop->value());
1367 if ((prop = node.property (X_("id-counter"))) != 0) {
1369 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1370 ID::init_counter (x);
1372 /* old sessions used a timebased counter, so fake
1373 the startup ID counter based on a standard
1378 ID::init_counter (now);
1381 if ((prop = node.property (X_("name-counter"))) != 0) {
1382 init_name_id_counter (atoi (prop->value()));
1385 if ((prop = node.property (X_("event-counter"))) != 0) {
1386 Evoral::init_event_id_counter (atoi (prop->value()));
1389 if ((prop = node.property (X_("vca-counter"))) != 0) {
1391 sscanf (prop->value().c_str(), "%" PRIu32, &x);
1392 VCA::set_next_vca_number (x);
1394 VCA::set_next_vca_number (1);
1397 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1398 _midi_ports->set_midi_port_states (child->children());
1401 IO::disable_connecting ();
1403 Stateful::save_extra_xml (node);
1405 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1406 load_options (*child);
1407 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1408 load_options (*child);
1410 error << _("Session: XML state has no options section") << endmsg;
1413 if (version >= 3000) {
1414 if ((child = find_named_node (node, "Metadata")) == 0) {
1415 warning << _("Session: XML state has no metadata section") << endmsg;
1416 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1421 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1422 _speakers->set_state (*child, version);
1425 if ((child = find_named_node (node, "Sources")) == 0) {
1426 error << _("Session: XML state has no sources section") << endmsg;
1428 } else if (load_sources (*child)) {
1432 if ((child = find_named_node (node, "TempoMap")) == 0) {
1433 error << _("Session: XML state has no Tempo Map section") << endmsg;
1435 } else if (_tempo_map->set_state (*child, version)) {
1439 if ((child = find_named_node (node, "Locations")) == 0) {
1440 error << _("Session: XML state has no locations section") << endmsg;
1442 } else if (_locations->set_state (*child, version)) {
1446 locations_changed ();
1448 if (_session_range_location) {
1449 AudioFileSource::set_header_position_offset (_session_range_location->start());
1452 if ((child = find_named_node (node, "Regions")) == 0) {
1453 error << _("Session: XML state has no Regions section") << endmsg;
1455 } else if (load_regions (*child)) {
1459 if ((child = find_named_node (node, "Playlists")) == 0) {
1460 error << _("Session: XML state has no playlists section") << endmsg;
1462 } else if (playlists->load (*this, *child)) {
1466 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1468 } else if (playlists->load_unused (*this, *child)) {
1472 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1473 if (load_compounds (*child)) {
1478 if (version >= 3000) {
1479 if ((child = find_named_node (node, "Bundles")) == 0) {
1480 warning << _("Session: XML state has no bundles section") << endmsg;
1483 /* We can't load Bundles yet as they need to be able
1484 to convert from port names to Port objects, which can't happen until
1486 _bundle_xml_node = new XMLNode (*child);
1490 if (version < 3000) {
1491 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1492 error << _("Session: XML state has no diskstreams section") << endmsg;
1494 } else if (load_diskstreams_2X (*child, version)) {
1499 if ((child = find_named_node (node, VCAManager::xml_node_name)) != 0) {
1500 _vca_manager->set_state (*child, version);
1503 if ((child = find_named_node (node, "Routes")) == 0) {
1504 error << _("Session: XML state has no routes section") << endmsg;
1506 } else if (load_routes (*child, version)) {
1510 /* Now that we have Routes and masters loaded, connect them if appropriate */
1512 Slavable::Assign (_vca_manager); /* EMIT SIGNAL */
1514 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1515 _diskstreams_2X.clear ();
1517 if (version >= 3000) {
1519 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1520 error << _("Session: XML state has no route groups section") << endmsg;
1522 } else if (load_route_groups (*child, version)) {
1526 } else if (version < 3000) {
1528 if ((child = find_named_node (node, "EditGroups")) == 0) {
1529 error << _("Session: XML state has no edit groups section") << endmsg;
1531 } else if (load_route_groups (*child, version)) {
1535 if ((child = find_named_node (node, "MixGroups")) == 0) {
1536 error << _("Session: XML state has no mix groups section") << endmsg;
1538 } else if (load_route_groups (*child, version)) {
1543 if ((child = find_named_node (node, "Click")) == 0) {
1544 warning << _("Session: XML state has no click section") << endmsg;
1545 } else if (_click_io) {
1546 setup_click_state (&node);
1549 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1550 ControlProtocolManager::instance().set_state (*child, version);
1553 if ((child = find_named_node (node, "Script"))) {
1554 for (XMLNodeList::const_iterator n = child->children ().begin (); n != child->children ().end (); ++n) {
1555 if (!(*n)->is_content ()) { continue; }
1557 guchar* buf = g_base64_decode ((*n)->content ().c_str (), &size);
1559 Glib::Threads::Mutex::Lock lm (lua_lock);
1560 (*_lua_load)(std::string ((const char*)buf, size));
1561 } catch (luabridge::LuaException const& e) {
1562 cerr << "LuaException:" << e.what () << endl;
1568 update_route_record_state ();
1570 /* here beginneth the second phase ... */
1571 set_snapshot_name (_current_snapshot_name);
1573 StateReady (); /* EMIT SIGNAL */
1586 Session::load_routes (const XMLNode& node, int version)
1589 XMLNodeConstIterator niter;
1590 RouteList new_routes;
1592 nlist = node.children();
1596 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1598 boost::shared_ptr<Route> route;
1599 if (version < 3000) {
1600 route = XMLRouteFactory_2X (**niter, version);
1602 route = XMLRouteFactory (**niter, version);
1606 error << _("Session: cannot create Route from XML description.") << endmsg;
1610 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1612 new_routes.push_back (route);
1615 BootMessage (_("Tracks/busses loaded; Adding to Session"));
1617 add_routes (new_routes, false, false, false, PresentationInfo::max_order);
1619 BootMessage (_("Finished adding tracks/busses"));
1624 boost::shared_ptr<Route>
1625 Session::XMLRouteFactory (const XMLNode& node, int version)
1627 boost::shared_ptr<Route> ret;
1629 if (node.name() != "Route") {
1633 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1635 DataType type = DataType::AUDIO;
1636 XMLProperty const * prop = node.property("default-type");
1639 type = DataType (prop->value());
1642 assert (type != DataType::NIL);
1646 boost::shared_ptr<Track> track;
1648 if (type == DataType::AUDIO) {
1649 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1651 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1654 if (track->init()) {
1658 if (track->set_state (node, version)) {
1662 BOOST_MARK_TRACK (track);
1666 PresentationInfo::Flag flags = PresentationInfo::get_flags (node);
1667 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1669 if (r->init () == 0 && r->set_state (node, version) == 0) {
1670 BOOST_MARK_ROUTE (r);
1678 boost::shared_ptr<Route>
1679 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1681 boost::shared_ptr<Route> ret;
1683 if (node.name() != "Route") {
1687 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1689 ds_prop = node.property (X_("diskstream"));
1692 DataType type = DataType::AUDIO;
1693 XMLProperty const * prop = node.property("default-type");
1696 type = DataType (prop->value());
1699 assert (type != DataType::NIL);
1703 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1704 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1708 if (i == _diskstreams_2X.end()) {
1709 error << _("Could not find diskstream for route") << endmsg;
1710 return boost::shared_ptr<Route> ();
1713 boost::shared_ptr<Track> track;
1715 if (type == DataType::AUDIO) {
1716 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1718 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1721 if (track->init()) {
1725 if (track->set_state (node, version)) {
1729 track->set_diskstream (*i);
1731 BOOST_MARK_TRACK (track);
1735 PresentationInfo::Flag flags = PresentationInfo::get_flags (node);
1736 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1738 if (r->init () == 0 && r->set_state (node, version) == 0) {
1739 BOOST_MARK_ROUTE (r);
1748 Session::load_regions (const XMLNode& node)
1751 XMLNodeConstIterator niter;
1752 boost::shared_ptr<Region> region;
1754 nlist = node.children();
1758 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1759 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1760 error << _("Session: cannot create Region from XML description.");
1761 XMLProperty const * name = (**niter).property("name");
1764 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1775 Session::load_compounds (const XMLNode& node)
1777 XMLNodeList calist = node.children();
1778 XMLNodeConstIterator caiter;
1779 XMLProperty const * caprop;
1781 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1782 XMLNode* ca = *caiter;
1786 if ((caprop = ca->property (X_("original"))) == 0) {
1789 orig_id = caprop->value();
1791 if ((caprop = ca->property (X_("copy"))) == 0) {
1794 copy_id = caprop->value();
1796 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1797 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1799 if (!orig || !copy) {
1800 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1806 RegionFactory::add_compound_association (orig, copy);
1813 Session::load_nested_sources (const XMLNode& node)
1816 XMLNodeConstIterator niter;
1818 nlist = node.children();
1820 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1821 if ((*niter)->name() == "Source") {
1823 /* it may already exist, so don't recreate it unnecessarily
1826 XMLProperty const * prop = (*niter)->property (X_("id"));
1828 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1832 ID source_id (prop->value());
1834 if (!source_by_id (source_id)) {
1837 SourceFactory::create (*this, **niter, true);
1839 catch (failed_constructor& err) {
1840 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1847 boost::shared_ptr<Region>
1848 Session::XMLRegionFactory (const XMLNode& node, bool full)
1850 XMLProperty const * type = node.property("type");
1854 const XMLNodeList& nlist = node.children();
1856 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1857 XMLNode *child = (*niter);
1858 if (child->name() == "NestedSource") {
1859 load_nested_sources (*child);
1863 if (!type || type->value() == "audio") {
1864 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1865 } else if (type->value() == "midi") {
1866 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1869 } catch (failed_constructor& err) {
1870 return boost::shared_ptr<Region> ();
1873 return boost::shared_ptr<Region> ();
1876 boost::shared_ptr<AudioRegion>
1877 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1879 XMLProperty const * prop;
1880 boost::shared_ptr<Source> source;
1881 boost::shared_ptr<AudioSource> as;
1883 SourceList master_sources;
1884 uint32_t nchans = 1;
1887 if (node.name() != X_("Region")) {
1888 return boost::shared_ptr<AudioRegion>();
1891 if ((prop = node.property (X_("channels"))) != 0) {
1892 nchans = atoi (prop->value().c_str());
1895 if ((prop = node.property ("name")) == 0) {
1896 cerr << "no name for this region\n";
1900 if ((prop = node.property (X_("source-0"))) == 0) {
1901 if ((prop = node.property ("source")) == 0) {
1902 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1903 return boost::shared_ptr<AudioRegion>();
1907 PBD::ID s_id (prop->value());
1909 if ((source = source_by_id (s_id)) == 0) {
1910 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1911 return boost::shared_ptr<AudioRegion>();
1914 as = boost::dynamic_pointer_cast<AudioSource>(source);
1916 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1917 return boost::shared_ptr<AudioRegion>();
1920 sources.push_back (as);
1922 /* pickup other channels */
1924 for (uint32_t n=1; n < nchans; ++n) {
1925 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1926 if ((prop = node.property (buf)) != 0) {
1928 PBD::ID id2 (prop->value());
1930 if ((source = source_by_id (id2)) == 0) {
1931 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1932 return boost::shared_ptr<AudioRegion>();
1935 as = boost::dynamic_pointer_cast<AudioSource>(source);
1937 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1938 return boost::shared_ptr<AudioRegion>();
1940 sources.push_back (as);
1944 for (uint32_t n = 0; n < nchans; ++n) {
1945 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1946 if ((prop = node.property (buf)) != 0) {
1948 PBD::ID id2 (prop->value());
1950 if ((source = source_by_id (id2)) == 0) {
1951 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1952 return boost::shared_ptr<AudioRegion>();
1955 as = boost::dynamic_pointer_cast<AudioSource>(source);
1957 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1958 return boost::shared_ptr<AudioRegion>();
1960 master_sources.push_back (as);
1965 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1967 /* a final detail: this is the one and only place that we know how long missing files are */
1969 if (region->whole_file()) {
1970 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1971 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1973 sfp->set_length (region->length());
1978 if (!master_sources.empty()) {
1979 if (master_sources.size() != nchans) {
1980 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1982 region->set_master_sources (master_sources);
1990 catch (failed_constructor& err) {
1991 return boost::shared_ptr<AudioRegion>();
1995 boost::shared_ptr<MidiRegion>
1996 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1998 XMLProperty const * prop;
1999 boost::shared_ptr<Source> source;
2000 boost::shared_ptr<MidiSource> ms;
2003 if (node.name() != X_("Region")) {
2004 return boost::shared_ptr<MidiRegion>();
2007 if ((prop = node.property ("name")) == 0) {
2008 cerr << "no name for this region\n";
2012 if ((prop = node.property (X_("source-0"))) == 0) {
2013 if ((prop = node.property ("source")) == 0) {
2014 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
2015 return boost::shared_ptr<MidiRegion>();
2019 PBD::ID s_id (prop->value());
2021 if ((source = source_by_id (s_id)) == 0) {
2022 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
2023 return boost::shared_ptr<MidiRegion>();
2026 ms = boost::dynamic_pointer_cast<MidiSource>(source);
2028 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
2029 return boost::shared_ptr<MidiRegion>();
2032 sources.push_back (ms);
2035 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
2036 /* a final detail: this is the one and only place that we know how long missing files are */
2038 if (region->whole_file()) {
2039 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
2040 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
2042 sfp->set_length (region->length());
2050 catch (failed_constructor& err) {
2051 return boost::shared_ptr<MidiRegion>();
2056 Session::get_sources_as_xml ()
2059 XMLNode* node = new XMLNode (X_("Sources"));
2060 Glib::Threads::Mutex::Lock lm (source_lock);
2062 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2063 node->add_child_nocopy (i->second->get_state());
2070 Session::reset_write_sources (bool mark_write_complete, bool force)
2072 boost::shared_ptr<RouteList> rl = routes.reader();
2073 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
2074 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
2076 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
2077 tr->reset_write_sources(mark_write_complete, force);
2078 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
2084 Session::load_sources (const XMLNode& node)
2087 XMLNodeConstIterator niter;
2088 boost::shared_ptr<Source> source; /* don't need this but it stops some
2089 * versions of gcc complaining about
2090 * discarded return values.
2093 nlist = node.children();
2097 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2100 if ((source = XMLSourceFactory (**niter)) == 0) {
2101 error << _("Session: cannot create Source from XML description.") << endmsg;
2104 } catch (MissingSource& err) {
2108 if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
2109 error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
2110 PROGRAM_NAME) << endmsg;
2114 if (!no_questions_about_missing_files) {
2115 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
2120 switch (user_choice) {
2122 /* user added a new search location, so try again */
2127 /* user asked to quit the entire session load
2132 no_questions_about_missing_files = true;
2136 no_questions_about_missing_files = true;
2143 case DataType::AUDIO:
2144 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
2147 case DataType::MIDI:
2148 /* The MIDI file is actually missing so
2149 * just create a new one in the same
2150 * location. Do not announce its
2154 if (!Glib::path_is_absolute (err.path)) {
2155 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
2157 /* this should be an unrecoverable error: we would be creating a MIDI file outside
2162 /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
2163 source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
2164 /* reset ID to match the missing one */
2165 source->set_id (**niter);
2166 /* Now we can announce it */
2167 SourceFactory::SourceCreated (source);
2178 boost::shared_ptr<Source>
2179 Session::XMLSourceFactory (const XMLNode& node)
2181 if (node.name() != "Source") {
2182 return boost::shared_ptr<Source>();
2186 /* note: do peak building in another thread when loading session state */
2187 return SourceFactory::create (*this, node, true);
2190 catch (failed_constructor& err) {
2191 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
2192 return boost::shared_ptr<Source>();
2197 Session::save_template (string template_name, bool replace_existing)
2199 if ((_state_of_the_state & CannotSave) || template_name.empty ()) {
2203 bool absolute_path = Glib::path_is_absolute (template_name);
2205 /* directory to put the template in */
2206 std::string template_dir_path;
2208 if (!absolute_path) {
2209 std::string user_template_dir(user_template_directory());
2211 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2212 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2213 user_template_dir, g_strerror (errno)) << endmsg;
2217 template_dir_path = Glib::build_filename (user_template_dir, template_name);
2219 template_dir_path = template_name;
2222 if (!ARDOUR::Profile->get_trx()) {
2223 if (!replace_existing && Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2224 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2225 template_dir_path) << endmsg;
2229 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2230 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2231 template_dir_path, g_strerror (errno)) << endmsg;
2237 std::string template_file_path;
2239 if (ARDOUR::Profile->get_trx()) {
2240 template_file_path = template_name;
2242 if (absolute_path) {
2243 template_file_path = Glib::build_filename (template_dir_path, Glib::path_get_basename (template_dir_path) + template_suffix);
2245 template_file_path = Glib::build_filename (template_dir_path, template_name + template_suffix);
2249 SessionSaveUnderway (); /* EMIT SIGNAL */
2254 PBD::Unwinder<std::string> uw (_template_state_dir, template_dir_path);
2255 tree.set_root (&get_template());
2258 if (!tree.write (template_file_path)) {
2259 error << _("template not saved") << endmsg;
2263 store_recent_templates (template_file_path);
2269 Session::refresh_disk_space ()
2271 #if __APPLE__ || __FreeBSD__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2273 Glib::Threads::Mutex::Lock lm (space_lock);
2275 /* get freespace on every FS that is part of the session path */
2277 _total_free_4k_blocks = 0;
2278 _total_free_4k_blocks_uncertain = false;
2280 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2282 struct statfs statfsbuf;
2283 statfs (i->path.c_str(), &statfsbuf);
2285 double const scale = statfsbuf.f_bsize / 4096.0;
2287 /* See if this filesystem is read-only */
2288 struct statvfs statvfsbuf;
2289 statvfs (i->path.c_str(), &statvfsbuf);
2291 /* f_bavail can be 0 if it is undefined for whatever
2292 filesystem we are looking at; Samba shares mounted
2293 via GVFS are an example of this.
2295 if (statfsbuf.f_bavail == 0) {
2296 /* block count unknown */
2298 i->blocks_unknown = true;
2299 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2300 /* read-only filesystem */
2302 i->blocks_unknown = false;
2304 /* read/write filesystem with known space */
2305 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2306 i->blocks_unknown = false;
2309 _total_free_4k_blocks += i->blocks;
2310 if (i->blocks_unknown) {
2311 _total_free_4k_blocks_uncertain = true;
2314 #elif defined PLATFORM_WINDOWS
2315 vector<string> scanned_volumes;
2316 vector<string>::iterator j;
2317 vector<space_and_path>::iterator i;
2318 DWORD nSectorsPerCluster, nBytesPerSector,
2319 nFreeClusters, nTotalClusters;
2323 _total_free_4k_blocks = 0;
2325 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2326 strncpy (disk_drive, (*i).path.c_str(), 3);
2330 volume_found = false;
2331 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2333 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2334 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2335 i->blocks = (uint32_t)(nFreeBytes / 4096);
2337 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2338 if (0 == j->compare(disk_drive)) {
2339 volume_found = true;
2344 if (!volume_found) {
2345 scanned_volumes.push_back(disk_drive);
2346 _total_free_4k_blocks += i->blocks;
2351 if (0 == _total_free_4k_blocks) {
2352 strncpy (disk_drive, path().c_str(), 3);
2355 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2357 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2358 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2359 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2366 Session::get_best_session_directory_for_new_audio ()
2368 vector<space_and_path>::iterator i;
2369 string result = _session_dir->root_path();
2371 /* handle common case without system calls */
2373 if (session_dirs.size() == 1) {
2377 /* OK, here's the algorithm we're following here:
2379 We want to select which directory to use for
2380 the next file source to be created. Ideally,
2381 we'd like to use a round-robin process so as to
2382 get maximum performance benefits from splitting
2383 the files across multiple disks.
2385 However, in situations without much diskspace, an
2386 RR approach may end up filling up a filesystem
2387 with new files while others still have space.
2388 Its therefore important to pay some attention to
2389 the freespace in the filesystem holding each
2390 directory as well. However, if we did that by
2391 itself, we'd keep creating new files in the file
2392 system with the most space until it was as full
2393 as all others, thus negating any performance
2394 benefits of this RAID-1 like approach.
2396 So, we use a user-configurable space threshold. If
2397 there are at least 2 filesystems with more than this
2398 much space available, we use RR selection between them.
2399 If not, then we pick the filesystem with the most space.
2401 This gets a good balance between the two
2405 refresh_disk_space ();
2407 int free_enough = 0;
2409 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2410 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2415 if (free_enough >= 2) {
2416 /* use RR selection process, ensuring that the one
2420 i = last_rr_session_dir;
2423 if (++i == session_dirs.end()) {
2424 i = session_dirs.begin();
2427 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2428 SessionDirectory sdir(i->path);
2429 if (sdir.create ()) {
2431 last_rr_session_dir = i;
2436 } while (i != last_rr_session_dir);
2440 /* pick FS with the most freespace (and that
2441 seems to actually work ...)
2444 vector<space_and_path> sorted;
2445 space_and_path_ascending_cmp cmp;
2447 sorted = session_dirs;
2448 sort (sorted.begin(), sorted.end(), cmp);
2450 for (i = sorted.begin(); i != sorted.end(); ++i) {
2451 SessionDirectory sdir(i->path);
2452 if (sdir.create ()) {
2454 last_rr_session_dir = i;
2464 Session::automation_dir () const
2466 return Glib::build_filename (_path, automation_dir_name);
2470 Session::analysis_dir () const
2472 return Glib::build_filename (_path, analysis_dir_name);
2476 Session::plugins_dir () const
2478 return Glib::build_filename (_path, plugins_dir_name);
2482 Session::externals_dir () const
2484 return Glib::build_filename (_path, externals_dir_name);
2488 Session::load_bundles (XMLNode const & node)
2490 XMLNodeList nlist = node.children();
2491 XMLNodeConstIterator niter;
2495 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2496 if ((*niter)->name() == "InputBundle") {
2497 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2498 } else if ((*niter)->name() == "OutputBundle") {
2499 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2501 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2510 Session::load_route_groups (const XMLNode& node, int version)
2512 XMLNodeList nlist = node.children();
2513 XMLNodeConstIterator niter;
2517 if (version >= 3000) {
2519 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2520 if ((*niter)->name() == "RouteGroup") {
2521 RouteGroup* rg = new RouteGroup (*this, "");
2522 add_route_group (rg);
2523 rg->set_state (**niter, version);
2527 } else if (version < 3000) {
2529 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2530 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2531 RouteGroup* rg = new RouteGroup (*this, "");
2532 add_route_group (rg);
2533 rg->set_state (**niter, version);
2542 state_file_filter (const string &str, void* /*arg*/)
2544 return (str.length() > strlen(statefile_suffix) &&
2545 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2549 remove_end(string state)
2551 string statename(state);
2553 string::size_type start,end;
2554 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2555 statename = statename.substr (start+1);
2558 if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2559 end = statename.length();
2562 return string(statename.substr (0, end));
2566 Session::possible_states (string path)
2568 vector<string> states;
2569 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2571 transform(states.begin(), states.end(), states.begin(), remove_end);
2573 sort (states.begin(), states.end());
2579 Session::possible_states () const
2581 return possible_states(_path);
2585 Session::add_route_group (RouteGroup* g)
2587 _route_groups.push_back (g);
2588 route_group_added (g); /* EMIT SIGNAL */
2590 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2591 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2592 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2598 Session::remove_route_group (RouteGroup& rg)
2600 list<RouteGroup*>::iterator i;
2602 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2603 _route_groups.erase (i);
2606 route_group_removed (); /* EMIT SIGNAL */
2610 /** Set a new order for our route groups, without adding or removing any.
2611 * @param groups Route group list in the new order.
2614 Session::reorder_route_groups (list<RouteGroup*> groups)
2616 _route_groups = groups;
2618 route_groups_reordered (); /* EMIT SIGNAL */
2624 Session::route_group_by_name (string name)
2626 list<RouteGroup *>::iterator i;
2628 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2629 if ((*i)->name() == name) {
2637 Session::all_route_group() const
2639 return *_all_route_group;
2643 Session::add_commands (vector<Command*> const & cmds)
2645 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2651 Session::add_command (Command* const cmd)
2653 assert (_current_trans);
2654 DEBUG_UNDO_HISTORY (
2655 string_compose ("Current Undo Transaction %1, adding command: %2",
2656 _current_trans->name (),
2658 _current_trans->add_command (cmd);
2661 PBD::StatefulDiffCommand*
2662 Session::add_stateful_diff_command (boost::shared_ptr<PBD::StatefulDestructible> sfd)
2664 PBD::StatefulDiffCommand* cmd = new PBD::StatefulDiffCommand (sfd);
2670 Session::begin_reversible_command (const string& name)
2672 begin_reversible_command (g_quark_from_string (name.c_str ()));
2675 /** Begin a reversible command using a GQuark to identify it.
2676 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2677 * but there must be as many begin...()s as there are commit...()s.
2680 Session::begin_reversible_command (GQuark q)
2682 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2683 to hold all the commands that are committed. This keeps the order of
2684 commands correct in the history.
2687 if (_current_trans == 0) {
2688 DEBUG_UNDO_HISTORY (string_compose (
2689 "Begin Reversible Command, new transaction: %1", g_quark_to_string (q)));
2691 /* start a new transaction */
2692 assert (_current_trans_quarks.empty ());
2693 _current_trans = new UndoTransaction();
2694 _current_trans->set_name (g_quark_to_string (q));
2696 DEBUG_UNDO_HISTORY (
2697 string_compose ("Begin Reversible Command, current transaction: %1",
2698 _current_trans->name ()));
2701 _current_trans_quarks.push_front (q);
2705 Session::abort_reversible_command ()
2707 if (_current_trans != 0) {
2708 DEBUG_UNDO_HISTORY (
2709 string_compose ("Abort Reversible Command: %1", _current_trans->name ()));
2710 _current_trans->clear();
2711 delete _current_trans;
2713 _current_trans_quarks.clear();
2718 Session::commit_reversible_command (Command *cmd)
2720 assert (_current_trans);
2721 assert (!_current_trans_quarks.empty ());
2726 DEBUG_UNDO_HISTORY (
2727 string_compose ("Current Undo Transaction %1, adding command: %2",
2728 _current_trans->name (),
2730 _current_trans->add_command (cmd);
2733 DEBUG_UNDO_HISTORY (
2734 string_compose ("Commit Reversible Command, current transaction: %1",
2735 _current_trans->name ()));
2737 _current_trans_quarks.pop_front ();
2739 if (!_current_trans_quarks.empty ()) {
2740 DEBUG_UNDO_HISTORY (
2741 string_compose ("Commit Reversible Command, transaction is not "
2742 "top-level, current transaction: %1",
2743 _current_trans->name ()));
2744 /* the transaction we're committing is not the top-level one */
2748 if (_current_trans->empty()) {
2749 /* no commands were added to the transaction, so just get rid of it */
2750 DEBUG_UNDO_HISTORY (
2751 string_compose ("Commit Reversible Command, No commands were "
2752 "added to current transaction: %1",
2753 _current_trans->name ()));
2754 delete _current_trans;
2759 gettimeofday (&now, 0);
2760 _current_trans->set_timestamp (now);
2762 _history.add (_current_trans);
2767 accept_all_audio_files (const string& path, void* /*arg*/)
2769 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2773 if (!AudioFileSource::safe_audio_file_extension (path)) {
2781 accept_all_midi_files (const string& path, void* /*arg*/)
2783 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2787 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2788 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2789 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2793 accept_all_state_files (const string& path, void* /*arg*/)
2795 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2799 std::string const statefile_ext (statefile_suffix);
2800 if (path.length() >= statefile_ext.length()) {
2801 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2808 Session::find_all_sources (string path, set<string>& result)
2813 if (!tree.read (path)) {
2817 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2822 XMLNodeConstIterator niter;
2824 nlist = node->children();
2828 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2830 XMLProperty const * prop;
2832 if ((prop = (*niter)->property (X_("type"))) == 0) {
2836 DataType type (prop->value());
2838 if ((prop = (*niter)->property (X_("name"))) == 0) {
2842 if (Glib::path_is_absolute (prop->value())) {
2843 /* external file, ignore */
2851 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2852 result.insert (found_path);
2860 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2862 vector<string> state_files;
2864 string this_snapshot_path;
2870 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2871 ripped = ripped.substr (0, ripped.length() - 1);
2874 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2876 if (state_files.empty()) {
2881 this_snapshot_path = Glib::build_filename (_path, legalize_for_path (_current_snapshot_name));
2882 this_snapshot_path += statefile_suffix;
2884 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2886 cerr << "Looking at snapshot " << (*i) << " ( with this = [" << this_snapshot_path << "])\n";
2888 if (exclude_this_snapshot && *i == this_snapshot_path) {
2889 cerr << "\texcluded\n";
2894 if (find_all_sources (*i, result) < 0) {
2902 struct RegionCounter {
2903 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2904 AudioSourceList::iterator iter;
2905 boost::shared_ptr<Region> region;
2908 RegionCounter() : count (0) {}
2912 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2914 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2915 return r.get_value_or (1);
2919 Session::cleanup_regions ()
2921 bool removed = false;
2922 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2924 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2926 uint32_t used = playlists->region_use_count (i->second);
2928 if (used == 0 && !i->second->automatic ()) {
2929 boost::weak_ptr<Region> w = i->second;
2932 RegionFactory::map_remove (w);
2939 // re-check to remove parent references of compound regions
2940 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2941 if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2945 assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2946 if (0 == playlists->region_use_count (i->second)) {
2947 boost::weak_ptr<Region> w = i->second;
2949 RegionFactory::map_remove (w);
2956 /* dump the history list */
2963 Session::can_cleanup_peakfiles () const
2965 if (deletion_in_progress()) {
2968 if (!_writable || (_state_of_the_state & CannotSave)) {
2969 warning << _("Cannot cleanup peak-files for read-only session.") << endmsg;
2972 if (record_status() == Recording) {
2973 error << _("Cannot cleanup peak-files while recording") << endmsg;
2980 Session::cleanup_peakfiles ()
2982 Glib::Threads::Mutex::Lock lm (peak_cleanup_lock, Glib::Threads::TRY_LOCK);
2987 assert (can_cleanup_peakfiles ());
2988 assert (!peaks_cleanup_in_progres());
2990 _state_of_the_state = StateOfTheState (_state_of_the_state | PeakCleanup);
2992 int timeout = 5000; // 5 seconds
2993 while (!SourceFactory::files_with_peaks.empty()) {
2994 Glib::usleep (1000);
2995 if (--timeout < 0) {
2996 warning << _("Timeout waiting for peak-file creation to terminate before cleanup, please try again later.") << endmsg;
2997 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
3002 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3003 boost::shared_ptr<AudioSource> as;
3004 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
3005 as->close_peakfile();
3009 PBD::clear_directory (session_directory().peak_path());
3011 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
3013 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3014 boost::shared_ptr<AudioSource> as;
3015 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
3016 SourceFactory::setup_peakfile(as, true);
3023 merge_all_sources (boost::shared_ptr<const Playlist> pl, std::set<boost::shared_ptr<Source> >* all_sources)
3025 pl->deep_sources (*all_sources);
3029 Session::cleanup_sources (CleanupReport& rep)
3031 // FIXME: needs adaptation to midi
3033 vector<boost::shared_ptr<Source> > dead_sources;
3036 vector<string> candidates;
3037 vector<string> unused;
3038 set<string> sources_used_by_all_snapshots;
3045 set<boost::shared_ptr<Source> > sources_used_by_this_snapshot;
3047 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
3049 /* this is mostly for windows which doesn't allow file
3050 * renaming if the file is in use. But we don't special
3051 * case it because we need to know if this causes
3052 * problems, and the easiest way to notice that is to
3053 * keep it in place for all platforms.
3056 request_stop (false);
3058 _butler->wait_until_finished ();
3060 /* consider deleting all unused playlists */
3062 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
3067 /* sync the "all regions" property of each playlist with its current state
3070 playlists->sync_all_regions_with_regions ();
3072 /* find all un-used sources */
3077 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3079 SourceMap::iterator tmp;
3084 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
3088 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
3089 dead_sources.push_back (i->second);
3090 i->second->drop_references ();
3096 /* build a list of all the possible audio directories for the session */
3098 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3099 SessionDirectory sdir ((*i).path);
3100 asp += sdir.sound_path();
3102 audio_path += asp.to_string();
3105 /* build a list of all the possible midi directories for the session */
3107 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3108 SessionDirectory sdir ((*i).path);
3109 msp += sdir.midi_path();
3111 midi_path += msp.to_string();
3113 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
3114 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
3116 /* add sources from all other snapshots as "used", but don't use this
3117 snapshot because the state file on disk still references sources we
3118 may have already dropped.
3121 find_all_sources_across_snapshots (sources_used_by_all_snapshots, true);
3123 /* Although the region factory has a list of all regions ever created
3124 * for this session, we're only interested in regions actually in
3125 * playlists right now. So merge all playlist regions lists together.
3127 * This will include the playlists used within compound regions.
3130 playlists->foreach (boost::bind (merge_all_sources, _1, &sources_used_by_this_snapshot));
3132 /* add our current source list
3135 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3136 boost::shared_ptr<FileSource> fs;
3137 SourceMap::iterator tmp = i;
3140 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) == 0) {
3146 /* this is mostly for windows which doesn't allow file
3147 * renaming if the file is in use. But we do not special
3148 * case it because we need to know if this causes
3149 * problems, and the easiest way to notice that is to
3150 * keep it in place for all platforms.
3155 if (!fs->is_stub()) {
3157 /* Note that we're checking a list of all
3158 * sources across all snapshots with the list
3159 * of sources used by this snapshot.
3162 if (sources_used_by_this_snapshot.find (i->second) != sources_used_by_this_snapshot.end()) {
3163 /* this source is in use by this snapshot */
3164 sources_used_by_all_snapshots.insert (fs->path());
3165 cerr << "Source from source list found in used_by_this_snapshot (" << fs->path() << ")\n";
3167 cerr << "Source from source list NOT found in used_by_this_snapshot (" << fs->path() << ")\n";
3168 /* this source is NOT in use by this snapshot
3171 /* remove all related regions from RegionFactory master list
3174 RegionFactory::remove_regions_using_source (i->second);
3176 /* remove from our current source list
3177 * also. We may not remove it from
3178 * disk, because it may be used by
3179 * other snapshots, but it isn't used inside this
3180 * snapshot anymore, so we don't need a
3191 /* now check each candidate source to see if it exists in the list of
3192 sources_used_by_all_snapshots. If it doesn't, put it into "unused".
3195 cerr << "Candidates: " << candidates.size() << endl;
3196 cerr << "Used by others: " << sources_used_by_all_snapshots.size() << endl;
3198 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
3203 for (set<string>::iterator i = sources_used_by_all_snapshots.begin(); i != sources_used_by_all_snapshots.end(); ++i) {
3205 tmppath1 = canonical_path (spath);
3206 tmppath2 = canonical_path ((*i));
3208 cerr << "\t => " << tmppath2 << endl;
3210 if (tmppath1 == tmppath2) {
3217 unused.push_back (spath);
3221 cerr << "Actually unused: " << unused.size() << endl;
3223 if (unused.empty()) {
3229 /* now try to move all unused files into the "dead" directory(ies) */
3231 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
3236 /* don't move the file across filesystems, just
3237 stick it in the `dead_dir_name' directory
3238 on whichever filesystem it was already on.
3241 if ((*x).find ("/sounds/") != string::npos) {
3243 /* old school, go up 1 level */
3245 newpath = Glib::path_get_dirname (*x); // "sounds"
3246 newpath = Glib::path_get_dirname (newpath); // "session-name"
3250 /* new school, go up 4 levels */
3252 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
3253 newpath = Glib::path_get_dirname (newpath); // "session-name"
3254 newpath = Glib::path_get_dirname (newpath); // "interchange"
3255 newpath = Glib::path_get_dirname (newpath); // "session-dir"
3258 newpath = Glib::build_filename (newpath, dead_dir_name);
3260 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
3261 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
3265 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
3267 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
3269 /* the new path already exists, try versioning */
3271 char buf[PATH_MAX+1];
3275 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3278 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
3279 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3283 if (version == 999) {
3284 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3288 newpath = newpath_v;
3293 g_stat ((*x).c_str(), &statbuf);
3295 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3296 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"), (*x), newpath, strerror (errno)) << endmsg;
3300 /* see if there an easy to find peakfile for this file, and remove it.
3303 string base = Glib::path_get_basename (*x);
3304 base += "%A"; /* this is what we add for the channel suffix of all native files,
3305 or for the first channel of embedded files. it will miss
3306 some peakfiles for other channels
3308 string peakpath = construct_peak_filepath (base);
3310 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
3311 if (::g_unlink (peakpath.c_str()) != 0) {
3312 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3313 peakpath, _path, strerror (errno))
3315 /* try to back out */
3316 ::rename (newpath.c_str(), _path.c_str());
3321 rep.paths.push_back (*x);
3322 rep.space += statbuf.st_size;
3325 /* dump the history list */
3329 /* save state so we don't end up a session file
3330 referring to non-existent sources.
3337 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3343 Session::cleanup_trash_sources (CleanupReport& rep)
3345 // FIXME: needs adaptation for MIDI
3347 vector<space_and_path>::iterator i;
3353 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3355 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
3357 clear_directory (dead_dir, &rep.space, &rep.paths);
3364 Session::set_dirty ()
3366 /* never mark session dirty during loading */
3368 if (_state_of_the_state & Loading) {
3372 bool was_dirty = dirty();
3374 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3378 DirtyChanged(); /* EMIT SIGNAL */
3384 Session::set_clean ()
3386 bool was_dirty = dirty();
3388 _state_of_the_state = Clean;
3392 DirtyChanged(); /* EMIT SIGNAL */
3397 Session::set_deletion_in_progress ()
3399 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3403 Session::clear_deletion_in_progress ()
3405 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3409 Session::add_controllable (boost::shared_ptr<Controllable> c)
3411 /* this adds a controllable to the list managed by the Session.
3412 this is a subset of those managed by the Controllable class
3413 itself, and represents the only ones whose state will be saved
3414 as part of the session.
3417 Glib::Threads::Mutex::Lock lm (controllables_lock);
3418 controllables.insert (c);
3421 struct null_deleter { void operator()(void const *) const {} };
3424 Session::remove_controllable (Controllable* c)
3426 if (_state_of_the_state & Deletion) {
3430 Glib::Threads::Mutex::Lock lm (controllables_lock);
3432 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3434 if (x != controllables.end()) {
3435 controllables.erase (x);
3439 boost::shared_ptr<Controllable>
3440 Session::controllable_by_id (const PBD::ID& id)
3442 Glib::Threads::Mutex::Lock lm (controllables_lock);
3444 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3445 if ((*i)->id() == id) {
3450 return boost::shared_ptr<Controllable>();
3453 boost::shared_ptr<Controllable>
3454 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3456 boost::shared_ptr<Controllable> c;
3457 boost::shared_ptr<Stripable> s;
3458 boost::shared_ptr<Route> r;
3460 switch (desc.top_level_type()) {
3461 case ControllableDescriptor::NamedRoute:
3463 std::string str = desc.top_level_name();
3465 if (str == "Master" || str == "master") {
3467 } else if (str == "control" || str == "listen" || str == "monitor" || str == "Monitor") {
3469 } else if (str == "auditioner") {
3472 s = route_by_name (desc.top_level_name());
3478 case ControllableDescriptor::PresentationOrderRoute:
3479 s = get_remote_nth_stripable (desc.presentation_order(), PresentationInfo::Route);
3482 case ControllableDescriptor::PresentationOrderTrack:
3483 s = get_remote_nth_stripable (desc.presentation_order(), PresentationInfo::Track);
3486 case ControllableDescriptor::PresentationOrderBus:
3487 s = get_remote_nth_stripable (desc.presentation_order(), PresentationInfo::Bus);
3490 case ControllableDescriptor::PresentationOrderVCA:
3491 s = get_remote_nth_stripable (desc.presentation_order(), PresentationInfo::VCA);
3494 case ControllableDescriptor::SelectionCount:
3495 s = route_by_selected_count (desc.selection_id());
3503 r = boost::dynamic_pointer_cast<Route> (s);
3505 switch (desc.subtype()) {
3506 case ControllableDescriptor::Gain:
3507 c = s->gain_control ();
3510 case ControllableDescriptor::Trim:
3511 c = s->trim_control ();
3514 case ControllableDescriptor::Solo:
3515 c = s->solo_control();
3518 case ControllableDescriptor::Mute:
3519 c = s->mute_control();
3522 case ControllableDescriptor::Recenable:
3523 c = s->rec_enable_control ();
3526 case ControllableDescriptor::PanDirection:
3527 c = s->pan_azimuth_control();
3530 case ControllableDescriptor::PanWidth:
3531 c = s->pan_width_control();
3534 case ControllableDescriptor::PanElevation:
3535 c = s->pan_elevation_control();
3538 case ControllableDescriptor::Balance:
3539 /* XXX simple pan control */
3542 case ControllableDescriptor::PluginParameter:
3544 uint32_t plugin = desc.target (0);
3545 uint32_t parameter_index = desc.target (1);
3547 /* revert to zero based counting */
3553 if (parameter_index > 0) {
3561 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3564 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3565 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3570 case ControllableDescriptor::SendGain: {
3571 uint32_t send = desc.target (0);
3578 c = r->send_level_controllable (send);
3583 /* relax and return a null pointer */
3591 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3594 Stateful::add_instant_xml (node, _path);
3597 if (write_to_config) {
3598 Config->add_instant_xml (node);
3603 Session::instant_xml (const string& node_name)
3605 return Stateful::instant_xml (node_name, _path);
3609 Session::save_history (string snapshot_name)
3617 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3618 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3622 if (snapshot_name.empty()) {
3623 snapshot_name = _current_snapshot_name;
3626 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3627 const string backup_filename = history_filename + backup_suffix;
3628 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3629 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3631 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3632 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3633 error << _("could not backup old history file, current history not saved") << endmsg;
3638 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3640 if (!tree.write (xml_path))
3642 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3644 if (g_remove (xml_path.c_str()) != 0) {
3645 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3646 xml_path, g_strerror (errno)) << endmsg;
3648 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3649 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3650 backup_path, g_strerror (errno)) << endmsg;
3660 Session::restore_history (string snapshot_name)
3664 if (snapshot_name.empty()) {
3665 snapshot_name = _current_snapshot_name;
3668 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3669 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3671 info << "Loading history from " << xml_path << endmsg;
3673 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3674 info << string_compose (_("%1: no history file \"%2\" for this session."),
3675 _name, xml_path) << endmsg;
3679 if (!tree.read (xml_path)) {
3680 error << string_compose (_("Could not understand session history file \"%1\""),
3681 xml_path) << endmsg;
3688 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3691 UndoTransaction* ut = new UndoTransaction ();
3694 ut->set_name(t->property("name")->value());
3695 stringstream ss(t->property("tv-sec")->value());
3697 ss.str(t->property("tv-usec")->value());
3699 ut->set_timestamp(tv);
3701 for (XMLNodeConstIterator child_it = t->children().begin();
3702 child_it != t->children().end(); child_it++)
3704 XMLNode *n = *child_it;
3707 if (n->name() == "MementoCommand" ||
3708 n->name() == "MementoUndoCommand" ||
3709 n->name() == "MementoRedoCommand") {
3711 if ((c = memento_command_factory(n))) {
3715 } else if (n->name() == "NoteDiffCommand") {
3716 PBD::ID id (n->property("midi-source")->value());
3717 boost::shared_ptr<MidiSource> midi_source =
3718 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3720 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3722 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3725 } else if (n->name() == "SysExDiffCommand") {
3727 PBD::ID id (n->property("midi-source")->value());
3728 boost::shared_ptr<MidiSource> midi_source =
3729 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3731 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3733 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3736 } else if (n->name() == "PatchChangeDiffCommand") {
3738 PBD::ID id (n->property("midi-source")->value());
3739 boost::shared_ptr<MidiSource> midi_source =
3740 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3742 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3744 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3747 } else if (n->name() == "StatefulDiffCommand") {
3748 if ((c = stateful_diff_command_factory (n))) {
3749 ut->add_command (c);
3752 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3763 Session::config_changed (std::string p, bool ours)
3769 if (p == "seamless-loop") {
3771 } else if (p == "rf-speed") {
3773 } else if (p == "auto-loop") {
3775 } else if (p == "auto-input") {
3777 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3778 /* auto-input only makes a difference if we're rolling */
3779 set_track_monitor_input_status (!config.get_auto_input());
3782 } else if (p == "punch-in") {
3786 if ((location = _locations->auto_punch_location()) != 0) {
3788 if (config.get_punch_in ()) {
3789 replace_event (SessionEvent::PunchIn, location->start());
3791 remove_event (location->start(), SessionEvent::PunchIn);
3795 } else if (p == "punch-out") {
3799 if ((location = _locations->auto_punch_location()) != 0) {
3801 if (config.get_punch_out()) {
3802 replace_event (SessionEvent::PunchOut, location->end());
3804 clear_events (SessionEvent::PunchOut);
3808 } else if (p == "edit-mode") {
3810 Glib::Threads::Mutex::Lock lm (playlists->lock);
3812 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3813 (*i)->set_edit_mode (Config->get_edit_mode ());
3816 } else if (p == "use-video-sync") {
3818 waiting_for_sync_offset = config.get_use_video_sync();
3820 } else if (p == "mmc-control") {
3822 //poke_midi_thread ();
3824 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3826 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3828 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3830 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3832 } else if (p == "midi-control") {
3834 //poke_midi_thread ();
3836 } else if (p == "raid-path") {
3838 setup_raid_path (config.get_raid_path());
3840 } else if (p == "timecode-format") {
3844 } else if (p == "video-pullup") {
3848 } else if (p == "seamless-loop") {
3850 if (play_loop && transport_rolling()) {
3851 // to reset diskstreams etc
3852 request_play_loop (true);
3855 } else if (p == "rf-speed") {
3857 cumulative_rf_motion = 0;
3860 } else if (p == "click-sound") {
3862 setup_click_sounds (1);
3864 } else if (p == "click-emphasis-sound") {
3866 setup_click_sounds (-1);
3868 } else if (p == "clicking") {
3870 if (Config->get_clicking()) {
3871 if (_click_io && click_data) { // don't require emphasis data
3878 } else if (p == "click-gain") {
3881 _click_gain->gain_control()->set_value (Config->get_click_gain(), Controllable::NoGroup);
3884 } else if (p == "send-mtc") {
3886 if (Config->get_send_mtc ()) {
3887 /* mark us ready to send */
3888 next_quarter_frame_to_send = 0;
3891 } else if (p == "send-mmc") {
3893 _mmc->enable_send (Config->get_send_mmc ());
3895 } else if (p == "midi-feedback") {
3897 session_midi_feedback = Config->get_midi_feedback();
3899 } else if (p == "jack-time-master") {
3901 engine().reset_timebase ();
3903 } else if (p == "native-file-header-format") {
3905 if (!first_file_header_format_reset) {
3906 reset_native_file_format ();
3909 first_file_header_format_reset = false;
3911 } else if (p == "native-file-data-format") {
3913 if (!first_file_data_format_reset) {
3914 reset_native_file_format ();
3917 first_file_data_format_reset = false;
3919 } else if (p == "external-sync") {
3920 if (!config.get_external_sync()) {
3921 drop_sync_source ();
3923 switch_to_sync_source (Config->get_sync_source());
3925 } else if (p == "denormal-model") {
3927 } else if (p == "history-depth") {
3928 set_history_depth (Config->get_history_depth());
3929 } else if (p == "remote-model") {
3930 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3933 } else if (p == "initial-program-change") {
3935 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3938 buf[0] = MIDI::program; // channel zero by default
3939 buf[1] = (Config->get_initial_program_change() & 0x7f);
3941 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3943 } else if (p == "solo-mute-override") {
3944 // catch_up_on_solo_mute_override ();
3945 } else if (p == "listen-position" || p == "pfl-position") {
3946 listen_position_changed ();
3947 } else if (p == "solo-control-is-listen-control") {
3948 solo_control_mode_changed ();
3949 } else if (p == "solo-mute-gain") {
3950 _solo_cut_control->Changed (true, Controllable::NoGroup);
3951 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3952 last_timecode_valid = false;
3953 } else if (p == "playback-buffer-seconds") {
3954 AudioSource::allocate_working_buffers (frame_rate());
3955 } else if (p == "ltc-source-port") {
3956 reconnect_ltc_input ();
3957 } else if (p == "ltc-sink-port") {
3958 reconnect_ltc_output ();
3959 } else if (p == "timecode-generator-offset") {
3960 ltc_tx_parse_offset();
3961 } else if (p == "auto-return-target-list") {
3962 follow_playhead_priority ();
3969 Session::set_history_depth (uint32_t d)
3971 _history.set_depth (d);
3975 Session::load_diskstreams_2X (XMLNode const & node, int)
3978 XMLNodeConstIterator citer;
3980 clist = node.children();
3982 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3985 /* diskstreams added automatically by DiskstreamCreated handler */
3986 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3987 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3988 _diskstreams_2X.push_back (dsp);
3990 error << _("Session: unknown diskstream type in XML") << endmsg;
3994 catch (failed_constructor& err) {
3995 error << _("Session: could not load diskstream via XML state") << endmsg;
4003 /** Connect things to the MMC object */
4005 Session::setup_midi_machine_control ()
4007 _mmc = new MIDI::MachineControl;
4009 boost::shared_ptr<AsyncMIDIPort> async_in = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_input_port());
4010 boost::shared_ptr<AsyncMIDIPort> async_out = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_output_port());
4012 if (!async_out || !async_out) {
4016 /* XXXX argh, passing raw pointers back into libmidi++ */
4018 MIDI::Port* mmc_in = async_in.get();
4019 MIDI::Port* mmc_out = async_out.get();
4021 _mmc->set_ports (mmc_in, mmc_out);
4023 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
4024 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
4025 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
4026 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
4027 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
4028 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
4029 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
4030 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
4031 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
4032 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
4033 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
4034 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
4035 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
4037 /* also handle MIDI SPP because its so common */
4039 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
4040 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
4041 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
4044 boost::shared_ptr<Controllable>
4045 Session::solo_cut_control() const
4047 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
4048 controls in Ardour that currently get presented to the user in the GUI that require
4049 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
4051 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
4052 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
4056 return _solo_cut_control;
4060 Session::save_snapshot_name (const std::string & n)
4062 /* assure Stateful::_instant_xml is loaded
4063 * add_instant_xml() only adds to existing data and defaults
4064 * to use an empty Tree otherwise
4066 instant_xml ("LastUsedSnapshot");
4068 XMLNode* last_used_snapshot = new XMLNode ("LastUsedSnapshot");
4069 last_used_snapshot->add_property ("name", string(n));
4070 add_instant_xml (*last_used_snapshot, false);
4074 Session::set_snapshot_name (const std::string & n)
4076 _current_snapshot_name = n;
4077 save_snapshot_name (n);
4081 Session::rename (const std::string& new_name)
4083 string legal_name = legalize_for_path (new_name);
4089 string const old_sources_root = _session_dir->sources_root();
4091 if (!_writable || (_state_of_the_state & CannotSave)) {
4092 error << _("Cannot rename read-only session.") << endmsg;
4093 return 0; // don't show "messed up" warning
4095 if (record_status() == Recording) {
4096 error << _("Cannot rename session while recording") << endmsg;
4097 return 0; // don't show "messed up" warning
4100 StateProtector stp (this);
4105 * interchange subdirectory
4109 * Backup files are left unchanged and not renamed.
4112 /* Windows requires that we close all files before attempting the
4113 * rename. This works on other platforms, but isn't necessary there.
4114 * Leave it in place for all platforms though, since it may help
4115 * catch issues that could arise if the way Source files work ever
4116 * change (since most developers are not using Windows).
4119 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4120 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4126 /* pass one: not 100% safe check that the new directory names don't
4130 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4134 /* this is a stupid hack because Glib::path_get_dirname() is
4135 * lexical-only, and so passing it /a/b/c/ gives a different
4136 * result than passing it /a/b/c ...
4139 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4140 oldstr = oldstr.substr (0, oldstr.length() - 1);
4143 string base = Glib::path_get_dirname (oldstr);
4145 newstr = Glib::build_filename (base, legal_name);
4147 cerr << "Looking for " << newstr << endl;
4149 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
4150 cerr << " exists\n";
4159 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4165 /* this is a stupid hack because Glib::path_get_dirname() is
4166 * lexical-only, and so passing it /a/b/c/ gives a different
4167 * result than passing it /a/b/c ...
4170 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4171 oldstr = oldstr.substr (0, oldstr.length() - 1);
4174 string base = Glib::path_get_dirname (oldstr);
4175 newstr = Glib::build_filename (base, legal_name);
4177 cerr << "for " << oldstr << " new dir = " << newstr << endl;
4179 cerr << "Rename " << oldstr << " => " << newstr << endl;
4180 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4181 cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4182 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4186 /* Reset path in "session dirs" */
4191 /* reset primary SessionDirectory object */
4194 (*_session_dir) = newstr;
4199 /* now rename directory below session_dir/interchange */
4201 string old_interchange_dir;
4202 string new_interchange_dir;
4204 /* use newstr here because we renamed the path
4205 * (folder/directory) that used to be oldstr to newstr above
4208 v.push_back (newstr);
4209 v.push_back (interchange_dir_name);
4210 v.push_back (Glib::path_get_basename (oldstr));
4212 old_interchange_dir = Glib::build_filename (v);
4215 v.push_back (newstr);
4216 v.push_back (interchange_dir_name);
4217 v.push_back (legal_name);
4219 new_interchange_dir = Glib::build_filename (v);
4221 cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
4223 if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
4224 cerr << string_compose (_("renaming %s as %2 failed (%3)"),
4225 old_interchange_dir, new_interchange_dir,
4228 error << string_compose (_("renaming %s as %2 failed (%3)"),
4229 old_interchange_dir, new_interchange_dir,
4238 oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
4239 newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
4241 cerr << "Rename " << oldstr << " => " << newstr << endl;
4243 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4244 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4245 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4251 oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
4253 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
4254 newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
4256 cerr << "Rename " << oldstr << " => " << newstr << endl;
4258 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4259 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4260 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4265 /* remove old name from recent sessions */
4266 remove_recent_sessions (_path);
4269 /* update file source paths */
4271 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
4272 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4274 string p = fs->path ();
4275 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
4277 SourceFactory::setup_peakfile(i->second, true);
4281 set_snapshot_name (new_name);
4286 /* save state again to get everything just right */
4288 save_state (_current_snapshot_name);
4290 /* add to recent sessions */
4292 store_recent_sessions (new_name, _path);
4298 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
4300 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
4304 if (!tree.read (xmlpath)) {
4312 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
4315 bool found_sr = false;
4316 bool found_data_format = false;
4318 if (get_session_info_from_path (tree, xmlpath)) {
4324 XMLProperty const * prop;
4325 XMLNode const * root (tree.root());
4327 if ((prop = root->property (X_("sample-rate"))) != 0) {
4328 sample_rate = atoi (prop->value());
4332 const XMLNodeList& children (root->children());
4333 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
4334 const XMLNode* child = *c;
4335 if (child->name() == "Config") {
4336 const XMLNodeList& options (child->children());
4337 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
4338 XMLNode const * option = *oc;
4339 XMLProperty const * name = option->property("name");
4345 if (name->value() == "native-file-data-format") {
4346 XMLProperty const * value = option->property ("value");
4348 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
4350 found_data_format = true;
4356 if (found_data_format) {
4361 return !(found_sr && found_data_format); // zero if they are both found
4365 Session::get_snapshot_from_instant (const std::string& session_dir)
4367 std::string instant_xml_path = Glib::build_filename (session_dir, "instant.xml");
4369 if (!Glib::file_test (instant_xml_path, Glib::FILE_TEST_EXISTS)) {
4374 if (!tree.read (instant_xml_path)) {
4378 XMLProperty const * prop;
4379 XMLNode *last_used_snapshot = tree.root()->child("LastUsedSnapshot");
4380 if (last_used_snapshot && (prop = last_used_snapshot->property ("name")) != 0) {
4381 return prop->value();
4387 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
4388 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
4391 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
4395 SourcePathMap source_path_map;
4397 boost::shared_ptr<AudioFileSource> afs;
4402 Glib::Threads::Mutex::Lock lm (source_lock);
4404 cerr << " total sources = " << sources.size();
4406 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4407 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4413 if (fs->within_session()) {
4417 if (source_path_map.find (fs->path()) != source_path_map.end()) {
4418 source_path_map[fs->path()].push_back (fs);
4420 SeveralFileSources v;
4422 source_path_map.insert (make_pair (fs->path(), v));
4428 cerr << " fsources = " << total << endl;
4430 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
4432 /* tell caller where we are */
4434 string old_path = i->first;
4436 callback (n, total, old_path);
4438 cerr << old_path << endl;
4442 switch (i->second.front()->type()) {
4443 case DataType::AUDIO:
4444 new_path = new_audio_source_path_for_embedded (old_path);
4447 case DataType::MIDI:
4448 /* XXX not implemented yet */
4452 if (new_path.empty()) {
4456 cerr << "Move " << old_path << " => " << new_path << endl;
4458 if (!copy_file (old_path, new_path)) {
4459 cerr << "failed !\n";
4463 /* make sure we stop looking in the external
4464 dir/folder. Remember, this is an all-or-nothing
4465 operations, it doesn't merge just some files.
4467 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
4469 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
4470 (*f)->set_path (new_path);
4475 save_state ("", false, false);
4481 bool accept_all_files (string const &, void *)
4487 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4489 /* 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.
4494 make_new_media_path (string old_path, string new_session_folder, string new_session_path)
4496 /* typedir is the "midifiles" or "audiofiles" etc. part of the path. */
4498 string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4500 v.push_back (new_session_folder); /* full path */
4501 v.push_back (interchange_dir_name);
4502 v.push_back (new_session_path); /* just one directory/folder */
4503 v.push_back (typedir);
4504 v.push_back (Glib::path_get_basename (old_path));
4506 return Glib::build_filename (v);
4510 Session::save_as (SaveAs& saveas)
4512 vector<string> files;
4513 string current_folder = Glib::path_get_dirname (_path);
4514 string new_folder = legalize_for_path (saveas.new_name);
4515 string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4516 int64_t total_bytes = 0;
4520 int32_t internal_file_cnt = 0;
4522 vector<string> do_not_copy_extensions;
4523 do_not_copy_extensions.push_back (statefile_suffix);
4524 do_not_copy_extensions.push_back (pending_suffix);
4525 do_not_copy_extensions.push_back (backup_suffix);
4526 do_not_copy_extensions.push_back (temp_suffix);
4527 do_not_copy_extensions.push_back (history_suffix);
4529 /* get total size */
4531 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4533 /* need to clear this because
4534 * find_files_matching_filter() is cumulative
4539 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4541 all += files.size();
4543 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4545 g_stat ((*i).c_str(), &gsb);
4546 total_bytes += gsb.st_size;
4550 /* save old values so we can switch back if we are not switching to the new session */
4552 string old_path = _path;
4553 string old_name = _name;
4554 string old_snapshot = _current_snapshot_name;
4555 string old_sd = _session_dir->root_path();
4556 vector<string> old_search_path[DataType::num_types];
4557 string old_config_search_path[DataType::num_types];
4559 old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4560 old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4561 old_config_search_path[DataType::AUDIO] = config.get_audio_search_path ();
4562 old_config_search_path[DataType::MIDI] = config.get_midi_search_path ();
4564 /* switch session directory */
4566 (*_session_dir) = to_dir;
4568 /* create new tree */
4570 if (!_session_dir->create()) {
4571 saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4576 /* copy all relevant files. Find each location in session_dirs,
4577 * and copy files from there to target.
4580 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4582 /* need to clear this because
4583 * find_files_matching_filter() is cumulative
4588 const size_t prefix_len = (*sd).path.size();
4590 /* Work just on the files within this session dir */
4592 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4594 /* add dir separator to protect against collisions with
4595 * track names (e.g. track named "audiofiles" or
4599 static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
4600 static const std::string midifile_dir_string = string (midi_dir_name) + G_DIR_SEPARATOR;
4601 static const std::string analysis_dir_string = analysis_dir() + G_DIR_SEPARATOR;
4603 /* copy all the files. Handling is different for media files
4604 than others because of the *silly* subtree we have below the interchange
4605 folder. That really was a bad idea, but I'm not fixing it as part of
4606 implementing ::save_as().
4609 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4611 std::string from = *i;
4614 string filename = Glib::path_get_basename (from);
4615 std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
4616 if (filename == ".DS_STORE") {
4621 if (from.find (audiofile_dir_string) != string::npos) {
4623 /* audio file: only copy if asked */
4625 if (saveas.include_media && saveas.copy_media) {
4627 string to = make_new_media_path (*i, to_dir, new_folder);
4629 info << "media file copying from " << from << " to " << to << endmsg;
4631 if (!copy_file (from, to)) {
4632 throw Glib::FileError (Glib::FileError::IO_ERROR,
4633 string_compose(_("\ncopying \"%1\" failed !"), from));
4637 /* we found media files inside the session folder */
4639 internal_file_cnt++;
4641 } else if (from.find (midifile_dir_string) != string::npos) {
4643 /* midi file: always copy unless
4644 * creating an empty new session
4647 if (saveas.include_media) {
4649 string to = make_new_media_path (*i, to_dir, new_folder);
4651 info << "media file copying from " << from << " to " << to << endmsg;
4653 if (!copy_file (from, to)) {
4654 throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4658 /* we found media files inside the session folder */
4660 internal_file_cnt++;
4662 } else if (from.find (analysis_dir_string) != string::npos) {
4664 /* make sure analysis dir exists in
4665 * new session folder, but we're not
4666 * copying analysis files here, see
4670 (void) g_mkdir_with_parents (analysis_dir().c_str(), 775);
4675 /* normal non-media file. Don't copy state, history, etc.
4678 bool do_copy = true;
4680 for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
4681 if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
4682 /* end of filename matches extension, do not copy file */
4688 if (!saveas.copy_media && from.find (peakfile_suffix) != string::npos) {
4689 /* don't copy peakfiles if
4690 * we're not copying media
4696 string to = Glib::build_filename (to_dir, from.substr (prefix_len));
4698 info << "attempting to make directory/folder " << to << endmsg;
4700 if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
4701 throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
4704 info << "attempting to copy " << from << " to " << to << endmsg;
4706 if (!copy_file (from, to)) {
4707 throw Glib::FileError (Glib::FileError::IO_ERROR,
4708 string_compose(_("\ncopying \"%1\" failed !"), from));
4713 /* measure file size even if we're not going to copy so that our Progress
4714 signals are correct, since we included these do-not-copy files
4715 in the computation of the total size and file count.
4719 g_stat (from.c_str(), &gsb);
4720 copied += gsb.st_size;
4723 double fraction = (double) copied / total_bytes;
4725 bool keep_going = true;
4727 if (saveas.copy_media) {
4729 /* no need or expectation of this if
4730 * media is not being copied, because
4731 * it will be fast(ish).
4734 /* tell someone "X percent, file M of N"; M is one-based */
4736 boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
4744 throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
4750 /* copy optional folders, if any */
4752 string old = plugins_dir ();
4753 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4754 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4755 copy_files (old, newdir);
4758 old = externals_dir ();
4759 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4760 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4761 copy_files (old, newdir);
4764 old = automation_dir ();
4765 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4766 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4767 copy_files (old, newdir);
4770 if (saveas.include_media) {
4772 if (saveas.copy_media) {
4773 #ifndef PLATFORM_WINDOWS
4774 /* There are problems with analysis files on
4775 * Windows, because they used a colon in their
4776 * names as late as 4.0. Colons are not legal
4777 * under Windows even if NTFS allows them.
4779 * This is a tricky problem to solve so for
4780 * just don't copy these files. They will be
4781 * regenerated as-needed anyway, subject to the
4782 * existing issue that the filenames will be
4783 * rejected by Windows, which is a separate
4784 * problem (though related).
4787 /* only needed if we are copying media, since the
4788 * analysis data refers to media data
4791 old = analysis_dir ();
4792 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4793 string newdir = Glib::build_filename (to_dir, "analysis");
4794 copy_files (old, newdir);
4796 #endif /* PLATFORM_WINDOWS */
4802 set_snapshot_name (saveas.new_name);
4803 _name = saveas.new_name;
4805 if (saveas.include_media && !saveas.copy_media) {
4807 /* reset search paths of the new session (which we're pretending to be right now) to
4808 include the original session search path, so we can still find all audio.
4811 if (internal_file_cnt) {
4812 for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
4813 ensure_search_path_includes (*s, DataType::AUDIO);
4814 cerr << "be sure to include " << *s << " for audio" << endl;
4817 /* we do not do this for MIDI because we copy
4818 all MIDI files if saveas.include_media is
4824 bool was_dirty = dirty ();
4826 save_state ("", false, false, !saveas.include_media);
4827 save_default_options ();
4829 if (saveas.copy_media && saveas.copy_external) {
4830 if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
4831 throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
4835 saveas.final_session_folder_name = _path;
4837 store_recent_sessions (_name, _path);
4839 if (!saveas.switch_to) {
4841 /* switch back to the way things were */
4845 set_snapshot_name (old_snapshot);
4847 (*_session_dir) = old_sd;
4853 if (internal_file_cnt) {
4854 /* reset these to their original values */
4855 config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
4856 config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
4861 /* prune session dirs, and update disk space statistics
4866 session_dirs.clear ();
4867 session_dirs.push_back (sp);
4868 refresh_disk_space ();
4870 /* ensure that all existing tracks reset their current capture source paths
4872 reset_write_sources (true, true);
4874 /* the copying above was based on actually discovering files, not just iterating over the sources list.
4875 But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
4878 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4879 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4885 if (fs->within_session()) {
4886 string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
4887 fs->set_path (newpath);
4892 } catch (Glib::FileError& e) {
4894 saveas.failure_message = e.what();
4896 /* recursively remove all the directories */
4898 remove_directory (to_dir);
4906 saveas.failure_message = _("unknown reason");
4908 /* recursively remove all the directories */
4910 remove_directory (to_dir);
4921 Session::undo (uint32_t n)
4923 if (actively_recording()) {
4931 Session::redo (uint32_t n)
4933 if (actively_recording()) {