2 Copyright (C) 1999-2013 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "libardour-config.h"
30 #include <cstdio> /* snprintf(3) ... grrr */
42 #include <sys/param.h>
43 #include <sys/mount.h>
46 #ifdef HAVE_SYS_STATVFS_H
47 #include <sys/statvfs.h>
51 #include "pbd/gstdio_compat.h"
54 #include <glibmm/threads.h>
55 #include <glibmm/fileutils.h>
57 #include <boost/algorithm/string.hpp>
59 #include "midi++/mmc.h"
60 #include "midi++/port.h"
62 #include "evoral/SMF.hpp"
64 #include "pbd/basename.h"
65 #include "pbd/controllable_descriptor.h"
66 #include "pbd/debug.h"
67 #include "pbd/enumwriter.h"
68 #include "pbd/error.h"
69 #include "pbd/file_utils.h"
70 #include "pbd/pathexpand.h"
71 #include "pbd/pthread_utils.h"
72 #include "pbd/stacktrace.h"
73 #include "pbd/convert.h"
74 #include "pbd/localtime_r.h"
75 #include "pbd/unwind.h"
77 #include "ardour/amp.h"
78 #include "ardour/async_midi_port.h"
79 #include "ardour/audio_diskstream.h"
80 #include "ardour/audio_track.h"
81 #include "ardour/audioengine.h"
82 #include "ardour/audiofilesource.h"
83 #include "ardour/audioregion.h"
84 #include "ardour/automation_control.h"
85 #include "ardour/boost_debug.h"
86 #include "ardour/butler.h"
87 #include "ardour/control_protocol_manager.h"
88 #include "ardour/directory_names.h"
89 #include "ardour/filename_extensions.h"
90 #include "ardour/graph.h"
91 #include "ardour/location.h"
92 #include "ardour/midi_model.h"
93 #include "ardour/midi_patch_manager.h"
94 #include "ardour/midi_region.h"
95 #include "ardour/midi_scene_changer.h"
96 #include "ardour/midi_source.h"
97 #include "ardour/midi_track.h"
98 #include "ardour/pannable.h"
99 #include "ardour/playlist_factory.h"
100 #include "ardour/playlist_source.h"
101 #include "ardour/port.h"
102 #include "ardour/processor.h"
103 #include "ardour/profile.h"
104 #include "ardour/proxy_controllable.h"
105 #include "ardour/recent_sessions.h"
106 #include "ardour/region_factory.h"
107 #include "ardour/route_group.h"
108 #include "ardour/send.h"
109 #include "ardour/session.h"
110 #include "ardour/session_directory.h"
111 #include "ardour/session_metadata.h"
112 #include "ardour/session_playlists.h"
113 #include "ardour/session_state_utils.h"
114 #include "ardour/silentfilesource.h"
115 #include "ardour/sndfilesource.h"
116 #include "ardour/source_factory.h"
117 #include "ardour/speakers.h"
118 #include "ardour/template_utils.h"
119 #include "ardour/tempo.h"
120 #include "ardour/ticker.h"
121 #include "ardour/user_bundle.h"
122 #include "ardour/vca.h"
123 #include "ardour/vca_manager.h"
125 #include "control_protocol/control_protocol.h"
127 #include "LuaBridge/LuaBridge.h"
133 using namespace ARDOUR;
136 #define DEBUG_UNDO_HISTORY(msg) DEBUG_TRACE (PBD::DEBUG::UndoHistory, string_compose ("%1: %2\n", __LINE__, msg));
139 Session::pre_engine_init (string fullpath)
141 if (fullpath.empty()) {
143 throw failed_constructor();
146 /* discover canonical fullpath */
148 _path = canonical_path(fullpath);
151 if (Profile->get_trx() ) {
152 // Waves TracksLive has a usecase of session replacement with a new one.
153 // We should check session state file (<session_name>.ardour) existance
154 // to determine if the session is new or not
156 string full_session_name = Glib::build_filename( fullpath, _name );
157 full_session_name += statefile_suffix;
159 _is_new = !Glib::file_test (full_session_name, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
161 _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
164 /* finish initialization that can't be done in a normal C++ constructor
168 timerclear (&last_mmc_step);
169 g_atomic_int_set (&processing_prohibited, 0);
170 g_atomic_int_set (&_record_status, Disabled);
171 g_atomic_int_set (&_playback_load, 100);
172 g_atomic_int_set (&_capture_load, 100);
174 _all_route_group->set_active (true, this);
175 interpolation.add_channel_to (0, 0);
176 _vca_manager = new VCAManager (*this);
178 if (config.get_use_video_sync()) {
179 waiting_for_sync_offset = true;
181 waiting_for_sync_offset = false;
184 last_rr_session_dir = session_dirs.begin();
186 set_history_depth (Config->get_history_depth());
188 /* default: assume simple stereo speaker configuration */
190 _speakers->setup_default_speakers (2);
192 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
193 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
194 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
195 add_controllable (_solo_cut_control);
197 /* These are all static "per-class" signals */
199 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
200 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
201 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
202 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
203 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
205 /* stop IO objects from doing stuff until we're ready for them */
207 Delivery::disable_panners ();
208 IO::disable_connecting ();
212 Session::post_engine_init ()
214 BootMessage (_("Set block size and sample rate"));
216 set_block_size (_engine.samples_per_cycle());
217 set_frame_rate (_engine.sample_rate());
219 BootMessage (_("Using configuration"));
221 _midi_ports = new MidiPortManager;
223 MIDISceneChanger* msc;
225 _scene_changer = msc = new MIDISceneChanger (*this);
226 msc->set_input_port (boost::dynamic_pointer_cast<MidiPort>(scene_input_port()));
227 msc->set_output_port (boost::dynamic_pointer_cast<MidiPort>(scene_output_port()));
229 boost::function<framecnt_t(void)> timer_func (boost::bind (&Session::audible_frame, this));
230 boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_input_port())->set_timer (timer_func);
232 setup_midi_machine_control ();
234 if (_butler->start_thread()) {
238 if (start_midi_thread ()) {
242 setup_click_sounds (0);
243 setup_midi_control ();
245 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
246 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
249 /* tempo map requires sample rate knowledge */
252 _tempo_map = new TempoMap (_current_frame_rate);
253 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
254 _tempo_map->MetricPositionChanged.connect_same_thread (*this, boost::bind (&Session::gui_tempo_map_changed, this));
256 /* MidiClock requires a tempo map */
259 midi_clock = new MidiClockTicker ();
260 midi_clock->set_session (this);
262 /* crossfades require sample rate knowledge */
264 SndFileSource::setup_standard_crossfades (*this, frame_rate());
265 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
267 AudioDiskstream::allocate_working_buffers();
268 refresh_disk_space ();
270 /* we're finally ready to call set_state() ... all objects have
271 * been created, the engine is running.
275 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
279 // set_state() will call setup_raid_path(), but if it's a new session we need
280 // to call setup_raid_path() here.
281 setup_raid_path (_path);
286 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
287 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
289 Config->map_parameters (ff);
290 config.map_parameters (ft);
291 _butler->map_parameters ();
293 /* Reset all panners */
295 Delivery::reset_panners ();
297 /* this will cause the CPM to instantiate any protocols that are in use
298 * (or mandatory), which will pass it this Session, and then call
299 * set_state() on each instantiated protocol to match stored state.
302 ControlProtocolManager::instance().set_session (this);
304 /* This must be done after the ControlProtocolManager set_session above,
305 as it will set states for ports which the ControlProtocolManager creates.
308 // XXX set state of MIDI::Port's
309 // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
311 /* And this must be done after the MIDI::Manager::set_port_states as
312 * it will try to make connections whose details are loaded by set_port_states.
317 /* Let control protocols know that we are now all connected, so they
318 * could start talking to surfaces if they want to.
321 ControlProtocolManager::instance().midi_connectivity_established ();
323 if (_is_new && !no_auto_connect()) {
324 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
325 auto_connect_master_bus ();
328 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
330 /* update latencies */
332 initialize_latencies ();
334 _locations->added.connect_same_thread (*this, boost::bind (&Session::location_added, this, _1));
335 _locations->removed.connect_same_thread (*this, boost::bind (&Session::location_removed, this, _1));
336 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
338 } catch (AudioEngine::PortRegistrationFailure& err) {
339 /* handle this one in a different way than all others, so that its clear what happened */
340 error << err.what() << endmsg;
346 BootMessage (_("Reset Remote Controls"));
348 // send_full_time_code (0);
349 _engine.transport_locate (0);
351 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
352 send_immediate_mmc (MIDI::MachineControlCommand (Timecode::Time ()));
354 MIDI::Name::MidiPatchManager::instance().add_search_path (session_directory().midi_patch_path() );
357 /* initial program change will be delivered later; see ::config_changed() */
359 _state_of_the_state = Clean;
361 Port::set_connecting_blocked (false);
363 DirtyChanged (); /* EMIT SIGNAL */
367 } else if (state_was_pending) {
369 remove_pending_capture_state ();
370 state_was_pending = false;
373 /* Now, finally, we can fill the playback buffers */
375 BootMessage (_("Filling playback buffers"));
377 boost::shared_ptr<RouteList> rl = routes.reader();
378 for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
379 boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<Track> (*r);
380 if (trk && !trk->hidden()) {
381 trk->seek (_transport_frame, true);
389 Session::session_loaded ()
393 _state_of_the_state = Clean;
395 DirtyChanged (); /* EMIT SIGNAL */
399 } else if (state_was_pending) {
401 remove_pending_capture_state ();
402 state_was_pending = false;
405 /* Now, finally, we can fill the playback buffers */
407 BootMessage (_("Filling playback buffers"));
408 force_locate (_transport_frame, false);
412 Session::raid_path () const
414 Searchpath raid_search_path;
416 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
417 raid_search_path += (*i).path;
420 return raid_search_path.to_string ();
424 Session::setup_raid_path (string path)
433 session_dirs.clear ();
435 Searchpath search_path(path);
436 Searchpath sound_search_path;
437 Searchpath midi_search_path;
439 for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
441 sp.blocks = 0; // not needed
442 session_dirs.push_back (sp);
444 SessionDirectory sdir(sp.path);
446 sound_search_path += sdir.sound_path ();
447 midi_search_path += sdir.midi_path ();
450 // reset the round-robin soundfile path thingie
451 last_rr_session_dir = session_dirs.begin();
455 Session::path_is_within_session (const std::string& path)
457 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
458 if (PBD::path_is_within (i->path, path)) {
466 Session::ensure_subdirs ()
470 dir = session_directory().peak_path();
472 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
473 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
477 dir = session_directory().sound_path();
479 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
480 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
484 dir = session_directory().midi_path();
486 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
487 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
491 dir = session_directory().dead_path();
493 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
494 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
498 dir = session_directory().export_path();
500 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
501 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
505 dir = analysis_dir ();
507 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
508 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
512 dir = plugins_dir ();
514 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
515 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
519 dir = externals_dir ();
521 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
522 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
529 /** @param session_template directory containing session template, or empty.
530 * Caller must not hold process lock.
533 Session::create (const string& session_template, BusProfile* bus_profile)
535 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
536 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
540 if (ensure_subdirs ()) {
544 _writable = exists_and_writable (_path);
546 if (!session_template.empty()) {
547 string in_path = (ARDOUR::Profile->get_trx () ? session_template : session_template_dir_to_file (session_template));
549 FILE* in = g_fopen (in_path.c_str(), "rb");
552 /* no need to call legalize_for_path() since the string
553 * in session_template is already a legal path name
555 string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
557 FILE* out = g_fopen (out_path.c_str(), "wb");
561 stringstream new_session;
564 size_t charsRead = fread (buf, sizeof(char), 1024, in);
567 error << string_compose (_("Error reading session template file %1 (%2)"), in_path, strerror (errno)) << endmsg;
572 if (charsRead == 0) {
575 new_session.write (buf, charsRead);
579 string file_contents = new_session.str();
580 size_t writeSize = file_contents.length();
581 if (fwrite (file_contents.c_str(), sizeof(char), writeSize, out) != writeSize) {
582 error << string_compose (_("Error writing session template file %1 (%2)"), out_path, strerror (errno)) << endmsg;
590 if (!ARDOUR::Profile->get_trx()) {
591 /* Copy plugin state files from template to new session */
592 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
593 copy_recurse (template_plugins, plugins_dir ());
599 error << string_compose (_("Could not open %1 for writing session template"), out_path)
606 error << string_compose (_("Could not open session template %1 for reading"), in_path)
613 if (Profile->get_trx()) {
615 /* set initial start + end point : ARDOUR::Session::session_end_shift long.
616 Remember that this is a brand new session. Sessions
617 loaded from saved state will get this range from the saved state.
620 set_session_range_location (0, 0);
622 /* Initial loop location, from absolute zero, length 10 seconds */
624 Location* loc = new Location (*this, 0, 10.0 * _engine.sample_rate(), _("Loop"), Location::IsAutoLoop);
625 _locations->add (loc, true);
626 set_auto_loop_location (loc);
629 _state_of_the_state = Clean;
631 /* set up Master Out and Control Out if necessary */
636 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
638 // Waves Tracks: always create master bus for Tracks
639 if (ARDOUR::Profile->get_trx() || bus_profile->master_out_channels) {
640 boost::shared_ptr<Route> r (new Route (*this, _("Master"), Route::MasterOut, DataType::AUDIO));
648 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
649 r->input()->ensure_io (count, false, this);
650 r->output()->ensure_io (count, false, this);
656 /* prohibit auto-connect to master, because there isn't one */
657 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
661 add_routes (rl, false, false, false);
664 // Waves Tracks: Skip this. Always use autoconnection for Tracks
665 if (!ARDOUR::Profile->get_trx()) {
667 /* this allows the user to override settings with an environment variable.
670 if (no_auto_connect()) {
671 bus_profile->input_ac = AutoConnectOption (0);
672 bus_profile->output_ac = AutoConnectOption (0);
675 Config->set_input_auto_connect (bus_profile->input_ac);
676 Config->set_output_auto_connect (bus_profile->output_ac);
680 if (Config->get_use_monitor_bus() && bus_profile) {
681 add_monitor_section ();
688 Session::maybe_write_autosave()
690 if (dirty() && record_status() != Recording) {
691 save_state("", true);
696 Session::remove_pending_capture_state ()
698 std::string pending_state_file_path(_session_dir->root_path());
700 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
702 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
704 if (g_remove (pending_state_file_path.c_str()) != 0) {
705 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
706 pending_state_file_path, g_strerror (errno)) << endmsg;
710 /** Rename a state file.
711 * @param old_name Old snapshot name.
712 * @param new_name New snapshot name.
715 Session::rename_state (string old_name, string new_name)
717 if (old_name == _current_snapshot_name || old_name == _name) {
718 /* refuse to rename the current snapshot or the "main" one */
722 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
723 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
725 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
726 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
728 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
729 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
730 old_name, new_name, g_strerror(errno)) << endmsg;
734 /** Remove a state file.
735 * @param snapshot_name Snapshot name.
738 Session::remove_state (string snapshot_name)
740 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
741 // refuse to remove the current snapshot or the "main" one
745 std::string xml_path(_session_dir->root_path());
747 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
749 if (!create_backup_file (xml_path)) {
750 // don't remove it if a backup can't be made
751 // create_backup_file will log the error.
756 if (g_remove (xml_path.c_str()) != 0) {
757 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
758 xml_path, g_strerror (errno)) << endmsg;
762 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
764 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot, bool template_only)
766 DEBUG_TRACE (DEBUG::Locale, string_compose ("Session::save_state locale '%1'\n", setlocale (LC_NUMERIC, NULL)));
769 std::string xml_path(_session_dir->root_path());
771 /* prevent concurrent saves from different threads */
773 Glib::Threads::Mutex::Lock lm (save_state_lock);
775 if (!_writable || (_state_of_the_state & CannotSave)) {
779 if (g_atomic_int_get(&_suspend_save)) {
783 _save_queued = false;
785 if (!_engine.connected ()) {
786 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
793 const int64_t save_start_time = g_get_monotonic_time();
796 /* tell sources we're saving first, in case they write out to a new file
797 * which should be saved with the state rather than the old one */
798 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
800 i->second->session_saved();
801 } catch (Evoral::SMF::FileError& e) {
802 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
806 SessionSaveUnderway (); /* EMIT SIGNAL */
808 bool mark_as_clean = true;
810 if (!snapshot_name.empty() && !switch_to_snapshot) {
811 mark_as_clean = false;
815 mark_as_clean = false;
816 tree.set_root (&get_template());
818 tree.set_root (&get_state());
821 if (snapshot_name.empty()) {
822 snapshot_name = _current_snapshot_name;
823 } else if (switch_to_snapshot) {
824 set_snapshot_name (snapshot_name);
827 assert (!snapshot_name.empty());
831 /* proper save: use statefile_suffix (.ardour in English) */
833 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
835 /* make a backup copy of the old file */
837 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
838 // create_backup_file will log the error
844 /* pending save: use pending_suffix (.pending in English) */
845 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
848 std::string tmp_path(_session_dir->root_path());
849 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
851 cerr << "actually writing state to " << tmp_path << endl;
853 if (!tree.write (tmp_path)) {
854 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
855 if (g_remove (tmp_path.c_str()) != 0) {
856 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
857 tmp_path, g_strerror (errno)) << endmsg;
863 cerr << "renaming state to " << xml_path << endl;
865 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
866 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
867 tmp_path, xml_path, g_strerror(errno)) << endmsg;
868 if (g_remove (tmp_path.c_str()) != 0) {
869 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
870 tmp_path, g_strerror (errno)) << endmsg;
878 save_history (snapshot_name);
881 bool was_dirty = dirty();
883 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
886 DirtyChanged (); /* EMIT SIGNAL */
890 StateSaved (snapshot_name); /* EMIT SIGNAL */
894 const int64_t elapsed_time_us = g_get_monotonic_time() - save_start_time;
895 cerr << "saved state in " << fixed << setprecision (1) << elapsed_time_us / 1000. << " ms\n";
901 Session::restore_state (string snapshot_name)
903 if (load_state (snapshot_name) == 0) {
904 set_state (*state_tree->root(), Stateful::loading_state_version);
911 Session::load_state (string snapshot_name)
916 state_was_pending = false;
918 /* check for leftover pending state from a crashed capture attempt */
920 std::string xmlpath(_session_dir->root_path());
921 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
923 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
925 /* there is pending state from a crashed capture attempt */
927 boost::optional<int> r = AskAboutPendingState();
928 if (r.get_value_or (1)) {
929 state_was_pending = true;
933 if (!state_was_pending) {
934 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
937 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
938 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
939 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
940 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
945 state_tree = new XMLTree;
949 _writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
951 if (!state_tree->read (xmlpath)) {
952 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
958 XMLNode const & root (*state_tree->root());
960 if (root.name() != X_("Session")) {
961 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
967 XMLProperty const * prop;
969 if ((prop = root.property ("version")) == 0) {
970 /* no version implies very old version of Ardour */
971 Stateful::loading_state_version = 1000;
973 if (prop->value().find ('.') != string::npos) {
974 /* old school version format */
975 if (prop->value()[0] == '2') {
976 Stateful::loading_state_version = 2000;
978 Stateful::loading_state_version = 3000;
981 Stateful::loading_state_version = atoi (prop->value());
985 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
987 std::string backup_path(_session_dir->root_path());
988 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
989 backup_path = Glib::build_filename (backup_path, backup_filename);
991 // only create a backup for a given statefile version once
993 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
995 VersionMismatch (xmlpath, backup_path);
997 if (!copy_file (xmlpath, backup_path)) {;
1003 save_snapshot_name (snapshot_name);
1009 Session::load_options (const XMLNode& node)
1012 config.set_variables (node);
1017 Session::save_default_options ()
1019 return config.save_state();
1023 Session::get_state()
1029 Session::get_template()
1031 /* if we don't disable rec-enable, diskstreams
1032 will believe they need to store their capture
1033 sources in their state node.
1036 disable_record (false);
1038 return state(false);
1042 Session::state (bool full_state)
1045 XMLNode* node = new XMLNode("Session");
1049 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
1050 node->add_property("version", buf);
1052 /* store configuration settings */
1056 node->add_property ("name", _name);
1057 snprintf (buf, sizeof (buf), "%" PRId64, _base_frame_rate);
1058 node->add_property ("sample-rate", buf);
1060 if (session_dirs.size() > 1) {
1064 vector<space_and_path>::iterator i = session_dirs.begin();
1065 vector<space_and_path>::iterator next;
1067 ++i; /* skip the first one */
1071 while (i != session_dirs.end()) {
1075 if (next != session_dirs.end()) {
1076 p += G_SEARCHPATH_SEPARATOR;
1085 child = node->add_child ("Path");
1086 child->add_content (p);
1090 /* save the ID counter */
1092 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1093 node->add_property ("id-counter", buf);
1095 snprintf (buf, sizeof (buf), "%u", name_id_counter ());
1096 node->add_property ("name-counter", buf);
1098 /* save the event ID counter */
1100 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1101 node->add_property ("event-counter", buf);
1103 /* save the VCA counter */
1105 snprintf (buf, sizeof (buf), "%" PRIu32, VCA::get_next_vca_number());
1106 node->add_property ("vca-counter", buf);
1108 /* various options */
1110 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
1111 if (!midi_port_nodes.empty()) {
1112 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
1113 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
1114 midi_port_stuff->add_child_nocopy (**n);
1116 node->add_child_nocopy (*midi_port_stuff);
1119 node->add_child_nocopy (config.get_variables ());
1121 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1123 child = node->add_child ("Sources");
1126 Glib::Threads::Mutex::Lock sl (source_lock);
1128 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1130 /* Don't save information about non-file Sources, or
1131 * about non-destructive file sources that are empty
1132 * and unused by any regions.
1135 boost::shared_ptr<FileSource> fs;
1137 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1139 if (!fs->destructive()) {
1140 if (fs->empty() && !fs->used()) {
1145 child->add_child_nocopy (siter->second->get_state());
1150 child = node->add_child ("Regions");
1153 Glib::Threads::Mutex::Lock rl (region_lock);
1154 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1155 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1156 boost::shared_ptr<Region> r = i->second;
1157 /* only store regions not attached to playlists */
1158 if (r->playlist() == 0) {
1159 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1160 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1162 child->add_child_nocopy (r->get_state ());
1167 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1169 if (!cassocs.empty()) {
1170 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1172 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1174 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1175 i->first->id().print (buf, sizeof (buf));
1176 can->add_property (X_("copy"), buf);
1177 i->second->id().print (buf, sizeof (buf));
1178 can->add_property (X_("original"), buf);
1179 ca->add_child_nocopy (*can);
1189 node->add_child_nocopy (_locations->get_state());
1192 Locations loc (*this);
1193 // for a template, just create a new Locations, populate it
1194 // with the default start and end, and get the state for that.
1195 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1196 range->set (max_framepos, 0);
1198 XMLNode& locations_state = loc.get_state();
1200 if (ARDOUR::Profile->get_trx() && _locations) {
1201 // For tracks we need stored the Auto Loop Range and all MIDI markers.
1202 for (Locations::LocationList::const_iterator i = _locations->list ().begin (); i != _locations->list ().end (); ++i) {
1203 if ((*i)->is_mark () || (*i)->is_auto_loop ()) {
1204 locations_state.add_child_nocopy ((*i)->get_state ());
1208 node->add_child_nocopy (locations_state);
1211 child = node->add_child ("Bundles");
1213 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1214 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1215 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1217 child->add_child_nocopy (b->get_state());
1222 node->add_child_nocopy (_vca_manager->get_state());
1224 child = node->add_child ("Routes");
1226 boost::shared_ptr<RouteList> r = routes.reader ();
1228 RoutePublicOrderSorter cmp;
1229 RouteList public_order (*r);
1230 public_order.sort (cmp);
1232 /* the sort should have put control outs first */
1235 assert (_monitor_out == public_order.front());
1238 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1239 if (!(*i)->is_auditioner()) {
1241 child->add_child_nocopy ((*i)->get_state());
1243 child->add_child_nocopy ((*i)->get_template());
1249 playlists->add_state (node, full_state);
1251 child = node->add_child ("RouteGroups");
1252 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1253 child->add_child_nocopy ((*i)->get_state());
1257 XMLNode* gain_child = node->add_child ("Click");
1258 gain_child->add_child_nocopy (_click_io->state (full_state));
1259 gain_child->add_child_nocopy (_click_gain->state (full_state));
1263 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1264 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1268 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1269 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1272 node->add_child_nocopy (_speakers->get_state());
1273 node->add_child_nocopy (_tempo_map->get_state());
1274 node->add_child_nocopy (get_control_protocol_state());
1277 node->add_child_copy (*_extra_xml);
1281 Glib::Threads::Mutex::Lock lm (lua_lock);
1284 luabridge::LuaRef savedstate ((*_lua_save)());
1285 saved = savedstate.cast<std::string>();
1287 lua.collect_garbage ();
1290 gchar* b64 = g_base64_encode ((const guchar*)saved.c_str (), saved.size ());
1291 std::string b64s (b64);
1294 XMLNode* script_node = new XMLNode (X_("Script"));
1295 script_node->add_property (X_("lua"), LUA_VERSION);
1296 script_node->add_content (b64s);
1297 node->add_child_nocopy (*script_node);
1304 Session::get_control_protocol_state ()
1306 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1307 return cpm.get_state();
1311 Session::set_state (const XMLNode& node, int version)
1316 XMLProperty const * prop;
1319 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1321 if (node.name() != X_("Session")) {
1322 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1326 if ((prop = node.property ("name")) != 0) {
1327 _name = prop->value ();
1330 if ((prop = node.property (X_("sample-rate"))) != 0) {
1332 _base_frame_rate = atoi (prop->value());
1333 _nominal_frame_rate = _base_frame_rate;
1335 assert (AudioEngine::instance()->running ());
1336 if (_base_frame_rate != AudioEngine::instance()->sample_rate ()) {
1337 boost::optional<int> r = AskAboutSampleRateMismatch (_base_frame_rate, _current_frame_rate);
1338 if (r.get_value_or (0)) {
1344 setup_raid_path(_session_dir->root_path());
1346 if ((prop = node.property (X_("id-counter"))) != 0) {
1348 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1349 ID::init_counter (x);
1351 /* old sessions used a timebased counter, so fake
1352 the startup ID counter based on a standard
1357 ID::init_counter (now);
1360 if ((prop = node.property (X_("name-counter"))) != 0) {
1361 init_name_id_counter (atoi (prop->value()));
1364 if ((prop = node.property (X_("event-counter"))) != 0) {
1365 Evoral::init_event_id_counter (atoi (prop->value()));
1368 if ((prop = node.property (X_("vca-counter"))) != 0) {
1370 sscanf (prop->value().c_str(), "%" PRIu32, &x);
1371 VCA::set_next_vca_number (x);
1373 VCA::set_next_vca_number (1);
1376 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1377 _midi_ports->set_midi_port_states (child->children());
1380 IO::disable_connecting ();
1382 Stateful::save_extra_xml (node);
1384 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1385 load_options (*child);
1386 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1387 load_options (*child);
1389 error << _("Session: XML state has no options section") << endmsg;
1392 if (version >= 3000) {
1393 if ((child = find_named_node (node, "Metadata")) == 0) {
1394 warning << _("Session: XML state has no metadata section") << endmsg;
1395 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1400 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1401 _speakers->set_state (*child, version);
1404 if ((child = find_named_node (node, "Sources")) == 0) {
1405 error << _("Session: XML state has no sources section") << endmsg;
1407 } else if (load_sources (*child)) {
1411 if ((child = find_named_node (node, "TempoMap")) == 0) {
1412 error << _("Session: XML state has no Tempo Map section") << endmsg;
1414 } else if (_tempo_map->set_state (*child, version)) {
1418 if ((child = find_named_node (node, "Locations")) == 0) {
1419 error << _("Session: XML state has no locations section") << endmsg;
1421 } else if (_locations->set_state (*child, version)) {
1425 locations_changed ();
1427 if (_session_range_location) {
1428 AudioFileSource::set_header_position_offset (_session_range_location->start());
1431 if ((child = find_named_node (node, "Regions")) == 0) {
1432 error << _("Session: XML state has no Regions section") << endmsg;
1434 } else if (load_regions (*child)) {
1438 if ((child = find_named_node (node, "Playlists")) == 0) {
1439 error << _("Session: XML state has no playlists section") << endmsg;
1441 } else if (playlists->load (*this, *child)) {
1445 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1447 } else if (playlists->load_unused (*this, *child)) {
1451 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1452 if (load_compounds (*child)) {
1457 if (version >= 3000) {
1458 if ((child = find_named_node (node, "Bundles")) == 0) {
1459 warning << _("Session: XML state has no bundles section") << endmsg;
1462 /* We can't load Bundles yet as they need to be able
1463 to convert from port names to Port objects, which can't happen until
1465 _bundle_xml_node = new XMLNode (*child);
1469 if (version < 3000) {
1470 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1471 error << _("Session: XML state has no diskstreams section") << endmsg;
1473 } else if (load_diskstreams_2X (*child, version)) {
1478 if ((child = find_named_node (node, VCAManager::xml_node_name)) != 0) {
1479 _vca_manager->set_state (*child, version);
1482 if ((child = find_named_node (node, "Routes")) == 0) {
1483 error << _("Session: XML state has no routes section") << endmsg;
1485 } else if (load_routes (*child, version)) {
1489 /* Now that we have Routes and masters loaded, connect them if appropriate */
1491 Slavable::Assign (_vca_manager); /* EMIT SIGNAL */
1493 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1494 _diskstreams_2X.clear ();
1496 if (version >= 3000) {
1498 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1499 error << _("Session: XML state has no route groups section") << endmsg;
1501 } else if (load_route_groups (*child, version)) {
1505 } else if (version < 3000) {
1507 if ((child = find_named_node (node, "EditGroups")) == 0) {
1508 error << _("Session: XML state has no edit groups section") << endmsg;
1510 } else if (load_route_groups (*child, version)) {
1514 if ((child = find_named_node (node, "MixGroups")) == 0) {
1515 error << _("Session: XML state has no mix groups section") << endmsg;
1517 } else if (load_route_groups (*child, version)) {
1522 if ((child = find_named_node (node, "Click")) == 0) {
1523 warning << _("Session: XML state has no click section") << endmsg;
1524 } else if (_click_io) {
1525 setup_click_state (&node);
1528 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1529 ControlProtocolManager::instance().set_state (*child, version);
1532 if ((child = find_named_node (node, "Script"))) {
1533 for (XMLNodeList::const_iterator n = child->children ().begin (); n != child->children ().end (); ++n) {
1534 if (!(*n)->is_content ()) { continue; }
1536 guchar* buf = g_base64_decode ((*n)->content ().c_str (), &size);
1538 Glib::Threads::Mutex::Lock lm (lua_lock);
1539 (*_lua_load)(std::string ((const char*)buf, size));
1540 } catch (luabridge::LuaException const& e) {
1541 cerr << "LuaException:" << e.what () << endl;
1547 update_route_record_state ();
1549 /* here beginneth the second phase ... */
1550 set_snapshot_name (_current_snapshot_name);
1552 StateReady (); /* EMIT SIGNAL */
1565 Session::load_routes (const XMLNode& node, int version)
1568 XMLNodeConstIterator niter;
1569 RouteList new_routes;
1571 nlist = node.children();
1575 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1577 boost::shared_ptr<Route> route;
1578 if (version < 3000) {
1579 route = XMLRouteFactory_2X (**niter, version);
1581 route = XMLRouteFactory (**niter, version);
1585 error << _("Session: cannot create Route from XML description.") << endmsg;
1589 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1591 new_routes.push_back (route);
1594 BootMessage (_("Tracks/busses loaded; Adding to Session"));
1596 add_routes (new_routes, false, false, false);
1598 BootMessage (_("Finished adding tracks/busses"));
1603 boost::shared_ptr<Route>
1604 Session::XMLRouteFactory (const XMLNode& node, int version)
1606 boost::shared_ptr<Route> ret;
1608 if (node.name() != "Route") {
1612 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1614 DataType type = DataType::AUDIO;
1615 XMLProperty const * prop = node.property("default-type");
1618 type = DataType (prop->value());
1621 assert (type != DataType::NIL);
1625 boost::shared_ptr<Track> track;
1627 if (type == DataType::AUDIO) {
1628 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1630 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1633 if (track->init()) {
1637 if (track->set_state (node, version)) {
1641 BOOST_MARK_TRACK (track);
1645 enum Route::Flag flags = Route::Flag(0);
1646 XMLProperty const * prop = node.property("flags");
1648 flags = Route::Flag (string_2_enum (prop->value(), flags));
1651 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1653 if (r->init () == 0 && r->set_state (node, version) == 0) {
1654 BOOST_MARK_ROUTE (r);
1662 boost::shared_ptr<Route>
1663 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1665 boost::shared_ptr<Route> ret;
1667 if (node.name() != "Route") {
1671 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1673 ds_prop = node.property (X_("diskstream"));
1676 DataType type = DataType::AUDIO;
1677 XMLProperty const * prop = node.property("default-type");
1680 type = DataType (prop->value());
1683 assert (type != DataType::NIL);
1687 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1688 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1692 if (i == _diskstreams_2X.end()) {
1693 error << _("Could not find diskstream for route") << endmsg;
1694 return boost::shared_ptr<Route> ();
1697 boost::shared_ptr<Track> track;
1699 if (type == DataType::AUDIO) {
1700 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1702 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1705 if (track->init()) {
1709 if (track->set_state (node, version)) {
1713 track->set_diskstream (*i);
1715 BOOST_MARK_TRACK (track);
1719 enum Route::Flag flags = Route::Flag(0);
1720 XMLProperty const * prop = node.property("flags");
1722 flags = Route::Flag (string_2_enum (prop->value(), flags));
1725 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1727 if (r->init () == 0 && r->set_state (node, version) == 0) {
1728 BOOST_MARK_ROUTE (r);
1737 Session::load_regions (const XMLNode& node)
1740 XMLNodeConstIterator niter;
1741 boost::shared_ptr<Region> region;
1743 nlist = node.children();
1747 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1748 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1749 error << _("Session: cannot create Region from XML description.");
1750 XMLProperty const * name = (**niter).property("name");
1753 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1764 Session::load_compounds (const XMLNode& node)
1766 XMLNodeList calist = node.children();
1767 XMLNodeConstIterator caiter;
1768 XMLProperty const * caprop;
1770 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1771 XMLNode* ca = *caiter;
1775 if ((caprop = ca->property (X_("original"))) == 0) {
1778 orig_id = caprop->value();
1780 if ((caprop = ca->property (X_("copy"))) == 0) {
1783 copy_id = caprop->value();
1785 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1786 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1788 if (!orig || !copy) {
1789 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1795 RegionFactory::add_compound_association (orig, copy);
1802 Session::load_nested_sources (const XMLNode& node)
1805 XMLNodeConstIterator niter;
1807 nlist = node.children();
1809 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1810 if ((*niter)->name() == "Source") {
1812 /* it may already exist, so don't recreate it unnecessarily
1815 XMLProperty const * prop = (*niter)->property (X_("id"));
1817 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1821 ID source_id (prop->value());
1823 if (!source_by_id (source_id)) {
1826 SourceFactory::create (*this, **niter, true);
1828 catch (failed_constructor& err) {
1829 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1836 boost::shared_ptr<Region>
1837 Session::XMLRegionFactory (const XMLNode& node, bool full)
1839 XMLProperty const * type = node.property("type");
1843 const XMLNodeList& nlist = node.children();
1845 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1846 XMLNode *child = (*niter);
1847 if (child->name() == "NestedSource") {
1848 load_nested_sources (*child);
1852 if (!type || type->value() == "audio") {
1853 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1854 } else if (type->value() == "midi") {
1855 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1858 } catch (failed_constructor& err) {
1859 return boost::shared_ptr<Region> ();
1862 return boost::shared_ptr<Region> ();
1865 boost::shared_ptr<AudioRegion>
1866 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1868 XMLProperty const * prop;
1869 boost::shared_ptr<Source> source;
1870 boost::shared_ptr<AudioSource> as;
1872 SourceList master_sources;
1873 uint32_t nchans = 1;
1876 if (node.name() != X_("Region")) {
1877 return boost::shared_ptr<AudioRegion>();
1880 if ((prop = node.property (X_("channels"))) != 0) {
1881 nchans = atoi (prop->value().c_str());
1884 if ((prop = node.property ("name")) == 0) {
1885 cerr << "no name for this region\n";
1889 if ((prop = node.property (X_("source-0"))) == 0) {
1890 if ((prop = node.property ("source")) == 0) {
1891 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1892 return boost::shared_ptr<AudioRegion>();
1896 PBD::ID s_id (prop->value());
1898 if ((source = source_by_id (s_id)) == 0) {
1899 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1900 return boost::shared_ptr<AudioRegion>();
1903 as = boost::dynamic_pointer_cast<AudioSource>(source);
1905 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1906 return boost::shared_ptr<AudioRegion>();
1909 sources.push_back (as);
1911 /* pickup other channels */
1913 for (uint32_t n=1; n < nchans; ++n) {
1914 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1915 if ((prop = node.property (buf)) != 0) {
1917 PBD::ID id2 (prop->value());
1919 if ((source = source_by_id (id2)) == 0) {
1920 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1921 return boost::shared_ptr<AudioRegion>();
1924 as = boost::dynamic_pointer_cast<AudioSource>(source);
1926 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1927 return boost::shared_ptr<AudioRegion>();
1929 sources.push_back (as);
1933 for (uint32_t n = 0; n < nchans; ++n) {
1934 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1935 if ((prop = node.property (buf)) != 0) {
1937 PBD::ID id2 (prop->value());
1939 if ((source = source_by_id (id2)) == 0) {
1940 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1941 return boost::shared_ptr<AudioRegion>();
1944 as = boost::dynamic_pointer_cast<AudioSource>(source);
1946 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1947 return boost::shared_ptr<AudioRegion>();
1949 master_sources.push_back (as);
1954 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1956 /* a final detail: this is the one and only place that we know how long missing files are */
1958 if (region->whole_file()) {
1959 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1960 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1962 sfp->set_length (region->length());
1967 if (!master_sources.empty()) {
1968 if (master_sources.size() != nchans) {
1969 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1971 region->set_master_sources (master_sources);
1979 catch (failed_constructor& err) {
1980 return boost::shared_ptr<AudioRegion>();
1984 boost::shared_ptr<MidiRegion>
1985 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1987 XMLProperty const * prop;
1988 boost::shared_ptr<Source> source;
1989 boost::shared_ptr<MidiSource> ms;
1992 if (node.name() != X_("Region")) {
1993 return boost::shared_ptr<MidiRegion>();
1996 if ((prop = node.property ("name")) == 0) {
1997 cerr << "no name for this region\n";
2001 if ((prop = node.property (X_("source-0"))) == 0) {
2002 if ((prop = node.property ("source")) == 0) {
2003 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
2004 return boost::shared_ptr<MidiRegion>();
2008 PBD::ID s_id (prop->value());
2010 if ((source = source_by_id (s_id)) == 0) {
2011 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
2012 return boost::shared_ptr<MidiRegion>();
2015 ms = boost::dynamic_pointer_cast<MidiSource>(source);
2017 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
2018 return boost::shared_ptr<MidiRegion>();
2021 sources.push_back (ms);
2024 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
2025 /* a final detail: this is the one and only place that we know how long missing files are */
2027 if (region->whole_file()) {
2028 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
2029 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
2031 sfp->set_length (region->length());
2039 catch (failed_constructor& err) {
2040 return boost::shared_ptr<MidiRegion>();
2045 Session::get_sources_as_xml ()
2048 XMLNode* node = new XMLNode (X_("Sources"));
2049 Glib::Threads::Mutex::Lock lm (source_lock);
2051 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2052 node->add_child_nocopy (i->second->get_state());
2059 Session::reset_write_sources (bool mark_write_complete, bool force)
2061 boost::shared_ptr<RouteList> rl = routes.reader();
2062 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
2063 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
2065 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
2066 tr->reset_write_sources(mark_write_complete, force);
2067 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
2073 Session::load_sources (const XMLNode& node)
2076 XMLNodeConstIterator niter;
2077 boost::shared_ptr<Source> source; /* don't need this but it stops some
2078 * versions of gcc complaining about
2079 * discarded return values.
2082 nlist = node.children();
2086 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2089 if ((source = XMLSourceFactory (**niter)) == 0) {
2090 error << _("Session: cannot create Source from XML description.") << endmsg;
2093 } catch (MissingSource& err) {
2097 if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
2098 error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
2099 PROGRAM_NAME) << endmsg;
2103 if (!no_questions_about_missing_files) {
2104 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
2109 switch (user_choice) {
2111 /* user added a new search location, so try again */
2116 /* user asked to quit the entire session load
2121 no_questions_about_missing_files = true;
2125 no_questions_about_missing_files = true;
2132 case DataType::AUDIO:
2133 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
2136 case DataType::MIDI:
2137 /* The MIDI file is actually missing so
2138 * just create a new one in the same
2139 * location. Do not announce its
2143 if (!Glib::path_is_absolute (err.path)) {
2144 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
2146 /* this should be an unrecoverable error: we would be creating a MIDI file outside
2151 /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
2152 source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
2153 /* reset ID to match the missing one */
2154 source->set_id (**niter);
2155 /* Now we can announce it */
2156 SourceFactory::SourceCreated (source);
2167 boost::shared_ptr<Source>
2168 Session::XMLSourceFactory (const XMLNode& node)
2170 if (node.name() != "Source") {
2171 return boost::shared_ptr<Source>();
2175 /* note: do peak building in another thread when loading session state */
2176 return SourceFactory::create (*this, node, true);
2179 catch (failed_constructor& err) {
2180 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
2181 return boost::shared_ptr<Source>();
2186 Session::save_template (string template_name, bool replace_existing)
2188 if ((_state_of_the_state & CannotSave) || template_name.empty ()) {
2192 bool absolute_path = Glib::path_is_absolute (template_name);
2194 /* directory to put the template in */
2195 std::string template_dir_path;
2197 if (!absolute_path) {
2198 std::string user_template_dir(user_template_directory());
2200 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2201 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2202 user_template_dir, g_strerror (errno)) << endmsg;
2206 template_dir_path = Glib::build_filename (user_template_dir, template_name);
2208 template_dir_path = template_name;
2211 if (!ARDOUR::Profile->get_trx()) {
2212 if (!replace_existing && Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2213 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2214 template_dir_path) << endmsg;
2218 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2219 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2220 template_dir_path, g_strerror (errno)) << endmsg;
2226 std::string template_file_path;
2228 if (ARDOUR::Profile->get_trx()) {
2229 template_file_path = template_name;
2231 if (absolute_path) {
2232 template_file_path = Glib::build_filename (template_dir_path, Glib::path_get_basename (template_dir_path) + template_suffix);
2234 template_file_path = Glib::build_filename (template_dir_path, template_name + template_suffix);
2238 SessionSaveUnderway (); /* EMIT SIGNAL */
2243 PBD::Unwinder<std::string> uw (_template_state_dir, template_dir_path);
2244 tree.set_root (&get_template());
2247 if (!tree.write (template_file_path)) {
2248 error << _("template not saved") << endmsg;
2252 store_recent_templates (template_file_path);
2258 Session::refresh_disk_space ()
2260 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2262 Glib::Threads::Mutex::Lock lm (space_lock);
2264 /* get freespace on every FS that is part of the session path */
2266 _total_free_4k_blocks = 0;
2267 _total_free_4k_blocks_uncertain = false;
2269 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2271 struct statfs statfsbuf;
2272 statfs (i->path.c_str(), &statfsbuf);
2274 double const scale = statfsbuf.f_bsize / 4096.0;
2276 /* See if this filesystem is read-only */
2277 struct statvfs statvfsbuf;
2278 statvfs (i->path.c_str(), &statvfsbuf);
2280 /* f_bavail can be 0 if it is undefined for whatever
2281 filesystem we are looking at; Samba shares mounted
2282 via GVFS are an example of this.
2284 if (statfsbuf.f_bavail == 0) {
2285 /* block count unknown */
2287 i->blocks_unknown = true;
2288 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2289 /* read-only filesystem */
2291 i->blocks_unknown = false;
2293 /* read/write filesystem with known space */
2294 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2295 i->blocks_unknown = false;
2298 _total_free_4k_blocks += i->blocks;
2299 if (i->blocks_unknown) {
2300 _total_free_4k_blocks_uncertain = true;
2303 #elif defined PLATFORM_WINDOWS
2304 vector<string> scanned_volumes;
2305 vector<string>::iterator j;
2306 vector<space_and_path>::iterator i;
2307 DWORD nSectorsPerCluster, nBytesPerSector,
2308 nFreeClusters, nTotalClusters;
2312 _total_free_4k_blocks = 0;
2314 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2315 strncpy (disk_drive, (*i).path.c_str(), 3);
2319 volume_found = false;
2320 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2322 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2323 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2324 i->blocks = (uint32_t)(nFreeBytes / 4096);
2326 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2327 if (0 == j->compare(disk_drive)) {
2328 volume_found = true;
2333 if (!volume_found) {
2334 scanned_volumes.push_back(disk_drive);
2335 _total_free_4k_blocks += i->blocks;
2340 if (0 == _total_free_4k_blocks) {
2341 strncpy (disk_drive, path().c_str(), 3);
2344 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2346 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2347 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2348 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2355 Session::get_best_session_directory_for_new_audio ()
2357 vector<space_and_path>::iterator i;
2358 string result = _session_dir->root_path();
2360 /* handle common case without system calls */
2362 if (session_dirs.size() == 1) {
2366 /* OK, here's the algorithm we're following here:
2368 We want to select which directory to use for
2369 the next file source to be created. Ideally,
2370 we'd like to use a round-robin process so as to
2371 get maximum performance benefits from splitting
2372 the files across multiple disks.
2374 However, in situations without much diskspace, an
2375 RR approach may end up filling up a filesystem
2376 with new files while others still have space.
2377 Its therefore important to pay some attention to
2378 the freespace in the filesystem holding each
2379 directory as well. However, if we did that by
2380 itself, we'd keep creating new files in the file
2381 system with the most space until it was as full
2382 as all others, thus negating any performance
2383 benefits of this RAID-1 like approach.
2385 So, we use a user-configurable space threshold. If
2386 there are at least 2 filesystems with more than this
2387 much space available, we use RR selection between them.
2388 If not, then we pick the filesystem with the most space.
2390 This gets a good balance between the two
2394 refresh_disk_space ();
2396 int free_enough = 0;
2398 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2399 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2404 if (free_enough >= 2) {
2405 /* use RR selection process, ensuring that the one
2409 i = last_rr_session_dir;
2412 if (++i == session_dirs.end()) {
2413 i = session_dirs.begin();
2416 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2417 SessionDirectory sdir(i->path);
2418 if (sdir.create ()) {
2420 last_rr_session_dir = i;
2425 } while (i != last_rr_session_dir);
2429 /* pick FS with the most freespace (and that
2430 seems to actually work ...)
2433 vector<space_and_path> sorted;
2434 space_and_path_ascending_cmp cmp;
2436 sorted = session_dirs;
2437 sort (sorted.begin(), sorted.end(), cmp);
2439 for (i = sorted.begin(); i != sorted.end(); ++i) {
2440 SessionDirectory sdir(i->path);
2441 if (sdir.create ()) {
2443 last_rr_session_dir = i;
2453 Session::automation_dir () const
2455 return Glib::build_filename (_path, automation_dir_name);
2459 Session::analysis_dir () const
2461 return Glib::build_filename (_path, analysis_dir_name);
2465 Session::plugins_dir () const
2467 return Glib::build_filename (_path, plugins_dir_name);
2471 Session::externals_dir () const
2473 return Glib::build_filename (_path, externals_dir_name);
2477 Session::load_bundles (XMLNode const & node)
2479 XMLNodeList nlist = node.children();
2480 XMLNodeConstIterator niter;
2484 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2485 if ((*niter)->name() == "InputBundle") {
2486 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2487 } else if ((*niter)->name() == "OutputBundle") {
2488 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2490 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2499 Session::load_route_groups (const XMLNode& node, int version)
2501 XMLNodeList nlist = node.children();
2502 XMLNodeConstIterator niter;
2506 if (version >= 3000) {
2508 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2509 if ((*niter)->name() == "RouteGroup") {
2510 RouteGroup* rg = new RouteGroup (*this, "");
2511 add_route_group (rg);
2512 rg->set_state (**niter, version);
2516 } else if (version < 3000) {
2518 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2519 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2520 RouteGroup* rg = new RouteGroup (*this, "");
2521 add_route_group (rg);
2522 rg->set_state (**niter, version);
2531 state_file_filter (const string &str, void* /*arg*/)
2533 return (str.length() > strlen(statefile_suffix) &&
2534 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2538 remove_end(string state)
2540 string statename(state);
2542 string::size_type start,end;
2543 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2544 statename = statename.substr (start+1);
2547 if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2548 end = statename.length();
2551 return string(statename.substr (0, end));
2555 Session::possible_states (string path)
2557 vector<string> states;
2558 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2560 transform(states.begin(), states.end(), states.begin(), remove_end);
2562 sort (states.begin(), states.end());
2568 Session::possible_states () const
2570 return possible_states(_path);
2574 Session::add_route_group (RouteGroup* g)
2576 _route_groups.push_back (g);
2577 route_group_added (g); /* EMIT SIGNAL */
2579 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2580 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2581 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2587 Session::remove_route_group (RouteGroup& rg)
2589 list<RouteGroup*>::iterator i;
2591 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2592 _route_groups.erase (i);
2595 route_group_removed (); /* EMIT SIGNAL */
2599 /** Set a new order for our route groups, without adding or removing any.
2600 * @param groups Route group list in the new order.
2603 Session::reorder_route_groups (list<RouteGroup*> groups)
2605 _route_groups = groups;
2607 route_groups_reordered (); /* EMIT SIGNAL */
2613 Session::route_group_by_name (string name)
2615 list<RouteGroup *>::iterator i;
2617 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2618 if ((*i)->name() == name) {
2626 Session::all_route_group() const
2628 return *_all_route_group;
2632 Session::add_commands (vector<Command*> const & cmds)
2634 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2640 Session::add_command (Command* const cmd)
2642 assert (_current_trans);
2643 DEBUG_UNDO_HISTORY (
2644 string_compose ("Current Undo Transaction %1, adding command: %2",
2645 _current_trans->name (),
2647 _current_trans->add_command (cmd);
2650 PBD::StatefulDiffCommand*
2651 Session::add_stateful_diff_command (boost::shared_ptr<PBD::StatefulDestructible> sfd)
2653 PBD::StatefulDiffCommand* cmd = new PBD::StatefulDiffCommand (sfd);
2659 Session::begin_reversible_command (const string& name)
2661 begin_reversible_command (g_quark_from_string (name.c_str ()));
2664 /** Begin a reversible command using a GQuark to identify it.
2665 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2666 * but there must be as many begin...()s as there are commit...()s.
2669 Session::begin_reversible_command (GQuark q)
2671 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2672 to hold all the commands that are committed. This keeps the order of
2673 commands correct in the history.
2676 if (_current_trans == 0) {
2677 DEBUG_UNDO_HISTORY (string_compose (
2678 "Begin Reversible Command, new transaction: %1", g_quark_to_string (q)));
2680 /* start a new transaction */
2681 assert (_current_trans_quarks.empty ());
2682 _current_trans = new UndoTransaction();
2683 _current_trans->set_name (g_quark_to_string (q));
2685 DEBUG_UNDO_HISTORY (
2686 string_compose ("Begin Reversible Command, current transaction: %1",
2687 _current_trans->name ()));
2690 _current_trans_quarks.push_front (q);
2694 Session::abort_reversible_command ()
2696 if (_current_trans != 0) {
2697 DEBUG_UNDO_HISTORY (
2698 string_compose ("Abort Reversible Command: %1", _current_trans->name ()));
2699 _current_trans->clear();
2700 delete _current_trans;
2702 _current_trans_quarks.clear();
2707 Session::commit_reversible_command (Command *cmd)
2709 assert (_current_trans);
2710 assert (!_current_trans_quarks.empty ());
2715 DEBUG_UNDO_HISTORY (
2716 string_compose ("Current Undo Transaction %1, adding command: %2",
2717 _current_trans->name (),
2719 _current_trans->add_command (cmd);
2722 DEBUG_UNDO_HISTORY (
2723 string_compose ("Commit Reversible Command, current transaction: %1",
2724 _current_trans->name ()));
2726 _current_trans_quarks.pop_front ();
2728 if (!_current_trans_quarks.empty ()) {
2729 DEBUG_UNDO_HISTORY (
2730 string_compose ("Commit Reversible Command, transaction is not "
2731 "top-level, current transaction: %1",
2732 _current_trans->name ()));
2733 /* the transaction we're committing is not the top-level one */
2737 if (_current_trans->empty()) {
2738 /* no commands were added to the transaction, so just get rid of it */
2739 DEBUG_UNDO_HISTORY (
2740 string_compose ("Commit Reversible Command, No commands were "
2741 "added to current transaction: %1",
2742 _current_trans->name ()));
2743 delete _current_trans;
2748 gettimeofday (&now, 0);
2749 _current_trans->set_timestamp (now);
2751 _history.add (_current_trans);
2756 accept_all_audio_files (const string& path, void* /*arg*/)
2758 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2762 if (!AudioFileSource::safe_audio_file_extension (path)) {
2770 accept_all_midi_files (const string& path, void* /*arg*/)
2772 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2776 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2777 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2778 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2782 accept_all_state_files (const string& path, void* /*arg*/)
2784 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2788 std::string const statefile_ext (statefile_suffix);
2789 if (path.length() >= statefile_ext.length()) {
2790 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2797 Session::find_all_sources (string path, set<string>& result)
2802 if (!tree.read (path)) {
2806 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2811 XMLNodeConstIterator niter;
2813 nlist = node->children();
2817 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2819 XMLProperty const * prop;
2821 if ((prop = (*niter)->property (X_("type"))) == 0) {
2825 DataType type (prop->value());
2827 if ((prop = (*niter)->property (X_("name"))) == 0) {
2831 if (Glib::path_is_absolute (prop->value())) {
2832 /* external file, ignore */
2840 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2841 result.insert (found_path);
2849 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2851 vector<string> state_files;
2853 string this_snapshot_path;
2859 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2860 ripped = ripped.substr (0, ripped.length() - 1);
2863 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2865 if (state_files.empty()) {
2870 this_snapshot_path = _path;
2871 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2872 this_snapshot_path += statefile_suffix;
2874 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2876 if (exclude_this_snapshot && *i == this_snapshot_path) {
2880 if (find_all_sources (*i, result) < 0) {
2888 struct RegionCounter {
2889 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2890 AudioSourceList::iterator iter;
2891 boost::shared_ptr<Region> region;
2894 RegionCounter() : count (0) {}
2898 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2900 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2901 return r.get_value_or (1);
2905 Session::cleanup_regions ()
2907 bool removed = false;
2908 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2910 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2912 uint32_t used = playlists->region_use_count (i->second);
2914 if (used == 0 && !i->second->automatic ()) {
2915 boost::weak_ptr<Region> w = i->second;
2918 RegionFactory::map_remove (w);
2925 // re-check to remove parent references of compound regions
2926 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2927 if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2931 assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2932 if (0 == playlists->region_use_count (i->second)) {
2933 boost::weak_ptr<Region> w = i->second;
2935 RegionFactory::map_remove (w);
2942 /* dump the history list */
2949 Session::can_cleanup_peakfiles () const
2951 if (deletion_in_progress()) {
2954 if (!_writable || (_state_of_the_state & CannotSave)) {
2955 warning << _("Cannot cleanup peak-files for read-only session.") << endmsg;
2958 if (record_status() == Recording) {
2959 error << _("Cannot cleanup peak-files while recording") << endmsg;
2966 Session::cleanup_peakfiles ()
2968 Glib::Threads::Mutex::Lock lm (peak_cleanup_lock, Glib::Threads::TRY_LOCK);
2973 assert (can_cleanup_peakfiles ());
2974 assert (!peaks_cleanup_in_progres());
2976 _state_of_the_state = StateOfTheState (_state_of_the_state | PeakCleanup);
2978 int timeout = 5000; // 5 seconds
2979 while (!SourceFactory::files_with_peaks.empty()) {
2980 Glib::usleep (1000);
2981 if (--timeout < 0) {
2982 warning << _("Timeout waiting for peak-file creation to terminate before cleanup, please try again later.") << endmsg;
2983 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
2988 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2989 boost::shared_ptr<AudioSource> as;
2990 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
2991 as->close_peakfile();
2995 PBD::clear_directory (session_directory().peak_path());
2997 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
2999 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3000 boost::shared_ptr<AudioSource> as;
3001 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
3002 SourceFactory::setup_peakfile(as, true);
3009 Session::cleanup_sources (CleanupReport& rep)
3011 // FIXME: needs adaptation to midi
3013 vector<boost::shared_ptr<Source> > dead_sources;
3016 vector<string> candidates;
3017 vector<string> unused;
3018 set<string> all_sources;
3027 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
3029 /* this is mostly for windows which doesn't allow file
3030 * renaming if the file is in use. But we don't special
3031 * case it because we need to know if this causes
3032 * problems, and the easiest way to notice that is to
3033 * keep it in place for all platforms.
3036 request_stop (false);
3038 _butler->wait_until_finished ();
3040 /* consider deleting all unused playlists */
3042 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
3047 /* sync the "all regions" property of each playlist with its current state
3050 playlists->sync_all_regions_with_regions ();
3052 /* find all un-used sources */
3057 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3059 SourceMap::iterator tmp;
3064 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
3068 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
3069 dead_sources.push_back (i->second);
3070 i->second->drop_references ();
3076 /* build a list of all the possible audio directories for the session */
3078 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3079 SessionDirectory sdir ((*i).path);
3080 asp += sdir.sound_path();
3082 audio_path += asp.to_string();
3085 /* build a list of all the possible midi directories for the session */
3087 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3088 SessionDirectory sdir ((*i).path);
3089 msp += sdir.midi_path();
3091 midi_path += msp.to_string();
3093 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
3094 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
3096 /* find all sources, but don't use this snapshot because the
3097 state file on disk still references sources we may have already
3101 find_all_sources_across_snapshots (all_sources, true);
3103 /* add our current source list
3106 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3107 boost::shared_ptr<FileSource> fs;
3108 SourceMap::iterator tmp = i;
3111 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
3113 /* this is mostly for windows which doesn't allow file
3114 * renaming if the file is in use. But we don't special
3115 * case it because we need to know if this causes
3116 * problems, and the easiest way to notice that is to
3117 * keep it in place for all platforms.
3122 if (!fs->is_stub()) {
3124 if (playlists->source_use_count (fs) != 0) {
3125 all_sources.insert (fs->path());
3128 /* we might not remove this source from disk, because it may be used
3129 by other snapshots, but its not being used in this version
3130 so lets get rid of it now, along with any representative regions
3134 RegionFactory::remove_regions_using_source (i->second);
3136 // also remove source from all_sources
3138 for (set<string>::iterator j = all_sources.begin(); j != all_sources.end(); ++j) {
3139 spath = Glib::path_get_basename (*j);
3140 if (spath == i->second->name()) {
3141 all_sources.erase (j);
3154 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
3159 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
3161 tmppath1 = canonical_path (spath);
3162 tmppath2 = canonical_path ((*i));
3164 if (tmppath1 == tmppath2) {
3171 unused.push_back (spath);
3175 /* now try to move all unused files into the "dead" directory(ies) */
3177 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
3182 /* don't move the file across filesystems, just
3183 stick it in the `dead_dir_name' directory
3184 on whichever filesystem it was already on.
3187 if ((*x).find ("/sounds/") != string::npos) {
3189 /* old school, go up 1 level */
3191 newpath = Glib::path_get_dirname (*x); // "sounds"
3192 newpath = Glib::path_get_dirname (newpath); // "session-name"
3196 /* new school, go up 4 levels */
3198 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
3199 newpath = Glib::path_get_dirname (newpath); // "session-name"
3200 newpath = Glib::path_get_dirname (newpath); // "interchange"
3201 newpath = Glib::path_get_dirname (newpath); // "session-dir"
3204 newpath = Glib::build_filename (newpath, dead_dir_name);
3206 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
3207 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
3211 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
3213 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
3215 /* the new path already exists, try versioning */
3217 char buf[PATH_MAX+1];
3221 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3224 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
3225 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3229 if (version == 999) {
3230 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3234 newpath = newpath_v;
3239 /* it doesn't exist, or we can't read it or something */
3243 g_stat ((*x).c_str(), &statbuf);
3245 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3246 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
3247 (*x), newpath, strerror (errno))
3252 /* see if there an easy to find peakfile for this file, and remove it.
3255 string base = Glib::path_get_basename (*x);
3256 base += "%A"; /* this is what we add for the channel suffix of all native files,
3257 or for the first channel of embedded files. it will miss
3258 some peakfiles for other channels
3260 string peakpath = construct_peak_filepath (base);
3262 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
3263 if (::g_unlink (peakpath.c_str()) != 0) {
3264 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3265 peakpath, _path, strerror (errno))
3267 /* try to back out */
3268 ::rename (newpath.c_str(), _path.c_str());
3273 rep.paths.push_back (*x);
3274 rep.space += statbuf.st_size;
3277 /* dump the history list */
3281 /* save state so we don't end up a session file
3282 referring to non-existent sources.
3289 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3295 Session::cleanup_trash_sources (CleanupReport& rep)
3297 // FIXME: needs adaptation for MIDI
3299 vector<space_and_path>::iterator i;
3305 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3307 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
3309 clear_directory (dead_dir, &rep.space, &rep.paths);
3316 Session::set_dirty ()
3318 /* never mark session dirty during loading */
3320 if (_state_of_the_state & Loading) {
3324 bool was_dirty = dirty();
3326 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3330 DirtyChanged(); /* EMIT SIGNAL */
3336 Session::set_clean ()
3338 bool was_dirty = dirty();
3340 _state_of_the_state = Clean;
3344 DirtyChanged(); /* EMIT SIGNAL */
3349 Session::set_deletion_in_progress ()
3351 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3355 Session::clear_deletion_in_progress ()
3357 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3361 Session::add_controllable (boost::shared_ptr<Controllable> c)
3363 /* this adds a controllable to the list managed by the Session.
3364 this is a subset of those managed by the Controllable class
3365 itself, and represents the only ones whose state will be saved
3366 as part of the session.
3369 Glib::Threads::Mutex::Lock lm (controllables_lock);
3370 controllables.insert (c);
3373 struct null_deleter { void operator()(void const *) const {} };
3376 Session::remove_controllable (Controllable* c)
3378 if (_state_of_the_state & Deletion) {
3382 Glib::Threads::Mutex::Lock lm (controllables_lock);
3384 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3386 if (x != controllables.end()) {
3387 controllables.erase (x);
3391 boost::shared_ptr<Controllable>
3392 Session::controllable_by_id (const PBD::ID& id)
3394 Glib::Threads::Mutex::Lock lm (controllables_lock);
3396 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3397 if ((*i)->id() == id) {
3402 return boost::shared_ptr<Controllable>();
3405 boost::shared_ptr<Controllable>
3406 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3408 boost::shared_ptr<Controllable> c;
3409 boost::shared_ptr<Route> r;
3411 switch (desc.top_level_type()) {
3412 case ControllableDescriptor::NamedRoute:
3414 std::string str = desc.top_level_name();
3415 if (str == "Master" || str == "master") {
3417 } else if (str == "control" || str == "listen") {
3420 r = route_by_name (desc.top_level_name());
3425 case ControllableDescriptor::RemoteControlID:
3426 r = route_by_remote_id (desc.rid());
3429 case ControllableDescriptor::SelectionCount:
3430 r = route_by_selected_count (desc.selection_id());
3438 switch (desc.subtype()) {
3439 case ControllableDescriptor::Gain:
3440 c = r->gain_control ();
3443 case ControllableDescriptor::Trim:
3444 c = r->trim()->gain_control ();
3447 case ControllableDescriptor::Solo:
3448 c = r->solo_control();
3451 case ControllableDescriptor::Mute:
3452 c = r->mute_control();
3455 case ControllableDescriptor::Recenable:
3457 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3460 c = t->rec_enable_control ();
3465 case ControllableDescriptor::PanDirection:
3466 c = r->pan_azimuth_control();
3469 case ControllableDescriptor::PanWidth:
3470 c = r->pan_width_control();
3473 case ControllableDescriptor::PanElevation:
3474 c = r->pan_elevation_control();
3477 case ControllableDescriptor::Balance:
3478 /* XXX simple pan control */
3481 case ControllableDescriptor::PluginParameter:
3483 uint32_t plugin = desc.target (0);
3484 uint32_t parameter_index = desc.target (1);
3486 /* revert to zero based counting */
3492 if (parameter_index > 0) {
3496 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3499 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3500 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3505 case ControllableDescriptor::SendGain: {
3506 uint32_t send = desc.target (0);
3510 c = r->send_level_controllable (send);
3515 /* relax and return a null pointer */
3523 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3526 Stateful::add_instant_xml (node, _path);
3529 if (write_to_config) {
3530 Config->add_instant_xml (node);
3535 Session::instant_xml (const string& node_name)
3537 return Stateful::instant_xml (node_name, _path);
3541 Session::save_history (string snapshot_name)
3549 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3550 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3554 if (snapshot_name.empty()) {
3555 snapshot_name = _current_snapshot_name;
3558 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3559 const string backup_filename = history_filename + backup_suffix;
3560 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3561 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3563 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3564 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3565 error << _("could not backup old history file, current history not saved") << endmsg;
3570 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3572 if (!tree.write (xml_path))
3574 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3576 if (g_remove (xml_path.c_str()) != 0) {
3577 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3578 xml_path, g_strerror (errno)) << endmsg;
3580 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3581 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3582 backup_path, g_strerror (errno)) << endmsg;
3592 Session::restore_history (string snapshot_name)
3596 if (snapshot_name.empty()) {
3597 snapshot_name = _current_snapshot_name;
3600 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3601 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3603 info << "Loading history from " << xml_path << endmsg;
3605 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3606 info << string_compose (_("%1: no history file \"%2\" for this session."),
3607 _name, xml_path) << endmsg;
3611 if (!tree.read (xml_path)) {
3612 error << string_compose (_("Could not understand session history file \"%1\""),
3613 xml_path) << endmsg;
3620 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3623 UndoTransaction* ut = new UndoTransaction ();
3626 ut->set_name(t->property("name")->value());
3627 stringstream ss(t->property("tv-sec")->value());
3629 ss.str(t->property("tv-usec")->value());
3631 ut->set_timestamp(tv);
3633 for (XMLNodeConstIterator child_it = t->children().begin();
3634 child_it != t->children().end(); child_it++)
3636 XMLNode *n = *child_it;
3639 if (n->name() == "MementoCommand" ||
3640 n->name() == "MementoUndoCommand" ||
3641 n->name() == "MementoRedoCommand") {
3643 if ((c = memento_command_factory(n))) {
3647 } else if (n->name() == "NoteDiffCommand") {
3648 PBD::ID id (n->property("midi-source")->value());
3649 boost::shared_ptr<MidiSource> midi_source =
3650 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3652 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3654 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3657 } else if (n->name() == "SysExDiffCommand") {
3659 PBD::ID id (n->property("midi-source")->value());
3660 boost::shared_ptr<MidiSource> midi_source =
3661 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3663 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3665 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3668 } else if (n->name() == "PatchChangeDiffCommand") {
3670 PBD::ID id (n->property("midi-source")->value());
3671 boost::shared_ptr<MidiSource> midi_source =
3672 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3674 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3676 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3679 } else if (n->name() == "StatefulDiffCommand") {
3680 if ((c = stateful_diff_command_factory (n))) {
3681 ut->add_command (c);
3684 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3695 Session::config_changed (std::string p, bool ours)
3701 if (p == "seamless-loop") {
3703 } else if (p == "rf-speed") {
3705 } else if (p == "auto-loop") {
3707 } else if (p == "auto-input") {
3709 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3710 /* auto-input only makes a difference if we're rolling */
3711 set_track_monitor_input_status (!config.get_auto_input());
3714 } else if (p == "punch-in") {
3718 if ((location = _locations->auto_punch_location()) != 0) {
3720 if (config.get_punch_in ()) {
3721 replace_event (SessionEvent::PunchIn, location->start());
3723 remove_event (location->start(), SessionEvent::PunchIn);
3727 } else if (p == "punch-out") {
3731 if ((location = _locations->auto_punch_location()) != 0) {
3733 if (config.get_punch_out()) {
3734 replace_event (SessionEvent::PunchOut, location->end());
3736 clear_events (SessionEvent::PunchOut);
3740 } else if (p == "edit-mode") {
3742 Glib::Threads::Mutex::Lock lm (playlists->lock);
3744 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3745 (*i)->set_edit_mode (Config->get_edit_mode ());
3748 } else if (p == "use-video-sync") {
3750 waiting_for_sync_offset = config.get_use_video_sync();
3752 } else if (p == "mmc-control") {
3754 //poke_midi_thread ();
3756 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3758 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3760 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3762 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3764 } else if (p == "midi-control") {
3766 //poke_midi_thread ();
3768 } else if (p == "raid-path") {
3770 setup_raid_path (config.get_raid_path());
3772 } else if (p == "timecode-format") {
3776 } else if (p == "video-pullup") {
3780 } else if (p == "seamless-loop") {
3782 if (play_loop && transport_rolling()) {
3783 // to reset diskstreams etc
3784 request_play_loop (true);
3787 } else if (p == "rf-speed") {
3789 cumulative_rf_motion = 0;
3792 } else if (p == "click-sound") {
3794 setup_click_sounds (1);
3796 } else if (p == "click-emphasis-sound") {
3798 setup_click_sounds (-1);
3800 } else if (p == "clicking") {
3802 if (Config->get_clicking()) {
3803 if (_click_io && click_data) { // don't require emphasis data
3810 } else if (p == "click-gain") {
3813 _click_gain->gain_control()->set_value (Config->get_click_gain(), Controllable::NoGroup);
3816 } else if (p == "send-mtc") {
3818 if (Config->get_send_mtc ()) {
3819 /* mark us ready to send */
3820 next_quarter_frame_to_send = 0;
3823 } else if (p == "send-mmc") {
3825 _mmc->enable_send (Config->get_send_mmc ());
3827 } else if (p == "midi-feedback") {
3829 session_midi_feedback = Config->get_midi_feedback();
3831 } else if (p == "jack-time-master") {
3833 engine().reset_timebase ();
3835 } else if (p == "native-file-header-format") {
3837 if (!first_file_header_format_reset) {
3838 reset_native_file_format ();
3841 first_file_header_format_reset = false;
3843 } else if (p == "native-file-data-format") {
3845 if (!first_file_data_format_reset) {
3846 reset_native_file_format ();
3849 first_file_data_format_reset = false;
3851 } else if (p == "external-sync") {
3852 if (!config.get_external_sync()) {
3853 drop_sync_source ();
3855 switch_to_sync_source (Config->get_sync_source());
3857 } else if (p == "denormal-model") {
3859 } else if (p == "history-depth") {
3860 set_history_depth (Config->get_history_depth());
3861 } else if (p == "remote-model") {
3862 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3865 } else if (p == "initial-program-change") {
3867 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3870 buf[0] = MIDI::program; // channel zero by default
3871 buf[1] = (Config->get_initial_program_change() & 0x7f);
3873 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3875 } else if (p == "solo-mute-override") {
3876 // catch_up_on_solo_mute_override ();
3877 } else if (p == "listen-position" || p == "pfl-position") {
3878 listen_position_changed ();
3879 } else if (p == "solo-control-is-listen-control") {
3880 solo_control_mode_changed ();
3881 } else if (p == "solo-mute-gain") {
3882 _solo_cut_control->Changed (true, Controllable::NoGroup);
3883 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3884 last_timecode_valid = false;
3885 } else if (p == "playback-buffer-seconds") {
3886 AudioSource::allocate_working_buffers (frame_rate());
3887 } else if (p == "ltc-source-port") {
3888 reconnect_ltc_input ();
3889 } else if (p == "ltc-sink-port") {
3890 reconnect_ltc_output ();
3891 } else if (p == "timecode-generator-offset") {
3892 ltc_tx_parse_offset();
3893 } else if (p == "auto-return-target-list") {
3894 follow_playhead_priority ();
3901 Session::set_history_depth (uint32_t d)
3903 _history.set_depth (d);
3907 Session::load_diskstreams_2X (XMLNode const & node, int)
3910 XMLNodeConstIterator citer;
3912 clist = node.children();
3914 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3917 /* diskstreams added automatically by DiskstreamCreated handler */
3918 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3919 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3920 _diskstreams_2X.push_back (dsp);
3922 error << _("Session: unknown diskstream type in XML") << endmsg;
3926 catch (failed_constructor& err) {
3927 error << _("Session: could not load diskstream via XML state") << endmsg;
3935 /** Connect things to the MMC object */
3937 Session::setup_midi_machine_control ()
3939 _mmc = new MIDI::MachineControl;
3941 boost::shared_ptr<AsyncMIDIPort> async_in = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_input_port());
3942 boost::shared_ptr<AsyncMIDIPort> async_out = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_output_port());
3944 if (!async_out || !async_out) {
3948 /* XXXX argh, passing raw pointers back into libmidi++ */
3950 MIDI::Port* mmc_in = async_in.get();
3951 MIDI::Port* mmc_out = async_out.get();
3953 _mmc->set_ports (mmc_in, mmc_out);
3955 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3956 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3957 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3958 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3959 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3960 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3961 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3962 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3963 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3964 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3965 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3966 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3967 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3969 /* also handle MIDI SPP because its so common */
3971 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3972 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3973 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3976 boost::shared_ptr<Controllable>
3977 Session::solo_cut_control() const
3979 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3980 controls in Ardour that currently get presented to the user in the GUI that require
3981 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3983 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3984 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3988 return _solo_cut_control;
3992 Session::save_snapshot_name (const std::string & n)
3994 /* assure Stateful::_instant_xml is loaded
3995 * add_instant_xml() only adds to existing data and defaults
3996 * to use an empty Tree otherwise
3998 instant_xml ("LastUsedSnapshot");
4000 XMLNode* last_used_snapshot = new XMLNode ("LastUsedSnapshot");
4001 last_used_snapshot->add_property ("name", string(n));
4002 add_instant_xml (*last_used_snapshot, false);
4006 Session::set_snapshot_name (const std::string & n)
4008 _current_snapshot_name = n;
4009 save_snapshot_name (n);
4013 Session::rename (const std::string& new_name)
4015 string legal_name = legalize_for_path (new_name);
4021 string const old_sources_root = _session_dir->sources_root();
4023 if (!_writable || (_state_of_the_state & CannotSave)) {
4024 error << _("Cannot rename read-only session.") << endmsg;
4025 return 0; // don't show "messed up" warning
4027 if (record_status() == Recording) {
4028 error << _("Cannot rename session while recording") << endmsg;
4029 return 0; // don't show "messed up" warning
4032 StateProtector stp (this);
4037 * interchange subdirectory
4041 * Backup files are left unchanged and not renamed.
4044 /* Windows requires that we close all files before attempting the
4045 * rename. This works on other platforms, but isn't necessary there.
4046 * Leave it in place for all platforms though, since it may help
4047 * catch issues that could arise if the way Source files work ever
4048 * change (since most developers are not using Windows).
4051 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4052 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4058 /* pass one: not 100% safe check that the new directory names don't
4062 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4066 /* this is a stupid hack because Glib::path_get_dirname() is
4067 * lexical-only, and so passing it /a/b/c/ gives a different
4068 * result than passing it /a/b/c ...
4071 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4072 oldstr = oldstr.substr (0, oldstr.length() - 1);
4075 string base = Glib::path_get_dirname (oldstr);
4077 newstr = Glib::build_filename (base, legal_name);
4079 cerr << "Looking for " << newstr << endl;
4081 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
4082 cerr << " exists\n";
4091 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4097 /* this is a stupid hack because Glib::path_get_dirname() is
4098 * lexical-only, and so passing it /a/b/c/ gives a different
4099 * result than passing it /a/b/c ...
4102 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4103 oldstr = oldstr.substr (0, oldstr.length() - 1);
4106 string base = Glib::path_get_dirname (oldstr);
4107 newstr = Glib::build_filename (base, legal_name);
4109 cerr << "for " << oldstr << " new dir = " << newstr << endl;
4111 cerr << "Rename " << oldstr << " => " << newstr << endl;
4112 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4113 cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4114 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4118 /* Reset path in "session dirs" */
4123 /* reset primary SessionDirectory object */
4126 (*_session_dir) = newstr;
4131 /* now rename directory below session_dir/interchange */
4133 string old_interchange_dir;
4134 string new_interchange_dir;
4136 /* use newstr here because we renamed the path
4137 * (folder/directory) that used to be oldstr to newstr above
4140 v.push_back (newstr);
4141 v.push_back (interchange_dir_name);
4142 v.push_back (Glib::path_get_basename (oldstr));
4144 old_interchange_dir = Glib::build_filename (v);
4147 v.push_back (newstr);
4148 v.push_back (interchange_dir_name);
4149 v.push_back (legal_name);
4151 new_interchange_dir = Glib::build_filename (v);
4153 cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
4155 if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
4156 cerr << string_compose (_("renaming %s as %2 failed (%3)"),
4157 old_interchange_dir, new_interchange_dir,
4160 error << string_compose (_("renaming %s as %2 failed (%3)"),
4161 old_interchange_dir, new_interchange_dir,
4170 oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
4171 newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
4173 cerr << "Rename " << oldstr << " => " << newstr << endl;
4175 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4176 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4177 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4183 oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
4185 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
4186 newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
4188 cerr << "Rename " << oldstr << " => " << newstr << endl;
4190 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4191 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4192 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4197 /* remove old name from recent sessions */
4198 remove_recent_sessions (_path);
4201 /* update file source paths */
4203 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
4204 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4206 string p = fs->path ();
4207 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
4209 SourceFactory::setup_peakfile(i->second, true);
4213 set_snapshot_name (new_name);
4218 /* save state again to get everything just right */
4220 save_state (_current_snapshot_name);
4222 /* add to recent sessions */
4224 store_recent_sessions (new_name, _path);
4230 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
4232 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
4236 if (!tree.read (xmlpath)) {
4244 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
4247 bool found_sr = false;
4248 bool found_data_format = false;
4250 if (get_session_info_from_path (tree, xmlpath)) {
4256 XMLProperty const * prop;
4257 XMLNode const * root (tree.root());
4259 if ((prop = root->property (X_("sample-rate"))) != 0) {
4260 sample_rate = atoi (prop->value());
4264 const XMLNodeList& children (root->children());
4265 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
4266 const XMLNode* child = *c;
4267 if (child->name() == "Config") {
4268 const XMLNodeList& options (child->children());
4269 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
4270 XMLNode const * option = *oc;
4271 XMLProperty const * name = option->property("name");
4277 if (name->value() == "native-file-data-format") {
4278 XMLProperty const * value = option->property ("value");
4280 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
4282 found_data_format = true;
4288 if (found_data_format) {
4293 return !(found_sr && found_data_format); // zero if they are both found
4297 Session::get_snapshot_from_instant (const std::string& session_dir)
4299 std::string instant_xml_path = Glib::build_filename (session_dir, "instant.xml");
4301 if (!Glib::file_test (instant_xml_path, Glib::FILE_TEST_EXISTS)) {
4306 if (!tree.read (instant_xml_path)) {
4310 XMLProperty const * prop;
4311 XMLNode *last_used_snapshot = tree.root()->child("LastUsedSnapshot");
4312 if (last_used_snapshot && (prop = last_used_snapshot->property ("name")) != 0) {
4313 return prop->value();
4319 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
4320 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
4323 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
4327 SourcePathMap source_path_map;
4329 boost::shared_ptr<AudioFileSource> afs;
4334 Glib::Threads::Mutex::Lock lm (source_lock);
4336 cerr << " total sources = " << sources.size();
4338 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4339 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4345 if (fs->within_session()) {
4349 if (source_path_map.find (fs->path()) != source_path_map.end()) {
4350 source_path_map[fs->path()].push_back (fs);
4352 SeveralFileSources v;
4354 source_path_map.insert (make_pair (fs->path(), v));
4360 cerr << " fsources = " << total << endl;
4362 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
4364 /* tell caller where we are */
4366 string old_path = i->first;
4368 callback (n, total, old_path);
4370 cerr << old_path << endl;
4374 switch (i->second.front()->type()) {
4375 case DataType::AUDIO:
4376 new_path = new_audio_source_path_for_embedded (old_path);
4379 case DataType::MIDI:
4380 /* XXX not implemented yet */
4384 if (new_path.empty()) {
4388 cerr << "Move " << old_path << " => " << new_path << endl;
4390 if (!copy_file (old_path, new_path)) {
4391 cerr << "failed !\n";
4395 /* make sure we stop looking in the external
4396 dir/folder. Remember, this is an all-or-nothing
4397 operations, it doesn't merge just some files.
4399 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
4401 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
4402 (*f)->set_path (new_path);
4407 save_state ("", false, false);
4413 bool accept_all_files (string const &, void *)
4419 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4421 /* 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.
4426 make_new_media_path (string old_path, string new_session_folder, string new_session_path)
4428 /* typedir is the "midifiles" or "audiofiles" etc. part of the path. */
4430 string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4432 v.push_back (new_session_folder); /* full path */
4433 v.push_back (interchange_dir_name);
4434 v.push_back (new_session_path); /* just one directory/folder */
4435 v.push_back (typedir);
4436 v.push_back (Glib::path_get_basename (old_path));
4438 return Glib::build_filename (v);
4442 Session::save_as (SaveAs& saveas)
4444 vector<string> files;
4445 string current_folder = Glib::path_get_dirname (_path);
4446 string new_folder = legalize_for_path (saveas.new_name);
4447 string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4448 int64_t total_bytes = 0;
4452 int32_t internal_file_cnt = 0;
4454 vector<string> do_not_copy_extensions;
4455 do_not_copy_extensions.push_back (statefile_suffix);
4456 do_not_copy_extensions.push_back (pending_suffix);
4457 do_not_copy_extensions.push_back (backup_suffix);
4458 do_not_copy_extensions.push_back (temp_suffix);
4459 do_not_copy_extensions.push_back (history_suffix);
4461 /* get total size */
4463 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4465 /* need to clear this because
4466 * find_files_matching_filter() is cumulative
4471 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4473 all += files.size();
4475 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4477 g_stat ((*i).c_str(), &gsb);
4478 total_bytes += gsb.st_size;
4482 /* save old values so we can switch back if we are not switching to the new session */
4484 string old_path = _path;
4485 string old_name = _name;
4486 string old_snapshot = _current_snapshot_name;
4487 string old_sd = _session_dir->root_path();
4488 vector<string> old_search_path[DataType::num_types];
4489 string old_config_search_path[DataType::num_types];
4491 old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4492 old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4493 old_config_search_path[DataType::AUDIO] = config.get_audio_search_path ();
4494 old_config_search_path[DataType::MIDI] = config.get_midi_search_path ();
4496 /* switch session directory */
4498 (*_session_dir) = to_dir;
4500 /* create new tree */
4502 if (!_session_dir->create()) {
4503 saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4508 /* copy all relevant files. Find each location in session_dirs,
4509 * and copy files from there to target.
4512 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4514 /* need to clear this because
4515 * find_files_matching_filter() is cumulative
4520 const size_t prefix_len = (*sd).path.size();
4522 /* Work just on the files within this session dir */
4524 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4526 /* add dir separator to protect against collisions with
4527 * track names (e.g. track named "audiofiles" or
4531 static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
4532 static const std::string midifile_dir_string = string (midi_dir_name) + G_DIR_SEPARATOR;
4533 static const std::string analysis_dir_string = analysis_dir() + G_DIR_SEPARATOR;
4535 /* copy all the files. Handling is different for media files
4536 than others because of the *silly* subtree we have below the interchange
4537 folder. That really was a bad idea, but I'm not fixing it as part of
4538 implementing ::save_as().
4541 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4543 std::string from = *i;
4546 string filename = Glib::path_get_basename (from);
4547 std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
4548 if (filename == ".DS_STORE") {
4553 if (from.find (audiofile_dir_string) != string::npos) {
4555 /* audio file: only copy if asked */
4557 if (saveas.include_media && saveas.copy_media) {
4559 string to = make_new_media_path (*i, to_dir, new_folder);
4561 info << "media file copying from " << from << " to " << to << endmsg;
4563 if (!copy_file (from, to)) {
4564 throw Glib::FileError (Glib::FileError::IO_ERROR,
4565 string_compose(_("\ncopying \"%1\" failed !"), from));
4569 /* we found media files inside the session folder */
4571 internal_file_cnt++;
4573 } else if (from.find (midifile_dir_string) != string::npos) {
4575 /* midi file: always copy unless
4576 * creating an empty new session
4579 if (saveas.include_media) {
4581 string to = make_new_media_path (*i, to_dir, new_folder);
4583 info << "media file copying from " << from << " to " << to << endmsg;
4585 if (!copy_file (from, to)) {
4586 throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4590 /* we found media files inside the session folder */
4592 internal_file_cnt++;
4594 } else if (from.find (analysis_dir_string) != string::npos) {
4596 /* make sure analysis dir exists in
4597 * new session folder, but we're not
4598 * copying analysis files here, see
4602 (void) g_mkdir_with_parents (analysis_dir().c_str(), 775);
4607 /* normal non-media file. Don't copy state, history, etc.
4610 bool do_copy = true;
4612 for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
4613 if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
4614 /* end of filename matches extension, do not copy file */
4620 if (!saveas.copy_media && from.find (peakfile_suffix) != string::npos) {
4621 /* don't copy peakfiles if
4622 * we're not copying media
4628 string to = Glib::build_filename (to_dir, from.substr (prefix_len));
4630 info << "attempting to make directory/folder " << to << endmsg;
4632 if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
4633 throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
4636 info << "attempting to copy " << from << " to " << to << endmsg;
4638 if (!copy_file (from, to)) {
4639 throw Glib::FileError (Glib::FileError::IO_ERROR,
4640 string_compose(_("\ncopying \"%1\" failed !"), from));
4645 /* measure file size even if we're not going to copy so that our Progress
4646 signals are correct, since we included these do-not-copy files
4647 in the computation of the total size and file count.
4651 g_stat (from.c_str(), &gsb);
4652 copied += gsb.st_size;
4655 double fraction = (double) copied / total_bytes;
4657 bool keep_going = true;
4659 if (saveas.copy_media) {
4661 /* no need or expectation of this if
4662 * media is not being copied, because
4663 * it will be fast(ish).
4666 /* tell someone "X percent, file M of N"; M is one-based */
4668 boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
4676 throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
4682 /* copy optional folders, if any */
4684 string old = plugins_dir ();
4685 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4686 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4687 copy_files (old, newdir);
4690 old = externals_dir ();
4691 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4692 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4693 copy_files (old, newdir);
4696 old = automation_dir ();
4697 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4698 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4699 copy_files (old, newdir);
4702 if (saveas.include_media) {
4704 if (saveas.copy_media) {
4705 #ifndef PLATFORM_WINDOWS
4706 /* There are problems with analysis files on
4707 * Windows, because they used a colon in their
4708 * names as late as 4.0. Colons are not legal
4709 * under Windows even if NTFS allows them.
4711 * This is a tricky problem to solve so for
4712 * just don't copy these files. They will be
4713 * regenerated as-needed anyway, subject to the
4714 * existing issue that the filenames will be
4715 * rejected by Windows, which is a separate
4716 * problem (though related).
4719 /* only needed if we are copying media, since the
4720 * analysis data refers to media data
4723 old = analysis_dir ();
4724 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4725 string newdir = Glib::build_filename (to_dir, "analysis");
4726 copy_files (old, newdir);
4728 #endif /* PLATFORM_WINDOWS */
4734 set_snapshot_name (saveas.new_name);
4735 _name = saveas.new_name;
4737 if (saveas.include_media && !saveas.copy_media) {
4739 /* reset search paths of the new session (which we're pretending to be right now) to
4740 include the original session search path, so we can still find all audio.
4743 if (internal_file_cnt) {
4744 for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
4745 ensure_search_path_includes (*s, DataType::AUDIO);
4746 cerr << "be sure to include " << *s << " for audio" << endl;
4749 /* we do not do this for MIDI because we copy
4750 all MIDI files if saveas.include_media is
4756 bool was_dirty = dirty ();
4758 save_state ("", false, false, !saveas.include_media);
4759 save_default_options ();
4761 if (saveas.copy_media && saveas.copy_external) {
4762 if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
4763 throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
4767 saveas.final_session_folder_name = _path;
4769 store_recent_sessions (_name, _path);
4771 if (!saveas.switch_to) {
4773 /* switch back to the way things were */
4777 set_snapshot_name (old_snapshot);
4779 (*_session_dir) = old_sd;
4785 if (internal_file_cnt) {
4786 /* reset these to their original values */
4787 config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
4788 config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
4793 /* prune session dirs, and update disk space statistics
4798 session_dirs.clear ();
4799 session_dirs.push_back (sp);
4800 refresh_disk_space ();
4802 /* ensure that all existing tracks reset their current capture source paths
4804 reset_write_sources (true, true);
4806 /* the copying above was based on actually discovering files, not just iterating over the sources list.
4807 But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
4810 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4811 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4817 if (fs->within_session()) {
4818 string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
4819 fs->set_path (newpath);
4824 } catch (Glib::FileError& e) {
4826 saveas.failure_message = e.what();
4828 /* recursively remove all the directories */
4830 remove_directory (to_dir);
4838 saveas.failure_message = _("unknown reason");
4840 /* recursively remove all the directories */
4842 remove_directory (to_dir);