2 Copyright (C) 1999-2013 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "libardour-config.h"
30 #include <cstdio> /* snprintf(3) ... grrr */
42 #include <sys/param.h>
43 #include <sys/mount.h>
46 #ifdef HAVE_SYS_STATVFS_H
47 #include <sys/statvfs.h>
51 #include "pbd/gstdio_compat.h"
54 #include <glibmm/threads.h>
55 #include <glibmm/fileutils.h>
57 #include <boost/algorithm/string.hpp>
59 #include "midi++/mmc.h"
60 #include "midi++/port.h"
62 #include "evoral/SMF.hpp"
64 #include "pbd/boost_debug.h"
65 #include "pbd/basename.h"
66 #include "pbd/controllable_descriptor.h"
67 #include "pbd/debug.h"
68 #include "pbd/enumwriter.h"
69 #include "pbd/error.h"
70 #include "pbd/file_utils.h"
71 #include "pbd/pathexpand.h"
72 #include "pbd/pthread_utils.h"
73 #include "pbd/stacktrace.h"
74 #include "pbd/convert.h"
75 #include "pbd/localtime_r.h"
76 #include "pbd/unwind.h"
78 #include "ardour/amp.h"
79 #include "ardour/async_midi_port.h"
80 #include "ardour/audio_diskstream.h"
81 #include "ardour/audio_track.h"
82 #include "ardour/audioengine.h"
83 #include "ardour/audiofilesource.h"
84 #include "ardour/audioregion.h"
85 #include "ardour/automation_control.h"
86 #include "ardour/butler.h"
87 #include "ardour/control_protocol_manager.h"
88 #include "ardour/directory_names.h"
89 #include "ardour/filename_extensions.h"
90 #include "ardour/graph.h"
91 #include "ardour/location.h"
92 #include "ardour/midi_model.h"
93 #include "ardour/midi_patch_manager.h"
94 #include "ardour/midi_region.h"
95 #include "ardour/midi_scene_changer.h"
96 #include "ardour/midi_source.h"
97 #include "ardour/midi_track.h"
98 #include "ardour/pannable.h"
99 #include "ardour/playlist_factory.h"
100 #include "ardour/playlist_source.h"
101 #include "ardour/port.h"
102 #include "ardour/processor.h"
103 #include "ardour/profile.h"
104 #include "ardour/proxy_controllable.h"
105 #include "ardour/recent_sessions.h"
106 #include "ardour/region_factory.h"
107 #include "ardour/route_group.h"
108 #include "ardour/send.h"
109 #include "ardour/session.h"
110 #include "ardour/session_directory.h"
111 #include "ardour/session_metadata.h"
112 #include "ardour/session_playlists.h"
113 #include "ardour/session_state_utils.h"
114 #include "ardour/silentfilesource.h"
115 #include "ardour/sndfilesource.h"
116 #include "ardour/source_factory.h"
117 #include "ardour/speakers.h"
118 #include "ardour/template_utils.h"
119 #include "ardour/tempo.h"
120 #include "ardour/ticker.h"
121 #include "ardour/user_bundle.h"
123 #include "control_protocol/control_protocol.h"
125 #include "LuaBridge/LuaBridge.h"
131 using namespace ARDOUR;
134 #define DEBUG_UNDO_HISTORY(msg) DEBUG_TRACE (PBD::DEBUG::UndoHistory, string_compose ("%1: %2\n", __LINE__, msg));
137 Session::pre_engine_init (string fullpath)
139 if (fullpath.empty()) {
141 throw failed_constructor();
144 /* discover canonical fullpath */
146 _path = canonical_path(fullpath);
149 if (Profile->get_trx() ) {
150 // Waves TracksLive has a usecase of session replacement with a new one.
151 // We should check session state file (<session_name>.ardour) existance
152 // to determine if the session is new or not
154 string full_session_name = Glib::build_filename( fullpath, _name );
155 full_session_name += statefile_suffix;
157 _is_new = !Glib::file_test (full_session_name, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
159 _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
162 /* finish initialization that can't be done in a normal C++ constructor
166 timerclear (&last_mmc_step);
167 g_atomic_int_set (&processing_prohibited, 0);
168 g_atomic_int_set (&_record_status, Disabled);
169 g_atomic_int_set (&_playback_load, 100);
170 g_atomic_int_set (&_capture_load, 100);
172 _all_route_group->set_active (true, this);
173 interpolation.add_channel_to (0, 0);
175 if (config.get_use_video_sync()) {
176 waiting_for_sync_offset = true;
178 waiting_for_sync_offset = false;
181 last_rr_session_dir = session_dirs.begin();
183 set_history_depth (Config->get_history_depth());
185 /* default: assume simple stereo speaker configuration */
187 _speakers->setup_default_speakers (2);
189 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
190 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
191 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
192 add_controllable (_solo_cut_control);
194 /* These are all static "per-class" signals */
196 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
197 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
198 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
199 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
200 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
202 /* stop IO objects from doing stuff until we're ready for them */
204 Delivery::disable_panners ();
205 IO::disable_connecting ();
209 Session::post_engine_init ()
211 BootMessage (_("Set block size and sample rate"));
213 set_block_size (_engine.samples_per_cycle());
214 set_frame_rate (_engine.sample_rate());
216 BootMessage (_("Using configuration"));
218 _midi_ports = new MidiPortManager;
220 MIDISceneChanger* msc;
222 _scene_changer = msc = new MIDISceneChanger (*this);
223 msc->set_input_port (boost::dynamic_pointer_cast<MidiPort>(scene_input_port()));
224 msc->set_output_port (boost::dynamic_pointer_cast<MidiPort>(scene_output_port()));
226 boost::function<framecnt_t(void)> timer_func (boost::bind (&Session::audible_frame, this));
227 boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_input_port())->set_timer (timer_func);
229 setup_midi_machine_control ();
231 if (_butler->start_thread()) {
235 if (start_midi_thread ()) {
239 setup_click_sounds (0);
240 setup_midi_control ();
242 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
243 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
246 /* tempo map requires sample rate knowledge */
249 _tempo_map = new TempoMap (_current_frame_rate);
250 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
252 /* MidiClock requires a tempo map */
254 midi_clock = new MidiClockTicker ();
255 midi_clock->set_session (this);
257 /* crossfades require sample rate knowledge */
259 SndFileSource::setup_standard_crossfades (*this, frame_rate());
260 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
262 AudioDiskstream::allocate_working_buffers();
263 refresh_disk_space ();
265 /* we're finally ready to call set_state() ... all objects have
266 * been created, the engine is running.
270 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
274 // set_state() will call setup_raid_path(), but if it's a new session we need
275 // to call setup_raid_path() here.
276 setup_raid_path (_path);
281 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
282 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
284 Config->map_parameters (ff);
285 config.map_parameters (ft);
286 _butler->map_parameters ();
288 /* Reset all panners */
290 Delivery::reset_panners ();
292 /* this will cause the CPM to instantiate any protocols that are in use
293 * (or mandatory), which will pass it this Session, and then call
294 * set_state() on each instantiated protocol to match stored state.
297 ControlProtocolManager::instance().set_session (this);
299 /* This must be done after the ControlProtocolManager set_session above,
300 as it will set states for ports which the ControlProtocolManager creates.
303 // XXX set state of MIDI::Port's
304 // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
306 /* And this must be done after the MIDI::Manager::set_port_states as
307 * it will try to make connections whose details are loaded by set_port_states.
312 /* Let control protocols know that we are now all connected, so they
313 * could start talking to surfaces if they want to.
316 ControlProtocolManager::instance().midi_connectivity_established ();
318 if (_is_new && !no_auto_connect()) {
319 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
320 auto_connect_master_bus ();
323 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
325 /* update latencies */
327 initialize_latencies ();
329 _locations->added.connect_same_thread (*this, boost::bind (&Session::location_added, this, _1));
330 _locations->removed.connect_same_thread (*this, boost::bind (&Session::location_removed, this, _1));
331 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
333 } catch (AudioEngine::PortRegistrationFailure& err) {
334 /* handle this one in a different way than all others, so that its clear what happened */
335 error << err.what() << endmsg;
341 BootMessage (_("Reset Remote Controls"));
343 // send_full_time_code (0);
344 _engine.transport_locate (0);
346 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
347 send_immediate_mmc (MIDI::MachineControlCommand (Timecode::Time ()));
349 MIDI::Name::MidiPatchManager::instance().add_search_path (session_directory().midi_patch_path() );
352 /* initial program change will be delivered later; see ::config_changed() */
354 _state_of_the_state = Clean;
356 Port::set_connecting_blocked (false);
358 DirtyChanged (); /* EMIT SIGNAL */
362 } else if (state_was_pending) {
364 remove_pending_capture_state ();
365 state_was_pending = false;
368 /* Now, finally, we can fill the playback buffers */
370 BootMessage (_("Filling playback buffers"));
372 boost::shared_ptr<RouteList> rl = routes.reader();
373 for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
374 boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<Track> (*r);
375 if (trk && !trk->hidden()) {
376 trk->seek (_transport_frame, true);
384 Session::session_loaded ()
388 _state_of_the_state = Clean;
390 DirtyChanged (); /* EMIT SIGNAL */
394 } else if (state_was_pending) {
396 remove_pending_capture_state ();
397 state_was_pending = false;
400 /* Now, finally, we can fill the playback buffers */
402 BootMessage (_("Filling playback buffers"));
403 force_locate (_transport_frame, false);
407 Session::raid_path () const
409 Searchpath raid_search_path;
411 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
412 raid_search_path += (*i).path;
415 return raid_search_path.to_string ();
419 Session::setup_raid_path (string path)
428 session_dirs.clear ();
430 Searchpath search_path(path);
431 Searchpath sound_search_path;
432 Searchpath midi_search_path;
434 for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
436 sp.blocks = 0; // not needed
437 session_dirs.push_back (sp);
439 SessionDirectory sdir(sp.path);
441 sound_search_path += sdir.sound_path ();
442 midi_search_path += sdir.midi_path ();
445 // reset the round-robin soundfile path thingie
446 last_rr_session_dir = session_dirs.begin();
450 Session::path_is_within_session (const std::string& path)
452 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
453 if (PBD::path_is_within (i->path, path)) {
461 Session::ensure_subdirs ()
465 dir = session_directory().peak_path();
467 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
468 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
472 dir = session_directory().sound_path();
474 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
475 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
479 dir = session_directory().midi_path();
481 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
482 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
486 dir = session_directory().dead_path();
488 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
489 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
493 dir = session_directory().export_path();
495 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
496 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
500 dir = analysis_dir ();
502 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
503 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
507 dir = plugins_dir ();
509 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
510 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
514 dir = externals_dir ();
516 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
517 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
524 /** @param session_template directory containing session template, or empty.
525 * Caller must not hold process lock.
528 Session::create (const string& session_template, BusProfile* bus_profile)
530 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
531 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
535 if (ensure_subdirs ()) {
539 _writable = exists_and_writable (_path);
541 if (!session_template.empty()) {
542 string in_path = (ARDOUR::Profile->get_trx () ? session_template : session_template_dir_to_file (session_template));
544 FILE* in = g_fopen (in_path.c_str(), "rb");
547 /* no need to call legalize_for_path() since the string
548 * in session_template is already a legal path name
550 string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
552 FILE* out = g_fopen (out_path.c_str(), "wb");
556 stringstream new_session;
559 size_t charsRead = fread (buf, sizeof(char), 1024, in);
562 error << string_compose (_("Error reading session template file %1 (%2)"), in_path, strerror (errno)) << endmsg;
567 if (charsRead == 0) {
570 new_session.write (buf, charsRead);
574 string file_contents = new_session.str();
575 size_t writeSize = file_contents.length();
576 if (fwrite (file_contents.c_str(), sizeof(char), writeSize, out) != writeSize) {
577 error << string_compose (_("Error writing session template file %1 (%2)"), out_path, strerror (errno)) << endmsg;
585 if (!ARDOUR::Profile->get_trx()) {
586 /* Copy plugin state files from template to new session */
587 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
588 copy_recurse (template_plugins, plugins_dir ());
594 error << string_compose (_("Could not open %1 for writing session template"), out_path)
601 error << string_compose (_("Could not open session template %1 for reading"), in_path)
608 if (Profile->get_trx()) {
610 /* set initial start + end point : ARDOUR::Session::session_end_shift long.
611 Remember that this is a brand new session. Sessions
612 loaded from saved state will get this range from the saved state.
615 set_session_range_location (0, 0);
617 /* Initial loop location, from absolute zero, length 10 seconds */
619 Location* loc = new Location (*this, 0, 10.0 * _engine.sample_rate(), _("Loop"), Location::IsAutoLoop);
620 _locations->add (loc, true);
621 set_auto_loop_location (loc);
624 _state_of_the_state = Clean;
626 /* set up Master Out and Control Out if necessary */
631 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
633 // Waves Tracks: always create master bus for Tracks
634 if (ARDOUR::Profile->get_trx() || bus_profile->master_out_channels) {
635 boost::shared_ptr<Route> r (new Route (*this, _("Master"), Route::MasterOut, DataType::AUDIO));
639 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
640 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
643 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
644 r->input()->ensure_io (count, false, this);
645 r->output()->ensure_io (count, false, this);
651 /* prohibit auto-connect to master, because there isn't one */
652 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
656 add_routes (rl, false, false, false);
659 // Waves Tracks: Skip this. Always use autoconnection for Tracks
660 if (!ARDOUR::Profile->get_trx()) {
662 /* this allows the user to override settings with an environment variable.
665 if (no_auto_connect()) {
666 bus_profile->input_ac = AutoConnectOption (0);
667 bus_profile->output_ac = AutoConnectOption (0);
670 Config->set_input_auto_connect (bus_profile->input_ac);
671 Config->set_output_auto_connect (bus_profile->output_ac);
675 if (Config->get_use_monitor_bus() && bus_profile) {
676 add_monitor_section ();
683 Session::maybe_write_autosave()
685 if (dirty() && record_status() != Recording) {
686 save_state("", true);
691 Session::remove_pending_capture_state ()
693 std::string pending_state_file_path(_session_dir->root_path());
695 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
697 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
699 if (g_remove (pending_state_file_path.c_str()) != 0) {
700 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
701 pending_state_file_path, g_strerror (errno)) << endmsg;
705 /** Rename a state file.
706 * @param old_name Old snapshot name.
707 * @param new_name New snapshot name.
710 Session::rename_state (string old_name, string new_name)
712 if (old_name == _current_snapshot_name || old_name == _name) {
713 /* refuse to rename the current snapshot or the "main" one */
717 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
718 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
720 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
721 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
723 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
724 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
725 old_name, new_name, g_strerror(errno)) << endmsg;
729 /** Remove a state file.
730 * @param snapshot_name Snapshot name.
733 Session::remove_state (string snapshot_name)
735 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
736 // refuse to remove the current snapshot or the "main" one
740 std::string xml_path(_session_dir->root_path());
742 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
744 if (!create_backup_file (xml_path)) {
745 // don't remove it if a backup can't be made
746 // create_backup_file will log the error.
751 if (g_remove (xml_path.c_str()) != 0) {
752 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
753 xml_path, g_strerror (errno)) << endmsg;
757 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
759 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot, bool template_only)
762 std::string xml_path(_session_dir->root_path());
764 /* prevent concurrent saves from different threads */
766 Glib::Threads::Mutex::Lock lm (save_state_lock);
768 if (!_writable || (_state_of_the_state & CannotSave)) {
772 if (g_atomic_int_get(&_suspend_save)) {
776 _save_queued = false;
778 if (!_engine.connected ()) {
779 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
786 const int64_t save_start_time = g_get_monotonic_time();
789 /* tell sources we're saving first, in case they write out to a new file
790 * which should be saved with the state rather than the old one */
791 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
793 i->second->session_saved();
794 } catch (Evoral::SMF::FileError& e) {
795 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
799 SessionSaveUnderway (); /* EMIT SIGNAL */
801 bool mark_as_clean = true;
803 if (!snapshot_name.empty() && !switch_to_snapshot) {
804 mark_as_clean = false;
808 mark_as_clean = false;
809 tree.set_root (&get_template());
811 tree.set_root (&get_state());
814 if (snapshot_name.empty()) {
815 snapshot_name = _current_snapshot_name;
816 } else if (switch_to_snapshot) {
817 set_snapshot_name (snapshot_name);
820 assert (!snapshot_name.empty());
824 /* proper save: use statefile_suffix (.ardour in English) */
826 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
828 /* make a backup copy of the old file */
830 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
831 // create_backup_file will log the error
837 /* pending save: use pending_suffix (.pending in English) */
838 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
841 std::string tmp_path(_session_dir->root_path());
842 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
844 cerr << "actually writing state to " << tmp_path << endl;
846 if (!tree.write (tmp_path)) {
847 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
848 if (g_remove (tmp_path.c_str()) != 0) {
849 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
850 tmp_path, g_strerror (errno)) << endmsg;
856 cerr << "renaming state to " << xml_path << endl;
858 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
859 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
860 tmp_path, xml_path, g_strerror(errno)) << endmsg;
861 if (g_remove (tmp_path.c_str()) != 0) {
862 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
863 tmp_path, g_strerror (errno)) << endmsg;
871 save_history (snapshot_name);
874 bool was_dirty = dirty();
876 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
879 DirtyChanged (); /* EMIT SIGNAL */
883 StateSaved (snapshot_name); /* EMIT SIGNAL */
887 const int64_t elapsed_time_us = g_get_monotonic_time() - save_start_time;
888 cerr << "saved state in " << fixed << setprecision (1) << elapsed_time_us / 1000. << " ms\n";
894 Session::restore_state (string snapshot_name)
896 if (load_state (snapshot_name) == 0) {
897 set_state (*state_tree->root(), Stateful::loading_state_version);
904 Session::load_state (string snapshot_name)
909 state_was_pending = false;
911 /* check for leftover pending state from a crashed capture attempt */
913 std::string xmlpath(_session_dir->root_path());
914 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
916 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
918 /* there is pending state from a crashed capture attempt */
920 boost::optional<int> r = AskAboutPendingState();
921 if (r.get_value_or (1)) {
922 state_was_pending = true;
926 if (!state_was_pending) {
927 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
930 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
931 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
932 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
933 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
938 state_tree = new XMLTree;
942 _writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
944 if (!state_tree->read (xmlpath)) {
945 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
951 XMLNode& root (*state_tree->root());
953 if (root.name() != X_("Session")) {
954 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
960 const XMLProperty* prop;
962 if ((prop = root.property ("version")) == 0) {
963 /* no version implies very old version of Ardour */
964 Stateful::loading_state_version = 1000;
966 if (prop->value().find ('.') != string::npos) {
967 /* old school version format */
968 if (prop->value()[0] == '2') {
969 Stateful::loading_state_version = 2000;
971 Stateful::loading_state_version = 3000;
974 Stateful::loading_state_version = atoi (prop->value());
978 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
980 std::string backup_path(_session_dir->root_path());
981 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
982 backup_path = Glib::build_filename (backup_path, backup_filename);
984 // only create a backup for a given statefile version once
986 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
988 VersionMismatch (xmlpath, backup_path);
990 if (!copy_file (xmlpath, backup_path)) {;
996 save_snapshot_name (snapshot_name);
1002 Session::load_options (const XMLNode& node)
1004 LocaleGuard lg (X_("C"));
1005 config.set_variables (node);
1010 Session::save_default_options ()
1012 return config.save_state();
1016 Session::get_state()
1022 Session::get_template()
1024 /* if we don't disable rec-enable, diskstreams
1025 will believe they need to store their capture
1026 sources in their state node.
1029 disable_record (false);
1031 return state(false);
1035 Session::state (bool full_state)
1037 XMLNode* node = new XMLNode("Session");
1041 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
1042 node->add_property("version", buf);
1044 /* store configuration settings */
1048 node->add_property ("name", _name);
1049 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
1050 node->add_property ("sample-rate", buf);
1052 if (session_dirs.size() > 1) {
1056 vector<space_and_path>::iterator i = session_dirs.begin();
1057 vector<space_and_path>::iterator next;
1059 ++i; /* skip the first one */
1063 while (i != session_dirs.end()) {
1067 if (next != session_dirs.end()) {
1068 p += G_SEARCHPATH_SEPARATOR;
1077 child = node->add_child ("Path");
1078 child->add_content (p);
1082 /* save the ID counter */
1084 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1085 node->add_property ("id-counter", buf);
1087 /* save the event ID counter */
1089 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1090 node->add_property ("event-counter", buf);
1092 /* various options */
1094 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
1095 if (!midi_port_nodes.empty()) {
1096 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
1097 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
1098 midi_port_stuff->add_child_nocopy (**n);
1100 node->add_child_nocopy (*midi_port_stuff);
1103 node->add_child_nocopy (config.get_variables ());
1105 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1107 child = node->add_child ("Sources");
1110 Glib::Threads::Mutex::Lock sl (source_lock);
1112 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1114 /* Don't save information about non-file Sources, or
1115 * about non-destructive file sources that are empty
1116 * and unused by any regions.
1119 boost::shared_ptr<FileSource> fs;
1121 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1123 if (!fs->destructive()) {
1124 if (fs->empty() && !fs->used()) {
1129 child->add_child_nocopy (siter->second->get_state());
1134 child = node->add_child ("Regions");
1137 Glib::Threads::Mutex::Lock rl (region_lock);
1138 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1139 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1140 boost::shared_ptr<Region> r = i->second;
1141 /* only store regions not attached to playlists */
1142 if (r->playlist() == 0) {
1143 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1144 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1146 child->add_child_nocopy (r->get_state ());
1151 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1153 if (!cassocs.empty()) {
1154 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1156 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1158 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1159 i->first->id().print (buf, sizeof (buf));
1160 can->add_property (X_("copy"), buf);
1161 i->second->id().print (buf, sizeof (buf));
1162 can->add_property (X_("original"), buf);
1163 ca->add_child_nocopy (*can);
1173 node->add_child_nocopy (_locations->get_state());
1176 Locations loc (*this);
1177 // for a template, just create a new Locations, populate it
1178 // with the default start and end, and get the state for that.
1179 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1180 range->set (max_framepos, 0);
1182 XMLNode& locations_state = loc.get_state();
1184 if (ARDOUR::Profile->get_trx() && _locations) {
1185 // For tracks we need stored the Auto Loop Range and all MIDI markers.
1186 for (Locations::LocationList::const_iterator i = _locations->list ().begin (); i != _locations->list ().end (); ++i) {
1187 if ((*i)->is_mark () || (*i)->is_auto_loop ()) {
1188 locations_state.add_child_nocopy ((*i)->get_state ());
1192 node->add_child_nocopy (locations_state);
1195 child = node->add_child ("Bundles");
1197 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1198 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1199 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1201 child->add_child_nocopy (b->get_state());
1206 child = node->add_child ("Routes");
1208 boost::shared_ptr<RouteList> r = routes.reader ();
1210 RoutePublicOrderSorter cmp;
1211 RouteList public_order (*r);
1212 public_order.sort (cmp);
1214 /* the sort should have put control outs first */
1217 assert (_monitor_out == public_order.front());
1220 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1221 if (!(*i)->is_auditioner()) {
1223 child->add_child_nocopy ((*i)->get_state());
1225 child->add_child_nocopy ((*i)->get_template());
1231 playlists->add_state (node, full_state);
1233 child = node->add_child ("RouteGroups");
1234 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1235 child->add_child_nocopy ((*i)->get_state());
1239 XMLNode* gain_child = node->add_child ("Click");
1240 gain_child->add_child_nocopy (_click_io->state (full_state));
1241 gain_child->add_child_nocopy (_click_gain->state (full_state));
1245 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1246 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1250 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1251 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1254 node->add_child_nocopy (_speakers->get_state());
1255 node->add_child_nocopy (_tempo_map->get_state());
1256 node->add_child_nocopy (get_control_protocol_state());
1259 node->add_child_copy (*_extra_xml);
1263 Glib::Threads::Mutex::Lock lm (lua_lock);
1266 luabridge::LuaRef savedstate ((*_lua_save)());
1267 saved = savedstate.cast<std::string>();
1269 lua.collect_garbage ();
1272 gchar* b64 = g_base64_encode ((const guchar*)saved.c_str (), saved.size ());
1273 std::string b64s (b64);
1276 XMLNode* script_node = new XMLNode (X_("Script"));
1277 script_node->add_property (X_("lua"), LUA_VERSION);
1278 script_node->add_content (b64s);
1279 node->add_child_nocopy (*script_node);
1286 Session::get_control_protocol_state ()
1288 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1289 return cpm.get_state();
1293 Session::set_state (const XMLNode& node, int version)
1297 const XMLProperty* prop;
1300 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1302 if (node.name() != X_("Session")) {
1303 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1307 if ((prop = node.property ("name")) != 0) {
1308 _name = prop->value ();
1311 if ((prop = node.property (X_("sample-rate"))) != 0) {
1313 _nominal_frame_rate = atoi (prop->value());
1315 if (_nominal_frame_rate != _current_frame_rate) {
1316 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1317 if (r.get_value_or (0)) {
1323 setup_raid_path(_session_dir->root_path());
1325 if ((prop = node.property (X_("id-counter"))) != 0) {
1327 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1328 ID::init_counter (x);
1330 /* old sessions used a timebased counter, so fake
1331 the startup ID counter based on a standard
1336 ID::init_counter (now);
1339 if ((prop = node.property (X_("event-counter"))) != 0) {
1340 Evoral::init_event_id_counter (atoi (prop->value()));
1344 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1345 _midi_ports->set_midi_port_states (child->children());
1348 IO::disable_connecting ();
1350 Stateful::save_extra_xml (node);
1352 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1353 load_options (*child);
1354 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1355 load_options (*child);
1357 error << _("Session: XML state has no options section") << endmsg;
1360 if (version >= 3000) {
1361 if ((child = find_named_node (node, "Metadata")) == 0) {
1362 warning << _("Session: XML state has no metadata section") << endmsg;
1363 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1368 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1369 _speakers->set_state (*child, version);
1372 if ((child = find_named_node (node, "Sources")) == 0) {
1373 error << _("Session: XML state has no sources section") << endmsg;
1375 } else if (load_sources (*child)) {
1379 if ((child = find_named_node (node, "TempoMap")) == 0) {
1380 error << _("Session: XML state has no Tempo Map section") << endmsg;
1382 } else if (_tempo_map->set_state (*child, version)) {
1386 if ((child = find_named_node (node, "Locations")) == 0) {
1387 error << _("Session: XML state has no locations section") << endmsg;
1389 } else if (_locations->set_state (*child, version)) {
1393 locations_changed ();
1395 if (_session_range_location) {
1396 AudioFileSource::set_header_position_offset (_session_range_location->start());
1399 if ((child = find_named_node (node, "Regions")) == 0) {
1400 error << _("Session: XML state has no Regions section") << endmsg;
1402 } else if (load_regions (*child)) {
1406 if ((child = find_named_node (node, "Playlists")) == 0) {
1407 error << _("Session: XML state has no playlists section") << endmsg;
1409 } else if (playlists->load (*this, *child)) {
1413 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1415 } else if (playlists->load_unused (*this, *child)) {
1419 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1420 if (load_compounds (*child)) {
1425 if (version >= 3000) {
1426 if ((child = find_named_node (node, "Bundles")) == 0) {
1427 warning << _("Session: XML state has no bundles section") << endmsg;
1430 /* We can't load Bundles yet as they need to be able
1431 to convert from port names to Port objects, which can't happen until
1433 _bundle_xml_node = new XMLNode (*child);
1437 if (version < 3000) {
1438 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1439 error << _("Session: XML state has no diskstreams section") << endmsg;
1441 } else if (load_diskstreams_2X (*child, version)) {
1446 if ((child = find_named_node (node, "Routes")) == 0) {
1447 error << _("Session: XML state has no routes section") << endmsg;
1449 } else if (load_routes (*child, version)) {
1453 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1454 _diskstreams_2X.clear ();
1456 if (version >= 3000) {
1458 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1459 error << _("Session: XML state has no route groups section") << endmsg;
1461 } else if (load_route_groups (*child, version)) {
1465 } else if (version < 3000) {
1467 if ((child = find_named_node (node, "EditGroups")) == 0) {
1468 error << _("Session: XML state has no edit groups section") << endmsg;
1470 } else if (load_route_groups (*child, version)) {
1474 if ((child = find_named_node (node, "MixGroups")) == 0) {
1475 error << _("Session: XML state has no mix groups section") << endmsg;
1477 } else if (load_route_groups (*child, version)) {
1482 if ((child = find_named_node (node, "Click")) == 0) {
1483 warning << _("Session: XML state has no click section") << endmsg;
1484 } else if (_click_io) {
1485 setup_click_state (&node);
1488 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1489 ControlProtocolManager::instance().set_state (*child, version);
1492 if ((child = find_named_node (node, "Script"))) {
1493 for (XMLNodeList::const_iterator n = child->children ().begin (); n != child->children ().end (); ++n) {
1494 if (!(*n)->is_content ()) { continue; }
1496 guchar* buf = g_base64_decode ((*n)->content ().c_str (), &size);
1498 Glib::Threads::Mutex::Lock lm (lua_lock);
1499 (*_lua_load)(std::string ((const char*)buf, size));
1500 } catch (luabridge::LuaException const& e) {
1501 cerr << "LuaException:" << e.what () << endl;
1507 update_route_record_state ();
1509 /* here beginneth the second phase ... */
1510 set_snapshot_name (_current_snapshot_name);
1512 StateReady (); /* EMIT SIGNAL */
1525 Session::load_routes (const XMLNode& node, int version)
1528 XMLNodeConstIterator niter;
1529 RouteList new_routes;
1531 nlist = node.children();
1535 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1537 boost::shared_ptr<Route> route;
1538 if (version < 3000) {
1539 route = XMLRouteFactory_2X (**niter, version);
1541 route = XMLRouteFactory (**niter, version);
1545 error << _("Session: cannot create Route from XML description.") << endmsg;
1549 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1551 new_routes.push_back (route);
1554 BootMessage (_("Tracks/busses loaded; Adding to Session"));
1556 add_routes (new_routes, false, false, false);
1558 BootMessage (_("Finished adding tracks/busses"));
1563 boost::shared_ptr<Route>
1564 Session::XMLRouteFactory (const XMLNode& node, int version)
1566 boost::shared_ptr<Route> ret;
1568 if (node.name() != "Route") {
1572 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1574 DataType type = DataType::AUDIO;
1575 const XMLProperty* prop = node.property("default-type");
1578 type = DataType (prop->value());
1581 assert (type != DataType::NIL);
1585 boost::shared_ptr<Track> track;
1587 if (type == DataType::AUDIO) {
1588 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1590 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1593 if (track->init()) {
1597 if (track->set_state (node, version)) {
1601 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1602 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1607 enum Route::Flag flags = Route::Flag(0);
1608 const XMLProperty* prop = node.property("flags");
1610 flags = Route::Flag (string_2_enum (prop->value(), flags));
1613 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1615 if (r->init () == 0 && r->set_state (node, version) == 0) {
1616 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1617 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1626 boost::shared_ptr<Route>
1627 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1629 boost::shared_ptr<Route> ret;
1631 if (node.name() != "Route") {
1635 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1637 ds_prop = node.property (X_("diskstream"));
1640 DataType type = DataType::AUDIO;
1641 const XMLProperty* prop = node.property("default-type");
1644 type = DataType (prop->value());
1647 assert (type != DataType::NIL);
1651 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1652 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1656 if (i == _diskstreams_2X.end()) {
1657 error << _("Could not find diskstream for route") << endmsg;
1658 return boost::shared_ptr<Route> ();
1661 boost::shared_ptr<Track> track;
1663 if (type == DataType::AUDIO) {
1664 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1666 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1669 if (track->init()) {
1673 if (track->set_state (node, version)) {
1677 track->set_diskstream (*i);
1679 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1680 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1685 enum Route::Flag flags = Route::Flag(0);
1686 const XMLProperty* prop = node.property("flags");
1688 flags = Route::Flag (string_2_enum (prop->value(), flags));
1691 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1693 if (r->init () == 0 && r->set_state (node, version) == 0) {
1694 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1695 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1705 Session::load_regions (const XMLNode& node)
1708 XMLNodeConstIterator niter;
1709 boost::shared_ptr<Region> region;
1711 nlist = node.children();
1715 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1716 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1717 error << _("Session: cannot create Region from XML description.");
1718 const XMLProperty *name = (**niter).property("name");
1721 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1732 Session::load_compounds (const XMLNode& node)
1734 XMLNodeList calist = node.children();
1735 XMLNodeConstIterator caiter;
1736 XMLProperty *caprop;
1738 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1739 XMLNode* ca = *caiter;
1743 if ((caprop = ca->property (X_("original"))) == 0) {
1746 orig_id = caprop->value();
1748 if ((caprop = ca->property (X_("copy"))) == 0) {
1751 copy_id = caprop->value();
1753 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1754 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1756 if (!orig || !copy) {
1757 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1763 RegionFactory::add_compound_association (orig, copy);
1770 Session::load_nested_sources (const XMLNode& node)
1773 XMLNodeConstIterator niter;
1775 nlist = node.children();
1777 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1778 if ((*niter)->name() == "Source") {
1780 /* it may already exist, so don't recreate it unnecessarily
1783 XMLProperty* prop = (*niter)->property (X_("id"));
1785 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1789 ID source_id (prop->value());
1791 if (!source_by_id (source_id)) {
1794 SourceFactory::create (*this, **niter, true);
1796 catch (failed_constructor& err) {
1797 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1804 boost::shared_ptr<Region>
1805 Session::XMLRegionFactory (const XMLNode& node, bool full)
1807 const XMLProperty* type = node.property("type");
1811 const XMLNodeList& nlist = node.children();
1813 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1814 XMLNode *child = (*niter);
1815 if (child->name() == "NestedSource") {
1816 load_nested_sources (*child);
1820 if (!type || type->value() == "audio") {
1821 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1822 } else if (type->value() == "midi") {
1823 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1826 } catch (failed_constructor& err) {
1827 return boost::shared_ptr<Region> ();
1830 return boost::shared_ptr<Region> ();
1833 boost::shared_ptr<AudioRegion>
1834 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1836 const XMLProperty* prop;
1837 boost::shared_ptr<Source> source;
1838 boost::shared_ptr<AudioSource> as;
1840 SourceList master_sources;
1841 uint32_t nchans = 1;
1844 if (node.name() != X_("Region")) {
1845 return boost::shared_ptr<AudioRegion>();
1848 if ((prop = node.property (X_("channels"))) != 0) {
1849 nchans = atoi (prop->value().c_str());
1852 if ((prop = node.property ("name")) == 0) {
1853 cerr << "no name for this region\n";
1857 if ((prop = node.property (X_("source-0"))) == 0) {
1858 if ((prop = node.property ("source")) == 0) {
1859 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1860 return boost::shared_ptr<AudioRegion>();
1864 PBD::ID s_id (prop->value());
1866 if ((source = source_by_id (s_id)) == 0) {
1867 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1868 return boost::shared_ptr<AudioRegion>();
1871 as = boost::dynamic_pointer_cast<AudioSource>(source);
1873 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1874 return boost::shared_ptr<AudioRegion>();
1877 sources.push_back (as);
1879 /* pickup other channels */
1881 for (uint32_t n=1; n < nchans; ++n) {
1882 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1883 if ((prop = node.property (buf)) != 0) {
1885 PBD::ID id2 (prop->value());
1887 if ((source = source_by_id (id2)) == 0) {
1888 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1889 return boost::shared_ptr<AudioRegion>();
1892 as = boost::dynamic_pointer_cast<AudioSource>(source);
1894 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1895 return boost::shared_ptr<AudioRegion>();
1897 sources.push_back (as);
1901 for (uint32_t n = 0; n < nchans; ++n) {
1902 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1903 if ((prop = node.property (buf)) != 0) {
1905 PBD::ID id2 (prop->value());
1907 if ((source = source_by_id (id2)) == 0) {
1908 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1909 return boost::shared_ptr<AudioRegion>();
1912 as = boost::dynamic_pointer_cast<AudioSource>(source);
1914 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1915 return boost::shared_ptr<AudioRegion>();
1917 master_sources.push_back (as);
1922 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1924 /* a final detail: this is the one and only place that we know how long missing files are */
1926 if (region->whole_file()) {
1927 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1928 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1930 sfp->set_length (region->length());
1935 if (!master_sources.empty()) {
1936 if (master_sources.size() != nchans) {
1937 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1939 region->set_master_sources (master_sources);
1947 catch (failed_constructor& err) {
1948 return boost::shared_ptr<AudioRegion>();
1952 boost::shared_ptr<MidiRegion>
1953 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1955 const XMLProperty* prop;
1956 boost::shared_ptr<Source> source;
1957 boost::shared_ptr<MidiSource> ms;
1960 if (node.name() != X_("Region")) {
1961 return boost::shared_ptr<MidiRegion>();
1964 if ((prop = node.property ("name")) == 0) {
1965 cerr << "no name for this region\n";
1969 if ((prop = node.property (X_("source-0"))) == 0) {
1970 if ((prop = node.property ("source")) == 0) {
1971 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1972 return boost::shared_ptr<MidiRegion>();
1976 PBD::ID s_id (prop->value());
1978 if ((source = source_by_id (s_id)) == 0) {
1979 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1980 return boost::shared_ptr<MidiRegion>();
1983 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1985 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1986 return boost::shared_ptr<MidiRegion>();
1989 sources.push_back (ms);
1992 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1993 /* a final detail: this is the one and only place that we know how long missing files are */
1995 if (region->whole_file()) {
1996 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1997 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1999 sfp->set_length (region->length());
2007 catch (failed_constructor& err) {
2008 return boost::shared_ptr<MidiRegion>();
2013 Session::get_sources_as_xml ()
2016 XMLNode* node = new XMLNode (X_("Sources"));
2017 Glib::Threads::Mutex::Lock lm (source_lock);
2019 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2020 node->add_child_nocopy (i->second->get_state());
2027 Session::reset_write_sources (bool mark_write_complete, bool force)
2029 boost::shared_ptr<RouteList> rl = routes.reader();
2030 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
2031 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
2033 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
2034 tr->reset_write_sources(mark_write_complete, force);
2035 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
2041 Session::load_sources (const XMLNode& node)
2044 XMLNodeConstIterator niter;
2045 boost::shared_ptr<Source> source; /* don't need this but it stops some
2046 * versions of gcc complaining about
2047 * discarded return values.
2050 nlist = node.children();
2054 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2057 if ((source = XMLSourceFactory (**niter)) == 0) {
2058 error << _("Session: cannot create Source from XML description.") << endmsg;
2061 } catch (MissingSource& err) {
2065 if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
2066 error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
2067 PROGRAM_NAME) << endmsg;
2071 if (!no_questions_about_missing_files) {
2072 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
2077 switch (user_choice) {
2079 /* user added a new search location, so try again */
2084 /* user asked to quit the entire session load
2089 no_questions_about_missing_files = true;
2093 no_questions_about_missing_files = true;
2100 case DataType::AUDIO:
2101 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
2104 case DataType::MIDI:
2105 /* The MIDI file is actually missing so
2106 * just create a new one in the same
2107 * location. Do not announce its
2111 if (!Glib::path_is_absolute (err.path)) {
2112 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
2114 /* this should be an unrecoverable error: we would be creating a MIDI file outside
2119 /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
2120 source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
2121 /* reset ID to match the missing one */
2122 source->set_id (**niter);
2123 /* Now we can announce it */
2124 SourceFactory::SourceCreated (source);
2135 boost::shared_ptr<Source>
2136 Session::XMLSourceFactory (const XMLNode& node)
2138 if (node.name() != "Source") {
2139 return boost::shared_ptr<Source>();
2143 /* note: do peak building in another thread when loading session state */
2144 return SourceFactory::create (*this, node, true);
2147 catch (failed_constructor& err) {
2148 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
2149 return boost::shared_ptr<Source>();
2154 Session::save_template (string template_name, bool replace_existing)
2156 if ((_state_of_the_state & CannotSave) || template_name.empty ()) {
2160 bool absolute_path = Glib::path_is_absolute (template_name);
2162 /* directory to put the template in */
2163 std::string template_dir_path;
2165 if (!absolute_path) {
2166 std::string user_template_dir(user_template_directory());
2168 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2169 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2170 user_template_dir, g_strerror (errno)) << endmsg;
2174 template_dir_path = Glib::build_filename (user_template_dir, template_name);
2176 template_dir_path = template_name;
2179 if (!ARDOUR::Profile->get_trx()) {
2180 if (!replace_existing && Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2181 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2182 template_dir_path) << endmsg;
2186 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2187 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2188 template_dir_path, g_strerror (errno)) << endmsg;
2194 std::string template_file_path;
2196 if (ARDOUR::Profile->get_trx()) {
2197 template_file_path = template_name;
2199 if (absolute_path) {
2200 template_file_path = Glib::build_filename (template_dir_path, Glib::path_get_basename (template_dir_path) + template_suffix);
2202 template_file_path = Glib::build_filename (template_dir_path, template_name + template_suffix);
2206 SessionSaveUnderway (); /* EMIT SIGNAL */
2211 PBD::Unwinder<std::string> uw (_template_state_dir, template_dir_path);
2212 tree.set_root (&get_template());
2215 if (!tree.write (template_file_path)) {
2216 error << _("template not saved") << endmsg;
2220 store_recent_templates (template_file_path);
2226 Session::refresh_disk_space ()
2228 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2230 Glib::Threads::Mutex::Lock lm (space_lock);
2232 /* get freespace on every FS that is part of the session path */
2234 _total_free_4k_blocks = 0;
2235 _total_free_4k_blocks_uncertain = false;
2237 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2239 struct statfs statfsbuf;
2240 statfs (i->path.c_str(), &statfsbuf);
2242 double const scale = statfsbuf.f_bsize / 4096.0;
2244 /* See if this filesystem is read-only */
2245 struct statvfs statvfsbuf;
2246 statvfs (i->path.c_str(), &statvfsbuf);
2248 /* f_bavail can be 0 if it is undefined for whatever
2249 filesystem we are looking at; Samba shares mounted
2250 via GVFS are an example of this.
2252 if (statfsbuf.f_bavail == 0) {
2253 /* block count unknown */
2255 i->blocks_unknown = true;
2256 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2257 /* read-only filesystem */
2259 i->blocks_unknown = false;
2261 /* read/write filesystem with known space */
2262 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2263 i->blocks_unknown = false;
2266 _total_free_4k_blocks += i->blocks;
2267 if (i->blocks_unknown) {
2268 _total_free_4k_blocks_uncertain = true;
2271 #elif defined PLATFORM_WINDOWS
2272 vector<string> scanned_volumes;
2273 vector<string>::iterator j;
2274 vector<space_and_path>::iterator i;
2275 DWORD nSectorsPerCluster, nBytesPerSector,
2276 nFreeClusters, nTotalClusters;
2280 _total_free_4k_blocks = 0;
2282 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2283 strncpy (disk_drive, (*i).path.c_str(), 3);
2287 volume_found = false;
2288 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2290 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2291 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2292 i->blocks = (uint32_t)(nFreeBytes / 4096);
2294 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2295 if (0 == j->compare(disk_drive)) {
2296 volume_found = true;
2301 if (!volume_found) {
2302 scanned_volumes.push_back(disk_drive);
2303 _total_free_4k_blocks += i->blocks;
2308 if (0 == _total_free_4k_blocks) {
2309 strncpy (disk_drive, path().c_str(), 3);
2312 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2314 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2315 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2316 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2323 Session::get_best_session_directory_for_new_audio ()
2325 vector<space_and_path>::iterator i;
2326 string result = _session_dir->root_path();
2328 /* handle common case without system calls */
2330 if (session_dirs.size() == 1) {
2334 /* OK, here's the algorithm we're following here:
2336 We want to select which directory to use for
2337 the next file source to be created. Ideally,
2338 we'd like to use a round-robin process so as to
2339 get maximum performance benefits from splitting
2340 the files across multiple disks.
2342 However, in situations without much diskspace, an
2343 RR approach may end up filling up a filesystem
2344 with new files while others still have space.
2345 Its therefore important to pay some attention to
2346 the freespace in the filesystem holding each
2347 directory as well. However, if we did that by
2348 itself, we'd keep creating new files in the file
2349 system with the most space until it was as full
2350 as all others, thus negating any performance
2351 benefits of this RAID-1 like approach.
2353 So, we use a user-configurable space threshold. If
2354 there are at least 2 filesystems with more than this
2355 much space available, we use RR selection between them.
2356 If not, then we pick the filesystem with the most space.
2358 This gets a good balance between the two
2362 refresh_disk_space ();
2364 int free_enough = 0;
2366 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2367 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2372 if (free_enough >= 2) {
2373 /* use RR selection process, ensuring that the one
2377 i = last_rr_session_dir;
2380 if (++i == session_dirs.end()) {
2381 i = session_dirs.begin();
2384 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2385 SessionDirectory sdir(i->path);
2386 if (sdir.create ()) {
2388 last_rr_session_dir = i;
2393 } while (i != last_rr_session_dir);
2397 /* pick FS with the most freespace (and that
2398 seems to actually work ...)
2401 vector<space_and_path> sorted;
2402 space_and_path_ascending_cmp cmp;
2404 sorted = session_dirs;
2405 sort (sorted.begin(), sorted.end(), cmp);
2407 for (i = sorted.begin(); i != sorted.end(); ++i) {
2408 SessionDirectory sdir(i->path);
2409 if (sdir.create ()) {
2411 last_rr_session_dir = i;
2421 Session::automation_dir () const
2423 return Glib::build_filename (_path, automation_dir_name);
2427 Session::analysis_dir () const
2429 return Glib::build_filename (_path, analysis_dir_name);
2433 Session::plugins_dir () const
2435 return Glib::build_filename (_path, plugins_dir_name);
2439 Session::externals_dir () const
2441 return Glib::build_filename (_path, externals_dir_name);
2445 Session::load_bundles (XMLNode const & node)
2447 XMLNodeList nlist = node.children();
2448 XMLNodeConstIterator niter;
2452 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2453 if ((*niter)->name() == "InputBundle") {
2454 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2455 } else if ((*niter)->name() == "OutputBundle") {
2456 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2458 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2467 Session::load_route_groups (const XMLNode& node, int version)
2469 XMLNodeList nlist = node.children();
2470 XMLNodeConstIterator niter;
2474 if (version >= 3000) {
2476 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2477 if ((*niter)->name() == "RouteGroup") {
2478 RouteGroup* rg = new RouteGroup (*this, "");
2479 add_route_group (rg);
2480 rg->set_state (**niter, version);
2484 } else if (version < 3000) {
2486 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2487 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2488 RouteGroup* rg = new RouteGroup (*this, "");
2489 add_route_group (rg);
2490 rg->set_state (**niter, version);
2499 state_file_filter (const string &str, void* /*arg*/)
2501 return (str.length() > strlen(statefile_suffix) &&
2502 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2506 remove_end(string state)
2508 string statename(state);
2510 string::size_type start,end;
2511 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2512 statename = statename.substr (start+1);
2515 if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2516 end = statename.length();
2519 return string(statename.substr (0, end));
2523 Session::possible_states (string path)
2525 vector<string> states;
2526 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2528 transform(states.begin(), states.end(), states.begin(), remove_end);
2530 sort (states.begin(), states.end());
2536 Session::possible_states () const
2538 return possible_states(_path);
2542 Session::add_route_group (RouteGroup* g)
2544 _route_groups.push_back (g);
2545 route_group_added (g); /* EMIT SIGNAL */
2547 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2548 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2549 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2555 Session::remove_route_group (RouteGroup& rg)
2557 list<RouteGroup*>::iterator i;
2559 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2560 _route_groups.erase (i);
2563 route_group_removed (); /* EMIT SIGNAL */
2567 /** Set a new order for our route groups, without adding or removing any.
2568 * @param groups Route group list in the new order.
2571 Session::reorder_route_groups (list<RouteGroup*> groups)
2573 _route_groups = groups;
2575 route_groups_reordered (); /* EMIT SIGNAL */
2581 Session::route_group_by_name (string name)
2583 list<RouteGroup *>::iterator i;
2585 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2586 if ((*i)->name() == name) {
2594 Session::all_route_group() const
2596 return *_all_route_group;
2600 Session::add_commands (vector<Command*> const & cmds)
2602 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2608 Session::add_command (Command* const cmd)
2610 assert (_current_trans);
2611 DEBUG_UNDO_HISTORY (
2612 string_compose ("Current Undo Transaction %1, adding command: %2",
2613 _current_trans->name (),
2615 _current_trans->add_command (cmd);
2618 PBD::StatefulDiffCommand*
2619 Session::add_stateful_diff_command (boost::shared_ptr<PBD::StatefulDestructible> sfd)
2621 PBD::StatefulDiffCommand* cmd = new PBD::StatefulDiffCommand (sfd);
2627 Session::begin_reversible_command (const string& name)
2629 begin_reversible_command (g_quark_from_string (name.c_str ()));
2632 /** Begin a reversible command using a GQuark to identify it.
2633 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2634 * but there must be as many begin...()s as there are commit...()s.
2637 Session::begin_reversible_command (GQuark q)
2639 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2640 to hold all the commands that are committed. This keeps the order of
2641 commands correct in the history.
2644 if (_current_trans == 0) {
2645 DEBUG_UNDO_HISTORY (string_compose (
2646 "Begin Reversible Command, new transaction: %1", g_quark_to_string (q)));
2648 /* start a new transaction */
2649 assert (_current_trans_quarks.empty ());
2650 _current_trans = new UndoTransaction();
2651 _current_trans->set_name (g_quark_to_string (q));
2653 DEBUG_UNDO_HISTORY (
2654 string_compose ("Begin Reversible Command, current transaction: %1",
2655 _current_trans->name ()));
2658 _current_trans_quarks.push_front (q);
2662 Session::abort_reversible_command ()
2664 if (_current_trans != 0) {
2665 DEBUG_UNDO_HISTORY (
2666 string_compose ("Abort Reversible Command: %1", _current_trans->name ()));
2667 _current_trans->clear();
2668 delete _current_trans;
2670 _current_trans_quarks.clear();
2675 Session::commit_reversible_command (Command *cmd)
2677 assert (_current_trans);
2678 assert (!_current_trans_quarks.empty ());
2683 DEBUG_UNDO_HISTORY (
2684 string_compose ("Current Undo Transaction %1, adding command: %2",
2685 _current_trans->name (),
2687 _current_trans->add_command (cmd);
2690 DEBUG_UNDO_HISTORY (
2691 string_compose ("Commit Reversible Command, current transaction: %1",
2692 _current_trans->name ()));
2694 _current_trans_quarks.pop_front ();
2696 if (!_current_trans_quarks.empty ()) {
2697 DEBUG_UNDO_HISTORY (
2698 string_compose ("Commit Reversible Command, transaction is not "
2699 "top-level, current transaction: %1",
2700 _current_trans->name ()));
2701 /* the transaction we're committing is not the top-level one */
2705 if (_current_trans->empty()) {
2706 /* no commands were added to the transaction, so just get rid of it */
2707 DEBUG_UNDO_HISTORY (
2708 string_compose ("Commit Reversible Command, No commands were "
2709 "added to current transaction: %1",
2710 _current_trans->name ()));
2711 delete _current_trans;
2716 gettimeofday (&now, 0);
2717 _current_trans->set_timestamp (now);
2719 _history.add (_current_trans);
2724 accept_all_audio_files (const string& path, void* /*arg*/)
2726 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2730 if (!AudioFileSource::safe_audio_file_extension (path)) {
2738 accept_all_midi_files (const string& path, void* /*arg*/)
2740 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2744 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2745 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2746 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2750 accept_all_state_files (const string& path, void* /*arg*/)
2752 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2756 std::string const statefile_ext (statefile_suffix);
2757 if (path.length() >= statefile_ext.length()) {
2758 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2765 Session::find_all_sources (string path, set<string>& result)
2770 if (!tree.read (path)) {
2774 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2779 XMLNodeConstIterator niter;
2781 nlist = node->children();
2785 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2789 if ((prop = (*niter)->property (X_("type"))) == 0) {
2793 DataType type (prop->value());
2795 if ((prop = (*niter)->property (X_("name"))) == 0) {
2799 if (Glib::path_is_absolute (prop->value())) {
2800 /* external file, ignore */
2808 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2809 result.insert (found_path);
2817 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2819 vector<string> state_files;
2821 string this_snapshot_path;
2827 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2828 ripped = ripped.substr (0, ripped.length() - 1);
2831 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2833 if (state_files.empty()) {
2838 this_snapshot_path = _path;
2839 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2840 this_snapshot_path += statefile_suffix;
2842 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2844 if (exclude_this_snapshot && *i == this_snapshot_path) {
2848 if (find_all_sources (*i, result) < 0) {
2856 struct RegionCounter {
2857 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2858 AudioSourceList::iterator iter;
2859 boost::shared_ptr<Region> region;
2862 RegionCounter() : count (0) {}
2866 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2868 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2869 return r.get_value_or (1);
2873 Session::cleanup_regions ()
2875 bool removed = false;
2876 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2878 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2880 uint32_t used = playlists->region_use_count (i->second);
2882 if (used == 0 && !i->second->automatic ()) {
2883 boost::weak_ptr<Region> w = i->second;
2886 RegionFactory::map_remove (w);
2893 // re-check to remove parent references of compound regions
2894 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end();) {
2895 if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2899 assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2900 if (0 == playlists->region_use_count (i->second)) {
2901 boost::weak_ptr<Region> w = i->second;
2903 RegionFactory::map_remove (w);
2910 /* dump the history list */
2917 Session::can_cleanup_peakfiles () const
2919 if (deletion_in_progress()) {
2922 if (!_writable || (_state_of_the_state & CannotSave)) {
2923 warning << _("Cannot cleanup peak-files for read-only session.") << endmsg;
2926 if (record_status() == Recording) {
2927 error << _("Cannot cleanup peak-files while recording") << endmsg;
2934 Session::cleanup_peakfiles ()
2936 Glib::Threads::Mutex::Lock lm (peak_cleanup_lock, Glib::Threads::TRY_LOCK);
2941 assert (can_cleanup_peakfiles ());
2942 assert (!peaks_cleanup_in_progres());
2944 _state_of_the_state = StateOfTheState (_state_of_the_state | PeakCleanup);
2946 int timeout = 5000; // 5 seconds
2947 while (!SourceFactory::files_with_peaks.empty()) {
2948 Glib::usleep (1000);
2949 if (--timeout < 0) {
2950 warning << _("Timeout waiting for peak-file creation to terminate before cleanup, please try again later.") << endmsg;
2951 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
2956 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2957 boost::shared_ptr<AudioSource> as;
2958 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
2959 as->close_peakfile();
2963 PBD::clear_directory (session_directory().peak_path());
2965 _state_of_the_state = StateOfTheState (_state_of_the_state & (~PeakCleanup));
2967 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
2968 boost::shared_ptr<AudioSource> as;
2969 if ((as = boost::dynamic_pointer_cast<AudioSource> (i->second)) != 0) {
2970 SourceFactory::setup_peakfile(as, true);
2977 Session::cleanup_sources (CleanupReport& rep)
2979 // FIXME: needs adaptation to midi
2981 vector<boost::shared_ptr<Source> > dead_sources;
2984 vector<string> candidates;
2985 vector<string> unused;
2986 set<string> all_sources;
2995 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2997 /* this is mostly for windows which doesn't allow file
2998 * renaming if the file is in use. But we don't special
2999 * case it because we need to know if this causes
3000 * problems, and the easiest way to notice that is to
3001 * keep it in place for all platforms.
3004 request_stop (false);
3006 _butler->wait_until_finished ();
3008 /* consider deleting all unused playlists */
3010 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
3015 /* sync the "all regions" property of each playlist with its current state
3018 playlists->sync_all_regions_with_regions ();
3020 /* find all un-used sources */
3025 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3027 SourceMap::iterator tmp;
3032 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
3036 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
3037 dead_sources.push_back (i->second);
3038 i->second->drop_references ();
3044 /* build a list of all the possible audio directories for the session */
3046 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3047 SessionDirectory sdir ((*i).path);
3048 asp += sdir.sound_path();
3050 audio_path += asp.to_string();
3053 /* build a list of all the possible midi directories for the session */
3055 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3056 SessionDirectory sdir ((*i).path);
3057 msp += sdir.midi_path();
3059 midi_path += msp.to_string();
3061 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
3062 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
3064 /* find all sources, but don't use this snapshot because the
3065 state file on disk still references sources we may have already
3069 find_all_sources_across_snapshots (all_sources, true);
3071 /* add our current source list
3074 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
3075 boost::shared_ptr<FileSource> fs;
3076 SourceMap::iterator tmp = i;
3079 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
3081 /* this is mostly for windows which doesn't allow file
3082 * renaming if the file is in use. But we don't special
3083 * case it because we need to know if this causes
3084 * problems, and the easiest way to notice that is to
3085 * keep it in place for all platforms.
3090 if (!fs->is_stub()) {
3092 if (playlists->source_use_count (fs) != 0) {
3093 all_sources.insert (fs->path());
3096 /* we might not remove this source from disk, because it may be used
3097 by other snapshots, but its not being used in this version
3098 so lets get rid of it now, along with any representative regions
3102 RegionFactory::remove_regions_using_source (i->second);
3104 // also remove source from all_sources
3106 for (set<string>::iterator j = all_sources.begin(); j != all_sources.end(); ++j) {
3107 spath = Glib::path_get_basename (*j);
3108 if (spath == i->second->name()) {
3109 all_sources.erase (j);
3122 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
3127 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
3129 tmppath1 = canonical_path (spath);
3130 tmppath2 = canonical_path ((*i));
3132 if (tmppath1 == tmppath2) {
3139 unused.push_back (spath);
3143 /* now try to move all unused files into the "dead" directory(ies) */
3145 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
3150 /* don't move the file across filesystems, just
3151 stick it in the `dead_dir_name' directory
3152 on whichever filesystem it was already on.
3155 if ((*x).find ("/sounds/") != string::npos) {
3157 /* old school, go up 1 level */
3159 newpath = Glib::path_get_dirname (*x); // "sounds"
3160 newpath = Glib::path_get_dirname (newpath); // "session-name"
3164 /* new school, go up 4 levels */
3166 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
3167 newpath = Glib::path_get_dirname (newpath); // "session-name"
3168 newpath = Glib::path_get_dirname (newpath); // "interchange"
3169 newpath = Glib::path_get_dirname (newpath); // "session-dir"
3172 newpath = Glib::build_filename (newpath, dead_dir_name);
3174 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
3175 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
3179 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
3181 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
3183 /* the new path already exists, try versioning */
3185 char buf[PATH_MAX+1];
3189 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
3192 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
3193 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
3197 if (version == 999) {
3198 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
3202 newpath = newpath_v;
3207 /* it doesn't exist, or we can't read it or something */
3211 g_stat ((*x).c_str(), &statbuf);
3213 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
3214 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
3215 (*x), newpath, strerror (errno))
3220 /* see if there an easy to find peakfile for this file, and remove it.
3223 string base = Glib::path_get_basename (*x);
3224 base += "%A"; /* this is what we add for the channel suffix of all native files,
3225 or for the first channel of embedded files. it will miss
3226 some peakfiles for other channels
3228 string peakpath = construct_peak_filepath (base);
3230 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
3231 if (::g_unlink (peakpath.c_str()) != 0) {
3232 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3233 peakpath, _path, strerror (errno))
3235 /* try to back out */
3236 ::rename (newpath.c_str(), _path.c_str());
3241 rep.paths.push_back (*x);
3242 rep.space += statbuf.st_size;
3245 /* dump the history list */
3249 /* save state so we don't end up a session file
3250 referring to non-existent sources.
3257 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3263 Session::cleanup_trash_sources (CleanupReport& rep)
3265 // FIXME: needs adaptation for MIDI
3267 vector<space_and_path>::iterator i;
3273 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3275 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
3277 clear_directory (dead_dir, &rep.space, &rep.paths);
3284 Session::set_dirty ()
3286 /* never mark session dirty during loading */
3288 if (_state_of_the_state & Loading) {
3292 bool was_dirty = dirty();
3294 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3298 DirtyChanged(); /* EMIT SIGNAL */
3304 Session::set_clean ()
3306 bool was_dirty = dirty();
3308 _state_of_the_state = Clean;
3312 DirtyChanged(); /* EMIT SIGNAL */
3317 Session::set_deletion_in_progress ()
3319 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3323 Session::clear_deletion_in_progress ()
3325 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3329 Session::add_controllable (boost::shared_ptr<Controllable> c)
3331 /* this adds a controllable to the list managed by the Session.
3332 this is a subset of those managed by the Controllable class
3333 itself, and represents the only ones whose state will be saved
3334 as part of the session.
3337 Glib::Threads::Mutex::Lock lm (controllables_lock);
3338 controllables.insert (c);
3341 struct null_deleter { void operator()(void const *) const {} };
3344 Session::remove_controllable (Controllable* c)
3346 if (_state_of_the_state & Deletion) {
3350 Glib::Threads::Mutex::Lock lm (controllables_lock);
3352 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3354 if (x != controllables.end()) {
3355 controllables.erase (x);
3359 boost::shared_ptr<Controllable>
3360 Session::controllable_by_id (const PBD::ID& id)
3362 Glib::Threads::Mutex::Lock lm (controllables_lock);
3364 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3365 if ((*i)->id() == id) {
3370 return boost::shared_ptr<Controllable>();
3373 boost::shared_ptr<Controllable>
3374 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3376 boost::shared_ptr<Controllable> c;
3377 boost::shared_ptr<Route> r;
3379 switch (desc.top_level_type()) {
3380 case ControllableDescriptor::NamedRoute:
3382 std::string str = desc.top_level_name();
3383 if (str == "Master" || str == "master") {
3385 } else if (str == "control" || str == "listen") {
3388 r = route_by_name (desc.top_level_name());
3393 case ControllableDescriptor::RemoteControlID:
3394 r = route_by_remote_id (desc.rid());
3397 case ControllableDescriptor::SelectionCount:
3398 r = route_by_selected_count (desc.selection_id());
3406 switch (desc.subtype()) {
3407 case ControllableDescriptor::Gain:
3408 c = r->gain_control ();
3411 case ControllableDescriptor::Trim:
3412 c = r->trim()->gain_control ();
3415 case ControllableDescriptor::Solo:
3416 c = r->solo_control();
3419 case ControllableDescriptor::Mute:
3420 c = r->mute_control();
3423 case ControllableDescriptor::Recenable:
3425 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3428 c = t->rec_enable_control ();
3433 case ControllableDescriptor::PanDirection:
3434 c = r->pan_azimuth_control();
3437 case ControllableDescriptor::PanWidth:
3438 c = r->pan_width_control();
3441 case ControllableDescriptor::PanElevation:
3442 c = r->pan_elevation_control();
3445 case ControllableDescriptor::Balance:
3446 /* XXX simple pan control */
3449 case ControllableDescriptor::PluginParameter:
3451 uint32_t plugin = desc.target (0);
3452 uint32_t parameter_index = desc.target (1);
3454 /* revert to zero based counting */
3460 if (parameter_index > 0) {
3464 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3467 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3468 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3473 case ControllableDescriptor::SendGain: {
3474 uint32_t send = desc.target (0);
3478 c = r->send_level_controllable (send);
3483 /* relax and return a null pointer */
3491 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3494 Stateful::add_instant_xml (node, _path);
3497 if (write_to_config) {
3498 Config->add_instant_xml (node);
3503 Session::instant_xml (const string& node_name)
3505 return Stateful::instant_xml (node_name, _path);
3509 Session::save_history (string snapshot_name)
3517 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3518 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3522 if (snapshot_name.empty()) {
3523 snapshot_name = _current_snapshot_name;
3526 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3527 const string backup_filename = history_filename + backup_suffix;
3528 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3529 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3531 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3532 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3533 error << _("could not backup old history file, current history not saved") << endmsg;
3538 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3540 if (!tree.write (xml_path))
3542 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3544 if (g_remove (xml_path.c_str()) != 0) {
3545 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3546 xml_path, g_strerror (errno)) << endmsg;
3548 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3549 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3550 backup_path, g_strerror (errno)) << endmsg;
3560 Session::restore_history (string snapshot_name)
3564 if (snapshot_name.empty()) {
3565 snapshot_name = _current_snapshot_name;
3568 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3569 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3571 info << "Loading history from " << xml_path << endmsg;
3573 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3574 info << string_compose (_("%1: no history file \"%2\" for this session."),
3575 _name, xml_path) << endmsg;
3579 if (!tree.read (xml_path)) {
3580 error << string_compose (_("Could not understand session history file \"%1\""),
3581 xml_path) << endmsg;
3588 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3591 UndoTransaction* ut = new UndoTransaction ();
3594 ut->set_name(t->property("name")->value());
3595 stringstream ss(t->property("tv-sec")->value());
3597 ss.str(t->property("tv-usec")->value());
3599 ut->set_timestamp(tv);
3601 for (XMLNodeConstIterator child_it = t->children().begin();
3602 child_it != t->children().end(); child_it++)
3604 XMLNode *n = *child_it;
3607 if (n->name() == "MementoCommand" ||
3608 n->name() == "MementoUndoCommand" ||
3609 n->name() == "MementoRedoCommand") {
3611 if ((c = memento_command_factory(n))) {
3615 } else if (n->name() == "NoteDiffCommand") {
3616 PBD::ID id (n->property("midi-source")->value());
3617 boost::shared_ptr<MidiSource> midi_source =
3618 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3620 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3622 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3625 } else if (n->name() == "SysExDiffCommand") {
3627 PBD::ID id (n->property("midi-source")->value());
3628 boost::shared_ptr<MidiSource> midi_source =
3629 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3631 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3633 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3636 } else if (n->name() == "PatchChangeDiffCommand") {
3638 PBD::ID id (n->property("midi-source")->value());
3639 boost::shared_ptr<MidiSource> midi_source =
3640 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3642 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3644 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3647 } else if (n->name() == "StatefulDiffCommand") {
3648 if ((c = stateful_diff_command_factory (n))) {
3649 ut->add_command (c);
3652 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3663 Session::config_changed (std::string p, bool ours)
3669 if (p == "seamless-loop") {
3671 } else if (p == "rf-speed") {
3673 } else if (p == "auto-loop") {
3675 } else if (p == "auto-input") {
3677 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3678 /* auto-input only makes a difference if we're rolling */
3679 set_track_monitor_input_status (!config.get_auto_input());
3682 } else if (p == "punch-in") {
3686 if ((location = _locations->auto_punch_location()) != 0) {
3688 if (config.get_punch_in ()) {
3689 replace_event (SessionEvent::PunchIn, location->start());
3691 remove_event (location->start(), SessionEvent::PunchIn);
3695 } else if (p == "punch-out") {
3699 if ((location = _locations->auto_punch_location()) != 0) {
3701 if (config.get_punch_out()) {
3702 replace_event (SessionEvent::PunchOut, location->end());
3704 clear_events (SessionEvent::PunchOut);
3708 } else if (p == "edit-mode") {
3710 Glib::Threads::Mutex::Lock lm (playlists->lock);
3712 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3713 (*i)->set_edit_mode (Config->get_edit_mode ());
3716 } else if (p == "use-video-sync") {
3718 waiting_for_sync_offset = config.get_use_video_sync();
3720 } else if (p == "mmc-control") {
3722 //poke_midi_thread ();
3724 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3726 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3728 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3730 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3732 } else if (p == "midi-control") {
3734 //poke_midi_thread ();
3736 } else if (p == "raid-path") {
3738 setup_raid_path (config.get_raid_path());
3740 } else if (p == "timecode-format") {
3744 } else if (p == "video-pullup") {
3748 } else if (p == "seamless-loop") {
3750 if (play_loop && transport_rolling()) {
3751 // to reset diskstreams etc
3752 request_play_loop (true);
3755 } else if (p == "rf-speed") {
3757 cumulative_rf_motion = 0;
3760 } else if (p == "click-sound") {
3762 setup_click_sounds (1);
3764 } else if (p == "click-emphasis-sound") {
3766 setup_click_sounds (-1);
3768 } else if (p == "clicking") {
3770 if (Config->get_clicking()) {
3771 if (_click_io && click_data) { // don't require emphasis data
3778 } else if (p == "click-gain") {
3781 _click_gain->gain_control()->set_value (Config->get_click_gain(), Controllable::NoGroup);
3784 } else if (p == "send-mtc") {
3786 if (Config->get_send_mtc ()) {
3787 /* mark us ready to send */
3788 next_quarter_frame_to_send = 0;
3791 } else if (p == "send-mmc") {
3793 _mmc->enable_send (Config->get_send_mmc ());
3795 } else if (p == "midi-feedback") {
3797 session_midi_feedback = Config->get_midi_feedback();
3799 } else if (p == "jack-time-master") {
3801 engine().reset_timebase ();
3803 } else if (p == "native-file-header-format") {
3805 if (!first_file_header_format_reset) {
3806 reset_native_file_format ();
3809 first_file_header_format_reset = false;
3811 } else if (p == "native-file-data-format") {
3813 if (!first_file_data_format_reset) {
3814 reset_native_file_format ();
3817 first_file_data_format_reset = false;
3819 } else if (p == "external-sync") {
3820 if (!config.get_external_sync()) {
3821 drop_sync_source ();
3823 switch_to_sync_source (Config->get_sync_source());
3825 } else if (p == "denormal-model") {
3827 } else if (p == "history-depth") {
3828 set_history_depth (Config->get_history_depth());
3829 } else if (p == "remote-model") {
3830 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3833 } else if (p == "initial-program-change") {
3835 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3838 buf[0] = MIDI::program; // channel zero by default
3839 buf[1] = (Config->get_initial_program_change() & 0x7f);
3841 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3843 } else if (p == "solo-mute-override") {
3844 // catch_up_on_solo_mute_override ();
3845 } else if (p == "listen-position" || p == "pfl-position") {
3846 listen_position_changed ();
3847 } else if (p == "solo-control-is-listen-control") {
3848 solo_control_mode_changed ();
3849 } else if (p == "solo-mute-gain") {
3850 _solo_cut_control->Changed();
3851 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3852 last_timecode_valid = false;
3853 } else if (p == "playback-buffer-seconds") {
3854 AudioSource::allocate_working_buffers (frame_rate());
3855 } else if (p == "ltc-source-port") {
3856 reconnect_ltc_input ();
3857 } else if (p == "ltc-sink-port") {
3858 reconnect_ltc_output ();
3859 } else if (p == "timecode-generator-offset") {
3860 ltc_tx_parse_offset();
3861 } else if (p == "auto-return-target-list") {
3862 follow_playhead_priority ();
3869 Session::set_history_depth (uint32_t d)
3871 _history.set_depth (d);
3875 Session::load_diskstreams_2X (XMLNode const & node, int)
3878 XMLNodeConstIterator citer;
3880 clist = node.children();
3882 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3885 /* diskstreams added automatically by DiskstreamCreated handler */
3886 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3887 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3888 _diskstreams_2X.push_back (dsp);
3890 error << _("Session: unknown diskstream type in XML") << endmsg;
3894 catch (failed_constructor& err) {
3895 error << _("Session: could not load diskstream via XML state") << endmsg;
3903 /** Connect things to the MMC object */
3905 Session::setup_midi_machine_control ()
3907 _mmc = new MIDI::MachineControl;
3909 boost::shared_ptr<AsyncMIDIPort> async_in = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_input_port());
3910 boost::shared_ptr<AsyncMIDIPort> async_out = boost::dynamic_pointer_cast<AsyncMIDIPort> (_midi_ports->mmc_output_port());
3912 if (!async_out || !async_out) {
3916 /* XXXX argh, passing raw pointers back into libmidi++ */
3918 MIDI::Port* mmc_in = async_in.get();
3919 MIDI::Port* mmc_out = async_out.get();
3921 _mmc->set_ports (mmc_in, mmc_out);
3923 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3924 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3925 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3926 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3927 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3928 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3929 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3930 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3931 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3932 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3933 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3934 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3935 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3937 /* also handle MIDI SPP because its so common */
3939 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3940 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3941 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3944 boost::shared_ptr<Controllable>
3945 Session::solo_cut_control() const
3947 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3948 controls in Ardour that currently get presented to the user in the GUI that require
3949 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3951 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3952 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3956 return _solo_cut_control;
3960 Session::save_snapshot_name (const std::string & n)
3962 /* assure Stateful::_instant_xml is loaded
3963 * add_instant_xml() only adds to existing data and defaults
3964 * to use an empty Tree otherwise
3966 instant_xml ("LastUsedSnapshot");
3968 XMLNode* last_used_snapshot = new XMLNode ("LastUsedSnapshot");
3969 last_used_snapshot->add_property ("name", string(n));
3970 add_instant_xml (*last_used_snapshot, false);
3974 Session::set_snapshot_name (const std::string & n)
3976 _current_snapshot_name = n;
3977 save_snapshot_name (n);
3981 Session::rename (const std::string& new_name)
3983 string legal_name = legalize_for_path (new_name);
3989 string const old_sources_root = _session_dir->sources_root();
3991 if (!_writable || (_state_of_the_state & CannotSave)) {
3992 error << _("Cannot rename read-only session.") << endmsg;
3993 return 0; // don't show "messed up" warning
3995 if (record_status() == Recording) {
3996 error << _("Cannot rename session while recording") << endmsg;
3997 return 0; // don't show "messed up" warning
4000 StateProtector stp (this);
4005 * interchange subdirectory
4009 * Backup files are left unchanged and not renamed.
4012 /* Windows requires that we close all files before attempting the
4013 * rename. This works on other platforms, but isn't necessary there.
4014 * Leave it in place for all platforms though, since it may help
4015 * catch issues that could arise if the way Source files work ever
4016 * change (since most developers are not using Windows).
4019 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4020 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4026 /* pass one: not 100% safe check that the new directory names don't
4030 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4034 /* this is a stupid hack because Glib::path_get_dirname() is
4035 * lexical-only, and so passing it /a/b/c/ gives a different
4036 * result than passing it /a/b/c ...
4039 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4040 oldstr = oldstr.substr (0, oldstr.length() - 1);
4043 string base = Glib::path_get_dirname (oldstr);
4045 newstr = Glib::build_filename (base, legal_name);
4047 cerr << "Looking for " << newstr << endl;
4049 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
4050 cerr << " exists\n";
4059 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
4065 /* this is a stupid hack because Glib::path_get_dirname() is
4066 * lexical-only, and so passing it /a/b/c/ gives a different
4067 * result than passing it /a/b/c ...
4070 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
4071 oldstr = oldstr.substr (0, oldstr.length() - 1);
4074 string base = Glib::path_get_dirname (oldstr);
4075 newstr = Glib::build_filename (base, legal_name);
4077 cerr << "for " << oldstr << " new dir = " << newstr << endl;
4079 cerr << "Rename " << oldstr << " => " << newstr << endl;
4080 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4081 cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4082 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4086 /* Reset path in "session dirs" */
4091 /* reset primary SessionDirectory object */
4094 (*_session_dir) = newstr;
4099 /* now rename directory below session_dir/interchange */
4101 string old_interchange_dir;
4102 string new_interchange_dir;
4104 /* use newstr here because we renamed the path
4105 * (folder/directory) that used to be oldstr to newstr above
4108 v.push_back (newstr);
4109 v.push_back (interchange_dir_name);
4110 v.push_back (Glib::path_get_basename (oldstr));
4112 old_interchange_dir = Glib::build_filename (v);
4115 v.push_back (newstr);
4116 v.push_back (interchange_dir_name);
4117 v.push_back (legal_name);
4119 new_interchange_dir = Glib::build_filename (v);
4121 cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
4123 if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
4124 cerr << string_compose (_("renaming %s as %2 failed (%3)"),
4125 old_interchange_dir, new_interchange_dir,
4128 error << string_compose (_("renaming %s as %2 failed (%3)"),
4129 old_interchange_dir, new_interchange_dir,
4138 oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
4139 newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
4141 cerr << "Rename " << oldstr << " => " << newstr << endl;
4143 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4144 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4145 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4151 oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
4153 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
4154 newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
4156 cerr << "Rename " << oldstr << " => " << newstr << endl;
4158 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
4159 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
4160 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
4165 /* remove old name from recent sessions */
4166 remove_recent_sessions (_path);
4169 /* update file source paths */
4171 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
4172 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4174 string p = fs->path ();
4175 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
4177 SourceFactory::setup_peakfile(i->second, true);
4181 set_snapshot_name (new_name);
4186 /* save state again to get everything just right */
4188 save_state (_current_snapshot_name);
4190 /* add to recent sessions */
4192 store_recent_sessions (new_name, _path);
4198 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
4200 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
4204 if (!tree.read (xmlpath)) {
4212 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
4215 bool found_sr = false;
4216 bool found_data_format = false;
4218 if (get_session_info_from_path (tree, xmlpath)) {
4224 const XMLProperty* prop;
4225 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
4226 sample_rate = atoi (prop->value());
4230 const XMLNodeList& children (tree.root()->children());
4231 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
4232 const XMLNode* child = *c;
4233 if (child->name() == "Config") {
4234 const XMLNodeList& options (child->children());
4235 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
4236 const XMLNode* option = *oc;
4237 const XMLProperty* name = option->property("name");
4243 if (name->value() == "native-file-data-format") {
4244 const XMLProperty* value = option->property ("value");
4246 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
4248 found_data_format = true;
4254 if (found_data_format) {
4259 return !(found_sr && found_data_format); // zero if they are both found
4263 Session::get_snapshot_from_instant (const std::string& session_dir)
4265 std::string instant_xml_path = Glib::build_filename (session_dir, "instant.xml");
4267 if (!Glib::file_test (instant_xml_path, Glib::FILE_TEST_EXISTS)) {
4272 if (!tree.read (instant_xml_path)) {
4276 const XMLProperty* prop;
4277 XMLNode *last_used_snapshot = tree.root()->child("LastUsedSnapshot");
4278 if (last_used_snapshot && (prop = last_used_snapshot->property ("name")) != 0) {
4279 return prop->value();
4285 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
4286 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
4289 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
4293 SourcePathMap source_path_map;
4295 boost::shared_ptr<AudioFileSource> afs;
4300 Glib::Threads::Mutex::Lock lm (source_lock);
4302 cerr << " total sources = " << sources.size();
4304 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4305 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4311 if (fs->within_session()) {
4315 if (source_path_map.find (fs->path()) != source_path_map.end()) {
4316 source_path_map[fs->path()].push_back (fs);
4318 SeveralFileSources v;
4320 source_path_map.insert (make_pair (fs->path(), v));
4326 cerr << " fsources = " << total << endl;
4328 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
4330 /* tell caller where we are */
4332 string old_path = i->first;
4334 callback (n, total, old_path);
4336 cerr << old_path << endl;
4340 switch (i->second.front()->type()) {
4341 case DataType::AUDIO:
4342 new_path = new_audio_source_path_for_embedded (old_path);
4345 case DataType::MIDI:
4346 /* XXX not implemented yet */
4350 if (new_path.empty()) {
4354 cerr << "Move " << old_path << " => " << new_path << endl;
4356 if (!copy_file (old_path, new_path)) {
4357 cerr << "failed !\n";
4361 /* make sure we stop looking in the external
4362 dir/folder. Remember, this is an all-or-nothing
4363 operations, it doesn't merge just some files.
4365 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
4367 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
4368 (*f)->set_path (new_path);
4373 save_state ("", false, false);
4379 bool accept_all_files (string const &, void *)
4385 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4387 /* 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.
4392 make_new_media_path (string old_path, string new_session_folder, string new_session_path)
4394 /* typedir is the "midifiles" or "audiofiles" etc. part of the path. */
4396 string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4398 v.push_back (new_session_folder); /* full path */
4399 v.push_back (interchange_dir_name);
4400 v.push_back (new_session_path); /* just one directory/folder */
4401 v.push_back (typedir);
4402 v.push_back (Glib::path_get_basename (old_path));
4404 return Glib::build_filename (v);
4408 Session::save_as (SaveAs& saveas)
4410 vector<string> files;
4411 string current_folder = Glib::path_get_dirname (_path);
4412 string new_folder = legalize_for_path (saveas.new_name);
4413 string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4414 int64_t total_bytes = 0;
4418 int32_t internal_file_cnt = 0;
4420 vector<string> do_not_copy_extensions;
4421 do_not_copy_extensions.push_back (statefile_suffix);
4422 do_not_copy_extensions.push_back (pending_suffix);
4423 do_not_copy_extensions.push_back (backup_suffix);
4424 do_not_copy_extensions.push_back (temp_suffix);
4425 do_not_copy_extensions.push_back (history_suffix);
4427 /* get total size */
4429 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4431 /* need to clear this because
4432 * find_files_matching_filter() is cumulative
4437 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4439 all += files.size();
4441 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4443 g_stat ((*i).c_str(), &gsb);
4444 total_bytes += gsb.st_size;
4448 /* save old values so we can switch back if we are not switching to the new session */
4450 string old_path = _path;
4451 string old_name = _name;
4452 string old_snapshot = _current_snapshot_name;
4453 string old_sd = _session_dir->root_path();
4454 vector<string> old_search_path[DataType::num_types];
4455 string old_config_search_path[DataType::num_types];
4457 old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4458 old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4459 old_config_search_path[DataType::AUDIO] = config.get_audio_search_path ();
4460 old_config_search_path[DataType::MIDI] = config.get_midi_search_path ();
4462 /* switch session directory */
4464 (*_session_dir) = to_dir;
4466 /* create new tree */
4468 if (!_session_dir->create()) {
4469 saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4474 /* copy all relevant files. Find each location in session_dirs,
4475 * and copy files from there to target.
4478 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4480 /* need to clear this because
4481 * find_files_matching_filter() is cumulative
4486 const size_t prefix_len = (*sd).path.size();
4488 /* Work just on the files within this session dir */
4490 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4492 /* add dir separator to protect against collisions with
4493 * track names (e.g. track named "audiofiles" or
4497 static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
4498 static const std::string midifile_dir_string = string (midi_dir_name) + G_DIR_SEPARATOR;
4499 static const std::string analysis_dir_string = analysis_dir() + G_DIR_SEPARATOR;
4501 /* copy all the files. Handling is different for media files
4502 than others because of the *silly* subtree we have below the interchange
4503 folder. That really was a bad idea, but I'm not fixing it as part of
4504 implementing ::save_as().
4507 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4509 std::string from = *i;
4512 string filename = Glib::path_get_basename (from);
4513 std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
4514 if (filename == ".DS_STORE") {
4519 if (from.find (audiofile_dir_string) != string::npos) {
4521 /* audio file: only copy if asked */
4523 if (saveas.include_media && saveas.copy_media) {
4525 string to = make_new_media_path (*i, to_dir, new_folder);
4527 info << "media file copying from " << from << " to " << to << endmsg;
4529 if (!copy_file (from, to)) {
4530 throw Glib::FileError (Glib::FileError::IO_ERROR,
4531 string_compose(_("\ncopying \"%1\" failed !"), from));
4535 /* we found media files inside the session folder */
4537 internal_file_cnt++;
4539 } else if (from.find (midifile_dir_string) != string::npos) {
4541 /* midi file: always copy unless
4542 * creating an empty new session
4545 if (saveas.include_media) {
4547 string to = make_new_media_path (*i, to_dir, new_folder);
4549 info << "media file copying from " << from << " to " << to << endmsg;
4551 if (!copy_file (from, to)) {
4552 throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4556 /* we found media files inside the session folder */
4558 internal_file_cnt++;
4560 } else if (from.find (analysis_dir_string) != string::npos) {
4562 /* make sure analysis dir exists in
4563 * new session folder, but we're not
4564 * copying analysis files here, see
4568 (void) g_mkdir_with_parents (analysis_dir().c_str(), 775);
4573 /* normal non-media file. Don't copy state, history, etc.
4576 bool do_copy = true;
4578 for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
4579 if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
4580 /* end of filename matches extension, do not copy file */
4586 if (!saveas.copy_media && from.find (peakfile_suffix) != string::npos) {
4587 /* don't copy peakfiles if
4588 * we're not copying media
4594 string to = Glib::build_filename (to_dir, from.substr (prefix_len));
4596 info << "attempting to make directory/folder " << to << endmsg;
4598 if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
4599 throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
4602 info << "attempting to copy " << from << " to " << to << endmsg;
4604 if (!copy_file (from, to)) {
4605 throw Glib::FileError (Glib::FileError::IO_ERROR,
4606 string_compose(_("\ncopying \"%1\" failed !"), from));
4611 /* measure file size even if we're not going to copy so that our Progress
4612 signals are correct, since we included these do-not-copy files
4613 in the computation of the total size and file count.
4617 g_stat (from.c_str(), &gsb);
4618 copied += gsb.st_size;
4621 double fraction = (double) copied / total_bytes;
4623 bool keep_going = true;
4625 if (saveas.copy_media) {
4627 /* no need or expectation of this if
4628 * media is not being copied, because
4629 * it will be fast(ish).
4632 /* tell someone "X percent, file M of N"; M is one-based */
4634 boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
4642 throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
4648 /* copy optional folders, if any */
4650 string old = plugins_dir ();
4651 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4652 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4653 copy_files (old, newdir);
4656 old = externals_dir ();
4657 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4658 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4659 copy_files (old, newdir);
4662 old = automation_dir ();
4663 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4664 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4665 copy_files (old, newdir);
4668 if (saveas.include_media) {
4670 if (saveas.copy_media) {
4671 #ifndef PLATFORM_WINDOWS
4672 /* There are problems with analysis files on
4673 * Windows, because they used a colon in their
4674 * names as late as 4.0. Colons are not legal
4675 * under Windows even if NTFS allows them.
4677 * This is a tricky problem to solve so for
4678 * just don't copy these files. They will be
4679 * regenerated as-needed anyway, subject to the
4680 * existing issue that the filenames will be
4681 * rejected by Windows, which is a separate
4682 * problem (though related).
4685 /* only needed if we are copying media, since the
4686 * analysis data refers to media data
4689 old = analysis_dir ();
4690 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4691 string newdir = Glib::build_filename (to_dir, "analysis");
4692 copy_files (old, newdir);
4694 #endif /* PLATFORM_WINDOWS */
4700 set_snapshot_name (saveas.new_name);
4701 _name = saveas.new_name;
4703 if (saveas.include_media && !saveas.copy_media) {
4705 /* reset search paths of the new session (which we're pretending to be right now) to
4706 include the original session search path, so we can still find all audio.
4709 if (internal_file_cnt) {
4710 for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
4711 ensure_search_path_includes (*s, DataType::AUDIO);
4712 cerr << "be sure to include " << *s << " for audio" << endl;
4715 /* we do not do this for MIDI because we copy
4716 all MIDI files if saveas.include_media is
4722 bool was_dirty = dirty ();
4724 save_state ("", false, false, !saveas.include_media);
4725 save_default_options ();
4727 if (saveas.copy_media && saveas.copy_external) {
4728 if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
4729 throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
4733 saveas.final_session_folder_name = _path;
4735 store_recent_sessions (_name, _path);
4737 if (!saveas.switch_to) {
4739 /* switch back to the way things were */
4743 set_snapshot_name (old_snapshot);
4745 (*_session_dir) = old_sd;
4751 if (internal_file_cnt) {
4752 /* reset these to their original values */
4753 config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
4754 config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
4759 /* prune session dirs, and update disk space statistics
4764 session_dirs.clear ();
4765 session_dirs.push_back (sp);
4766 refresh_disk_space ();
4768 /* ensure that all existing tracks reset their current capture source paths
4770 reset_write_sources (true, true);
4772 /* the copying above was based on actually discovering files, not just iterating over the sources list.
4773 But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
4776 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4777 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4783 if (fs->within_session()) {
4784 string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
4785 fs->set_path (newpath);
4790 } catch (Glib::FileError& e) {
4792 saveas.failure_message = e.what();
4794 /* recursively remove all the directories */
4796 remove_directory (to_dir);
4804 saveas.failure_message = _("unknown reason");
4806 /* recursively remove all the directories */
4808 remove_directory (to_dir);