2 Copyright (C) 1999-2013 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "libardour-config.h"
30 #include <cstdio> /* snprintf(3) ... grrr */
43 #include <sys/param.h>
44 #include <sys/mount.h>
47 #ifdef HAVE_SYS_STATVFS_H
48 #include <sys/statvfs.h>
52 #include "pbd/gstdio_compat.h"
55 #include <glibmm/threads.h>
56 #include <glibmm/fileutils.h>
58 #include <boost/algorithm/string.hpp>
60 #include "midi++/mmc.h"
61 #include "midi++/port.h"
63 #include "evoral/SMF.hpp"
65 #include "pbd/basename.h"
66 #include "pbd/debug.h"
67 #include "pbd/enumwriter.h"
68 #include "pbd/error.h"
69 #include "pbd/file_utils.h"
70 #include "pbd/pathexpand.h"
71 #include "pbd/pthread_utils.h"
72 #include "pbd/stacktrace.h"
73 #include "pbd/convert.h"
74 #include "pbd/localtime_r.h"
75 #include "pbd/unwind.h"
77 #include "ardour/amp.h"
78 #include "ardour/async_midi_port.h"
79 #include "ardour/audio_diskstream.h"
80 #include "ardour/audio_track.h"
81 #include "ardour/audioengine.h"
82 #include "ardour/audiofilesource.h"
83 #include "ardour/audioregion.h"
84 #include "ardour/auditioner.h"
85 #include "ardour/automation_control.h"
86 #include "ardour/boost_debug.h"
87 #include "ardour/butler.h"
88 #include "ardour/controllable_descriptor.h"
89 #include "ardour/control_protocol_manager.h"
90 #include "ardour/directory_names.h"
91 #include "ardour/filename_extensions.h"
92 #include "ardour/graph.h"
93 #include "ardour/location.h"
94 #include "ardour/midi_model.h"
95 #include "ardour/midi_patch_manager.h"
96 #include "ardour/midi_region.h"
97 #include "ardour/midi_scene_changer.h"
98 #include "ardour/midi_source.h"
99 #include "ardour/midi_track.h"
100 #include "ardour/pannable.h"
101 #include "ardour/playlist_factory.h"
102 #include "ardour/playlist_source.h"
103 #include "ardour/port.h"
104 #include "ardour/processor.h"
105 #include "ardour/profile.h"
106 #include "ardour/proxy_controllable.h"
107 #include "ardour/recent_sessions.h"
108 #include "ardour/region_factory.h"
109 #include "ardour/revision.h"
110 #include "ardour/route_group.h"
111 #include "ardour/send.h"
112 #include "ardour/session.h"
113 #include "ardour/session_directory.h"
114 #include "ardour/session_metadata.h"
115 #include "ardour/session_playlists.h"
116 #include "ardour/session_state_utils.h"
117 #include "ardour/silentfilesource.h"
118 #include "ardour/sndfilesource.h"
119 #include "ardour/source_factory.h"
120 #include "ardour/speakers.h"
121 #include "ardour/template_utils.h"
122 #include "ardour/tempo.h"
123 #include "ardour/ticker.h"
124 #include "ardour/user_bundle.h"
125 #include "ardour/vca.h"
126 #include "ardour/vca_manager.h"
128 #include "control_protocol/control_protocol.h"
130 #include "LuaBridge/LuaBridge.h"
136 using namespace ARDOUR;
139 #define DEBUG_UNDO_HISTORY(msg) DEBUG_TRACE (PBD::DEBUG::UndoHistory, string_compose ("%1: %2\n", __LINE__, msg));
142 Session::pre_engine_init (string fullpath)
144 if (fullpath.empty()) {
146 throw failed_constructor();
149 /* discover canonical fullpath */
151 _path = canonical_path(fullpath);
154 if (Profile->get_trx() ) {
155 // Waves TracksLive has a usecase of session replacement with a new one.
156 // We should check session state file (<session_name>.ardour) existance
157 // to determine if the session is new or not
159 string full_session_name = Glib::build_filename( fullpath, _name );
160 full_session_name += statefile_suffix;
162 _is_new = !Glib::file_test (full_session_name, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
164 _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
167 /* finish initialization that can't be done in a normal C++ constructor
171 timerclear (&last_mmc_step);
172 g_atomic_int_set (&processing_prohibited, 0);
173 g_atomic_int_set (&_record_status, Disabled);
174 g_atomic_int_set (&_playback_load, 100);
175 g_atomic_int_set (&_capture_load, 100);
177 _all_route_group->set_active (true, this);
178 interpolation.add_channel_to (0, 0);
179 _vca_manager = new VCAManager (*this);
181 if (config.get_use_video_sync()) {
182 waiting_for_sync_offset = true;
184 waiting_for_sync_offset = false;
187 last_rr_session_dir = session_dirs.begin();
189 set_history_depth (Config->get_history_depth());
191 /* default: assume simple stereo speaker configuration */
193 _speakers->setup_default_speakers (2);
195 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
196 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
197 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
198 add_controllable (_solo_cut_control);
200 /* These are all static "per-class" signals */
202 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
203 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
204 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
205 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
206 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
208 /* stop IO objects from doing stuff until we're ready for them */
210 Delivery::disable_panners ();
211 IO::disable_connecting ();
215 Session::post_engine_init ()
217 BootMessage (_("Set block size and sample rate"));
219 set_block_size (_engine.samples_per_cycle());
220 set_frame_rate (_engine.sample_rate());
222 BootMessage (_("Using configuration"));
224 _midi_ports = new MidiPortManager;
226 MIDISceneChanger* msc;
228 _scene_changer = msc = new MIDISceneChanger (*this);
229 msc->set_input_port (boost::dynamic_pointer_cast<MidiPort>(scene_input_port()));
230 msc->set_output_port (boost::dynamic_pointer_cast<MidiPort>(scene_output_port()));
232 boost::function<framecnt_t(void)> timer_func (boost::bind (&Session::audible_frame, this));
233 boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_input_port())->set_timer (timer_func);
235 setup_midi_machine_control ();
237 if (_butler->start_thread()) {
241 if (start_midi_thread ()) {
245 setup_click_sounds (0);
246 setup_midi_control ();
248 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
249 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
252 /* tempo map requires sample rate knowledge */
255 _tempo_map = new TempoMap (_current_frame_rate);
256 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
257 _tempo_map->MetricPositionChanged.connect_same_thread (*this, boost::bind (&Session::gui_tempo_map_changed, this));
259 /* MidiClock requires a tempo map */
262 midi_clock = new MidiClockTicker ();
263 midi_clock->set_session (this);
265 /* crossfades require sample rate knowledge */
267 SndFileSource::setup_standard_crossfades (*this, frame_rate());
268 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
270 AudioDiskstream::allocate_working_buffers();
271 refresh_disk_space ();
273 /* we're finally ready to call set_state() ... all objects have
274 * been created, the engine is running.
278 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
282 // set_state() will call setup_raid_path(), but if it's a new session we need
283 // to call setup_raid_path() here.
284 setup_raid_path (_path);
289 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
290 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
292 Config->map_parameters (ff);
293 config.map_parameters (ft);
294 _butler->map_parameters ();
296 /* Reset all panners */
298 Delivery::reset_panners ();
300 /* this will cause the CPM to instantiate any protocols that are in use
301 * (or mandatory), which will pass it this Session, and then call
302 * set_state() on each instantiated protocol to match stored state.
305 ControlProtocolManager::instance().set_session (this);
307 /* This must be done after the ControlProtocolManager set_session above,
308 as it will set states for ports which the ControlProtocolManager creates.
311 // XXX set state of MIDI::Port's
312 // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
314 /* And this must be done after the MIDI::Manager::set_port_states as
315 * it will try to make connections whose details are loaded by set_port_states.
320 /* Let control protocols know that we are now all connected, so they
321 * could start talking to surfaces if they want to.
324 ControlProtocolManager::instance().midi_connectivity_established ();
326 if (_is_new && !no_auto_connect()) {
327 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
328 auto_connect_master_bus ();
331 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
333 /* update latencies */
335 initialize_latencies ();
337 _locations->added.connect_same_thread (*this, boost::bind (&Session::location_added, this, _1));
338 _locations->removed.connect_same_thread (*this, boost::bind (&Session::location_removed, this, _1));
339 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
341 } catch (AudioEngine::PortRegistrationFailure& err) {
342 /* handle this one in a different way than all others, so that its clear what happened */
343 error << err.what() << endmsg;
349 BootMessage (_("Reset Remote Controls"));
351 // send_full_time_code (0);
352 _engine.transport_locate (0);
354 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
355 send_immediate_mmc (MIDI::MachineControlCommand (Timecode::Time ()));
357 MIDI::Name::MidiPatchManager::instance().add_search_path (session_directory().midi_patch_path() );
360 /* initial program change will be delivered later; see ::config_changed() */
362 _state_of_the_state = Clean;
364 Port::set_connecting_blocked (false);
366 DirtyChanged (); /* EMIT SIGNAL */
370 } else if (state_was_pending) {
372 remove_pending_capture_state ();
373 state_was_pending = false;
376 /* Now, finally, we can fill the playback buffers */
378 BootMessage (_("Filling playback buffers"));
380 boost::shared_ptr<RouteList> rl = routes.reader();
381 for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
382 boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<Track> (*r);
383 if (trk && !trk->hidden()) {
384 trk->seek (_transport_frame, true);
392 Session::session_loaded ()
396 _state_of_the_state = Clean;
398 DirtyChanged (); /* EMIT SIGNAL */
402 } else if (state_was_pending) {
404 remove_pending_capture_state ();
405 state_was_pending = false;
408 /* Now, finally, we can fill the playback buffers */
410 BootMessage (_("Filling playback buffers"));
411 force_locate (_transport_frame, false);
415 Session::raid_path () const
417 Searchpath raid_search_path;
419 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
420 raid_search_path += (*i).path;
423 return raid_search_path.to_string ();
427 Session::setup_raid_path (string path)
436 session_dirs.clear ();
438 Searchpath search_path(path);
439 Searchpath sound_search_path;
440 Searchpath midi_search_path;
442 for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
444 sp.blocks = 0; // not needed
445 session_dirs.push_back (sp);
447 SessionDirectory sdir(sp.path);
449 sound_search_path += sdir.sound_path ();
450 midi_search_path += sdir.midi_path ();
453 // reset the round-robin soundfile path thingie
454 last_rr_session_dir = session_dirs.begin();
458 Session::path_is_within_session (const std::string& path)
460 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
461 if (PBD::path_is_within (i->path, path)) {
469 Session::ensure_subdirs ()
473 dir = session_directory().peak_path();
475 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
476 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
480 dir = session_directory().sound_path();
482 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
483 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
487 dir = session_directory().midi_path();
489 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
490 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
494 dir = session_directory().dead_path();
496 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
497 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
501 dir = session_directory().export_path();
503 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
504 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
508 dir = analysis_dir ();
510 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
511 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
515 dir = plugins_dir ();
517 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
518 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
522 dir = externals_dir ();
524 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
525 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
532 /** @param session_template directory containing session template, or empty.
533 * Caller must not hold process lock.
536 Session::create (const string& session_template, BusProfile* bus_profile)
538 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
539 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
543 if (ensure_subdirs ()) {
547 _writable = exists_and_writable (_path);
549 if (!session_template.empty()) {
550 string in_path = (ARDOUR::Profile->get_trx () ? session_template : session_template_dir_to_file (session_template));
552 FILE* in = g_fopen (in_path.c_str(), "rb");
555 /* no need to call legalize_for_path() since the string
556 * in session_template is already a legal path name
558 string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
560 FILE* out = g_fopen (out_path.c_str(), "wb");
564 stringstream new_session;
567 size_t charsRead = fread (buf, sizeof(char), 1024, in);
570 error << string_compose (_("Error reading session template file %1 (%2)"), in_path, strerror (errno)) << endmsg;
575 if (charsRead == 0) {
578 new_session.write (buf, charsRead);
582 string file_contents = new_session.str();
583 size_t writeSize = file_contents.length();
584 if (fwrite (file_contents.c_str(), sizeof(char), writeSize, out) != writeSize) {
585 error << string_compose (_("Error writing session template file %1 (%2)"), out_path, strerror (errno)) << endmsg;
593 if (!ARDOUR::Profile->get_trx()) {
594 /* Copy plugin state files from template to new session */
595 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
596 copy_recurse (template_plugins, plugins_dir ());
602 error << string_compose (_("Could not open %1 for writing session template"), out_path)
609 error << string_compose (_("Could not open session template %1 for reading"), in_path)
616 if (Profile->get_trx()) {
618 /* set initial start + end point : ARDOUR::Session::session_end_shift long.
619 Remember that this is a brand new session. Sessions
620 loaded from saved state will get this range from the saved state.
623 set_session_range_location (0, 0);
625 /* Initial loop location, from absolute zero, length 10 seconds */
627 Location* loc = new Location (*this, 0, 10.0 * _engine.sample_rate(), _("Loop"), Location::IsAutoLoop);
628 _locations->add (loc, true);
629 set_auto_loop_location (loc);
632 _state_of_the_state = Clean;
634 /* set up Master Out and Monitor Out if necessary */
639 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
641 // Waves Tracks: always create master bus for Tracks
642 if (ARDOUR::Profile->get_trx() || bus_profile->master_out_channels) {
643 boost::shared_ptr<Route> r (new Route (*this, _("Master"), PresentationInfo::MasterOut, DataType::AUDIO));
651 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
652 r->input()->ensure_io (count, false, this);
653 r->output()->ensure_io (count, false, this);
659 /* prohibit auto-connect to master, because there isn't one */
660 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
664 add_routes (rl, false, false, false, PresentationInfo::max_order);
667 // Waves Tracks: Skip this. Always use autoconnection for Tracks
668 if (!ARDOUR::Profile->get_trx()) {
670 /* this allows the user to override settings with an environment variable.
673 if (no_auto_connect()) {
674 bus_profile->input_ac = AutoConnectOption (0);
675 bus_profile->output_ac = AutoConnectOption (0);
678 Config->set_input_auto_connect (bus_profile->input_ac);
679 Config->set_output_auto_connect (bus_profile->output_ac);
683 if (Config->get_use_monitor_bus() && bus_profile) {
684 add_monitor_section ();
691 Session::maybe_write_autosave()
693 if (dirty() && record_status() != Recording) {
694 save_state("", true);
699 Session::remove_pending_capture_state ()
701 std::string pending_state_file_path(_session_dir->root_path());
703 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
705 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
707 if (g_remove (pending_state_file_path.c_str()) != 0) {
708 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
709 pending_state_file_path, g_strerror (errno)) << endmsg;
713 /** Rename a state file.
714 * @param old_name Old snapshot name.
715 * @param new_name New snapshot name.
718 Session::rename_state (string old_name, string new_name)
720 if (old_name == _current_snapshot_name || old_name == _name) {
721 /* refuse to rename the current snapshot or the "main" one */
725 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
726 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
728 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
729 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
731 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
732 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
733 old_name, new_name, g_strerror(errno)) << endmsg;
737 /** Remove a state file.
738 * @param snapshot_name Snapshot name.
741 Session::remove_state (string snapshot_name)
743 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
744 // refuse to remove the current snapshot or the "main" one
748 std::string xml_path(_session_dir->root_path());
750 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
752 if (!create_backup_file (xml_path)) {
753 // don't remove it if a backup can't be made
754 // create_backup_file will log the error.
759 if (g_remove (xml_path.c_str()) != 0) {
760 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
761 xml_path, g_strerror (errno)) << endmsg;
765 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
767 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot, bool template_only)
769 DEBUG_TRACE (DEBUG::Locale, string_compose ("Session::save_state locale '%1'\n", setlocale (LC_NUMERIC, NULL)));
772 std::string xml_path(_session_dir->root_path());
774 /* prevent concurrent saves from different threads */
776 Glib::Threads::Mutex::Lock lm (save_state_lock);
778 if (!_writable || (_state_of_the_state & CannotSave)) {
782 if (g_atomic_int_get(&_suspend_save)) {
786 _save_queued = false;
788 if (!_engine.connected ()) {
789 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
796 const int64_t save_start_time = g_get_monotonic_time();
799 /* tell sources we're saving first, in case they write out to a new file
800 * which should be saved with the state rather than the old one */
801 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
803 i->second->session_saved();
804 } catch (Evoral::SMF::FileError& e) {
805 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
809 SessionSaveUnderway (); /* EMIT SIGNAL */
811 bool mark_as_clean = true;
813 if (!snapshot_name.empty() && !switch_to_snapshot) {
814 mark_as_clean = false;
818 mark_as_clean = false;
819 tree.set_root (&get_template());
821 tree.set_root (&get_state());
824 if (snapshot_name.empty()) {
825 snapshot_name = _current_snapshot_name;
826 } else if (switch_to_snapshot) {
827 set_snapshot_name (snapshot_name);
830 assert (!snapshot_name.empty());
834 /* proper save: use statefile_suffix (.ardour in English) */
836 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
838 /* make a backup copy of the old file */
840 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
841 // create_backup_file will log the error
847 /* pending save: use pending_suffix (.pending in English) */
848 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
851 std::string tmp_path(_session_dir->root_path());
852 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
854 cerr << "actually writing state to " << tmp_path << endl;
856 if (!tree.write (tmp_path)) {
857 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
858 if (g_remove (tmp_path.c_str()) != 0) {
859 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
860 tmp_path, g_strerror (errno)) << endmsg;
866 cerr << "renaming state to " << xml_path << endl;
868 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
869 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
870 tmp_path, xml_path, g_strerror(errno)) << endmsg;
871 if (g_remove (tmp_path.c_str()) != 0) {
872 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
873 tmp_path, g_strerror (errno)) << endmsg;
881 save_history (snapshot_name);
884 bool was_dirty = dirty();
886 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
889 DirtyChanged (); /* EMIT SIGNAL */
893 StateSaved (snapshot_name); /* EMIT SIGNAL */
897 const int64_t elapsed_time_us = g_get_monotonic_time() - save_start_time;
898 cerr << "saved state in " << fixed << setprecision (1) << elapsed_time_us / 1000. << " ms\n";
904 Session::restore_state (string snapshot_name)
906 if (load_state (snapshot_name) == 0) {
907 set_state (*state_tree->root(), Stateful::loading_state_version);
914 Session::load_state (string snapshot_name)
919 state_was_pending = false;
921 /* check for leftover pending state from a crashed capture attempt */
923 std::string xmlpath(_session_dir->root_path());
924 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
926 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
928 /* there is pending state from a crashed capture attempt */
930 boost::optional<int> r = AskAboutPendingState();
931 if (r.get_value_or (1)) {
932 state_was_pending = true;
936 if (!state_was_pending) {
937 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
940 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
941 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
942 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
943 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
948 state_tree = new XMLTree;
952 _writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
954 if (!state_tree->read (xmlpath)) {
955 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
961 XMLNode const & root (*state_tree->root());
963 if (root.name() != X_("Session")) {
964 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
970 XMLProperty const * prop;
972 if ((prop = root.property ("version")) == 0) {
973 /* no version implies very old version of Ardour */
974 Stateful::loading_state_version = 1000;
976 if (prop->value().find ('.') != string::npos) {
977 /* old school version format */
978 if (prop->value()[0] == '2') {
979 Stateful::loading_state_version = 2000;
981 Stateful::loading_state_version = 3000;
984 Stateful::loading_state_version = atoi (prop->value());
988 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
990 std::string backup_path(_session_dir->root_path());
991 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
992 backup_path = Glib::build_filename (backup_path, backup_filename);
994 // only create a backup for a given statefile version once
996 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
998 VersionMismatch (xmlpath, backup_path);
1000 if (!copy_file (xmlpath, backup_path)) {;
1006 save_snapshot_name (snapshot_name);
1012 Session::load_options (const XMLNode& node)
1015 config.set_variables (node);
1020 Session::save_default_options ()
1022 return config.save_state();
1026 Session::get_state()
1032 Session::get_template()
1034 /* if we don't disable rec-enable, diskstreams
1035 will believe they need to store their capture
1036 sources in their state node.
1039 disable_record (false);
1041 return state(false);
1045 Session::state (bool full_state)
1048 XMLNode* node = new XMLNode("Session");
1052 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
1053 node->add_property("version", buf);
1055 child = node->add_child ("ProgramVersion");
1056 child->add_property("created-with", created_with);
1058 std::string modified_with = string_compose ("%1 %2", PROGRAM_NAME, revision);
1059 child->add_property("modified-with", modified_with);
1061 /* store configuration settings */
1065 node->add_property ("name", _name);
1066 snprintf (buf, sizeof (buf), "%" PRId64, _base_frame_rate);
1067 node->add_property ("sample-rate", buf);
1069 if (session_dirs.size() > 1) {
1073 vector<space_and_path>::iterator i = session_dirs.begin();
1074 vector<space_and_path>::iterator next;
1076 ++i; /* skip the first one */
1080 while (i != session_dirs.end()) {
1084 if (next != session_dirs.end()) {
1085 p += G_SEARCHPATH_SEPARATOR;
1094 child = node->add_child ("Path");
1095 child->add_content (p);
1099 /* save the ID counter */
1101 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1102 node->add_property ("id-counter", buf);
1104 snprintf (buf, sizeof (buf), "%u", name_id_counter ());
1105 node->add_property ("name-counter", buf);
1107 /* save the event ID counter */
1109 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1110 node->add_property ("event-counter", buf);
1112 /* save the VCA counter */
1114 snprintf (buf, sizeof (buf), "%" PRIu32, VCA::get_next_vca_number());
1115 node->add_property ("vca-counter", buf);
1117 /* various options */
1119 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
1120 if (!midi_port_nodes.empty()) {
1121 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
1122 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
1123 midi_port_stuff->add_child_nocopy (**n);
1125 node->add_child_nocopy (*midi_port_stuff);
1128 node->add_child_nocopy (config.get_variables ());
1130 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1132 child = node->add_child ("Sources");
1135 Glib::Threads::Mutex::Lock sl (source_lock);
1137 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1139 /* Don't save information about non-file Sources, or
1140 * about non-destructive file sources that are empty
1141 * and unused by any regions.
1144 boost::shared_ptr<FileSource> fs;
1146 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1148 if (!fs->destructive()) {
1149 if (fs->empty() && !fs->used()) {
1154 child->add_child_nocopy (siter->second->get_state());
1159 child = node->add_child ("Regions");
1162 Glib::Threads::Mutex::Lock rl (region_lock);
1163 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1164 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1165 boost::shared_ptr<Region> r = i->second;
1166 /* only store regions not attached to playlists */
1167 if (r->playlist() == 0) {
1168 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1169 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1171 child->add_child_nocopy (r->get_state ());
1176 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1178 if (!cassocs.empty()) {
1179 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1181 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1183 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1184 i->first->id().print (buf, sizeof (buf));
1185 can->add_property (X_("copy"), buf);
1186 i->second->id().print (buf, sizeof (buf));
1187 can->add_property (X_("original"), buf);
1188 ca->add_child_nocopy (*can);
1198 node->add_child_nocopy (_locations->get_state());
1201 Locations loc (*this);
1202 // for a template, just create a new Locations, populate it
1203 // with the default start and end, and get the state for that.
1204 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1205 range->set (max_framepos, 0);
1207 XMLNode& locations_state = loc.get_state();
1209 if (ARDOUR::Profile->get_trx() && _locations) {
1210 // For tracks we need stored the Auto Loop Range and all MIDI markers.
1211 for (Locations::LocationList::const_iterator i = _locations->list ().begin (); i != _locations->list ().end (); ++i) {
1212 if ((*i)->is_mark () || (*i)->is_auto_loop ()) {
1213 locations_state.add_child_nocopy ((*i)->get_state ());
1217 node->add_child_nocopy (locations_state);
1220 child = node->add_child ("Bundles");
1222 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1223 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1224 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1226 child->add_child_nocopy (b->get_state());
1231 node->add_child_nocopy (_vca_manager->get_state());
1233 child = node->add_child ("Routes");
1235 boost::shared_ptr<RouteList> r = routes.reader ();
1237 RoutePublicOrderSorter cmp;
1238 RouteList public_order (*r);
1239 public_order.sort (cmp);
1241 /* the sort should have put control outs first */
1244 assert (_monitor_out == public_order.front());
1247 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1248 if (!(*i)->is_auditioner()) {
1250 child->add_child_nocopy ((*i)->get_state());
1252 child->add_child_nocopy ((*i)->get_template());
1258 playlists->add_state (node, full_state);
1260 child = node->add_child ("RouteGroups");
1261 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1262 child->add_child_nocopy ((*i)->get_state());
1266 XMLNode* gain_child = node->add_child ("Click");
1267 gain_child->add_child_nocopy (_click_io->state (full_state));
1268 gain_child->add_child_nocopy (_click_gain->state (full_state));
1272 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1273 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1277 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1278 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1281 node->add_child_nocopy (_speakers->get_state());
1282 node->add_child_nocopy (_tempo_map->get_state());
1283 node->add_child_nocopy (get_control_protocol_state());
1286 node->add_child_copy (*_extra_xml);
1290 Glib::Threads::Mutex::Lock lm (lua_lock);
1293 luabridge::LuaRef savedstate ((*_lua_save)());
1294 saved = savedstate.cast<std::string>();
1296 lua.collect_garbage ();
1299 gchar* b64 = g_base64_encode ((const guchar*)saved.c_str (), saved.size ());
1300 std::string b64s (b64);
1303 XMLNode* script_node = new XMLNode (X_("Script"));
1304 script_node->add_property (X_("lua"), LUA_VERSION);
1305 script_node->add_content (b64s);
1306 node->add_child_nocopy (*script_node);
1313 Session::get_control_protocol_state ()
1315 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1316 return cpm.get_state();
1320 Session::set_state (const XMLNode& node, int version)
1325 XMLProperty const * prop;
1328 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1330 if (node.name() != X_("Session")) {
1331 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1335 if ((prop = node.property ("name")) != 0) {
1336 _name = prop->value ();
1339 if ((prop = node.property (X_("sample-rate"))) != 0) {
1341 _base_frame_rate = atoi (prop->value());
1342 _nominal_frame_rate = _base_frame_rate;
1344 assert (AudioEngine::instance()->running ());
1345 if (_base_frame_rate != AudioEngine::instance()->sample_rate ()) {
1346 boost::optional<int> r = AskAboutSampleRateMismatch (_base_frame_rate, _current_frame_rate);
1347 if (r.get_value_or (0)) {
1353 created_with = "unknown";
1354 if ((child = find_named_node (node, "ProgramVersion")) != 0) {
1355 if ((prop = child->property (X_("created-with"))) != 0) {
1356 created_with = prop->value ();
1360 setup_raid_path(_session_dir->root_path());
1362 if ((prop = node.property (X_("id-counter"))) != 0) {
1364 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1365 ID::init_counter (x);
1367 /* old sessions used a timebased counter, so fake
1368 the startup ID counter based on a standard
1373 ID::init_counter (now);
1376 if ((prop = node.property (X_("name-counter"))) != 0) {
1377 init_name_id_counter (atoi (prop->value()));
1380 if ((prop = node.property (X_("event-counter"))) != 0) {
1381 Evoral::init_event_id_counter (atoi (prop->value()));
1384 if ((prop = node.property (X_("vca-counter"))) != 0) {
1386 sscanf (prop->value().c_str(), "%" PRIu32, &x);
1387 VCA::set_next_vca_number (x);
1389 VCA::set_next_vca_number (1);
1392 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1393 _midi_ports->set_midi_port_states (child->children());
1396 IO::disable_connecting ();
1398 Stateful::save_extra_xml (node);
1400 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1401 load_options (*child);
1402 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1403 load_options (*child);
1405 error << _("Session: XML state has no options section") << endmsg;
1408 if (version >= 3000) {
1409 if ((child = find_named_node (node, "Metadata")) == 0) {
1410 warning << _("Session: XML state has no metadata section") << endmsg;
1411 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1416 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1417 _speakers->set_state (*child, version);
1420 if ((child = find_named_node (node, "Sources")) == 0) {
1421 error << _("Session: XML state has no sources section") << endmsg;
1423 } else if (load_sources (*child)) {
1427 if ((child = find_named_node (node, "TempoMap")) == 0) {
1428 error << _("Session: XML state has no Tempo Map section") << endmsg;
1430 } else if (_tempo_map->set_state (*child, version)) {
1434 if ((child = find_named_node (node, "Locations")) == 0) {
1435 error << _("Session: XML state has no locations section") << endmsg;
1437 } else if (_locations->set_state (*child, version)) {
1441 locations_changed ();
1443 if (_session_range_location) {
1444 AudioFileSource::set_header_position_offset (_session_range_location->start());
1447 if ((child = find_named_node (node, "Regions")) == 0) {
1448 error << _("Session: XML state has no Regions section") << endmsg;
1450 } else if (load_regions (*child)) {
1454 if ((child = find_named_node (node, "Playlists")) == 0) {
1455 error << _("Session: XML state has no playlists section") << endmsg;
1457 } else if (playlists->load (*this, *child)) {
1461 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1463 } else if (playlists->load_unused (*this, *child)) {
1467 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1468 if (load_compounds (*child)) {
1473 if (version >= 3000) {
1474 if ((child = find_named_node (node, "Bundles")) == 0) {
1475 warning << _("Session: XML state has no bundles section") << endmsg;
1478 /* We can't load Bundles yet as they need to be able
1479 to convert from port names to Port objects, which can't happen until
1481 _bundle_xml_node = new XMLNode (*child);
1485 if (version < 3000) {
1486 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1487 error << _("Session: XML state has no diskstreams section") << endmsg;
1489 } else if (load_diskstreams_2X (*child, version)) {
1494 if ((child = find_named_node (node, VCAManager::xml_node_name)) != 0) {
1495 _vca_manager->set_state (*child, version);
1498 if ((child = find_named_node (node, "Routes")) == 0) {
1499 error << _("Session: XML state has no routes section") << endmsg;
1501 } else if (load_routes (*child, version)) {
1505 /* Now that we have Routes and masters loaded, connect them if appropriate */
1507 Slavable::Assign (_vca_manager); /* EMIT SIGNAL */
1509 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1510 _diskstreams_2X.clear ();
1512 if (version >= 3000) {
1514 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1515 error << _("Session: XML state has no route groups section") << endmsg;
1517 } else if (load_route_groups (*child, version)) {
1521 } else if (version < 3000) {
1523 if ((child = find_named_node (node, "EditGroups")) == 0) {
1524 error << _("Session: XML state has no edit groups section") << endmsg;
1526 } else if (load_route_groups (*child, version)) {
1530 if ((child = find_named_node (node, "MixGroups")) == 0) {
1531 error << _("Session: XML state has no mix groups section") << endmsg;
1533 } else if (load_route_groups (*child, version)) {
1538 if ((child = find_named_node (node, "Click")) == 0) {
1539 warning << _("Session: XML state has no click section") << endmsg;
1540 } else if (_click_io) {
1541 setup_click_state (&node);
1544 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1545 ControlProtocolManager::instance().set_state (*child, version);
1548 if ((child = find_named_node (node, "Script"))) {
1549 for (XMLNodeList::const_iterator n = child->children ().begin (); n != child->children ().end (); ++n) {
1550 if (!(*n)->is_content ()) { continue; }
1552 guchar* buf = g_base64_decode ((*n)->content ().c_str (), &size);
1554 Glib::Threads::Mutex::Lock lm (lua_lock);
1555 (*_lua_load)(std::string ((const char*)buf, size));
1556 } catch (luabridge::LuaException const& e) {
1557 cerr << "LuaException:" << e.what () << endl;
1563 update_route_record_state ();
1565 /* here beginneth the second phase ... */
1566 set_snapshot_name (_current_snapshot_name);
1568 StateReady (); /* EMIT SIGNAL */
1581 Session::load_routes (const XMLNode& node, int version)
1584 XMLNodeConstIterator niter;
1585 RouteList new_routes;
1587 nlist = node.children();
1591 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1593 boost::shared_ptr<Route> route;
1594 if (version < 3000) {
1595 route = XMLRouteFactory_2X (**niter, version);
1597 route = XMLRouteFactory (**niter, version);
1601 error << _("Session: cannot create Route from XML description.") << endmsg;
1605 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1607 new_routes.push_back (route);
1610 BootMessage (_("Tracks/busses loaded; Adding to Session"));
1612 add_routes (new_routes, false, false, false, PresentationInfo::max_order);
1614 BootMessage (_("Finished adding tracks/busses"));
1619 boost::shared_ptr<Route>
1620 Session::XMLRouteFactory (const XMLNode& node, int version)
1622 boost::shared_ptr<Route> ret;
1624 if (node.name() != "Route") {
1628 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1630 DataType type = DataType::AUDIO;
1631 XMLProperty const * prop = node.property("default-type");
1634 type = DataType (prop->value());
1637 assert (type != DataType::NIL);
1641 boost::shared_ptr<Track> track;
1643 if (type == DataType::AUDIO) {
1644 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1646 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1649 if (track->init()) {
1653 if (track->set_state (node, version)) {
1657 BOOST_MARK_TRACK (track);
1661 PresentationInfo::Flag flags = PresentationInfo::get_flags (node);
1662 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1664 if (r->init () == 0 && r->set_state (node, version) == 0) {
1665 BOOST_MARK_ROUTE (r);
1673 boost::shared_ptr<Route>
1674 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1676 boost::shared_ptr<Route> ret;
1678 if (node.name() != "Route") {
1682 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1684 ds_prop = node.property (X_("diskstream"));
1687 DataType type = DataType::AUDIO;
1688 XMLProperty const * prop = node.property("default-type");
1691 type = DataType (prop->value());
1694 assert (type != DataType::NIL);
1698 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1699 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1703 if (i == _diskstreams_2X.end()) {
1704 error << _("Could not find diskstream for route") << endmsg;
1705 return boost::shared_ptr<Route> ();
1708 boost::shared_ptr<Track> track;
1710 if (type == DataType::AUDIO) {
1711 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1713 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1716 if (track->init()) {
1720 if (track->set_state (node, version)) {
1724 track->set_diskstream (*i);
1726 BOOST_MARK_TRACK (track);
1730 PresentationInfo::Flag flags = PresentationInfo::get_flags (node);
1731 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1733 if (r->init () == 0 && r->set_state (node, version) == 0) {
1734 BOOST_MARK_ROUTE (r);
1743 Session::load_regions (const XMLNode& node)
1746 XMLNodeConstIterator niter;
1747 boost::shared_ptr<Region> region;
1749 nlist = node.children();
1753 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1754 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1755 error << _("Session: cannot create Region from XML description.");
1756 XMLProperty const * name = (**niter).property("name");
1759 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1770 Session::load_compounds (const XMLNode& node)
1772 XMLNodeList calist = node.children();
1773 XMLNodeConstIterator caiter;
1774 XMLProperty const * caprop;
1776 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1777 XMLNode* ca = *caiter;
1781 if ((caprop = ca->property (X_("original"))) == 0) {
1784 orig_id = caprop->value();
1786 if ((caprop = ca->property (X_("copy"))) == 0) {
1789 copy_id = caprop->value();
1791 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1792 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1794 if (!orig || !copy) {
1795 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1801 RegionFactory::add_compound_association (orig, copy);
1808 Session::load_nested_sources (const XMLNode& node)
1811 XMLNodeConstIterator niter;
1813 nlist = node.children();
1815 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1816 if ((*niter)->name() == "Source") {
1818 /* it may already exist, so don't recreate it unnecessarily
1821 XMLProperty const * prop = (*niter)->property (X_("id"));
1823 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1827 ID source_id (prop->value());
1829 if (!source_by_id (source_id)) {
1832 SourceFactory::create (*this, **niter, true);
1834 catch (failed_constructor& err) {
1835 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1842 boost::shared_ptr<Region>
1843 Session::XMLRegionFactory (const XMLNode& node, bool full)
1845 XMLProperty const * type = node.property("type");
1849 const XMLNodeList& nlist = node.children();
1851 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1852 XMLNode *child = (*niter);
1853 if (child->name() == "NestedSource") {
1854 load_nested_sources (*child);
1858 if (!type || type->value() == "audio") {
1859 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1860 } else if (type->value() == "midi") {
1861 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1864 } catch (failed_constructor& err) {
1865 return boost::shared_ptr<Region> ();
1868 return boost::shared_ptr<Region> ();
1871 boost::shared_ptr<AudioRegion>
1872 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1874 XMLProperty const * prop;
1875 boost::shared_ptr<Source> source;
1876 boost::shared_ptr<AudioSource> as;
1878 SourceList master_sources;
1879 uint32_t nchans = 1;
1882 if (node.name() != X_("Region")) {
1883 return boost::shared_ptr<AudioRegion>();
1886 if ((prop = node.property (X_("channels"))) != 0) {
1887 nchans = atoi (prop->value().c_str());
1890 if ((prop = node.property ("name")) == 0) {
1891 cerr << "no name for this region\n";
1895 if ((prop = node.property (X_("source-0"))) == 0) {
1896 if ((prop = node.property ("source")) == 0) {
1897 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1898 return boost::shared_ptr<AudioRegion>();
1902 PBD::ID s_id (prop->value());
1904 if ((source = source_by_id (s_id)) == 0) {
1905 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1906 return boost::shared_ptr<AudioRegion>();
1909 as = boost::dynamic_pointer_cast<AudioSource>(source);
1911 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1912 return boost::shared_ptr<AudioRegion>();
1915 sources.push_back (as);
1917 /* pickup other channels */
1919 for (uint32_t n=1; n < nchans; ++n) {
1920 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1921 if ((prop = node.property (buf)) != 0) {
1923 PBD::ID id2 (prop->value());
1925 if ((source = source_by_id (id2)) == 0) {
1926 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1927 return boost::shared_ptr<AudioRegion>();
1930 as = boost::dynamic_pointer_cast<AudioSource>(source);
1932 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1933 return boost::shared_ptr<AudioRegion>();
1935 sources.push_back (as);
1939 for (uint32_t n = 0; n < nchans; ++n) {
1940 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1941 if ((prop = node.property (buf)) != 0) {
1943 PBD::ID id2 (prop->value());
1945 if ((source = source_by_id (id2)) == 0) {
1946 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1947 return boost::shared_ptr<AudioRegion>();
1950 as = boost::dynamic_pointer_cast<AudioSource>(source);
1952 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1953 return boost::shared_ptr<AudioRegion>();
1955 master_sources.push_back (as);
1960 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1962 /* a final detail: this is the one and only place that we know how long missing files are */
1964 if (region->whole_file()) {
1965 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1966 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1968 sfp->set_length (region->length());
1973 if (!master_sources.empty()) {
1974 if (master_sources.size() != nchans) {
1975 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1977 region->set_master_sources (master_sources);
1985 catch (failed_constructor& err) {
1986 return boost::shared_ptr<AudioRegion>();
1990 boost::shared_ptr<MidiRegion>
1991 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1993 XMLProperty const * prop;
1994 boost::shared_ptr<Source> source;
1995 boost::shared_ptr<MidiSource> ms;
1998 if (node.name() != X_("Region")) {
1999 return boost::shared_ptr<MidiRegion>();
2002 if ((prop = node.property ("name")) == 0) {
2003 cerr << "no name for this region\n";
2007 if ((prop = node.property (X_("source-0"))) == 0) {
2008 if ((prop = node.property ("source")) == 0) {
2009 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
2010 return boost::shared_ptr<MidiRegion>();
2014 PBD::ID s_id (prop->value());
2016 if ((source = source_by_id (s_id)) == 0) {
2017 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
2018 return boost::shared_ptr<MidiRegion>();
2021 ms = boost::dynamic_pointer_cast<MidiSource>(source);
2023 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
2024 return boost::shared_ptr<MidiRegion>();
2027 sources.push_back (ms);
2030 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
2031 /* a final detail: this is the one and only place that we know how long missing files are */
2033 if (region->whole_file()) {
2034 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
2035 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
2037 sfp->set_length (region->length());
2045 catch (failed_constructor& err) {
2046 return boost::shared_ptr<MidiRegion>();
2051 Session::get_sources_as_xml ()
2054 XMLNode* node = new XMLNode (X_("Sources"));
2055 Glib::Threads::Mutex::Lock lm (source_lock);
2057 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2058 node->add_child_nocopy (i->second->get_state());
2065 Session::reset_write_sources (bool mark_write_complete, bool force)
2067 boost::shared_ptr<RouteList> rl = routes.reader();
2068 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
2069 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
2071 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
2072 tr->reset_write_sources(mark_write_complete, force);
2073 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
2079 Session::load_sources (const XMLNode& node)
2082 XMLNodeConstIterator niter;
2083 boost::shared_ptr<Source> source; /* don't need this but it stops some
2084 * versions of gcc complaining about
2085 * discarded return values.
2088 nlist = node.children();
2092 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2095 if ((source = XMLSourceFactory (**niter)) == 0) {
2096 error << _("Session: cannot create Source from XML description.") << endmsg;
2099 } catch (MissingSource& err) {
2103 if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
2104 error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
2105 PROGRAM_NAME) << endmsg;
2109 if (!no_questions_about_missing_files) {
2110 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
2115 switch (user_choice) {
2117 /* user added a new search location, so try again */
2122 /* user asked to quit the entire session load
2127 no_questions_about_missing_files = true;
2131 no_questions_about_missing_files = true;
2138 case DataType::AUDIO:
2139 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
2142 case DataType::MIDI:
2143 /* The MIDI file is actually missing so
2144 * just create a new one in the same
2145 * location. Do not announce its
2149 if (!Glib::path_is_absolute (err.path)) {
2150 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
2152 /* this should be an unrecoverable error: we would be creating a MIDI file outside
2157 /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
2158 source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
2159 /* reset ID to match the missing one */
2160 source->set_id (**niter);
2161 /* Now we can announce it */
2162 SourceFactory::SourceCreated (source);
2173 boost::shared_ptr<Source>
2174 Session::XMLSourceFactory (const XMLNode& node)
2176 if (node.name() != "Source") {
2177 return boost::shared_ptr<Source>();
2181 /* note: do peak building in another thread when loading session state */
2182 return SourceFactory::create (*this, node, true);
2185 catch (failed_constructor& err) {
2186 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
2187 return boost::shared_ptr<Source>();
2192 Session::save_template (string template_name, bool replace_existing)
2194 if ((_state_of_the_state & CannotSave) || template_name.empty ()) {
2198 bool absolute_path = Glib::path_is_absolute (template_name);
2200 /* directory to put the template in */
2201 std::string template_dir_path;
2203 if (!absolute_path) {
2204 std::string user_template_dir(user_template_directory());
2206 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2207 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2208 user_template_dir, g_strerror (errno)) << endmsg;
2212 template_dir_path = Glib::build_filename (user_template_dir, template_name);
2214 template_dir_path = template_name;
2217 if (!ARDOUR::Profile->get_trx()) {
2218 if (!replace_existing && Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2219 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2220 template_dir_path) << endmsg;
2224 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2225 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2226 template_dir_path, g_strerror (errno)) << endmsg;
2232 std::string template_file_path;
2234 if (ARDOUR::Profile->get_trx()) {
2235 template_file_path = template_name;
2237 if (absolute_path) {
2238 template_file_path = Glib::build_filename (template_dir_path, Glib::path_get_basename (template_dir_path) + template_suffix);
2240 template_file_path = Glib::build_filename (template_dir_path, template_name + template_suffix);
2244 SessionSaveUnderway (); /* EMIT SIGNAL */
2249 PBD::Unwinder<std::string> uw (_template_state_dir, template_dir_path);
2250 tree.set_root (&get_template());
2253 if (!tree.write (template_file_path)) {
2254 error << _("template not saved") << endmsg;
2258 store_recent_templates (template_file_path);
2264 Session::refresh_disk_space ()
2266 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2268 Glib::Threads::Mutex::Lock lm (space_lock);
2270 /* get freespace on every FS that is part of the session path */
2272 _total_free_4k_blocks = 0;
2273 _total_free_4k_blocks_uncertain = false;
2275 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2277 struct statfs statfsbuf;
2278 statfs (i->path.c_str(), &statfsbuf);
2280 double const scale = statfsbuf.f_bsize / 4096.0;
2282 /* See if this filesystem is read-only */
2283 struct statvfs statvfsbuf;
2284 statvfs (i->path.c_str(), &statvfsbuf);
2286 /* f_bavail can be 0 if it is undefined for whatever
2287 filesystem we are looking at; Samba shares mounted
2288 via GVFS are an example of this.
2290 if (statfsbuf.f_bavail == 0) {
2291 /* block count unknown */
2293 i->blocks_unknown = true;
2294 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2295 /* read-only filesystem */
2297 i->blocks_unknown = false;
2299 /* read/write filesystem with known space */
2300 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2301 i->blocks_unknown = false;
2304 _total_free_4k_blocks += i->blocks;
2305 if (i->blocks_unknown) {
2306 _total_free_4k_blocks_uncertain = true;
2309 #elif defined PLATFORM_WINDOWS
2310 vector<string> scanned_volumes;
2311 vector<string>::iterator j;
2312 vector<space_and_path>::iterator i;
2313 DWORD nSectorsPerCluster, nBytesPerSector,
2314 nFreeClusters, nTotalClusters;
2318 _total_free_4k_blocks = 0;
2320 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2321 strncpy (disk_drive, (*i).path.c_str(), 3);
2325 volume_found = false;
2326 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2328 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2329 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2330 i->blocks = (uint32_t)(nFreeBytes / 4096);
2332 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2333 if (0 == j->compare(disk_drive)) {
2334 volume_found = true;
2339 if (!volume_found) {
2340 scanned_volumes.push_back(disk_drive);
2341 _total_free_4k_blocks += i->blocks;
2346 if (0 == _total_free_4k_blocks) {
2347 strncpy (disk_drive, path().c_str(), 3);
2350 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2352 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2353 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2354 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2361 Session::get_best_session_directory_for_new_audio ()
2363 vector<space_and_path>::iterator i;
2364 string result = _session_dir->root_path();
2366 /* handle common case without system calls */
2368 if (session_dirs.size() == 1) {
2372 /* OK, here's the algorithm we're following here:
2374 We want to select which directory to use for
2375 the next file source to be created. Ideally,
2376 we'd like to use a round-robin process so as to
2377 get maximum performance benefits from splitting
2378 the files across multiple disks.
2380 However, in situations without much diskspace, an
2381 RR approach may end up filling up a filesystem
2382 with new files while others still have space.
2383 Its therefore important to pay some attention to
2384 the freespace in the filesystem holding each
2385 directory as well. However, if we did that by
2386 itself, we'd keep creating new files in the file
2387 system with the most space until it was as full
2388 as all others, thus negating any performance
2389 benefits of this RAID-1 like approach.
2391 So, we use a user-configurable space threshold. If
2392 there are at least 2 filesystems with more than this
2393 much space available, we use RR selection between them.
2394 If not, then we pick the filesystem with the most space.
2396 This gets a good balance between the two
2400 refresh_disk_space ();
2402 int free_enough = 0;
2404 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2405 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2410 if (free_enough >= 2) {
2411 /* use RR selection process, ensuring that the one
2415 i = last_rr_session_dir;
2418 if (++i == session_dirs.end()) {
2419 i = session_dirs.begin();
2422 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2423 SessionDirectory sdir(i->path);
2424 if (sdir.create ()) {
2426 last_rr_session_dir = i;
2431 } while (i != last_rr_session_dir);
2435 /* pick FS with the most freespace (and that
2436 seems to actually work ...)
2439 vector<space_and_path> sorted;
2440 space_and_path_ascending_cmp cmp;
2442 sorted = session_dirs;
2443 sort (sorted.begin(), sorted.end(), cmp);
2445 for (i = sorted.begin(); i != sorted.end(); ++i) {
2446 SessionDirectory sdir(i->path);
2447 if (sdir.create ()) {
2449 last_rr_session_dir = i;
2459 Session::automation_dir () const
2461 return Glib::build_filename (_path, automation_dir_name);
2465 Session::analysis_dir () const
2467 return Glib::build_filename (_path, analysis_dir_name);
2471 Session::plugins_dir () const
2473 return Glib::build_filename (_path, plugins_dir_name);
2477 Session::externals_dir () const
2479 return Glib::build_filename (_path, externals_dir_name);
2483 Session::load_bundles (XMLNode const & node)
2485 XMLNodeList nlist = node.children();
2486 XMLNodeConstIterator niter;
2490 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2491 if ((*niter)->name() == "InputBundle") {
2492 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2493 } else if ((*niter)->name() == "OutputBundle") {
2494 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2496 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2505 Session::load_route_groups (const XMLNode& node, int version)
2507 XMLNodeList nlist = node.children();
2508 XMLNodeConstIterator niter;
2512 if (version >= 3000) {
2514 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2515 if ((*niter)->name() == "RouteGroup") {
2516 RouteGroup* rg = new RouteGroup (*this, "");
2517 add_route_group (rg);
2518 rg->set_state (**niter, version);
2522 } else if (version < 3000) {
2524 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2525 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2526 RouteGroup* rg = new RouteGroup (*this, "");
2527 add_route_group (rg);
2528 rg->set_state (**niter, version);
2537 state_file_filter (const string &str, void* /*arg*/)
2539 return (str.length() > strlen(statefile_suffix) &&
2540 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2544 remove_end(string state)
2546 string statename(state);
2548 string::size_type start,end;
2549 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2550 statename = statename.substr (start+1);
2553 if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2554 end = statename.length();
2557 return string(statename.substr (0, end));
2561 Session::possible_states (string path)
2563 vector<string> states;
2564 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2566 transform(states.begin(), states.end(), states.begin(), remove_end);
2568 sort (states.begin(), states.end());
2574 Session::possible_states () const
2576 return possible_states(_path);
2580 Session::add_route_group (RouteGroup* g)
2582 _route_groups.push_back (g);
2583 route_group_added (g); /* EMIT SIGNAL */
2585 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2586 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2587 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2593 Session::remove_route_group (RouteGroup& rg)
2595 list<RouteGroup*>::iterator i;
2597 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2598 _route_groups.erase (i);
2601 route_group_removed (); /* EMIT SIGNAL */
2605 /** Set a new order for our route groups, without adding or removing any.
2606 * @param groups Route group list in the new order.
2609 Session::reorder_route_groups (list<RouteGroup*> groups)
2611 _route_groups = groups;
2613 route_groups_reordered (); /* EMIT SIGNAL */
2619 Session::route_group_by_name (string name)
2621 list<RouteGroup *>::iterator i;
2623 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2624 if ((*i)->name() == name) {
2632 Session::all_route_group() const
2634 return *_all_route_group;
2638 Session::add_commands (vector<Command*> const & cmds)
2640 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2646 Session::add_command (Command* const cmd)
2648 assert (_current_trans);
2649 DEBUG_UNDO_HISTORY (
2650 string_compose ("Current Undo Transaction %1, adding command: %2",
2651 _current_trans->name (),
2653 _current_trans->add_command (cmd);
2656 PBD::StatefulDiffCommand*
2657 Session::add_stateful_diff_command (boost::shared_ptr<PBD::StatefulDestructible> sfd)
2659 PBD::StatefulDiffCommand* cmd = new PBD::StatefulDiffCommand (sfd);
2665 Session::begin_reversible_command (const string& name)
2667 begin_reversible_command (g_quark_from_string (name.c_str ()));
2670 /** Begin a reversible command using a GQuark to identify it.
2671 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2672 * but there must be as many begin...()s as there are commit...()s.
2675 Session::begin_reversible_command (GQuark q)
2677 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2678 to hold all the commands that are committed. This keeps the order of
2679 commands correct in the history.
2682 if (_current_trans == 0) {
2683 DEBUG_UNDO_HISTORY (string_compose (
2684 "Begin Reversible Command, new transaction: %1", g_quark_to_string (q)));
2686 /* start a new transaction */
2687 assert (_current_trans_quarks.empty ());
2688 _current_trans = new UndoTransaction();
2689 _current_trans->set_name (g_quark_to_string (q));
2691 DEBUG_UNDO_HISTORY (
2692 string_compose ("Begin Reversible Command, current transaction: %1",
2693 _current_trans->name ()));
2696 _current_trans_quarks.push_front (q);
2700 Session::abort_reversible_command ()
2702 if (_current_trans != 0) {
2703 DEBUG_UNDO_HISTORY (
2704 string_compose ("Abort Reversible Command: %1", _current_trans->name ()));
2705 _current_trans->clear();
2706 delete _current_trans;
2708 _current_trans_quarks.clear();
2713 Session::commit_reversible_command (Command *cmd)
2715 assert (_current_trans);
2716 assert (!_current_trans_quarks.empty ());
2721 DEBUG_UNDO_HISTORY (
2722 string_compose ("Current Undo Transaction %1, adding command: %2",
2723 _current_trans->name (),
2725 _current_trans->add_command (cmd);
2728 DEBUG_UNDO_HISTORY (
2729 string_compose ("Commit Reversible Command, current transaction: %1",
2730 _current_trans->name ()));
2732 _current_trans_quarks.pop_front ();
2734 if (!_current_trans_quarks.empty ()) {
2735 DEBUG_UNDO_HISTORY (
2736 string_compose ("Commit Reversible Command, transaction is not "
2737 "top-level, current transaction: %1",
2738 _current_trans->name ()));
2739 /* the transaction we're committing is not the top-level one */
2743 if (_current_trans->empty()) {
2744 /* no commands were added to the transaction, so just get rid of it */
2745 DEBUG_UNDO_HISTORY (
2746 string_compose ("Commit Reversible Command, No commands were "
2747 "added to current transaction: %1",
2748 _current_trans->name ()));
2749 delete _current_trans;
2754 gettimeofday (&now, 0);
2755 _current_trans->set_timestamp (now);
2757 _history.add (_current_trans);
2762 accept_all_audio_files (const string& path, void* /*arg*/)
2764 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2768 if (!AudioFileSource::safe_audio_file_extension (path)) {
2776 accept_all_midi_files (const string& path, void* /*arg*/)
2778 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2782 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2783 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2784 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2788 accept_all_state_files (const string& path, void* /*arg*/)
2790 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2794 std::string const statefile_ext (statefile_suffix);
2795 if (path.length() >= statefile_ext.length()) {
2796 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2803 Session::find_all_sources (string path, set<string>& result)
2808 if (!tree.read (path)) {
2812 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2817 XMLNodeConstIterator niter;
2819 nlist = node->children();
2823 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2825 XMLProperty const * prop;
2827 if ((prop = (*niter)->property (X_("type"))) == 0) {
2831 DataType type (prop->value());
2833 if ((prop = (*niter)->property (X_("name"))) == 0) {
2837 if (Glib::path_is_absolute (prop->value())) {
2838 /* external file, ignore */
2846 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2847 result.insert (found_path);
2855 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2857 vector<string> state_files;
2859 string this_snapshot_path;
2865 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2866 ripped = ripped.substr (0, ripped.length() - 1);
2869 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2871 if (state_files.empty()) {
2876 this_snapshot_path = _path;
2877 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2878 this_snapshot_path += statefile_suffix;
2880 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2882 if (exclude_this_snapshot && *i == this_snapshot_path) {
2886 if (find_all_sources (*i, result) < 0) {
2894 struct RegionCounter {
2895 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2896 AudioSourceList::iterator iter;
2897 boost::shared_ptr<Region> region;
2900 RegionCounter() : count (0) {}
2904 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2906 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2907 return r.get_value_or (1);
2911 Session::cleanup_regions ()
2913 bool removed = false;
2914 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2916 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2918 uint32_t used = playlists->region_use_count (i->second);
2920 if (used == 0 && !i->second->automatic ()) {
2921 boost::weak_ptr<Region> w = i->second;
2924 RegionFactory::map_remove (w);
2931 // re-check to remove parent references of compound regions
2932 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2933 if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2937 assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2938 if (0 == playlists->region_use_count (i->second)) {
2939 boost::weak_ptr<Region> w = i->second;
2941 RegionFactory::map_remove (w);
2948 /* dump the history list */
2955 Session::can_cleanup_peakfiles () const
2957 if (deletion_in_progress()) {
2960 if (!_writable || (_state_of_the_state & CannotSave)) {
2961 warning << _("Cannot cleanup peak-files for read-only session.") << endmsg;
2964 if (record_status() == Recording) {
2965 error << _("Cannot cleanup peak-files while recording") << endmsg;
2972 Session::cleanup_peakfiles ()
2974 Glib::Threads::Mutex::Lock lm (peak_cleanup_lock, Glib::Threads::TRY_LOCK);
2979 assert (can_cleanup_peakfiles ());
2980 assert (!peaks_cleanup_in_progres());
2982 _state_of_the_state = StateOfTheState (_state_of_the_state | PeakCleanup);
2984 int timeout = 5000; // 5 seconds
2985 while (!SourceFactory::files_with_peaks.empty()) {
2986 Glib::usleep (1000);
2987 if (--timeout < 0) {
2988 warning << _("Timeout waiting for peak-file creation to terminate before cleanup, please try again later.") << endmsg;
2989 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
2994 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2995 boost::shared_ptr<AudioSource> as;
2996 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
2997 as->close_peakfile();
3001 PBD::clear_directory (session_directory().peak_path());
3003 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
3005 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3006 boost::shared_ptr<AudioSource> as;
3007 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
3008 SourceFactory::setup_peakfile(as, true);
3015 Session::cleanup_sources (CleanupReport& rep)
3017 // FIXME: needs adaptation to midi
3019 vector<boost::shared_ptr<Source> > dead_sources;
3022 vector<string> candidates;
3023 vector<string> unused;
3024 set<string> all_sources;
3033 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
3035 /* this is mostly for windows which doesn't allow file
3036 * renaming if the file is in use. But we don't special
3037 * case it because we need to know if this causes
3038 * problems, and the easiest way to notice that is to
3039 * keep it in place for all platforms.
3042 request_stop (false);
3044 _butler->wait_until_finished ();
3046 /* consider deleting all unused playlists */
3048 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
3053 /* sync the "all regions" property of each playlist with its current state
3056 playlists->sync_all_regions_with_regions ();
3058 /* find all un-used sources */
3063 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3065 SourceMap::iterator tmp;
3070 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
3074 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
3075 dead_sources.push_back (i->second);
3076 i->second->drop_references ();
3082 /* build a list of all the possible audio directories for the session */
3084 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3085 SessionDirectory sdir ((*i).path);
3086 asp += sdir.sound_path();
3088 audio_path += asp.to_string();
3091 /* build a list of all the possible midi directories for the session */
3093 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3094 SessionDirectory sdir ((*i).path);
3095 msp += sdir.midi_path();
3097 midi_path += msp.to_string();
3099 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
3100 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
3102 /* find all sources, but don't use this snapshot because the
3103 state file on disk still references sources we may have already
3107 find_all_sources_across_snapshots (all_sources, true);
3109 /* add our current source list
3112 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3113 boost::shared_ptr<FileSource> fs;
3114 SourceMap::iterator tmp = i;
3117 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
3119 /* this is mostly for windows which doesn't allow file
3120 * renaming if the file is in use. But we don't special
3121 * case it because we need to know if this causes
3122 * problems, and the easiest way to notice that is to
3123 * keep it in place for all platforms.
3128 if (!fs->is_stub()) {
3130 if (playlists->source_use_count (fs) != 0) {
3131 all_sources.insert (fs->path());
3134 /* we might not remove this source from disk, because it may be used
3135 by other snapshots, but its not being used in this version
3136 so lets get rid of it now, along with any representative regions
3140 RegionFactory::remove_regions_using_source (i->second);
3142 // also remove source from all_sources
3144 for (set<string>::iterator j = all_sources.begin(); j != all_sources.end(); ++j) {
3145 spath = Glib::path_get_basename (*j);
3146 if (spath == i->second->name()) {
3147 all_sources.erase (j);
3160 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
3165 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
3167 tmppath1 = canonical_path (spath);
3168 tmppath2 = canonical_path ((*i));
3170 if (tmppath1 == tmppath2) {
3177 unused.push_back (spath);
3181 /* now try to move all unused files into the "dead" directory(ies) */
3183 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
3188 /* don't move the file across filesystems, just
3189 stick it in the `dead_dir_name' directory
3190 on whichever filesystem it was already on.
3193 if ((*x).find ("/sounds/") != string::npos) {
3195 /* old school, go up 1 level */
3197 newpath = Glib::path_get_dirname (*x); // "sounds"
3198 newpath = Glib::path_get_dirname (newpath); // "session-name"
3202 /* new school, go up 4 levels */
3204 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
3205 newpath = Glib::path_get_dirname (newpath); // "session-name"
3206 newpath = Glib::path_get_dirname (newpath); // "interchange"
3207 newpath = Glib::path_get_dirname (newpath); // "session-dir"
3210 newpath = Glib::build_filename (newpath, dead_dir_name);
3212 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
3213 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
3217 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
3219 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
3221 /* the new path already exists, try versioning */
3223 char buf[PATH_MAX+1];
3227 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3230 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
3231 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3235 if (version == 999) {
3236 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3240 newpath = newpath_v;
3245 /* it doesn't exist, or we can't read it or something */
3249 g_stat ((*x).c_str(), &statbuf);
3251 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3252 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
3253 (*x), newpath, strerror (errno))
3258 /* see if there an easy to find peakfile for this file, and remove it.
3261 string base = Glib::path_get_basename (*x);
3262 base += "%A"; /* this is what we add for the channel suffix of all native files,
3263 or for the first channel of embedded files. it will miss
3264 some peakfiles for other channels
3266 string peakpath = construct_peak_filepath (base);
3268 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
3269 if (::g_unlink (peakpath.c_str()) != 0) {
3270 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3271 peakpath, _path, strerror (errno))
3273 /* try to back out */
3274 ::rename (newpath.c_str(), _path.c_str());
3279 rep.paths.push_back (*x);
3280 rep.space += statbuf.st_size;
3283 /* dump the history list */
3287 /* save state so we don't end up a session file
3288 referring to non-existent sources.
3295 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3301 Session::cleanup_trash_sources (CleanupReport& rep)
3303 // FIXME: needs adaptation for MIDI
3305 vector<space_and_path>::iterator i;
3311 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3313 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
3315 clear_directory (dead_dir, &rep.space, &rep.paths);
3322 Session::set_dirty ()
3324 /* never mark session dirty during loading */
3326 if (_state_of_the_state & Loading) {
3330 bool was_dirty = dirty();
3332 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3336 DirtyChanged(); /* EMIT SIGNAL */
3342 Session::set_clean ()
3344 bool was_dirty = dirty();
3346 _state_of_the_state = Clean;
3350 DirtyChanged(); /* EMIT SIGNAL */
3355 Session::set_deletion_in_progress ()
3357 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3361 Session::clear_deletion_in_progress ()
3363 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3367 Session::add_controllable (boost::shared_ptr<Controllable> c)
3369 /* this adds a controllable to the list managed by the Session.
3370 this is a subset of those managed by the Controllable class
3371 itself, and represents the only ones whose state will be saved
3372 as part of the session.
3375 Glib::Threads::Mutex::Lock lm (controllables_lock);
3376 controllables.insert (c);
3379 struct null_deleter { void operator()(void const *) const {} };
3382 Session::remove_controllable (Controllable* c)
3384 if (_state_of_the_state & Deletion) {
3388 Glib::Threads::Mutex::Lock lm (controllables_lock);
3390 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3392 if (x != controllables.end()) {
3393 controllables.erase (x);
3397 boost::shared_ptr<Controllable>
3398 Session::controllable_by_id (const PBD::ID& id)
3400 Glib::Threads::Mutex::Lock lm (controllables_lock);
3402 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3403 if ((*i)->id() == id) {
3408 return boost::shared_ptr<Controllable>();
3411 boost::shared_ptr<Controllable>
3412 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3414 boost::shared_ptr<Controllable> c;
3415 boost::shared_ptr<Stripable> s;
3416 boost::shared_ptr<Route> r;
3418 switch (desc.top_level_type()) {
3419 case ControllableDescriptor::NamedRoute:
3421 std::string str = desc.top_level_name();
3423 if (str == "Master" || str == "master") {
3425 } else if (str == "control" || str == "listen" || str == "monitor" || str == "Monitor") {
3427 } else if (str == "auditioner") {
3430 s = route_by_name (desc.top_level_name());
3436 case ControllableDescriptor::PresentationOrderRoute:
3437 s = get_remote_nth_stripable (desc.presentation_order(), PresentationInfo::Route);
3440 case ControllableDescriptor::PresentationOrderTrack:
3441 s = get_remote_nth_stripable (desc.presentation_order(), PresentationInfo::Track);
3444 case ControllableDescriptor::PresentationOrderBus:
3445 s = get_remote_nth_stripable (desc.presentation_order(), PresentationInfo::Bus);
3448 case ControllableDescriptor::PresentationOrderVCA:
3449 s = get_remote_nth_stripable (desc.presentation_order(), PresentationInfo::VCA);
3452 case ControllableDescriptor::SelectionCount:
3453 s = route_by_selected_count (desc.selection_id());
3461 r = boost::dynamic_pointer_cast<Route> (s);
3463 switch (desc.subtype()) {
3464 case ControllableDescriptor::Gain:
3465 c = s->gain_control ();
3468 case ControllableDescriptor::Trim:
3469 c = s->trim_control ();
3472 case ControllableDescriptor::Solo:
3473 c = s->solo_control();
3476 case ControllableDescriptor::Mute:
3477 c = s->mute_control();
3480 case ControllableDescriptor::Recenable:
3481 c = s->rec_enable_control ();
3484 case ControllableDescriptor::PanDirection:
3485 c = s->pan_azimuth_control();
3488 case ControllableDescriptor::PanWidth:
3489 c = s->pan_width_control();
3492 case ControllableDescriptor::PanElevation:
3493 c = s->pan_elevation_control();
3496 case ControllableDescriptor::Balance:
3497 /* XXX simple pan control */
3500 case ControllableDescriptor::PluginParameter:
3502 uint32_t plugin = desc.target (0);
3503 uint32_t parameter_index = desc.target (1);
3505 /* revert to zero based counting */
3511 if (parameter_index > 0) {
3519 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3522 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3523 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3528 case ControllableDescriptor::SendGain: {
3529 uint32_t send = desc.target (0);
3536 c = r->send_level_controllable (send);
3541 /* relax and return a null pointer */
3549 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3552 Stateful::add_instant_xml (node, _path);
3555 if (write_to_config) {
3556 Config->add_instant_xml (node);
3561 Session::instant_xml (const string& node_name)
3563 return Stateful::instant_xml (node_name, _path);
3567 Session::save_history (string snapshot_name)
3575 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3576 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3580 if (snapshot_name.empty()) {
3581 snapshot_name = _current_snapshot_name;
3584 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3585 const string backup_filename = history_filename + backup_suffix;
3586 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3587 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3589 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3590 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3591 error << _("could not backup old history file, current history not saved") << endmsg;
3596 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3598 if (!tree.write (xml_path))
3600 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3602 if (g_remove (xml_path.c_str()) != 0) {
3603 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3604 xml_path, g_strerror (errno)) << endmsg;
3606 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3607 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3608 backup_path, g_strerror (errno)) << endmsg;
3618 Session::restore_history (string snapshot_name)
3622 if (snapshot_name.empty()) {
3623 snapshot_name = _current_snapshot_name;
3626 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3627 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3629 info << "Loading history from " << xml_path << endmsg;
3631 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3632 info << string_compose (_("%1: no history file \"%2\" for this session."),
3633 _name, xml_path) << endmsg;
3637 if (!tree.read (xml_path)) {
3638 error << string_compose (_("Could not understand session history file \"%1\""),
3639 xml_path) << endmsg;
3646 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3649 UndoTransaction* ut = new UndoTransaction ();
3652 ut->set_name(t->property("name")->value());
3653 stringstream ss(t->property("tv-sec")->value());
3655 ss.str(t->property("tv-usec")->value());
3657 ut->set_timestamp(tv);
3659 for (XMLNodeConstIterator child_it = t->children().begin();
3660 child_it != t->children().end(); child_it++)
3662 XMLNode *n = *child_it;
3665 if (n->name() == "MementoCommand" ||
3666 n->name() == "MementoUndoCommand" ||
3667 n->name() == "MementoRedoCommand") {
3669 if ((c = memento_command_factory(n))) {
3673 } else if (n->name() == "NoteDiffCommand") {
3674 PBD::ID id (n->property("midi-source")->value());
3675 boost::shared_ptr<MidiSource> midi_source =
3676 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3678 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3680 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3683 } else if (n->name() == "SysExDiffCommand") {
3685 PBD::ID id (n->property("midi-source")->value());
3686 boost::shared_ptr<MidiSource> midi_source =
3687 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3689 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3691 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3694 } else if (n->name() == "PatchChangeDiffCommand") {
3696 PBD::ID id (n->property("midi-source")->value());
3697 boost::shared_ptr<MidiSource> midi_source =
3698 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3700 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3702 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3705 } else if (n->name() == "StatefulDiffCommand") {
3706 if ((c = stateful_diff_command_factory (n))) {
3707 ut->add_command (c);
3710 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3721 Session::config_changed (std::string p, bool ours)
3727 if (p == "seamless-loop") {
3729 } else if (p == "rf-speed") {
3731 } else if (p == "auto-loop") {
3733 } else if (p == "auto-input") {
3735 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3736 /* auto-input only makes a difference if we're rolling */
3737 set_track_monitor_input_status (!config.get_auto_input());
3740 } else if (p == "punch-in") {
3744 if ((location = _locations->auto_punch_location()) != 0) {
3746 if (config.get_punch_in ()) {
3747 replace_event (SessionEvent::PunchIn, location->start());
3749 remove_event (location->start(), SessionEvent::PunchIn);
3753 } else if (p == "punch-out") {
3757 if ((location = _locations->auto_punch_location()) != 0) {
3759 if (config.get_punch_out()) {
3760 replace_event (SessionEvent::PunchOut, location->end());
3762 clear_events (SessionEvent::PunchOut);
3766 } else if (p == "edit-mode") {
3768 Glib::Threads::Mutex::Lock lm (playlists->lock);
3770 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3771 (*i)->set_edit_mode (Config->get_edit_mode ());
3774 } else if (p == "use-video-sync") {
3776 waiting_for_sync_offset = config.get_use_video_sync();
3778 } else if (p == "mmc-control") {
3780 //poke_midi_thread ();
3782 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3784 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3786 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3788 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3790 } else if (p == "midi-control") {
3792 //poke_midi_thread ();
3794 } else if (p == "raid-path") {
3796 setup_raid_path (config.get_raid_path());
3798 } else if (p == "timecode-format") {
3802 } else if (p == "video-pullup") {
3806 } else if (p == "seamless-loop") {
3808 if (play_loop && transport_rolling()) {
3809 // to reset diskstreams etc
3810 request_play_loop (true);
3813 } else if (p == "rf-speed") {
3815 cumulative_rf_motion = 0;
3818 } else if (p == "click-sound") {
3820 setup_click_sounds (1);
3822 } else if (p == "click-emphasis-sound") {
3824 setup_click_sounds (-1);
3826 } else if (p == "clicking") {
3828 if (Config->get_clicking()) {
3829 if (_click_io && click_data) { // don't require emphasis data
3836 } else if (p == "click-gain") {
3839 _click_gain->gain_control()->set_value (Config->get_click_gain(), Controllable::NoGroup);
3842 } else if (p == "send-mtc") {
3844 if (Config->get_send_mtc ()) {
3845 /* mark us ready to send */
3846 next_quarter_frame_to_send = 0;
3849 } else if (p == "send-mmc") {
3851 _mmc->enable_send (Config->get_send_mmc ());
3853 } else if (p == "midi-feedback") {
3855 session_midi_feedback = Config->get_midi_feedback();
3857 } else if (p == "jack-time-master") {
3859 engine().reset_timebase ();
3861 } else if (p == "native-file-header-format") {
3863 if (!first_file_header_format_reset) {
3864 reset_native_file_format ();
3867 first_file_header_format_reset = false;
3869 } else if (p == "native-file-data-format") {
3871 if (!first_file_data_format_reset) {
3872 reset_native_file_format ();
3875 first_file_data_format_reset = false;
3877 } else if (p == "external-sync") {
3878 if (!config.get_external_sync()) {
3879 drop_sync_source ();
3881 switch_to_sync_source (Config->get_sync_source());
3883 } else if (p == "denormal-model") {
3885 } else if (p == "history-depth") {
3886 set_history_depth (Config->get_history_depth());
3887 } else if (p == "remote-model") {
3888 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3891 } else if (p == "initial-program-change") {
3893 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3896 buf[0] = MIDI::program; // channel zero by default
3897 buf[1] = (Config->get_initial_program_change() & 0x7f);
3899 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3901 } else if (p == "solo-mute-override") {
3902 // catch_up_on_solo_mute_override ();
3903 } else if (p == "listen-position" || p == "pfl-position") {
3904 listen_position_changed ();
3905 } else if (p == "solo-control-is-listen-control") {
3906 solo_control_mode_changed ();
3907 } else if (p == "solo-mute-gain") {
3908 _solo_cut_control->Changed (true, Controllable::NoGroup);
3909 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3910 last_timecode_valid = false;
3911 } else if (p == "playback-buffer-seconds") {
3912 AudioSource::allocate_working_buffers (frame_rate());
3913 } else if (p == "ltc-source-port") {
3914 reconnect_ltc_input ();
3915 } else if (p == "ltc-sink-port") {
3916 reconnect_ltc_output ();
3917 } else if (p == "timecode-generator-offset") {
3918 ltc_tx_parse_offset();
3919 } else if (p == "auto-return-target-list") {
3920 follow_playhead_priority ();
3927 Session::set_history_depth (uint32_t d)
3929 _history.set_depth (d);
3933 Session::load_diskstreams_2X (XMLNode const & node, int)
3936 XMLNodeConstIterator citer;
3938 clist = node.children();
3940 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3943 /* diskstreams added automatically by DiskstreamCreated handler */
3944 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3945 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3946 _diskstreams_2X.push_back (dsp);
3948 error << _("Session: unknown diskstream type in XML") << endmsg;
3952 catch (failed_constructor& err) {
3953 error << _("Session: could not load diskstream via XML state") << endmsg;
3961 /** Connect things to the MMC object */
3963 Session::setup_midi_machine_control ()
3965 _mmc = new MIDI::MachineControl;
3967 boost::shared_ptr<AsyncMIDIPort> async_in = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_input_port());
3968 boost::shared_ptr<AsyncMIDIPort> async_out = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_output_port());
3970 if (!async_out || !async_out) {
3974 /* XXXX argh, passing raw pointers back into libmidi++ */
3976 MIDI::Port* mmc_in = async_in.get();
3977 MIDI::Port* mmc_out = async_out.get();
3979 _mmc->set_ports (mmc_in, mmc_out);
3981 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3982 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3983 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3984 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3985 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3986 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3987 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3988 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3989 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3990 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3991 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3992 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3993 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3995 /* also handle MIDI SPP because its so common */
3997 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3998 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3999 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
4002 boost::shared_ptr<Controllable>
4003 Session::solo_cut_control() const
4005 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
4006 controls in Ardour that currently get presented to the user in the GUI that require
4007 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
4009 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
4010 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
4014 return _solo_cut_control;
4018 Session::save_snapshot_name (const std::string & n)
4020 /* assure Stateful::_instant_xml is loaded
4021 * add_instant_xml() only adds to existing data and defaults
4022 * to use an empty Tree otherwise
4024 instant_xml ("LastUsedSnapshot");
4026 XMLNode* last_used_snapshot = new XMLNode ("LastUsedSnapshot");
4027 last_used_snapshot->add_property ("name", string(n));
4028 add_instant_xml (*last_used_snapshot, false);
4032 Session::set_snapshot_name (const std::string & n)
4034 _current_snapshot_name = n;
4035 save_snapshot_name (n);
4039 Session::rename (const std::string& new_name)
4041 string legal_name = legalize_for_path (new_name);
4047 string const old_sources_root = _session_dir->sources_root();
4049 if (!_writable || (_state_of_the_state & CannotSave)) {
4050 error << _("Cannot rename read-only session.") << endmsg;
4051 return 0; // don't show "messed up" warning
4053 if (record_status() == Recording) {
4054 error << _("Cannot rename session while recording") << endmsg;
4055 return 0; // don't show "messed up" warning
4058 StateProtector stp (this);
4063 * interchange subdirectory
4067 * Backup files are left unchanged and not renamed.
4070 /* Windows requires that we close all files before attempting the
4071 * rename. This works on other platforms, but isn't necessary there.
4072 * Leave it in place for all platforms though, since it may help
4073 * catch issues that could arise if the way Source files work ever
4074 * change (since most developers are not using Windows).
4077 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4078 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4084 /* pass one: not 100% safe check that the new directory names don't
4088 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4092 /* this is a stupid hack because Glib::path_get_dirname() is
4093 * lexical-only, and so passing it /a/b/c/ gives a different
4094 * result than passing it /a/b/c ...
4097 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4098 oldstr = oldstr.substr (0, oldstr.length() - 1);
4101 string base = Glib::path_get_dirname (oldstr);
4103 newstr = Glib::build_filename (base, legal_name);
4105 cerr << "Looking for " << newstr << endl;
4107 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
4108 cerr << " exists\n";
4117 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4123 /* this is a stupid hack because Glib::path_get_dirname() is
4124 * lexical-only, and so passing it /a/b/c/ gives a different
4125 * result than passing it /a/b/c ...
4128 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4129 oldstr = oldstr.substr (0, oldstr.length() - 1);
4132 string base = Glib::path_get_dirname (oldstr);
4133 newstr = Glib::build_filename (base, legal_name);
4135 cerr << "for " << oldstr << " new dir = " << newstr << endl;
4137 cerr << "Rename " << oldstr << " => " << newstr << endl;
4138 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4139 cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4140 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4144 /* Reset path in "session dirs" */
4149 /* reset primary SessionDirectory object */
4152 (*_session_dir) = newstr;
4157 /* now rename directory below session_dir/interchange */
4159 string old_interchange_dir;
4160 string new_interchange_dir;
4162 /* use newstr here because we renamed the path
4163 * (folder/directory) that used to be oldstr to newstr above
4166 v.push_back (newstr);
4167 v.push_back (interchange_dir_name);
4168 v.push_back (Glib::path_get_basename (oldstr));
4170 old_interchange_dir = Glib::build_filename (v);
4173 v.push_back (newstr);
4174 v.push_back (interchange_dir_name);
4175 v.push_back (legal_name);
4177 new_interchange_dir = Glib::build_filename (v);
4179 cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
4181 if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
4182 cerr << string_compose (_("renaming %s as %2 failed (%3)"),
4183 old_interchange_dir, new_interchange_dir,
4186 error << string_compose (_("renaming %s as %2 failed (%3)"),
4187 old_interchange_dir, new_interchange_dir,
4196 oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
4197 newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
4199 cerr << "Rename " << oldstr << " => " << newstr << endl;
4201 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4202 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4203 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4209 oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
4211 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
4212 newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
4214 cerr << "Rename " << oldstr << " => " << newstr << endl;
4216 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4217 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4218 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4223 /* remove old name from recent sessions */
4224 remove_recent_sessions (_path);
4227 /* update file source paths */
4229 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
4230 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4232 string p = fs->path ();
4233 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
4235 SourceFactory::setup_peakfile(i->second, true);
4239 set_snapshot_name (new_name);
4244 /* save state again to get everything just right */
4246 save_state (_current_snapshot_name);
4248 /* add to recent sessions */
4250 store_recent_sessions (new_name, _path);
4256 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
4258 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
4262 if (!tree.read (xmlpath)) {
4270 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
4273 bool found_sr = false;
4274 bool found_data_format = false;
4276 if (get_session_info_from_path (tree, xmlpath)) {
4282 XMLProperty const * prop;
4283 XMLNode const * root (tree.root());
4285 if ((prop = root->property (X_("sample-rate"))) != 0) {
4286 sample_rate = atoi (prop->value());
4290 const XMLNodeList& children (root->children());
4291 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
4292 const XMLNode* child = *c;
4293 if (child->name() == "Config") {
4294 const XMLNodeList& options (child->children());
4295 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
4296 XMLNode const * option = *oc;
4297 XMLProperty const * name = option->property("name");
4303 if (name->value() == "native-file-data-format") {
4304 XMLProperty const * value = option->property ("value");
4306 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
4308 found_data_format = true;
4314 if (found_data_format) {
4319 return !(found_sr && found_data_format); // zero if they are both found
4323 Session::get_snapshot_from_instant (const std::string& session_dir)
4325 std::string instant_xml_path = Glib::build_filename (session_dir, "instant.xml");
4327 if (!Glib::file_test (instant_xml_path, Glib::FILE_TEST_EXISTS)) {
4332 if (!tree.read (instant_xml_path)) {
4336 XMLProperty const * prop;
4337 XMLNode *last_used_snapshot = tree.root()->child("LastUsedSnapshot");
4338 if (last_used_snapshot && (prop = last_used_snapshot->property ("name")) != 0) {
4339 return prop->value();
4345 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
4346 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
4349 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
4353 SourcePathMap source_path_map;
4355 boost::shared_ptr<AudioFileSource> afs;
4360 Glib::Threads::Mutex::Lock lm (source_lock);
4362 cerr << " total sources = " << sources.size();
4364 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4365 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4371 if (fs->within_session()) {
4375 if (source_path_map.find (fs->path()) != source_path_map.end()) {
4376 source_path_map[fs->path()].push_back (fs);
4378 SeveralFileSources v;
4380 source_path_map.insert (make_pair (fs->path(), v));
4386 cerr << " fsources = " << total << endl;
4388 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
4390 /* tell caller where we are */
4392 string old_path = i->first;
4394 callback (n, total, old_path);
4396 cerr << old_path << endl;
4400 switch (i->second.front()->type()) {
4401 case DataType::AUDIO:
4402 new_path = new_audio_source_path_for_embedded (old_path);
4405 case DataType::MIDI:
4406 /* XXX not implemented yet */
4410 if (new_path.empty()) {
4414 cerr << "Move " << old_path << " => " << new_path << endl;
4416 if (!copy_file (old_path, new_path)) {
4417 cerr << "failed !\n";
4421 /* make sure we stop looking in the external
4422 dir/folder. Remember, this is an all-or-nothing
4423 operations, it doesn't merge just some files.
4425 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
4427 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
4428 (*f)->set_path (new_path);
4433 save_state ("", false, false);
4439 bool accept_all_files (string const &, void *)
4445 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4447 /* 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.
4452 make_new_media_path (string old_path, string new_session_folder, string new_session_path)
4454 /* typedir is the "midifiles" or "audiofiles" etc. part of the path. */
4456 string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4458 v.push_back (new_session_folder); /* full path */
4459 v.push_back (interchange_dir_name);
4460 v.push_back (new_session_path); /* just one directory/folder */
4461 v.push_back (typedir);
4462 v.push_back (Glib::path_get_basename (old_path));
4464 return Glib::build_filename (v);
4468 Session::save_as (SaveAs& saveas)
4470 vector<string> files;
4471 string current_folder = Glib::path_get_dirname (_path);
4472 string new_folder = legalize_for_path (saveas.new_name);
4473 string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4474 int64_t total_bytes = 0;
4478 int32_t internal_file_cnt = 0;
4480 vector<string> do_not_copy_extensions;
4481 do_not_copy_extensions.push_back (statefile_suffix);
4482 do_not_copy_extensions.push_back (pending_suffix);
4483 do_not_copy_extensions.push_back (backup_suffix);
4484 do_not_copy_extensions.push_back (temp_suffix);
4485 do_not_copy_extensions.push_back (history_suffix);
4487 /* get total size */
4489 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4491 /* need to clear this because
4492 * find_files_matching_filter() is cumulative
4497 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4499 all += files.size();
4501 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4503 g_stat ((*i).c_str(), &gsb);
4504 total_bytes += gsb.st_size;
4508 /* save old values so we can switch back if we are not switching to the new session */
4510 string old_path = _path;
4511 string old_name = _name;
4512 string old_snapshot = _current_snapshot_name;
4513 string old_sd = _session_dir->root_path();
4514 vector<string> old_search_path[DataType::num_types];
4515 string old_config_search_path[DataType::num_types];
4517 old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4518 old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4519 old_config_search_path[DataType::AUDIO] = config.get_audio_search_path ();
4520 old_config_search_path[DataType::MIDI] = config.get_midi_search_path ();
4522 /* switch session directory */
4524 (*_session_dir) = to_dir;
4526 /* create new tree */
4528 if (!_session_dir->create()) {
4529 saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4534 /* copy all relevant files. Find each location in session_dirs,
4535 * and copy files from there to target.
4538 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4540 /* need to clear this because
4541 * find_files_matching_filter() is cumulative
4546 const size_t prefix_len = (*sd).path.size();
4548 /* Work just on the files within this session dir */
4550 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4552 /* add dir separator to protect against collisions with
4553 * track names (e.g. track named "audiofiles" or
4557 static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
4558 static const std::string midifile_dir_string = string (midi_dir_name) + G_DIR_SEPARATOR;
4559 static const std::string analysis_dir_string = analysis_dir() + G_DIR_SEPARATOR;
4561 /* copy all the files. Handling is different for media files
4562 than others because of the *silly* subtree we have below the interchange
4563 folder. That really was a bad idea, but I'm not fixing it as part of
4564 implementing ::save_as().
4567 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4569 std::string from = *i;
4572 string filename = Glib::path_get_basename (from);
4573 std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
4574 if (filename == ".DS_STORE") {
4579 if (from.find (audiofile_dir_string) != string::npos) {
4581 /* audio file: only copy if asked */
4583 if (saveas.include_media && saveas.copy_media) {
4585 string to = make_new_media_path (*i, to_dir, new_folder);
4587 info << "media file copying from " << from << " to " << to << endmsg;
4589 if (!copy_file (from, to)) {
4590 throw Glib::FileError (Glib::FileError::IO_ERROR,
4591 string_compose(_("\ncopying \"%1\" failed !"), from));
4595 /* we found media files inside the session folder */
4597 internal_file_cnt++;
4599 } else if (from.find (midifile_dir_string) != string::npos) {
4601 /* midi file: always copy unless
4602 * creating an empty new session
4605 if (saveas.include_media) {
4607 string to = make_new_media_path (*i, to_dir, new_folder);
4609 info << "media file copying from " << from << " to " << to << endmsg;
4611 if (!copy_file (from, to)) {
4612 throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4616 /* we found media files inside the session folder */
4618 internal_file_cnt++;
4620 } else if (from.find (analysis_dir_string) != string::npos) {
4622 /* make sure analysis dir exists in
4623 * new session folder, but we're not
4624 * copying analysis files here, see
4628 (void) g_mkdir_with_parents (analysis_dir().c_str(), 775);
4633 /* normal non-media file. Don't copy state, history, etc.
4636 bool do_copy = true;
4638 for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
4639 if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
4640 /* end of filename matches extension, do not copy file */
4646 if (!saveas.copy_media && from.find (peakfile_suffix) != string::npos) {
4647 /* don't copy peakfiles if
4648 * we're not copying media
4654 string to = Glib::build_filename (to_dir, from.substr (prefix_len));
4656 info << "attempting to make directory/folder " << to << endmsg;
4658 if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
4659 throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
4662 info << "attempting to copy " << from << " to " << to << endmsg;
4664 if (!copy_file (from, to)) {
4665 throw Glib::FileError (Glib::FileError::IO_ERROR,
4666 string_compose(_("\ncopying \"%1\" failed !"), from));
4671 /* measure file size even if we're not going to copy so that our Progress
4672 signals are correct, since we included these do-not-copy files
4673 in the computation of the total size and file count.
4677 g_stat (from.c_str(), &gsb);
4678 copied += gsb.st_size;
4681 double fraction = (double) copied / total_bytes;
4683 bool keep_going = true;
4685 if (saveas.copy_media) {
4687 /* no need or expectation of this if
4688 * media is not being copied, because
4689 * it will be fast(ish).
4692 /* tell someone "X percent, file M of N"; M is one-based */
4694 boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
4702 throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
4708 /* copy optional folders, if any */
4710 string old = plugins_dir ();
4711 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4712 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4713 copy_files (old, newdir);
4716 old = externals_dir ();
4717 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4718 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4719 copy_files (old, newdir);
4722 old = automation_dir ();
4723 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4724 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4725 copy_files (old, newdir);
4728 if (saveas.include_media) {
4730 if (saveas.copy_media) {
4731 #ifndef PLATFORM_WINDOWS
4732 /* There are problems with analysis files on
4733 * Windows, because they used a colon in their
4734 * names as late as 4.0. Colons are not legal
4735 * under Windows even if NTFS allows them.
4737 * This is a tricky problem to solve so for
4738 * just don't copy these files. They will be
4739 * regenerated as-needed anyway, subject to the
4740 * existing issue that the filenames will be
4741 * rejected by Windows, which is a separate
4742 * problem (though related).
4745 /* only needed if we are copying media, since the
4746 * analysis data refers to media data
4749 old = analysis_dir ();
4750 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4751 string newdir = Glib::build_filename (to_dir, "analysis");
4752 copy_files (old, newdir);
4754 #endif /* PLATFORM_WINDOWS */
4760 set_snapshot_name (saveas.new_name);
4761 _name = saveas.new_name;
4763 if (saveas.include_media && !saveas.copy_media) {
4765 /* reset search paths of the new session (which we're pretending to be right now) to
4766 include the original session search path, so we can still find all audio.
4769 if (internal_file_cnt) {
4770 for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
4771 ensure_search_path_includes (*s, DataType::AUDIO);
4772 cerr << "be sure to include " << *s << " for audio" << endl;
4775 /* we do not do this for MIDI because we copy
4776 all MIDI files if saveas.include_media is
4782 bool was_dirty = dirty ();
4784 save_state ("", false, false, !saveas.include_media);
4785 save_default_options ();
4787 if (saveas.copy_media && saveas.copy_external) {
4788 if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
4789 throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
4793 saveas.final_session_folder_name = _path;
4795 store_recent_sessions (_name, _path);
4797 if (!saveas.switch_to) {
4799 /* switch back to the way things were */
4803 set_snapshot_name (old_snapshot);
4805 (*_session_dir) = old_sd;
4811 if (internal_file_cnt) {
4812 /* reset these to their original values */
4813 config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
4814 config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
4819 /* prune session dirs, and update disk space statistics
4824 session_dirs.clear ();
4825 session_dirs.push_back (sp);
4826 refresh_disk_space ();
4828 /* ensure that all existing tracks reset their current capture source paths
4830 reset_write_sources (true, true);
4832 /* the copying above was based on actually discovering files, not just iterating over the sources list.
4833 But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
4836 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4837 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4843 if (fs->within_session()) {
4844 string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
4845 fs->set_path (newpath);
4850 } catch (Glib::FileError& e) {
4852 saveas.failure_message = e.what();
4854 /* recursively remove all the directories */
4856 remove_directory (to_dir);
4864 saveas.failure_message = _("unknown reason");
4866 /* recursively remove all the directories */
4868 remove_directory (to_dir);