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"
129 using namespace ARDOUR;
132 #define DEBUG_UNDO_HISTORY(msg) DEBUG_TRACE (PBD::DEBUG::UndoHistory, string_compose ("%1: %2\n", __LINE__, msg));
135 Session::pre_engine_init (string fullpath)
137 if (fullpath.empty()) {
139 throw failed_constructor();
142 /* discover canonical fullpath */
144 _path = canonical_path(fullpath);
147 if (Profile->get_trx() ) {
148 // Waves TracksLive has a usecase of session replacement with a new one.
149 // We should check session state file (<session_name>.ardour) existance
150 // to determine if the session is new or not
152 string full_session_name = Glib::build_filename( fullpath, _name );
153 full_session_name += statefile_suffix;
155 _is_new = !Glib::file_test (full_session_name, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
157 _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
160 /* finish initialization that can't be done in a normal C++ constructor
164 timerclear (&last_mmc_step);
165 g_atomic_int_set (&processing_prohibited, 0);
166 g_atomic_int_set (&_record_status, Disabled);
167 g_atomic_int_set (&_playback_load, 100);
168 g_atomic_int_set (&_capture_load, 100);
170 _all_route_group->set_active (true, this);
171 interpolation.add_channel_to (0, 0);
173 if (config.get_use_video_sync()) {
174 waiting_for_sync_offset = true;
176 waiting_for_sync_offset = false;
179 last_rr_session_dir = session_dirs.begin();
181 set_history_depth (Config->get_history_depth());
183 /* default: assume simple stereo speaker configuration */
185 _speakers->setup_default_speakers (2);
187 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
188 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
189 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
190 add_controllable (_solo_cut_control);
192 /* These are all static "per-class" signals */
194 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
195 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
196 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
197 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
198 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
200 /* stop IO objects from doing stuff until we're ready for them */
202 Delivery::disable_panners ();
203 IO::disable_connecting ();
207 Session::post_engine_init ()
209 BootMessage (_("Set block size and sample rate"));
211 set_block_size (_engine.samples_per_cycle());
212 set_frame_rate (_engine.sample_rate());
214 BootMessage (_("Using configuration"));
216 _midi_ports = new MidiPortManager;
218 MIDISceneChanger* msc;
220 _scene_changer = msc = new MIDISceneChanger (*this);
221 msc->set_input_port (boost::dynamic_pointer_cast<MidiPort>(scene_input_port()));
222 msc->set_output_port (boost::dynamic_pointer_cast<MidiPort>(scene_output_port()));
224 boost::function<framecnt_t(void)> timer_func (boost::bind (&Session::audible_frame, this));
225 boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_input_port())->set_timer (timer_func);
227 setup_midi_machine_control ();
229 if (_butler->start_thread()) {
233 if (start_midi_thread ()) {
237 setup_click_sounds (0);
238 setup_midi_control ();
240 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
241 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
244 /* tempo map requires sample rate knowledge */
247 _tempo_map = new TempoMap (_current_frame_rate);
248 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
250 /* MidiClock requires a tempo map */
252 midi_clock = new MidiClockTicker ();
253 midi_clock->set_session (this);
255 /* crossfades require sample rate knowledge */
257 SndFileSource::setup_standard_crossfades (*this, frame_rate());
258 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
260 AudioDiskstream::allocate_working_buffers();
261 refresh_disk_space ();
263 /* we're finally ready to call set_state() ... all objects have
264 * been created, the engine is running.
268 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
272 // set_state() will call setup_raid_path(), but if it's a new session we need
273 // to call setup_raid_path() here.
274 setup_raid_path (_path);
279 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
280 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
282 Config->map_parameters (ff);
283 config.map_parameters (ft);
284 _butler->map_parameters ();
286 /* Reset all panners */
288 Delivery::reset_panners ();
290 /* this will cause the CPM to instantiate any protocols that are in use
291 * (or mandatory), which will pass it this Session, and then call
292 * set_state() on each instantiated protocol to match stored state.
295 ControlProtocolManager::instance().set_session (this);
297 /* This must be done after the ControlProtocolManager set_session above,
298 as it will set states for ports which the ControlProtocolManager creates.
301 // XXX set state of MIDI::Port's
302 // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
304 /* And this must be done after the MIDI::Manager::set_port_states as
305 * it will try to make connections whose details are loaded by set_port_states.
310 /* Let control protocols know that we are now all connected, so they
311 * could start talking to surfaces if they want to.
314 ControlProtocolManager::instance().midi_connectivity_established ();
316 if (_is_new && !no_auto_connect()) {
317 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
318 auto_connect_master_bus ();
321 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
323 /* update latencies */
325 initialize_latencies ();
327 _locations->added.connect_same_thread (*this, boost::bind (&Session::location_added, this, _1));
328 _locations->removed.connect_same_thread (*this, boost::bind (&Session::location_removed, this, _1));
329 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
331 } catch (AudioEngine::PortRegistrationFailure& err) {
332 /* handle this one in a different way than all others, so that its clear what happened */
333 error << err.what() << endmsg;
339 BootMessage (_("Reset Remote Controls"));
341 // send_full_time_code (0);
342 _engine.transport_locate (0);
344 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
345 send_immediate_mmc (MIDI::MachineControlCommand (Timecode::Time ()));
347 MIDI::Name::MidiPatchManager::instance().add_search_path (session_directory().midi_patch_path() );
350 /* initial program change will be delivered later; see ::config_changed() */
352 _state_of_the_state = Clean;
354 Port::set_connecting_blocked (false);
356 DirtyChanged (); /* EMIT SIGNAL */
360 } else if (state_was_pending) {
362 remove_pending_capture_state ();
363 state_was_pending = false;
366 /* Now, finally, we can fill the playback buffers */
368 BootMessage (_("Filling playback buffers"));
370 boost::shared_ptr<RouteList> rl = routes.reader();
371 for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
372 boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<Track> (*r);
373 if (trk && !trk->hidden()) {
374 trk->seek (_transport_frame, true);
382 Session::session_loaded ()
386 _state_of_the_state = Clean;
388 DirtyChanged (); /* EMIT SIGNAL */
392 } else if (state_was_pending) {
394 remove_pending_capture_state ();
395 state_was_pending = false;
398 /* Now, finally, we can fill the playback buffers */
400 BootMessage (_("Filling playback buffers"));
401 force_locate (_transport_frame, false);
405 Session::raid_path () const
407 Searchpath raid_search_path;
409 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
410 raid_search_path += (*i).path;
413 return raid_search_path.to_string ();
417 Session::setup_raid_path (string path)
426 session_dirs.clear ();
428 Searchpath search_path(path);
429 Searchpath sound_search_path;
430 Searchpath midi_search_path;
432 for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
434 sp.blocks = 0; // not needed
435 session_dirs.push_back (sp);
437 SessionDirectory sdir(sp.path);
439 sound_search_path += sdir.sound_path ();
440 midi_search_path += sdir.midi_path ();
443 // reset the round-robin soundfile path thingie
444 last_rr_session_dir = session_dirs.begin();
448 Session::path_is_within_session (const std::string& path)
450 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
451 if (PBD::path_is_within (i->path, path)) {
459 Session::ensure_subdirs ()
463 dir = session_directory().peak_path();
465 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
466 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
470 dir = session_directory().sound_path();
472 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
473 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
477 dir = session_directory().midi_path();
479 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
480 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
484 dir = session_directory().dead_path();
486 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
487 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
491 dir = session_directory().export_path();
493 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
494 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
498 dir = analysis_dir ();
500 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
501 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
505 dir = plugins_dir ();
507 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
508 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
512 dir = externals_dir ();
514 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
515 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
522 /** @param session_template directory containing session template, or empty.
523 * Caller must not hold process lock.
526 Session::create (const string& session_template, BusProfile* bus_profile)
528 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
529 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
533 if (ensure_subdirs ()) {
537 _writable = exists_and_writable (_path);
539 if (!session_template.empty()) {
540 string in_path = (ARDOUR::Profile->get_trx () ? session_template : session_template_dir_to_file (session_template));
542 FILE* in = g_fopen (in_path.c_str(), "rb");
545 /* no need to call legalize_for_path() since the string
546 * in session_template is already a legal path name
548 string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
550 FILE* out = g_fopen (out_path.c_str(), "wb");
554 stringstream new_session;
557 size_t charsRead = fread (buf, sizeof(char), 1024, in);
560 error << string_compose (_("Error reading session template file %1 (%2)"), in_path, strerror (errno)) << endmsg;
565 if (charsRead == 0) {
568 new_session.write (buf, charsRead);
572 string file_contents = new_session.str();
573 size_t writeSize = file_contents.length();
574 if (fwrite (file_contents.c_str(), sizeof(char), writeSize, out) != writeSize) {
575 error << string_compose (_("Error writing session template file %1 (%2)"), out_path, strerror (errno)) << endmsg;
583 if (!ARDOUR::Profile->get_trx()) {
584 /* Copy plugin state files from template to new session */
585 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
586 copy_recurse (template_plugins, plugins_dir ());
592 error << string_compose (_("Could not open %1 for writing session template"), out_path)
599 error << string_compose (_("Could not open session template %1 for reading"), in_path)
606 if (Profile->get_trx()) {
608 /* set initial start + end point : ARDOUR::Session::session_end_shift long.
609 Remember that this is a brand new session. Sessions
610 loaded from saved state will get this range from the saved state.
613 set_session_range_location (0, 0);
615 /* Initial loop location, from absolute zero, length 10 seconds */
617 Location* loc = new Location (*this, 0, 10.0 * _engine.sample_rate(), _("Loop"), Location::IsAutoLoop);
618 _locations->add (loc, true);
619 set_auto_loop_location (loc);
622 _state_of_the_state = Clean;
624 /* set up Master Out and Control Out if necessary */
629 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
631 // Waves Tracks: always create master bus for Tracks
632 if (ARDOUR::Profile->get_trx() || bus_profile->master_out_channels) {
633 boost::shared_ptr<Route> r (new Route (*this, _("Master"), Route::MasterOut, DataType::AUDIO));
637 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
638 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
641 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
642 r->input()->ensure_io (count, false, this);
643 r->output()->ensure_io (count, false, this);
649 /* prohibit auto-connect to master, because there isn't one */
650 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
654 add_routes (rl, false, false, false);
657 // Waves Tracks: Skip this. Always use autoconnection for Tracks
658 if (!ARDOUR::Profile->get_trx()) {
660 /* this allows the user to override settings with an environment variable.
663 if (no_auto_connect()) {
664 bus_profile->input_ac = AutoConnectOption (0);
665 bus_profile->output_ac = AutoConnectOption (0);
668 Config->set_input_auto_connect (bus_profile->input_ac);
669 Config->set_output_auto_connect (bus_profile->output_ac);
673 if (Config->get_use_monitor_bus() && bus_profile) {
674 add_monitor_section ();
681 Session::maybe_write_autosave()
683 if (dirty() && record_status() != Recording) {
684 save_state("", true);
689 Session::remove_pending_capture_state ()
691 std::string pending_state_file_path(_session_dir->root_path());
693 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
695 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
697 if (g_remove (pending_state_file_path.c_str()) != 0) {
698 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
699 pending_state_file_path, g_strerror (errno)) << endmsg;
703 /** Rename a state file.
704 * @param old_name Old snapshot name.
705 * @param new_name New snapshot name.
708 Session::rename_state (string old_name, string new_name)
710 if (old_name == _current_snapshot_name || old_name == _name) {
711 /* refuse to rename the current snapshot or the "main" one */
715 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
716 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
718 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
719 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
721 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
722 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
723 old_name, new_name, g_strerror(errno)) << endmsg;
727 /** Remove a state file.
728 * @param snapshot_name Snapshot name.
731 Session::remove_state (string snapshot_name)
733 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
734 // refuse to remove the current snapshot or the "main" one
738 std::string xml_path(_session_dir->root_path());
740 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
742 if (!create_backup_file (xml_path)) {
743 // don't remove it if a backup can't be made
744 // create_backup_file will log the error.
749 if (g_remove (xml_path.c_str()) != 0) {
750 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
751 xml_path, g_strerror (errno)) << endmsg;
755 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
757 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot, bool template_only)
760 std::string xml_path(_session_dir->root_path());
762 /* prevent concurrent saves from different threads */
764 Glib::Threads::Mutex::Lock lm (save_state_lock);
766 if (!_writable || (_state_of_the_state & CannotSave)) {
770 if (g_atomic_int_get(&_suspend_save)) {
774 _save_queued = false;
776 if (!_engine.connected ()) {
777 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
783 /* tell sources we're saving first, in case they write out to a new file
784 * which should be saved with the state rather than the old one */
785 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
787 i->second->session_saved();
788 } catch (Evoral::SMF::FileError& e) {
789 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
793 SessionSaveUnderway (); /* EMIT SIGNAL */
795 bool mark_as_clean = true;
797 if (!snapshot_name.empty() && !switch_to_snapshot) {
798 mark_as_clean = false;
802 mark_as_clean = false;
803 tree.set_root (&get_template());
805 tree.set_root (&get_state());
808 if (snapshot_name.empty()) {
809 snapshot_name = _current_snapshot_name;
810 } else if (switch_to_snapshot) {
811 set_snapshot_name (snapshot_name);
814 assert (!snapshot_name.empty());
818 /* proper save: use statefile_suffix (.ardour in English) */
820 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
822 /* make a backup copy of the old file */
824 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
825 // create_backup_file will log the error
831 /* pending save: use pending_suffix (.pending in English) */
832 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
835 std::string tmp_path(_session_dir->root_path());
836 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
838 cerr << "actually writing state to " << tmp_path << endl;
840 if (!tree.write (tmp_path)) {
841 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
842 if (g_remove (tmp_path.c_str()) != 0) {
843 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
844 tmp_path, g_strerror (errno)) << endmsg;
850 cerr << "renaming state to " << xml_path << endl;
852 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
853 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
854 tmp_path, xml_path, g_strerror(errno)) << endmsg;
855 if (g_remove (tmp_path.c_str()) != 0) {
856 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
857 tmp_path, g_strerror (errno)) << endmsg;
865 save_history (snapshot_name);
868 bool was_dirty = dirty();
870 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
873 DirtyChanged (); /* EMIT SIGNAL */
877 StateSaved (snapshot_name); /* EMIT SIGNAL */
884 Session::restore_state (string snapshot_name)
886 if (load_state (snapshot_name) == 0) {
887 set_state (*state_tree->root(), Stateful::loading_state_version);
894 Session::load_state (string snapshot_name)
899 state_was_pending = false;
901 /* check for leftover pending state from a crashed capture attempt */
903 std::string xmlpath(_session_dir->root_path());
904 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
906 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
908 /* there is pending state from a crashed capture attempt */
910 boost::optional<int> r = AskAboutPendingState();
911 if (r.get_value_or (1)) {
912 state_was_pending = true;
916 if (!state_was_pending) {
917 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
920 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
921 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
922 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
923 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
928 state_tree = new XMLTree;
932 _writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
934 if (!state_tree->read (xmlpath)) {
935 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
941 XMLNode& root (*state_tree->root());
943 if (root.name() != X_("Session")) {
944 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
950 const XMLProperty* prop;
952 if ((prop = root.property ("version")) == 0) {
953 /* no version implies very old version of Ardour */
954 Stateful::loading_state_version = 1000;
956 if (prop->value().find ('.') != string::npos) {
957 /* old school version format */
958 if (prop->value()[0] == '2') {
959 Stateful::loading_state_version = 2000;
961 Stateful::loading_state_version = 3000;
964 Stateful::loading_state_version = atoi (prop->value());
968 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
970 std::string backup_path(_session_dir->root_path());
971 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
972 backup_path = Glib::build_filename (backup_path, backup_filename);
974 // only create a backup for a given statefile version once
976 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
978 VersionMismatch (xmlpath, backup_path);
980 if (!copy_file (xmlpath, backup_path)) {;
986 save_snapshot_name (snapshot_name);
992 Session::load_options (const XMLNode& node)
994 LocaleGuard lg (X_("C"));
995 config.set_variables (node);
1000 Session::save_default_options ()
1002 return config.save_state();
1006 Session::get_state()
1012 Session::get_template()
1014 /* if we don't disable rec-enable, diskstreams
1015 will believe they need to store their capture
1016 sources in their state node.
1019 disable_record (false);
1021 return state(false);
1025 Session::state (bool full_state)
1027 XMLNode* node = new XMLNode("Session");
1031 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
1032 node->add_property("version", buf);
1034 /* store configuration settings */
1038 node->add_property ("name", _name);
1039 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
1040 node->add_property ("sample-rate", buf);
1042 if (session_dirs.size() > 1) {
1046 vector<space_and_path>::iterator i = session_dirs.begin();
1047 vector<space_and_path>::iterator next;
1049 ++i; /* skip the first one */
1053 while (i != session_dirs.end()) {
1057 if (next != session_dirs.end()) {
1058 p += G_SEARCHPATH_SEPARATOR;
1067 child = node->add_child ("Path");
1068 child->add_content (p);
1072 /* save the ID counter */
1074 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1075 node->add_property ("id-counter", buf);
1077 /* save the event ID counter */
1079 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1080 node->add_property ("event-counter", buf);
1082 /* various options */
1084 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
1085 if (!midi_port_nodes.empty()) {
1086 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
1087 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
1088 midi_port_stuff->add_child_nocopy (**n);
1090 node->add_child_nocopy (*midi_port_stuff);
1093 node->add_child_nocopy (config.get_variables ());
1095 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1097 child = node->add_child ("Sources");
1100 Glib::Threads::Mutex::Lock sl (source_lock);
1102 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1104 /* Don't save information about non-file Sources, or
1105 * about non-destructive file sources that are empty
1106 * and unused by any regions.
1109 boost::shared_ptr<FileSource> fs;
1111 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1113 if (!fs->destructive()) {
1114 if (fs->empty() && !fs->used()) {
1119 child->add_child_nocopy (siter->second->get_state());
1124 child = node->add_child ("Regions");
1127 Glib::Threads::Mutex::Lock rl (region_lock);
1128 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1129 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1130 boost::shared_ptr<Region> r = i->second;
1131 /* only store regions not attached to playlists */
1132 if (r->playlist() == 0) {
1133 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1134 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1136 child->add_child_nocopy (r->get_state ());
1141 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1143 if (!cassocs.empty()) {
1144 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1146 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1148 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1149 i->first->id().print (buf, sizeof (buf));
1150 can->add_property (X_("copy"), buf);
1151 i->second->id().print (buf, sizeof (buf));
1152 can->add_property (X_("original"), buf);
1153 ca->add_child_nocopy (*can);
1163 node->add_child_nocopy (_locations->get_state());
1166 Locations loc (*this);
1167 // for a template, just create a new Locations, populate it
1168 // with the default start and end, and get the state for that.
1169 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1170 range->set (max_framepos, 0);
1172 XMLNode& locations_state = loc.get_state();
1174 if (ARDOUR::Profile->get_trx() && _locations) {
1175 // For tracks we need stored the Auto Loop Range and all MIDI markers.
1176 for (Locations::LocationList::const_iterator i = _locations->list ().begin (); i != _locations->list ().end (); ++i) {
1177 if ((*i)->is_mark () || (*i)->is_auto_loop ()) {
1178 locations_state.add_child_nocopy ((*i)->get_state ());
1182 node->add_child_nocopy (locations_state);
1185 child = node->add_child ("Bundles");
1187 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1188 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1189 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1191 child->add_child_nocopy (b->get_state());
1196 child = node->add_child ("Routes");
1198 boost::shared_ptr<RouteList> r = routes.reader ();
1200 RoutePublicOrderSorter cmp;
1201 RouteList public_order (*r);
1202 public_order.sort (cmp);
1204 /* the sort should have put control outs first */
1207 assert (_monitor_out == public_order.front());
1210 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1211 if (!(*i)->is_auditioner()) {
1213 child->add_child_nocopy ((*i)->get_state());
1215 child->add_child_nocopy ((*i)->get_template());
1221 playlists->add_state (node, full_state);
1223 child = node->add_child ("RouteGroups");
1224 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1225 child->add_child_nocopy ((*i)->get_state());
1229 XMLNode* gain_child = node->add_child ("Click");
1230 gain_child->add_child_nocopy (_click_io->state (full_state));
1231 gain_child->add_child_nocopy (_click_gain->state (full_state));
1235 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1236 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1240 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1241 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1244 node->add_child_nocopy (_speakers->get_state());
1245 node->add_child_nocopy (_tempo_map->get_state());
1246 node->add_child_nocopy (get_control_protocol_state());
1249 node->add_child_copy (*_extra_xml);
1256 Session::get_control_protocol_state ()
1258 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1259 return cpm.get_state();
1263 Session::set_state (const XMLNode& node, int version)
1267 const XMLProperty* prop;
1270 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1272 if (node.name() != X_("Session")) {
1273 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1277 if ((prop = node.property ("name")) != 0) {
1278 _name = prop->value ();
1281 if ((prop = node.property (X_("sample-rate"))) != 0) {
1283 _nominal_frame_rate = atoi (prop->value());
1285 if (_nominal_frame_rate != _current_frame_rate) {
1286 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1287 if (r.get_value_or (0)) {
1293 setup_raid_path(_session_dir->root_path());
1295 if ((prop = node.property (X_("id-counter"))) != 0) {
1297 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1298 ID::init_counter (x);
1300 /* old sessions used a timebased counter, so fake
1301 the startup ID counter based on a standard
1306 ID::init_counter (now);
1309 if ((prop = node.property (X_("event-counter"))) != 0) {
1310 Evoral::init_event_id_counter (atoi (prop->value()));
1314 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1315 _midi_ports->set_midi_port_states (child->children());
1318 IO::disable_connecting ();
1320 Stateful::save_extra_xml (node);
1322 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1323 load_options (*child);
1324 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1325 load_options (*child);
1327 error << _("Session: XML state has no options section") << endmsg;
1330 if (version >= 3000) {
1331 if ((child = find_named_node (node, "Metadata")) == 0) {
1332 warning << _("Session: XML state has no metadata section") << endmsg;
1333 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1338 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1339 _speakers->set_state (*child, version);
1342 if ((child = find_named_node (node, "Sources")) == 0) {
1343 error << _("Session: XML state has no sources section") << endmsg;
1345 } else if (load_sources (*child)) {
1349 if ((child = find_named_node (node, "TempoMap")) == 0) {
1350 error << _("Session: XML state has no Tempo Map section") << endmsg;
1352 } else if (_tempo_map->set_state (*child, version)) {
1356 if ((child = find_named_node (node, "Locations")) == 0) {
1357 error << _("Session: XML state has no locations section") << endmsg;
1359 } else if (_locations->set_state (*child, version)) {
1363 locations_changed ();
1365 if (_session_range_location) {
1366 AudioFileSource::set_header_position_offset (_session_range_location->start());
1369 if ((child = find_named_node (node, "Regions")) == 0) {
1370 error << _("Session: XML state has no Regions section") << endmsg;
1372 } else if (load_regions (*child)) {
1376 if ((child = find_named_node (node, "Playlists")) == 0) {
1377 error << _("Session: XML state has no playlists section") << endmsg;
1379 } else if (playlists->load (*this, *child)) {
1383 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1385 } else if (playlists->load_unused (*this, *child)) {
1389 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1390 if (load_compounds (*child)) {
1395 if (version >= 3000) {
1396 if ((child = find_named_node (node, "Bundles")) == 0) {
1397 warning << _("Session: XML state has no bundles section") << endmsg;
1400 /* We can't load Bundles yet as they need to be able
1401 to convert from port names to Port objects, which can't happen until
1403 _bundle_xml_node = new XMLNode (*child);
1407 if (version < 3000) {
1408 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1409 error << _("Session: XML state has no diskstreams section") << endmsg;
1411 } else if (load_diskstreams_2X (*child, version)) {
1416 if ((child = find_named_node (node, "Routes")) == 0) {
1417 error << _("Session: XML state has no routes section") << endmsg;
1419 } else if (load_routes (*child, version)) {
1423 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1424 _diskstreams_2X.clear ();
1426 if (version >= 3000) {
1428 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1429 error << _("Session: XML state has no route groups section") << endmsg;
1431 } else if (load_route_groups (*child, version)) {
1435 } else if (version < 3000) {
1437 if ((child = find_named_node (node, "EditGroups")) == 0) {
1438 error << _("Session: XML state has no edit groups section") << endmsg;
1440 } else if (load_route_groups (*child, version)) {
1444 if ((child = find_named_node (node, "MixGroups")) == 0) {
1445 error << _("Session: XML state has no mix groups section") << endmsg;
1447 } else if (load_route_groups (*child, version)) {
1452 if ((child = find_named_node (node, "Click")) == 0) {
1453 warning << _("Session: XML state has no click section") << endmsg;
1454 } else if (_click_io) {
1455 setup_click_state (&node);
1458 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1459 ControlProtocolManager::instance().set_state (*child, version);
1462 update_route_record_state ();
1464 /* here beginneth the second phase ... */
1465 set_snapshot_name (_current_snapshot_name);
1467 StateReady (); /* EMIT SIGNAL */
1480 Session::load_routes (const XMLNode& node, int version)
1483 XMLNodeConstIterator niter;
1484 RouteList new_routes;
1486 nlist = node.children();
1490 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1492 boost::shared_ptr<Route> route;
1493 if (version < 3000) {
1494 route = XMLRouteFactory_2X (**niter, version);
1496 route = XMLRouteFactory (**niter, version);
1500 error << _("Session: cannot create Route from XML description.") << endmsg;
1504 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1506 new_routes.push_back (route);
1509 BootMessage (_("Tracks/busses loaded; Adding to Session"));
1511 add_routes (new_routes, false, false, false);
1513 BootMessage (_("Finished adding tracks/busses"));
1518 boost::shared_ptr<Route>
1519 Session::XMLRouteFactory (const XMLNode& node, int version)
1521 boost::shared_ptr<Route> ret;
1523 if (node.name() != "Route") {
1527 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1529 DataType type = DataType::AUDIO;
1530 const XMLProperty* prop = node.property("default-type");
1533 type = DataType (prop->value());
1536 assert (type != DataType::NIL);
1540 boost::shared_ptr<Track> track;
1542 if (type == DataType::AUDIO) {
1543 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1545 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1548 if (track->init()) {
1552 if (track->set_state (node, version)) {
1556 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1557 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1562 enum Route::Flag flags = Route::Flag(0);
1563 const XMLProperty* prop = node.property("flags");
1565 flags = Route::Flag (string_2_enum (prop->value(), flags));
1568 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1570 if (r->init () == 0 && r->set_state (node, version) == 0) {
1571 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1572 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1581 boost::shared_ptr<Route>
1582 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1584 boost::shared_ptr<Route> ret;
1586 if (node.name() != "Route") {
1590 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1592 ds_prop = node.property (X_("diskstream"));
1595 DataType type = DataType::AUDIO;
1596 const XMLProperty* prop = node.property("default-type");
1599 type = DataType (prop->value());
1602 assert (type != DataType::NIL);
1606 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1607 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1611 if (i == _diskstreams_2X.end()) {
1612 error << _("Could not find diskstream for route") << endmsg;
1613 return boost::shared_ptr<Route> ();
1616 boost::shared_ptr<Track> track;
1618 if (type == DataType::AUDIO) {
1619 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1621 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1624 if (track->init()) {
1628 if (track->set_state (node, version)) {
1632 track->set_diskstream (*i);
1634 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1635 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1640 enum Route::Flag flags = Route::Flag(0);
1641 const XMLProperty* prop = node.property("flags");
1643 flags = Route::Flag (string_2_enum (prop->value(), flags));
1646 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1648 if (r->init () == 0 && r->set_state (node, version) == 0) {
1649 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1650 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1660 Session::load_regions (const XMLNode& node)
1663 XMLNodeConstIterator niter;
1664 boost::shared_ptr<Region> region;
1666 nlist = node.children();
1670 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1671 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1672 error << _("Session: cannot create Region from XML description.");
1673 const XMLProperty *name = (**niter).property("name");
1676 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1687 Session::load_compounds (const XMLNode& node)
1689 XMLNodeList calist = node.children();
1690 XMLNodeConstIterator caiter;
1691 XMLProperty *caprop;
1693 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1694 XMLNode* ca = *caiter;
1698 if ((caprop = ca->property (X_("original"))) == 0) {
1701 orig_id = caprop->value();
1703 if ((caprop = ca->property (X_("copy"))) == 0) {
1706 copy_id = caprop->value();
1708 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1709 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1711 if (!orig || !copy) {
1712 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1718 RegionFactory::add_compound_association (orig, copy);
1725 Session::load_nested_sources (const XMLNode& node)
1728 XMLNodeConstIterator niter;
1730 nlist = node.children();
1732 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1733 if ((*niter)->name() == "Source") {
1735 /* it may already exist, so don't recreate it unnecessarily
1738 XMLProperty* prop = (*niter)->property (X_("id"));
1740 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1744 ID source_id (prop->value());
1746 if (!source_by_id (source_id)) {
1749 SourceFactory::create (*this, **niter, true);
1751 catch (failed_constructor& err) {
1752 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1759 boost::shared_ptr<Region>
1760 Session::XMLRegionFactory (const XMLNode& node, bool full)
1762 const XMLProperty* type = node.property("type");
1766 const XMLNodeList& nlist = node.children();
1768 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1769 XMLNode *child = (*niter);
1770 if (child->name() == "NestedSource") {
1771 load_nested_sources (*child);
1775 if (!type || type->value() == "audio") {
1776 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1777 } else if (type->value() == "midi") {
1778 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1781 } catch (failed_constructor& err) {
1782 return boost::shared_ptr<Region> ();
1785 return boost::shared_ptr<Region> ();
1788 boost::shared_ptr<AudioRegion>
1789 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1791 const XMLProperty* prop;
1792 boost::shared_ptr<Source> source;
1793 boost::shared_ptr<AudioSource> as;
1795 SourceList master_sources;
1796 uint32_t nchans = 1;
1799 if (node.name() != X_("Region")) {
1800 return boost::shared_ptr<AudioRegion>();
1803 if ((prop = node.property (X_("channels"))) != 0) {
1804 nchans = atoi (prop->value().c_str());
1807 if ((prop = node.property ("name")) == 0) {
1808 cerr << "no name for this region\n";
1812 if ((prop = node.property (X_("source-0"))) == 0) {
1813 if ((prop = node.property ("source")) == 0) {
1814 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1815 return boost::shared_ptr<AudioRegion>();
1819 PBD::ID s_id (prop->value());
1821 if ((source = source_by_id (s_id)) == 0) {
1822 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1823 return boost::shared_ptr<AudioRegion>();
1826 as = boost::dynamic_pointer_cast<AudioSource>(source);
1828 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1829 return boost::shared_ptr<AudioRegion>();
1832 sources.push_back (as);
1834 /* pickup other channels */
1836 for (uint32_t n=1; n < nchans; ++n) {
1837 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1838 if ((prop = node.property (buf)) != 0) {
1840 PBD::ID id2 (prop->value());
1842 if ((source = source_by_id (id2)) == 0) {
1843 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1844 return boost::shared_ptr<AudioRegion>();
1847 as = boost::dynamic_pointer_cast<AudioSource>(source);
1849 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1850 return boost::shared_ptr<AudioRegion>();
1852 sources.push_back (as);
1856 for (uint32_t n = 0; n < nchans; ++n) {
1857 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1858 if ((prop = node.property (buf)) != 0) {
1860 PBD::ID id2 (prop->value());
1862 if ((source = source_by_id (id2)) == 0) {
1863 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1864 return boost::shared_ptr<AudioRegion>();
1867 as = boost::dynamic_pointer_cast<AudioSource>(source);
1869 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1870 return boost::shared_ptr<AudioRegion>();
1872 master_sources.push_back (as);
1877 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1879 /* a final detail: this is the one and only place that we know how long missing files are */
1881 if (region->whole_file()) {
1882 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1883 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1885 sfp->set_length (region->length());
1890 if (!master_sources.empty()) {
1891 if (master_sources.size() != nchans) {
1892 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1894 region->set_master_sources (master_sources);
1902 catch (failed_constructor& err) {
1903 return boost::shared_ptr<AudioRegion>();
1907 boost::shared_ptr<MidiRegion>
1908 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1910 const XMLProperty* prop;
1911 boost::shared_ptr<Source> source;
1912 boost::shared_ptr<MidiSource> ms;
1915 if (node.name() != X_("Region")) {
1916 return boost::shared_ptr<MidiRegion>();
1919 if ((prop = node.property ("name")) == 0) {
1920 cerr << "no name for this region\n";
1924 if ((prop = node.property (X_("source-0"))) == 0) {
1925 if ((prop = node.property ("source")) == 0) {
1926 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1927 return boost::shared_ptr<MidiRegion>();
1931 PBD::ID s_id (prop->value());
1933 if ((source = source_by_id (s_id)) == 0) {
1934 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1935 return boost::shared_ptr<MidiRegion>();
1938 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1940 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1941 return boost::shared_ptr<MidiRegion>();
1944 sources.push_back (ms);
1947 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1948 /* a final detail: this is the one and only place that we know how long missing files are */
1950 if (region->whole_file()) {
1951 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1952 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1954 sfp->set_length (region->length());
1962 catch (failed_constructor& err) {
1963 return boost::shared_ptr<MidiRegion>();
1968 Session::get_sources_as_xml ()
1971 XMLNode* node = new XMLNode (X_("Sources"));
1972 Glib::Threads::Mutex::Lock lm (source_lock);
1974 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1975 node->add_child_nocopy (i->second->get_state());
1982 Session::reset_write_sources (bool mark_write_complete, bool force)
1984 boost::shared_ptr<RouteList> rl = routes.reader();
1985 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1986 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1988 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
1989 tr->reset_write_sources(mark_write_complete, force);
1990 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
1996 Session::load_sources (const XMLNode& node)
1999 XMLNodeConstIterator niter;
2000 boost::shared_ptr<Source> source; /* don't need this but it stops some
2001 * versions of gcc complaining about
2002 * discarded return values.
2005 nlist = node.children();
2009 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2012 if ((source = XMLSourceFactory (**niter)) == 0) {
2013 error << _("Session: cannot create Source from XML description.") << endmsg;
2016 } catch (MissingSource& err) {
2020 if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
2021 error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
2022 PROGRAM_NAME) << endmsg;
2026 if (!no_questions_about_missing_files) {
2027 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
2032 switch (user_choice) {
2034 /* user added a new search location, so try again */
2039 /* user asked to quit the entire session load
2044 no_questions_about_missing_files = true;
2048 no_questions_about_missing_files = true;
2055 case DataType::AUDIO:
2056 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
2059 case DataType::MIDI:
2060 /* The MIDI file is actually missing so
2061 * just create a new one in the same
2062 * location. Do not announce its
2066 if (!Glib::path_is_absolute (err.path)) {
2067 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
2069 /* this should be an unrecoverable error: we would be creating a MIDI file outside
2074 /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
2075 source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
2076 /* reset ID to match the missing one */
2077 source->set_id (**niter);
2078 /* Now we can announce it */
2079 SourceFactory::SourceCreated (source);
2090 boost::shared_ptr<Source>
2091 Session::XMLSourceFactory (const XMLNode& node)
2093 if (node.name() != "Source") {
2094 return boost::shared_ptr<Source>();
2098 /* note: do peak building in another thread when loading session state */
2099 return SourceFactory::create (*this, node, true);
2102 catch (failed_constructor& err) {
2103 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
2104 return boost::shared_ptr<Source>();
2109 Session::save_template (string template_name, bool replace_existing)
2111 if ((_state_of_the_state & CannotSave) || template_name.empty ()) {
2115 bool absolute_path = Glib::path_is_absolute (template_name);
2117 /* directory to put the template in */
2118 std::string template_dir_path;
2120 if (!absolute_path) {
2121 std::string user_template_dir(user_template_directory());
2123 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2124 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2125 user_template_dir, g_strerror (errno)) << endmsg;
2129 template_dir_path = Glib::build_filename (user_template_dir, template_name);
2131 template_dir_path = template_name;
2134 if (!ARDOUR::Profile->get_trx()) {
2135 if (!replace_existing && Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2136 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2137 template_dir_path) << endmsg;
2141 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2142 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2143 template_dir_path, g_strerror (errno)) << endmsg;
2149 std::string template_file_path;
2151 if (ARDOUR::Profile->get_trx()) {
2152 template_file_path = template_name;
2154 if (absolute_path) {
2155 template_file_path = Glib::build_filename (template_dir_path, Glib::path_get_basename (template_dir_path) + template_suffix);
2157 template_file_path = Glib::build_filename (template_dir_path, template_name + template_suffix);
2161 SessionSaveUnderway (); /* EMIT SIGNAL */
2166 PBD::Unwinder<std::string> uw (_template_state_dir, template_dir_path);
2167 tree.set_root (&get_template());
2170 if (!tree.write (template_file_path)) {
2171 error << _("template not saved") << endmsg;
2175 store_recent_templates (template_file_path);
2181 Session::refresh_disk_space ()
2183 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2185 Glib::Threads::Mutex::Lock lm (space_lock);
2187 /* get freespace on every FS that is part of the session path */
2189 _total_free_4k_blocks = 0;
2190 _total_free_4k_blocks_uncertain = false;
2192 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2194 struct statfs statfsbuf;
2195 statfs (i->path.c_str(), &statfsbuf);
2197 double const scale = statfsbuf.f_bsize / 4096.0;
2199 /* See if this filesystem is read-only */
2200 struct statvfs statvfsbuf;
2201 statvfs (i->path.c_str(), &statvfsbuf);
2203 /* f_bavail can be 0 if it is undefined for whatever
2204 filesystem we are looking at; Samba shares mounted
2205 via GVFS are an example of this.
2207 if (statfsbuf.f_bavail == 0) {
2208 /* block count unknown */
2210 i->blocks_unknown = true;
2211 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2212 /* read-only filesystem */
2214 i->blocks_unknown = false;
2216 /* read/write filesystem with known space */
2217 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2218 i->blocks_unknown = false;
2221 _total_free_4k_blocks += i->blocks;
2222 if (i->blocks_unknown) {
2223 _total_free_4k_blocks_uncertain = true;
2226 #elif defined PLATFORM_WINDOWS
2227 vector<string> scanned_volumes;
2228 vector<string>::iterator j;
2229 vector<space_and_path>::iterator i;
2230 DWORD nSectorsPerCluster, nBytesPerSector,
2231 nFreeClusters, nTotalClusters;
2235 _total_free_4k_blocks = 0;
2237 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2238 strncpy (disk_drive, (*i).path.c_str(), 3);
2242 volume_found = false;
2243 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2245 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2246 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2247 i->blocks = (uint32_t)(nFreeBytes / 4096);
2249 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2250 if (0 == j->compare(disk_drive)) {
2251 volume_found = true;
2256 if (!volume_found) {
2257 scanned_volumes.push_back(disk_drive);
2258 _total_free_4k_blocks += i->blocks;
2263 if (0 == _total_free_4k_blocks) {
2264 strncpy (disk_drive, path().c_str(), 3);
2267 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2269 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2270 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2271 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2278 Session::get_best_session_directory_for_new_audio ()
2280 vector<space_and_path>::iterator i;
2281 string result = _session_dir->root_path();
2283 /* handle common case without system calls */
2285 if (session_dirs.size() == 1) {
2289 /* OK, here's the algorithm we're following here:
2291 We want to select which directory to use for
2292 the next file source to be created. Ideally,
2293 we'd like to use a round-robin process so as to
2294 get maximum performance benefits from splitting
2295 the files across multiple disks.
2297 However, in situations without much diskspace, an
2298 RR approach may end up filling up a filesystem
2299 with new files while others still have space.
2300 Its therefore important to pay some attention to
2301 the freespace in the filesystem holding each
2302 directory as well. However, if we did that by
2303 itself, we'd keep creating new files in the file
2304 system with the most space until it was as full
2305 as all others, thus negating any performance
2306 benefits of this RAID-1 like approach.
2308 So, we use a user-configurable space threshold. If
2309 there are at least 2 filesystems with more than this
2310 much space available, we use RR selection between them.
2311 If not, then we pick the filesystem with the most space.
2313 This gets a good balance between the two
2317 refresh_disk_space ();
2319 int free_enough = 0;
2321 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2322 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2327 if (free_enough >= 2) {
2328 /* use RR selection process, ensuring that the one
2332 i = last_rr_session_dir;
2335 if (++i == session_dirs.end()) {
2336 i = session_dirs.begin();
2339 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2340 SessionDirectory sdir(i->path);
2341 if (sdir.create ()) {
2343 last_rr_session_dir = i;
2348 } while (i != last_rr_session_dir);
2352 /* pick FS with the most freespace (and that
2353 seems to actually work ...)
2356 vector<space_and_path> sorted;
2357 space_and_path_ascending_cmp cmp;
2359 sorted = session_dirs;
2360 sort (sorted.begin(), sorted.end(), cmp);
2362 for (i = sorted.begin(); i != sorted.end(); ++i) {
2363 SessionDirectory sdir(i->path);
2364 if (sdir.create ()) {
2366 last_rr_session_dir = i;
2376 Session::automation_dir () const
2378 return Glib::build_filename (_path, automation_dir_name);
2382 Session::analysis_dir () const
2384 return Glib::build_filename (_path, analysis_dir_name);
2388 Session::plugins_dir () const
2390 return Glib::build_filename (_path, plugins_dir_name);
2394 Session::externals_dir () const
2396 return Glib::build_filename (_path, externals_dir_name);
2400 Session::load_bundles (XMLNode const & node)
2402 XMLNodeList nlist = node.children();
2403 XMLNodeConstIterator niter;
2407 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2408 if ((*niter)->name() == "InputBundle") {
2409 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2410 } else if ((*niter)->name() == "OutputBundle") {
2411 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2413 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2422 Session::load_route_groups (const XMLNode& node, int version)
2424 XMLNodeList nlist = node.children();
2425 XMLNodeConstIterator niter;
2429 if (version >= 3000) {
2431 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2432 if ((*niter)->name() == "RouteGroup") {
2433 RouteGroup* rg = new RouteGroup (*this, "");
2434 add_route_group (rg);
2435 rg->set_state (**niter, version);
2439 } else if (version < 3000) {
2441 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2442 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2443 RouteGroup* rg = new RouteGroup (*this, "");
2444 add_route_group (rg);
2445 rg->set_state (**niter, version);
2454 state_file_filter (const string &str, void* /*arg*/)
2456 return (str.length() > strlen(statefile_suffix) &&
2457 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2461 remove_end(string state)
2463 string statename(state);
2465 string::size_type start,end;
2466 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2467 statename = statename.substr (start+1);
2470 if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2471 end = statename.length();
2474 return string(statename.substr (0, end));
2478 Session::possible_states (string path)
2480 vector<string> states;
2481 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2483 transform(states.begin(), states.end(), states.begin(), remove_end);
2485 sort (states.begin(), states.end());
2491 Session::possible_states () const
2493 return possible_states(_path);
2497 Session::add_route_group (RouteGroup* g)
2499 _route_groups.push_back (g);
2500 route_group_added (g); /* EMIT SIGNAL */
2502 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2503 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2504 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2510 Session::remove_route_group (RouteGroup& rg)
2512 list<RouteGroup*>::iterator i;
2514 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2515 _route_groups.erase (i);
2518 route_group_removed (); /* EMIT SIGNAL */
2522 /** Set a new order for our route groups, without adding or removing any.
2523 * @param groups Route group list in the new order.
2526 Session::reorder_route_groups (list<RouteGroup*> groups)
2528 _route_groups = groups;
2530 route_groups_reordered (); /* EMIT SIGNAL */
2536 Session::route_group_by_name (string name)
2538 list<RouteGroup *>::iterator i;
2540 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2541 if ((*i)->name() == name) {
2549 Session::all_route_group() const
2551 return *_all_route_group;
2555 Session::add_commands (vector<Command*> const & cmds)
2557 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2563 Session::add_command (Command* const cmd)
2565 assert (_current_trans);
2566 DEBUG_UNDO_HISTORY (
2567 string_compose ("Current Undo Transaction %1, adding command: %2",
2568 _current_trans->name (),
2570 _current_trans->add_command (cmd);
2573 Session::begin_reversible_command (const string& name)
2575 begin_reversible_command (g_quark_from_string (name.c_str ()));
2578 /** Begin a reversible command using a GQuark to identify it.
2579 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2580 * but there must be as many begin...()s as there are commit...()s.
2583 Session::begin_reversible_command (GQuark q)
2585 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2586 to hold all the commands that are committed. This keeps the order of
2587 commands correct in the history.
2590 if (_current_trans == 0) {
2591 DEBUG_UNDO_HISTORY (string_compose (
2592 "Begin Reversible Command, new transaction: %1", g_quark_to_string (q)));
2594 /* start a new transaction */
2595 assert (_current_trans_quarks.empty ());
2596 _current_trans = new UndoTransaction();
2597 _current_trans->set_name (g_quark_to_string (q));
2599 DEBUG_UNDO_HISTORY (
2600 string_compose ("Begin Reversible Command, current transaction: %1",
2601 _current_trans->name ()));
2604 _current_trans_quarks.push_front (q);
2608 Session::abort_reversible_command ()
2610 if (_current_trans != 0) {
2611 DEBUG_UNDO_HISTORY (
2612 string_compose ("Abort Reversible Command: %1", _current_trans->name ()));
2613 _current_trans->clear();
2614 delete _current_trans;
2616 _current_trans_quarks.clear();
2621 Session::commit_reversible_command (Command *cmd)
2623 assert (_current_trans);
2624 assert (!_current_trans_quarks.empty ());
2629 DEBUG_UNDO_HISTORY (
2630 string_compose ("Current Undo Transaction %1, adding command: %2",
2631 _current_trans->name (),
2633 _current_trans->add_command (cmd);
2636 DEBUG_UNDO_HISTORY (
2637 string_compose ("Commit Reversible Command, current transaction: %1",
2638 _current_trans->name ()));
2640 _current_trans_quarks.pop_front ();
2642 if (!_current_trans_quarks.empty ()) {
2643 DEBUG_UNDO_HISTORY (
2644 string_compose ("Commit Reversible Command, transaction is not "
2645 "top-level, current transaction: %1",
2646 _current_trans->name ()));
2647 /* the transaction we're committing is not the top-level one */
2651 if (_current_trans->empty()) {
2652 /* no commands were added to the transaction, so just get rid of it */
2653 DEBUG_UNDO_HISTORY (
2654 string_compose ("Commit Reversible Command, No commands were "
2655 "added to current transaction: %1",
2656 _current_trans->name ()));
2657 delete _current_trans;
2662 gettimeofday (&now, 0);
2663 _current_trans->set_timestamp (now);
2665 _history.add (_current_trans);
2670 accept_all_audio_files (const string& path, void* /*arg*/)
2672 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2676 if (!AudioFileSource::safe_audio_file_extension (path)) {
2684 accept_all_midi_files (const string& path, void* /*arg*/)
2686 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2690 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2691 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2692 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2696 accept_all_state_files (const string& path, void* /*arg*/)
2698 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2702 std::string const statefile_ext (statefile_suffix);
2703 if (path.length() >= statefile_ext.length()) {
2704 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2711 Session::find_all_sources (string path, set<string>& result)
2716 if (!tree.read (path)) {
2720 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2725 XMLNodeConstIterator niter;
2727 nlist = node->children();
2731 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2735 if ((prop = (*niter)->property (X_("type"))) == 0) {
2739 DataType type (prop->value());
2741 if ((prop = (*niter)->property (X_("name"))) == 0) {
2745 if (Glib::path_is_absolute (prop->value())) {
2746 /* external file, ignore */
2754 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2755 result.insert (found_path);
2763 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2765 vector<string> state_files;
2767 string this_snapshot_path;
2773 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2774 ripped = ripped.substr (0, ripped.length() - 1);
2777 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2779 if (state_files.empty()) {
2784 this_snapshot_path = _path;
2785 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2786 this_snapshot_path += statefile_suffix;
2788 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2790 if (exclude_this_snapshot && *i == this_snapshot_path) {
2794 if (find_all_sources (*i, result) < 0) {
2802 struct RegionCounter {
2803 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2804 AudioSourceList::iterator iter;
2805 boost::shared_ptr<Region> region;
2808 RegionCounter() : count (0) {}
2812 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2814 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2815 return r.get_value_or (1);
2819 Session::cleanup_regions ()
2821 bool removed = false;
2822 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2824 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2826 uint32_t used = playlists->region_use_count (i->second);
2828 if (used == 0 && !i->second->automatic ()) {
2829 boost::weak_ptr<Region> w = i->second;
2832 RegionFactory::map_remove (w);
2839 // re-check to remove parent references of compound regions
2840 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2841 if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2845 assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2846 if (0 == playlists->region_use_count (i->second)) {
2847 boost::weak_ptr<Region> w = i->second;
2849 RegionFactory::map_remove (w);
2856 /* dump the history list */
2863 Session::can_cleanup_peakfiles () const
2865 if (deletion_in_progress()) {
2868 if (!_writable || (_state_of_the_state & CannotSave)) {
2869 warning << _("Cannot cleanup peak-files for read-only session.") << endmsg;
2872 if (record_status() == Recording) {
2873 error << _("Cannot cleanup peak-files while recording") << endmsg;
2880 Session::cleanup_peakfiles ()
2882 Glib::Threads::Mutex::Lock lm (peak_cleanup_lock, Glib::Threads::TRY_LOCK);
2887 assert (can_cleanup_peakfiles ());
2888 assert (!peaks_cleanup_in_progres());
2890 _state_of_the_state = StateOfTheState (_state_of_the_state | PeakCleanup);
2892 int timeout = 5000; // 5 seconds
2893 while (!SourceFactory::files_with_peaks.empty()) {
2894 Glib::usleep (1000);
2895 if (--timeout < 0) {
2896 warning << _("Timeout waiting for peak-file creation to terminate before cleanup, please try again later.") << endmsg;
2897 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
2902 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2903 boost::shared_ptr<AudioSource> as;
2904 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
2905 as->close_peakfile();
2909 PBD::clear_directory (session_directory().peak_path());
2911 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
2913 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2914 boost::shared_ptr<AudioSource> as;
2915 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
2916 SourceFactory::setup_peakfile(as, true);
2923 Session::cleanup_sources (CleanupReport& rep)
2925 // FIXME: needs adaptation to midi
2927 vector<boost::shared_ptr<Source> > dead_sources;
2930 vector<string> candidates;
2931 vector<string> unused;
2932 set<string> all_sources;
2941 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2943 /* this is mostly for windows which doesn't allow file
2944 * renaming if the file is in use. But we don't special
2945 * case it because we need to know if this causes
2946 * problems, and the easiest way to notice that is to
2947 * keep it in place for all platforms.
2950 request_stop (false);
2952 _butler->wait_until_finished ();
2954 /* consider deleting all unused playlists */
2956 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2961 /* sync the "all regions" property of each playlist with its current state
2964 playlists->sync_all_regions_with_regions ();
2966 /* find all un-used sources */
2971 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2973 SourceMap::iterator tmp;
2978 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2982 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2983 dead_sources.push_back (i->second);
2984 i->second->drop_references ();
2990 /* build a list of all the possible audio directories for the session */
2992 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2993 SessionDirectory sdir ((*i).path);
2994 asp += sdir.sound_path();
2996 audio_path += asp.to_string();
2999 /* build a list of all the possible midi directories for the session */
3001 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3002 SessionDirectory sdir ((*i).path);
3003 msp += sdir.midi_path();
3005 midi_path += msp.to_string();
3007 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
3008 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
3010 /* find all sources, but don't use this snapshot because the
3011 state file on disk still references sources we may have already
3015 find_all_sources_across_snapshots (all_sources, true);
3017 /* add our current source list
3020 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3021 boost::shared_ptr<FileSource> fs;
3022 SourceMap::iterator tmp = i;
3025 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
3027 /* this is mostly for windows which doesn't allow file
3028 * renaming if the file is in use. But we don't special
3029 * case it because we need to know if this causes
3030 * problems, and the easiest way to notice that is to
3031 * keep it in place for all platforms.
3036 if (!fs->is_stub()) {
3038 if (playlists->source_use_count (fs) != 0) {
3039 all_sources.insert (fs->path());
3042 /* we might not remove this source from disk, because it may be used
3043 by other snapshots, but its not being used in this version
3044 so lets get rid of it now, along with any representative regions
3048 RegionFactory::remove_regions_using_source (i->second);
3050 // also remove source from all_sources
3052 for (set<string>::iterator j = all_sources.begin(); j != all_sources.end(); ++j) {
3053 spath = Glib::path_get_basename (*j);
3054 if (spath == i->second->name()) {
3055 all_sources.erase (j);
3068 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
3073 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
3075 tmppath1 = canonical_path (spath);
3076 tmppath2 = canonical_path ((*i));
3078 if (tmppath1 == tmppath2) {
3085 unused.push_back (spath);
3089 /* now try to move all unused files into the "dead" directory(ies) */
3091 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
3096 /* don't move the file across filesystems, just
3097 stick it in the `dead_dir_name' directory
3098 on whichever filesystem it was already on.
3101 if ((*x).find ("/sounds/") != string::npos) {
3103 /* old school, go up 1 level */
3105 newpath = Glib::path_get_dirname (*x); // "sounds"
3106 newpath = Glib::path_get_dirname (newpath); // "session-name"
3110 /* new school, go up 4 levels */
3112 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
3113 newpath = Glib::path_get_dirname (newpath); // "session-name"
3114 newpath = Glib::path_get_dirname (newpath); // "interchange"
3115 newpath = Glib::path_get_dirname (newpath); // "session-dir"
3118 newpath = Glib::build_filename (newpath, dead_dir_name);
3120 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
3121 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
3125 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
3127 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
3129 /* the new path already exists, try versioning */
3131 char buf[PATH_MAX+1];
3135 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3138 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
3139 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3143 if (version == 999) {
3144 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3148 newpath = newpath_v;
3153 /* it doesn't exist, or we can't read it or something */
3157 g_stat ((*x).c_str(), &statbuf);
3159 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3160 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
3161 (*x), newpath, strerror (errno))
3166 /* see if there an easy to find peakfile for this file, and remove it.
3169 string base = Glib::path_get_basename (*x);
3170 base += "%A"; /* this is what we add for the channel suffix of all native files,
3171 or for the first channel of embedded files. it will miss
3172 some peakfiles for other channels
3174 string peakpath = construct_peak_filepath (base);
3176 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
3177 if (::g_unlink (peakpath.c_str()) != 0) {
3178 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3179 peakpath, _path, strerror (errno))
3181 /* try to back out */
3182 ::rename (newpath.c_str(), _path.c_str());
3187 rep.paths.push_back (*x);
3188 rep.space += statbuf.st_size;
3191 /* dump the history list */
3195 /* save state so we don't end up a session file
3196 referring to non-existent sources.
3203 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3209 Session::cleanup_trash_sources (CleanupReport& rep)
3211 // FIXME: needs adaptation for MIDI
3213 vector<space_and_path>::iterator i;
3219 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3221 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
3223 clear_directory (dead_dir, &rep.space, &rep.paths);
3230 Session::set_dirty ()
3232 /* never mark session dirty during loading */
3234 if (_state_of_the_state & Loading) {
3238 bool was_dirty = dirty();
3240 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3244 DirtyChanged(); /* EMIT SIGNAL */
3250 Session::set_clean ()
3252 bool was_dirty = dirty();
3254 _state_of_the_state = Clean;
3258 DirtyChanged(); /* EMIT SIGNAL */
3263 Session::set_deletion_in_progress ()
3265 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3269 Session::clear_deletion_in_progress ()
3271 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3275 Session::add_controllable (boost::shared_ptr<Controllable> c)
3277 /* this adds a controllable to the list managed by the Session.
3278 this is a subset of those managed by the Controllable class
3279 itself, and represents the only ones whose state will be saved
3280 as part of the session.
3283 Glib::Threads::Mutex::Lock lm (controllables_lock);
3284 controllables.insert (c);
3287 struct null_deleter { void operator()(void const *) const {} };
3290 Session::remove_controllable (Controllable* c)
3292 if (_state_of_the_state & Deletion) {
3296 Glib::Threads::Mutex::Lock lm (controllables_lock);
3298 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3300 if (x != controllables.end()) {
3301 controllables.erase (x);
3305 boost::shared_ptr<Controllable>
3306 Session::controllable_by_id (const PBD::ID& id)
3308 Glib::Threads::Mutex::Lock lm (controllables_lock);
3310 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3311 if ((*i)->id() == id) {
3316 return boost::shared_ptr<Controllable>();
3319 boost::shared_ptr<Controllable>
3320 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3322 boost::shared_ptr<Controllable> c;
3323 boost::shared_ptr<Route> r;
3325 switch (desc.top_level_type()) {
3326 case ControllableDescriptor::NamedRoute:
3328 std::string str = desc.top_level_name();
3329 if (str == "Master" || str == "master") {
3331 } else if (str == "control" || str == "listen") {
3334 r = route_by_name (desc.top_level_name());
3339 case ControllableDescriptor::RemoteControlID:
3340 r = route_by_remote_id (desc.rid());
3348 switch (desc.subtype()) {
3349 case ControllableDescriptor::Gain:
3350 c = r->gain_control ();
3353 case ControllableDescriptor::Trim:
3354 c = r->trim()->gain_control ();
3357 case ControllableDescriptor::Solo:
3358 c = r->solo_control();
3361 case ControllableDescriptor::Mute:
3362 c = r->mute_control();
3365 case ControllableDescriptor::Recenable:
3367 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3370 c = t->rec_enable_control ();
3375 case ControllableDescriptor::PanDirection:
3377 c = r->pannable()->pan_azimuth_control;
3381 case ControllableDescriptor::PanWidth:
3383 c = r->pannable()->pan_width_control;
3387 case ControllableDescriptor::PanElevation:
3389 c = r->pannable()->pan_elevation_control;
3393 case ControllableDescriptor::Balance:
3394 /* XXX simple pan control */
3397 case ControllableDescriptor::PluginParameter:
3399 uint32_t plugin = desc.target (0);
3400 uint32_t parameter_index = desc.target (1);
3402 /* revert to zero based counting */
3408 if (parameter_index > 0) {
3412 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3415 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3416 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3421 case ControllableDescriptor::SendGain:
3423 uint32_t send = desc.target (0);
3425 /* revert to zero-based counting */
3431 boost::shared_ptr<Processor> p = r->nth_send (send);
3434 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3435 boost::shared_ptr<Amp> a = s->amp();
3438 c = s->amp()->gain_control();
3445 /* relax and return a null pointer */
3453 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3456 Stateful::add_instant_xml (node, _path);
3459 if (write_to_config) {
3460 Config->add_instant_xml (node);
3465 Session::instant_xml (const string& node_name)
3467 return Stateful::instant_xml (node_name, _path);
3471 Session::save_history (string snapshot_name)
3479 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3480 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3484 if (snapshot_name.empty()) {
3485 snapshot_name = _current_snapshot_name;
3488 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3489 const string backup_filename = history_filename + backup_suffix;
3490 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3491 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3493 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3494 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3495 error << _("could not backup old history file, current history not saved") << endmsg;
3500 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3502 if (!tree.write (xml_path))
3504 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3506 if (g_remove (xml_path.c_str()) != 0) {
3507 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3508 xml_path, g_strerror (errno)) << endmsg;
3510 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3511 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3512 backup_path, g_strerror (errno)) << endmsg;
3522 Session::restore_history (string snapshot_name)
3526 if (snapshot_name.empty()) {
3527 snapshot_name = _current_snapshot_name;
3530 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3531 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3533 info << "Loading history from " << xml_path << endmsg;
3535 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3536 info << string_compose (_("%1: no history file \"%2\" for this session."),
3537 _name, xml_path) << endmsg;
3541 if (!tree.read (xml_path)) {
3542 error << string_compose (_("Could not understand session history file \"%1\""),
3543 xml_path) << endmsg;
3550 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3553 UndoTransaction* ut = new UndoTransaction ();
3556 ut->set_name(t->property("name")->value());
3557 stringstream ss(t->property("tv-sec")->value());
3559 ss.str(t->property("tv-usec")->value());
3561 ut->set_timestamp(tv);
3563 for (XMLNodeConstIterator child_it = t->children().begin();
3564 child_it != t->children().end(); child_it++)
3566 XMLNode *n = *child_it;
3569 if (n->name() == "MementoCommand" ||
3570 n->name() == "MementoUndoCommand" ||
3571 n->name() == "MementoRedoCommand") {
3573 if ((c = memento_command_factory(n))) {
3577 } else if (n->name() == "NoteDiffCommand") {
3578 PBD::ID id (n->property("midi-source")->value());
3579 boost::shared_ptr<MidiSource> midi_source =
3580 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3582 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3584 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3587 } else if (n->name() == "SysExDiffCommand") {
3589 PBD::ID id (n->property("midi-source")->value());
3590 boost::shared_ptr<MidiSource> midi_source =
3591 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3593 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3595 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3598 } else if (n->name() == "PatchChangeDiffCommand") {
3600 PBD::ID id (n->property("midi-source")->value());
3601 boost::shared_ptr<MidiSource> midi_source =
3602 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3604 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3606 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3609 } else if (n->name() == "StatefulDiffCommand") {
3610 if ((c = stateful_diff_command_factory (n))) {
3611 ut->add_command (c);
3614 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3625 Session::config_changed (std::string p, bool ours)
3631 if (p == "seamless-loop") {
3633 } else if (p == "rf-speed") {
3635 } else if (p == "auto-loop") {
3637 } else if (p == "auto-input") {
3639 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3640 /* auto-input only makes a difference if we're rolling */
3641 set_track_monitor_input_status (!config.get_auto_input());
3644 } else if (p == "punch-in") {
3648 if ((location = _locations->auto_punch_location()) != 0) {
3650 if (config.get_punch_in ()) {
3651 replace_event (SessionEvent::PunchIn, location->start());
3653 remove_event (location->start(), SessionEvent::PunchIn);
3657 } else if (p == "punch-out") {
3661 if ((location = _locations->auto_punch_location()) != 0) {
3663 if (config.get_punch_out()) {
3664 replace_event (SessionEvent::PunchOut, location->end());
3666 clear_events (SessionEvent::PunchOut);
3670 } else if (p == "edit-mode") {
3672 Glib::Threads::Mutex::Lock lm (playlists->lock);
3674 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3675 (*i)->set_edit_mode (Config->get_edit_mode ());
3678 } else if (p == "use-video-sync") {
3680 waiting_for_sync_offset = config.get_use_video_sync();
3682 } else if (p == "mmc-control") {
3684 //poke_midi_thread ();
3686 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3688 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3690 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3692 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3694 } else if (p == "midi-control") {
3696 //poke_midi_thread ();
3698 } else if (p == "raid-path") {
3700 setup_raid_path (config.get_raid_path());
3702 } else if (p == "timecode-format") {
3706 } else if (p == "video-pullup") {
3710 } else if (p == "seamless-loop") {
3712 if (play_loop && transport_rolling()) {
3713 // to reset diskstreams etc
3714 request_play_loop (true);
3717 } else if (p == "rf-speed") {
3719 cumulative_rf_motion = 0;
3722 } else if (p == "click-sound") {
3724 setup_click_sounds (1);
3726 } else if (p == "click-emphasis-sound") {
3728 setup_click_sounds (-1);
3730 } else if (p == "clicking") {
3732 if (Config->get_clicking()) {
3733 if (_click_io && click_data) { // don't require emphasis data
3740 } else if (p == "click-gain") {
3743 _click_gain->gain_control()->set_value (Config->get_click_gain(), Controllable::NoGroup);
3746 } else if (p == "send-mtc") {
3748 if (Config->get_send_mtc ()) {
3749 /* mark us ready to send */
3750 next_quarter_frame_to_send = 0;
3753 } else if (p == "send-mmc") {
3755 _mmc->enable_send (Config->get_send_mmc ());
3757 } else if (p == "midi-feedback") {
3759 session_midi_feedback = Config->get_midi_feedback();
3761 } else if (p == "jack-time-master") {
3763 engine().reset_timebase ();
3765 } else if (p == "native-file-header-format") {
3767 if (!first_file_header_format_reset) {
3768 reset_native_file_format ();
3771 first_file_header_format_reset = false;
3773 } else if (p == "native-file-data-format") {
3775 if (!first_file_data_format_reset) {
3776 reset_native_file_format ();
3779 first_file_data_format_reset = false;
3781 } else if (p == "external-sync") {
3782 if (!config.get_external_sync()) {
3783 drop_sync_source ();
3785 switch_to_sync_source (Config->get_sync_source());
3787 } else if (p == "denormal-model") {
3789 } else if (p == "history-depth") {
3790 set_history_depth (Config->get_history_depth());
3791 } else if (p == "remote-model") {
3792 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3795 } else if (p == "initial-program-change") {
3797 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3800 buf[0] = MIDI::program; // channel zero by default
3801 buf[1] = (Config->get_initial_program_change() & 0x7f);
3803 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3805 } else if (p == "solo-mute-override") {
3806 // catch_up_on_solo_mute_override ();
3807 } else if (p == "listen-position" || p == "pfl-position") {
3808 listen_position_changed ();
3809 } else if (p == "solo-control-is-listen-control") {
3810 solo_control_mode_changed ();
3811 } else if (p == "solo-mute-gain") {
3812 _solo_cut_control->Changed();
3813 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3814 last_timecode_valid = false;
3815 } else if (p == "playback-buffer-seconds") {
3816 AudioSource::allocate_working_buffers (frame_rate());
3817 } else if (p == "ltc-source-port") {
3818 reconnect_ltc_input ();
3819 } else if (p == "ltc-sink-port") {
3820 reconnect_ltc_output ();
3821 } else if (p == "timecode-generator-offset") {
3822 ltc_tx_parse_offset();
3823 } else if (p == "auto-return-target-list") {
3824 follow_playhead_priority ();
3831 Session::set_history_depth (uint32_t d)
3833 _history.set_depth (d);
3837 Session::load_diskstreams_2X (XMLNode const & node, int)
3840 XMLNodeConstIterator citer;
3842 clist = node.children();
3844 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3847 /* diskstreams added automatically by DiskstreamCreated handler */
3848 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3849 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3850 _diskstreams_2X.push_back (dsp);
3852 error << _("Session: unknown diskstream type in XML") << endmsg;
3856 catch (failed_constructor& err) {
3857 error << _("Session: could not load diskstream via XML state") << endmsg;
3865 /** Connect things to the MMC object */
3867 Session::setup_midi_machine_control ()
3869 _mmc = new MIDI::MachineControl;
3871 boost::shared_ptr<AsyncMIDIPort> async_in = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_input_port());
3872 boost::shared_ptr<AsyncMIDIPort> async_out = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_output_port());
3874 if (!async_out || !async_out) {
3878 /* XXXX argh, passing raw pointers back into libmidi++ */
3880 MIDI::Port* mmc_in = async_in.get();
3881 MIDI::Port* mmc_out = async_out.get();
3883 _mmc->set_ports (mmc_in, mmc_out);
3885 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3886 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3887 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3888 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3889 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3890 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3891 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3892 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3893 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3894 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3895 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3896 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3897 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3899 /* also handle MIDI SPP because its so common */
3901 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3902 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3903 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3906 boost::shared_ptr<Controllable>
3907 Session::solo_cut_control() const
3909 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3910 controls in Ardour that currently get presented to the user in the GUI that require
3911 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3913 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3914 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3918 return _solo_cut_control;
3922 Session::save_snapshot_name (const std::string & n)
3924 /* assure Stateful::_instant_xml is loaded
3925 * add_instant_xml() only adds to existing data and defaults
3926 * to use an empty Tree otherwise
3928 instant_xml ("LastUsedSnapshot");
3930 XMLNode* last_used_snapshot = new XMLNode ("LastUsedSnapshot");
3931 last_used_snapshot->add_property ("name", string(n));
3932 add_instant_xml (*last_used_snapshot, false);
3936 Session::set_snapshot_name (const std::string & n)
3938 _current_snapshot_name = n;
3939 save_snapshot_name (n);
3943 Session::rename (const std::string& new_name)
3945 string legal_name = legalize_for_path (new_name);
3951 string const old_sources_root = _session_dir->sources_root();
3953 if (!_writable || (_state_of_the_state & CannotSave)) {
3954 error << _("Cannot rename read-only session.") << endmsg;
3955 return 0; // don't show "messed up" warning
3957 if (record_status() == Recording) {
3958 error << _("Cannot rename session while recording") << endmsg;
3959 return 0; // don't show "messed up" warning
3962 StateProtector stp (this);
3967 * interchange subdirectory
3971 * Backup files are left unchanged and not renamed.
3974 /* Windows requires that we close all files before attempting the
3975 * rename. This works on other platforms, but isn't necessary there.
3976 * Leave it in place for all platforms though, since it may help
3977 * catch issues that could arise if the way Source files work ever
3978 * change (since most developers are not using Windows).
3981 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
3982 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3988 /* pass one: not 100% safe check that the new directory names don't
3992 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3996 /* this is a stupid hack because Glib::path_get_dirname() is
3997 * lexical-only, and so passing it /a/b/c/ gives a different
3998 * result than passing it /a/b/c ...
4001 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4002 oldstr = oldstr.substr (0, oldstr.length() - 1);
4005 string base = Glib::path_get_dirname (oldstr);
4007 newstr = Glib::build_filename (base, legal_name);
4009 cerr << "Looking for " << newstr << endl;
4011 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
4012 cerr << " exists\n";
4021 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4027 /* this is a stupid hack because Glib::path_get_dirname() is
4028 * lexical-only, and so passing it /a/b/c/ gives a different
4029 * result than passing it /a/b/c ...
4032 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4033 oldstr = oldstr.substr (0, oldstr.length() - 1);
4036 string base = Glib::path_get_dirname (oldstr);
4037 newstr = Glib::build_filename (base, legal_name);
4039 cerr << "for " << oldstr << " new dir = " << newstr << endl;
4041 cerr << "Rename " << oldstr << " => " << newstr << endl;
4042 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4043 cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4044 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4048 /* Reset path in "session dirs" */
4053 /* reset primary SessionDirectory object */
4056 (*_session_dir) = newstr;
4061 /* now rename directory below session_dir/interchange */
4063 string old_interchange_dir;
4064 string new_interchange_dir;
4066 /* use newstr here because we renamed the path
4067 * (folder/directory) that used to be oldstr to newstr above
4070 v.push_back (newstr);
4071 v.push_back (interchange_dir_name);
4072 v.push_back (Glib::path_get_basename (oldstr));
4074 old_interchange_dir = Glib::build_filename (v);
4077 v.push_back (newstr);
4078 v.push_back (interchange_dir_name);
4079 v.push_back (legal_name);
4081 new_interchange_dir = Glib::build_filename (v);
4083 cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
4085 if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
4086 cerr << string_compose (_("renaming %s as %2 failed (%3)"),
4087 old_interchange_dir, new_interchange_dir,
4090 error << string_compose (_("renaming %s as %2 failed (%3)"),
4091 old_interchange_dir, new_interchange_dir,
4100 oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
4101 newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
4103 cerr << "Rename " << oldstr << " => " << newstr << endl;
4105 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4106 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4107 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4113 oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
4115 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
4116 newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
4118 cerr << "Rename " << oldstr << " => " << newstr << endl;
4120 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4121 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4122 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4127 /* remove old name from recent sessions */
4128 remove_recent_sessions (_path);
4131 /* update file source paths */
4133 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
4134 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4136 string p = fs->path ();
4137 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
4139 SourceFactory::setup_peakfile(i->second, true);
4143 set_snapshot_name (new_name);
4148 /* save state again to get everything just right */
4150 save_state (_current_snapshot_name);
4152 /* add to recent sessions */
4154 store_recent_sessions (new_name, _path);
4160 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
4162 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
4166 if (!tree.read (xmlpath)) {
4174 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
4177 bool found_sr = false;
4178 bool found_data_format = false;
4180 if (get_session_info_from_path (tree, xmlpath)) {
4186 const XMLProperty* prop;
4187 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
4188 sample_rate = atoi (prop->value());
4192 const XMLNodeList& children (tree.root()->children());
4193 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
4194 const XMLNode* child = *c;
4195 if (child->name() == "Config") {
4196 const XMLNodeList& options (child->children());
4197 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
4198 const XMLNode* option = *oc;
4199 const XMLProperty* name = option->property("name");
4205 if (name->value() == "native-file-data-format") {
4206 const XMLProperty* value = option->property ("value");
4208 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
4210 found_data_format = true;
4216 if (found_data_format) {
4221 return !(found_sr && found_data_format); // zero if they are both found
4225 Session::get_snapshot_from_instant (const std::string& session_dir)
4227 std::string instant_xml_path = Glib::build_filename (session_dir, "instant.xml");
4229 if (!Glib::file_test (instant_xml_path, Glib::FILE_TEST_EXISTS)) {
4234 if (!tree.read (instant_xml_path)) {
4238 const XMLProperty* prop;
4239 XMLNode *last_used_snapshot = tree.root()->child("LastUsedSnapshot");
4240 if (last_used_snapshot && (prop = last_used_snapshot->property ("name")) != 0) {
4241 return prop->value();
4247 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
4248 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
4251 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
4255 SourcePathMap source_path_map;
4257 boost::shared_ptr<AudioFileSource> afs;
4262 Glib::Threads::Mutex::Lock lm (source_lock);
4264 cerr << " total sources = " << sources.size();
4266 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4267 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4273 if (fs->within_session()) {
4277 if (source_path_map.find (fs->path()) != source_path_map.end()) {
4278 source_path_map[fs->path()].push_back (fs);
4280 SeveralFileSources v;
4282 source_path_map.insert (make_pair (fs->path(), v));
4288 cerr << " fsources = " << total << endl;
4290 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
4292 /* tell caller where we are */
4294 string old_path = i->first;
4296 callback (n, total, old_path);
4298 cerr << old_path << endl;
4302 switch (i->second.front()->type()) {
4303 case DataType::AUDIO:
4304 new_path = new_audio_source_path_for_embedded (old_path);
4307 case DataType::MIDI:
4308 /* XXX not implemented yet */
4312 if (new_path.empty()) {
4316 cerr << "Move " << old_path << " => " << new_path << endl;
4318 if (!copy_file (old_path, new_path)) {
4319 cerr << "failed !\n";
4323 /* make sure we stop looking in the external
4324 dir/folder. Remember, this is an all-or-nothing
4325 operations, it doesn't merge just some files.
4327 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
4329 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
4330 (*f)->set_path (new_path);
4335 save_state ("", false, false);
4341 bool accept_all_files (string const &, void *)
4347 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4349 /* 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.
4354 make_new_media_path (string old_path, string new_session_folder, string new_session_path)
4356 /* typedir is the "midifiles" or "audiofiles" etc. part of the path. */
4358 string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4360 v.push_back (new_session_folder); /* full path */
4361 v.push_back (interchange_dir_name);
4362 v.push_back (new_session_path); /* just one directory/folder */
4363 v.push_back (typedir);
4364 v.push_back (Glib::path_get_basename (old_path));
4366 return Glib::build_filename (v);
4370 Session::save_as (SaveAs& saveas)
4372 vector<string> files;
4373 string current_folder = Glib::path_get_dirname (_path);
4374 string new_folder = legalize_for_path (saveas.new_name);
4375 string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4376 int64_t total_bytes = 0;
4380 int32_t internal_file_cnt = 0;
4382 vector<string> do_not_copy_extensions;
4383 do_not_copy_extensions.push_back (statefile_suffix);
4384 do_not_copy_extensions.push_back (pending_suffix);
4385 do_not_copy_extensions.push_back (backup_suffix);
4386 do_not_copy_extensions.push_back (temp_suffix);
4387 do_not_copy_extensions.push_back (history_suffix);
4389 /* get total size */
4391 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4393 /* need to clear this because
4394 * find_files_matching_filter() is cumulative
4399 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4401 all += files.size();
4403 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4405 g_stat ((*i).c_str(), &gsb);
4406 total_bytes += gsb.st_size;
4410 /* save old values so we can switch back if we are not switching to the new session */
4412 string old_path = _path;
4413 string old_name = _name;
4414 string old_snapshot = _current_snapshot_name;
4415 string old_sd = _session_dir->root_path();
4416 vector<string> old_search_path[DataType::num_types];
4417 string old_config_search_path[DataType::num_types];
4419 old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4420 old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4421 old_config_search_path[DataType::AUDIO] = config.get_audio_search_path ();
4422 old_config_search_path[DataType::MIDI] = config.get_midi_search_path ();
4424 /* switch session directory */
4426 (*_session_dir) = to_dir;
4428 /* create new tree */
4430 if (!_session_dir->create()) {
4431 saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4436 /* copy all relevant files. Find each location in session_dirs,
4437 * and copy files from there to target.
4440 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4442 /* need to clear this because
4443 * find_files_matching_filter() is cumulative
4448 const size_t prefix_len = (*sd).path.size();
4450 /* Work just on the files within this session dir */
4452 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4454 /* add dir separator to protect against collisions with
4455 * track names (e.g. track named "audiofiles" or
4459 static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
4460 static const std::string midifile_dir_string = string (midi_dir_name) + G_DIR_SEPARATOR;
4461 static const std::string analysis_dir_string = analysis_dir() + G_DIR_SEPARATOR;
4463 /* copy all the files. Handling is different for media files
4464 than others because of the *silly* subtree we have below the interchange
4465 folder. That really was a bad idea, but I'm not fixing it as part of
4466 implementing ::save_as().
4469 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4471 std::string from = *i;
4474 string filename = Glib::path_get_basename (from);
4475 std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
4476 if (filename == ".DS_STORE") {
4481 if (from.find (audiofile_dir_string) != string::npos) {
4483 /* audio file: only copy if asked */
4485 if (saveas.include_media && saveas.copy_media) {
4487 string to = make_new_media_path (*i, to_dir, new_folder);
4489 info << "media file copying from " << from << " to " << to << endmsg;
4491 if (!copy_file (from, to)) {
4492 throw Glib::FileError (Glib::FileError::IO_ERROR,
4493 string_compose(_("\ncopying \"%1\" failed !"), from));
4497 /* we found media files inside the session folder */
4499 internal_file_cnt++;
4501 } else if (from.find (midifile_dir_string) != string::npos) {
4503 /* midi file: always copy unless
4504 * creating an empty new session
4507 if (saveas.include_media) {
4509 string to = make_new_media_path (*i, to_dir, new_folder);
4511 info << "media file copying from " << from << " to " << to << endmsg;
4513 if (!copy_file (from, to)) {
4514 throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4518 /* we found media files inside the session folder */
4520 internal_file_cnt++;
4522 } else if (from.find (analysis_dir_string) != string::npos) {
4524 /* make sure analysis dir exists in
4525 * new session folder, but we're not
4526 * copying analysis files here, see
4530 (void) g_mkdir_with_parents (analysis_dir().c_str(), 775);
4535 /* normal non-media file. Don't copy state, history, etc.
4538 bool do_copy = true;
4540 for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
4541 if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
4542 /* end of filename matches extension, do not copy file */
4548 if (!saveas.copy_media && from.find (peakfile_suffix) != string::npos) {
4549 /* don't copy peakfiles if
4550 * we're not copying media
4556 string to = Glib::build_filename (to_dir, from.substr (prefix_len));
4558 info << "attempting to make directory/folder " << to << endmsg;
4560 if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
4561 throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
4564 info << "attempting to copy " << from << " to " << to << endmsg;
4566 if (!copy_file (from, to)) {
4567 throw Glib::FileError (Glib::FileError::IO_ERROR,
4568 string_compose(_("\ncopying \"%1\" failed !"), from));
4573 /* measure file size even if we're not going to copy so that our Progress
4574 signals are correct, since we included these do-not-copy files
4575 in the computation of the total size and file count.
4579 g_stat (from.c_str(), &gsb);
4580 copied += gsb.st_size;
4583 double fraction = (double) copied / total_bytes;
4585 bool keep_going = true;
4587 if (saveas.copy_media) {
4589 /* no need or expectation of this if
4590 * media is not being copied, because
4591 * it will be fast(ish).
4594 /* tell someone "X percent, file M of N"; M is one-based */
4596 boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
4604 throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
4610 /* copy optional folders, if any */
4612 string old = plugins_dir ();
4613 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4614 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4615 copy_files (old, newdir);
4618 old = externals_dir ();
4619 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4620 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4621 copy_files (old, newdir);
4624 old = automation_dir ();
4625 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4626 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4627 copy_files (old, newdir);
4630 if (saveas.include_media) {
4632 if (saveas.copy_media) {
4633 #ifndef PLATFORM_WINDOWS
4634 /* There are problems with analysis files on
4635 * Windows, because they used a colon in their
4636 * names as late as 4.0. Colons are not legal
4637 * under Windows even if NTFS allows them.
4639 * This is a tricky problem to solve so for
4640 * just don't copy these files. They will be
4641 * regenerated as-needed anyway, subject to the
4642 * existing issue that the filenames will be
4643 * rejected by Windows, which is a separate
4644 * problem (though related).
4647 /* only needed if we are copying media, since the
4648 * analysis data refers to media data
4651 old = analysis_dir ();
4652 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4653 string newdir = Glib::build_filename (to_dir, "analysis");
4654 copy_files (old, newdir);
4656 #endif /* PLATFORM_WINDOWS */
4662 set_snapshot_name (saveas.new_name);
4663 _name = saveas.new_name;
4665 if (saveas.include_media && !saveas.copy_media) {
4667 /* reset search paths of the new session (which we're pretending to be right now) to
4668 include the original session search path, so we can still find all audio.
4671 if (internal_file_cnt) {
4672 for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
4673 ensure_search_path_includes (*s, DataType::AUDIO);
4674 cerr << "be sure to include " << *s << " for audio" << endl;
4677 /* we do not do this for MIDI because we copy
4678 all MIDI files if saveas.include_media is
4684 bool was_dirty = dirty ();
4686 save_state ("", false, false, !saveas.include_media);
4687 save_default_options ();
4689 if (saveas.copy_media && saveas.copy_external) {
4690 if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
4691 throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
4695 saveas.final_session_folder_name = _path;
4697 store_recent_sessions (_name, _path);
4699 if (!saveas.switch_to) {
4701 /* switch back to the way things were */
4705 set_snapshot_name (old_snapshot);
4707 (*_session_dir) = old_sd;
4713 if (internal_file_cnt) {
4714 /* reset these to their original values */
4715 config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
4716 config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
4721 /* prune session dirs, and update disk space statistics
4726 session_dirs.clear ();
4727 session_dirs.push_back (sp);
4728 refresh_disk_space ();
4730 /* ensure that all existing tracks reset their current capture source paths
4732 reset_write_sources (true, true);
4734 /* the copying above was based on actually discovering files, not just iterating over the sources list.
4735 But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
4738 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4739 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4745 if (fs->within_session()) {
4746 string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
4747 fs->set_path (newpath);
4752 } catch (Glib::FileError& e) {
4754 saveas.failure_message = e.what();
4756 /* recursively remove all the directories */
4758 remove_directory (to_dir);
4766 saveas.failure_message = _("unknown reason");
4768 /* recursively remove all the directories */
4770 remove_directory (to_dir);