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 */
254 midi_clock = new MidiClockTicker ();
255 midi_clock->set_session (this);
257 /* crossfades require sample rate knowledge */
259 SndFileSource::setup_standard_crossfades (*this, frame_rate());
260 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
262 AudioDiskstream::allocate_working_buffers();
263 refresh_disk_space ();
265 /* we're finally ready to call set_state() ... all objects have
266 * been created, the engine is running.
270 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
274 // set_state() will call setup_raid_path(), but if it's a new session we need
275 // to call setup_raid_path() here.
276 setup_raid_path (_path);
281 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
282 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
284 Config->map_parameters (ff);
285 config.map_parameters (ft);
286 _butler->map_parameters ();
288 /* Reset all panners */
290 Delivery::reset_panners ();
292 /* this will cause the CPM to instantiate any protocols that are in use
293 * (or mandatory), which will pass it this Session, and then call
294 * set_state() on each instantiated protocol to match stored state.
297 ControlProtocolManager::instance().set_session (this);
299 /* This must be done after the ControlProtocolManager set_session above,
300 as it will set states for ports which the ControlProtocolManager creates.
303 // XXX set state of MIDI::Port's
304 // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
306 /* And this must be done after the MIDI::Manager::set_port_states as
307 * it will try to make connections whose details are loaded by set_port_states.
312 /* Let control protocols know that we are now all connected, so they
313 * could start talking to surfaces if they want to.
316 ControlProtocolManager::instance().midi_connectivity_established ();
318 if (_is_new && !no_auto_connect()) {
319 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
320 auto_connect_master_bus ();
323 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
325 /* update latencies */
327 initialize_latencies ();
329 _locations->added.connect_same_thread (*this, boost::bind (&Session::location_added, this, _1));
330 _locations->removed.connect_same_thread (*this, boost::bind (&Session::location_removed, this, _1));
331 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
333 } catch (AudioEngine::PortRegistrationFailure& err) {
334 /* handle this one in a different way than all others, so that its clear what happened */
335 error << err.what() << endmsg;
341 BootMessage (_("Reset Remote Controls"));
343 // send_full_time_code (0);
344 _engine.transport_locate (0);
346 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
347 send_immediate_mmc (MIDI::MachineControlCommand (Timecode::Time ()));
349 MIDI::Name::MidiPatchManager::instance().add_search_path (session_directory().midi_patch_path() );
352 /* initial program change will be delivered later; see ::config_changed() */
354 _state_of_the_state = Clean;
356 Port::set_connecting_blocked (false);
358 DirtyChanged (); /* EMIT SIGNAL */
362 } else if (state_was_pending) {
364 remove_pending_capture_state ();
365 state_was_pending = false;
368 /* Now, finally, we can fill the playback buffers */
370 BootMessage (_("Filling playback buffers"));
372 boost::shared_ptr<RouteList> rl = routes.reader();
373 for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
374 boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<Track> (*r);
375 if (trk && !trk->hidden()) {
376 trk->seek (_transport_frame, true);
384 Session::session_loaded ()
388 _state_of_the_state = Clean;
390 DirtyChanged (); /* EMIT SIGNAL */
394 } else if (state_was_pending) {
396 remove_pending_capture_state ();
397 state_was_pending = false;
400 /* Now, finally, we can fill the playback buffers */
402 BootMessage (_("Filling playback buffers"));
403 force_locate (_transport_frame, false);
407 Session::raid_path () const
409 Searchpath raid_search_path;
411 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
412 raid_search_path += (*i).path;
415 return raid_search_path.to_string ();
419 Session::setup_raid_path (string path)
428 session_dirs.clear ();
430 Searchpath search_path(path);
431 Searchpath sound_search_path;
432 Searchpath midi_search_path;
434 for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
436 sp.blocks = 0; // not needed
437 session_dirs.push_back (sp);
439 SessionDirectory sdir(sp.path);
441 sound_search_path += sdir.sound_path ();
442 midi_search_path += sdir.midi_path ();
445 // reset the round-robin soundfile path thingie
446 last_rr_session_dir = session_dirs.begin();
450 Session::path_is_within_session (const std::string& path)
452 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
453 if (PBD::path_is_within (i->path, path)) {
461 Session::ensure_subdirs ()
465 dir = session_directory().peak_path();
467 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
468 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
472 dir = session_directory().sound_path();
474 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
475 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
479 dir = session_directory().midi_path();
481 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
482 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
486 dir = session_directory().dead_path();
488 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
489 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
493 dir = session_directory().export_path();
495 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
496 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
500 dir = analysis_dir ();
502 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
503 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
507 dir = plugins_dir ();
509 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
510 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
514 dir = externals_dir ();
516 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
517 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
524 /** @param session_template directory containing session template, or empty.
525 * Caller must not hold process lock.
528 Session::create (const string& session_template, BusProfile* bus_profile)
530 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
531 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
535 if (ensure_subdirs ()) {
539 _writable = exists_and_writable (_path);
541 if (!session_template.empty()) {
542 string in_path = (ARDOUR::Profile->get_trx () ? session_template : session_template_dir_to_file (session_template));
544 FILE* in = g_fopen (in_path.c_str(), "rb");
547 /* no need to call legalize_for_path() since the string
548 * in session_template is already a legal path name
550 string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
552 FILE* out = g_fopen (out_path.c_str(), "wb");
556 stringstream new_session;
559 size_t charsRead = fread (buf, sizeof(char), 1024, in);
562 error << string_compose (_("Error reading session template file %1 (%2)"), in_path, strerror (errno)) << endmsg;
567 if (charsRead == 0) {
570 new_session.write (buf, charsRead);
574 string file_contents = new_session.str();
575 size_t writeSize = file_contents.length();
576 if (fwrite (file_contents.c_str(), sizeof(char), writeSize, out) != writeSize) {
577 error << string_compose (_("Error writing session template file %1 (%2)"), out_path, strerror (errno)) << endmsg;
585 if (!ARDOUR::Profile->get_trx()) {
586 /* Copy plugin state files from template to new session */
587 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
588 copy_recurse (template_plugins, plugins_dir ());
594 error << string_compose (_("Could not open %1 for writing session template"), out_path)
601 error << string_compose (_("Could not open session template %1 for reading"), in_path)
608 if (Profile->get_trx()) {
610 /* set initial start + end point : ARDOUR::Session::session_end_shift long.
611 Remember that this is a brand new session. Sessions
612 loaded from saved state will get this range from the saved state.
615 set_session_range_location (0, 0);
617 /* Initial loop location, from absolute zero, length 10 seconds */
619 Location* loc = new Location (*this, 0, 10.0 * _engine.sample_rate(), _("Loop"), Location::IsAutoLoop);
620 _locations->add (loc, true);
621 set_auto_loop_location (loc);
624 _state_of_the_state = Clean;
626 /* set up Master Out and Control Out if necessary */
631 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
633 // Waves Tracks: always create master bus for Tracks
634 if (ARDOUR::Profile->get_trx() || bus_profile->master_out_channels) {
635 boost::shared_ptr<Route> r (new Route (*this, _("Master"), Route::MasterOut, DataType::AUDIO));
639 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
640 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
643 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
644 r->input()->ensure_io (count, false, this);
645 r->output()->ensure_io (count, false, this);
651 /* prohibit auto-connect to master, because there isn't one */
652 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
656 add_routes (rl, false, false, false);
659 // Waves Tracks: Skip this. Always use autoconnection for Tracks
660 if (!ARDOUR::Profile->get_trx()) {
662 /* this allows the user to override settings with an environment variable.
665 if (no_auto_connect()) {
666 bus_profile->input_ac = AutoConnectOption (0);
667 bus_profile->output_ac = AutoConnectOption (0);
670 Config->set_input_auto_connect (bus_profile->input_ac);
671 Config->set_output_auto_connect (bus_profile->output_ac);
675 if (Config->get_use_monitor_bus() && bus_profile) {
676 add_monitor_section ();
683 Session::maybe_write_autosave()
685 if (dirty() && record_status() != Recording) {
686 save_state("", true);
691 Session::remove_pending_capture_state ()
693 std::string pending_state_file_path(_session_dir->root_path());
695 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
697 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
699 if (g_remove (pending_state_file_path.c_str()) != 0) {
700 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
701 pending_state_file_path, g_strerror (errno)) << endmsg;
705 /** Rename a state file.
706 * @param old_name Old snapshot name.
707 * @param new_name New snapshot name.
710 Session::rename_state (string old_name, string new_name)
712 if (old_name == _current_snapshot_name || old_name == _name) {
713 /* refuse to rename the current snapshot or the "main" one */
717 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
718 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
720 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
721 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
723 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
724 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
725 old_name, new_name, g_strerror(errno)) << endmsg;
729 /** Remove a state file.
730 * @param snapshot_name Snapshot name.
733 Session::remove_state (string snapshot_name)
735 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
736 // refuse to remove the current snapshot or the "main" one
740 std::string xml_path(_session_dir->root_path());
742 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
744 if (!create_backup_file (xml_path)) {
745 // don't remove it if a backup can't be made
746 // create_backup_file will log the error.
751 if (g_remove (xml_path.c_str()) != 0) {
752 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
753 xml_path, g_strerror (errno)) << endmsg;
757 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
759 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot, bool template_only)
762 std::string xml_path(_session_dir->root_path());
764 /* prevent concurrent saves from different threads */
766 Glib::Threads::Mutex::Lock lm (save_state_lock);
768 if (!_writable || (_state_of_the_state & CannotSave)) {
772 if (g_atomic_int_get(&_suspend_save)) {
776 _save_queued = false;
778 if (!_engine.connected ()) {
779 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
786 const int64_t save_start_time = g_get_monotonic_time();
789 /* tell sources we're saving first, in case they write out to a new file
790 * which should be saved with the state rather than the old one */
791 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
793 i->second->session_saved();
794 } catch (Evoral::SMF::FileError& e) {
795 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
799 SessionSaveUnderway (); /* EMIT SIGNAL */
801 bool mark_as_clean = true;
803 if (!snapshot_name.empty() && !switch_to_snapshot) {
804 mark_as_clean = false;
808 mark_as_clean = false;
809 tree.set_root (&get_template());
811 tree.set_root (&get_state());
814 if (snapshot_name.empty()) {
815 snapshot_name = _current_snapshot_name;
816 } else if (switch_to_snapshot) {
817 set_snapshot_name (snapshot_name);
820 assert (!snapshot_name.empty());
824 /* proper save: use statefile_suffix (.ardour in English) */
826 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
828 /* make a backup copy of the old file */
830 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
831 // create_backup_file will log the error
837 /* pending save: use pending_suffix (.pending in English) */
838 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
841 std::string tmp_path(_session_dir->root_path());
842 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
844 cerr << "actually writing state to " << tmp_path << endl;
846 if (!tree.write (tmp_path)) {
847 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
848 if (g_remove (tmp_path.c_str()) != 0) {
849 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
850 tmp_path, g_strerror (errno)) << endmsg;
856 cerr << "renaming state to " << xml_path << endl;
858 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
859 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
860 tmp_path, xml_path, g_strerror(errno)) << endmsg;
861 if (g_remove (tmp_path.c_str()) != 0) {
862 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
863 tmp_path, g_strerror (errno)) << endmsg;
871 save_history (snapshot_name);
874 bool was_dirty = dirty();
876 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
879 DirtyChanged (); /* EMIT SIGNAL */
883 StateSaved (snapshot_name); /* EMIT SIGNAL */
887 const int64_t elapsed_time_us = g_get_monotonic_time() - save_start_time;
888 cerr << "saved state in " << fixed << setprecision (1) << elapsed_time_us / 1000. << " ms\n";
894 Session::restore_state (string snapshot_name)
896 if (load_state (snapshot_name) == 0) {
897 set_state (*state_tree->root(), Stateful::loading_state_version);
904 Session::load_state (string snapshot_name)
909 state_was_pending = false;
911 /* check for leftover pending state from a crashed capture attempt */
913 std::string xmlpath(_session_dir->root_path());
914 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
916 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
918 /* there is pending state from a crashed capture attempt */
920 boost::optional<int> r = AskAboutPendingState();
921 if (r.get_value_or (1)) {
922 state_was_pending = true;
926 if (!state_was_pending) {
927 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
930 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
931 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
932 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
933 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
938 state_tree = new XMLTree;
942 _writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
944 if (!state_tree->read (xmlpath)) {
945 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
951 XMLNode& root (*state_tree->root());
953 if (root.name() != X_("Session")) {
954 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
960 const XMLProperty* prop;
962 if ((prop = root.property ("version")) == 0) {
963 /* no version implies very old version of Ardour */
964 Stateful::loading_state_version = 1000;
966 if (prop->value().find ('.') != string::npos) {
967 /* old school version format */
968 if (prop->value()[0] == '2') {
969 Stateful::loading_state_version = 2000;
971 Stateful::loading_state_version = 3000;
974 Stateful::loading_state_version = atoi (prop->value());
978 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
980 std::string backup_path(_session_dir->root_path());
981 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
982 backup_path = Glib::build_filename (backup_path, backup_filename);
984 // only create a backup for a given statefile version once
986 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
988 VersionMismatch (xmlpath, backup_path);
990 if (!copy_file (xmlpath, backup_path)) {;
996 save_snapshot_name (snapshot_name);
1002 Session::load_options (const XMLNode& node)
1004 LocaleGuard lg (X_("C"));
1005 config.set_variables (node);
1010 Session::save_default_options ()
1012 return config.save_state();
1016 Session::get_state()
1022 Session::get_template()
1024 /* if we don't disable rec-enable, diskstreams
1025 will believe they need to store their capture
1026 sources in their state node.
1029 disable_record (false);
1031 return state(false);
1035 Session::state (bool full_state)
1037 XMLNode* node = new XMLNode("Session");
1041 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
1042 node->add_property("version", buf);
1044 /* store configuration settings */
1048 node->add_property ("name", _name);
1049 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
1050 node->add_property ("sample-rate", buf);
1052 if (session_dirs.size() > 1) {
1056 vector<space_and_path>::iterator i = session_dirs.begin();
1057 vector<space_and_path>::iterator next;
1059 ++i; /* skip the first one */
1063 while (i != session_dirs.end()) {
1067 if (next != session_dirs.end()) {
1068 p += G_SEARCHPATH_SEPARATOR;
1077 child = node->add_child ("Path");
1078 child->add_content (p);
1082 /* save the ID counter */
1084 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1085 node->add_property ("id-counter", buf);
1087 /* save the event ID counter */
1089 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1090 node->add_property ("event-counter", buf);
1092 /* various options */
1094 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
1095 if (!midi_port_nodes.empty()) {
1096 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
1097 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
1098 midi_port_stuff->add_child_nocopy (**n);
1100 node->add_child_nocopy (*midi_port_stuff);
1103 node->add_child_nocopy (config.get_variables ());
1105 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1107 child = node->add_child ("Sources");
1110 Glib::Threads::Mutex::Lock sl (source_lock);
1112 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1114 /* Don't save information about non-file Sources, or
1115 * about non-destructive file sources that are empty
1116 * and unused by any regions.
1119 boost::shared_ptr<FileSource> fs;
1121 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1123 if (!fs->destructive()) {
1124 if (fs->empty() && !fs->used()) {
1129 child->add_child_nocopy (siter->second->get_state());
1134 child = node->add_child ("Regions");
1137 Glib::Threads::Mutex::Lock rl (region_lock);
1138 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1139 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1140 boost::shared_ptr<Region> r = i->second;
1141 /* only store regions not attached to playlists */
1142 if (r->playlist() == 0) {
1143 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1144 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1146 child->add_child_nocopy (r->get_state ());
1151 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1153 if (!cassocs.empty()) {
1154 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1156 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1158 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1159 i->first->id().print (buf, sizeof (buf));
1160 can->add_property (X_("copy"), buf);
1161 i->second->id().print (buf, sizeof (buf));
1162 can->add_property (X_("original"), buf);
1163 ca->add_child_nocopy (*can);
1173 node->add_child_nocopy (_locations->get_state());
1176 Locations loc (*this);
1177 // for a template, just create a new Locations, populate it
1178 // with the default start and end, and get the state for that.
1179 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1180 range->set (max_framepos, 0);
1182 XMLNode& locations_state = loc.get_state();
1184 if (ARDOUR::Profile->get_trx() && _locations) {
1185 // For tracks we need stored the Auto Loop Range and all MIDI markers.
1186 for (Locations::LocationList::const_iterator i = _locations->list ().begin (); i != _locations->list ().end (); ++i) {
1187 if ((*i)->is_mark () || (*i)->is_auto_loop ()) {
1188 locations_state.add_child_nocopy ((*i)->get_state ());
1192 node->add_child_nocopy (locations_state);
1195 child = node->add_child ("Bundles");
1197 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1198 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1199 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1201 child->add_child_nocopy (b->get_state());
1206 child = node->add_child ("Routes");
1208 boost::shared_ptr<RouteList> r = routes.reader ();
1210 RoutePublicOrderSorter cmp;
1211 RouteList public_order (*r);
1212 public_order.sort (cmp);
1214 /* the sort should have put control outs first */
1217 assert (_monitor_out == public_order.front());
1220 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1221 if (!(*i)->is_auditioner()) {
1223 child->add_child_nocopy ((*i)->get_state());
1225 child->add_child_nocopy ((*i)->get_template());
1231 playlists->add_state (node, full_state);
1233 child = node->add_child ("RouteGroups");
1234 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1235 child->add_child_nocopy ((*i)->get_state());
1239 XMLNode* gain_child = node->add_child ("Click");
1240 gain_child->add_child_nocopy (_click_io->state (full_state));
1241 gain_child->add_child_nocopy (_click_gain->state (full_state));
1245 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1246 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1250 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1251 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1254 node->add_child_nocopy (_speakers->get_state());
1255 node->add_child_nocopy (_tempo_map->get_state());
1256 node->add_child_nocopy (get_control_protocol_state());
1259 node->add_child_copy (*_extra_xml);
1263 Glib::Threads::Mutex::Lock lm (lua_lock);
1266 luabridge::LuaRef savedstate ((*_lua_save)());
1267 saved = savedstate.cast<std::string>();
1269 lua.collect_garbage ();
1272 gchar* b64 = g_base64_encode ((const guchar*)saved.c_str (), saved.size ());
1273 std::string b64s (b64);
1276 XMLNode* script_node = new XMLNode (X_("Script"));
1277 script_node->add_property (X_("lua"), LUA_VERSION);
1278 script_node->add_content (b64s);
1279 node->add_child_nocopy (*script_node);
1286 Session::get_control_protocol_state ()
1288 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1289 return cpm.get_state();
1293 Session::set_state (const XMLNode& node, int version)
1297 const XMLProperty* prop;
1300 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1302 if (node.name() != X_("Session")) {
1303 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1307 if ((prop = node.property ("name")) != 0) {
1308 _name = prop->value ();
1311 if ((prop = node.property (X_("sample-rate"))) != 0) {
1313 _nominal_frame_rate = atoi (prop->value());
1315 if (_nominal_frame_rate != _current_frame_rate) {
1316 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1317 if (r.get_value_or (0)) {
1323 setup_raid_path(_session_dir->root_path());
1325 if ((prop = node.property (X_("id-counter"))) != 0) {
1327 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1328 ID::init_counter (x);
1330 /* old sessions used a timebased counter, so fake
1331 the startup ID counter based on a standard
1336 ID::init_counter (now);
1339 if ((prop = node.property (X_("event-counter"))) != 0) {
1340 Evoral::init_event_id_counter (atoi (prop->value()));
1344 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1345 _midi_ports->set_midi_port_states (child->children());
1348 IO::disable_connecting ();
1350 Stateful::save_extra_xml (node);
1352 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1353 load_options (*child);
1354 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1355 load_options (*child);
1357 error << _("Session: XML state has no options section") << endmsg;
1360 if (version >= 3000) {
1361 if ((child = find_named_node (node, "Metadata")) == 0) {
1362 warning << _("Session: XML state has no metadata section") << endmsg;
1363 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1368 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1369 _speakers->set_state (*child, version);
1372 if ((child = find_named_node (node, "Sources")) == 0) {
1373 error << _("Session: XML state has no sources section") << endmsg;
1375 } else if (load_sources (*child)) {
1379 if ((child = find_named_node (node, "TempoMap")) == 0) {
1380 error << _("Session: XML state has no Tempo Map section") << endmsg;
1382 } else if (_tempo_map->set_state (*child, version)) {
1386 if ((child = find_named_node (node, "Locations")) == 0) {
1387 error << _("Session: XML state has no locations section") << endmsg;
1389 } else if (_locations->set_state (*child, version)) {
1393 locations_changed ();
1395 if (_session_range_location) {
1396 AudioFileSource::set_header_position_offset (_session_range_location->start());
1399 if ((child = find_named_node (node, "Regions")) == 0) {
1400 error << _("Session: XML state has no Regions section") << endmsg;
1402 } else if (load_regions (*child)) {
1406 if ((child = find_named_node (node, "Playlists")) == 0) {
1407 error << _("Session: XML state has no playlists section") << endmsg;
1409 } else if (playlists->load (*this, *child)) {
1413 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1415 } else if (playlists->load_unused (*this, *child)) {
1419 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1420 if (load_compounds (*child)) {
1425 if (version >= 3000) {
1426 if ((child = find_named_node (node, "Bundles")) == 0) {
1427 warning << _("Session: XML state has no bundles section") << endmsg;
1430 /* We can't load Bundles yet as they need to be able
1431 to convert from port names to Port objects, which can't happen until
1433 _bundle_xml_node = new XMLNode (*child);
1437 if (version < 3000) {
1438 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1439 error << _("Session: XML state has no diskstreams section") << endmsg;
1441 } else if (load_diskstreams_2X (*child, version)) {
1446 if ((child = find_named_node (node, "Routes")) == 0) {
1447 error << _("Session: XML state has no routes section") << endmsg;
1449 } else if (load_routes (*child, version)) {
1453 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1454 _diskstreams_2X.clear ();
1456 if (version >= 3000) {
1458 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1459 error << _("Session: XML state has no route groups section") << endmsg;
1461 } else if (load_route_groups (*child, version)) {
1465 } else if (version < 3000) {
1467 if ((child = find_named_node (node, "EditGroups")) == 0) {
1468 error << _("Session: XML state has no edit groups section") << endmsg;
1470 } else if (load_route_groups (*child, version)) {
1474 if ((child = find_named_node (node, "MixGroups")) == 0) {
1475 error << _("Session: XML state has no mix groups section") << endmsg;
1477 } else if (load_route_groups (*child, version)) {
1482 if ((child = find_named_node (node, "Click")) == 0) {
1483 warning << _("Session: XML state has no click section") << endmsg;
1484 } else if (_click_io) {
1485 setup_click_state (&node);
1488 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1489 ControlProtocolManager::instance().set_state (*child, version);
1492 if ((child = find_named_node (node, "Script"))) {
1493 for (XMLNodeList::const_iterator n = child->children ().begin (); n != child->children ().end (); ++n) {
1494 if (!(*n)->is_content ()) { continue; }
1496 guchar* buf = g_base64_decode ((*n)->content ().c_str (), &size);
1498 Glib::Threads::Mutex::Lock lm (lua_lock);
1499 (*_lua_load)(std::string ((const char*)buf, size));
1500 } catch (luabridge::LuaException const& e) {
1501 cerr << "LuaException:" << e.what () << endl;
1507 update_route_record_state ();
1509 /* here beginneth the second phase ... */
1510 set_snapshot_name (_current_snapshot_name);
1512 StateReady (); /* EMIT SIGNAL */
1525 Session::load_routes (const XMLNode& node, int version)
1528 XMLNodeConstIterator niter;
1529 RouteList new_routes;
1531 nlist = node.children();
1535 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1537 boost::shared_ptr<Route> route;
1538 if (version < 3000) {
1539 route = XMLRouteFactory_2X (**niter, version);
1541 route = XMLRouteFactory (**niter, version);
1545 error << _("Session: cannot create Route from XML description.") << endmsg;
1549 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1551 new_routes.push_back (route);
1554 BootMessage (_("Tracks/busses loaded; Adding to Session"));
1556 add_routes (new_routes, false, false, false);
1558 BootMessage (_("Finished adding tracks/busses"));
1563 boost::shared_ptr<Route>
1564 Session::XMLRouteFactory (const XMLNode& node, int version)
1566 boost::shared_ptr<Route> ret;
1568 if (node.name() != "Route") {
1572 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1574 DataType type = DataType::AUDIO;
1575 const XMLProperty* prop = node.property("default-type");
1578 type = DataType (prop->value());
1581 assert (type != DataType::NIL);
1585 boost::shared_ptr<Track> track;
1587 if (type == DataType::AUDIO) {
1588 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1590 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1593 if (track->init()) {
1597 if (track->set_state (node, version)) {
1601 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1602 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1607 enum Route::Flag flags = Route::Flag(0);
1608 const XMLProperty* prop = node.property("flags");
1610 flags = Route::Flag (string_2_enum (prop->value(), flags));
1613 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1615 if (r->init () == 0 && r->set_state (node, version) == 0) {
1616 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1617 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1626 boost::shared_ptr<Route>
1627 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1629 boost::shared_ptr<Route> ret;
1631 if (node.name() != "Route") {
1635 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1637 ds_prop = node.property (X_("diskstream"));
1640 DataType type = DataType::AUDIO;
1641 const XMLProperty* prop = node.property("default-type");
1644 type = DataType (prop->value());
1647 assert (type != DataType::NIL);
1651 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1652 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1656 if (i == _diskstreams_2X.end()) {
1657 error << _("Could not find diskstream for route") << endmsg;
1658 return boost::shared_ptr<Route> ();
1661 boost::shared_ptr<Track> track;
1663 if (type == DataType::AUDIO) {
1664 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1666 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1669 if (track->init()) {
1673 if (track->set_state (node, version)) {
1677 track->set_diskstream (*i);
1679 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1680 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1685 enum Route::Flag flags = Route::Flag(0);
1686 const XMLProperty* prop = node.property("flags");
1688 flags = Route::Flag (string_2_enum (prop->value(), flags));
1691 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1693 if (r->init () == 0 && r->set_state (node, version) == 0) {
1694 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1695 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1705 Session::load_regions (const XMLNode& node)
1708 XMLNodeConstIterator niter;
1709 boost::shared_ptr<Region> region;
1711 nlist = node.children();
1715 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1716 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1717 error << _("Session: cannot create Region from XML description.");
1718 const XMLProperty *name = (**niter).property("name");
1721 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1732 Session::load_compounds (const XMLNode& node)
1734 XMLNodeList calist = node.children();
1735 XMLNodeConstIterator caiter;
1736 XMLProperty *caprop;
1738 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1739 XMLNode* ca = *caiter;
1743 if ((caprop = ca->property (X_("original"))) == 0) {
1746 orig_id = caprop->value();
1748 if ((caprop = ca->property (X_("copy"))) == 0) {
1751 copy_id = caprop->value();
1753 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1754 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1756 if (!orig || !copy) {
1757 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1763 RegionFactory::add_compound_association (orig, copy);
1770 Session::load_nested_sources (const XMLNode& node)
1773 XMLNodeConstIterator niter;
1775 nlist = node.children();
1777 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1778 if ((*niter)->name() == "Source") {
1780 /* it may already exist, so don't recreate it unnecessarily
1783 XMLProperty* prop = (*niter)->property (X_("id"));
1785 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1789 ID source_id (prop->value());
1791 if (!source_by_id (source_id)) {
1794 SourceFactory::create (*this, **niter, true);
1796 catch (failed_constructor& err) {
1797 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1804 boost::shared_ptr<Region>
1805 Session::XMLRegionFactory (const XMLNode& node, bool full)
1807 const XMLProperty* type = node.property("type");
1811 const XMLNodeList& nlist = node.children();
1813 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1814 XMLNode *child = (*niter);
1815 if (child->name() == "NestedSource") {
1816 load_nested_sources (*child);
1820 if (!type || type->value() == "audio") {
1821 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1822 } else if (type->value() == "midi") {
1823 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1826 } catch (failed_constructor& err) {
1827 return boost::shared_ptr<Region> ();
1830 return boost::shared_ptr<Region> ();
1833 boost::shared_ptr<AudioRegion>
1834 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1836 const XMLProperty* prop;
1837 boost::shared_ptr<Source> source;
1838 boost::shared_ptr<AudioSource> as;
1840 SourceList master_sources;
1841 uint32_t nchans = 1;
1844 if (node.name() != X_("Region")) {
1845 return boost::shared_ptr<AudioRegion>();
1848 if ((prop = node.property (X_("channels"))) != 0) {
1849 nchans = atoi (prop->value().c_str());
1852 if ((prop = node.property ("name")) == 0) {
1853 cerr << "no name for this region\n";
1857 if ((prop = node.property (X_("source-0"))) == 0) {
1858 if ((prop = node.property ("source")) == 0) {
1859 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1860 return boost::shared_ptr<AudioRegion>();
1864 PBD::ID s_id (prop->value());
1866 if ((source = source_by_id (s_id)) == 0) {
1867 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1868 return boost::shared_ptr<AudioRegion>();
1871 as = boost::dynamic_pointer_cast<AudioSource>(source);
1873 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1874 return boost::shared_ptr<AudioRegion>();
1877 sources.push_back (as);
1879 /* pickup other channels */
1881 for (uint32_t n=1; n < nchans; ++n) {
1882 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1883 if ((prop = node.property (buf)) != 0) {
1885 PBD::ID id2 (prop->value());
1887 if ((source = source_by_id (id2)) == 0) {
1888 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1889 return boost::shared_ptr<AudioRegion>();
1892 as = boost::dynamic_pointer_cast<AudioSource>(source);
1894 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1895 return boost::shared_ptr<AudioRegion>();
1897 sources.push_back (as);
1901 for (uint32_t n = 0; n < nchans; ++n) {
1902 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1903 if ((prop = node.property (buf)) != 0) {
1905 PBD::ID id2 (prop->value());
1907 if ((source = source_by_id (id2)) == 0) {
1908 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1909 return boost::shared_ptr<AudioRegion>();
1912 as = boost::dynamic_pointer_cast<AudioSource>(source);
1914 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1915 return boost::shared_ptr<AudioRegion>();
1917 master_sources.push_back (as);
1922 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1924 /* a final detail: this is the one and only place that we know how long missing files are */
1926 if (region->whole_file()) {
1927 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1928 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1930 sfp->set_length (region->length());
1935 if (!master_sources.empty()) {
1936 if (master_sources.size() != nchans) {
1937 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1939 region->set_master_sources (master_sources);
1947 catch (failed_constructor& err) {
1948 return boost::shared_ptr<AudioRegion>();
1952 boost::shared_ptr<MidiRegion>
1953 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1955 const XMLProperty* prop;
1956 boost::shared_ptr<Source> source;
1957 boost::shared_ptr<MidiSource> ms;
1960 if (node.name() != X_("Region")) {
1961 return boost::shared_ptr<MidiRegion>();
1964 if ((prop = node.property ("name")) == 0) {
1965 cerr << "no name for this region\n";
1969 if ((prop = node.property (X_("source-0"))) == 0) {
1970 if ((prop = node.property ("source")) == 0) {
1971 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1972 return boost::shared_ptr<MidiRegion>();
1976 PBD::ID s_id (prop->value());
1978 if ((source = source_by_id (s_id)) == 0) {
1979 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1980 return boost::shared_ptr<MidiRegion>();
1983 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1985 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1986 return boost::shared_ptr<MidiRegion>();
1989 sources.push_back (ms);
1992 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1993 /* a final detail: this is the one and only place that we know how long missing files are */
1995 if (region->whole_file()) {
1996 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1997 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1999 sfp->set_length (region->length());
2007 catch (failed_constructor& err) {
2008 return boost::shared_ptr<MidiRegion>();
2013 Session::get_sources_as_xml ()
2016 XMLNode* node = new XMLNode (X_("Sources"));
2017 Glib::Threads::Mutex::Lock lm (source_lock);
2019 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2020 node->add_child_nocopy (i->second->get_state());
2027 Session::reset_write_sources (bool mark_write_complete, bool force)
2029 boost::shared_ptr<RouteList> rl = routes.reader();
2030 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
2031 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
2033 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
2034 tr->reset_write_sources(mark_write_complete, force);
2035 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
2041 Session::load_sources (const XMLNode& node)
2044 XMLNodeConstIterator niter;
2045 boost::shared_ptr<Source> source; /* don't need this but it stops some
2046 * versions of gcc complaining about
2047 * discarded return values.
2050 nlist = node.children();
2054 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2057 if ((source = XMLSourceFactory (**niter)) == 0) {
2058 error << _("Session: cannot create Source from XML description.") << endmsg;
2061 } catch (MissingSource& err) {
2065 if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
2066 error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
2067 PROGRAM_NAME) << endmsg;
2071 if (!no_questions_about_missing_files) {
2072 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
2077 switch (user_choice) {
2079 /* user added a new search location, so try again */
2084 /* user asked to quit the entire session load
2089 no_questions_about_missing_files = true;
2093 no_questions_about_missing_files = true;
2100 case DataType::AUDIO:
2101 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
2104 case DataType::MIDI:
2105 /* The MIDI file is actually missing so
2106 * just create a new one in the same
2107 * location. Do not announce its
2111 if (!Glib::path_is_absolute (err.path)) {
2112 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
2114 /* this should be an unrecoverable error: we would be creating a MIDI file outside
2119 /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
2120 source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
2121 /* reset ID to match the missing one */
2122 source->set_id (**niter);
2123 /* Now we can announce it */
2124 SourceFactory::SourceCreated (source);
2135 boost::shared_ptr<Source>
2136 Session::XMLSourceFactory (const XMLNode& node)
2138 if (node.name() != "Source") {
2139 return boost::shared_ptr<Source>();
2143 /* note: do peak building in another thread when loading session state */
2144 return SourceFactory::create (*this, node, true);
2147 catch (failed_constructor& err) {
2148 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
2149 return boost::shared_ptr<Source>();
2154 Session::save_template (string template_name, bool replace_existing)
2156 if ((_state_of_the_state & CannotSave) || template_name.empty ()) {
2160 bool absolute_path = Glib::path_is_absolute (template_name);
2162 /* directory to put the template in */
2163 std::string template_dir_path;
2165 if (!absolute_path) {
2166 std::string user_template_dir(user_template_directory());
2168 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2169 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2170 user_template_dir, g_strerror (errno)) << endmsg;
2174 template_dir_path = Glib::build_filename (user_template_dir, template_name);
2176 template_dir_path = template_name;
2179 if (!ARDOUR::Profile->get_trx()) {
2180 if (!replace_existing && Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2181 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2182 template_dir_path) << endmsg;
2186 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2187 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2188 template_dir_path, g_strerror (errno)) << endmsg;
2194 std::string template_file_path;
2196 if (ARDOUR::Profile->get_trx()) {
2197 template_file_path = template_name;
2199 if (absolute_path) {
2200 template_file_path = Glib::build_filename (template_dir_path, Glib::path_get_basename (template_dir_path) + template_suffix);
2202 template_file_path = Glib::build_filename (template_dir_path, template_name + template_suffix);
2206 SessionSaveUnderway (); /* EMIT SIGNAL */
2211 PBD::Unwinder<std::string> uw (_template_state_dir, template_dir_path);
2212 tree.set_root (&get_template());
2215 if (!tree.write (template_file_path)) {
2216 error << _("template not saved") << endmsg;
2220 store_recent_templates (template_file_path);
2226 Session::refresh_disk_space ()
2228 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2230 Glib::Threads::Mutex::Lock lm (space_lock);
2232 /* get freespace on every FS that is part of the session path */
2234 _total_free_4k_blocks = 0;
2235 _total_free_4k_blocks_uncertain = false;
2237 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2239 struct statfs statfsbuf;
2240 statfs (i->path.c_str(), &statfsbuf);
2242 double const scale = statfsbuf.f_bsize / 4096.0;
2244 /* See if this filesystem is read-only */
2245 struct statvfs statvfsbuf;
2246 statvfs (i->path.c_str(), &statvfsbuf);
2248 /* f_bavail can be 0 if it is undefined for whatever
2249 filesystem we are looking at; Samba shares mounted
2250 via GVFS are an example of this.
2252 if (statfsbuf.f_bavail == 0) {
2253 /* block count unknown */
2255 i->blocks_unknown = true;
2256 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2257 /* read-only filesystem */
2259 i->blocks_unknown = false;
2261 /* read/write filesystem with known space */
2262 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2263 i->blocks_unknown = false;
2266 _total_free_4k_blocks += i->blocks;
2267 if (i->blocks_unknown) {
2268 _total_free_4k_blocks_uncertain = true;
2271 #elif defined PLATFORM_WINDOWS
2272 vector<string> scanned_volumes;
2273 vector<string>::iterator j;
2274 vector<space_and_path>::iterator i;
2275 DWORD nSectorsPerCluster, nBytesPerSector,
2276 nFreeClusters, nTotalClusters;
2280 _total_free_4k_blocks = 0;
2282 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2283 strncpy (disk_drive, (*i).path.c_str(), 3);
2287 volume_found = false;
2288 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2290 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2291 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2292 i->blocks = (uint32_t)(nFreeBytes / 4096);
2294 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2295 if (0 == j->compare(disk_drive)) {
2296 volume_found = true;
2301 if (!volume_found) {
2302 scanned_volumes.push_back(disk_drive);
2303 _total_free_4k_blocks += i->blocks;
2308 if (0 == _total_free_4k_blocks) {
2309 strncpy (disk_drive, path().c_str(), 3);
2312 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2314 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2315 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2316 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2323 Session::get_best_session_directory_for_new_audio ()
2325 vector<space_and_path>::iterator i;
2326 string result = _session_dir->root_path();
2328 /* handle common case without system calls */
2330 if (session_dirs.size() == 1) {
2334 /* OK, here's the algorithm we're following here:
2336 We want to select which directory to use for
2337 the next file source to be created. Ideally,
2338 we'd like to use a round-robin process so as to
2339 get maximum performance benefits from splitting
2340 the files across multiple disks.
2342 However, in situations without much diskspace, an
2343 RR approach may end up filling up a filesystem
2344 with new files while others still have space.
2345 Its therefore important to pay some attention to
2346 the freespace in the filesystem holding each
2347 directory as well. However, if we did that by
2348 itself, we'd keep creating new files in the file
2349 system with the most space until it was as full
2350 as all others, thus negating any performance
2351 benefits of this RAID-1 like approach.
2353 So, we use a user-configurable space threshold. If
2354 there are at least 2 filesystems with more than this
2355 much space available, we use RR selection between them.
2356 If not, then we pick the filesystem with the most space.
2358 This gets a good balance between the two
2362 refresh_disk_space ();
2364 int free_enough = 0;
2366 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2367 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2372 if (free_enough >= 2) {
2373 /* use RR selection process, ensuring that the one
2377 i = last_rr_session_dir;
2380 if (++i == session_dirs.end()) {
2381 i = session_dirs.begin();
2384 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2385 SessionDirectory sdir(i->path);
2386 if (sdir.create ()) {
2388 last_rr_session_dir = i;
2393 } while (i != last_rr_session_dir);
2397 /* pick FS with the most freespace (and that
2398 seems to actually work ...)
2401 vector<space_and_path> sorted;
2402 space_and_path_ascending_cmp cmp;
2404 sorted = session_dirs;
2405 sort (sorted.begin(), sorted.end(), cmp);
2407 for (i = sorted.begin(); i != sorted.end(); ++i) {
2408 SessionDirectory sdir(i->path);
2409 if (sdir.create ()) {
2411 last_rr_session_dir = i;
2421 Session::automation_dir () const
2423 return Glib::build_filename (_path, automation_dir_name);
2427 Session::analysis_dir () const
2429 return Glib::build_filename (_path, analysis_dir_name);
2433 Session::plugins_dir () const
2435 return Glib::build_filename (_path, plugins_dir_name);
2439 Session::externals_dir () const
2441 return Glib::build_filename (_path, externals_dir_name);
2445 Session::load_bundles (XMLNode const & node)
2447 XMLNodeList nlist = node.children();
2448 XMLNodeConstIterator niter;
2452 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2453 if ((*niter)->name() == "InputBundle") {
2454 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2455 } else if ((*niter)->name() == "OutputBundle") {
2456 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2458 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2467 Session::load_route_groups (const XMLNode& node, int version)
2469 XMLNodeList nlist = node.children();
2470 XMLNodeConstIterator niter;
2474 if (version >= 3000) {
2476 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2477 if ((*niter)->name() == "RouteGroup") {
2478 RouteGroup* rg = new RouteGroup (*this, "");
2479 add_route_group (rg);
2480 rg->set_state (**niter, version);
2484 } else if (version < 3000) {
2486 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2487 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2488 RouteGroup* rg = new RouteGroup (*this, "");
2489 add_route_group (rg);
2490 rg->set_state (**niter, version);
2499 state_file_filter (const string &str, void* /*arg*/)
2501 return (str.length() > strlen(statefile_suffix) &&
2502 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2506 remove_end(string state)
2508 string statename(state);
2510 string::size_type start,end;
2511 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2512 statename = statename.substr (start+1);
2515 if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2516 end = statename.length();
2519 return string(statename.substr (0, end));
2523 Session::possible_states (string path)
2525 vector<string> states;
2526 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2528 transform(states.begin(), states.end(), states.begin(), remove_end);
2530 sort (states.begin(), states.end());
2536 Session::possible_states () const
2538 return possible_states(_path);
2542 Session::add_route_group (RouteGroup* g)
2544 _route_groups.push_back (g);
2545 route_group_added (g); /* EMIT SIGNAL */
2547 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2548 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2549 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2555 Session::remove_route_group (RouteGroup& rg)
2557 list<RouteGroup*>::iterator i;
2559 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2560 _route_groups.erase (i);
2563 route_group_removed (); /* EMIT SIGNAL */
2567 /** Set a new order for our route groups, without adding or removing any.
2568 * @param groups Route group list in the new order.
2571 Session::reorder_route_groups (list<RouteGroup*> groups)
2573 _route_groups = groups;
2575 route_groups_reordered (); /* EMIT SIGNAL */
2581 Session::route_group_by_name (string name)
2583 list<RouteGroup *>::iterator i;
2585 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2586 if ((*i)->name() == name) {
2594 Session::all_route_group() const
2596 return *_all_route_group;
2600 Session::add_commands (vector<Command*> const & cmds)
2602 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2608 Session::add_command (Command* const cmd)
2610 assert (_current_trans);
2611 DEBUG_UNDO_HISTORY (
2612 string_compose ("Current Undo Transaction %1, adding command: %2",
2613 _current_trans->name (),
2615 _current_trans->add_command (cmd);
2618 Session::begin_reversible_command (const string& name)
2620 begin_reversible_command (g_quark_from_string (name.c_str ()));
2623 /** Begin a reversible command using a GQuark to identify it.
2624 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2625 * but there must be as many begin...()s as there are commit...()s.
2628 Session::begin_reversible_command (GQuark q)
2630 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2631 to hold all the commands that are committed. This keeps the order of
2632 commands correct in the history.
2635 if (_current_trans == 0) {
2636 DEBUG_UNDO_HISTORY (string_compose (
2637 "Begin Reversible Command, new transaction: %1", g_quark_to_string (q)));
2639 /* start a new transaction */
2640 assert (_current_trans_quarks.empty ());
2641 _current_trans = new UndoTransaction();
2642 _current_trans->set_name (g_quark_to_string (q));
2644 DEBUG_UNDO_HISTORY (
2645 string_compose ("Begin Reversible Command, current transaction: %1",
2646 _current_trans->name ()));
2649 _current_trans_quarks.push_front (q);
2653 Session::abort_reversible_command ()
2655 if (_current_trans != 0) {
2656 DEBUG_UNDO_HISTORY (
2657 string_compose ("Abort Reversible Command: %1", _current_trans->name ()));
2658 _current_trans->clear();
2659 delete _current_trans;
2661 _current_trans_quarks.clear();
2666 Session::commit_reversible_command (Command *cmd)
2668 assert (_current_trans);
2669 assert (!_current_trans_quarks.empty ());
2674 DEBUG_UNDO_HISTORY (
2675 string_compose ("Current Undo Transaction %1, adding command: %2",
2676 _current_trans->name (),
2678 _current_trans->add_command (cmd);
2681 DEBUG_UNDO_HISTORY (
2682 string_compose ("Commit Reversible Command, current transaction: %1",
2683 _current_trans->name ()));
2685 _current_trans_quarks.pop_front ();
2687 if (!_current_trans_quarks.empty ()) {
2688 DEBUG_UNDO_HISTORY (
2689 string_compose ("Commit Reversible Command, transaction is not "
2690 "top-level, current transaction: %1",
2691 _current_trans->name ()));
2692 /* the transaction we're committing is not the top-level one */
2696 if (_current_trans->empty()) {
2697 /* no commands were added to the transaction, so just get rid of it */
2698 DEBUG_UNDO_HISTORY (
2699 string_compose ("Commit Reversible Command, No commands were "
2700 "added to current transaction: %1",
2701 _current_trans->name ()));
2702 delete _current_trans;
2707 gettimeofday (&now, 0);
2708 _current_trans->set_timestamp (now);
2710 _history.add (_current_trans);
2715 accept_all_audio_files (const string& path, void* /*arg*/)
2717 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2721 if (!AudioFileSource::safe_audio_file_extension (path)) {
2729 accept_all_midi_files (const string& path, void* /*arg*/)
2731 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2735 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2736 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2737 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2741 accept_all_state_files (const string& path, void* /*arg*/)
2743 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2747 std::string const statefile_ext (statefile_suffix);
2748 if (path.length() >= statefile_ext.length()) {
2749 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2756 Session::find_all_sources (string path, set<string>& result)
2761 if (!tree.read (path)) {
2765 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2770 XMLNodeConstIterator niter;
2772 nlist = node->children();
2776 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2780 if ((prop = (*niter)->property (X_("type"))) == 0) {
2784 DataType type (prop->value());
2786 if ((prop = (*niter)->property (X_("name"))) == 0) {
2790 if (Glib::path_is_absolute (prop->value())) {
2791 /* external file, ignore */
2799 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2800 result.insert (found_path);
2808 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2810 vector<string> state_files;
2812 string this_snapshot_path;
2818 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2819 ripped = ripped.substr (0, ripped.length() - 1);
2822 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2824 if (state_files.empty()) {
2829 this_snapshot_path = _path;
2830 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2831 this_snapshot_path += statefile_suffix;
2833 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2835 if (exclude_this_snapshot && *i == this_snapshot_path) {
2839 if (find_all_sources (*i, result) < 0) {
2847 struct RegionCounter {
2848 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2849 AudioSourceList::iterator iter;
2850 boost::shared_ptr<Region> region;
2853 RegionCounter() : count (0) {}
2857 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2859 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2860 return r.get_value_or (1);
2864 Session::cleanup_regions ()
2866 bool removed = false;
2867 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2869 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2871 uint32_t used = playlists->region_use_count (i->second);
2873 if (used == 0 && !i->second->automatic ()) {
2874 boost::weak_ptr<Region> w = i->second;
2877 RegionFactory::map_remove (w);
2884 // re-check to remove parent references of compound regions
2885 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2886 if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2890 assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2891 if (0 == playlists->region_use_count (i->second)) {
2892 boost::weak_ptr<Region> w = i->second;
2894 RegionFactory::map_remove (w);
2901 /* dump the history list */
2908 Session::can_cleanup_peakfiles () const
2910 if (deletion_in_progress()) {
2913 if (!_writable || (_state_of_the_state & CannotSave)) {
2914 warning << _("Cannot cleanup peak-files for read-only session.") << endmsg;
2917 if (record_status() == Recording) {
2918 error << _("Cannot cleanup peak-files while recording") << endmsg;
2925 Session::cleanup_peakfiles ()
2927 Glib::Threads::Mutex::Lock lm (peak_cleanup_lock, Glib::Threads::TRY_LOCK);
2932 assert (can_cleanup_peakfiles ());
2933 assert (!peaks_cleanup_in_progres());
2935 _state_of_the_state = StateOfTheState (_state_of_the_state | PeakCleanup);
2937 int timeout = 5000; // 5 seconds
2938 while (!SourceFactory::files_with_peaks.empty()) {
2939 Glib::usleep (1000);
2940 if (--timeout < 0) {
2941 warning << _("Timeout waiting for peak-file creation to terminate before cleanup, please try again later.") << endmsg;
2942 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
2947 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2948 boost::shared_ptr<AudioSource> as;
2949 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
2950 as->close_peakfile();
2954 PBD::clear_directory (session_directory().peak_path());
2956 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
2958 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2959 boost::shared_ptr<AudioSource> as;
2960 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
2961 SourceFactory::setup_peakfile(as, true);
2968 Session::cleanup_sources (CleanupReport& rep)
2970 // FIXME: needs adaptation to midi
2972 vector<boost::shared_ptr<Source> > dead_sources;
2975 vector<string> candidates;
2976 vector<string> unused;
2977 set<string> all_sources;
2986 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2988 /* this is mostly for windows which doesn't allow file
2989 * renaming if the file is in use. But we don't special
2990 * case it because we need to know if this causes
2991 * problems, and the easiest way to notice that is to
2992 * keep it in place for all platforms.
2995 request_stop (false);
2997 _butler->wait_until_finished ();
2999 /* consider deleting all unused playlists */
3001 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
3006 /* sync the "all regions" property of each playlist with its current state
3009 playlists->sync_all_regions_with_regions ();
3011 /* find all un-used sources */
3016 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3018 SourceMap::iterator tmp;
3023 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
3027 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
3028 dead_sources.push_back (i->second);
3029 i->second->drop_references ();
3035 /* build a list of all the possible audio directories for the session */
3037 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3038 SessionDirectory sdir ((*i).path);
3039 asp += sdir.sound_path();
3041 audio_path += asp.to_string();
3044 /* build a list of all the possible midi directories for the session */
3046 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3047 SessionDirectory sdir ((*i).path);
3048 msp += sdir.midi_path();
3050 midi_path += msp.to_string();
3052 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
3053 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
3055 /* find all sources, but don't use this snapshot because the
3056 state file on disk still references sources we may have already
3060 find_all_sources_across_snapshots (all_sources, true);
3062 /* add our current source list
3065 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3066 boost::shared_ptr<FileSource> fs;
3067 SourceMap::iterator tmp = i;
3070 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
3072 /* this is mostly for windows which doesn't allow file
3073 * renaming if the file is in use. But we don't special
3074 * case it because we need to know if this causes
3075 * problems, and the easiest way to notice that is to
3076 * keep it in place for all platforms.
3081 if (!fs->is_stub()) {
3083 if (playlists->source_use_count (fs) != 0) {
3084 all_sources.insert (fs->path());
3087 /* we might not remove this source from disk, because it may be used
3088 by other snapshots, but its not being used in this version
3089 so lets get rid of it now, along with any representative regions
3093 RegionFactory::remove_regions_using_source (i->second);
3095 // also remove source from all_sources
3097 for (set<string>::iterator j = all_sources.begin(); j != all_sources.end(); ++j) {
3098 spath = Glib::path_get_basename (*j);
3099 if (spath == i->second->name()) {
3100 all_sources.erase (j);
3113 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
3118 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
3120 tmppath1 = canonical_path (spath);
3121 tmppath2 = canonical_path ((*i));
3123 if (tmppath1 == tmppath2) {
3130 unused.push_back (spath);
3134 /* now try to move all unused files into the "dead" directory(ies) */
3136 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
3141 /* don't move the file across filesystems, just
3142 stick it in the `dead_dir_name' directory
3143 on whichever filesystem it was already on.
3146 if ((*x).find ("/sounds/") != string::npos) {
3148 /* old school, go up 1 level */
3150 newpath = Glib::path_get_dirname (*x); // "sounds"
3151 newpath = Glib::path_get_dirname (newpath); // "session-name"
3155 /* new school, go up 4 levels */
3157 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
3158 newpath = Glib::path_get_dirname (newpath); // "session-name"
3159 newpath = Glib::path_get_dirname (newpath); // "interchange"
3160 newpath = Glib::path_get_dirname (newpath); // "session-dir"
3163 newpath = Glib::build_filename (newpath, dead_dir_name);
3165 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
3166 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
3170 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
3172 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
3174 /* the new path already exists, try versioning */
3176 char buf[PATH_MAX+1];
3180 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3183 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
3184 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3188 if (version == 999) {
3189 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3193 newpath = newpath_v;
3198 /* it doesn't exist, or we can't read it or something */
3202 g_stat ((*x).c_str(), &statbuf);
3204 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3205 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
3206 (*x), newpath, strerror (errno))
3211 /* see if there an easy to find peakfile for this file, and remove it.
3214 string base = Glib::path_get_basename (*x);
3215 base += "%A"; /* this is what we add for the channel suffix of all native files,
3216 or for the first channel of embedded files. it will miss
3217 some peakfiles for other channels
3219 string peakpath = construct_peak_filepath (base);
3221 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
3222 if (::g_unlink (peakpath.c_str()) != 0) {
3223 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3224 peakpath, _path, strerror (errno))
3226 /* try to back out */
3227 ::rename (newpath.c_str(), _path.c_str());
3232 rep.paths.push_back (*x);
3233 rep.space += statbuf.st_size;
3236 /* dump the history list */
3240 /* save state so we don't end up a session file
3241 referring to non-existent sources.
3248 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3254 Session::cleanup_trash_sources (CleanupReport& rep)
3256 // FIXME: needs adaptation for MIDI
3258 vector<space_and_path>::iterator i;
3264 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3266 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
3268 clear_directory (dead_dir, &rep.space, &rep.paths);
3275 Session::set_dirty ()
3277 /* never mark session dirty during loading */
3279 if (_state_of_the_state & Loading) {
3283 bool was_dirty = dirty();
3285 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3289 DirtyChanged(); /* EMIT SIGNAL */
3295 Session::set_clean ()
3297 bool was_dirty = dirty();
3299 _state_of_the_state = Clean;
3303 DirtyChanged(); /* EMIT SIGNAL */
3308 Session::set_deletion_in_progress ()
3310 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3314 Session::clear_deletion_in_progress ()
3316 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3320 Session::add_controllable (boost::shared_ptr<Controllable> c)
3322 /* this adds a controllable to the list managed by the Session.
3323 this is a subset of those managed by the Controllable class
3324 itself, and represents the only ones whose state will be saved
3325 as part of the session.
3328 Glib::Threads::Mutex::Lock lm (controllables_lock);
3329 controllables.insert (c);
3332 struct null_deleter { void operator()(void const *) const {} };
3335 Session::remove_controllable (Controllable* c)
3337 if (_state_of_the_state & Deletion) {
3341 Glib::Threads::Mutex::Lock lm (controllables_lock);
3343 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3345 if (x != controllables.end()) {
3346 controllables.erase (x);
3350 boost::shared_ptr<Controllable>
3351 Session::controllable_by_id (const PBD::ID& id)
3353 Glib::Threads::Mutex::Lock lm (controllables_lock);
3355 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3356 if ((*i)->id() == id) {
3361 return boost::shared_ptr<Controllable>();
3364 boost::shared_ptr<Controllable>
3365 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3367 boost::shared_ptr<Controllable> c;
3368 boost::shared_ptr<Route> r;
3370 switch (desc.top_level_type()) {
3371 case ControllableDescriptor::NamedRoute:
3373 std::string str = desc.top_level_name();
3374 if (str == "Master" || str == "master") {
3376 } else if (str == "control" || str == "listen") {
3379 r = route_by_name (desc.top_level_name());
3384 case ControllableDescriptor::RemoteControlID:
3385 r = route_by_remote_id (desc.rid());
3388 case ControllableDescriptor::SelectionCount:
3389 r = route_by_selected_count (desc.selection_id());
3397 switch (desc.subtype()) {
3398 case ControllableDescriptor::Gain:
3399 c = r->gain_control ();
3402 case ControllableDescriptor::Trim:
3403 c = r->trim()->gain_control ();
3406 case ControllableDescriptor::Solo:
3407 c = r->solo_control();
3410 case ControllableDescriptor::Mute:
3411 c = r->mute_control();
3414 case ControllableDescriptor::Recenable:
3416 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3419 c = t->rec_enable_control ();
3424 case ControllableDescriptor::PanDirection:
3425 c = r->pan_azimuth_control();
3428 case ControllableDescriptor::PanWidth:
3429 c = r->pan_width_control();
3432 case ControllableDescriptor::PanElevation:
3433 c = r->pan_elevation_control();
3436 case ControllableDescriptor::Balance:
3437 /* XXX simple pan control */
3440 case ControllableDescriptor::PluginParameter:
3442 uint32_t plugin = desc.target (0);
3443 uint32_t parameter_index = desc.target (1);
3445 /* revert to zero based counting */
3451 if (parameter_index > 0) {
3455 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3458 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3459 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3464 case ControllableDescriptor::SendGain: {
3465 uint32_t send = desc.target (0);
3469 c = r->send_level_controllable (send);
3474 /* relax and return a null pointer */
3482 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3485 Stateful::add_instant_xml (node, _path);
3488 if (write_to_config) {
3489 Config->add_instant_xml (node);
3494 Session::instant_xml (const string& node_name)
3496 return Stateful::instant_xml (node_name, _path);
3500 Session::save_history (string snapshot_name)
3508 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3509 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3513 if (snapshot_name.empty()) {
3514 snapshot_name = _current_snapshot_name;
3517 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3518 const string backup_filename = history_filename + backup_suffix;
3519 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3520 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3522 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3523 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3524 error << _("could not backup old history file, current history not saved") << endmsg;
3529 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3531 if (!tree.write (xml_path))
3533 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3535 if (g_remove (xml_path.c_str()) != 0) {
3536 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3537 xml_path, g_strerror (errno)) << endmsg;
3539 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3540 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3541 backup_path, g_strerror (errno)) << endmsg;
3551 Session::restore_history (string snapshot_name)
3555 if (snapshot_name.empty()) {
3556 snapshot_name = _current_snapshot_name;
3559 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3560 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3562 info << "Loading history from " << xml_path << endmsg;
3564 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3565 info << string_compose (_("%1: no history file \"%2\" for this session."),
3566 _name, xml_path) << endmsg;
3570 if (!tree.read (xml_path)) {
3571 error << string_compose (_("Could not understand session history file \"%1\""),
3572 xml_path) << endmsg;
3579 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3582 UndoTransaction* ut = new UndoTransaction ();
3585 ut->set_name(t->property("name")->value());
3586 stringstream ss(t->property("tv-sec")->value());
3588 ss.str(t->property("tv-usec")->value());
3590 ut->set_timestamp(tv);
3592 for (XMLNodeConstIterator child_it = t->children().begin();
3593 child_it != t->children().end(); child_it++)
3595 XMLNode *n = *child_it;
3598 if (n->name() == "MementoCommand" ||
3599 n->name() == "MementoUndoCommand" ||
3600 n->name() == "MementoRedoCommand") {
3602 if ((c = memento_command_factory(n))) {
3606 } else if (n->name() == "NoteDiffCommand") {
3607 PBD::ID id (n->property("midi-source")->value());
3608 boost::shared_ptr<MidiSource> midi_source =
3609 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3611 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3613 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3616 } else if (n->name() == "SysExDiffCommand") {
3618 PBD::ID id (n->property("midi-source")->value());
3619 boost::shared_ptr<MidiSource> midi_source =
3620 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3622 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3624 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3627 } else if (n->name() == "PatchChangeDiffCommand") {
3629 PBD::ID id (n->property("midi-source")->value());
3630 boost::shared_ptr<MidiSource> midi_source =
3631 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3633 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3635 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3638 } else if (n->name() == "StatefulDiffCommand") {
3639 if ((c = stateful_diff_command_factory (n))) {
3640 ut->add_command (c);
3643 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3654 Session::config_changed (std::string p, bool ours)
3660 if (p == "seamless-loop") {
3662 } else if (p == "rf-speed") {
3664 } else if (p == "auto-loop") {
3666 } else if (p == "auto-input") {
3668 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3669 /* auto-input only makes a difference if we're rolling */
3670 set_track_monitor_input_status (!config.get_auto_input());
3673 } else if (p == "punch-in") {
3677 if ((location = _locations->auto_punch_location()) != 0) {
3679 if (config.get_punch_in ()) {
3680 replace_event (SessionEvent::PunchIn, location->start());
3682 remove_event (location->start(), SessionEvent::PunchIn);
3686 } else if (p == "punch-out") {
3690 if ((location = _locations->auto_punch_location()) != 0) {
3692 if (config.get_punch_out()) {
3693 replace_event (SessionEvent::PunchOut, location->end());
3695 clear_events (SessionEvent::PunchOut);
3699 } else if (p == "edit-mode") {
3701 Glib::Threads::Mutex::Lock lm (playlists->lock);
3703 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3704 (*i)->set_edit_mode (Config->get_edit_mode ());
3707 } else if (p == "use-video-sync") {
3709 waiting_for_sync_offset = config.get_use_video_sync();
3711 } else if (p == "mmc-control") {
3713 //poke_midi_thread ();
3715 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3717 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3719 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3721 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3723 } else if (p == "midi-control") {
3725 //poke_midi_thread ();
3727 } else if (p == "raid-path") {
3729 setup_raid_path (config.get_raid_path());
3731 } else if (p == "timecode-format") {
3735 } else if (p == "video-pullup") {
3739 } else if (p == "seamless-loop") {
3741 if (play_loop && transport_rolling()) {
3742 // to reset diskstreams etc
3743 request_play_loop (true);
3746 } else if (p == "rf-speed") {
3748 cumulative_rf_motion = 0;
3751 } else if (p == "click-sound") {
3753 setup_click_sounds (1);
3755 } else if (p == "click-emphasis-sound") {
3757 setup_click_sounds (-1);
3759 } else if (p == "clicking") {
3761 if (Config->get_clicking()) {
3762 if (_click_io && click_data) { // don't require emphasis data
3769 } else if (p == "click-gain") {
3772 _click_gain->gain_control()->set_value (Config->get_click_gain(), Controllable::NoGroup);
3775 } else if (p == "send-mtc") {
3777 if (Config->get_send_mtc ()) {
3778 /* mark us ready to send */
3779 next_quarter_frame_to_send = 0;
3782 } else if (p == "send-mmc") {
3784 _mmc->enable_send (Config->get_send_mmc ());
3786 } else if (p == "midi-feedback") {
3788 session_midi_feedback = Config->get_midi_feedback();
3790 } else if (p == "jack-time-master") {
3792 engine().reset_timebase ();
3794 } else if (p == "native-file-header-format") {
3796 if (!first_file_header_format_reset) {
3797 reset_native_file_format ();
3800 first_file_header_format_reset = false;
3802 } else if (p == "native-file-data-format") {
3804 if (!first_file_data_format_reset) {
3805 reset_native_file_format ();
3808 first_file_data_format_reset = false;
3810 } else if (p == "external-sync") {
3811 if (!config.get_external_sync()) {
3812 drop_sync_source ();
3814 switch_to_sync_source (Config->get_sync_source());
3816 } else if (p == "denormal-model") {
3818 } else if (p == "history-depth") {
3819 set_history_depth (Config->get_history_depth());
3820 } else if (p == "remote-model") {
3821 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3824 } else if (p == "initial-program-change") {
3826 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3829 buf[0] = MIDI::program; // channel zero by default
3830 buf[1] = (Config->get_initial_program_change() & 0x7f);
3832 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3834 } else if (p == "solo-mute-override") {
3835 // catch_up_on_solo_mute_override ();
3836 } else if (p == "listen-position" || p == "pfl-position") {
3837 listen_position_changed ();
3838 } else if (p == "solo-control-is-listen-control") {
3839 solo_control_mode_changed ();
3840 } else if (p == "solo-mute-gain") {
3841 _solo_cut_control->Changed();
3842 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3843 last_timecode_valid = false;
3844 } else if (p == "playback-buffer-seconds") {
3845 AudioSource::allocate_working_buffers (frame_rate());
3846 } else if (p == "ltc-source-port") {
3847 reconnect_ltc_input ();
3848 } else if (p == "ltc-sink-port") {
3849 reconnect_ltc_output ();
3850 } else if (p == "timecode-generator-offset") {
3851 ltc_tx_parse_offset();
3852 } else if (p == "auto-return-target-list") {
3853 follow_playhead_priority ();
3860 Session::set_history_depth (uint32_t d)
3862 _history.set_depth (d);
3866 Session::load_diskstreams_2X (XMLNode const & node, int)
3869 XMLNodeConstIterator citer;
3871 clist = node.children();
3873 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3876 /* diskstreams added automatically by DiskstreamCreated handler */
3877 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3878 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3879 _diskstreams_2X.push_back (dsp);
3881 error << _("Session: unknown diskstream type in XML") << endmsg;
3885 catch (failed_constructor& err) {
3886 error << _("Session: could not load diskstream via XML state") << endmsg;
3894 /** Connect things to the MMC object */
3896 Session::setup_midi_machine_control ()
3898 _mmc = new MIDI::MachineControl;
3900 boost::shared_ptr<AsyncMIDIPort> async_in = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_input_port());
3901 boost::shared_ptr<AsyncMIDIPort> async_out = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_output_port());
3903 if (!async_out || !async_out) {
3907 /* XXXX argh, passing raw pointers back into libmidi++ */
3909 MIDI::Port* mmc_in = async_in.get();
3910 MIDI::Port* mmc_out = async_out.get();
3912 _mmc->set_ports (mmc_in, mmc_out);
3914 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3915 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3916 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3917 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3918 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3919 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3920 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3921 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3922 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3923 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3924 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3925 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3926 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3928 /* also handle MIDI SPP because its so common */
3930 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3931 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3932 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3935 boost::shared_ptr<Controllable>
3936 Session::solo_cut_control() const
3938 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3939 controls in Ardour that currently get presented to the user in the GUI that require
3940 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3942 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3943 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3947 return _solo_cut_control;
3951 Session::save_snapshot_name (const std::string & n)
3953 /* assure Stateful::_instant_xml is loaded
3954 * add_instant_xml() only adds to existing data and defaults
3955 * to use an empty Tree otherwise
3957 instant_xml ("LastUsedSnapshot");
3959 XMLNode* last_used_snapshot = new XMLNode ("LastUsedSnapshot");
3960 last_used_snapshot->add_property ("name", string(n));
3961 add_instant_xml (*last_used_snapshot, false);
3965 Session::set_snapshot_name (const std::string & n)
3967 _current_snapshot_name = n;
3968 save_snapshot_name (n);
3972 Session::rename (const std::string& new_name)
3974 string legal_name = legalize_for_path (new_name);
3980 string const old_sources_root = _session_dir->sources_root();
3982 if (!_writable || (_state_of_the_state & CannotSave)) {
3983 error << _("Cannot rename read-only session.") << endmsg;
3984 return 0; // don't show "messed up" warning
3986 if (record_status() == Recording) {
3987 error << _("Cannot rename session while recording") << endmsg;
3988 return 0; // don't show "messed up" warning
3991 StateProtector stp (this);
3996 * interchange subdirectory
4000 * Backup files are left unchanged and not renamed.
4003 /* Windows requires that we close all files before attempting the
4004 * rename. This works on other platforms, but isn't necessary there.
4005 * Leave it in place for all platforms though, since it may help
4006 * catch issues that could arise if the way Source files work ever
4007 * change (since most developers are not using Windows).
4010 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4011 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4017 /* pass one: not 100% safe check that the new directory names don't
4021 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4025 /* this is a stupid hack because Glib::path_get_dirname() is
4026 * lexical-only, and so passing it /a/b/c/ gives a different
4027 * result than passing it /a/b/c ...
4030 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4031 oldstr = oldstr.substr (0, oldstr.length() - 1);
4034 string base = Glib::path_get_dirname (oldstr);
4036 newstr = Glib::build_filename (base, legal_name);
4038 cerr << "Looking for " << newstr << endl;
4040 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
4041 cerr << " exists\n";
4050 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4056 /* this is a stupid hack because Glib::path_get_dirname() is
4057 * lexical-only, and so passing it /a/b/c/ gives a different
4058 * result than passing it /a/b/c ...
4061 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4062 oldstr = oldstr.substr (0, oldstr.length() - 1);
4065 string base = Glib::path_get_dirname (oldstr);
4066 newstr = Glib::build_filename (base, legal_name);
4068 cerr << "for " << oldstr << " new dir = " << newstr << endl;
4070 cerr << "Rename " << oldstr << " => " << newstr << endl;
4071 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4072 cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4073 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4077 /* Reset path in "session dirs" */
4082 /* reset primary SessionDirectory object */
4085 (*_session_dir) = newstr;
4090 /* now rename directory below session_dir/interchange */
4092 string old_interchange_dir;
4093 string new_interchange_dir;
4095 /* use newstr here because we renamed the path
4096 * (folder/directory) that used to be oldstr to newstr above
4099 v.push_back (newstr);
4100 v.push_back (interchange_dir_name);
4101 v.push_back (Glib::path_get_basename (oldstr));
4103 old_interchange_dir = Glib::build_filename (v);
4106 v.push_back (newstr);
4107 v.push_back (interchange_dir_name);
4108 v.push_back (legal_name);
4110 new_interchange_dir = Glib::build_filename (v);
4112 cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
4114 if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
4115 cerr << string_compose (_("renaming %s as %2 failed (%3)"),
4116 old_interchange_dir, new_interchange_dir,
4119 error << string_compose (_("renaming %s as %2 failed (%3)"),
4120 old_interchange_dir, new_interchange_dir,
4129 oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
4130 newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
4132 cerr << "Rename " << oldstr << " => " << newstr << endl;
4134 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4135 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4136 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4142 oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
4144 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
4145 newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
4147 cerr << "Rename " << oldstr << " => " << newstr << endl;
4149 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4150 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4151 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4156 /* remove old name from recent sessions */
4157 remove_recent_sessions (_path);
4160 /* update file source paths */
4162 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
4163 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4165 string p = fs->path ();
4166 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
4168 SourceFactory::setup_peakfile(i->second, true);
4172 set_snapshot_name (new_name);
4177 /* save state again to get everything just right */
4179 save_state (_current_snapshot_name);
4181 /* add to recent sessions */
4183 store_recent_sessions (new_name, _path);
4189 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
4191 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
4195 if (!tree.read (xmlpath)) {
4203 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
4206 bool found_sr = false;
4207 bool found_data_format = false;
4209 if (get_session_info_from_path (tree, xmlpath)) {
4215 const XMLProperty* prop;
4216 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
4217 sample_rate = atoi (prop->value());
4221 const XMLNodeList& children (tree.root()->children());
4222 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
4223 const XMLNode* child = *c;
4224 if (child->name() == "Config") {
4225 const XMLNodeList& options (child->children());
4226 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
4227 const XMLNode* option = *oc;
4228 const XMLProperty* name = option->property("name");
4234 if (name->value() == "native-file-data-format") {
4235 const XMLProperty* value = option->property ("value");
4237 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
4239 found_data_format = true;
4245 if (found_data_format) {
4250 return !(found_sr && found_data_format); // zero if they are both found
4254 Session::get_snapshot_from_instant (const std::string& session_dir)
4256 std::string instant_xml_path = Glib::build_filename (session_dir, "instant.xml");
4258 if (!Glib::file_test (instant_xml_path, Glib::FILE_TEST_EXISTS)) {
4263 if (!tree.read (instant_xml_path)) {
4267 const XMLProperty* prop;
4268 XMLNode *last_used_snapshot = tree.root()->child("LastUsedSnapshot");
4269 if (last_used_snapshot && (prop = last_used_snapshot->property ("name")) != 0) {
4270 return prop->value();
4276 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
4277 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
4280 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
4284 SourcePathMap source_path_map;
4286 boost::shared_ptr<AudioFileSource> afs;
4291 Glib::Threads::Mutex::Lock lm (source_lock);
4293 cerr << " total sources = " << sources.size();
4295 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4296 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4302 if (fs->within_session()) {
4306 if (source_path_map.find (fs->path()) != source_path_map.end()) {
4307 source_path_map[fs->path()].push_back (fs);
4309 SeveralFileSources v;
4311 source_path_map.insert (make_pair (fs->path(), v));
4317 cerr << " fsources = " << total << endl;
4319 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
4321 /* tell caller where we are */
4323 string old_path = i->first;
4325 callback (n, total, old_path);
4327 cerr << old_path << endl;
4331 switch (i->second.front()->type()) {
4332 case DataType::AUDIO:
4333 new_path = new_audio_source_path_for_embedded (old_path);
4336 case DataType::MIDI:
4337 /* XXX not implemented yet */
4341 if (new_path.empty()) {
4345 cerr << "Move " << old_path << " => " << new_path << endl;
4347 if (!copy_file (old_path, new_path)) {
4348 cerr << "failed !\n";
4352 /* make sure we stop looking in the external
4353 dir/folder. Remember, this is an all-or-nothing
4354 operations, it doesn't merge just some files.
4356 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
4358 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
4359 (*f)->set_path (new_path);
4364 save_state ("", false, false);
4370 bool accept_all_files (string const &, void *)
4376 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4378 /* 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.
4383 make_new_media_path (string old_path, string new_session_folder, string new_session_path)
4385 /* typedir is the "midifiles" or "audiofiles" etc. part of the path. */
4387 string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4389 v.push_back (new_session_folder); /* full path */
4390 v.push_back (interchange_dir_name);
4391 v.push_back (new_session_path); /* just one directory/folder */
4392 v.push_back (typedir);
4393 v.push_back (Glib::path_get_basename (old_path));
4395 return Glib::build_filename (v);
4399 Session::save_as (SaveAs& saveas)
4401 vector<string> files;
4402 string current_folder = Glib::path_get_dirname (_path);
4403 string new_folder = legalize_for_path (saveas.new_name);
4404 string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4405 int64_t total_bytes = 0;
4409 int32_t internal_file_cnt = 0;
4411 vector<string> do_not_copy_extensions;
4412 do_not_copy_extensions.push_back (statefile_suffix);
4413 do_not_copy_extensions.push_back (pending_suffix);
4414 do_not_copy_extensions.push_back (backup_suffix);
4415 do_not_copy_extensions.push_back (temp_suffix);
4416 do_not_copy_extensions.push_back (history_suffix);
4418 /* get total size */
4420 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4422 /* need to clear this because
4423 * find_files_matching_filter() is cumulative
4428 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4430 all += files.size();
4432 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4434 g_stat ((*i).c_str(), &gsb);
4435 total_bytes += gsb.st_size;
4439 /* save old values so we can switch back if we are not switching to the new session */
4441 string old_path = _path;
4442 string old_name = _name;
4443 string old_snapshot = _current_snapshot_name;
4444 string old_sd = _session_dir->root_path();
4445 vector<string> old_search_path[DataType::num_types];
4446 string old_config_search_path[DataType::num_types];
4448 old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4449 old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4450 old_config_search_path[DataType::AUDIO] = config.get_audio_search_path ();
4451 old_config_search_path[DataType::MIDI] = config.get_midi_search_path ();
4453 /* switch session directory */
4455 (*_session_dir) = to_dir;
4457 /* create new tree */
4459 if (!_session_dir->create()) {
4460 saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4465 /* copy all relevant files. Find each location in session_dirs,
4466 * and copy files from there to target.
4469 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4471 /* need to clear this because
4472 * find_files_matching_filter() is cumulative
4477 const size_t prefix_len = (*sd).path.size();
4479 /* Work just on the files within this session dir */
4481 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4483 /* add dir separator to protect against collisions with
4484 * track names (e.g. track named "audiofiles" or
4488 static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
4489 static const std::string midifile_dir_string = string (midi_dir_name) + G_DIR_SEPARATOR;
4490 static const std::string analysis_dir_string = analysis_dir() + G_DIR_SEPARATOR;
4492 /* copy all the files. Handling is different for media files
4493 than others because of the *silly* subtree we have below the interchange
4494 folder. That really was a bad idea, but I'm not fixing it as part of
4495 implementing ::save_as().
4498 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4500 std::string from = *i;
4503 string filename = Glib::path_get_basename (from);
4504 std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
4505 if (filename == ".DS_STORE") {
4510 if (from.find (audiofile_dir_string) != string::npos) {
4512 /* audio file: only copy if asked */
4514 if (saveas.include_media && saveas.copy_media) {
4516 string to = make_new_media_path (*i, to_dir, new_folder);
4518 info << "media file copying from " << from << " to " << to << endmsg;
4520 if (!copy_file (from, to)) {
4521 throw Glib::FileError (Glib::FileError::IO_ERROR,
4522 string_compose(_("\ncopying \"%1\" failed !"), from));
4526 /* we found media files inside the session folder */
4528 internal_file_cnt++;
4530 } else if (from.find (midifile_dir_string) != string::npos) {
4532 /* midi file: always copy unless
4533 * creating an empty new session
4536 if (saveas.include_media) {
4538 string to = make_new_media_path (*i, to_dir, new_folder);
4540 info << "media file copying from " << from << " to " << to << endmsg;
4542 if (!copy_file (from, to)) {
4543 throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4547 /* we found media files inside the session folder */
4549 internal_file_cnt++;
4551 } else if (from.find (analysis_dir_string) != string::npos) {
4553 /* make sure analysis dir exists in
4554 * new session folder, but we're not
4555 * copying analysis files here, see
4559 (void) g_mkdir_with_parents (analysis_dir().c_str(), 775);
4564 /* normal non-media file. Don't copy state, history, etc.
4567 bool do_copy = true;
4569 for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
4570 if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
4571 /* end of filename matches extension, do not copy file */
4577 if (!saveas.copy_media && from.find (peakfile_suffix) != string::npos) {
4578 /* don't copy peakfiles if
4579 * we're not copying media
4585 string to = Glib::build_filename (to_dir, from.substr (prefix_len));
4587 info << "attempting to make directory/folder " << to << endmsg;
4589 if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
4590 throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
4593 info << "attempting to copy " << from << " to " << to << endmsg;
4595 if (!copy_file (from, to)) {
4596 throw Glib::FileError (Glib::FileError::IO_ERROR,
4597 string_compose(_("\ncopying \"%1\" failed !"), from));
4602 /* measure file size even if we're not going to copy so that our Progress
4603 signals are correct, since we included these do-not-copy files
4604 in the computation of the total size and file count.
4608 g_stat (from.c_str(), &gsb);
4609 copied += gsb.st_size;
4612 double fraction = (double) copied / total_bytes;
4614 bool keep_going = true;
4616 if (saveas.copy_media) {
4618 /* no need or expectation of this if
4619 * media is not being copied, because
4620 * it will be fast(ish).
4623 /* tell someone "X percent, file M of N"; M is one-based */
4625 boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
4633 throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
4639 /* copy optional folders, if any */
4641 string old = plugins_dir ();
4642 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4643 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4644 copy_files (old, newdir);
4647 old = externals_dir ();
4648 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4649 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4650 copy_files (old, newdir);
4653 old = automation_dir ();
4654 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4655 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4656 copy_files (old, newdir);
4659 if (saveas.include_media) {
4661 if (saveas.copy_media) {
4662 #ifndef PLATFORM_WINDOWS
4663 /* There are problems with analysis files on
4664 * Windows, because they used a colon in their
4665 * names as late as 4.0. Colons are not legal
4666 * under Windows even if NTFS allows them.
4668 * This is a tricky problem to solve so for
4669 * just don't copy these files. They will be
4670 * regenerated as-needed anyway, subject to the
4671 * existing issue that the filenames will be
4672 * rejected by Windows, which is a separate
4673 * problem (though related).
4676 /* only needed if we are copying media, since the
4677 * analysis data refers to media data
4680 old = analysis_dir ();
4681 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4682 string newdir = Glib::build_filename (to_dir, "analysis");
4683 copy_files (old, newdir);
4685 #endif /* PLATFORM_WINDOWS */
4691 set_snapshot_name (saveas.new_name);
4692 _name = saveas.new_name;
4694 if (saveas.include_media && !saveas.copy_media) {
4696 /* reset search paths of the new session (which we're pretending to be right now) to
4697 include the original session search path, so we can still find all audio.
4700 if (internal_file_cnt) {
4701 for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
4702 ensure_search_path_includes (*s, DataType::AUDIO);
4703 cerr << "be sure to include " << *s << " for audio" << endl;
4706 /* we do not do this for MIDI because we copy
4707 all MIDI files if saveas.include_media is
4713 bool was_dirty = dirty ();
4715 save_state ("", false, false, !saveas.include_media);
4716 save_default_options ();
4718 if (saveas.copy_media && saveas.copy_external) {
4719 if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
4720 throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
4724 saveas.final_session_folder_name = _path;
4726 store_recent_sessions (_name, _path);
4728 if (!saveas.switch_to) {
4730 /* switch back to the way things were */
4734 set_snapshot_name (old_snapshot);
4736 (*_session_dir) = old_sd;
4742 if (internal_file_cnt) {
4743 /* reset these to their original values */
4744 config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
4745 config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
4750 /* prune session dirs, and update disk space statistics
4755 session_dirs.clear ();
4756 session_dirs.push_back (sp);
4757 refresh_disk_space ();
4759 /* ensure that all existing tracks reset their current capture source paths
4761 reset_write_sources (true, true);
4763 /* the copying above was based on actually discovering files, not just iterating over the sources list.
4764 But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
4767 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4768 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4774 if (fs->within_session()) {
4775 string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
4776 fs->set_path (newpath);
4781 } catch (Glib::FileError& e) {
4783 saveas.failure_message = e.what();
4785 /* recursively remove all the directories */
4787 remove_directory (to_dir);
4795 saveas.failure_message = _("unknown reason");
4797 /* recursively remove all the directories */
4799 remove_directory (to_dir);