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 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1490 _diskstreams_2X.clear ();
1492 if (version >= 3000) {
1494 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1495 error << _("Session: XML state has no route groups section") << endmsg;
1497 } else if (load_route_groups (*child, version)) {
1501 } else if (version < 3000) {
1503 if ((child = find_named_node (node, "EditGroups")) == 0) {
1504 error << _("Session: XML state has no edit groups section") << endmsg;
1506 } else if (load_route_groups (*child, version)) {
1510 if ((child = find_named_node (node, "MixGroups")) == 0) {
1511 error << _("Session: XML state has no mix groups section") << endmsg;
1513 } else if (load_route_groups (*child, version)) {
1518 if ((child = find_named_node (node, "Click")) == 0) {
1519 warning << _("Session: XML state has no click section") << endmsg;
1520 } else if (_click_io) {
1521 setup_click_state (&node);
1524 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1525 ControlProtocolManager::instance().set_state (*child, version);
1528 if ((child = find_named_node (node, "Script"))) {
1529 for (XMLNodeList::const_iterator n = child->children ().begin (); n != child->children ().end (); ++n) {
1530 if (!(*n)->is_content ()) { continue; }
1532 guchar* buf = g_base64_decode ((*n)->content ().c_str (), &size);
1534 Glib::Threads::Mutex::Lock lm (lua_lock);
1535 (*_lua_load)(std::string ((const char*)buf, size));
1536 } catch (luabridge::LuaException const& e) {
1537 cerr << "LuaException:" << e.what () << endl;
1543 update_route_record_state ();
1545 /* here beginneth the second phase ... */
1546 set_snapshot_name (_current_snapshot_name);
1548 StateReady (); /* EMIT SIGNAL */
1561 Session::load_routes (const XMLNode& node, int version)
1564 XMLNodeConstIterator niter;
1565 RouteList new_routes;
1567 nlist = node.children();
1571 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1573 boost::shared_ptr<Route> route;
1574 if (version < 3000) {
1575 route = XMLRouteFactory_2X (**niter, version);
1577 route = XMLRouteFactory (**niter, version);
1581 error << _("Session: cannot create Route from XML description.") << endmsg;
1585 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1587 new_routes.push_back (route);
1590 BootMessage (_("Tracks/busses loaded; Adding to Session"));
1592 add_routes (new_routes, false, false, false);
1594 BootMessage (_("Finished adding tracks/busses"));
1599 boost::shared_ptr<Route>
1600 Session::XMLRouteFactory (const XMLNode& node, int version)
1602 boost::shared_ptr<Route> ret;
1604 if (node.name() != "Route") {
1608 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1610 DataType type = DataType::AUDIO;
1611 XMLProperty const * prop = node.property("default-type");
1614 type = DataType (prop->value());
1617 assert (type != DataType::NIL);
1621 boost::shared_ptr<Track> track;
1623 if (type == DataType::AUDIO) {
1624 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1626 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1629 if (track->init()) {
1633 if (track->set_state (node, version)) {
1637 BOOST_MARK_TRACK (track);
1641 enum Route::Flag flags = Route::Flag(0);
1642 XMLProperty const * prop = node.property("flags");
1644 flags = Route::Flag (string_2_enum (prop->value(), flags));
1647 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1649 if (r->init () == 0 && r->set_state (node, version) == 0) {
1650 BOOST_MARK_ROUTE (r);
1658 boost::shared_ptr<Route>
1659 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1661 boost::shared_ptr<Route> ret;
1663 if (node.name() != "Route") {
1667 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1669 ds_prop = node.property (X_("diskstream"));
1672 DataType type = DataType::AUDIO;
1673 XMLProperty const * prop = node.property("default-type");
1676 type = DataType (prop->value());
1679 assert (type != DataType::NIL);
1683 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1684 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1688 if (i == _diskstreams_2X.end()) {
1689 error << _("Could not find diskstream for route") << endmsg;
1690 return boost::shared_ptr<Route> ();
1693 boost::shared_ptr<Track> track;
1695 if (type == DataType::AUDIO) {
1696 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1698 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1701 if (track->init()) {
1705 if (track->set_state (node, version)) {
1709 track->set_diskstream (*i);
1711 BOOST_MARK_TRACK (track);
1715 enum Route::Flag flags = Route::Flag(0);
1716 XMLProperty const * prop = node.property("flags");
1718 flags = Route::Flag (string_2_enum (prop->value(), flags));
1721 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1723 if (r->init () == 0 && r->set_state (node, version) == 0) {
1724 BOOST_MARK_ROUTE (r);
1733 Session::load_regions (const XMLNode& node)
1736 XMLNodeConstIterator niter;
1737 boost::shared_ptr<Region> region;
1739 nlist = node.children();
1743 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1744 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1745 error << _("Session: cannot create Region from XML description.");
1746 XMLProperty const * name = (**niter).property("name");
1749 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1760 Session::load_compounds (const XMLNode& node)
1762 XMLNodeList calist = node.children();
1763 XMLNodeConstIterator caiter;
1764 XMLProperty const * caprop;
1766 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1767 XMLNode* ca = *caiter;
1771 if ((caprop = ca->property (X_("original"))) == 0) {
1774 orig_id = caprop->value();
1776 if ((caprop = ca->property (X_("copy"))) == 0) {
1779 copy_id = caprop->value();
1781 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1782 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1784 if (!orig || !copy) {
1785 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1791 RegionFactory::add_compound_association (orig, copy);
1798 Session::load_nested_sources (const XMLNode& node)
1801 XMLNodeConstIterator niter;
1803 nlist = node.children();
1805 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1806 if ((*niter)->name() == "Source") {
1808 /* it may already exist, so don't recreate it unnecessarily
1811 XMLProperty const * prop = (*niter)->property (X_("id"));
1813 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1817 ID source_id (prop->value());
1819 if (!source_by_id (source_id)) {
1822 SourceFactory::create (*this, **niter, true);
1824 catch (failed_constructor& err) {
1825 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1832 boost::shared_ptr<Region>
1833 Session::XMLRegionFactory (const XMLNode& node, bool full)
1835 XMLProperty const * type = node.property("type");
1839 const XMLNodeList& nlist = node.children();
1841 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1842 XMLNode *child = (*niter);
1843 if (child->name() == "NestedSource") {
1844 load_nested_sources (*child);
1848 if (!type || type->value() == "audio") {
1849 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1850 } else if (type->value() == "midi") {
1851 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1854 } catch (failed_constructor& err) {
1855 return boost::shared_ptr<Region> ();
1858 return boost::shared_ptr<Region> ();
1861 boost::shared_ptr<AudioRegion>
1862 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1864 XMLProperty const * prop;
1865 boost::shared_ptr<Source> source;
1866 boost::shared_ptr<AudioSource> as;
1868 SourceList master_sources;
1869 uint32_t nchans = 1;
1872 if (node.name() != X_("Region")) {
1873 return boost::shared_ptr<AudioRegion>();
1876 if ((prop = node.property (X_("channels"))) != 0) {
1877 nchans = atoi (prop->value().c_str());
1880 if ((prop = node.property ("name")) == 0) {
1881 cerr << "no name for this region\n";
1885 if ((prop = node.property (X_("source-0"))) == 0) {
1886 if ((prop = node.property ("source")) == 0) {
1887 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1888 return boost::shared_ptr<AudioRegion>();
1892 PBD::ID s_id (prop->value());
1894 if ((source = source_by_id (s_id)) == 0) {
1895 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1896 return boost::shared_ptr<AudioRegion>();
1899 as = boost::dynamic_pointer_cast<AudioSource>(source);
1901 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1902 return boost::shared_ptr<AudioRegion>();
1905 sources.push_back (as);
1907 /* pickup other channels */
1909 for (uint32_t n=1; n < nchans; ++n) {
1910 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1911 if ((prop = node.property (buf)) != 0) {
1913 PBD::ID id2 (prop->value());
1915 if ((source = source_by_id (id2)) == 0) {
1916 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1917 return boost::shared_ptr<AudioRegion>();
1920 as = boost::dynamic_pointer_cast<AudioSource>(source);
1922 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1923 return boost::shared_ptr<AudioRegion>();
1925 sources.push_back (as);
1929 for (uint32_t n = 0; n < nchans; ++n) {
1930 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1931 if ((prop = node.property (buf)) != 0) {
1933 PBD::ID id2 (prop->value());
1935 if ((source = source_by_id (id2)) == 0) {
1936 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1937 return boost::shared_ptr<AudioRegion>();
1940 as = boost::dynamic_pointer_cast<AudioSource>(source);
1942 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1943 return boost::shared_ptr<AudioRegion>();
1945 master_sources.push_back (as);
1950 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1952 /* a final detail: this is the one and only place that we know how long missing files are */
1954 if (region->whole_file()) {
1955 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1956 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1958 sfp->set_length (region->length());
1963 if (!master_sources.empty()) {
1964 if (master_sources.size() != nchans) {
1965 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1967 region->set_master_sources (master_sources);
1975 catch (failed_constructor& err) {
1976 return boost::shared_ptr<AudioRegion>();
1980 boost::shared_ptr<MidiRegion>
1981 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1983 XMLProperty const * prop;
1984 boost::shared_ptr<Source> source;
1985 boost::shared_ptr<MidiSource> ms;
1988 if (node.name() != X_("Region")) {
1989 return boost::shared_ptr<MidiRegion>();
1992 if ((prop = node.property ("name")) == 0) {
1993 cerr << "no name for this region\n";
1997 if ((prop = node.property (X_("source-0"))) == 0) {
1998 if ((prop = node.property ("source")) == 0) {
1999 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
2000 return boost::shared_ptr<MidiRegion>();
2004 PBD::ID s_id (prop->value());
2006 if ((source = source_by_id (s_id)) == 0) {
2007 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
2008 return boost::shared_ptr<MidiRegion>();
2011 ms = boost::dynamic_pointer_cast<MidiSource>(source);
2013 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
2014 return boost::shared_ptr<MidiRegion>();
2017 sources.push_back (ms);
2020 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
2021 /* a final detail: this is the one and only place that we know how long missing files are */
2023 if (region->whole_file()) {
2024 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
2025 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
2027 sfp->set_length (region->length());
2035 catch (failed_constructor& err) {
2036 return boost::shared_ptr<MidiRegion>();
2041 Session::get_sources_as_xml ()
2044 XMLNode* node = new XMLNode (X_("Sources"));
2045 Glib::Threads::Mutex::Lock lm (source_lock);
2047 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2048 node->add_child_nocopy (i->second->get_state());
2055 Session::reset_write_sources (bool mark_write_complete, bool force)
2057 boost::shared_ptr<RouteList> rl = routes.reader();
2058 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
2059 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
2061 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
2062 tr->reset_write_sources(mark_write_complete, force);
2063 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
2069 Session::load_sources (const XMLNode& node)
2072 XMLNodeConstIterator niter;
2073 boost::shared_ptr<Source> source; /* don't need this but it stops some
2074 * versions of gcc complaining about
2075 * discarded return values.
2078 nlist = node.children();
2082 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2085 if ((source = XMLSourceFactory (**niter)) == 0) {
2086 error << _("Session: cannot create Source from XML description.") << endmsg;
2089 } catch (MissingSource& err) {
2093 if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
2094 error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
2095 PROGRAM_NAME) << endmsg;
2099 if (!no_questions_about_missing_files) {
2100 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
2105 switch (user_choice) {
2107 /* user added a new search location, so try again */
2112 /* user asked to quit the entire session load
2117 no_questions_about_missing_files = true;
2121 no_questions_about_missing_files = true;
2128 case DataType::AUDIO:
2129 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
2132 case DataType::MIDI:
2133 /* The MIDI file is actually missing so
2134 * just create a new one in the same
2135 * location. Do not announce its
2139 if (!Glib::path_is_absolute (err.path)) {
2140 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
2142 /* this should be an unrecoverable error: we would be creating a MIDI file outside
2147 /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
2148 source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
2149 /* reset ID to match the missing one */
2150 source->set_id (**niter);
2151 /* Now we can announce it */
2152 SourceFactory::SourceCreated (source);
2163 boost::shared_ptr<Source>
2164 Session::XMLSourceFactory (const XMLNode& node)
2166 if (node.name() != "Source") {
2167 return boost::shared_ptr<Source>();
2171 /* note: do peak building in another thread when loading session state */
2172 return SourceFactory::create (*this, node, true);
2175 catch (failed_constructor& err) {
2176 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
2177 return boost::shared_ptr<Source>();
2182 Session::save_template (string template_name, bool replace_existing)
2184 if ((_state_of_the_state & CannotSave) || template_name.empty ()) {
2188 bool absolute_path = Glib::path_is_absolute (template_name);
2190 /* directory to put the template in */
2191 std::string template_dir_path;
2193 if (!absolute_path) {
2194 std::string user_template_dir(user_template_directory());
2196 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2197 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2198 user_template_dir, g_strerror (errno)) << endmsg;
2202 template_dir_path = Glib::build_filename (user_template_dir, template_name);
2204 template_dir_path = template_name;
2207 if (!ARDOUR::Profile->get_trx()) {
2208 if (!replace_existing && Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2209 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2210 template_dir_path) << endmsg;
2214 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2215 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2216 template_dir_path, g_strerror (errno)) << endmsg;
2222 std::string template_file_path;
2224 if (ARDOUR::Profile->get_trx()) {
2225 template_file_path = template_name;
2227 if (absolute_path) {
2228 template_file_path = Glib::build_filename (template_dir_path, Glib::path_get_basename (template_dir_path) + template_suffix);
2230 template_file_path = Glib::build_filename (template_dir_path, template_name + template_suffix);
2234 SessionSaveUnderway (); /* EMIT SIGNAL */
2239 PBD::Unwinder<std::string> uw (_template_state_dir, template_dir_path);
2240 tree.set_root (&get_template());
2243 if (!tree.write (template_file_path)) {
2244 error << _("template not saved") << endmsg;
2248 store_recent_templates (template_file_path);
2254 Session::refresh_disk_space ()
2256 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2258 Glib::Threads::Mutex::Lock lm (space_lock);
2260 /* get freespace on every FS that is part of the session path */
2262 _total_free_4k_blocks = 0;
2263 _total_free_4k_blocks_uncertain = false;
2265 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2267 struct statfs statfsbuf;
2268 statfs (i->path.c_str(), &statfsbuf);
2270 double const scale = statfsbuf.f_bsize / 4096.0;
2272 /* See if this filesystem is read-only */
2273 struct statvfs statvfsbuf;
2274 statvfs (i->path.c_str(), &statvfsbuf);
2276 /* f_bavail can be 0 if it is undefined for whatever
2277 filesystem we are looking at; Samba shares mounted
2278 via GVFS are an example of this.
2280 if (statfsbuf.f_bavail == 0) {
2281 /* block count unknown */
2283 i->blocks_unknown = true;
2284 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2285 /* read-only filesystem */
2287 i->blocks_unknown = false;
2289 /* read/write filesystem with known space */
2290 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2291 i->blocks_unknown = false;
2294 _total_free_4k_blocks += i->blocks;
2295 if (i->blocks_unknown) {
2296 _total_free_4k_blocks_uncertain = true;
2299 #elif defined PLATFORM_WINDOWS
2300 vector<string> scanned_volumes;
2301 vector<string>::iterator j;
2302 vector<space_and_path>::iterator i;
2303 DWORD nSectorsPerCluster, nBytesPerSector,
2304 nFreeClusters, nTotalClusters;
2308 _total_free_4k_blocks = 0;
2310 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2311 strncpy (disk_drive, (*i).path.c_str(), 3);
2315 volume_found = false;
2316 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2318 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2319 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2320 i->blocks = (uint32_t)(nFreeBytes / 4096);
2322 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2323 if (0 == j->compare(disk_drive)) {
2324 volume_found = true;
2329 if (!volume_found) {
2330 scanned_volumes.push_back(disk_drive);
2331 _total_free_4k_blocks += i->blocks;
2336 if (0 == _total_free_4k_blocks) {
2337 strncpy (disk_drive, path().c_str(), 3);
2340 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2342 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2343 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2344 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2351 Session::get_best_session_directory_for_new_audio ()
2353 vector<space_and_path>::iterator i;
2354 string result = _session_dir->root_path();
2356 /* handle common case without system calls */
2358 if (session_dirs.size() == 1) {
2362 /* OK, here's the algorithm we're following here:
2364 We want to select which directory to use for
2365 the next file source to be created. Ideally,
2366 we'd like to use a round-robin process so as to
2367 get maximum performance benefits from splitting
2368 the files across multiple disks.
2370 However, in situations without much diskspace, an
2371 RR approach may end up filling up a filesystem
2372 with new files while others still have space.
2373 Its therefore important to pay some attention to
2374 the freespace in the filesystem holding each
2375 directory as well. However, if we did that by
2376 itself, we'd keep creating new files in the file
2377 system with the most space until it was as full
2378 as all others, thus negating any performance
2379 benefits of this RAID-1 like approach.
2381 So, we use a user-configurable space threshold. If
2382 there are at least 2 filesystems with more than this
2383 much space available, we use RR selection between them.
2384 If not, then we pick the filesystem with the most space.
2386 This gets a good balance between the two
2390 refresh_disk_space ();
2392 int free_enough = 0;
2394 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2395 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2400 if (free_enough >= 2) {
2401 /* use RR selection process, ensuring that the one
2405 i = last_rr_session_dir;
2408 if (++i == session_dirs.end()) {
2409 i = session_dirs.begin();
2412 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2413 SessionDirectory sdir(i->path);
2414 if (sdir.create ()) {
2416 last_rr_session_dir = i;
2421 } while (i != last_rr_session_dir);
2425 /* pick FS with the most freespace (and that
2426 seems to actually work ...)
2429 vector<space_and_path> sorted;
2430 space_and_path_ascending_cmp cmp;
2432 sorted = session_dirs;
2433 sort (sorted.begin(), sorted.end(), cmp);
2435 for (i = sorted.begin(); i != sorted.end(); ++i) {
2436 SessionDirectory sdir(i->path);
2437 if (sdir.create ()) {
2439 last_rr_session_dir = i;
2449 Session::automation_dir () const
2451 return Glib::build_filename (_path, automation_dir_name);
2455 Session::analysis_dir () const
2457 return Glib::build_filename (_path, analysis_dir_name);
2461 Session::plugins_dir () const
2463 return Glib::build_filename (_path, plugins_dir_name);
2467 Session::externals_dir () const
2469 return Glib::build_filename (_path, externals_dir_name);
2473 Session::load_bundles (XMLNode const & node)
2475 XMLNodeList nlist = node.children();
2476 XMLNodeConstIterator niter;
2480 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2481 if ((*niter)->name() == "InputBundle") {
2482 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2483 } else if ((*niter)->name() == "OutputBundle") {
2484 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2486 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2495 Session::load_route_groups (const XMLNode& node, int version)
2497 XMLNodeList nlist = node.children();
2498 XMLNodeConstIterator niter;
2502 if (version >= 3000) {
2504 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2505 if ((*niter)->name() == "RouteGroup") {
2506 RouteGroup* rg = new RouteGroup (*this, "");
2507 add_route_group (rg);
2508 rg->set_state (**niter, version);
2512 } else if (version < 3000) {
2514 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2515 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2516 RouteGroup* rg = new RouteGroup (*this, "");
2517 add_route_group (rg);
2518 rg->set_state (**niter, version);
2527 state_file_filter (const string &str, void* /*arg*/)
2529 return (str.length() > strlen(statefile_suffix) &&
2530 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2534 remove_end(string state)
2536 string statename(state);
2538 string::size_type start,end;
2539 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2540 statename = statename.substr (start+1);
2543 if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2544 end = statename.length();
2547 return string(statename.substr (0, end));
2551 Session::possible_states (string path)
2553 vector<string> states;
2554 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2556 transform(states.begin(), states.end(), states.begin(), remove_end);
2558 sort (states.begin(), states.end());
2564 Session::possible_states () const
2566 return possible_states(_path);
2570 Session::add_route_group (RouteGroup* g)
2572 _route_groups.push_back (g);
2573 route_group_added (g); /* EMIT SIGNAL */
2575 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2576 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2577 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2583 Session::remove_route_group (RouteGroup& rg)
2585 list<RouteGroup*>::iterator i;
2587 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2588 _route_groups.erase (i);
2591 route_group_removed (); /* EMIT SIGNAL */
2595 /** Set a new order for our route groups, without adding or removing any.
2596 * @param groups Route group list in the new order.
2599 Session::reorder_route_groups (list<RouteGroup*> groups)
2601 _route_groups = groups;
2603 route_groups_reordered (); /* EMIT SIGNAL */
2609 Session::route_group_by_name (string name)
2611 list<RouteGroup *>::iterator i;
2613 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2614 if ((*i)->name() == name) {
2622 Session::all_route_group() const
2624 return *_all_route_group;
2628 Session::add_commands (vector<Command*> const & cmds)
2630 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2636 Session::add_command (Command* const cmd)
2638 assert (_current_trans);
2639 DEBUG_UNDO_HISTORY (
2640 string_compose ("Current Undo Transaction %1, adding command: %2",
2641 _current_trans->name (),
2643 _current_trans->add_command (cmd);
2646 PBD::StatefulDiffCommand*
2647 Session::add_stateful_diff_command (boost::shared_ptr<PBD::StatefulDestructible> sfd)
2649 PBD::StatefulDiffCommand* cmd = new PBD::StatefulDiffCommand (sfd);
2655 Session::begin_reversible_command (const string& name)
2657 begin_reversible_command (g_quark_from_string (name.c_str ()));
2660 /** Begin a reversible command using a GQuark to identify it.
2661 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2662 * but there must be as many begin...()s as there are commit...()s.
2665 Session::begin_reversible_command (GQuark q)
2667 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2668 to hold all the commands that are committed. This keeps the order of
2669 commands correct in the history.
2672 if (_current_trans == 0) {
2673 DEBUG_UNDO_HISTORY (string_compose (
2674 "Begin Reversible Command, new transaction: %1", g_quark_to_string (q)));
2676 /* start a new transaction */
2677 assert (_current_trans_quarks.empty ());
2678 _current_trans = new UndoTransaction();
2679 _current_trans->set_name (g_quark_to_string (q));
2681 DEBUG_UNDO_HISTORY (
2682 string_compose ("Begin Reversible Command, current transaction: %1",
2683 _current_trans->name ()));
2686 _current_trans_quarks.push_front (q);
2690 Session::abort_reversible_command ()
2692 if (_current_trans != 0) {
2693 DEBUG_UNDO_HISTORY (
2694 string_compose ("Abort Reversible Command: %1", _current_trans->name ()));
2695 _current_trans->clear();
2696 delete _current_trans;
2698 _current_trans_quarks.clear();
2703 Session::commit_reversible_command (Command *cmd)
2705 assert (_current_trans);
2706 assert (!_current_trans_quarks.empty ());
2711 DEBUG_UNDO_HISTORY (
2712 string_compose ("Current Undo Transaction %1, adding command: %2",
2713 _current_trans->name (),
2715 _current_trans->add_command (cmd);
2718 DEBUG_UNDO_HISTORY (
2719 string_compose ("Commit Reversible Command, current transaction: %1",
2720 _current_trans->name ()));
2722 _current_trans_quarks.pop_front ();
2724 if (!_current_trans_quarks.empty ()) {
2725 DEBUG_UNDO_HISTORY (
2726 string_compose ("Commit Reversible Command, transaction is not "
2727 "top-level, current transaction: %1",
2728 _current_trans->name ()));
2729 /* the transaction we're committing is not the top-level one */
2733 if (_current_trans->empty()) {
2734 /* no commands were added to the transaction, so just get rid of it */
2735 DEBUG_UNDO_HISTORY (
2736 string_compose ("Commit Reversible Command, No commands were "
2737 "added to current transaction: %1",
2738 _current_trans->name ()));
2739 delete _current_trans;
2744 gettimeofday (&now, 0);
2745 _current_trans->set_timestamp (now);
2747 _history.add (_current_trans);
2752 accept_all_audio_files (const string& path, void* /*arg*/)
2754 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2758 if (!AudioFileSource::safe_audio_file_extension (path)) {
2766 accept_all_midi_files (const string& path, void* /*arg*/)
2768 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2772 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2773 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2774 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2778 accept_all_state_files (const string& path, void* /*arg*/)
2780 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2784 std::string const statefile_ext (statefile_suffix);
2785 if (path.length() >= statefile_ext.length()) {
2786 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2793 Session::find_all_sources (string path, set<string>& result)
2798 if (!tree.read (path)) {
2802 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2807 XMLNodeConstIterator niter;
2809 nlist = node->children();
2813 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2815 XMLProperty const * prop;
2817 if ((prop = (*niter)->property (X_("type"))) == 0) {
2821 DataType type (prop->value());
2823 if ((prop = (*niter)->property (X_("name"))) == 0) {
2827 if (Glib::path_is_absolute (prop->value())) {
2828 /* external file, ignore */
2836 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2837 result.insert (found_path);
2845 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2847 vector<string> state_files;
2849 string this_snapshot_path;
2855 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2856 ripped = ripped.substr (0, ripped.length() - 1);
2859 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2861 if (state_files.empty()) {
2866 this_snapshot_path = _path;
2867 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2868 this_snapshot_path += statefile_suffix;
2870 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2872 if (exclude_this_snapshot && *i == this_snapshot_path) {
2876 if (find_all_sources (*i, result) < 0) {
2884 struct RegionCounter {
2885 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2886 AudioSourceList::iterator iter;
2887 boost::shared_ptr<Region> region;
2890 RegionCounter() : count (0) {}
2894 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2896 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2897 return r.get_value_or (1);
2901 Session::cleanup_regions ()
2903 bool removed = false;
2904 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2906 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2908 uint32_t used = playlists->region_use_count (i->second);
2910 if (used == 0 && !i->second->automatic ()) {
2911 boost::weak_ptr<Region> w = i->second;
2914 RegionFactory::map_remove (w);
2921 // re-check to remove parent references of compound regions
2922 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2923 if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2927 assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2928 if (0 == playlists->region_use_count (i->second)) {
2929 boost::weak_ptr<Region> w = i->second;
2931 RegionFactory::map_remove (w);
2938 /* dump the history list */
2945 Session::can_cleanup_peakfiles () const
2947 if (deletion_in_progress()) {
2950 if (!_writable || (_state_of_the_state & CannotSave)) {
2951 warning << _("Cannot cleanup peak-files for read-only session.") << endmsg;
2954 if (record_status() == Recording) {
2955 error << _("Cannot cleanup peak-files while recording") << endmsg;
2962 Session::cleanup_peakfiles ()
2964 Glib::Threads::Mutex::Lock lm (peak_cleanup_lock, Glib::Threads::TRY_LOCK);
2969 assert (can_cleanup_peakfiles ());
2970 assert (!peaks_cleanup_in_progres());
2972 _state_of_the_state = StateOfTheState (_state_of_the_state | PeakCleanup);
2974 int timeout = 5000; // 5 seconds
2975 while (!SourceFactory::files_with_peaks.empty()) {
2976 Glib::usleep (1000);
2977 if (--timeout < 0) {
2978 warning << _("Timeout waiting for peak-file creation to terminate before cleanup, please try again later.") << endmsg;
2979 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
2984 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2985 boost::shared_ptr<AudioSource> as;
2986 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
2987 as->close_peakfile();
2991 PBD::clear_directory (session_directory().peak_path());
2993 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
2995 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2996 boost::shared_ptr<AudioSource> as;
2997 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
2998 SourceFactory::setup_peakfile(as, true);
3005 Session::cleanup_sources (CleanupReport& rep)
3007 // FIXME: needs adaptation to midi
3009 vector<boost::shared_ptr<Source> > dead_sources;
3012 vector<string> candidates;
3013 vector<string> unused;
3014 set<string> all_sources;
3023 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
3025 /* this is mostly for windows which doesn't allow file
3026 * renaming if the file is in use. But we don't special
3027 * case it because we need to know if this causes
3028 * problems, and the easiest way to notice that is to
3029 * keep it in place for all platforms.
3032 request_stop (false);
3034 _butler->wait_until_finished ();
3036 /* consider deleting all unused playlists */
3038 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
3043 /* sync the "all regions" property of each playlist with its current state
3046 playlists->sync_all_regions_with_regions ();
3048 /* find all un-used sources */
3053 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3055 SourceMap::iterator tmp;
3060 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
3064 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
3065 dead_sources.push_back (i->second);
3066 i->second->drop_references ();
3072 /* build a list of all the possible audio directories for the session */
3074 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3075 SessionDirectory sdir ((*i).path);
3076 asp += sdir.sound_path();
3078 audio_path += asp.to_string();
3081 /* build a list of all the possible midi directories for the session */
3083 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3084 SessionDirectory sdir ((*i).path);
3085 msp += sdir.midi_path();
3087 midi_path += msp.to_string();
3089 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
3090 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
3092 /* find all sources, but don't use this snapshot because the
3093 state file on disk still references sources we may have already
3097 find_all_sources_across_snapshots (all_sources, true);
3099 /* add our current source list
3102 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3103 boost::shared_ptr<FileSource> fs;
3104 SourceMap::iterator tmp = i;
3107 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
3109 /* this is mostly for windows which doesn't allow file
3110 * renaming if the file is in use. But we don't special
3111 * case it because we need to know if this causes
3112 * problems, and the easiest way to notice that is to
3113 * keep it in place for all platforms.
3118 if (!fs->is_stub()) {
3120 if (playlists->source_use_count (fs) != 0) {
3121 all_sources.insert (fs->path());
3124 /* we might not remove this source from disk, because it may be used
3125 by other snapshots, but its not being used in this version
3126 so lets get rid of it now, along with any representative regions
3130 RegionFactory::remove_regions_using_source (i->second);
3132 // also remove source from all_sources
3134 for (set<string>::iterator j = all_sources.begin(); j != all_sources.end(); ++j) {
3135 spath = Glib::path_get_basename (*j);
3136 if (spath == i->second->name()) {
3137 all_sources.erase (j);
3150 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
3155 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
3157 tmppath1 = canonical_path (spath);
3158 tmppath2 = canonical_path ((*i));
3160 if (tmppath1 == tmppath2) {
3167 unused.push_back (spath);
3171 /* now try to move all unused files into the "dead" directory(ies) */
3173 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
3178 /* don't move the file across filesystems, just
3179 stick it in the `dead_dir_name' directory
3180 on whichever filesystem it was already on.
3183 if ((*x).find ("/sounds/") != string::npos) {
3185 /* old school, go up 1 level */
3187 newpath = Glib::path_get_dirname (*x); // "sounds"
3188 newpath = Glib::path_get_dirname (newpath); // "session-name"
3192 /* new school, go up 4 levels */
3194 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
3195 newpath = Glib::path_get_dirname (newpath); // "session-name"
3196 newpath = Glib::path_get_dirname (newpath); // "interchange"
3197 newpath = Glib::path_get_dirname (newpath); // "session-dir"
3200 newpath = Glib::build_filename (newpath, dead_dir_name);
3202 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
3203 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
3207 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
3209 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
3211 /* the new path already exists, try versioning */
3213 char buf[PATH_MAX+1];
3217 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3220 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
3221 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3225 if (version == 999) {
3226 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3230 newpath = newpath_v;
3235 /* it doesn't exist, or we can't read it or something */
3239 g_stat ((*x).c_str(), &statbuf);
3241 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3242 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
3243 (*x), newpath, strerror (errno))
3248 /* see if there an easy to find peakfile for this file, and remove it.
3251 string base = Glib::path_get_basename (*x);
3252 base += "%A"; /* this is what we add for the channel suffix of all native files,
3253 or for the first channel of embedded files. it will miss
3254 some peakfiles for other channels
3256 string peakpath = construct_peak_filepath (base);
3258 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
3259 if (::g_unlink (peakpath.c_str()) != 0) {
3260 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3261 peakpath, _path, strerror (errno))
3263 /* try to back out */
3264 ::rename (newpath.c_str(), _path.c_str());
3269 rep.paths.push_back (*x);
3270 rep.space += statbuf.st_size;
3273 /* dump the history list */
3277 /* save state so we don't end up a session file
3278 referring to non-existent sources.
3285 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3291 Session::cleanup_trash_sources (CleanupReport& rep)
3293 // FIXME: needs adaptation for MIDI
3295 vector<space_and_path>::iterator i;
3301 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3303 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
3305 clear_directory (dead_dir, &rep.space, &rep.paths);
3312 Session::set_dirty ()
3314 /* never mark session dirty during loading */
3316 if (_state_of_the_state & Loading) {
3320 bool was_dirty = dirty();
3322 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3326 DirtyChanged(); /* EMIT SIGNAL */
3332 Session::set_clean ()
3334 bool was_dirty = dirty();
3336 _state_of_the_state = Clean;
3340 DirtyChanged(); /* EMIT SIGNAL */
3345 Session::set_deletion_in_progress ()
3347 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3351 Session::clear_deletion_in_progress ()
3353 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3357 Session::add_controllable (boost::shared_ptr<Controllable> c)
3359 /* this adds a controllable to the list managed by the Session.
3360 this is a subset of those managed by the Controllable class
3361 itself, and represents the only ones whose state will be saved
3362 as part of the session.
3365 Glib::Threads::Mutex::Lock lm (controllables_lock);
3366 controllables.insert (c);
3369 struct null_deleter { void operator()(void const *) const {} };
3372 Session::remove_controllable (Controllable* c)
3374 if (_state_of_the_state & Deletion) {
3378 Glib::Threads::Mutex::Lock lm (controllables_lock);
3380 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3382 if (x != controllables.end()) {
3383 controllables.erase (x);
3387 boost::shared_ptr<Controllable>
3388 Session::controllable_by_id (const PBD::ID& id)
3390 Glib::Threads::Mutex::Lock lm (controllables_lock);
3392 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3393 if ((*i)->id() == id) {
3398 return boost::shared_ptr<Controllable>();
3401 boost::shared_ptr<Controllable>
3402 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3404 boost::shared_ptr<Controllable> c;
3405 boost::shared_ptr<Route> r;
3407 switch (desc.top_level_type()) {
3408 case ControllableDescriptor::NamedRoute:
3410 std::string str = desc.top_level_name();
3411 if (str == "Master" || str == "master") {
3413 } else if (str == "control" || str == "listen") {
3416 r = route_by_name (desc.top_level_name());
3421 case ControllableDescriptor::RemoteControlID:
3422 r = route_by_remote_id (desc.rid());
3425 case ControllableDescriptor::SelectionCount:
3426 r = route_by_selected_count (desc.selection_id());
3434 switch (desc.subtype()) {
3435 case ControllableDescriptor::Gain:
3436 c = r->gain_control ();
3439 case ControllableDescriptor::Trim:
3440 c = r->trim()->gain_control ();
3443 case ControllableDescriptor::Solo:
3444 c = r->solo_control();
3447 case ControllableDescriptor::Mute:
3448 c = r->mute_control();
3451 case ControllableDescriptor::Recenable:
3453 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3456 c = t->rec_enable_control ();
3461 case ControllableDescriptor::PanDirection:
3462 c = r->pan_azimuth_control();
3465 case ControllableDescriptor::PanWidth:
3466 c = r->pan_width_control();
3469 case ControllableDescriptor::PanElevation:
3470 c = r->pan_elevation_control();
3473 case ControllableDescriptor::Balance:
3474 /* XXX simple pan control */
3477 case ControllableDescriptor::PluginParameter:
3479 uint32_t plugin = desc.target (0);
3480 uint32_t parameter_index = desc.target (1);
3482 /* revert to zero based counting */
3488 if (parameter_index > 0) {
3492 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3495 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3496 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3501 case ControllableDescriptor::SendGain: {
3502 uint32_t send = desc.target (0);
3506 c = r->send_level_controllable (send);
3511 /* relax and return a null pointer */
3519 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3522 Stateful::add_instant_xml (node, _path);
3525 if (write_to_config) {
3526 Config->add_instant_xml (node);
3531 Session::instant_xml (const string& node_name)
3533 return Stateful::instant_xml (node_name, _path);
3537 Session::save_history (string snapshot_name)
3545 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3546 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3550 if (snapshot_name.empty()) {
3551 snapshot_name = _current_snapshot_name;
3554 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3555 const string backup_filename = history_filename + backup_suffix;
3556 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3557 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3559 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3560 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3561 error << _("could not backup old history file, current history not saved") << endmsg;
3566 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3568 if (!tree.write (xml_path))
3570 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3572 if (g_remove (xml_path.c_str()) != 0) {
3573 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3574 xml_path, g_strerror (errno)) << endmsg;
3576 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3577 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3578 backup_path, g_strerror (errno)) << endmsg;
3588 Session::restore_history (string snapshot_name)
3592 if (snapshot_name.empty()) {
3593 snapshot_name = _current_snapshot_name;
3596 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3597 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3599 info << "Loading history from " << xml_path << endmsg;
3601 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3602 info << string_compose (_("%1: no history file \"%2\" for this session."),
3603 _name, xml_path) << endmsg;
3607 if (!tree.read (xml_path)) {
3608 error << string_compose (_("Could not understand session history file \"%1\""),
3609 xml_path) << endmsg;
3616 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3619 UndoTransaction* ut = new UndoTransaction ();
3622 ut->set_name(t->property("name")->value());
3623 stringstream ss(t->property("tv-sec")->value());
3625 ss.str(t->property("tv-usec")->value());
3627 ut->set_timestamp(tv);
3629 for (XMLNodeConstIterator child_it = t->children().begin();
3630 child_it != t->children().end(); child_it++)
3632 XMLNode *n = *child_it;
3635 if (n->name() == "MementoCommand" ||
3636 n->name() == "MementoUndoCommand" ||
3637 n->name() == "MementoRedoCommand") {
3639 if ((c = memento_command_factory(n))) {
3643 } else if (n->name() == "NoteDiffCommand") {
3644 PBD::ID id (n->property("midi-source")->value());
3645 boost::shared_ptr<MidiSource> midi_source =
3646 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3648 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3650 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3653 } else if (n->name() == "SysExDiffCommand") {
3655 PBD::ID id (n->property("midi-source")->value());
3656 boost::shared_ptr<MidiSource> midi_source =
3657 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3659 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3661 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3664 } else if (n->name() == "PatchChangeDiffCommand") {
3666 PBD::ID id (n->property("midi-source")->value());
3667 boost::shared_ptr<MidiSource> midi_source =
3668 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3670 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3672 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3675 } else if (n->name() == "StatefulDiffCommand") {
3676 if ((c = stateful_diff_command_factory (n))) {
3677 ut->add_command (c);
3680 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3691 Session::config_changed (std::string p, bool ours)
3697 if (p == "seamless-loop") {
3699 } else if (p == "rf-speed") {
3701 } else if (p == "auto-loop") {
3703 } else if (p == "auto-input") {
3705 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3706 /* auto-input only makes a difference if we're rolling */
3707 set_track_monitor_input_status (!config.get_auto_input());
3710 } else if (p == "punch-in") {
3714 if ((location = _locations->auto_punch_location()) != 0) {
3716 if (config.get_punch_in ()) {
3717 replace_event (SessionEvent::PunchIn, location->start());
3719 remove_event (location->start(), SessionEvent::PunchIn);
3723 } else if (p == "punch-out") {
3727 if ((location = _locations->auto_punch_location()) != 0) {
3729 if (config.get_punch_out()) {
3730 replace_event (SessionEvent::PunchOut, location->end());
3732 clear_events (SessionEvent::PunchOut);
3736 } else if (p == "edit-mode") {
3738 Glib::Threads::Mutex::Lock lm (playlists->lock);
3740 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3741 (*i)->set_edit_mode (Config->get_edit_mode ());
3744 } else if (p == "use-video-sync") {
3746 waiting_for_sync_offset = config.get_use_video_sync();
3748 } else if (p == "mmc-control") {
3750 //poke_midi_thread ();
3752 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3754 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3756 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3758 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3760 } else if (p == "midi-control") {
3762 //poke_midi_thread ();
3764 } else if (p == "raid-path") {
3766 setup_raid_path (config.get_raid_path());
3768 } else if (p == "timecode-format") {
3772 } else if (p == "video-pullup") {
3776 } else if (p == "seamless-loop") {
3778 if (play_loop && transport_rolling()) {
3779 // to reset diskstreams etc
3780 request_play_loop (true);
3783 } else if (p == "rf-speed") {
3785 cumulative_rf_motion = 0;
3788 } else if (p == "click-sound") {
3790 setup_click_sounds (1);
3792 } else if (p == "click-emphasis-sound") {
3794 setup_click_sounds (-1);
3796 } else if (p == "clicking") {
3798 if (Config->get_clicking()) {
3799 if (_click_io && click_data) { // don't require emphasis data
3806 } else if (p == "click-gain") {
3809 _click_gain->gain_control()->set_value (Config->get_click_gain(), Controllable::NoGroup);
3812 } else if (p == "send-mtc") {
3814 if (Config->get_send_mtc ()) {
3815 /* mark us ready to send */
3816 next_quarter_frame_to_send = 0;
3819 } else if (p == "send-mmc") {
3821 _mmc->enable_send (Config->get_send_mmc ());
3823 } else if (p == "midi-feedback") {
3825 session_midi_feedback = Config->get_midi_feedback();
3827 } else if (p == "jack-time-master") {
3829 engine().reset_timebase ();
3831 } else if (p == "native-file-header-format") {
3833 if (!first_file_header_format_reset) {
3834 reset_native_file_format ();
3837 first_file_header_format_reset = false;
3839 } else if (p == "native-file-data-format") {
3841 if (!first_file_data_format_reset) {
3842 reset_native_file_format ();
3845 first_file_data_format_reset = false;
3847 } else if (p == "external-sync") {
3848 if (!config.get_external_sync()) {
3849 drop_sync_source ();
3851 switch_to_sync_source (Config->get_sync_source());
3853 } else if (p == "denormal-model") {
3855 } else if (p == "history-depth") {
3856 set_history_depth (Config->get_history_depth());
3857 } else if (p == "remote-model") {
3858 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3861 } else if (p == "initial-program-change") {
3863 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3866 buf[0] = MIDI::program; // channel zero by default
3867 buf[1] = (Config->get_initial_program_change() & 0x7f);
3869 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3871 } else if (p == "solo-mute-override") {
3872 // catch_up_on_solo_mute_override ();
3873 } else if (p == "listen-position" || p == "pfl-position") {
3874 listen_position_changed ();
3875 } else if (p == "solo-control-is-listen-control") {
3876 solo_control_mode_changed ();
3877 } else if (p == "solo-mute-gain") {
3878 _solo_cut_control->Changed();
3879 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3880 last_timecode_valid = false;
3881 } else if (p == "playback-buffer-seconds") {
3882 AudioSource::allocate_working_buffers (frame_rate());
3883 } else if (p == "ltc-source-port") {
3884 reconnect_ltc_input ();
3885 } else if (p == "ltc-sink-port") {
3886 reconnect_ltc_output ();
3887 } else if (p == "timecode-generator-offset") {
3888 ltc_tx_parse_offset();
3889 } else if (p == "auto-return-target-list") {
3890 follow_playhead_priority ();
3897 Session::set_history_depth (uint32_t d)
3899 _history.set_depth (d);
3903 Session::load_diskstreams_2X (XMLNode const & node, int)
3906 XMLNodeConstIterator citer;
3908 clist = node.children();
3910 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3913 /* diskstreams added automatically by DiskstreamCreated handler */
3914 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3915 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3916 _diskstreams_2X.push_back (dsp);
3918 error << _("Session: unknown diskstream type in XML") << endmsg;
3922 catch (failed_constructor& err) {
3923 error << _("Session: could not load diskstream via XML state") << endmsg;
3931 /** Connect things to the MMC object */
3933 Session::setup_midi_machine_control ()
3935 _mmc = new MIDI::MachineControl;
3937 boost::shared_ptr<AsyncMIDIPort> async_in = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_input_port());
3938 boost::shared_ptr<AsyncMIDIPort> async_out = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_output_port());
3940 if (!async_out || !async_out) {
3944 /* XXXX argh, passing raw pointers back into libmidi++ */
3946 MIDI::Port* mmc_in = async_in.get();
3947 MIDI::Port* mmc_out = async_out.get();
3949 _mmc->set_ports (mmc_in, mmc_out);
3951 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3952 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3953 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3954 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3955 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3956 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3957 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3958 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3959 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3960 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3961 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3962 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3963 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3965 /* also handle MIDI SPP because its so common */
3967 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3968 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3969 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3972 boost::shared_ptr<Controllable>
3973 Session::solo_cut_control() const
3975 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3976 controls in Ardour that currently get presented to the user in the GUI that require
3977 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3979 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3980 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3984 return _solo_cut_control;
3988 Session::save_snapshot_name (const std::string & n)
3990 /* assure Stateful::_instant_xml is loaded
3991 * add_instant_xml() only adds to existing data and defaults
3992 * to use an empty Tree otherwise
3994 instant_xml ("LastUsedSnapshot");
3996 XMLNode* last_used_snapshot = new XMLNode ("LastUsedSnapshot");
3997 last_used_snapshot->add_property ("name", string(n));
3998 add_instant_xml (*last_used_snapshot, false);
4002 Session::set_snapshot_name (const std::string & n)
4004 _current_snapshot_name = n;
4005 save_snapshot_name (n);
4009 Session::rename (const std::string& new_name)
4011 string legal_name = legalize_for_path (new_name);
4017 string const old_sources_root = _session_dir->sources_root();
4019 if (!_writable || (_state_of_the_state & CannotSave)) {
4020 error << _("Cannot rename read-only session.") << endmsg;
4021 return 0; // don't show "messed up" warning
4023 if (record_status() == Recording) {
4024 error << _("Cannot rename session while recording") << endmsg;
4025 return 0; // don't show "messed up" warning
4028 StateProtector stp (this);
4033 * interchange subdirectory
4037 * Backup files are left unchanged and not renamed.
4040 /* Windows requires that we close all files before attempting the
4041 * rename. This works on other platforms, but isn't necessary there.
4042 * Leave it in place for all platforms though, since it may help
4043 * catch issues that could arise if the way Source files work ever
4044 * change (since most developers are not using Windows).
4047 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4048 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4054 /* pass one: not 100% safe check that the new directory names don't
4058 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4062 /* this is a stupid hack because Glib::path_get_dirname() is
4063 * lexical-only, and so passing it /a/b/c/ gives a different
4064 * result than passing it /a/b/c ...
4067 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4068 oldstr = oldstr.substr (0, oldstr.length() - 1);
4071 string base = Glib::path_get_dirname (oldstr);
4073 newstr = Glib::build_filename (base, legal_name);
4075 cerr << "Looking for " << newstr << endl;
4077 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
4078 cerr << " exists\n";
4087 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4093 /* this is a stupid hack because Glib::path_get_dirname() is
4094 * lexical-only, and so passing it /a/b/c/ gives a different
4095 * result than passing it /a/b/c ...
4098 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4099 oldstr = oldstr.substr (0, oldstr.length() - 1);
4102 string base = Glib::path_get_dirname (oldstr);
4103 newstr = Glib::build_filename (base, legal_name);
4105 cerr << "for " << oldstr << " new dir = " << newstr << endl;
4107 cerr << "Rename " << oldstr << " => " << newstr << endl;
4108 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4109 cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4110 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4114 /* Reset path in "session dirs" */
4119 /* reset primary SessionDirectory object */
4122 (*_session_dir) = newstr;
4127 /* now rename directory below session_dir/interchange */
4129 string old_interchange_dir;
4130 string new_interchange_dir;
4132 /* use newstr here because we renamed the path
4133 * (folder/directory) that used to be oldstr to newstr above
4136 v.push_back (newstr);
4137 v.push_back (interchange_dir_name);
4138 v.push_back (Glib::path_get_basename (oldstr));
4140 old_interchange_dir = Glib::build_filename (v);
4143 v.push_back (newstr);
4144 v.push_back (interchange_dir_name);
4145 v.push_back (legal_name);
4147 new_interchange_dir = Glib::build_filename (v);
4149 cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
4151 if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
4152 cerr << string_compose (_("renaming %s as %2 failed (%3)"),
4153 old_interchange_dir, new_interchange_dir,
4156 error << string_compose (_("renaming %s as %2 failed (%3)"),
4157 old_interchange_dir, new_interchange_dir,
4166 oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
4167 newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
4169 cerr << "Rename " << oldstr << " => " << newstr << endl;
4171 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4172 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4173 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4179 oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
4181 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
4182 newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
4184 cerr << "Rename " << oldstr << " => " << newstr << endl;
4186 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4187 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4188 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4193 /* remove old name from recent sessions */
4194 remove_recent_sessions (_path);
4197 /* update file source paths */
4199 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
4200 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4202 string p = fs->path ();
4203 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
4205 SourceFactory::setup_peakfile(i->second, true);
4209 set_snapshot_name (new_name);
4214 /* save state again to get everything just right */
4216 save_state (_current_snapshot_name);
4218 /* add to recent sessions */
4220 store_recent_sessions (new_name, _path);
4226 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
4228 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
4232 if (!tree.read (xmlpath)) {
4240 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
4243 bool found_sr = false;
4244 bool found_data_format = false;
4246 if (get_session_info_from_path (tree, xmlpath)) {
4252 XMLProperty const * prop;
4253 XMLNode const * root (tree.root());
4255 if ((prop = root->property (X_("sample-rate"))) != 0) {
4256 sample_rate = atoi (prop->value());
4260 const XMLNodeList& children (root->children());
4261 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
4262 const XMLNode* child = *c;
4263 if (child->name() == "Config") {
4264 const XMLNodeList& options (child->children());
4265 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
4266 XMLNode const * option = *oc;
4267 XMLProperty const * name = option->property("name");
4273 if (name->value() == "native-file-data-format") {
4274 XMLProperty const * value = option->property ("value");
4276 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
4278 found_data_format = true;
4284 if (found_data_format) {
4289 return !(found_sr && found_data_format); // zero if they are both found
4293 Session::get_snapshot_from_instant (const std::string& session_dir)
4295 std::string instant_xml_path = Glib::build_filename (session_dir, "instant.xml");
4297 if (!Glib::file_test (instant_xml_path, Glib::FILE_TEST_EXISTS)) {
4302 if (!tree.read (instant_xml_path)) {
4306 XMLProperty const * prop;
4307 XMLNode *last_used_snapshot = tree.root()->child("LastUsedSnapshot");
4308 if (last_used_snapshot && (prop = last_used_snapshot->property ("name")) != 0) {
4309 return prop->value();
4315 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
4316 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
4319 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
4323 SourcePathMap source_path_map;
4325 boost::shared_ptr<AudioFileSource> afs;
4330 Glib::Threads::Mutex::Lock lm (source_lock);
4332 cerr << " total sources = " << sources.size();
4334 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4335 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4341 if (fs->within_session()) {
4345 if (source_path_map.find (fs->path()) != source_path_map.end()) {
4346 source_path_map[fs->path()].push_back (fs);
4348 SeveralFileSources v;
4350 source_path_map.insert (make_pair (fs->path(), v));
4356 cerr << " fsources = " << total << endl;
4358 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
4360 /* tell caller where we are */
4362 string old_path = i->first;
4364 callback (n, total, old_path);
4366 cerr << old_path << endl;
4370 switch (i->second.front()->type()) {
4371 case DataType::AUDIO:
4372 new_path = new_audio_source_path_for_embedded (old_path);
4375 case DataType::MIDI:
4376 /* XXX not implemented yet */
4380 if (new_path.empty()) {
4384 cerr << "Move " << old_path << " => " << new_path << endl;
4386 if (!copy_file (old_path, new_path)) {
4387 cerr << "failed !\n";
4391 /* make sure we stop looking in the external
4392 dir/folder. Remember, this is an all-or-nothing
4393 operations, it doesn't merge just some files.
4395 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
4397 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
4398 (*f)->set_path (new_path);
4403 save_state ("", false, false);
4409 bool accept_all_files (string const &, void *)
4415 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4417 /* 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.
4422 make_new_media_path (string old_path, string new_session_folder, string new_session_path)
4424 /* typedir is the "midifiles" or "audiofiles" etc. part of the path. */
4426 string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4428 v.push_back (new_session_folder); /* full path */
4429 v.push_back (interchange_dir_name);
4430 v.push_back (new_session_path); /* just one directory/folder */
4431 v.push_back (typedir);
4432 v.push_back (Glib::path_get_basename (old_path));
4434 return Glib::build_filename (v);
4438 Session::save_as (SaveAs& saveas)
4440 vector<string> files;
4441 string current_folder = Glib::path_get_dirname (_path);
4442 string new_folder = legalize_for_path (saveas.new_name);
4443 string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4444 int64_t total_bytes = 0;
4448 int32_t internal_file_cnt = 0;
4450 vector<string> do_not_copy_extensions;
4451 do_not_copy_extensions.push_back (statefile_suffix);
4452 do_not_copy_extensions.push_back (pending_suffix);
4453 do_not_copy_extensions.push_back (backup_suffix);
4454 do_not_copy_extensions.push_back (temp_suffix);
4455 do_not_copy_extensions.push_back (history_suffix);
4457 /* get total size */
4459 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4461 /* need to clear this because
4462 * find_files_matching_filter() is cumulative
4467 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4469 all += files.size();
4471 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4473 g_stat ((*i).c_str(), &gsb);
4474 total_bytes += gsb.st_size;
4478 /* save old values so we can switch back if we are not switching to the new session */
4480 string old_path = _path;
4481 string old_name = _name;
4482 string old_snapshot = _current_snapshot_name;
4483 string old_sd = _session_dir->root_path();
4484 vector<string> old_search_path[DataType::num_types];
4485 string old_config_search_path[DataType::num_types];
4487 old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4488 old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4489 old_config_search_path[DataType::AUDIO] = config.get_audio_search_path ();
4490 old_config_search_path[DataType::MIDI] = config.get_midi_search_path ();
4492 /* switch session directory */
4494 (*_session_dir) = to_dir;
4496 /* create new tree */
4498 if (!_session_dir->create()) {
4499 saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4504 /* copy all relevant files. Find each location in session_dirs,
4505 * and copy files from there to target.
4508 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4510 /* need to clear this because
4511 * find_files_matching_filter() is cumulative
4516 const size_t prefix_len = (*sd).path.size();
4518 /* Work just on the files within this session dir */
4520 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4522 /* add dir separator to protect against collisions with
4523 * track names (e.g. track named "audiofiles" or
4527 static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
4528 static const std::string midifile_dir_string = string (midi_dir_name) + G_DIR_SEPARATOR;
4529 static const std::string analysis_dir_string = analysis_dir() + G_DIR_SEPARATOR;
4531 /* copy all the files. Handling is different for media files
4532 than others because of the *silly* subtree we have below the interchange
4533 folder. That really was a bad idea, but I'm not fixing it as part of
4534 implementing ::save_as().
4537 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4539 std::string from = *i;
4542 string filename = Glib::path_get_basename (from);
4543 std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
4544 if (filename == ".DS_STORE") {
4549 if (from.find (audiofile_dir_string) != string::npos) {
4551 /* audio file: only copy if asked */
4553 if (saveas.include_media && saveas.copy_media) {
4555 string to = make_new_media_path (*i, to_dir, new_folder);
4557 info << "media file copying from " << from << " to " << to << endmsg;
4559 if (!copy_file (from, to)) {
4560 throw Glib::FileError (Glib::FileError::IO_ERROR,
4561 string_compose(_("\ncopying \"%1\" failed !"), from));
4565 /* we found media files inside the session folder */
4567 internal_file_cnt++;
4569 } else if (from.find (midifile_dir_string) != string::npos) {
4571 /* midi file: always copy unless
4572 * creating an empty new session
4575 if (saveas.include_media) {
4577 string to = make_new_media_path (*i, to_dir, new_folder);
4579 info << "media file copying from " << from << " to " << to << endmsg;
4581 if (!copy_file (from, to)) {
4582 throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4586 /* we found media files inside the session folder */
4588 internal_file_cnt++;
4590 } else if (from.find (analysis_dir_string) != string::npos) {
4592 /* make sure analysis dir exists in
4593 * new session folder, but we're not
4594 * copying analysis files here, see
4598 (void) g_mkdir_with_parents (analysis_dir().c_str(), 775);
4603 /* normal non-media file. Don't copy state, history, etc.
4606 bool do_copy = true;
4608 for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
4609 if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
4610 /* end of filename matches extension, do not copy file */
4616 if (!saveas.copy_media && from.find (peakfile_suffix) != string::npos) {
4617 /* don't copy peakfiles if
4618 * we're not copying media
4624 string to = Glib::build_filename (to_dir, from.substr (prefix_len));
4626 info << "attempting to make directory/folder " << to << endmsg;
4628 if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
4629 throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
4632 info << "attempting to copy " << from << " to " << to << endmsg;
4634 if (!copy_file (from, to)) {
4635 throw Glib::FileError (Glib::FileError::IO_ERROR,
4636 string_compose(_("\ncopying \"%1\" failed !"), from));
4641 /* measure file size even if we're not going to copy so that our Progress
4642 signals are correct, since we included these do-not-copy files
4643 in the computation of the total size and file count.
4647 g_stat (from.c_str(), &gsb);
4648 copied += gsb.st_size;
4651 double fraction = (double) copied / total_bytes;
4653 bool keep_going = true;
4655 if (saveas.copy_media) {
4657 /* no need or expectation of this if
4658 * media is not being copied, because
4659 * it will be fast(ish).
4662 /* tell someone "X percent, file M of N"; M is one-based */
4664 boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
4672 throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
4678 /* copy optional folders, if any */
4680 string old = plugins_dir ();
4681 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4682 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4683 copy_files (old, newdir);
4686 old = externals_dir ();
4687 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4688 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4689 copy_files (old, newdir);
4692 old = automation_dir ();
4693 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4694 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4695 copy_files (old, newdir);
4698 if (saveas.include_media) {
4700 if (saveas.copy_media) {
4701 #ifndef PLATFORM_WINDOWS
4702 /* There are problems with analysis files on
4703 * Windows, because they used a colon in their
4704 * names as late as 4.0. Colons are not legal
4705 * under Windows even if NTFS allows them.
4707 * This is a tricky problem to solve so for
4708 * just don't copy these files. They will be
4709 * regenerated as-needed anyway, subject to the
4710 * existing issue that the filenames will be
4711 * rejected by Windows, which is a separate
4712 * problem (though related).
4715 /* only needed if we are copying media, since the
4716 * analysis data refers to media data
4719 old = analysis_dir ();
4720 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4721 string newdir = Glib::build_filename (to_dir, "analysis");
4722 copy_files (old, newdir);
4724 #endif /* PLATFORM_WINDOWS */
4730 set_snapshot_name (saveas.new_name);
4731 _name = saveas.new_name;
4733 if (saveas.include_media && !saveas.copy_media) {
4735 /* reset search paths of the new session (which we're pretending to be right now) to
4736 include the original session search path, so we can still find all audio.
4739 if (internal_file_cnt) {
4740 for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
4741 ensure_search_path_includes (*s, DataType::AUDIO);
4742 cerr << "be sure to include " << *s << " for audio" << endl;
4745 /* we do not do this for MIDI because we copy
4746 all MIDI files if saveas.include_media is
4752 bool was_dirty = dirty ();
4754 save_state ("", false, false, !saveas.include_media);
4755 save_default_options ();
4757 if (saveas.copy_media && saveas.copy_external) {
4758 if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
4759 throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
4763 saveas.final_session_folder_name = _path;
4765 store_recent_sessions (_name, _path);
4767 if (!saveas.switch_to) {
4769 /* switch back to the way things were */
4773 set_snapshot_name (old_snapshot);
4775 (*_session_dir) = old_sd;
4781 if (internal_file_cnt) {
4782 /* reset these to their original values */
4783 config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
4784 config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
4789 /* prune session dirs, and update disk space statistics
4794 session_dirs.clear ();
4795 session_dirs.push_back (sp);
4796 refresh_disk_space ();
4798 /* ensure that all existing tracks reset their current capture source paths
4800 reset_write_sources (true, true);
4802 /* the copying above was based on actually discovering files, not just iterating over the sources list.
4803 But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
4806 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4807 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4813 if (fs->within_session()) {
4814 string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
4815 fs->set_path (newpath);
4820 } catch (Glib::FileError& e) {
4822 saveas.failure_message = e.what();
4824 /* recursively remove all the directories */
4826 remove_directory (to_dir);
4834 saveas.failure_message = _("unknown reason");
4836 /* recursively remove all the directories */
4838 remove_directory (to_dir);