2 Copyright (C) 1999-2013 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "libardour-config.h"
30 #include <cstdio> /* snprintf(3) ... grrr */
42 #include <sys/param.h>
43 #include <sys/mount.h>
46 #ifdef HAVE_SYS_STATVFS_H
47 #include <sys/statvfs.h>
51 #include "pbd/gstdio_compat.h"
54 #include <glibmm/threads.h>
55 #include <glibmm/fileutils.h>
57 #include <boost/algorithm/string.hpp>
59 #include "midi++/mmc.h"
60 #include "midi++/port.h"
62 #include "evoral/SMF.hpp"
64 #include "pbd/boost_debug.h"
65 #include "pbd/basename.h"
66 #include "pbd/controllable_descriptor.h"
67 #include "pbd/debug.h"
68 #include "pbd/enumwriter.h"
69 #include "pbd/error.h"
70 #include "pbd/file_utils.h"
71 #include "pbd/pathexpand.h"
72 #include "pbd/pthread_utils.h"
73 #include "pbd/stacktrace.h"
74 #include "pbd/convert.h"
75 #include "pbd/localtime_r.h"
76 #include "pbd/unwind.h"
78 #include "ardour/amp.h"
79 #include "ardour/async_midi_port.h"
80 #include "ardour/audio_diskstream.h"
81 #include "ardour/audio_track.h"
82 #include "ardour/audioengine.h"
83 #include "ardour/audiofilesource.h"
84 #include "ardour/audioregion.h"
85 #include "ardour/automation_control.h"
86 #include "ardour/butler.h"
87 #include "ardour/control_protocol_manager.h"
88 #include "ardour/directory_names.h"
89 #include "ardour/filename_extensions.h"
90 #include "ardour/graph.h"
91 #include "ardour/location.h"
92 #include "ardour/midi_model.h"
93 #include "ardour/midi_patch_manager.h"
94 #include "ardour/midi_region.h"
95 #include "ardour/midi_scene_changer.h"
96 #include "ardour/midi_source.h"
97 #include "ardour/midi_track.h"
98 #include "ardour/pannable.h"
99 #include "ardour/playlist_factory.h"
100 #include "ardour/playlist_source.h"
101 #include "ardour/port.h"
102 #include "ardour/processor.h"
103 #include "ardour/profile.h"
104 #include "ardour/proxy_controllable.h"
105 #include "ardour/recent_sessions.h"
106 #include "ardour/region_factory.h"
107 #include "ardour/route_group.h"
108 #include "ardour/send.h"
109 #include "ardour/session.h"
110 #include "ardour/session_directory.h"
111 #include "ardour/session_metadata.h"
112 #include "ardour/session_playlists.h"
113 #include "ardour/session_state_utils.h"
114 #include "ardour/silentfilesource.h"
115 #include "ardour/sndfilesource.h"
116 #include "ardour/source_factory.h"
117 #include "ardour/speakers.h"
118 #include "ardour/template_utils.h"
119 #include "ardour/tempo.h"
120 #include "ardour/ticker.h"
121 #include "ardour/user_bundle.h"
123 #include "control_protocol/control_protocol.h"
125 #include "LuaBridge/LuaBridge.h"
131 using namespace ARDOUR;
134 #define DEBUG_UNDO_HISTORY(msg) DEBUG_TRACE (PBD::DEBUG::UndoHistory, string_compose ("%1: %2\n", __LINE__, msg));
137 Session::pre_engine_init (string fullpath)
139 if (fullpath.empty()) {
141 throw failed_constructor();
144 /* discover canonical fullpath */
146 _path = canonical_path(fullpath);
149 if (Profile->get_trx() ) {
150 // Waves TracksLive has a usecase of session replacement with a new one.
151 // We should check session state file (<session_name>.ardour) existance
152 // to determine if the session is new or not
154 string full_session_name = Glib::build_filename( fullpath, _name );
155 full_session_name += statefile_suffix;
157 _is_new = !Glib::file_test (full_session_name, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
159 _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
162 /* finish initialization that can't be done in a normal C++ constructor
166 timerclear (&last_mmc_step);
167 g_atomic_int_set (&processing_prohibited, 0);
168 g_atomic_int_set (&_record_status, Disabled);
169 g_atomic_int_set (&_playback_load, 100);
170 g_atomic_int_set (&_capture_load, 100);
172 _all_route_group->set_active (true, this);
173 interpolation.add_channel_to (0, 0);
175 if (config.get_use_video_sync()) {
176 waiting_for_sync_offset = true;
178 waiting_for_sync_offset = false;
181 last_rr_session_dir = session_dirs.begin();
183 set_history_depth (Config->get_history_depth());
185 /* default: assume simple stereo speaker configuration */
187 _speakers->setup_default_speakers (2);
189 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
190 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
191 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
192 add_controllable (_solo_cut_control);
194 /* These are all static "per-class" signals */
196 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
197 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
198 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
199 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
200 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
202 /* stop IO objects from doing stuff until we're ready for them */
204 Delivery::disable_panners ();
205 IO::disable_connecting ();
209 Session::post_engine_init ()
211 BootMessage (_("Set block size and sample rate"));
213 set_block_size (_engine.samples_per_cycle());
214 set_frame_rate (_engine.sample_rate());
216 BootMessage (_("Using configuration"));
218 _midi_ports = new MidiPortManager;
220 MIDISceneChanger* msc;
222 _scene_changer = msc = new MIDISceneChanger (*this);
223 msc->set_input_port (boost::dynamic_pointer_cast<MidiPort>(scene_input_port()));
224 msc->set_output_port (boost::dynamic_pointer_cast<MidiPort>(scene_output_port()));
226 boost::function<framecnt_t(void)> timer_func (boost::bind (&Session::audible_frame, this));
227 boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_input_port())->set_timer (timer_func);
229 setup_midi_machine_control ();
231 if (_butler->start_thread()) {
235 if (start_midi_thread ()) {
239 setup_click_sounds (0);
240 setup_midi_control ();
242 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
243 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
246 /* tempo map requires sample rate knowledge */
249 _tempo_map = new TempoMap (_current_frame_rate);
250 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
252 /* MidiClock requires a tempo map */
255 midi_clock = new MidiClockTicker ();
256 midi_clock->set_session (this);
258 /* crossfades require sample rate knowledge */
260 SndFileSource::setup_standard_crossfades (*this, frame_rate());
261 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
263 AudioDiskstream::allocate_working_buffers();
264 refresh_disk_space ();
266 /* we're finally ready to call set_state() ... all objects have
267 * been created, the engine is running.
271 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
275 // set_state() will call setup_raid_path(), but if it's a new session we need
276 // to call setup_raid_path() here.
277 setup_raid_path (_path);
282 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
283 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
285 Config->map_parameters (ff);
286 config.map_parameters (ft);
287 _butler->map_parameters ();
289 /* Reset all panners */
291 Delivery::reset_panners ();
293 /* this will cause the CPM to instantiate any protocols that are in use
294 * (or mandatory), which will pass it this Session, and then call
295 * set_state() on each instantiated protocol to match stored state.
298 ControlProtocolManager::instance().set_session (this);
300 /* This must be done after the ControlProtocolManager set_session above,
301 as it will set states for ports which the ControlProtocolManager creates.
304 // XXX set state of MIDI::Port's
305 // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
307 /* And this must be done after the MIDI::Manager::set_port_states as
308 * it will try to make connections whose details are loaded by set_port_states.
313 /* Let control protocols know that we are now all connected, so they
314 * could start talking to surfaces if they want to.
317 ControlProtocolManager::instance().midi_connectivity_established ();
319 if (_is_new && !no_auto_connect()) {
320 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
321 auto_connect_master_bus ();
324 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
326 /* update latencies */
328 initialize_latencies ();
330 _locations->added.connect_same_thread (*this, boost::bind (&Session::location_added, this, _1));
331 _locations->removed.connect_same_thread (*this, boost::bind (&Session::location_removed, this, _1));
332 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
334 } catch (AudioEngine::PortRegistrationFailure& err) {
335 /* handle this one in a different way than all others, so that its clear what happened */
336 error << err.what() << endmsg;
342 BootMessage (_("Reset Remote Controls"));
344 // send_full_time_code (0);
345 _engine.transport_locate (0);
347 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
348 send_immediate_mmc (MIDI::MachineControlCommand (Timecode::Time ()));
350 MIDI::Name::MidiPatchManager::instance().add_search_path (session_directory().midi_patch_path() );
353 /* initial program change will be delivered later; see ::config_changed() */
355 _state_of_the_state = Clean;
357 Port::set_connecting_blocked (false);
359 DirtyChanged (); /* EMIT SIGNAL */
363 } else if (state_was_pending) {
365 remove_pending_capture_state ();
366 state_was_pending = false;
369 /* Now, finally, we can fill the playback buffers */
371 BootMessage (_("Filling playback buffers"));
373 boost::shared_ptr<RouteList> rl = routes.reader();
374 for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
375 boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<Track> (*r);
376 if (trk && !trk->hidden()) {
377 trk->seek (_transport_frame, true);
385 Session::session_loaded ()
389 _state_of_the_state = Clean;
391 DirtyChanged (); /* EMIT SIGNAL */
395 } else if (state_was_pending) {
397 remove_pending_capture_state ();
398 state_was_pending = false;
401 /* Now, finally, we can fill the playback buffers */
403 BootMessage (_("Filling playback buffers"));
404 force_locate (_transport_frame, false);
408 Session::raid_path () const
410 Searchpath raid_search_path;
412 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
413 raid_search_path += (*i).path;
416 return raid_search_path.to_string ();
420 Session::setup_raid_path (string path)
429 session_dirs.clear ();
431 Searchpath search_path(path);
432 Searchpath sound_search_path;
433 Searchpath midi_search_path;
435 for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
437 sp.blocks = 0; // not needed
438 session_dirs.push_back (sp);
440 SessionDirectory sdir(sp.path);
442 sound_search_path += sdir.sound_path ();
443 midi_search_path += sdir.midi_path ();
446 // reset the round-robin soundfile path thingie
447 last_rr_session_dir = session_dirs.begin();
451 Session::path_is_within_session (const std::string& path)
453 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
454 if (PBD::path_is_within (i->path, path)) {
462 Session::ensure_subdirs ()
466 dir = session_directory().peak_path();
468 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
469 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
473 dir = session_directory().sound_path();
475 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
476 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
480 dir = session_directory().midi_path();
482 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
483 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
487 dir = session_directory().dead_path();
489 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
490 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
494 dir = session_directory().export_path();
496 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
497 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
501 dir = analysis_dir ();
503 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
504 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
508 dir = plugins_dir ();
510 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
511 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
515 dir = externals_dir ();
517 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
518 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
525 /** @param session_template directory containing session template, or empty.
526 * Caller must not hold process lock.
529 Session::create (const string& session_template, BusProfile* bus_profile)
531 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
532 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
536 if (ensure_subdirs ()) {
540 _writable = exists_and_writable (_path);
542 if (!session_template.empty()) {
543 string in_path = (ARDOUR::Profile->get_trx () ? session_template : session_template_dir_to_file (session_template));
545 FILE* in = g_fopen (in_path.c_str(), "rb");
548 /* no need to call legalize_for_path() since the string
549 * in session_template is already a legal path name
551 string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
553 FILE* out = g_fopen (out_path.c_str(), "wb");
557 stringstream new_session;
560 size_t charsRead = fread (buf, sizeof(char), 1024, in);
563 error << string_compose (_("Error reading session template file %1 (%2)"), in_path, strerror (errno)) << endmsg;
568 if (charsRead == 0) {
571 new_session.write (buf, charsRead);
575 string file_contents = new_session.str();
576 size_t writeSize = file_contents.length();
577 if (fwrite (file_contents.c_str(), sizeof(char), writeSize, out) != writeSize) {
578 error << string_compose (_("Error writing session template file %1 (%2)"), out_path, strerror (errno)) << endmsg;
586 if (!ARDOUR::Profile->get_trx()) {
587 /* Copy plugin state files from template to new session */
588 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
589 copy_recurse (template_plugins, plugins_dir ());
595 error << string_compose (_("Could not open %1 for writing session template"), out_path)
602 error << string_compose (_("Could not open session template %1 for reading"), in_path)
609 if (Profile->get_trx()) {
611 /* set initial start + end point : ARDOUR::Session::session_end_shift long.
612 Remember that this is a brand new session. Sessions
613 loaded from saved state will get this range from the saved state.
616 set_session_range_location (0, 0);
618 /* Initial loop location, from absolute zero, length 10 seconds */
620 Location* loc = new Location (*this, 0, 10.0 * _engine.sample_rate(), _("Loop"), Location::IsAutoLoop);
621 _locations->add (loc, true);
622 set_auto_loop_location (loc);
625 _state_of_the_state = Clean;
627 /* set up Master Out and Control Out if necessary */
632 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
634 // Waves Tracks: always create master bus for Tracks
635 if (ARDOUR::Profile->get_trx() || bus_profile->master_out_channels) {
636 boost::shared_ptr<Route> r (new Route (*this, _("Master"), Route::MasterOut, DataType::AUDIO));
640 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
641 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
644 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
645 r->input()->ensure_io (count, false, this);
646 r->output()->ensure_io (count, false, this);
652 /* prohibit auto-connect to master, because there isn't one */
653 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
657 add_routes (rl, false, false, false);
660 // Waves Tracks: Skip this. Always use autoconnection for Tracks
661 if (!ARDOUR::Profile->get_trx()) {
663 /* this allows the user to override settings with an environment variable.
666 if (no_auto_connect()) {
667 bus_profile->input_ac = AutoConnectOption (0);
668 bus_profile->output_ac = AutoConnectOption (0);
671 Config->set_input_auto_connect (bus_profile->input_ac);
672 Config->set_output_auto_connect (bus_profile->output_ac);
676 if (Config->get_use_monitor_bus() && bus_profile) {
677 add_monitor_section ();
684 Session::maybe_write_autosave()
686 if (dirty() && record_status() != Recording) {
687 save_state("", true);
692 Session::remove_pending_capture_state ()
694 std::string pending_state_file_path(_session_dir->root_path());
696 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
698 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
700 if (g_remove (pending_state_file_path.c_str()) != 0) {
701 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
702 pending_state_file_path, g_strerror (errno)) << endmsg;
706 /** Rename a state file.
707 * @param old_name Old snapshot name.
708 * @param new_name New snapshot name.
711 Session::rename_state (string old_name, string new_name)
713 if (old_name == _current_snapshot_name || old_name == _name) {
714 /* refuse to rename the current snapshot or the "main" one */
718 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
719 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
721 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
722 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
724 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
725 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
726 old_name, new_name, g_strerror(errno)) << endmsg;
730 /** Remove a state file.
731 * @param snapshot_name Snapshot name.
734 Session::remove_state (string snapshot_name)
736 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
737 // refuse to remove the current snapshot or the "main" one
741 std::string xml_path(_session_dir->root_path());
743 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
745 if (!create_backup_file (xml_path)) {
746 // don't remove it if a backup can't be made
747 // create_backup_file will log the error.
752 if (g_remove (xml_path.c_str()) != 0) {
753 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
754 xml_path, g_strerror (errno)) << endmsg;
758 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
760 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot, bool template_only)
763 std::string xml_path(_session_dir->root_path());
765 /* prevent concurrent saves from different threads */
767 Glib::Threads::Mutex::Lock lm (save_state_lock);
769 if (!_writable || (_state_of_the_state & CannotSave)) {
773 if (g_atomic_int_get(&_suspend_save)) {
777 _save_queued = false;
779 if (!_engine.connected ()) {
780 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
787 const int64_t save_start_time = g_get_monotonic_time();
790 /* tell sources we're saving first, in case they write out to a new file
791 * which should be saved with the state rather than the old one */
792 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
794 i->second->session_saved();
795 } catch (Evoral::SMF::FileError& e) {
796 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
800 SessionSaveUnderway (); /* EMIT SIGNAL */
802 bool mark_as_clean = true;
804 if (!snapshot_name.empty() && !switch_to_snapshot) {
805 mark_as_clean = false;
809 mark_as_clean = false;
810 tree.set_root (&get_template());
812 tree.set_root (&get_state());
815 if (snapshot_name.empty()) {
816 snapshot_name = _current_snapshot_name;
817 } else if (switch_to_snapshot) {
818 set_snapshot_name (snapshot_name);
821 assert (!snapshot_name.empty());
825 /* proper save: use statefile_suffix (.ardour in English) */
827 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
829 /* make a backup copy of the old file */
831 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
832 // create_backup_file will log the error
838 /* pending save: use pending_suffix (.pending in English) */
839 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
842 std::string tmp_path(_session_dir->root_path());
843 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
845 cerr << "actually writing state to " << tmp_path << endl;
847 if (!tree.write (tmp_path)) {
848 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
849 if (g_remove (tmp_path.c_str()) != 0) {
850 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
851 tmp_path, g_strerror (errno)) << endmsg;
857 cerr << "renaming state to " << xml_path << endl;
859 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
860 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
861 tmp_path, xml_path, g_strerror(errno)) << endmsg;
862 if (g_remove (tmp_path.c_str()) != 0) {
863 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
864 tmp_path, g_strerror (errno)) << endmsg;
872 save_history (snapshot_name);
875 bool was_dirty = dirty();
877 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
880 DirtyChanged (); /* EMIT SIGNAL */
884 StateSaved (snapshot_name); /* EMIT SIGNAL */
888 const int64_t elapsed_time_us = g_get_monotonic_time() - save_start_time;
889 cerr << "saved state in " << fixed << setprecision (1) << elapsed_time_us / 1000. << " ms\n";
895 Session::restore_state (string snapshot_name)
897 if (load_state (snapshot_name) == 0) {
898 set_state (*state_tree->root(), Stateful::loading_state_version);
905 Session::load_state (string snapshot_name)
910 state_was_pending = false;
912 /* check for leftover pending state from a crashed capture attempt */
914 std::string xmlpath(_session_dir->root_path());
915 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
917 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
919 /* there is pending state from a crashed capture attempt */
921 boost::optional<int> r = AskAboutPendingState();
922 if (r.get_value_or (1)) {
923 state_was_pending = true;
927 if (!state_was_pending) {
928 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
931 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
932 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
933 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
934 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
939 state_tree = new XMLTree;
943 _writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
945 if (!state_tree->read (xmlpath)) {
946 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
952 XMLNode const & root (*state_tree->root());
954 if (root.name() != X_("Session")) {
955 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
961 XMLProperty const * prop;
963 if ((prop = root.property ("version")) == 0) {
964 /* no version implies very old version of Ardour */
965 Stateful::loading_state_version = 1000;
967 if (prop->value().find ('.') != string::npos) {
968 /* old school version format */
969 if (prop->value()[0] == '2') {
970 Stateful::loading_state_version = 2000;
972 Stateful::loading_state_version = 3000;
975 Stateful::loading_state_version = atoi (prop->value());
979 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
981 std::string backup_path(_session_dir->root_path());
982 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
983 backup_path = Glib::build_filename (backup_path, backup_filename);
985 // only create a backup for a given statefile version once
987 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
989 VersionMismatch (xmlpath, backup_path);
991 if (!copy_file (xmlpath, backup_path)) {;
997 save_snapshot_name (snapshot_name);
1003 Session::load_options (const XMLNode& node)
1006 config.set_variables (node);
1011 Session::save_default_options ()
1013 return config.save_state();
1017 Session::get_state()
1023 Session::get_template()
1025 /* if we don't disable rec-enable, diskstreams
1026 will believe they need to store their capture
1027 sources in their state node.
1030 disable_record (false);
1032 return state(false);
1036 Session::state (bool full_state)
1038 XMLNode* node = new XMLNode("Session");
1042 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
1043 node->add_property("version", buf);
1045 /* store configuration settings */
1049 node->add_property ("name", _name);
1050 snprintf (buf, sizeof (buf), "%" PRId64, _base_frame_rate);
1051 node->add_property ("sample-rate", buf);
1053 if (session_dirs.size() > 1) {
1057 vector<space_and_path>::iterator i = session_dirs.begin();
1058 vector<space_and_path>::iterator next;
1060 ++i; /* skip the first one */
1064 while (i != session_dirs.end()) {
1068 if (next != session_dirs.end()) {
1069 p += G_SEARCHPATH_SEPARATOR;
1078 child = node->add_child ("Path");
1079 child->add_content (p);
1083 /* save the ID counter */
1085 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1086 node->add_property ("id-counter", buf);
1088 snprintf (buf, sizeof (buf), "%u", name_id_counter ());
1089 node->add_property ("name-counter", buf);
1091 /* save the event ID counter */
1093 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1094 node->add_property ("event-counter", buf);
1096 /* various options */
1098 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
1099 if (!midi_port_nodes.empty()) {
1100 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
1101 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
1102 midi_port_stuff->add_child_nocopy (**n);
1104 node->add_child_nocopy (*midi_port_stuff);
1107 node->add_child_nocopy (config.get_variables ());
1109 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1111 child = node->add_child ("Sources");
1114 Glib::Threads::Mutex::Lock sl (source_lock);
1116 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1118 /* Don't save information about non-file Sources, or
1119 * about non-destructive file sources that are empty
1120 * and unused by any regions.
1123 boost::shared_ptr<FileSource> fs;
1125 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1127 if (!fs->destructive()) {
1128 if (fs->empty() && !fs->used()) {
1133 child->add_child_nocopy (siter->second->get_state());
1138 child = node->add_child ("Regions");
1141 Glib::Threads::Mutex::Lock rl (region_lock);
1142 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1143 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1144 boost::shared_ptr<Region> r = i->second;
1145 /* only store regions not attached to playlists */
1146 if (r->playlist() == 0) {
1147 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1148 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1150 child->add_child_nocopy (r->get_state ());
1155 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1157 if (!cassocs.empty()) {
1158 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1160 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1162 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1163 i->first->id().print (buf, sizeof (buf));
1164 can->add_property (X_("copy"), buf);
1165 i->second->id().print (buf, sizeof (buf));
1166 can->add_property (X_("original"), buf);
1167 ca->add_child_nocopy (*can);
1177 node->add_child_nocopy (_locations->get_state());
1180 Locations loc (*this);
1181 // for a template, just create a new Locations, populate it
1182 // with the default start and end, and get the state for that.
1183 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1184 range->set (max_framepos, 0);
1186 XMLNode& locations_state = loc.get_state();
1188 if (ARDOUR::Profile->get_trx() && _locations) {
1189 // For tracks we need stored the Auto Loop Range and all MIDI markers.
1190 for (Locations::LocationList::const_iterator i = _locations->list ().begin (); i != _locations->list ().end (); ++i) {
1191 if ((*i)->is_mark () || (*i)->is_auto_loop ()) {
1192 locations_state.add_child_nocopy ((*i)->get_state ());
1196 node->add_child_nocopy (locations_state);
1199 child = node->add_child ("Bundles");
1201 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1202 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1203 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1205 child->add_child_nocopy (b->get_state());
1210 child = node->add_child ("Routes");
1212 boost::shared_ptr<RouteList> r = routes.reader ();
1214 RoutePublicOrderSorter cmp;
1215 RouteList public_order (*r);
1216 public_order.sort (cmp);
1218 /* the sort should have put control outs first */
1221 assert (_monitor_out == public_order.front());
1224 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1225 if (!(*i)->is_auditioner()) {
1227 child->add_child_nocopy ((*i)->get_state());
1229 child->add_child_nocopy ((*i)->get_template());
1235 playlists->add_state (node, full_state);
1237 child = node->add_child ("RouteGroups");
1238 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1239 child->add_child_nocopy ((*i)->get_state());
1243 XMLNode* gain_child = node->add_child ("Click");
1244 gain_child->add_child_nocopy (_click_io->state (full_state));
1245 gain_child->add_child_nocopy (_click_gain->state (full_state));
1249 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1250 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1254 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1255 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1258 node->add_child_nocopy (_speakers->get_state());
1259 node->add_child_nocopy (_tempo_map->get_state());
1260 node->add_child_nocopy (get_control_protocol_state());
1263 node->add_child_copy (*_extra_xml);
1267 Glib::Threads::Mutex::Lock lm (lua_lock);
1270 luabridge::LuaRef savedstate ((*_lua_save)());
1271 saved = savedstate.cast<std::string>();
1273 lua.collect_garbage ();
1276 gchar* b64 = g_base64_encode ((const guchar*)saved.c_str (), saved.size ());
1277 std::string b64s (b64);
1280 XMLNode* script_node = new XMLNode (X_("Script"));
1281 script_node->add_property (X_("lua"), LUA_VERSION);
1282 script_node->add_content (b64s);
1283 node->add_child_nocopy (*script_node);
1290 Session::get_control_protocol_state ()
1292 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1293 return cpm.get_state();
1297 Session::set_state (const XMLNode& node, int version)
1301 XMLProperty const * prop;
1304 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1306 if (node.name() != X_("Session")) {
1307 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1311 if ((prop = node.property ("name")) != 0) {
1312 _name = prop->value ();
1315 if ((prop = node.property (X_("sample-rate"))) != 0) {
1317 _base_frame_rate = atoi (prop->value());
1318 _nominal_frame_rate = _base_frame_rate;
1320 assert (AudioEngine::instance()->running ());
1321 if (_base_frame_rate != AudioEngine::instance()->sample_rate ()) {
1322 boost::optional<int> r = AskAboutSampleRateMismatch (_base_frame_rate, _current_frame_rate);
1323 if (r.get_value_or (0)) {
1329 setup_raid_path(_session_dir->root_path());
1331 if ((prop = node.property (X_("id-counter"))) != 0) {
1333 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1334 ID::init_counter (x);
1336 /* old sessions used a timebased counter, so fake
1337 the startup ID counter based on a standard
1342 ID::init_counter (now);
1345 if ((prop = node.property (X_("name-counter"))) != 0) {
1346 init_name_id_counter (atoi (prop->value()));
1349 if ((prop = node.property (X_("event-counter"))) != 0) {
1350 Evoral::init_event_id_counter (atoi (prop->value()));
1353 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1354 _midi_ports->set_midi_port_states (child->children());
1357 IO::disable_connecting ();
1359 Stateful::save_extra_xml (node);
1361 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1362 load_options (*child);
1363 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1364 load_options (*child);
1366 error << _("Session: XML state has no options section") << endmsg;
1369 if (version >= 3000) {
1370 if ((child = find_named_node (node, "Metadata")) == 0) {
1371 warning << _("Session: XML state has no metadata section") << endmsg;
1372 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1377 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1378 _speakers->set_state (*child, version);
1381 if ((child = find_named_node (node, "Sources")) == 0) {
1382 error << _("Session: XML state has no sources section") << endmsg;
1384 } else if (load_sources (*child)) {
1388 if ((child = find_named_node (node, "TempoMap")) == 0) {
1389 error << _("Session: XML state has no Tempo Map section") << endmsg;
1391 } else if (_tempo_map->set_state (*child, version)) {
1395 if ((child = find_named_node (node, "Locations")) == 0) {
1396 error << _("Session: XML state has no locations section") << endmsg;
1398 } else if (_locations->set_state (*child, version)) {
1402 locations_changed ();
1404 if (_session_range_location) {
1405 AudioFileSource::set_header_position_offset (_session_range_location->start());
1408 if ((child = find_named_node (node, "Regions")) == 0) {
1409 error << _("Session: XML state has no Regions section") << endmsg;
1411 } else if (load_regions (*child)) {
1415 if ((child = find_named_node (node, "Playlists")) == 0) {
1416 error << _("Session: XML state has no playlists section") << endmsg;
1418 } else if (playlists->load (*this, *child)) {
1422 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1424 } else if (playlists->load_unused (*this, *child)) {
1428 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1429 if (load_compounds (*child)) {
1434 if (version >= 3000) {
1435 if ((child = find_named_node (node, "Bundles")) == 0) {
1436 warning << _("Session: XML state has no bundles section") << endmsg;
1439 /* We can't load Bundles yet as they need to be able
1440 to convert from port names to Port objects, which can't happen until
1442 _bundle_xml_node = new XMLNode (*child);
1446 if (version < 3000) {
1447 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1448 error << _("Session: XML state has no diskstreams section") << endmsg;
1450 } else if (load_diskstreams_2X (*child, version)) {
1455 if ((child = find_named_node (node, "Routes")) == 0) {
1456 error << _("Session: XML state has no routes section") << endmsg;
1458 } else if (load_routes (*child, version)) {
1462 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1463 _diskstreams_2X.clear ();
1465 if (version >= 3000) {
1467 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1468 error << _("Session: XML state has no route groups section") << endmsg;
1470 } else if (load_route_groups (*child, version)) {
1474 } else if (version < 3000) {
1476 if ((child = find_named_node (node, "EditGroups")) == 0) {
1477 error << _("Session: XML state has no edit groups section") << endmsg;
1479 } else if (load_route_groups (*child, version)) {
1483 if ((child = find_named_node (node, "MixGroups")) == 0) {
1484 error << _("Session: XML state has no mix groups section") << endmsg;
1486 } else if (load_route_groups (*child, version)) {
1491 if ((child = find_named_node (node, "Click")) == 0) {
1492 warning << _("Session: XML state has no click section") << endmsg;
1493 } else if (_click_io) {
1494 setup_click_state (&node);
1497 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1498 ControlProtocolManager::instance().set_state (*child, version);
1501 if ((child = find_named_node (node, "Script"))) {
1502 for (XMLNodeList::const_iterator n = child->children ().begin (); n != child->children ().end (); ++n) {
1503 if (!(*n)->is_content ()) { continue; }
1505 guchar* buf = g_base64_decode ((*n)->content ().c_str (), &size);
1507 Glib::Threads::Mutex::Lock lm (lua_lock);
1508 (*_lua_load)(std::string ((const char*)buf, size));
1509 } catch (luabridge::LuaException const& e) {
1510 cerr << "LuaException:" << e.what () << endl;
1516 update_route_record_state ();
1518 /* here beginneth the second phase ... */
1519 set_snapshot_name (_current_snapshot_name);
1521 StateReady (); /* EMIT SIGNAL */
1534 Session::load_routes (const XMLNode& node, int version)
1537 XMLNodeConstIterator niter;
1538 RouteList new_routes;
1540 nlist = node.children();
1544 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1546 boost::shared_ptr<Route> route;
1547 if (version < 3000) {
1548 route = XMLRouteFactory_2X (**niter, version);
1550 route = XMLRouteFactory (**niter, version);
1554 error << _("Session: cannot create Route from XML description.") << endmsg;
1558 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1560 new_routes.push_back (route);
1563 BootMessage (_("Tracks/busses loaded; Adding to Session"));
1565 add_routes (new_routes, false, false, false);
1567 BootMessage (_("Finished adding tracks/busses"));
1572 boost::shared_ptr<Route>
1573 Session::XMLRouteFactory (const XMLNode& node, int version)
1575 boost::shared_ptr<Route> ret;
1577 if (node.name() != "Route") {
1581 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1583 DataType type = DataType::AUDIO;
1584 XMLProperty const * prop = node.property("default-type");
1587 type = DataType (prop->value());
1590 assert (type != DataType::NIL);
1594 boost::shared_ptr<Track> track;
1596 if (type == DataType::AUDIO) {
1597 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1599 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1602 if (track->init()) {
1606 if (track->set_state (node, version)) {
1610 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1611 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1616 enum Route::Flag flags = Route::Flag(0);
1617 XMLProperty const * prop = node.property("flags");
1619 flags = Route::Flag (string_2_enum (prop->value(), flags));
1622 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1624 if (r->init () == 0 && r->set_state (node, version) == 0) {
1625 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1626 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1635 boost::shared_ptr<Route>
1636 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1638 boost::shared_ptr<Route> ret;
1640 if (node.name() != "Route") {
1644 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1646 ds_prop = node.property (X_("diskstream"));
1649 DataType type = DataType::AUDIO;
1650 XMLProperty const * prop = node.property("default-type");
1653 type = DataType (prop->value());
1656 assert (type != DataType::NIL);
1660 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1661 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1665 if (i == _diskstreams_2X.end()) {
1666 error << _("Could not find diskstream for route") << endmsg;
1667 return boost::shared_ptr<Route> ();
1670 boost::shared_ptr<Track> track;
1672 if (type == DataType::AUDIO) {
1673 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1675 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1678 if (track->init()) {
1682 if (track->set_state (node, version)) {
1686 track->set_diskstream (*i);
1688 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1689 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1694 enum Route::Flag flags = Route::Flag(0);
1695 XMLProperty const * prop = node.property("flags");
1697 flags = Route::Flag (string_2_enum (prop->value(), flags));
1700 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1702 if (r->init () == 0 && r->set_state (node, version) == 0) {
1703 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1704 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1714 Session::load_regions (const XMLNode& node)
1717 XMLNodeConstIterator niter;
1718 boost::shared_ptr<Region> region;
1720 nlist = node.children();
1724 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1725 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1726 error << _("Session: cannot create Region from XML description.");
1727 XMLProperty const * name = (**niter).property("name");
1730 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1741 Session::load_compounds (const XMLNode& node)
1743 XMLNodeList calist = node.children();
1744 XMLNodeConstIterator caiter;
1745 XMLProperty const * caprop;
1747 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1748 XMLNode* ca = *caiter;
1752 if ((caprop = ca->property (X_("original"))) == 0) {
1755 orig_id = caprop->value();
1757 if ((caprop = ca->property (X_("copy"))) == 0) {
1760 copy_id = caprop->value();
1762 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1763 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1765 if (!orig || !copy) {
1766 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1772 RegionFactory::add_compound_association (orig, copy);
1779 Session::load_nested_sources (const XMLNode& node)
1782 XMLNodeConstIterator niter;
1784 nlist = node.children();
1786 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1787 if ((*niter)->name() == "Source") {
1789 /* it may already exist, so don't recreate it unnecessarily
1792 XMLProperty const * prop = (*niter)->property (X_("id"));
1794 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1798 ID source_id (prop->value());
1800 if (!source_by_id (source_id)) {
1803 SourceFactory::create (*this, **niter, true);
1805 catch (failed_constructor& err) {
1806 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1813 boost::shared_ptr<Region>
1814 Session::XMLRegionFactory (const XMLNode& node, bool full)
1816 XMLProperty const * type = node.property("type");
1820 const XMLNodeList& nlist = node.children();
1822 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1823 XMLNode *child = (*niter);
1824 if (child->name() == "NestedSource") {
1825 load_nested_sources (*child);
1829 if (!type || type->value() == "audio") {
1830 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1831 } else if (type->value() == "midi") {
1832 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1835 } catch (failed_constructor& err) {
1836 return boost::shared_ptr<Region> ();
1839 return boost::shared_ptr<Region> ();
1842 boost::shared_ptr<AudioRegion>
1843 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1845 XMLProperty const * prop;
1846 boost::shared_ptr<Source> source;
1847 boost::shared_ptr<AudioSource> as;
1849 SourceList master_sources;
1850 uint32_t nchans = 1;
1853 if (node.name() != X_("Region")) {
1854 return boost::shared_ptr<AudioRegion>();
1857 if ((prop = node.property (X_("channels"))) != 0) {
1858 nchans = atoi (prop->value().c_str());
1861 if ((prop = node.property ("name")) == 0) {
1862 cerr << "no name for this region\n";
1866 if ((prop = node.property (X_("source-0"))) == 0) {
1867 if ((prop = node.property ("source")) == 0) {
1868 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1869 return boost::shared_ptr<AudioRegion>();
1873 PBD::ID s_id (prop->value());
1875 if ((source = source_by_id (s_id)) == 0) {
1876 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1877 return boost::shared_ptr<AudioRegion>();
1880 as = boost::dynamic_pointer_cast<AudioSource>(source);
1882 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1883 return boost::shared_ptr<AudioRegion>();
1886 sources.push_back (as);
1888 /* pickup other channels */
1890 for (uint32_t n=1; n < nchans; ++n) {
1891 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1892 if ((prop = node.property (buf)) != 0) {
1894 PBD::ID id2 (prop->value());
1896 if ((source = source_by_id (id2)) == 0) {
1897 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1898 return boost::shared_ptr<AudioRegion>();
1901 as = boost::dynamic_pointer_cast<AudioSource>(source);
1903 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1904 return boost::shared_ptr<AudioRegion>();
1906 sources.push_back (as);
1910 for (uint32_t n = 0; n < nchans; ++n) {
1911 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1912 if ((prop = node.property (buf)) != 0) {
1914 PBD::ID id2 (prop->value());
1916 if ((source = source_by_id (id2)) == 0) {
1917 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1918 return boost::shared_ptr<AudioRegion>();
1921 as = boost::dynamic_pointer_cast<AudioSource>(source);
1923 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1924 return boost::shared_ptr<AudioRegion>();
1926 master_sources.push_back (as);
1931 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1933 /* a final detail: this is the one and only place that we know how long missing files are */
1935 if (region->whole_file()) {
1936 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1937 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1939 sfp->set_length (region->length());
1944 if (!master_sources.empty()) {
1945 if (master_sources.size() != nchans) {
1946 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1948 region->set_master_sources (master_sources);
1956 catch (failed_constructor& err) {
1957 return boost::shared_ptr<AudioRegion>();
1961 boost::shared_ptr<MidiRegion>
1962 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1964 XMLProperty const * prop;
1965 boost::shared_ptr<Source> source;
1966 boost::shared_ptr<MidiSource> ms;
1969 if (node.name() != X_("Region")) {
1970 return boost::shared_ptr<MidiRegion>();
1973 if ((prop = node.property ("name")) == 0) {
1974 cerr << "no name for this region\n";
1978 if ((prop = node.property (X_("source-0"))) == 0) {
1979 if ((prop = node.property ("source")) == 0) {
1980 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1981 return boost::shared_ptr<MidiRegion>();
1985 PBD::ID s_id (prop->value());
1987 if ((source = source_by_id (s_id)) == 0) {
1988 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1989 return boost::shared_ptr<MidiRegion>();
1992 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1994 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1995 return boost::shared_ptr<MidiRegion>();
1998 sources.push_back (ms);
2001 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
2002 /* a final detail: this is the one and only place that we know how long missing files are */
2004 if (region->whole_file()) {
2005 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
2006 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
2008 sfp->set_length (region->length());
2016 catch (failed_constructor& err) {
2017 return boost::shared_ptr<MidiRegion>();
2022 Session::get_sources_as_xml ()
2025 XMLNode* node = new XMLNode (X_("Sources"));
2026 Glib::Threads::Mutex::Lock lm (source_lock);
2028 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2029 node->add_child_nocopy (i->second->get_state());
2036 Session::reset_write_sources (bool mark_write_complete, bool force)
2038 boost::shared_ptr<RouteList> rl = routes.reader();
2039 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
2040 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
2042 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
2043 tr->reset_write_sources(mark_write_complete, force);
2044 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
2050 Session::load_sources (const XMLNode& node)
2053 XMLNodeConstIterator niter;
2054 boost::shared_ptr<Source> source; /* don't need this but it stops some
2055 * versions of gcc complaining about
2056 * discarded return values.
2059 nlist = node.children();
2063 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2066 if ((source = XMLSourceFactory (**niter)) == 0) {
2067 error << _("Session: cannot create Source from XML description.") << endmsg;
2070 } catch (MissingSource& err) {
2074 if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
2075 error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
2076 PROGRAM_NAME) << endmsg;
2080 if (!no_questions_about_missing_files) {
2081 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
2086 switch (user_choice) {
2088 /* user added a new search location, so try again */
2093 /* user asked to quit the entire session load
2098 no_questions_about_missing_files = true;
2102 no_questions_about_missing_files = true;
2109 case DataType::AUDIO:
2110 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
2113 case DataType::MIDI:
2114 /* The MIDI file is actually missing so
2115 * just create a new one in the same
2116 * location. Do not announce its
2120 if (!Glib::path_is_absolute (err.path)) {
2121 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
2123 /* this should be an unrecoverable error: we would be creating a MIDI file outside
2128 /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
2129 source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
2130 /* reset ID to match the missing one */
2131 source->set_id (**niter);
2132 /* Now we can announce it */
2133 SourceFactory::SourceCreated (source);
2144 boost::shared_ptr<Source>
2145 Session::XMLSourceFactory (const XMLNode& node)
2147 if (node.name() != "Source") {
2148 return boost::shared_ptr<Source>();
2152 /* note: do peak building in another thread when loading session state */
2153 return SourceFactory::create (*this, node, true);
2156 catch (failed_constructor& err) {
2157 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
2158 return boost::shared_ptr<Source>();
2163 Session::save_template (string template_name, bool replace_existing)
2165 if ((_state_of_the_state & CannotSave) || template_name.empty ()) {
2169 bool absolute_path = Glib::path_is_absolute (template_name);
2171 /* directory to put the template in */
2172 std::string template_dir_path;
2174 if (!absolute_path) {
2175 std::string user_template_dir(user_template_directory());
2177 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2178 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2179 user_template_dir, g_strerror (errno)) << endmsg;
2183 template_dir_path = Glib::build_filename (user_template_dir, template_name);
2185 template_dir_path = template_name;
2188 if (!ARDOUR::Profile->get_trx()) {
2189 if (!replace_existing && Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2190 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2191 template_dir_path) << endmsg;
2195 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2196 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2197 template_dir_path, g_strerror (errno)) << endmsg;
2203 std::string template_file_path;
2205 if (ARDOUR::Profile->get_trx()) {
2206 template_file_path = template_name;
2208 if (absolute_path) {
2209 template_file_path = Glib::build_filename (template_dir_path, Glib::path_get_basename (template_dir_path) + template_suffix);
2211 template_file_path = Glib::build_filename (template_dir_path, template_name + template_suffix);
2215 SessionSaveUnderway (); /* EMIT SIGNAL */
2220 PBD::Unwinder<std::string> uw (_template_state_dir, template_dir_path);
2221 tree.set_root (&get_template());
2224 if (!tree.write (template_file_path)) {
2225 error << _("template not saved") << endmsg;
2229 store_recent_templates (template_file_path);
2235 Session::refresh_disk_space ()
2237 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2239 Glib::Threads::Mutex::Lock lm (space_lock);
2241 /* get freespace on every FS that is part of the session path */
2243 _total_free_4k_blocks = 0;
2244 _total_free_4k_blocks_uncertain = false;
2246 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2248 struct statfs statfsbuf;
2249 statfs (i->path.c_str(), &statfsbuf);
2251 double const scale = statfsbuf.f_bsize / 4096.0;
2253 /* See if this filesystem is read-only */
2254 struct statvfs statvfsbuf;
2255 statvfs (i->path.c_str(), &statvfsbuf);
2257 /* f_bavail can be 0 if it is undefined for whatever
2258 filesystem we are looking at; Samba shares mounted
2259 via GVFS are an example of this.
2261 if (statfsbuf.f_bavail == 0) {
2262 /* block count unknown */
2264 i->blocks_unknown = true;
2265 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2266 /* read-only filesystem */
2268 i->blocks_unknown = false;
2270 /* read/write filesystem with known space */
2271 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2272 i->blocks_unknown = false;
2275 _total_free_4k_blocks += i->blocks;
2276 if (i->blocks_unknown) {
2277 _total_free_4k_blocks_uncertain = true;
2280 #elif defined PLATFORM_WINDOWS
2281 vector<string> scanned_volumes;
2282 vector<string>::iterator j;
2283 vector<space_and_path>::iterator i;
2284 DWORD nSectorsPerCluster, nBytesPerSector,
2285 nFreeClusters, nTotalClusters;
2289 _total_free_4k_blocks = 0;
2291 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2292 strncpy (disk_drive, (*i).path.c_str(), 3);
2296 volume_found = false;
2297 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2299 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2300 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2301 i->blocks = (uint32_t)(nFreeBytes / 4096);
2303 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2304 if (0 == j->compare(disk_drive)) {
2305 volume_found = true;
2310 if (!volume_found) {
2311 scanned_volumes.push_back(disk_drive);
2312 _total_free_4k_blocks += i->blocks;
2317 if (0 == _total_free_4k_blocks) {
2318 strncpy (disk_drive, path().c_str(), 3);
2321 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2323 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2324 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2325 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2332 Session::get_best_session_directory_for_new_audio ()
2334 vector<space_and_path>::iterator i;
2335 string result = _session_dir->root_path();
2337 /* handle common case without system calls */
2339 if (session_dirs.size() == 1) {
2343 /* OK, here's the algorithm we're following here:
2345 We want to select which directory to use for
2346 the next file source to be created. Ideally,
2347 we'd like to use a round-robin process so as to
2348 get maximum performance benefits from splitting
2349 the files across multiple disks.
2351 However, in situations without much diskspace, an
2352 RR approach may end up filling up a filesystem
2353 with new files while others still have space.
2354 Its therefore important to pay some attention to
2355 the freespace in the filesystem holding each
2356 directory as well. However, if we did that by
2357 itself, we'd keep creating new files in the file
2358 system with the most space until it was as full
2359 as all others, thus negating any performance
2360 benefits of this RAID-1 like approach.
2362 So, we use a user-configurable space threshold. If
2363 there are at least 2 filesystems with more than this
2364 much space available, we use RR selection between them.
2365 If not, then we pick the filesystem with the most space.
2367 This gets a good balance between the two
2371 refresh_disk_space ();
2373 int free_enough = 0;
2375 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2376 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2381 if (free_enough >= 2) {
2382 /* use RR selection process, ensuring that the one
2386 i = last_rr_session_dir;
2389 if (++i == session_dirs.end()) {
2390 i = session_dirs.begin();
2393 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2394 SessionDirectory sdir(i->path);
2395 if (sdir.create ()) {
2397 last_rr_session_dir = i;
2402 } while (i != last_rr_session_dir);
2406 /* pick FS with the most freespace (and that
2407 seems to actually work ...)
2410 vector<space_and_path> sorted;
2411 space_and_path_ascending_cmp cmp;
2413 sorted = session_dirs;
2414 sort (sorted.begin(), sorted.end(), cmp);
2416 for (i = sorted.begin(); i != sorted.end(); ++i) {
2417 SessionDirectory sdir(i->path);
2418 if (sdir.create ()) {
2420 last_rr_session_dir = i;
2430 Session::automation_dir () const
2432 return Glib::build_filename (_path, automation_dir_name);
2436 Session::analysis_dir () const
2438 return Glib::build_filename (_path, analysis_dir_name);
2442 Session::plugins_dir () const
2444 return Glib::build_filename (_path, plugins_dir_name);
2448 Session::externals_dir () const
2450 return Glib::build_filename (_path, externals_dir_name);
2454 Session::load_bundles (XMLNode const & node)
2456 XMLNodeList nlist = node.children();
2457 XMLNodeConstIterator niter;
2461 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2462 if ((*niter)->name() == "InputBundle") {
2463 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2464 } else if ((*niter)->name() == "OutputBundle") {
2465 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2467 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2476 Session::load_route_groups (const XMLNode& node, int version)
2478 XMLNodeList nlist = node.children();
2479 XMLNodeConstIterator niter;
2483 if (version >= 3000) {
2485 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2486 if ((*niter)->name() == "RouteGroup") {
2487 RouteGroup* rg = new RouteGroup (*this, "");
2488 add_route_group (rg);
2489 rg->set_state (**niter, version);
2493 } else if (version < 3000) {
2495 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2496 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2497 RouteGroup* rg = new RouteGroup (*this, "");
2498 add_route_group (rg);
2499 rg->set_state (**niter, version);
2508 state_file_filter (const string &str, void* /*arg*/)
2510 return (str.length() > strlen(statefile_suffix) &&
2511 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2515 remove_end(string state)
2517 string statename(state);
2519 string::size_type start,end;
2520 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2521 statename = statename.substr (start+1);
2524 if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2525 end = statename.length();
2528 return string(statename.substr (0, end));
2532 Session::possible_states (string path)
2534 vector<string> states;
2535 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2537 transform(states.begin(), states.end(), states.begin(), remove_end);
2539 sort (states.begin(), states.end());
2545 Session::possible_states () const
2547 return possible_states(_path);
2551 Session::add_route_group (RouteGroup* g)
2553 _route_groups.push_back (g);
2554 route_group_added (g); /* EMIT SIGNAL */
2556 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2557 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2558 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2564 Session::remove_route_group (RouteGroup& rg)
2566 list<RouteGroup*>::iterator i;
2568 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2569 _route_groups.erase (i);
2572 route_group_removed (); /* EMIT SIGNAL */
2576 /** Set a new order for our route groups, without adding or removing any.
2577 * @param groups Route group list in the new order.
2580 Session::reorder_route_groups (list<RouteGroup*> groups)
2582 _route_groups = groups;
2584 route_groups_reordered (); /* EMIT SIGNAL */
2590 Session::route_group_by_name (string name)
2592 list<RouteGroup *>::iterator i;
2594 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2595 if ((*i)->name() == name) {
2603 Session::all_route_group() const
2605 return *_all_route_group;
2609 Session::add_commands (vector<Command*> const & cmds)
2611 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2617 Session::add_command (Command* const cmd)
2619 assert (_current_trans);
2620 DEBUG_UNDO_HISTORY (
2621 string_compose ("Current Undo Transaction %1, adding command: %2",
2622 _current_trans->name (),
2624 _current_trans->add_command (cmd);
2627 PBD::StatefulDiffCommand*
2628 Session::add_stateful_diff_command (boost::shared_ptr<PBD::StatefulDestructible> sfd)
2630 PBD::StatefulDiffCommand* cmd = new PBD::StatefulDiffCommand (sfd);
2636 Session::begin_reversible_command (const string& name)
2638 begin_reversible_command (g_quark_from_string (name.c_str ()));
2641 /** Begin a reversible command using a GQuark to identify it.
2642 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2643 * but there must be as many begin...()s as there are commit...()s.
2646 Session::begin_reversible_command (GQuark q)
2648 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2649 to hold all the commands that are committed. This keeps the order of
2650 commands correct in the history.
2653 if (_current_trans == 0) {
2654 DEBUG_UNDO_HISTORY (string_compose (
2655 "Begin Reversible Command, new transaction: %1", g_quark_to_string (q)));
2657 /* start a new transaction */
2658 assert (_current_trans_quarks.empty ());
2659 _current_trans = new UndoTransaction();
2660 _current_trans->set_name (g_quark_to_string (q));
2662 DEBUG_UNDO_HISTORY (
2663 string_compose ("Begin Reversible Command, current transaction: %1",
2664 _current_trans->name ()));
2667 _current_trans_quarks.push_front (q);
2671 Session::abort_reversible_command ()
2673 if (_current_trans != 0) {
2674 DEBUG_UNDO_HISTORY (
2675 string_compose ("Abort Reversible Command: %1", _current_trans->name ()));
2676 _current_trans->clear();
2677 delete _current_trans;
2679 _current_trans_quarks.clear();
2684 Session::commit_reversible_command (Command *cmd)
2686 assert (_current_trans);
2687 assert (!_current_trans_quarks.empty ());
2692 DEBUG_UNDO_HISTORY (
2693 string_compose ("Current Undo Transaction %1, adding command: %2",
2694 _current_trans->name (),
2696 _current_trans->add_command (cmd);
2699 DEBUG_UNDO_HISTORY (
2700 string_compose ("Commit Reversible Command, current transaction: %1",
2701 _current_trans->name ()));
2703 _current_trans_quarks.pop_front ();
2705 if (!_current_trans_quarks.empty ()) {
2706 DEBUG_UNDO_HISTORY (
2707 string_compose ("Commit Reversible Command, transaction is not "
2708 "top-level, current transaction: %1",
2709 _current_trans->name ()));
2710 /* the transaction we're committing is not the top-level one */
2714 if (_current_trans->empty()) {
2715 /* no commands were added to the transaction, so just get rid of it */
2716 DEBUG_UNDO_HISTORY (
2717 string_compose ("Commit Reversible Command, No commands were "
2718 "added to current transaction: %1",
2719 _current_trans->name ()));
2720 delete _current_trans;
2725 gettimeofday (&now, 0);
2726 _current_trans->set_timestamp (now);
2728 _history.add (_current_trans);
2733 accept_all_audio_files (const string& path, void* /*arg*/)
2735 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2739 if (!AudioFileSource::safe_audio_file_extension (path)) {
2747 accept_all_midi_files (const string& path, void* /*arg*/)
2749 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2753 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2754 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2755 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2759 accept_all_state_files (const string& path, void* /*arg*/)
2761 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2765 std::string const statefile_ext (statefile_suffix);
2766 if (path.length() >= statefile_ext.length()) {
2767 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2774 Session::find_all_sources (string path, set<string>& result)
2779 if (!tree.read (path)) {
2783 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2788 XMLNodeConstIterator niter;
2790 nlist = node->children();
2794 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2796 XMLProperty const * prop;
2798 if ((prop = (*niter)->property (X_("type"))) == 0) {
2802 DataType type (prop->value());
2804 if ((prop = (*niter)->property (X_("name"))) == 0) {
2808 if (Glib::path_is_absolute (prop->value())) {
2809 /* external file, ignore */
2817 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2818 result.insert (found_path);
2826 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2828 vector<string> state_files;
2830 string this_snapshot_path;
2836 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2837 ripped = ripped.substr (0, ripped.length() - 1);
2840 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2842 if (state_files.empty()) {
2847 this_snapshot_path = _path;
2848 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2849 this_snapshot_path += statefile_suffix;
2851 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2853 if (exclude_this_snapshot && *i == this_snapshot_path) {
2857 if (find_all_sources (*i, result) < 0) {
2865 struct RegionCounter {
2866 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2867 AudioSourceList::iterator iter;
2868 boost::shared_ptr<Region> region;
2871 RegionCounter() : count (0) {}
2875 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2877 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2878 return r.get_value_or (1);
2882 Session::cleanup_regions ()
2884 bool removed = false;
2885 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2887 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2889 uint32_t used = playlists->region_use_count (i->second);
2891 if (used == 0 && !i->second->automatic ()) {
2892 boost::weak_ptr<Region> w = i->second;
2895 RegionFactory::map_remove (w);
2902 // re-check to remove parent references of compound regions
2903 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2904 if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2908 assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2909 if (0 == playlists->region_use_count (i->second)) {
2910 boost::weak_ptr<Region> w = i->second;
2912 RegionFactory::map_remove (w);
2919 /* dump the history list */
2926 Session::can_cleanup_peakfiles () const
2928 if (deletion_in_progress()) {
2931 if (!_writable || (_state_of_the_state & CannotSave)) {
2932 warning << _("Cannot cleanup peak-files for read-only session.") << endmsg;
2935 if (record_status() == Recording) {
2936 error << _("Cannot cleanup peak-files while recording") << endmsg;
2943 Session::cleanup_peakfiles ()
2945 Glib::Threads::Mutex::Lock lm (peak_cleanup_lock, Glib::Threads::TRY_LOCK);
2950 assert (can_cleanup_peakfiles ());
2951 assert (!peaks_cleanup_in_progres());
2953 _state_of_the_state = StateOfTheState (_state_of_the_state | PeakCleanup);
2955 int timeout = 5000; // 5 seconds
2956 while (!SourceFactory::files_with_peaks.empty()) {
2957 Glib::usleep (1000);
2958 if (--timeout < 0) {
2959 warning << _("Timeout waiting for peak-file creation to terminate before cleanup, please try again later.") << endmsg;
2960 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
2965 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2966 boost::shared_ptr<AudioSource> as;
2967 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
2968 as->close_peakfile();
2972 PBD::clear_directory (session_directory().peak_path());
2974 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
2976 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2977 boost::shared_ptr<AudioSource> as;
2978 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
2979 SourceFactory::setup_peakfile(as, true);
2986 Session::cleanup_sources (CleanupReport& rep)
2988 // FIXME: needs adaptation to midi
2990 vector<boost::shared_ptr<Source> > dead_sources;
2993 vector<string> candidates;
2994 vector<string> unused;
2995 set<string> all_sources;
3004 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
3006 /* this is mostly for windows which doesn't allow file
3007 * renaming if the file is in use. But we don't special
3008 * case it because we need to know if this causes
3009 * problems, and the easiest way to notice that is to
3010 * keep it in place for all platforms.
3013 request_stop (false);
3015 _butler->wait_until_finished ();
3017 /* consider deleting all unused playlists */
3019 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
3024 /* sync the "all regions" property of each playlist with its current state
3027 playlists->sync_all_regions_with_regions ();
3029 /* find all un-used sources */
3034 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3036 SourceMap::iterator tmp;
3041 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
3045 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
3046 dead_sources.push_back (i->second);
3047 i->second->drop_references ();
3053 /* build a list of all the possible audio directories for the session */
3055 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3056 SessionDirectory sdir ((*i).path);
3057 asp += sdir.sound_path();
3059 audio_path += asp.to_string();
3062 /* build a list of all the possible midi directories for the session */
3064 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3065 SessionDirectory sdir ((*i).path);
3066 msp += sdir.midi_path();
3068 midi_path += msp.to_string();
3070 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
3071 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
3073 /* find all sources, but don't use this snapshot because the
3074 state file on disk still references sources we may have already
3078 find_all_sources_across_snapshots (all_sources, true);
3080 /* add our current source list
3083 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3084 boost::shared_ptr<FileSource> fs;
3085 SourceMap::iterator tmp = i;
3088 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
3090 /* this is mostly for windows which doesn't allow file
3091 * renaming if the file is in use. But we don't special
3092 * case it because we need to know if this causes
3093 * problems, and the easiest way to notice that is to
3094 * keep it in place for all platforms.
3099 if (!fs->is_stub()) {
3101 if (playlists->source_use_count (fs) != 0) {
3102 all_sources.insert (fs->path());
3105 /* we might not remove this source from disk, because it may be used
3106 by other snapshots, but its not being used in this version
3107 so lets get rid of it now, along with any representative regions
3111 RegionFactory::remove_regions_using_source (i->second);
3113 // also remove source from all_sources
3115 for (set<string>::iterator j = all_sources.begin(); j != all_sources.end(); ++j) {
3116 spath = Glib::path_get_basename (*j);
3117 if (spath == i->second->name()) {
3118 all_sources.erase (j);
3131 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
3136 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
3138 tmppath1 = canonical_path (spath);
3139 tmppath2 = canonical_path ((*i));
3141 if (tmppath1 == tmppath2) {
3148 unused.push_back (spath);
3152 /* now try to move all unused files into the "dead" directory(ies) */
3154 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
3159 /* don't move the file across filesystems, just
3160 stick it in the `dead_dir_name' directory
3161 on whichever filesystem it was already on.
3164 if ((*x).find ("/sounds/") != string::npos) {
3166 /* old school, go up 1 level */
3168 newpath = Glib::path_get_dirname (*x); // "sounds"
3169 newpath = Glib::path_get_dirname (newpath); // "session-name"
3173 /* new school, go up 4 levels */
3175 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
3176 newpath = Glib::path_get_dirname (newpath); // "session-name"
3177 newpath = Glib::path_get_dirname (newpath); // "interchange"
3178 newpath = Glib::path_get_dirname (newpath); // "session-dir"
3181 newpath = Glib::build_filename (newpath, dead_dir_name);
3183 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
3184 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
3188 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
3190 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
3192 /* the new path already exists, try versioning */
3194 char buf[PATH_MAX+1];
3198 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3201 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
3202 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3206 if (version == 999) {
3207 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3211 newpath = newpath_v;
3216 /* it doesn't exist, or we can't read it or something */
3220 g_stat ((*x).c_str(), &statbuf);
3222 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3223 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
3224 (*x), newpath, strerror (errno))
3229 /* see if there an easy to find peakfile for this file, and remove it.
3232 string base = Glib::path_get_basename (*x);
3233 base += "%A"; /* this is what we add for the channel suffix of all native files,
3234 or for the first channel of embedded files. it will miss
3235 some peakfiles for other channels
3237 string peakpath = construct_peak_filepath (base);
3239 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
3240 if (::g_unlink (peakpath.c_str()) != 0) {
3241 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3242 peakpath, _path, strerror (errno))
3244 /* try to back out */
3245 ::rename (newpath.c_str(), _path.c_str());
3250 rep.paths.push_back (*x);
3251 rep.space += statbuf.st_size;
3254 /* dump the history list */
3258 /* save state so we don't end up a session file
3259 referring to non-existent sources.
3266 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3272 Session::cleanup_trash_sources (CleanupReport& rep)
3274 // FIXME: needs adaptation for MIDI
3276 vector<space_and_path>::iterator i;
3282 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3284 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
3286 clear_directory (dead_dir, &rep.space, &rep.paths);
3293 Session::set_dirty ()
3295 /* never mark session dirty during loading */
3297 if (_state_of_the_state & Loading) {
3301 bool was_dirty = dirty();
3303 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3307 DirtyChanged(); /* EMIT SIGNAL */
3313 Session::set_clean ()
3315 bool was_dirty = dirty();
3317 _state_of_the_state = Clean;
3321 DirtyChanged(); /* EMIT SIGNAL */
3326 Session::set_deletion_in_progress ()
3328 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3332 Session::clear_deletion_in_progress ()
3334 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3338 Session::add_controllable (boost::shared_ptr<Controllable> c)
3340 /* this adds a controllable to the list managed by the Session.
3341 this is a subset of those managed by the Controllable class
3342 itself, and represents the only ones whose state will be saved
3343 as part of the session.
3346 Glib::Threads::Mutex::Lock lm (controllables_lock);
3347 controllables.insert (c);
3350 struct null_deleter { void operator()(void const *) const {} };
3353 Session::remove_controllable (Controllable* c)
3355 if (_state_of_the_state & Deletion) {
3359 Glib::Threads::Mutex::Lock lm (controllables_lock);
3361 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3363 if (x != controllables.end()) {
3364 controllables.erase (x);
3368 boost::shared_ptr<Controllable>
3369 Session::controllable_by_id (const PBD::ID& id)
3371 Glib::Threads::Mutex::Lock lm (controllables_lock);
3373 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3374 if ((*i)->id() == id) {
3379 return boost::shared_ptr<Controllable>();
3382 boost::shared_ptr<Controllable>
3383 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3385 boost::shared_ptr<Controllable> c;
3386 boost::shared_ptr<Route> r;
3388 switch (desc.top_level_type()) {
3389 case ControllableDescriptor::NamedRoute:
3391 std::string str = desc.top_level_name();
3392 if (str == "Master" || str == "master") {
3394 } else if (str == "control" || str == "listen") {
3397 r = route_by_name (desc.top_level_name());
3402 case ControllableDescriptor::RemoteControlID:
3403 r = route_by_remote_id (desc.rid());
3406 case ControllableDescriptor::SelectionCount:
3407 r = route_by_selected_count (desc.selection_id());
3415 switch (desc.subtype()) {
3416 case ControllableDescriptor::Gain:
3417 c = r->gain_control ();
3420 case ControllableDescriptor::Trim:
3421 c = r->trim()->gain_control ();
3424 case ControllableDescriptor::Solo:
3425 c = r->solo_control();
3428 case ControllableDescriptor::Mute:
3429 c = r->mute_control();
3432 case ControllableDescriptor::Recenable:
3434 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3437 c = t->rec_enable_control ();
3442 case ControllableDescriptor::PanDirection:
3443 c = r->pan_azimuth_control();
3446 case ControllableDescriptor::PanWidth:
3447 c = r->pan_width_control();
3450 case ControllableDescriptor::PanElevation:
3451 c = r->pan_elevation_control();
3454 case ControllableDescriptor::Balance:
3455 /* XXX simple pan control */
3458 case ControllableDescriptor::PluginParameter:
3460 uint32_t plugin = desc.target (0);
3461 uint32_t parameter_index = desc.target (1);
3463 /* revert to zero based counting */
3469 if (parameter_index > 0) {
3473 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3476 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3477 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3482 case ControllableDescriptor::SendGain: {
3483 uint32_t send = desc.target (0);
3487 c = r->send_level_controllable (send);
3492 /* relax and return a null pointer */
3500 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3503 Stateful::add_instant_xml (node, _path);
3506 if (write_to_config) {
3507 Config->add_instant_xml (node);
3512 Session::instant_xml (const string& node_name)
3514 return Stateful::instant_xml (node_name, _path);
3518 Session::save_history (string snapshot_name)
3526 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3527 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3531 if (snapshot_name.empty()) {
3532 snapshot_name = _current_snapshot_name;
3535 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3536 const string backup_filename = history_filename + backup_suffix;
3537 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3538 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3540 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3541 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3542 error << _("could not backup old history file, current history not saved") << endmsg;
3547 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3549 if (!tree.write (xml_path))
3551 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3553 if (g_remove (xml_path.c_str()) != 0) {
3554 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3555 xml_path, g_strerror (errno)) << endmsg;
3557 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3558 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3559 backup_path, g_strerror (errno)) << endmsg;
3569 Session::restore_history (string snapshot_name)
3573 if (snapshot_name.empty()) {
3574 snapshot_name = _current_snapshot_name;
3577 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3578 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3580 info << "Loading history from " << xml_path << endmsg;
3582 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3583 info << string_compose (_("%1: no history file \"%2\" for this session."),
3584 _name, xml_path) << endmsg;
3588 if (!tree.read (xml_path)) {
3589 error << string_compose (_("Could not understand session history file \"%1\""),
3590 xml_path) << endmsg;
3597 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3600 UndoTransaction* ut = new UndoTransaction ();
3603 ut->set_name(t->property("name")->value());
3604 stringstream ss(t->property("tv-sec")->value());
3606 ss.str(t->property("tv-usec")->value());
3608 ut->set_timestamp(tv);
3610 for (XMLNodeConstIterator child_it = t->children().begin();
3611 child_it != t->children().end(); child_it++)
3613 XMLNode *n = *child_it;
3616 if (n->name() == "MementoCommand" ||
3617 n->name() == "MementoUndoCommand" ||
3618 n->name() == "MementoRedoCommand") {
3620 if ((c = memento_command_factory(n))) {
3624 } else if (n->name() == "NoteDiffCommand") {
3625 PBD::ID id (n->property("midi-source")->value());
3626 boost::shared_ptr<MidiSource> midi_source =
3627 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3629 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3631 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3634 } else if (n->name() == "SysExDiffCommand") {
3636 PBD::ID id (n->property("midi-source")->value());
3637 boost::shared_ptr<MidiSource> midi_source =
3638 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3640 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3642 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3645 } else if (n->name() == "PatchChangeDiffCommand") {
3647 PBD::ID id (n->property("midi-source")->value());
3648 boost::shared_ptr<MidiSource> midi_source =
3649 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3651 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3653 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3656 } else if (n->name() == "StatefulDiffCommand") {
3657 if ((c = stateful_diff_command_factory (n))) {
3658 ut->add_command (c);
3661 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3672 Session::config_changed (std::string p, bool ours)
3678 if (p == "seamless-loop") {
3680 } else if (p == "rf-speed") {
3682 } else if (p == "auto-loop") {
3684 } else if (p == "auto-input") {
3686 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3687 /* auto-input only makes a difference if we're rolling */
3688 set_track_monitor_input_status (!config.get_auto_input());
3691 } else if (p == "punch-in") {
3695 if ((location = _locations->auto_punch_location()) != 0) {
3697 if (config.get_punch_in ()) {
3698 replace_event (SessionEvent::PunchIn, location->start());
3700 remove_event (location->start(), SessionEvent::PunchIn);
3704 } else if (p == "punch-out") {
3708 if ((location = _locations->auto_punch_location()) != 0) {
3710 if (config.get_punch_out()) {
3711 replace_event (SessionEvent::PunchOut, location->end());
3713 clear_events (SessionEvent::PunchOut);
3717 } else if (p == "edit-mode") {
3719 Glib::Threads::Mutex::Lock lm (playlists->lock);
3721 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3722 (*i)->set_edit_mode (Config->get_edit_mode ());
3725 } else if (p == "use-video-sync") {
3727 waiting_for_sync_offset = config.get_use_video_sync();
3729 } else if (p == "mmc-control") {
3731 //poke_midi_thread ();
3733 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3735 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3737 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3739 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3741 } else if (p == "midi-control") {
3743 //poke_midi_thread ();
3745 } else if (p == "raid-path") {
3747 setup_raid_path (config.get_raid_path());
3749 } else if (p == "timecode-format") {
3753 } else if (p == "video-pullup") {
3757 } else if (p == "seamless-loop") {
3759 if (play_loop && transport_rolling()) {
3760 // to reset diskstreams etc
3761 request_play_loop (true);
3764 } else if (p == "rf-speed") {
3766 cumulative_rf_motion = 0;
3769 } else if (p == "click-sound") {
3771 setup_click_sounds (1);
3773 } else if (p == "click-emphasis-sound") {
3775 setup_click_sounds (-1);
3777 } else if (p == "clicking") {
3779 if (Config->get_clicking()) {
3780 if (_click_io && click_data) { // don't require emphasis data
3787 } else if (p == "click-gain") {
3790 _click_gain->gain_control()->set_value (Config->get_click_gain(), Controllable::NoGroup);
3793 } else if (p == "send-mtc") {
3795 if (Config->get_send_mtc ()) {
3796 /* mark us ready to send */
3797 next_quarter_frame_to_send = 0;
3800 } else if (p == "send-mmc") {
3802 _mmc->enable_send (Config->get_send_mmc ());
3804 } else if (p == "midi-feedback") {
3806 session_midi_feedback = Config->get_midi_feedback();
3808 } else if (p == "jack-time-master") {
3810 engine().reset_timebase ();
3812 } else if (p == "native-file-header-format") {
3814 if (!first_file_header_format_reset) {
3815 reset_native_file_format ();
3818 first_file_header_format_reset = false;
3820 } else if (p == "native-file-data-format") {
3822 if (!first_file_data_format_reset) {
3823 reset_native_file_format ();
3826 first_file_data_format_reset = false;
3828 } else if (p == "external-sync") {
3829 if (!config.get_external_sync()) {
3830 drop_sync_source ();
3832 switch_to_sync_source (Config->get_sync_source());
3834 } else if (p == "denormal-model") {
3836 } else if (p == "history-depth") {
3837 set_history_depth (Config->get_history_depth());
3838 } else if (p == "remote-model") {
3839 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3842 } else if (p == "initial-program-change") {
3844 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3847 buf[0] = MIDI::program; // channel zero by default
3848 buf[1] = (Config->get_initial_program_change() & 0x7f);
3850 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3852 } else if (p == "solo-mute-override") {
3853 // catch_up_on_solo_mute_override ();
3854 } else if (p == "listen-position" || p == "pfl-position") {
3855 listen_position_changed ();
3856 } else if (p == "solo-control-is-listen-control") {
3857 solo_control_mode_changed ();
3858 } else if (p == "solo-mute-gain") {
3859 _solo_cut_control->Changed();
3860 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3861 last_timecode_valid = false;
3862 } else if (p == "playback-buffer-seconds") {
3863 AudioSource::allocate_working_buffers (frame_rate());
3864 } else if (p == "ltc-source-port") {
3865 reconnect_ltc_input ();
3866 } else if (p == "ltc-sink-port") {
3867 reconnect_ltc_output ();
3868 } else if (p == "timecode-generator-offset") {
3869 ltc_tx_parse_offset();
3870 } else if (p == "auto-return-target-list") {
3871 follow_playhead_priority ();
3878 Session::set_history_depth (uint32_t d)
3880 _history.set_depth (d);
3884 Session::load_diskstreams_2X (XMLNode const & node, int)
3887 XMLNodeConstIterator citer;
3889 clist = node.children();
3891 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3894 /* diskstreams added automatically by DiskstreamCreated handler */
3895 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3896 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3897 _diskstreams_2X.push_back (dsp);
3899 error << _("Session: unknown diskstream type in XML") << endmsg;
3903 catch (failed_constructor& err) {
3904 error << _("Session: could not load diskstream via XML state") << endmsg;
3912 /** Connect things to the MMC object */
3914 Session::setup_midi_machine_control ()
3916 _mmc = new MIDI::MachineControl;
3918 boost::shared_ptr<AsyncMIDIPort> async_in = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_input_port());
3919 boost::shared_ptr<AsyncMIDIPort> async_out = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_output_port());
3921 if (!async_out || !async_out) {
3925 /* XXXX argh, passing raw pointers back into libmidi++ */
3927 MIDI::Port* mmc_in = async_in.get();
3928 MIDI::Port* mmc_out = async_out.get();
3930 _mmc->set_ports (mmc_in, mmc_out);
3932 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3933 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3934 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3935 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3936 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3937 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3938 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3939 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3940 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3941 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3942 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3943 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3944 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3946 /* also handle MIDI SPP because its so common */
3948 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3949 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3950 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3953 boost::shared_ptr<Controllable>
3954 Session::solo_cut_control() const
3956 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3957 controls in Ardour that currently get presented to the user in the GUI that require
3958 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3960 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3961 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3965 return _solo_cut_control;
3969 Session::save_snapshot_name (const std::string & n)
3971 /* assure Stateful::_instant_xml is loaded
3972 * add_instant_xml() only adds to existing data and defaults
3973 * to use an empty Tree otherwise
3975 instant_xml ("LastUsedSnapshot");
3977 XMLNode* last_used_snapshot = new XMLNode ("LastUsedSnapshot");
3978 last_used_snapshot->add_property ("name", string(n));
3979 add_instant_xml (*last_used_snapshot, false);
3983 Session::set_snapshot_name (const std::string & n)
3985 _current_snapshot_name = n;
3986 save_snapshot_name (n);
3990 Session::rename (const std::string& new_name)
3992 string legal_name = legalize_for_path (new_name);
3998 string const old_sources_root = _session_dir->sources_root();
4000 if (!_writable || (_state_of_the_state & CannotSave)) {
4001 error << _("Cannot rename read-only session.") << endmsg;
4002 return 0; // don't show "messed up" warning
4004 if (record_status() == Recording) {
4005 error << _("Cannot rename session while recording") << endmsg;
4006 return 0; // don't show "messed up" warning
4009 StateProtector stp (this);
4014 * interchange subdirectory
4018 * Backup files are left unchanged and not renamed.
4021 /* Windows requires that we close all files before attempting the
4022 * rename. This works on other platforms, but isn't necessary there.
4023 * Leave it in place for all platforms though, since it may help
4024 * catch issues that could arise if the way Source files work ever
4025 * change (since most developers are not using Windows).
4028 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4029 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4035 /* pass one: not 100% safe check that the new directory names don't
4039 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4043 /* this is a stupid hack because Glib::path_get_dirname() is
4044 * lexical-only, and so passing it /a/b/c/ gives a different
4045 * result than passing it /a/b/c ...
4048 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4049 oldstr = oldstr.substr (0, oldstr.length() - 1);
4052 string base = Glib::path_get_dirname (oldstr);
4054 newstr = Glib::build_filename (base, legal_name);
4056 cerr << "Looking for " << newstr << endl;
4058 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
4059 cerr << " exists\n";
4068 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4074 /* this is a stupid hack because Glib::path_get_dirname() is
4075 * lexical-only, and so passing it /a/b/c/ gives a different
4076 * result than passing it /a/b/c ...
4079 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4080 oldstr = oldstr.substr (0, oldstr.length() - 1);
4083 string base = Glib::path_get_dirname (oldstr);
4084 newstr = Glib::build_filename (base, legal_name);
4086 cerr << "for " << oldstr << " new dir = " << newstr << endl;
4088 cerr << "Rename " << oldstr << " => " << newstr << endl;
4089 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4090 cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4091 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4095 /* Reset path in "session dirs" */
4100 /* reset primary SessionDirectory object */
4103 (*_session_dir) = newstr;
4108 /* now rename directory below session_dir/interchange */
4110 string old_interchange_dir;
4111 string new_interchange_dir;
4113 /* use newstr here because we renamed the path
4114 * (folder/directory) that used to be oldstr to newstr above
4117 v.push_back (newstr);
4118 v.push_back (interchange_dir_name);
4119 v.push_back (Glib::path_get_basename (oldstr));
4121 old_interchange_dir = Glib::build_filename (v);
4124 v.push_back (newstr);
4125 v.push_back (interchange_dir_name);
4126 v.push_back (legal_name);
4128 new_interchange_dir = Glib::build_filename (v);
4130 cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
4132 if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
4133 cerr << string_compose (_("renaming %s as %2 failed (%3)"),
4134 old_interchange_dir, new_interchange_dir,
4137 error << string_compose (_("renaming %s as %2 failed (%3)"),
4138 old_interchange_dir, new_interchange_dir,
4147 oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
4148 newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
4150 cerr << "Rename " << oldstr << " => " << newstr << endl;
4152 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4153 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4154 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4160 oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
4162 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
4163 newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
4165 cerr << "Rename " << oldstr << " => " << newstr << endl;
4167 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4168 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4169 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4174 /* remove old name from recent sessions */
4175 remove_recent_sessions (_path);
4178 /* update file source paths */
4180 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
4181 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4183 string p = fs->path ();
4184 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
4186 SourceFactory::setup_peakfile(i->second, true);
4190 set_snapshot_name (new_name);
4195 /* save state again to get everything just right */
4197 save_state (_current_snapshot_name);
4199 /* add to recent sessions */
4201 store_recent_sessions (new_name, _path);
4207 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
4209 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
4213 if (!tree.read (xmlpath)) {
4221 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
4224 bool found_sr = false;
4225 bool found_data_format = false;
4227 if (get_session_info_from_path (tree, xmlpath)) {
4233 XMLProperty const * prop;
4234 XMLNode const * root (tree.root());
4236 if ((prop = root->property (X_("sample-rate"))) != 0) {
4237 sample_rate = atoi (prop->value());
4241 const XMLNodeList& children (root->children());
4242 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
4243 const XMLNode* child = *c;
4244 if (child->name() == "Config") {
4245 const XMLNodeList& options (child->children());
4246 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
4247 XMLNode const * option = *oc;
4248 XMLProperty const * name = option->property("name");
4254 if (name->value() == "native-file-data-format") {
4255 XMLProperty const * value = option->property ("value");
4257 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
4259 found_data_format = true;
4265 if (found_data_format) {
4270 return !(found_sr && found_data_format); // zero if they are both found
4274 Session::get_snapshot_from_instant (const std::string& session_dir)
4276 std::string instant_xml_path = Glib::build_filename (session_dir, "instant.xml");
4278 if (!Glib::file_test (instant_xml_path, Glib::FILE_TEST_EXISTS)) {
4283 if (!tree.read (instant_xml_path)) {
4287 XMLProperty const * prop;
4288 XMLNode *last_used_snapshot = tree.root()->child("LastUsedSnapshot");
4289 if (last_used_snapshot && (prop = last_used_snapshot->property ("name")) != 0) {
4290 return prop->value();
4296 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
4297 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
4300 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
4304 SourcePathMap source_path_map;
4306 boost::shared_ptr<AudioFileSource> afs;
4311 Glib::Threads::Mutex::Lock lm (source_lock);
4313 cerr << " total sources = " << sources.size();
4315 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4316 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4322 if (fs->within_session()) {
4326 if (source_path_map.find (fs->path()) != source_path_map.end()) {
4327 source_path_map[fs->path()].push_back (fs);
4329 SeveralFileSources v;
4331 source_path_map.insert (make_pair (fs->path(), v));
4337 cerr << " fsources = " << total << endl;
4339 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
4341 /* tell caller where we are */
4343 string old_path = i->first;
4345 callback (n, total, old_path);
4347 cerr << old_path << endl;
4351 switch (i->second.front()->type()) {
4352 case DataType::AUDIO:
4353 new_path = new_audio_source_path_for_embedded (old_path);
4356 case DataType::MIDI:
4357 /* XXX not implemented yet */
4361 if (new_path.empty()) {
4365 cerr << "Move " << old_path << " => " << new_path << endl;
4367 if (!copy_file (old_path, new_path)) {
4368 cerr << "failed !\n";
4372 /* make sure we stop looking in the external
4373 dir/folder. Remember, this is an all-or-nothing
4374 operations, it doesn't merge just some files.
4376 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
4378 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
4379 (*f)->set_path (new_path);
4384 save_state ("", false, false);
4390 bool accept_all_files (string const &, void *)
4396 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4398 /* 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.
4403 make_new_media_path (string old_path, string new_session_folder, string new_session_path)
4405 /* typedir is the "midifiles" or "audiofiles" etc. part of the path. */
4407 string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4409 v.push_back (new_session_folder); /* full path */
4410 v.push_back (interchange_dir_name);
4411 v.push_back (new_session_path); /* just one directory/folder */
4412 v.push_back (typedir);
4413 v.push_back (Glib::path_get_basename (old_path));
4415 return Glib::build_filename (v);
4419 Session::save_as (SaveAs& saveas)
4421 vector<string> files;
4422 string current_folder = Glib::path_get_dirname (_path);
4423 string new_folder = legalize_for_path (saveas.new_name);
4424 string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4425 int64_t total_bytes = 0;
4429 int32_t internal_file_cnt = 0;
4431 vector<string> do_not_copy_extensions;
4432 do_not_copy_extensions.push_back (statefile_suffix);
4433 do_not_copy_extensions.push_back (pending_suffix);
4434 do_not_copy_extensions.push_back (backup_suffix);
4435 do_not_copy_extensions.push_back (temp_suffix);
4436 do_not_copy_extensions.push_back (history_suffix);
4438 /* get total size */
4440 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4442 /* need to clear this because
4443 * find_files_matching_filter() is cumulative
4448 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4450 all += files.size();
4452 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4454 g_stat ((*i).c_str(), &gsb);
4455 total_bytes += gsb.st_size;
4459 /* save old values so we can switch back if we are not switching to the new session */
4461 string old_path = _path;
4462 string old_name = _name;
4463 string old_snapshot = _current_snapshot_name;
4464 string old_sd = _session_dir->root_path();
4465 vector<string> old_search_path[DataType::num_types];
4466 string old_config_search_path[DataType::num_types];
4468 old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4469 old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4470 old_config_search_path[DataType::AUDIO] = config.get_audio_search_path ();
4471 old_config_search_path[DataType::MIDI] = config.get_midi_search_path ();
4473 /* switch session directory */
4475 (*_session_dir) = to_dir;
4477 /* create new tree */
4479 if (!_session_dir->create()) {
4480 saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4485 /* copy all relevant files. Find each location in session_dirs,
4486 * and copy files from there to target.
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 const size_t prefix_len = (*sd).path.size();
4499 /* Work just on the files within this session dir */
4501 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4503 /* add dir separator to protect against collisions with
4504 * track names (e.g. track named "audiofiles" or
4508 static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
4509 static const std::string midifile_dir_string = string (midi_dir_name) + G_DIR_SEPARATOR;
4510 static const std::string analysis_dir_string = analysis_dir() + G_DIR_SEPARATOR;
4512 /* copy all the files. Handling is different for media files
4513 than others because of the *silly* subtree we have below the interchange
4514 folder. That really was a bad idea, but I'm not fixing it as part of
4515 implementing ::save_as().
4518 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4520 std::string from = *i;
4523 string filename = Glib::path_get_basename (from);
4524 std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
4525 if (filename == ".DS_STORE") {
4530 if (from.find (audiofile_dir_string) != string::npos) {
4532 /* audio file: only copy if asked */
4534 if (saveas.include_media && saveas.copy_media) {
4536 string to = make_new_media_path (*i, to_dir, new_folder);
4538 info << "media file copying from " << from << " to " << to << endmsg;
4540 if (!copy_file (from, to)) {
4541 throw Glib::FileError (Glib::FileError::IO_ERROR,
4542 string_compose(_("\ncopying \"%1\" failed !"), from));
4546 /* we found media files inside the session folder */
4548 internal_file_cnt++;
4550 } else if (from.find (midifile_dir_string) != string::npos) {
4552 /* midi file: always copy unless
4553 * creating an empty new session
4556 if (saveas.include_media) {
4558 string to = make_new_media_path (*i, to_dir, new_folder);
4560 info << "media file copying from " << from << " to " << to << endmsg;
4562 if (!copy_file (from, to)) {
4563 throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4567 /* we found media files inside the session folder */
4569 internal_file_cnt++;
4571 } else if (from.find (analysis_dir_string) != string::npos) {
4573 /* make sure analysis dir exists in
4574 * new session folder, but we're not
4575 * copying analysis files here, see
4579 (void) g_mkdir_with_parents (analysis_dir().c_str(), 775);
4584 /* normal non-media file. Don't copy state, history, etc.
4587 bool do_copy = true;
4589 for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
4590 if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
4591 /* end of filename matches extension, do not copy file */
4597 if (!saveas.copy_media && from.find (peakfile_suffix) != string::npos) {
4598 /* don't copy peakfiles if
4599 * we're not copying media
4605 string to = Glib::build_filename (to_dir, from.substr (prefix_len));
4607 info << "attempting to make directory/folder " << to << endmsg;
4609 if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
4610 throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
4613 info << "attempting to copy " << from << " to " << to << endmsg;
4615 if (!copy_file (from, to)) {
4616 throw Glib::FileError (Glib::FileError::IO_ERROR,
4617 string_compose(_("\ncopying \"%1\" failed !"), from));
4622 /* measure file size even if we're not going to copy so that our Progress
4623 signals are correct, since we included these do-not-copy files
4624 in the computation of the total size and file count.
4628 g_stat (from.c_str(), &gsb);
4629 copied += gsb.st_size;
4632 double fraction = (double) copied / total_bytes;
4634 bool keep_going = true;
4636 if (saveas.copy_media) {
4638 /* no need or expectation of this if
4639 * media is not being copied, because
4640 * it will be fast(ish).
4643 /* tell someone "X percent, file M of N"; M is one-based */
4645 boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
4653 throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
4659 /* copy optional folders, if any */
4661 string old = plugins_dir ();
4662 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4663 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4664 copy_files (old, newdir);
4667 old = externals_dir ();
4668 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4669 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4670 copy_files (old, newdir);
4673 old = automation_dir ();
4674 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4675 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4676 copy_files (old, newdir);
4679 if (saveas.include_media) {
4681 if (saveas.copy_media) {
4682 #ifndef PLATFORM_WINDOWS
4683 /* There are problems with analysis files on
4684 * Windows, because they used a colon in their
4685 * names as late as 4.0. Colons are not legal
4686 * under Windows even if NTFS allows them.
4688 * This is a tricky problem to solve so for
4689 * just don't copy these files. They will be
4690 * regenerated as-needed anyway, subject to the
4691 * existing issue that the filenames will be
4692 * rejected by Windows, which is a separate
4693 * problem (though related).
4696 /* only needed if we are copying media, since the
4697 * analysis data refers to media data
4700 old = analysis_dir ();
4701 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4702 string newdir = Glib::build_filename (to_dir, "analysis");
4703 copy_files (old, newdir);
4705 #endif /* PLATFORM_WINDOWS */
4711 set_snapshot_name (saveas.new_name);
4712 _name = saveas.new_name;
4714 if (saveas.include_media && !saveas.copy_media) {
4716 /* reset search paths of the new session (which we're pretending to be right now) to
4717 include the original session search path, so we can still find all audio.
4720 if (internal_file_cnt) {
4721 for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
4722 ensure_search_path_includes (*s, DataType::AUDIO);
4723 cerr << "be sure to include " << *s << " for audio" << endl;
4726 /* we do not do this for MIDI because we copy
4727 all MIDI files if saveas.include_media is
4733 bool was_dirty = dirty ();
4735 save_state ("", false, false, !saveas.include_media);
4736 save_default_options ();
4738 if (saveas.copy_media && saveas.copy_external) {
4739 if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
4740 throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
4744 saveas.final_session_folder_name = _path;
4746 store_recent_sessions (_name, _path);
4748 if (!saveas.switch_to) {
4750 /* switch back to the way things were */
4754 set_snapshot_name (old_snapshot);
4756 (*_session_dir) = old_sd;
4762 if (internal_file_cnt) {
4763 /* reset these to their original values */
4764 config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
4765 config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
4770 /* prune session dirs, and update disk space statistics
4775 session_dirs.clear ();
4776 session_dirs.push_back (sp);
4777 refresh_disk_space ();
4779 /* ensure that all existing tracks reset their current capture source paths
4781 reset_write_sources (true, true);
4783 /* the copying above was based on actually discovering files, not just iterating over the sources list.
4784 But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
4787 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4788 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4794 if (fs->within_session()) {
4795 string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
4796 fs->set_path (newpath);
4801 } catch (Glib::FileError& e) {
4803 saveas.failure_message = e.what();
4805 /* recursively remove all the directories */
4807 remove_directory (to_dir);
4815 saveas.failure_message = _("unknown reason");
4817 /* recursively remove all the directories */
4819 remove_directory (to_dir);