2 Copyright (C) 1999-2013 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "libardour-config.h"
30 #include <cstdio> /* snprintf(3) ... grrr */
42 #include <sys/param.h>
43 #include <sys/mount.h>
46 #ifdef HAVE_SYS_STATVFS_H
47 #include <sys/statvfs.h>
51 #include "pbd/gstdio_compat.h"
54 #include <glibmm/threads.h>
55 #include <glibmm/fileutils.h>
57 #include <boost/algorithm/string.hpp>
59 #include "midi++/mmc.h"
60 #include "midi++/port.h"
62 #include "evoral/SMF.hpp"
64 #include "pbd/boost_debug.h"
65 #include "pbd/basename.h"
66 #include "pbd/controllable_descriptor.h"
67 #include "pbd/debug.h"
68 #include "pbd/enumwriter.h"
69 #include "pbd/error.h"
70 #include "pbd/file_utils.h"
71 #include "pbd/pathexpand.h"
72 #include "pbd/pthread_utils.h"
73 #include "pbd/stacktrace.h"
74 #include "pbd/convert.h"
75 #include "pbd/localtime_r.h"
76 #include "pbd/unwind.h"
78 #include "ardour/amp.h"
79 #include "ardour/async_midi_port.h"
80 #include "ardour/audio_diskstream.h"
81 #include "ardour/audio_track.h"
82 #include "ardour/audioengine.h"
83 #include "ardour/audiofilesource.h"
84 #include "ardour/audioregion.h"
85 #include "ardour/automation_control.h"
86 #include "ardour/butler.h"
87 #include "ardour/control_protocol_manager.h"
88 #include "ardour/directory_names.h"
89 #include "ardour/filename_extensions.h"
90 #include "ardour/graph.h"
91 #include "ardour/location.h"
92 #include "ardour/midi_model.h"
93 #include "ardour/midi_patch_manager.h"
94 #include "ardour/midi_region.h"
95 #include "ardour/midi_scene_changer.h"
96 #include "ardour/midi_source.h"
97 #include "ardour/midi_track.h"
98 #include "ardour/pannable.h"
99 #include "ardour/playlist_factory.h"
100 #include "ardour/playlist_source.h"
101 #include "ardour/port.h"
102 #include "ardour/processor.h"
103 #include "ardour/profile.h"
104 #include "ardour/proxy_controllable.h"
105 #include "ardour/recent_sessions.h"
106 #include "ardour/region_factory.h"
107 #include "ardour/route_group.h"
108 #include "ardour/send.h"
109 #include "ardour/session.h"
110 #include "ardour/session_directory.h"
111 #include "ardour/session_metadata.h"
112 #include "ardour/session_playlists.h"
113 #include "ardour/session_state_utils.h"
114 #include "ardour/silentfilesource.h"
115 #include "ardour/sndfilesource.h"
116 #include "ardour/source_factory.h"
117 #include "ardour/speakers.h"
118 #include "ardour/template_utils.h"
119 #include "ardour/tempo.h"
120 #include "ardour/ticker.h"
121 #include "ardour/user_bundle.h"
123 #include "control_protocol/control_protocol.h"
125 #include "LuaBridge/LuaBridge.h"
131 using namespace ARDOUR;
134 #define DEBUG_UNDO_HISTORY(msg) DEBUG_TRACE (PBD::DEBUG::UndoHistory, string_compose ("%1: %2\n", __LINE__, msg));
137 Session::pre_engine_init (string fullpath)
139 if (fullpath.empty()) {
141 throw failed_constructor();
144 /* discover canonical fullpath */
146 _path = canonical_path(fullpath);
149 if (Profile->get_trx() ) {
150 // Waves TracksLive has a usecase of session replacement with a new one.
151 // We should check session state file (<session_name>.ardour) existance
152 // to determine if the session is new or not
154 string full_session_name = Glib::build_filename( fullpath, _name );
155 full_session_name += statefile_suffix;
157 _is_new = !Glib::file_test (full_session_name, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
159 _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
162 /* finish initialization that can't be done in a normal C++ constructor
166 timerclear (&last_mmc_step);
167 g_atomic_int_set (&processing_prohibited, 0);
168 g_atomic_int_set (&_record_status, Disabled);
169 g_atomic_int_set (&_playback_load, 100);
170 g_atomic_int_set (&_capture_load, 100);
172 _all_route_group->set_active (true, this);
173 interpolation.add_channel_to (0, 0);
175 if (config.get_use_video_sync()) {
176 waiting_for_sync_offset = true;
178 waiting_for_sync_offset = false;
181 last_rr_session_dir = session_dirs.begin();
183 set_history_depth (Config->get_history_depth());
185 /* default: assume simple stereo speaker configuration */
187 _speakers->setup_default_speakers (2);
189 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
190 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
191 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
192 add_controllable (_solo_cut_control);
194 /* These are all static "per-class" signals */
196 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
197 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
198 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
199 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
200 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
202 /* stop IO objects from doing stuff until we're ready for them */
204 Delivery::disable_panners ();
205 IO::disable_connecting ();
209 Session::post_engine_init ()
211 BootMessage (_("Set block size and sample rate"));
213 set_block_size (_engine.samples_per_cycle());
214 set_frame_rate (_engine.sample_rate());
216 BootMessage (_("Using configuration"));
218 _midi_ports = new MidiPortManager;
220 MIDISceneChanger* msc;
222 _scene_changer = msc = new MIDISceneChanger (*this);
223 msc->set_input_port (boost::dynamic_pointer_cast<MidiPort>(scene_input_port()));
224 msc->set_output_port (boost::dynamic_pointer_cast<MidiPort>(scene_output_port()));
226 boost::function<framecnt_t(void)> timer_func (boost::bind (&Session::audible_frame, this));
227 boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_input_port())->set_timer (timer_func);
229 setup_midi_machine_control ();
231 if (_butler->start_thread()) {
235 if (start_midi_thread ()) {
239 setup_click_sounds (0);
240 setup_midi_control ();
242 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
243 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
246 /* tempo map requires sample rate knowledge */
249 _tempo_map = new TempoMap (_current_frame_rate);
250 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
252 /* MidiClock requires a tempo map */
254 midi_clock = new MidiClockTicker ();
255 midi_clock->set_session (this);
257 /* crossfades require sample rate knowledge */
259 SndFileSource::setup_standard_crossfades (*this, frame_rate());
260 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
262 AudioDiskstream::allocate_working_buffers();
263 refresh_disk_space ();
265 /* we're finally ready to call set_state() ... all objects have
266 * been created, the engine is running.
270 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
274 // set_state() will call setup_raid_path(), but if it's a new session we need
275 // to call setup_raid_path() here.
276 setup_raid_path (_path);
281 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
282 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
284 Config->map_parameters (ff);
285 config.map_parameters (ft);
286 _butler->map_parameters ();
288 /* Reset all panners */
290 Delivery::reset_panners ();
292 /* this will cause the CPM to instantiate any protocols that are in use
293 * (or mandatory), which will pass it this Session, and then call
294 * set_state() on each instantiated protocol to match stored state.
297 ControlProtocolManager::instance().set_session (this);
299 /* This must be done after the ControlProtocolManager set_session above,
300 as it will set states for ports which the ControlProtocolManager creates.
303 // XXX set state of MIDI::Port's
304 // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
306 /* And this must be done after the MIDI::Manager::set_port_states as
307 * it will try to make connections whose details are loaded by set_port_states.
312 /* Let control protocols know that we are now all connected, so they
313 * could start talking to surfaces if they want to.
316 ControlProtocolManager::instance().midi_connectivity_established ();
318 if (_is_new && !no_auto_connect()) {
319 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
320 auto_connect_master_bus ();
323 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
325 /* update latencies */
327 initialize_latencies ();
329 _locations->added.connect_same_thread (*this, boost::bind (&Session::location_added, this, _1));
330 _locations->removed.connect_same_thread (*this, boost::bind (&Session::location_removed, this, _1));
331 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
333 } catch (AudioEngine::PortRegistrationFailure& err) {
334 /* handle this one in a different way than all others, so that its clear what happened */
335 error << err.what() << endmsg;
341 BootMessage (_("Reset Remote Controls"));
343 // send_full_time_code (0);
344 _engine.transport_locate (0);
346 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
347 send_immediate_mmc (MIDI::MachineControlCommand (Timecode::Time ()));
349 MIDI::Name::MidiPatchManager::instance().add_search_path (session_directory().midi_patch_path() );
352 /* initial program change will be delivered later; see ::config_changed() */
354 _state_of_the_state = Clean;
356 Port::set_connecting_blocked (false);
358 DirtyChanged (); /* EMIT SIGNAL */
362 } else if (state_was_pending) {
364 remove_pending_capture_state ();
365 state_was_pending = false;
368 /* Now, finally, we can fill the playback buffers */
370 BootMessage (_("Filling playback buffers"));
372 boost::shared_ptr<RouteList> rl = routes.reader();
373 for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
374 boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<Track> (*r);
375 if (trk && !trk->hidden()) {
376 trk->seek (_transport_frame, true);
384 Session::session_loaded ()
388 _state_of_the_state = Clean;
390 DirtyChanged (); /* EMIT SIGNAL */
394 } else if (state_was_pending) {
396 remove_pending_capture_state ();
397 state_was_pending = false;
400 /* Now, finally, we can fill the playback buffers */
402 BootMessage (_("Filling playback buffers"));
403 force_locate (_transport_frame, false);
407 Session::raid_path () const
409 Searchpath raid_search_path;
411 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
412 raid_search_path += (*i).path;
415 return raid_search_path.to_string ();
419 Session::setup_raid_path (string path)
428 session_dirs.clear ();
430 Searchpath search_path(path);
431 Searchpath sound_search_path;
432 Searchpath midi_search_path;
434 for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
436 sp.blocks = 0; // not needed
437 session_dirs.push_back (sp);
439 SessionDirectory sdir(sp.path);
441 sound_search_path += sdir.sound_path ();
442 midi_search_path += sdir.midi_path ();
445 // reset the round-robin soundfile path thingie
446 last_rr_session_dir = session_dirs.begin();
450 Session::path_is_within_session (const std::string& path)
452 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
453 if (PBD::path_is_within (i->path, path)) {
461 Session::ensure_subdirs ()
465 dir = session_directory().peak_path();
467 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
468 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
472 dir = session_directory().sound_path();
474 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
475 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
479 dir = session_directory().midi_path();
481 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
482 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
486 dir = session_directory().dead_path();
488 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
489 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
493 dir = session_directory().export_path();
495 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
496 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
500 dir = analysis_dir ();
502 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
503 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
507 dir = plugins_dir ();
509 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
510 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
514 dir = externals_dir ();
516 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
517 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
524 /** @param session_template directory containing session template, or empty.
525 * Caller must not hold process lock.
528 Session::create (const string& session_template, BusProfile* bus_profile)
530 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
531 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
535 if (ensure_subdirs ()) {
539 _writable = exists_and_writable (_path);
541 if (!session_template.empty()) {
542 string in_path = (ARDOUR::Profile->get_trx () ? session_template : session_template_dir_to_file (session_template));
544 FILE* in = g_fopen (in_path.c_str(), "rb");
547 /* no need to call legalize_for_path() since the string
548 * in session_template is already a legal path name
550 string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
552 FILE* out = g_fopen (out_path.c_str(), "wb");
556 stringstream new_session;
559 size_t charsRead = fread (buf, sizeof(char), 1024, in);
562 error << string_compose (_("Error reading session template file %1 (%2)"), in_path, strerror (errno)) << endmsg;
567 if (charsRead == 0) {
570 new_session.write (buf, charsRead);
574 string file_contents = new_session.str();
575 size_t writeSize = file_contents.length();
576 if (fwrite (file_contents.c_str(), sizeof(char), writeSize, out) != writeSize) {
577 error << string_compose (_("Error writing session template file %1 (%2)"), out_path, strerror (errno)) << endmsg;
585 if (!ARDOUR::Profile->get_trx()) {
586 /* Copy plugin state files from template to new session */
587 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
588 copy_recurse (template_plugins, plugins_dir ());
594 error << string_compose (_("Could not open %1 for writing session template"), out_path)
601 error << string_compose (_("Could not open session template %1 for reading"), in_path)
608 if (Profile->get_trx()) {
610 /* set initial start + end point : ARDOUR::Session::session_end_shift long.
611 Remember that this is a brand new session. Sessions
612 loaded from saved state will get this range from the saved state.
615 set_session_range_location (0, 0);
617 /* Initial loop location, from absolute zero, length 10 seconds */
619 Location* loc = new Location (*this, 0, 10.0 * _engine.sample_rate(), _("Loop"), Location::IsAutoLoop);
620 _locations->add (loc, true);
621 set_auto_loop_location (loc);
624 _state_of_the_state = Clean;
626 /* set up Master Out and Control Out if necessary */
631 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
633 // Waves Tracks: always create master bus for Tracks
634 if (ARDOUR::Profile->get_trx() || bus_profile->master_out_channels) {
635 boost::shared_ptr<Route> r (new Route (*this, _("Master"), Route::MasterOut, DataType::AUDIO));
639 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
640 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
643 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
644 r->input()->ensure_io (count, false, this);
645 r->output()->ensure_io (count, false, this);
651 /* prohibit auto-connect to master, because there isn't one */
652 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
656 add_routes (rl, false, false, false);
659 // Waves Tracks: Skip this. Always use autoconnection for Tracks
660 if (!ARDOUR::Profile->get_trx()) {
662 /* this allows the user to override settings with an environment variable.
665 if (no_auto_connect()) {
666 bus_profile->input_ac = AutoConnectOption (0);
667 bus_profile->output_ac = AutoConnectOption (0);
670 Config->set_input_auto_connect (bus_profile->input_ac);
671 Config->set_output_auto_connect (bus_profile->output_ac);
675 if (Config->get_use_monitor_bus() && bus_profile) {
676 add_monitor_section ();
683 Session::maybe_write_autosave()
685 if (dirty() && record_status() != Recording) {
686 save_state("", true);
691 Session::remove_pending_capture_state ()
693 std::string pending_state_file_path(_session_dir->root_path());
695 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
697 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
699 if (g_remove (pending_state_file_path.c_str()) != 0) {
700 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
701 pending_state_file_path, g_strerror (errno)) << endmsg;
705 /** Rename a state file.
706 * @param old_name Old snapshot name.
707 * @param new_name New snapshot name.
710 Session::rename_state (string old_name, string new_name)
712 if (old_name == _current_snapshot_name || old_name == _name) {
713 /* refuse to rename the current snapshot or the "main" one */
717 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
718 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
720 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
721 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
723 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
724 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
725 old_name, new_name, g_strerror(errno)) << endmsg;
729 /** Remove a state file.
730 * @param snapshot_name Snapshot name.
733 Session::remove_state (string snapshot_name)
735 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
736 // refuse to remove the current snapshot or the "main" one
740 std::string xml_path(_session_dir->root_path());
742 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
744 if (!create_backup_file (xml_path)) {
745 // don't remove it if a backup can't be made
746 // create_backup_file will log the error.
751 if (g_remove (xml_path.c_str()) != 0) {
752 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
753 xml_path, g_strerror (errno)) << endmsg;
757 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
759 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot, bool template_only)
762 std::string xml_path(_session_dir->root_path());
764 /* prevent concurrent saves from different threads */
766 Glib::Threads::Mutex::Lock lm (save_state_lock);
768 if (!_writable || (_state_of_the_state & CannotSave)) {
772 if (g_atomic_int_get(&_suspend_save)) {
776 _save_queued = false;
778 if (!_engine.connected ()) {
779 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
785 /* tell sources we're saving first, in case they write out to a new file
786 * which should be saved with the state rather than the old one */
787 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
789 i->second->session_saved();
790 } catch (Evoral::SMF::FileError& e) {
791 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
795 SessionSaveUnderway (); /* EMIT SIGNAL */
797 bool mark_as_clean = true;
799 if (!snapshot_name.empty() && !switch_to_snapshot) {
800 mark_as_clean = false;
804 mark_as_clean = false;
805 tree.set_root (&get_template());
807 tree.set_root (&get_state());
810 if (snapshot_name.empty()) {
811 snapshot_name = _current_snapshot_name;
812 } else if (switch_to_snapshot) {
813 set_snapshot_name (snapshot_name);
816 assert (!snapshot_name.empty());
820 /* proper save: use statefile_suffix (.ardour in English) */
822 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
824 /* make a backup copy of the old file */
826 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
827 // create_backup_file will log the error
833 /* pending save: use pending_suffix (.pending in English) */
834 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
837 std::string tmp_path(_session_dir->root_path());
838 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
840 cerr << "actually writing state to " << tmp_path << endl;
842 if (!tree.write (tmp_path)) {
843 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
844 if (g_remove (tmp_path.c_str()) != 0) {
845 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
846 tmp_path, g_strerror (errno)) << endmsg;
852 cerr << "renaming state to " << xml_path << endl;
854 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
855 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
856 tmp_path, xml_path, g_strerror(errno)) << endmsg;
857 if (g_remove (tmp_path.c_str()) != 0) {
858 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
859 tmp_path, g_strerror (errno)) << endmsg;
867 save_history (snapshot_name);
870 bool was_dirty = dirty();
872 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
875 DirtyChanged (); /* EMIT SIGNAL */
879 StateSaved (snapshot_name); /* EMIT SIGNAL */
886 Session::restore_state (string snapshot_name)
888 if (load_state (snapshot_name) == 0) {
889 set_state (*state_tree->root(), Stateful::loading_state_version);
896 Session::load_state (string snapshot_name)
901 state_was_pending = false;
903 /* check for leftover pending state from a crashed capture attempt */
905 std::string xmlpath(_session_dir->root_path());
906 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
908 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
910 /* there is pending state from a crashed capture attempt */
912 boost::optional<int> r = AskAboutPendingState();
913 if (r.get_value_or (1)) {
914 state_was_pending = true;
918 if (!state_was_pending) {
919 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
922 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
923 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
924 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
925 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
930 state_tree = new XMLTree;
934 _writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
936 if (!state_tree->read (xmlpath)) {
937 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
943 XMLNode& root (*state_tree->root());
945 if (root.name() != X_("Session")) {
946 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
952 const XMLProperty* prop;
954 if ((prop = root.property ("version")) == 0) {
955 /* no version implies very old version of Ardour */
956 Stateful::loading_state_version = 1000;
958 if (prop->value().find ('.') != string::npos) {
959 /* old school version format */
960 if (prop->value()[0] == '2') {
961 Stateful::loading_state_version = 2000;
963 Stateful::loading_state_version = 3000;
966 Stateful::loading_state_version = atoi (prop->value());
970 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
972 std::string backup_path(_session_dir->root_path());
973 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
974 backup_path = Glib::build_filename (backup_path, backup_filename);
976 // only create a backup for a given statefile version once
978 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
980 VersionMismatch (xmlpath, backup_path);
982 if (!copy_file (xmlpath, backup_path)) {;
988 save_snapshot_name (snapshot_name);
994 Session::load_options (const XMLNode& node)
996 LocaleGuard lg (X_("C"));
997 config.set_variables (node);
1002 Session::save_default_options ()
1004 return config.save_state();
1008 Session::get_state()
1014 Session::get_template()
1016 /* if we don't disable rec-enable, diskstreams
1017 will believe they need to store their capture
1018 sources in their state node.
1021 disable_record (false);
1023 return state(false);
1027 Session::state (bool full_state)
1029 XMLNode* node = new XMLNode("Session");
1033 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
1034 node->add_property("version", buf);
1036 /* store configuration settings */
1040 node->add_property ("name", _name);
1041 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
1042 node->add_property ("sample-rate", buf);
1044 if (session_dirs.size() > 1) {
1048 vector<space_and_path>::iterator i = session_dirs.begin();
1049 vector<space_and_path>::iterator next;
1051 ++i; /* skip the first one */
1055 while (i != session_dirs.end()) {
1059 if (next != session_dirs.end()) {
1060 p += G_SEARCHPATH_SEPARATOR;
1069 child = node->add_child ("Path");
1070 child->add_content (p);
1074 /* save the ID counter */
1076 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1077 node->add_property ("id-counter", buf);
1079 /* save the event ID counter */
1081 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1082 node->add_property ("event-counter", buf);
1084 /* various options */
1086 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
1087 if (!midi_port_nodes.empty()) {
1088 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
1089 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
1090 midi_port_stuff->add_child_nocopy (**n);
1092 node->add_child_nocopy (*midi_port_stuff);
1095 node->add_child_nocopy (config.get_variables ());
1097 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1099 child = node->add_child ("Sources");
1102 Glib::Threads::Mutex::Lock sl (source_lock);
1104 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1106 /* Don't save information about non-file Sources, or
1107 * about non-destructive file sources that are empty
1108 * and unused by any regions.
1111 boost::shared_ptr<FileSource> fs;
1113 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1115 if (!fs->destructive()) {
1116 if (fs->empty() && !fs->used()) {
1121 child->add_child_nocopy (siter->second->get_state());
1126 child = node->add_child ("Regions");
1129 Glib::Threads::Mutex::Lock rl (region_lock);
1130 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1131 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1132 boost::shared_ptr<Region> r = i->second;
1133 /* only store regions not attached to playlists */
1134 if (r->playlist() == 0) {
1135 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1136 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1138 child->add_child_nocopy (r->get_state ());
1143 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1145 if (!cassocs.empty()) {
1146 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1148 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1150 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1151 i->first->id().print (buf, sizeof (buf));
1152 can->add_property (X_("copy"), buf);
1153 i->second->id().print (buf, sizeof (buf));
1154 can->add_property (X_("original"), buf);
1155 ca->add_child_nocopy (*can);
1165 node->add_child_nocopy (_locations->get_state());
1168 Locations loc (*this);
1169 // for a template, just create a new Locations, populate it
1170 // with the default start and end, and get the state for that.
1171 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1172 range->set (max_framepos, 0);
1174 XMLNode& locations_state = loc.get_state();
1176 if (ARDOUR::Profile->get_trx() && _locations) {
1177 // For tracks we need stored the Auto Loop Range and all MIDI markers.
1178 for (Locations::LocationList::const_iterator i = _locations->list ().begin (); i != _locations->list ().end (); ++i) {
1179 if ((*i)->is_mark () || (*i)->is_auto_loop ()) {
1180 locations_state.add_child_nocopy ((*i)->get_state ());
1184 node->add_child_nocopy (locations_state);
1187 child = node->add_child ("Bundles");
1189 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1190 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1191 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1193 child->add_child_nocopy (b->get_state());
1198 child = node->add_child ("Routes");
1200 boost::shared_ptr<RouteList> r = routes.reader ();
1202 RoutePublicOrderSorter cmp;
1203 RouteList public_order (*r);
1204 public_order.sort (cmp);
1206 /* the sort should have put control outs first */
1209 assert (_monitor_out == public_order.front());
1212 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1213 if (!(*i)->is_auditioner()) {
1215 child->add_child_nocopy ((*i)->get_state());
1217 child->add_child_nocopy ((*i)->get_template());
1223 playlists->add_state (node, full_state);
1225 child = node->add_child ("RouteGroups");
1226 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1227 child->add_child_nocopy ((*i)->get_state());
1231 XMLNode* gain_child = node->add_child ("Click");
1232 gain_child->add_child_nocopy (_click_io->state (full_state));
1233 gain_child->add_child_nocopy (_click_gain->state (full_state));
1237 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1238 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1242 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1243 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1246 node->add_child_nocopy (_speakers->get_state());
1247 node->add_child_nocopy (_tempo_map->get_state());
1248 node->add_child_nocopy (get_control_protocol_state());
1251 node->add_child_copy (*_extra_xml);
1255 Glib::Threads::Mutex::Lock lm (lua_lock);
1258 luabridge::LuaRef savedstate ((*_lua_save)());
1259 saved = savedstate.cast<std::string>();
1261 lua.collect_garbage ();
1264 gchar* b64 = g_base64_encode ((const guchar*)saved.c_str (), saved.size ());
1265 std::string b64s (b64);
1268 XMLNode* script_node = new XMLNode (X_("Script"));
1269 script_node->add_property (X_("lua"), LUA_VERSION);
1270 script_node->add_content (b64s);
1271 node->add_child_nocopy (*script_node);
1278 Session::get_control_protocol_state ()
1280 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1281 return cpm.get_state();
1285 Session::set_state (const XMLNode& node, int version)
1289 const XMLProperty* prop;
1292 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1294 if (node.name() != X_("Session")) {
1295 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1299 if ((prop = node.property ("name")) != 0) {
1300 _name = prop->value ();
1303 if ((prop = node.property (X_("sample-rate"))) != 0) {
1305 _nominal_frame_rate = atoi (prop->value());
1307 if (_nominal_frame_rate != _current_frame_rate) {
1308 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1309 if (r.get_value_or (0)) {
1315 setup_raid_path(_session_dir->root_path());
1317 if ((prop = node.property (X_("id-counter"))) != 0) {
1319 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1320 ID::init_counter (x);
1322 /* old sessions used a timebased counter, so fake
1323 the startup ID counter based on a standard
1328 ID::init_counter (now);
1331 if ((prop = node.property (X_("event-counter"))) != 0) {
1332 Evoral::init_event_id_counter (atoi (prop->value()));
1336 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1337 _midi_ports->set_midi_port_states (child->children());
1340 IO::disable_connecting ();
1342 Stateful::save_extra_xml (node);
1344 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1345 load_options (*child);
1346 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1347 load_options (*child);
1349 error << _("Session: XML state has no options section") << endmsg;
1352 if (version >= 3000) {
1353 if ((child = find_named_node (node, "Metadata")) == 0) {
1354 warning << _("Session: XML state has no metadata section") << endmsg;
1355 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1360 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1361 _speakers->set_state (*child, version);
1364 if ((child = find_named_node (node, "Sources")) == 0) {
1365 error << _("Session: XML state has no sources section") << endmsg;
1367 } else if (load_sources (*child)) {
1371 if ((child = find_named_node (node, "TempoMap")) == 0) {
1372 error << _("Session: XML state has no Tempo Map section") << endmsg;
1374 } else if (_tempo_map->set_state (*child, version)) {
1378 if ((child = find_named_node (node, "Locations")) == 0) {
1379 error << _("Session: XML state has no locations section") << endmsg;
1381 } else if (_locations->set_state (*child, version)) {
1385 locations_changed ();
1387 if (_session_range_location) {
1388 AudioFileSource::set_header_position_offset (_session_range_location->start());
1391 if ((child = find_named_node (node, "Regions")) == 0) {
1392 error << _("Session: XML state has no Regions section") << endmsg;
1394 } else if (load_regions (*child)) {
1398 if ((child = find_named_node (node, "Playlists")) == 0) {
1399 error << _("Session: XML state has no playlists section") << endmsg;
1401 } else if (playlists->load (*this, *child)) {
1405 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1407 } else if (playlists->load_unused (*this, *child)) {
1411 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1412 if (load_compounds (*child)) {
1417 if (version >= 3000) {
1418 if ((child = find_named_node (node, "Bundles")) == 0) {
1419 warning << _("Session: XML state has no bundles section") << endmsg;
1422 /* We can't load Bundles yet as they need to be able
1423 to convert from port names to Port objects, which can't happen until
1425 _bundle_xml_node = new XMLNode (*child);
1429 if (version < 3000) {
1430 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1431 error << _("Session: XML state has no diskstreams section") << endmsg;
1433 } else if (load_diskstreams_2X (*child, version)) {
1438 if ((child = find_named_node (node, "Routes")) == 0) {
1439 error << _("Session: XML state has no routes section") << endmsg;
1441 } else if (load_routes (*child, version)) {
1445 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1446 _diskstreams_2X.clear ();
1448 if (version >= 3000) {
1450 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1451 error << _("Session: XML state has no route groups section") << endmsg;
1453 } else if (load_route_groups (*child, version)) {
1457 } else if (version < 3000) {
1459 if ((child = find_named_node (node, "EditGroups")) == 0) {
1460 error << _("Session: XML state has no edit groups section") << endmsg;
1462 } else if (load_route_groups (*child, version)) {
1466 if ((child = find_named_node (node, "MixGroups")) == 0) {
1467 error << _("Session: XML state has no mix groups section") << endmsg;
1469 } else if (load_route_groups (*child, version)) {
1474 if ((child = find_named_node (node, "Click")) == 0) {
1475 warning << _("Session: XML state has no click section") << endmsg;
1476 } else if (_click_io) {
1477 setup_click_state (&node);
1480 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1481 ControlProtocolManager::instance().set_state (*child, version);
1484 if ((child = find_named_node (node, "Script"))) {
1485 for (XMLNodeList::const_iterator n = child->children ().begin (); n != child->children ().end (); ++n) {
1486 if (!(*n)->is_content ()) { continue; }
1488 guchar* buf = g_base64_decode ((*n)->content ().c_str (), &size);
1490 Glib::Threads::Mutex::Lock lm (lua_lock);
1491 (*_lua_load)(std::string ((const char*)buf, size));
1492 } catch (luabridge::LuaException const& e) {
1493 cerr << "LuaException:" << e.what () << endl;
1499 update_route_record_state ();
1501 /* here beginneth the second phase ... */
1502 set_snapshot_name (_current_snapshot_name);
1504 StateReady (); /* EMIT SIGNAL */
1517 Session::load_routes (const XMLNode& node, int version)
1520 XMLNodeConstIterator niter;
1521 RouteList new_routes;
1523 nlist = node.children();
1527 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1529 boost::shared_ptr<Route> route;
1530 if (version < 3000) {
1531 route = XMLRouteFactory_2X (**niter, version);
1533 route = XMLRouteFactory (**niter, version);
1537 error << _("Session: cannot create Route from XML description.") << endmsg;
1541 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1543 new_routes.push_back (route);
1546 BootMessage (_("Tracks/busses loaded; Adding to Session"));
1548 add_routes (new_routes, false, false, false);
1550 BootMessage (_("Finished adding tracks/busses"));
1555 boost::shared_ptr<Route>
1556 Session::XMLRouteFactory (const XMLNode& node, int version)
1558 boost::shared_ptr<Route> ret;
1560 if (node.name() != "Route") {
1564 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1566 DataType type = DataType::AUDIO;
1567 const XMLProperty* prop = node.property("default-type");
1570 type = DataType (prop->value());
1573 assert (type != DataType::NIL);
1577 boost::shared_ptr<Track> track;
1579 if (type == DataType::AUDIO) {
1580 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1582 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1585 if (track->init()) {
1589 if (track->set_state (node, version)) {
1593 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1594 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1599 enum Route::Flag flags = Route::Flag(0);
1600 const XMLProperty* prop = node.property("flags");
1602 flags = Route::Flag (string_2_enum (prop->value(), flags));
1605 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1607 if (r->init () == 0 && r->set_state (node, version) == 0) {
1608 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1609 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1618 boost::shared_ptr<Route>
1619 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1621 boost::shared_ptr<Route> ret;
1623 if (node.name() != "Route") {
1627 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1629 ds_prop = node.property (X_("diskstream"));
1632 DataType type = DataType::AUDIO;
1633 const XMLProperty* prop = node.property("default-type");
1636 type = DataType (prop->value());
1639 assert (type != DataType::NIL);
1643 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1644 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1648 if (i == _diskstreams_2X.end()) {
1649 error << _("Could not find diskstream for route") << endmsg;
1650 return boost::shared_ptr<Route> ();
1653 boost::shared_ptr<Track> track;
1655 if (type == DataType::AUDIO) {
1656 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1658 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1661 if (track->init()) {
1665 if (track->set_state (node, version)) {
1669 track->set_diskstream (*i);
1671 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1672 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1677 enum Route::Flag flags = Route::Flag(0);
1678 const XMLProperty* prop = node.property("flags");
1680 flags = Route::Flag (string_2_enum (prop->value(), flags));
1683 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1685 if (r->init () == 0 && r->set_state (node, version) == 0) {
1686 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1687 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1697 Session::load_regions (const XMLNode& node)
1700 XMLNodeConstIterator niter;
1701 boost::shared_ptr<Region> region;
1703 nlist = node.children();
1707 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1708 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1709 error << _("Session: cannot create Region from XML description.");
1710 const XMLProperty *name = (**niter).property("name");
1713 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1724 Session::load_compounds (const XMLNode& node)
1726 XMLNodeList calist = node.children();
1727 XMLNodeConstIterator caiter;
1728 XMLProperty *caprop;
1730 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1731 XMLNode* ca = *caiter;
1735 if ((caprop = ca->property (X_("original"))) == 0) {
1738 orig_id = caprop->value();
1740 if ((caprop = ca->property (X_("copy"))) == 0) {
1743 copy_id = caprop->value();
1745 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1746 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1748 if (!orig || !copy) {
1749 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1755 RegionFactory::add_compound_association (orig, copy);
1762 Session::load_nested_sources (const XMLNode& node)
1765 XMLNodeConstIterator niter;
1767 nlist = node.children();
1769 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1770 if ((*niter)->name() == "Source") {
1772 /* it may already exist, so don't recreate it unnecessarily
1775 XMLProperty* prop = (*niter)->property (X_("id"));
1777 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1781 ID source_id (prop->value());
1783 if (!source_by_id (source_id)) {
1786 SourceFactory::create (*this, **niter, true);
1788 catch (failed_constructor& err) {
1789 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1796 boost::shared_ptr<Region>
1797 Session::XMLRegionFactory (const XMLNode& node, bool full)
1799 const XMLProperty* type = node.property("type");
1803 const XMLNodeList& nlist = node.children();
1805 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1806 XMLNode *child = (*niter);
1807 if (child->name() == "NestedSource") {
1808 load_nested_sources (*child);
1812 if (!type || type->value() == "audio") {
1813 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1814 } else if (type->value() == "midi") {
1815 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1818 } catch (failed_constructor& err) {
1819 return boost::shared_ptr<Region> ();
1822 return boost::shared_ptr<Region> ();
1825 boost::shared_ptr<AudioRegion>
1826 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1828 const XMLProperty* prop;
1829 boost::shared_ptr<Source> source;
1830 boost::shared_ptr<AudioSource> as;
1832 SourceList master_sources;
1833 uint32_t nchans = 1;
1836 if (node.name() != X_("Region")) {
1837 return boost::shared_ptr<AudioRegion>();
1840 if ((prop = node.property (X_("channels"))) != 0) {
1841 nchans = atoi (prop->value().c_str());
1844 if ((prop = node.property ("name")) == 0) {
1845 cerr << "no name for this region\n";
1849 if ((prop = node.property (X_("source-0"))) == 0) {
1850 if ((prop = node.property ("source")) == 0) {
1851 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1852 return boost::shared_ptr<AudioRegion>();
1856 PBD::ID s_id (prop->value());
1858 if ((source = source_by_id (s_id)) == 0) {
1859 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1860 return boost::shared_ptr<AudioRegion>();
1863 as = boost::dynamic_pointer_cast<AudioSource>(source);
1865 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1866 return boost::shared_ptr<AudioRegion>();
1869 sources.push_back (as);
1871 /* pickup other channels */
1873 for (uint32_t n=1; n < nchans; ++n) {
1874 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1875 if ((prop = node.property (buf)) != 0) {
1877 PBD::ID id2 (prop->value());
1879 if ((source = source_by_id (id2)) == 0) {
1880 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1881 return boost::shared_ptr<AudioRegion>();
1884 as = boost::dynamic_pointer_cast<AudioSource>(source);
1886 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1887 return boost::shared_ptr<AudioRegion>();
1889 sources.push_back (as);
1893 for (uint32_t n = 0; n < nchans; ++n) {
1894 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1895 if ((prop = node.property (buf)) != 0) {
1897 PBD::ID id2 (prop->value());
1899 if ((source = source_by_id (id2)) == 0) {
1900 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1901 return boost::shared_ptr<AudioRegion>();
1904 as = boost::dynamic_pointer_cast<AudioSource>(source);
1906 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1907 return boost::shared_ptr<AudioRegion>();
1909 master_sources.push_back (as);
1914 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1916 /* a final detail: this is the one and only place that we know how long missing files are */
1918 if (region->whole_file()) {
1919 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1920 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1922 sfp->set_length (region->length());
1927 if (!master_sources.empty()) {
1928 if (master_sources.size() != nchans) {
1929 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1931 region->set_master_sources (master_sources);
1939 catch (failed_constructor& err) {
1940 return boost::shared_ptr<AudioRegion>();
1944 boost::shared_ptr<MidiRegion>
1945 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1947 const XMLProperty* prop;
1948 boost::shared_ptr<Source> source;
1949 boost::shared_ptr<MidiSource> ms;
1952 if (node.name() != X_("Region")) {
1953 return boost::shared_ptr<MidiRegion>();
1956 if ((prop = node.property ("name")) == 0) {
1957 cerr << "no name for this region\n";
1961 if ((prop = node.property (X_("source-0"))) == 0) {
1962 if ((prop = node.property ("source")) == 0) {
1963 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1964 return boost::shared_ptr<MidiRegion>();
1968 PBD::ID s_id (prop->value());
1970 if ((source = source_by_id (s_id)) == 0) {
1971 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1972 return boost::shared_ptr<MidiRegion>();
1975 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1977 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1978 return boost::shared_ptr<MidiRegion>();
1981 sources.push_back (ms);
1984 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1985 /* a final detail: this is the one and only place that we know how long missing files are */
1987 if (region->whole_file()) {
1988 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1989 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1991 sfp->set_length (region->length());
1999 catch (failed_constructor& err) {
2000 return boost::shared_ptr<MidiRegion>();
2005 Session::get_sources_as_xml ()
2008 XMLNode* node = new XMLNode (X_("Sources"));
2009 Glib::Threads::Mutex::Lock lm (source_lock);
2011 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2012 node->add_child_nocopy (i->second->get_state());
2019 Session::reset_write_sources (bool mark_write_complete, bool force)
2021 boost::shared_ptr<RouteList> rl = routes.reader();
2022 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
2023 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
2025 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
2026 tr->reset_write_sources(mark_write_complete, force);
2027 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
2033 Session::load_sources (const XMLNode& node)
2036 XMLNodeConstIterator niter;
2037 boost::shared_ptr<Source> source; /* don't need this but it stops some
2038 * versions of gcc complaining about
2039 * discarded return values.
2042 nlist = node.children();
2046 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2049 if ((source = XMLSourceFactory (**niter)) == 0) {
2050 error << _("Session: cannot create Source from XML description.") << endmsg;
2053 } catch (MissingSource& err) {
2057 if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
2058 error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
2059 PROGRAM_NAME) << endmsg;
2063 if (!no_questions_about_missing_files) {
2064 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
2069 switch (user_choice) {
2071 /* user added a new search location, so try again */
2076 /* user asked to quit the entire session load
2081 no_questions_about_missing_files = true;
2085 no_questions_about_missing_files = true;
2092 case DataType::AUDIO:
2093 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
2096 case DataType::MIDI:
2097 /* The MIDI file is actually missing so
2098 * just create a new one in the same
2099 * location. Do not announce its
2103 if (!Glib::path_is_absolute (err.path)) {
2104 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
2106 /* this should be an unrecoverable error: we would be creating a MIDI file outside
2111 /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
2112 source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
2113 /* reset ID to match the missing one */
2114 source->set_id (**niter);
2115 /* Now we can announce it */
2116 SourceFactory::SourceCreated (source);
2127 boost::shared_ptr<Source>
2128 Session::XMLSourceFactory (const XMLNode& node)
2130 if (node.name() != "Source") {
2131 return boost::shared_ptr<Source>();
2135 /* note: do peak building in another thread when loading session state */
2136 return SourceFactory::create (*this, node, true);
2139 catch (failed_constructor& err) {
2140 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
2141 return boost::shared_ptr<Source>();
2146 Session::save_template (string template_name, bool replace_existing)
2148 if ((_state_of_the_state & CannotSave) || template_name.empty ()) {
2152 bool absolute_path = Glib::path_is_absolute (template_name);
2154 /* directory to put the template in */
2155 std::string template_dir_path;
2157 if (!absolute_path) {
2158 std::string user_template_dir(user_template_directory());
2160 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2161 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2162 user_template_dir, g_strerror (errno)) << endmsg;
2166 template_dir_path = Glib::build_filename (user_template_dir, template_name);
2168 template_dir_path = template_name;
2171 if (!ARDOUR::Profile->get_trx()) {
2172 if (!replace_existing && Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2173 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2174 template_dir_path) << endmsg;
2178 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2179 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2180 template_dir_path, g_strerror (errno)) << endmsg;
2186 std::string template_file_path;
2188 if (ARDOUR::Profile->get_trx()) {
2189 template_file_path = template_name;
2191 if (absolute_path) {
2192 template_file_path = Glib::build_filename (template_dir_path, Glib::path_get_basename (template_dir_path) + template_suffix);
2194 template_file_path = Glib::build_filename (template_dir_path, template_name + template_suffix);
2198 SessionSaveUnderway (); /* EMIT SIGNAL */
2203 PBD::Unwinder<std::string> uw (_template_state_dir, template_dir_path);
2204 tree.set_root (&get_template());
2207 if (!tree.write (template_file_path)) {
2208 error << _("template not saved") << endmsg;
2212 store_recent_templates (template_file_path);
2218 Session::refresh_disk_space ()
2220 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2222 Glib::Threads::Mutex::Lock lm (space_lock);
2224 /* get freespace on every FS that is part of the session path */
2226 _total_free_4k_blocks = 0;
2227 _total_free_4k_blocks_uncertain = false;
2229 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2231 struct statfs statfsbuf;
2232 statfs (i->path.c_str(), &statfsbuf);
2234 double const scale = statfsbuf.f_bsize / 4096.0;
2236 /* See if this filesystem is read-only */
2237 struct statvfs statvfsbuf;
2238 statvfs (i->path.c_str(), &statvfsbuf);
2240 /* f_bavail can be 0 if it is undefined for whatever
2241 filesystem we are looking at; Samba shares mounted
2242 via GVFS are an example of this.
2244 if (statfsbuf.f_bavail == 0) {
2245 /* block count unknown */
2247 i->blocks_unknown = true;
2248 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2249 /* read-only filesystem */
2251 i->blocks_unknown = false;
2253 /* read/write filesystem with known space */
2254 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2255 i->blocks_unknown = false;
2258 _total_free_4k_blocks += i->blocks;
2259 if (i->blocks_unknown) {
2260 _total_free_4k_blocks_uncertain = true;
2263 #elif defined PLATFORM_WINDOWS
2264 vector<string> scanned_volumes;
2265 vector<string>::iterator j;
2266 vector<space_and_path>::iterator i;
2267 DWORD nSectorsPerCluster, nBytesPerSector,
2268 nFreeClusters, nTotalClusters;
2272 _total_free_4k_blocks = 0;
2274 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2275 strncpy (disk_drive, (*i).path.c_str(), 3);
2279 volume_found = false;
2280 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2282 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2283 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2284 i->blocks = (uint32_t)(nFreeBytes / 4096);
2286 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2287 if (0 == j->compare(disk_drive)) {
2288 volume_found = true;
2293 if (!volume_found) {
2294 scanned_volumes.push_back(disk_drive);
2295 _total_free_4k_blocks += i->blocks;
2300 if (0 == _total_free_4k_blocks) {
2301 strncpy (disk_drive, path().c_str(), 3);
2304 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2306 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2307 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2308 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2315 Session::get_best_session_directory_for_new_audio ()
2317 vector<space_and_path>::iterator i;
2318 string result = _session_dir->root_path();
2320 /* handle common case without system calls */
2322 if (session_dirs.size() == 1) {
2326 /* OK, here's the algorithm we're following here:
2328 We want to select which directory to use for
2329 the next file source to be created. Ideally,
2330 we'd like to use a round-robin process so as to
2331 get maximum performance benefits from splitting
2332 the files across multiple disks.
2334 However, in situations without much diskspace, an
2335 RR approach may end up filling up a filesystem
2336 with new files while others still have space.
2337 Its therefore important to pay some attention to
2338 the freespace in the filesystem holding each
2339 directory as well. However, if we did that by
2340 itself, we'd keep creating new files in the file
2341 system with the most space until it was as full
2342 as all others, thus negating any performance
2343 benefits of this RAID-1 like approach.
2345 So, we use a user-configurable space threshold. If
2346 there are at least 2 filesystems with more than this
2347 much space available, we use RR selection between them.
2348 If not, then we pick the filesystem with the most space.
2350 This gets a good balance between the two
2354 refresh_disk_space ();
2356 int free_enough = 0;
2358 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2359 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2364 if (free_enough >= 2) {
2365 /* use RR selection process, ensuring that the one
2369 i = last_rr_session_dir;
2372 if (++i == session_dirs.end()) {
2373 i = session_dirs.begin();
2376 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2377 SessionDirectory sdir(i->path);
2378 if (sdir.create ()) {
2380 last_rr_session_dir = i;
2385 } while (i != last_rr_session_dir);
2389 /* pick FS with the most freespace (and that
2390 seems to actually work ...)
2393 vector<space_and_path> sorted;
2394 space_and_path_ascending_cmp cmp;
2396 sorted = session_dirs;
2397 sort (sorted.begin(), sorted.end(), cmp);
2399 for (i = sorted.begin(); i != sorted.end(); ++i) {
2400 SessionDirectory sdir(i->path);
2401 if (sdir.create ()) {
2403 last_rr_session_dir = i;
2413 Session::automation_dir () const
2415 return Glib::build_filename (_path, automation_dir_name);
2419 Session::analysis_dir () const
2421 return Glib::build_filename (_path, analysis_dir_name);
2425 Session::plugins_dir () const
2427 return Glib::build_filename (_path, plugins_dir_name);
2431 Session::externals_dir () const
2433 return Glib::build_filename (_path, externals_dir_name);
2437 Session::load_bundles (XMLNode const & node)
2439 XMLNodeList nlist = node.children();
2440 XMLNodeConstIterator niter;
2444 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2445 if ((*niter)->name() == "InputBundle") {
2446 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2447 } else if ((*niter)->name() == "OutputBundle") {
2448 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2450 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2459 Session::load_route_groups (const XMLNode& node, int version)
2461 XMLNodeList nlist = node.children();
2462 XMLNodeConstIterator niter;
2466 if (version >= 3000) {
2468 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2469 if ((*niter)->name() == "RouteGroup") {
2470 RouteGroup* rg = new RouteGroup (*this, "");
2471 add_route_group (rg);
2472 rg->set_state (**niter, version);
2476 } else if (version < 3000) {
2478 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2479 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2480 RouteGroup* rg = new RouteGroup (*this, "");
2481 add_route_group (rg);
2482 rg->set_state (**niter, version);
2491 state_file_filter (const string &str, void* /*arg*/)
2493 return (str.length() > strlen(statefile_suffix) &&
2494 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2498 remove_end(string state)
2500 string statename(state);
2502 string::size_type start,end;
2503 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2504 statename = statename.substr (start+1);
2507 if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2508 end = statename.length();
2511 return string(statename.substr (0, end));
2515 Session::possible_states (string path)
2517 vector<string> states;
2518 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2520 transform(states.begin(), states.end(), states.begin(), remove_end);
2522 sort (states.begin(), states.end());
2528 Session::possible_states () const
2530 return possible_states(_path);
2534 Session::add_route_group (RouteGroup* g)
2536 _route_groups.push_back (g);
2537 route_group_added (g); /* EMIT SIGNAL */
2539 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2540 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2541 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2547 Session::remove_route_group (RouteGroup& rg)
2549 list<RouteGroup*>::iterator i;
2551 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2552 _route_groups.erase (i);
2555 route_group_removed (); /* EMIT SIGNAL */
2559 /** Set a new order for our route groups, without adding or removing any.
2560 * @param groups Route group list in the new order.
2563 Session::reorder_route_groups (list<RouteGroup*> groups)
2565 _route_groups = groups;
2567 route_groups_reordered (); /* EMIT SIGNAL */
2573 Session::route_group_by_name (string name)
2575 list<RouteGroup *>::iterator i;
2577 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2578 if ((*i)->name() == name) {
2586 Session::all_route_group() const
2588 return *_all_route_group;
2592 Session::add_commands (vector<Command*> const & cmds)
2594 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2600 Session::add_command (Command* const cmd)
2602 assert (_current_trans);
2603 DEBUG_UNDO_HISTORY (
2604 string_compose ("Current Undo Transaction %1, adding command: %2",
2605 _current_trans->name (),
2607 _current_trans->add_command (cmd);
2610 Session::begin_reversible_command (const string& name)
2612 begin_reversible_command (g_quark_from_string (name.c_str ()));
2615 /** Begin a reversible command using a GQuark to identify it.
2616 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2617 * but there must be as many begin...()s as there are commit...()s.
2620 Session::begin_reversible_command (GQuark q)
2622 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2623 to hold all the commands that are committed. This keeps the order of
2624 commands correct in the history.
2627 if (_current_trans == 0) {
2628 DEBUG_UNDO_HISTORY (string_compose (
2629 "Begin Reversible Command, new transaction: %1", g_quark_to_string (q)));
2631 /* start a new transaction */
2632 assert (_current_trans_quarks.empty ());
2633 _current_trans = new UndoTransaction();
2634 _current_trans->set_name (g_quark_to_string (q));
2636 DEBUG_UNDO_HISTORY (
2637 string_compose ("Begin Reversible Command, current transaction: %1",
2638 _current_trans->name ()));
2641 _current_trans_quarks.push_front (q);
2645 Session::abort_reversible_command ()
2647 if (_current_trans != 0) {
2648 DEBUG_UNDO_HISTORY (
2649 string_compose ("Abort Reversible Command: %1", _current_trans->name ()));
2650 _current_trans->clear();
2651 delete _current_trans;
2653 _current_trans_quarks.clear();
2658 Session::commit_reversible_command (Command *cmd)
2660 assert (_current_trans);
2661 assert (!_current_trans_quarks.empty ());
2666 DEBUG_UNDO_HISTORY (
2667 string_compose ("Current Undo Transaction %1, adding command: %2",
2668 _current_trans->name (),
2670 _current_trans->add_command (cmd);
2673 DEBUG_UNDO_HISTORY (
2674 string_compose ("Commit Reversible Command, current transaction: %1",
2675 _current_trans->name ()));
2677 _current_trans_quarks.pop_front ();
2679 if (!_current_trans_quarks.empty ()) {
2680 DEBUG_UNDO_HISTORY (
2681 string_compose ("Commit Reversible Command, transaction is not "
2682 "top-level, current transaction: %1",
2683 _current_trans->name ()));
2684 /* the transaction we're committing is not the top-level one */
2688 if (_current_trans->empty()) {
2689 /* no commands were added to the transaction, so just get rid of it */
2690 DEBUG_UNDO_HISTORY (
2691 string_compose ("Commit Reversible Command, No commands were "
2692 "added to current transaction: %1",
2693 _current_trans->name ()));
2694 delete _current_trans;
2699 gettimeofday (&now, 0);
2700 _current_trans->set_timestamp (now);
2702 _history.add (_current_trans);
2707 accept_all_audio_files (const string& path, void* /*arg*/)
2709 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2713 if (!AudioFileSource::safe_audio_file_extension (path)) {
2721 accept_all_midi_files (const string& path, void* /*arg*/)
2723 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2727 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2728 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2729 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2733 accept_all_state_files (const string& path, void* /*arg*/)
2735 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2739 std::string const statefile_ext (statefile_suffix);
2740 if (path.length() >= statefile_ext.length()) {
2741 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2748 Session::find_all_sources (string path, set<string>& result)
2753 if (!tree.read (path)) {
2757 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2762 XMLNodeConstIterator niter;
2764 nlist = node->children();
2768 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2772 if ((prop = (*niter)->property (X_("type"))) == 0) {
2776 DataType type (prop->value());
2778 if ((prop = (*niter)->property (X_("name"))) == 0) {
2782 if (Glib::path_is_absolute (prop->value())) {
2783 /* external file, ignore */
2791 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2792 result.insert (found_path);
2800 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2802 vector<string> state_files;
2804 string this_snapshot_path;
2810 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2811 ripped = ripped.substr (0, ripped.length() - 1);
2814 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2816 if (state_files.empty()) {
2821 this_snapshot_path = _path;
2822 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2823 this_snapshot_path += statefile_suffix;
2825 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2827 if (exclude_this_snapshot && *i == this_snapshot_path) {
2831 if (find_all_sources (*i, result) < 0) {
2839 struct RegionCounter {
2840 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2841 AudioSourceList::iterator iter;
2842 boost::shared_ptr<Region> region;
2845 RegionCounter() : count (0) {}
2849 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2851 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2852 return r.get_value_or (1);
2856 Session::cleanup_regions ()
2858 bool removed = false;
2859 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2861 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2863 uint32_t used = playlists->region_use_count (i->second);
2865 if (used == 0 && !i->second->automatic ()) {
2866 boost::weak_ptr<Region> w = i->second;
2869 RegionFactory::map_remove (w);
2876 // re-check to remove parent references of compound regions
2877 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2878 if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2882 assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2883 if (0 == playlists->region_use_count (i->second)) {
2884 boost::weak_ptr<Region> w = i->second;
2886 RegionFactory::map_remove (w);
2893 /* dump the history list */
2900 Session::can_cleanup_peakfiles () const
2902 if (deletion_in_progress()) {
2905 if (!_writable || (_state_of_the_state & CannotSave)) {
2906 warning << _("Cannot cleanup peak-files for read-only session.") << endmsg;
2909 if (record_status() == Recording) {
2910 error << _("Cannot cleanup peak-files while recording") << endmsg;
2917 Session::cleanup_peakfiles ()
2919 Glib::Threads::Mutex::Lock lm (peak_cleanup_lock, Glib::Threads::TRY_LOCK);
2924 assert (can_cleanup_peakfiles ());
2925 assert (!peaks_cleanup_in_progres());
2927 _state_of_the_state = StateOfTheState (_state_of_the_state | PeakCleanup);
2929 int timeout = 5000; // 5 seconds
2930 while (!SourceFactory::files_with_peaks.empty()) {
2931 Glib::usleep (1000);
2932 if (--timeout < 0) {
2933 warning << _("Timeout waiting for peak-file creation to terminate before cleanup, please try again later.") << endmsg;
2934 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
2939 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2940 boost::shared_ptr<AudioSource> as;
2941 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
2942 as->close_peakfile();
2946 PBD::clear_directory (session_directory().peak_path());
2948 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
2950 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2951 boost::shared_ptr<AudioSource> as;
2952 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
2953 SourceFactory::setup_peakfile(as, true);
2960 Session::cleanup_sources (CleanupReport& rep)
2962 // FIXME: needs adaptation to midi
2964 vector<boost::shared_ptr<Source> > dead_sources;
2967 vector<string> candidates;
2968 vector<string> unused;
2969 set<string> all_sources;
2978 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2980 /* this is mostly for windows which doesn't allow file
2981 * renaming if the file is in use. But we don't special
2982 * case it because we need to know if this causes
2983 * problems, and the easiest way to notice that is to
2984 * keep it in place for all platforms.
2987 request_stop (false);
2989 _butler->wait_until_finished ();
2991 /* consider deleting all unused playlists */
2993 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2998 /* sync the "all regions" property of each playlist with its current state
3001 playlists->sync_all_regions_with_regions ();
3003 /* find all un-used sources */
3008 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3010 SourceMap::iterator tmp;
3015 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
3019 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
3020 dead_sources.push_back (i->second);
3021 i->second->drop_references ();
3027 /* build a list of all the possible audio directories for the session */
3029 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3030 SessionDirectory sdir ((*i).path);
3031 asp += sdir.sound_path();
3033 audio_path += asp.to_string();
3036 /* build a list of all the possible midi directories for the session */
3038 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3039 SessionDirectory sdir ((*i).path);
3040 msp += sdir.midi_path();
3042 midi_path += msp.to_string();
3044 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
3045 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
3047 /* find all sources, but don't use this snapshot because the
3048 state file on disk still references sources we may have already
3052 find_all_sources_across_snapshots (all_sources, true);
3054 /* add our current source list
3057 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3058 boost::shared_ptr<FileSource> fs;
3059 SourceMap::iterator tmp = i;
3062 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
3064 /* this is mostly for windows which doesn't allow file
3065 * renaming if the file is in use. But we don't special
3066 * case it because we need to know if this causes
3067 * problems, and the easiest way to notice that is to
3068 * keep it in place for all platforms.
3073 if (!fs->is_stub()) {
3075 if (playlists->source_use_count (fs) != 0) {
3076 all_sources.insert (fs->path());
3079 /* we might not remove this source from disk, because it may be used
3080 by other snapshots, but its not being used in this version
3081 so lets get rid of it now, along with any representative regions
3085 RegionFactory::remove_regions_using_source (i->second);
3087 // also remove source from all_sources
3089 for (set<string>::iterator j = all_sources.begin(); j != all_sources.end(); ++j) {
3090 spath = Glib::path_get_basename (*j);
3091 if (spath == i->second->name()) {
3092 all_sources.erase (j);
3105 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
3110 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
3112 tmppath1 = canonical_path (spath);
3113 tmppath2 = canonical_path ((*i));
3115 if (tmppath1 == tmppath2) {
3122 unused.push_back (spath);
3126 /* now try to move all unused files into the "dead" directory(ies) */
3128 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
3133 /* don't move the file across filesystems, just
3134 stick it in the `dead_dir_name' directory
3135 on whichever filesystem it was already on.
3138 if ((*x).find ("/sounds/") != string::npos) {
3140 /* old school, go up 1 level */
3142 newpath = Glib::path_get_dirname (*x); // "sounds"
3143 newpath = Glib::path_get_dirname (newpath); // "session-name"
3147 /* new school, go up 4 levels */
3149 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
3150 newpath = Glib::path_get_dirname (newpath); // "session-name"
3151 newpath = Glib::path_get_dirname (newpath); // "interchange"
3152 newpath = Glib::path_get_dirname (newpath); // "session-dir"
3155 newpath = Glib::build_filename (newpath, dead_dir_name);
3157 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
3158 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
3162 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
3164 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
3166 /* the new path already exists, try versioning */
3168 char buf[PATH_MAX+1];
3172 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3175 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
3176 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3180 if (version == 999) {
3181 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3185 newpath = newpath_v;
3190 /* it doesn't exist, or we can't read it or something */
3194 g_stat ((*x).c_str(), &statbuf);
3196 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3197 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
3198 (*x), newpath, strerror (errno))
3203 /* see if there an easy to find peakfile for this file, and remove it.
3206 string base = Glib::path_get_basename (*x);
3207 base += "%A"; /* this is what we add for the channel suffix of all native files,
3208 or for the first channel of embedded files. it will miss
3209 some peakfiles for other channels
3211 string peakpath = construct_peak_filepath (base);
3213 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
3214 if (::g_unlink (peakpath.c_str()) != 0) {
3215 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3216 peakpath, _path, strerror (errno))
3218 /* try to back out */
3219 ::rename (newpath.c_str(), _path.c_str());
3224 rep.paths.push_back (*x);
3225 rep.space += statbuf.st_size;
3228 /* dump the history list */
3232 /* save state so we don't end up a session file
3233 referring to non-existent sources.
3240 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3246 Session::cleanup_trash_sources (CleanupReport& rep)
3248 // FIXME: needs adaptation for MIDI
3250 vector<space_and_path>::iterator i;
3256 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3258 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
3260 clear_directory (dead_dir, &rep.space, &rep.paths);
3267 Session::set_dirty ()
3269 /* never mark session dirty during loading */
3271 if (_state_of_the_state & Loading) {
3275 bool was_dirty = dirty();
3277 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3281 DirtyChanged(); /* EMIT SIGNAL */
3287 Session::set_clean ()
3289 bool was_dirty = dirty();
3291 _state_of_the_state = Clean;
3295 DirtyChanged(); /* EMIT SIGNAL */
3300 Session::set_deletion_in_progress ()
3302 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3306 Session::clear_deletion_in_progress ()
3308 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3312 Session::add_controllable (boost::shared_ptr<Controllable> c)
3314 /* this adds a controllable to the list managed by the Session.
3315 this is a subset of those managed by the Controllable class
3316 itself, and represents the only ones whose state will be saved
3317 as part of the session.
3320 Glib::Threads::Mutex::Lock lm (controllables_lock);
3321 controllables.insert (c);
3324 struct null_deleter { void operator()(void const *) const {} };
3327 Session::remove_controllable (Controllable* c)
3329 if (_state_of_the_state & Deletion) {
3333 Glib::Threads::Mutex::Lock lm (controllables_lock);
3335 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3337 if (x != controllables.end()) {
3338 controllables.erase (x);
3342 boost::shared_ptr<Controllable>
3343 Session::controllable_by_id (const PBD::ID& id)
3345 Glib::Threads::Mutex::Lock lm (controllables_lock);
3347 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3348 if ((*i)->id() == id) {
3353 return boost::shared_ptr<Controllable>();
3356 boost::shared_ptr<Controllable>
3357 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3359 boost::shared_ptr<Controllable> c;
3360 boost::shared_ptr<Route> r;
3362 switch (desc.top_level_type()) {
3363 case ControllableDescriptor::NamedRoute:
3365 std::string str = desc.top_level_name();
3366 if (str == "Master" || str == "master") {
3368 } else if (str == "control" || str == "listen") {
3371 r = route_by_name (desc.top_level_name());
3376 case ControllableDescriptor::RemoteControlID:
3377 r = route_by_remote_id (desc.rid());
3380 case ControllableDescriptor::SelectionCount:
3381 r = route_by_selected_count (desc.selection_id());
3389 switch (desc.subtype()) {
3390 case ControllableDescriptor::Gain:
3391 c = r->gain_control ();
3394 case ControllableDescriptor::Trim:
3395 c = r->trim()->gain_control ();
3398 case ControllableDescriptor::Solo:
3399 c = r->solo_control();
3402 case ControllableDescriptor::Mute:
3403 c = r->mute_control();
3406 case ControllableDescriptor::Recenable:
3408 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3411 c = t->rec_enable_control ();
3416 case ControllableDescriptor::PanDirection:
3417 c = r->pan_azimuth_control();
3420 case ControllableDescriptor::PanWidth:
3421 c = r->pan_width_control();
3424 case ControllableDescriptor::PanElevation:
3425 c = r->pan_elevation_control();
3428 case ControllableDescriptor::Balance:
3429 /* XXX simple pan control */
3432 case ControllableDescriptor::PluginParameter:
3434 uint32_t plugin = desc.target (0);
3435 uint32_t parameter_index = desc.target (1);
3437 /* revert to zero based counting */
3443 if (parameter_index > 0) {
3447 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3450 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3451 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3456 case ControllableDescriptor::SendGain: {
3457 uint32_t send = desc.target (0);
3461 c = r->send_level_controllable (send);
3466 /* relax and return a null pointer */
3474 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3477 Stateful::add_instant_xml (node, _path);
3480 if (write_to_config) {
3481 Config->add_instant_xml (node);
3486 Session::instant_xml (const string& node_name)
3488 return Stateful::instant_xml (node_name, _path);
3492 Session::save_history (string snapshot_name)
3500 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3501 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3505 if (snapshot_name.empty()) {
3506 snapshot_name = _current_snapshot_name;
3509 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3510 const string backup_filename = history_filename + backup_suffix;
3511 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3512 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3514 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3515 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3516 error << _("could not backup old history file, current history not saved") << endmsg;
3521 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3523 if (!tree.write (xml_path))
3525 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3527 if (g_remove (xml_path.c_str()) != 0) {
3528 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3529 xml_path, g_strerror (errno)) << endmsg;
3531 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3532 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3533 backup_path, g_strerror (errno)) << endmsg;
3543 Session::restore_history (string snapshot_name)
3547 if (snapshot_name.empty()) {
3548 snapshot_name = _current_snapshot_name;
3551 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3552 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3554 info << "Loading history from " << xml_path << endmsg;
3556 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3557 info << string_compose (_("%1: no history file \"%2\" for this session."),
3558 _name, xml_path) << endmsg;
3562 if (!tree.read (xml_path)) {
3563 error << string_compose (_("Could not understand session history file \"%1\""),
3564 xml_path) << endmsg;
3571 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3574 UndoTransaction* ut = new UndoTransaction ();
3577 ut->set_name(t->property("name")->value());
3578 stringstream ss(t->property("tv-sec")->value());
3580 ss.str(t->property("tv-usec")->value());
3582 ut->set_timestamp(tv);
3584 for (XMLNodeConstIterator child_it = t->children().begin();
3585 child_it != t->children().end(); child_it++)
3587 XMLNode *n = *child_it;
3590 if (n->name() == "MementoCommand" ||
3591 n->name() == "MementoUndoCommand" ||
3592 n->name() == "MementoRedoCommand") {
3594 if ((c = memento_command_factory(n))) {
3598 } else if (n->name() == "NoteDiffCommand") {
3599 PBD::ID id (n->property("midi-source")->value());
3600 boost::shared_ptr<MidiSource> midi_source =
3601 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3603 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3605 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3608 } else if (n->name() == "SysExDiffCommand") {
3610 PBD::ID id (n->property("midi-source")->value());
3611 boost::shared_ptr<MidiSource> midi_source =
3612 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3614 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3616 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3619 } else if (n->name() == "PatchChangeDiffCommand") {
3621 PBD::ID id (n->property("midi-source")->value());
3622 boost::shared_ptr<MidiSource> midi_source =
3623 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3625 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3627 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3630 } else if (n->name() == "StatefulDiffCommand") {
3631 if ((c = stateful_diff_command_factory (n))) {
3632 ut->add_command (c);
3635 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3646 Session::config_changed (std::string p, bool ours)
3652 if (p == "seamless-loop") {
3654 } else if (p == "rf-speed") {
3656 } else if (p == "auto-loop") {
3658 } else if (p == "auto-input") {
3660 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3661 /* auto-input only makes a difference if we're rolling */
3662 set_track_monitor_input_status (!config.get_auto_input());
3665 } else if (p == "punch-in") {
3669 if ((location = _locations->auto_punch_location()) != 0) {
3671 if (config.get_punch_in ()) {
3672 replace_event (SessionEvent::PunchIn, location->start());
3674 remove_event (location->start(), SessionEvent::PunchIn);
3678 } else if (p == "punch-out") {
3682 if ((location = _locations->auto_punch_location()) != 0) {
3684 if (config.get_punch_out()) {
3685 replace_event (SessionEvent::PunchOut, location->end());
3687 clear_events (SessionEvent::PunchOut);
3691 } else if (p == "edit-mode") {
3693 Glib::Threads::Mutex::Lock lm (playlists->lock);
3695 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3696 (*i)->set_edit_mode (Config->get_edit_mode ());
3699 } else if (p == "use-video-sync") {
3701 waiting_for_sync_offset = config.get_use_video_sync();
3703 } else if (p == "mmc-control") {
3705 //poke_midi_thread ();
3707 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3709 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3711 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3713 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3715 } else if (p == "midi-control") {
3717 //poke_midi_thread ();
3719 } else if (p == "raid-path") {
3721 setup_raid_path (config.get_raid_path());
3723 } else if (p == "timecode-format") {
3727 } else if (p == "video-pullup") {
3731 } else if (p == "seamless-loop") {
3733 if (play_loop && transport_rolling()) {
3734 // to reset diskstreams etc
3735 request_play_loop (true);
3738 } else if (p == "rf-speed") {
3740 cumulative_rf_motion = 0;
3743 } else if (p == "click-sound") {
3745 setup_click_sounds (1);
3747 } else if (p == "click-emphasis-sound") {
3749 setup_click_sounds (-1);
3751 } else if (p == "clicking") {
3753 if (Config->get_clicking()) {
3754 if (_click_io && click_data) { // don't require emphasis data
3761 } else if (p == "click-gain") {
3764 _click_gain->gain_control()->set_value (Config->get_click_gain(), Controllable::NoGroup);
3767 } else if (p == "send-mtc") {
3769 if (Config->get_send_mtc ()) {
3770 /* mark us ready to send */
3771 next_quarter_frame_to_send = 0;
3774 } else if (p == "send-mmc") {
3776 _mmc->enable_send (Config->get_send_mmc ());
3778 } else if (p == "midi-feedback") {
3780 session_midi_feedback = Config->get_midi_feedback();
3782 } else if (p == "jack-time-master") {
3784 engine().reset_timebase ();
3786 } else if (p == "native-file-header-format") {
3788 if (!first_file_header_format_reset) {
3789 reset_native_file_format ();
3792 first_file_header_format_reset = false;
3794 } else if (p == "native-file-data-format") {
3796 if (!first_file_data_format_reset) {
3797 reset_native_file_format ();
3800 first_file_data_format_reset = false;
3802 } else if (p == "external-sync") {
3803 if (!config.get_external_sync()) {
3804 drop_sync_source ();
3806 switch_to_sync_source (Config->get_sync_source());
3808 } else if (p == "denormal-model") {
3810 } else if (p == "history-depth") {
3811 set_history_depth (Config->get_history_depth());
3812 } else if (p == "remote-model") {
3813 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3816 } else if (p == "initial-program-change") {
3818 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3821 buf[0] = MIDI::program; // channel zero by default
3822 buf[1] = (Config->get_initial_program_change() & 0x7f);
3824 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3826 } else if (p == "solo-mute-override") {
3827 // catch_up_on_solo_mute_override ();
3828 } else if (p == "listen-position" || p == "pfl-position") {
3829 listen_position_changed ();
3830 } else if (p == "solo-control-is-listen-control") {
3831 solo_control_mode_changed ();
3832 } else if (p == "solo-mute-gain") {
3833 _solo_cut_control->Changed();
3834 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3835 last_timecode_valid = false;
3836 } else if (p == "playback-buffer-seconds") {
3837 AudioSource::allocate_working_buffers (frame_rate());
3838 } else if (p == "ltc-source-port") {
3839 reconnect_ltc_input ();
3840 } else if (p == "ltc-sink-port") {
3841 reconnect_ltc_output ();
3842 } else if (p == "timecode-generator-offset") {
3843 ltc_tx_parse_offset();
3844 } else if (p == "auto-return-target-list") {
3845 follow_playhead_priority ();
3852 Session::set_history_depth (uint32_t d)
3854 _history.set_depth (d);
3858 Session::load_diskstreams_2X (XMLNode const & node, int)
3861 XMLNodeConstIterator citer;
3863 clist = node.children();
3865 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3868 /* diskstreams added automatically by DiskstreamCreated handler */
3869 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3870 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3871 _diskstreams_2X.push_back (dsp);
3873 error << _("Session: unknown diskstream type in XML") << endmsg;
3877 catch (failed_constructor& err) {
3878 error << _("Session: could not load diskstream via XML state") << endmsg;
3886 /** Connect things to the MMC object */
3888 Session::setup_midi_machine_control ()
3890 _mmc = new MIDI::MachineControl;
3892 boost::shared_ptr<AsyncMIDIPort> async_in = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_input_port());
3893 boost::shared_ptr<AsyncMIDIPort> async_out = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_output_port());
3895 if (!async_out || !async_out) {
3899 /* XXXX argh, passing raw pointers back into libmidi++ */
3901 MIDI::Port* mmc_in = async_in.get();
3902 MIDI::Port* mmc_out = async_out.get();
3904 _mmc->set_ports (mmc_in, mmc_out);
3906 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3907 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3908 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3909 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3910 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3911 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3912 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3913 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3914 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3915 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3916 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3917 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3918 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3920 /* also handle MIDI SPP because its so common */
3922 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3923 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3924 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3927 boost::shared_ptr<Controllable>
3928 Session::solo_cut_control() const
3930 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3931 controls in Ardour that currently get presented to the user in the GUI that require
3932 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3934 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3935 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3939 return _solo_cut_control;
3943 Session::save_snapshot_name (const std::string & n)
3945 /* assure Stateful::_instant_xml is loaded
3946 * add_instant_xml() only adds to existing data and defaults
3947 * to use an empty Tree otherwise
3949 instant_xml ("LastUsedSnapshot");
3951 XMLNode* last_used_snapshot = new XMLNode ("LastUsedSnapshot");
3952 last_used_snapshot->add_property ("name", string(n));
3953 add_instant_xml (*last_used_snapshot, false);
3957 Session::set_snapshot_name (const std::string & n)
3959 _current_snapshot_name = n;
3960 save_snapshot_name (n);
3964 Session::rename (const std::string& new_name)
3966 string legal_name = legalize_for_path (new_name);
3972 string const old_sources_root = _session_dir->sources_root();
3974 if (!_writable || (_state_of_the_state & CannotSave)) {
3975 error << _("Cannot rename read-only session.") << endmsg;
3976 return 0; // don't show "messed up" warning
3978 if (record_status() == Recording) {
3979 error << _("Cannot rename session while recording") << endmsg;
3980 return 0; // don't show "messed up" warning
3983 StateProtector stp (this);
3988 * interchange subdirectory
3992 * Backup files are left unchanged and not renamed.
3995 /* Windows requires that we close all files before attempting the
3996 * rename. This works on other platforms, but isn't necessary there.
3997 * Leave it in place for all platforms though, since it may help
3998 * catch issues that could arise if the way Source files work ever
3999 * change (since most developers are not using Windows).
4002 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4003 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4009 /* pass one: not 100% safe check that the new directory names don't
4013 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4017 /* this is a stupid hack because Glib::path_get_dirname() is
4018 * lexical-only, and so passing it /a/b/c/ gives a different
4019 * result than passing it /a/b/c ...
4022 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4023 oldstr = oldstr.substr (0, oldstr.length() - 1);
4026 string base = Glib::path_get_dirname (oldstr);
4028 newstr = Glib::build_filename (base, legal_name);
4030 cerr << "Looking for " << newstr << endl;
4032 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
4033 cerr << " exists\n";
4042 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4048 /* this is a stupid hack because Glib::path_get_dirname() is
4049 * lexical-only, and so passing it /a/b/c/ gives a different
4050 * result than passing it /a/b/c ...
4053 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4054 oldstr = oldstr.substr (0, oldstr.length() - 1);
4057 string base = Glib::path_get_dirname (oldstr);
4058 newstr = Glib::build_filename (base, legal_name);
4060 cerr << "for " << oldstr << " new dir = " << newstr << endl;
4062 cerr << "Rename " << oldstr << " => " << newstr << endl;
4063 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4064 cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4065 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4069 /* Reset path in "session dirs" */
4074 /* reset primary SessionDirectory object */
4077 (*_session_dir) = newstr;
4082 /* now rename directory below session_dir/interchange */
4084 string old_interchange_dir;
4085 string new_interchange_dir;
4087 /* use newstr here because we renamed the path
4088 * (folder/directory) that used to be oldstr to newstr above
4091 v.push_back (newstr);
4092 v.push_back (interchange_dir_name);
4093 v.push_back (Glib::path_get_basename (oldstr));
4095 old_interchange_dir = Glib::build_filename (v);
4098 v.push_back (newstr);
4099 v.push_back (interchange_dir_name);
4100 v.push_back (legal_name);
4102 new_interchange_dir = Glib::build_filename (v);
4104 cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
4106 if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
4107 cerr << string_compose (_("renaming %s as %2 failed (%3)"),
4108 old_interchange_dir, new_interchange_dir,
4111 error << string_compose (_("renaming %s as %2 failed (%3)"),
4112 old_interchange_dir, new_interchange_dir,
4121 oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
4122 newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
4124 cerr << "Rename " << oldstr << " => " << newstr << endl;
4126 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4127 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4128 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4134 oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
4136 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
4137 newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
4139 cerr << "Rename " << oldstr << " => " << newstr << endl;
4141 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4142 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4143 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4148 /* remove old name from recent sessions */
4149 remove_recent_sessions (_path);
4152 /* update file source paths */
4154 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
4155 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4157 string p = fs->path ();
4158 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
4160 SourceFactory::setup_peakfile(i->second, true);
4164 set_snapshot_name (new_name);
4169 /* save state again to get everything just right */
4171 save_state (_current_snapshot_name);
4173 /* add to recent sessions */
4175 store_recent_sessions (new_name, _path);
4181 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
4183 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
4187 if (!tree.read (xmlpath)) {
4195 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
4198 bool found_sr = false;
4199 bool found_data_format = false;
4201 if (get_session_info_from_path (tree, xmlpath)) {
4207 const XMLProperty* prop;
4208 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
4209 sample_rate = atoi (prop->value());
4213 const XMLNodeList& children (tree.root()->children());
4214 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
4215 const XMLNode* child = *c;
4216 if (child->name() == "Config") {
4217 const XMLNodeList& options (child->children());
4218 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
4219 const XMLNode* option = *oc;
4220 const XMLProperty* name = option->property("name");
4226 if (name->value() == "native-file-data-format") {
4227 const XMLProperty* value = option->property ("value");
4229 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
4231 found_data_format = true;
4237 if (found_data_format) {
4242 return !(found_sr && found_data_format); // zero if they are both found
4246 Session::get_snapshot_from_instant (const std::string& session_dir)
4248 std::string instant_xml_path = Glib::build_filename (session_dir, "instant.xml");
4250 if (!Glib::file_test (instant_xml_path, Glib::FILE_TEST_EXISTS)) {
4255 if (!tree.read (instant_xml_path)) {
4259 const XMLProperty* prop;
4260 XMLNode *last_used_snapshot = tree.root()->child("LastUsedSnapshot");
4261 if (last_used_snapshot && (prop = last_used_snapshot->property ("name")) != 0) {
4262 return prop->value();
4268 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
4269 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
4272 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
4276 SourcePathMap source_path_map;
4278 boost::shared_ptr<AudioFileSource> afs;
4283 Glib::Threads::Mutex::Lock lm (source_lock);
4285 cerr << " total sources = " << sources.size();
4287 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4288 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4294 if (fs->within_session()) {
4298 if (source_path_map.find (fs->path()) != source_path_map.end()) {
4299 source_path_map[fs->path()].push_back (fs);
4301 SeveralFileSources v;
4303 source_path_map.insert (make_pair (fs->path(), v));
4309 cerr << " fsources = " << total << endl;
4311 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
4313 /* tell caller where we are */
4315 string old_path = i->first;
4317 callback (n, total, old_path);
4319 cerr << old_path << endl;
4323 switch (i->second.front()->type()) {
4324 case DataType::AUDIO:
4325 new_path = new_audio_source_path_for_embedded (old_path);
4328 case DataType::MIDI:
4329 /* XXX not implemented yet */
4333 if (new_path.empty()) {
4337 cerr << "Move " << old_path << " => " << new_path << endl;
4339 if (!copy_file (old_path, new_path)) {
4340 cerr << "failed !\n";
4344 /* make sure we stop looking in the external
4345 dir/folder. Remember, this is an all-or-nothing
4346 operations, it doesn't merge just some files.
4348 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
4350 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
4351 (*f)->set_path (new_path);
4356 save_state ("", false, false);
4362 bool accept_all_files (string const &, void *)
4368 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4370 /* 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.
4375 make_new_media_path (string old_path, string new_session_folder, string new_session_path)
4377 /* typedir is the "midifiles" or "audiofiles" etc. part of the path. */
4379 string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4381 v.push_back (new_session_folder); /* full path */
4382 v.push_back (interchange_dir_name);
4383 v.push_back (new_session_path); /* just one directory/folder */
4384 v.push_back (typedir);
4385 v.push_back (Glib::path_get_basename (old_path));
4387 return Glib::build_filename (v);
4391 Session::save_as (SaveAs& saveas)
4393 vector<string> files;
4394 string current_folder = Glib::path_get_dirname (_path);
4395 string new_folder = legalize_for_path (saveas.new_name);
4396 string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4397 int64_t total_bytes = 0;
4401 int32_t internal_file_cnt = 0;
4403 vector<string> do_not_copy_extensions;
4404 do_not_copy_extensions.push_back (statefile_suffix);
4405 do_not_copy_extensions.push_back (pending_suffix);
4406 do_not_copy_extensions.push_back (backup_suffix);
4407 do_not_copy_extensions.push_back (temp_suffix);
4408 do_not_copy_extensions.push_back (history_suffix);
4410 /* get total size */
4412 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4414 /* need to clear this because
4415 * find_files_matching_filter() is cumulative
4420 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4422 all += files.size();
4424 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4426 g_stat ((*i).c_str(), &gsb);
4427 total_bytes += gsb.st_size;
4431 /* save old values so we can switch back if we are not switching to the new session */
4433 string old_path = _path;
4434 string old_name = _name;
4435 string old_snapshot = _current_snapshot_name;
4436 string old_sd = _session_dir->root_path();
4437 vector<string> old_search_path[DataType::num_types];
4438 string old_config_search_path[DataType::num_types];
4440 old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4441 old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4442 old_config_search_path[DataType::AUDIO] = config.get_audio_search_path ();
4443 old_config_search_path[DataType::MIDI] = config.get_midi_search_path ();
4445 /* switch session directory */
4447 (*_session_dir) = to_dir;
4449 /* create new tree */
4451 if (!_session_dir->create()) {
4452 saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4457 /* copy all relevant files. Find each location in session_dirs,
4458 * and copy files from there to target.
4461 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4463 /* need to clear this because
4464 * find_files_matching_filter() is cumulative
4469 const size_t prefix_len = (*sd).path.size();
4471 /* Work just on the files within this session dir */
4473 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4475 /* add dir separator to protect against collisions with
4476 * track names (e.g. track named "audiofiles" or
4480 static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
4481 static const std::string midifile_dir_string = string (midi_dir_name) + G_DIR_SEPARATOR;
4482 static const std::string analysis_dir_string = analysis_dir() + G_DIR_SEPARATOR;
4484 /* copy all the files. Handling is different for media files
4485 than others because of the *silly* subtree we have below the interchange
4486 folder. That really was a bad idea, but I'm not fixing it as part of
4487 implementing ::save_as().
4490 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4492 std::string from = *i;
4495 string filename = Glib::path_get_basename (from);
4496 std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
4497 if (filename == ".DS_STORE") {
4502 if (from.find (audiofile_dir_string) != string::npos) {
4504 /* audio file: only copy if asked */
4506 if (saveas.include_media && saveas.copy_media) {
4508 string to = make_new_media_path (*i, to_dir, new_folder);
4510 info << "media file copying from " << from << " to " << to << endmsg;
4512 if (!copy_file (from, to)) {
4513 throw Glib::FileError (Glib::FileError::IO_ERROR,
4514 string_compose(_("\ncopying \"%1\" failed !"), from));
4518 /* we found media files inside the session folder */
4520 internal_file_cnt++;
4522 } else if (from.find (midifile_dir_string) != string::npos) {
4524 /* midi file: always copy unless
4525 * creating an empty new session
4528 if (saveas.include_media) {
4530 string to = make_new_media_path (*i, to_dir, new_folder);
4532 info << "media file copying from " << from << " to " << to << endmsg;
4534 if (!copy_file (from, to)) {
4535 throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4539 /* we found media files inside the session folder */
4541 internal_file_cnt++;
4543 } else if (from.find (analysis_dir_string) != string::npos) {
4545 /* make sure analysis dir exists in
4546 * new session folder, but we're not
4547 * copying analysis files here, see
4551 (void) g_mkdir_with_parents (analysis_dir().c_str(), 775);
4556 /* normal non-media file. Don't copy state, history, etc.
4559 bool do_copy = true;
4561 for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
4562 if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
4563 /* end of filename matches extension, do not copy file */
4569 if (!saveas.copy_media && from.find (peakfile_suffix) != string::npos) {
4570 /* don't copy peakfiles if
4571 * we're not copying media
4577 string to = Glib::build_filename (to_dir, from.substr (prefix_len));
4579 info << "attempting to make directory/folder " << to << endmsg;
4581 if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
4582 throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
4585 info << "attempting to copy " << from << " to " << to << endmsg;
4587 if (!copy_file (from, to)) {
4588 throw Glib::FileError (Glib::FileError::IO_ERROR,
4589 string_compose(_("\ncopying \"%1\" failed !"), from));
4594 /* measure file size even if we're not going to copy so that our Progress
4595 signals are correct, since we included these do-not-copy files
4596 in the computation of the total size and file count.
4600 g_stat (from.c_str(), &gsb);
4601 copied += gsb.st_size;
4604 double fraction = (double) copied / total_bytes;
4606 bool keep_going = true;
4608 if (saveas.copy_media) {
4610 /* no need or expectation of this if
4611 * media is not being copied, because
4612 * it will be fast(ish).
4615 /* tell someone "X percent, file M of N"; M is one-based */
4617 boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
4625 throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
4631 /* copy optional folders, if any */
4633 string old = plugins_dir ();
4634 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4635 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4636 copy_files (old, newdir);
4639 old = externals_dir ();
4640 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4641 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4642 copy_files (old, newdir);
4645 old = automation_dir ();
4646 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4647 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4648 copy_files (old, newdir);
4651 if (saveas.include_media) {
4653 if (saveas.copy_media) {
4654 #ifndef PLATFORM_WINDOWS
4655 /* There are problems with analysis files on
4656 * Windows, because they used a colon in their
4657 * names as late as 4.0. Colons are not legal
4658 * under Windows even if NTFS allows them.
4660 * This is a tricky problem to solve so for
4661 * just don't copy these files. They will be
4662 * regenerated as-needed anyway, subject to the
4663 * existing issue that the filenames will be
4664 * rejected by Windows, which is a separate
4665 * problem (though related).
4668 /* only needed if we are copying media, since the
4669 * analysis data refers to media data
4672 old = analysis_dir ();
4673 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4674 string newdir = Glib::build_filename (to_dir, "analysis");
4675 copy_files (old, newdir);
4677 #endif /* PLATFORM_WINDOWS */
4683 set_snapshot_name (saveas.new_name);
4684 _name = saveas.new_name;
4686 if (saveas.include_media && !saveas.copy_media) {
4688 /* reset search paths of the new session (which we're pretending to be right now) to
4689 include the original session search path, so we can still find all audio.
4692 if (internal_file_cnt) {
4693 for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
4694 ensure_search_path_includes (*s, DataType::AUDIO);
4695 cerr << "be sure to include " << *s << " for audio" << endl;
4698 /* we do not do this for MIDI because we copy
4699 all MIDI files if saveas.include_media is
4705 bool was_dirty = dirty ();
4707 save_state ("", false, false, !saveas.include_media);
4708 save_default_options ();
4710 if (saveas.copy_media && saveas.copy_external) {
4711 if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
4712 throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
4716 saveas.final_session_folder_name = _path;
4718 store_recent_sessions (_name, _path);
4720 if (!saveas.switch_to) {
4722 /* switch back to the way things were */
4726 set_snapshot_name (old_snapshot);
4728 (*_session_dir) = old_sd;
4734 if (internal_file_cnt) {
4735 /* reset these to their original values */
4736 config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
4737 config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
4742 /* prune session dirs, and update disk space statistics
4747 session_dirs.clear ();
4748 session_dirs.push_back (sp);
4749 refresh_disk_space ();
4751 /* ensure that all existing tracks reset their current capture source paths
4753 reset_write_sources (true, true);
4755 /* the copying above was based on actually discovering files, not just iterating over the sources list.
4756 But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
4759 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4760 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4766 if (fs->within_session()) {
4767 string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
4768 fs->set_path (newpath);
4773 } catch (Glib::FileError& e) {
4775 saveas.failure_message = e.what();
4777 /* recursively remove all the directories */
4779 remove_directory (to_dir);
4787 saveas.failure_message = _("unknown reason");
4789 /* recursively remove all the directories */
4791 remove_directory (to_dir);