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"
31 #include <cstdio> /* snprintf(3) ... grrr */
44 #include <sys/param.h>
45 #include <sys/mount.h>
48 #ifdef HAVE_SYS_STATVFS_H
49 #include <sys/statvfs.h>
53 #include <glib/gstdio.h>
56 #include <glibmm/threads.h>
57 #include <glibmm/fileutils.h>
59 #include <boost/algorithm/string.hpp>
61 #include "midi++/mmc.h"
62 #include "midi++/port.h"
64 #include "evoral/SMF.hpp"
66 #include "pbd/boost_debug.h"
67 #include "pbd/basename.h"
68 #include "pbd/controllable_descriptor.h"
69 #include "pbd/enumwriter.h"
70 #include "pbd/error.h"
71 #include "pbd/file_utils.h"
72 #include "pbd/pathexpand.h"
73 #include "pbd/pthread_utils.h"
74 #include "pbd/stacktrace.h"
75 #include "pbd/convert.h"
76 #include "pbd/localtime_r.h"
78 #include "ardour/amp.h"
79 #include "ardour/async_midi_port.h"
80 #include "ardour/audio_diskstream.h"
81 #include "ardour/audio_track.h"
82 #include "ardour/audioengine.h"
83 #include "ardour/audiofilesource.h"
84 #include "ardour/audioregion.h"
85 #include "ardour/automation_control.h"
86 #include "ardour/butler.h"
87 #include "ardour/control_protocol_manager.h"
88 #include "ardour/directory_names.h"
89 #include "ardour/filename_extensions.h"
90 #include "ardour/graph.h"
91 #include "ardour/location.h"
92 #include "ardour/midi_model.h"
93 #include "ardour/midi_patch_manager.h"
94 #include "ardour/midi_region.h"
95 #include "ardour/midi_scene_changer.h"
96 #include "ardour/midi_source.h"
97 #include "ardour/midi_track.h"
98 #include "ardour/pannable.h"
99 #include "ardour/playlist_factory.h"
100 #include "ardour/playlist_source.h"
101 #include "ardour/port.h"
102 #include "ardour/processor.h"
103 #include "ardour/profile.h"
104 #include "ardour/proxy_controllable.h"
105 #include "ardour/recent_sessions.h"
106 #include "ardour/region_factory.h"
107 #include "ardour/route_group.h"
108 #include "ardour/send.h"
109 #include "ardour/session.h"
110 #include "ardour/session_directory.h"
111 #include "ardour/session_metadata.h"
112 #include "ardour/session_playlists.h"
113 #include "ardour/session_state_utils.h"
114 #include "ardour/silentfilesource.h"
115 #include "ardour/sndfilesource.h"
116 #include "ardour/source_factory.h"
117 #include "ardour/speakers.h"
118 #include "ardour/template_utils.h"
119 #include "ardour/tempo.h"
120 #include "ardour/ticker.h"
121 #include "ardour/user_bundle.h"
123 #include "control_protocol/control_protocol.h"
129 using namespace ARDOUR;
133 Session::pre_engine_init (string fullpath)
135 if (fullpath.empty()) {
137 throw failed_constructor();
140 /* discover canonical fullpath */
142 _path = canonical_path(fullpath);
146 _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
148 /* finish initialization that can't be done in a normal C++ constructor
152 timerclear (&last_mmc_step);
153 g_atomic_int_set (&processing_prohibited, 0);
154 g_atomic_int_set (&_record_status, Disabled);
155 g_atomic_int_set (&_playback_load, 100);
156 g_atomic_int_set (&_capture_load, 100);
158 _all_route_group->set_active (true, this);
159 interpolation.add_channel_to (0, 0);
161 if (config.get_use_video_sync()) {
162 waiting_for_sync_offset = true;
164 waiting_for_sync_offset = false;
167 last_rr_session_dir = session_dirs.begin();
169 set_history_depth (Config->get_history_depth());
171 /* default: assume simple stereo speaker configuration */
173 _speakers->setup_default_speakers (2);
175 _solo_cut_control.reset (new ProxyControllable (_("solo cut control (dB)"), PBD::Controllable::GainLike,
176 boost::bind (&RCConfiguration::set_solo_mute_gain, Config, _1),
177 boost::bind (&RCConfiguration::get_solo_mute_gain, Config)));
178 add_controllable (_solo_cut_control);
180 /* These are all static "per-class" signals */
182 SourceFactory::SourceCreated.connect_same_thread (*this, boost::bind (&Session::add_source, this, _1));
183 PlaylistFactory::PlaylistCreated.connect_same_thread (*this, boost::bind (&Session::add_playlist, this, _1, _2));
184 AutomationList::AutomationListCreated.connect_same_thread (*this, boost::bind (&Session::add_automation_list, this, _1));
185 Controllable::Destroyed.connect_same_thread (*this, boost::bind (&Session::remove_controllable, this, _1));
186 IO::PortCountChanged.connect_same_thread (*this, boost::bind (&Session::ensure_buffers, this, _1));
188 /* stop IO objects from doing stuff until we're ready for them */
190 Delivery::disable_panners ();
191 IO::disable_connecting ();
193 AudioFileSource::set_peak_dir (_session_dir->peak_path());
197 Session::post_engine_init ()
199 BootMessage (_("Set block size and sample rate"));
201 set_block_size (_engine.samples_per_cycle());
202 set_frame_rate (_engine.sample_rate());
204 BootMessage (_("Using configuration"));
206 _midi_ports = new MidiPortManager;
208 MIDISceneChanger* msc;
210 _scene_changer = msc = new MIDISceneChanger (*this);
211 msc->set_input_port (scene_input_port());
212 msc->set_output_port (scene_out());
214 boost::function<framecnt_t(void)> timer_func (boost::bind (&Session::audible_frame, this));
215 boost::dynamic_pointer_cast<AsyncMIDIPort>(scene_in())->set_timer (timer_func);
217 setup_midi_machine_control ();
219 if (_butler->start_thread()) {
223 if (start_midi_thread ()) {
227 setup_click_sounds (0);
228 setup_midi_control ();
230 _engine.Halted.connect_same_thread (*this, boost::bind (&Session::engine_halted, this));
231 _engine.Xrun.connect_same_thread (*this, boost::bind (&Session::xrun_recovery, this));
234 /* tempo map requires sample rate knowledge */
237 _tempo_map = new TempoMap (_current_frame_rate);
238 _tempo_map->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::tempo_map_changed, this, _1));
240 /* MidiClock requires a tempo map */
242 midi_clock = new MidiClockTicker ();
243 midi_clock->set_session (this);
245 /* crossfades require sample rate knowledge */
247 SndFileSource::setup_standard_crossfades (*this, frame_rate());
248 _engine.GraphReordered.connect_same_thread (*this, boost::bind (&Session::graph_reordered, this));
250 AudioDiskstream::allocate_working_buffers();
251 refresh_disk_space ();
253 /* we're finally ready to call set_state() ... all objects have
254 * been created, the engine is running.
258 if (set_state (*state_tree->root(), Stateful::loading_state_version)) {
262 // set_state() will call setup_raid_path(), but if it's a new session we need
263 // to call setup_raid_path() here.
264 setup_raid_path (_path);
269 boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
270 boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
272 Config->map_parameters (ff);
273 config.map_parameters (ft);
274 _butler->map_parameters ();
276 /* Reset all panners */
278 Delivery::reset_panners ();
280 /* this will cause the CPM to instantiate any protocols that are in use
281 * (or mandatory), which will pass it this Session, and then call
282 * set_state() on each instantiated protocol to match stored state.
285 ControlProtocolManager::instance().set_session (this);
287 /* This must be done after the ControlProtocolManager set_session above,
288 as it will set states for ports which the ControlProtocolManager creates.
291 // XXX set state of MIDI::Port's
292 // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
294 /* And this must be done after the MIDI::Manager::set_port_states as
295 * it will try to make connections whose details are loaded by set_port_states.
300 /* Let control protocols know that we are now all connected, so they
301 * could start talking to surfaces if they want to.
304 ControlProtocolManager::instance().midi_connectivity_established ();
306 if (_is_new && !no_auto_connect()) {
307 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
308 auto_connect_master_bus ();
311 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
313 /* update latencies */
315 initialize_latencies ();
317 _locations->added.connect_same_thread (*this, boost::bind (&Session::location_added, this, _1));
318 _locations->removed.connect_same_thread (*this, boost::bind (&Session::location_removed, this, _1));
319 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
321 } catch (AudioEngine::PortRegistrationFailure& err) {
322 /* handle this one in a different way than all others, so that its clear what happened */
323 error << err.what() << endmsg;
329 BootMessage (_("Reset Remote Controls"));
331 // send_full_time_code (0);
332 _engine.transport_locate (0);
334 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
335 send_immediate_mmc (MIDI::MachineControlCommand (Timecode::Time ()));
337 MIDI::Name::MidiPatchManager::instance().set_session (this);
340 /* initial program change will be delivered later; see ::config_changed() */
342 _state_of_the_state = Clean;
344 Port::set_connecting_blocked (false);
346 DirtyChanged (); /* EMIT SIGNAL */
350 } else if (state_was_pending) {
352 remove_pending_capture_state ();
353 state_was_pending = false;
356 /* Now, finally, we can fill the playback buffers */
358 BootMessage (_("Filling playback buffers"));
360 boost::shared_ptr<RouteList> rl = routes.reader();
361 for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
362 boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<Track> (*r);
363 if (trk && !trk->hidden()) {
364 trk->seek (_transport_frame, true);
372 Session::session_loaded ()
376 _state_of_the_state = Clean;
378 DirtyChanged (); /* EMIT SIGNAL */
382 } else if (state_was_pending) {
384 remove_pending_capture_state ();
385 state_was_pending = false;
388 /* Now, finally, we can fill the playback buffers */
390 BootMessage (_("Filling playback buffers"));
392 boost::shared_ptr<RouteList> rl = routes.reader();
393 for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
394 boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<Track> (*r);
395 if (trk && !trk->hidden()) {
396 trk->seek (_transport_frame, true);
402 Session::raid_path () const
404 Searchpath raid_search_path;
406 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
407 raid_search_path += (*i).path;
410 return raid_search_path.to_string ();
414 Session::setup_raid_path (string path)
423 session_dirs.clear ();
425 Searchpath search_path(path);
426 Searchpath sound_search_path;
427 Searchpath midi_search_path;
429 for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
431 sp.blocks = 0; // not needed
432 session_dirs.push_back (sp);
434 SessionDirectory sdir(sp.path);
436 sound_search_path += sdir.sound_path ();
437 midi_search_path += sdir.midi_path ();
440 // reset the round-robin soundfile path thingie
441 last_rr_session_dir = session_dirs.begin();
445 Session::path_is_within_session (const std::string& path)
447 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
448 if (PBD::path_is_within (i->path, path)) {
456 Session::ensure_subdirs ()
460 dir = session_directory().peak_path();
462 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
463 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
467 dir = session_directory().sound_path();
469 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
470 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
474 dir = session_directory().midi_path();
476 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
477 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
481 dir = session_directory().dead_path();
483 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
484 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
488 dir = session_directory().export_path();
490 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
491 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
495 dir = analysis_dir ();
497 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
498 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
502 dir = plugins_dir ();
504 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
505 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
509 dir = externals_dir ();
511 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
512 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
519 /** @param session_template directory containing session template, or empty.
520 * Caller must not hold process lock.
523 Session::create (const string& session_template, BusProfile* bus_profile)
525 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
526 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
530 if (ensure_subdirs ()) {
534 _writable = exists_and_writable (_path);
536 if (!session_template.empty()) {
537 std::string in_path = (ARDOUR::Profile->get_trx () ? session_template : session_template_dir_to_file (session_template));
539 ifstream in(in_path.c_str());
542 /* no need to call legalize_for_path() since the string
543 * in session_template is already a legal path name
545 string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
547 ofstream out(out_path.c_str());
553 if (!ARDOUR::Profile->get_trx()) {
554 /* Copy plugin state files from template to new session */
555 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
556 copy_recurse (template_plugins, plugins_dir ());
562 error << string_compose (_("Could not open %1 for writing session template"), out_path)
568 error << string_compose (_("Could not open session template %1 for reading"), in_path)
575 /* set initial start + end point */
577 _state_of_the_state = Clean;
579 /* set up Master Out and Control Out if necessary */
584 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
586 // Waves Tracks: always create master bus for Tracks
587 if (ARDOUR::Profile->get_trx() || bus_profile->master_out_channels) {
588 boost::shared_ptr<Route> r (new Route (*this, _("Master"), Route::MasterOut, DataType::AUDIO));
592 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
593 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
596 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
597 r->input()->ensure_io (count, false, this);
598 r->output()->ensure_io (count, false, this);
604 /* prohibit auto-connect to master, because there isn't one */
605 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
609 add_routes (rl, false, false, false);
612 // Waves Tracks: Skip this. Always use autoconnection for Tracks
613 if (!ARDOUR::Profile->get_trx()) {
615 /* this allows the user to override settings with an environment variable.
618 if (no_auto_connect()) {
619 bus_profile->input_ac = AutoConnectOption (0);
620 bus_profile->output_ac = AutoConnectOption (0);
623 Config->set_input_auto_connect (bus_profile->input_ac);
624 Config->set_output_auto_connect (bus_profile->output_ac);
628 if (Config->get_use_monitor_bus() && bus_profile) {
629 add_monitor_section ();
636 Session::maybe_write_autosave()
638 if (dirty() && record_status() != Recording) {
639 save_state("", true);
644 Session::remove_pending_capture_state ()
646 std::string pending_state_file_path(_session_dir->root_path());
648 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
650 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
652 if (g_remove (pending_state_file_path.c_str()) != 0) {
653 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
654 pending_state_file_path, g_strerror (errno)) << endmsg;
658 /** Rename a state file.
659 * @param old_name Old snapshot name.
660 * @param new_name New snapshot name.
663 Session::rename_state (string old_name, string new_name)
665 if (old_name == _current_snapshot_name || old_name == _name) {
666 /* refuse to rename the current snapshot or the "main" one */
670 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
671 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
673 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
674 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
676 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
677 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
678 old_name, new_name, g_strerror(errno)) << endmsg;
682 /** Remove a state file.
683 * @param snapshot_name Snapshot name.
686 Session::remove_state (string snapshot_name)
688 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
689 // refuse to remove the current snapshot or the "main" one
693 std::string xml_path(_session_dir->root_path());
695 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
697 if (!create_backup_file (xml_path)) {
698 // don't remove it if a backup can't be made
699 // create_backup_file will log the error.
704 if (g_remove (xml_path.c_str()) != 0) {
705 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
706 xml_path, g_strerror (errno)) << endmsg;
710 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
712 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot, bool template_only)
715 std::string xml_path(_session_dir->root_path());
717 /* prevent concurrent saves from different threads */
719 Glib::Threads::Mutex::Lock lm (save_state_lock);
721 if (!_writable || (_state_of_the_state & CannotSave)) {
725 if (g_atomic_int_get(&_suspend_save)) {
729 _save_queued = false;
731 if (!_engine.connected ()) {
732 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
738 /* tell sources we're saving first, in case they write out to a new file
739 * which should be saved with the state rather than the old one */
740 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
742 i->second->session_saved();
743 } catch (Evoral::SMF::FileError& e) {
744 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
748 SessionSaveUnderway (); /* EMIT SIGNAL */
751 tree.set_root (&get_template());
753 tree.set_root (&get_state());
756 if (snapshot_name.empty()) {
757 snapshot_name = _current_snapshot_name;
758 } else if (switch_to_snapshot) {
759 _current_snapshot_name = snapshot_name;
764 /* proper save: use statefile_suffix (.ardour in English) */
766 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
768 /* make a backup copy of the old file */
770 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
771 // create_backup_file will log the error
777 /* pending save: use pending_suffix (.pending in English) */
778 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
781 std::string tmp_path(_session_dir->root_path());
782 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
784 cerr << "actually writing state to " << tmp_path << endl;
786 if (!tree.write (tmp_path)) {
787 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
788 if (g_remove (tmp_path.c_str()) != 0) {
789 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
790 tmp_path, g_strerror (errno)) << endmsg;
796 cerr << "renaming state to " << xml_path << endl;
798 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
799 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
800 tmp_path, xml_path, g_strerror(errno)) << endmsg;
801 if (g_remove (tmp_path.c_str()) != 0) {
802 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
803 tmp_path, g_strerror (errno)) << endmsg;
811 save_history (snapshot_name);
813 bool was_dirty = dirty();
815 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
818 DirtyChanged (); /* EMIT SIGNAL */
821 StateSaved (snapshot_name); /* EMIT SIGNAL */
828 Session::restore_state (string snapshot_name)
830 if (load_state (snapshot_name) == 0) {
831 set_state (*state_tree->root(), Stateful::loading_state_version);
838 Session::load_state (string snapshot_name)
843 state_was_pending = false;
845 /* check for leftover pending state from a crashed capture attempt */
847 std::string xmlpath(_session_dir->root_path());
848 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
850 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
852 /* there is pending state from a crashed capture attempt */
854 boost::optional<int> r = AskAboutPendingState();
855 if (r.get_value_or (1)) {
856 state_was_pending = true;
860 if (!state_was_pending) {
861 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
864 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
865 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
866 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
867 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
872 state_tree = new XMLTree;
876 _writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
878 if (!state_tree->read (xmlpath)) {
879 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
885 XMLNode& root (*state_tree->root());
887 if (root.name() != X_("Session")) {
888 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
894 const XMLProperty* prop;
896 if ((prop = root.property ("version")) == 0) {
897 /* no version implies very old version of Ardour */
898 Stateful::loading_state_version = 1000;
900 if (prop->value().find ('.') != string::npos) {
901 /* old school version format */
902 if (prop->value()[0] == '2') {
903 Stateful::loading_state_version = 2000;
905 Stateful::loading_state_version = 3000;
908 Stateful::loading_state_version = atoi (prop->value());
912 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
914 std::string backup_path(_session_dir->root_path());
915 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
916 backup_path = Glib::build_filename (backup_path, backup_filename);
918 // only create a backup for a given statefile version once
920 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
922 VersionMismatch (xmlpath, backup_path);
924 if (!copy_file (xmlpath, backup_path)) {;
934 Session::load_options (const XMLNode& node)
936 LocaleGuard lg (X_("C"));
937 config.set_variables (node);
942 Session::save_default_options ()
944 return config.save_state();
954 Session::get_template()
956 /* if we don't disable rec-enable, diskstreams
957 will believe they need to store their capture
958 sources in their state node.
961 disable_record (false);
967 Session::state (bool full_state)
969 XMLNode* node = new XMLNode("Session");
973 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
974 node->add_property("version", buf);
976 /* store configuration settings */
980 node->add_property ("name", _name);
981 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
982 node->add_property ("sample-rate", buf);
984 if (session_dirs.size() > 1) {
988 vector<space_and_path>::iterator i = session_dirs.begin();
989 vector<space_and_path>::iterator next;
991 ++i; /* skip the first one */
995 while (i != session_dirs.end()) {
999 if (next != session_dirs.end()) {
1000 p += G_SEARCHPATH_SEPARATOR;
1009 child = node->add_child ("Path");
1010 child->add_content (p);
1014 /* save the ID counter */
1016 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1017 node->add_property ("id-counter", buf);
1019 /* save the event ID counter */
1021 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1022 node->add_property ("event-counter", buf);
1024 /* various options */
1026 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
1027 if (!midi_port_nodes.empty()) {
1028 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
1029 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
1030 midi_port_stuff->add_child_nocopy (**n);
1032 node->add_child_nocopy (*midi_port_stuff);
1035 node->add_child_nocopy (config.get_variables ());
1037 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1039 child = node->add_child ("Sources");
1042 Glib::Threads::Mutex::Lock sl (source_lock);
1044 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1046 /* Don't save information about non-file Sources, or
1047 * about non-destructive file sources that are empty
1048 * and unused by any regions.
1051 boost::shared_ptr<FileSource> fs;
1053 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1055 if (!fs->destructive()) {
1056 if (fs->empty() && !fs->used()) {
1061 child->add_child_nocopy (siter->second->get_state());
1066 child = node->add_child ("Regions");
1069 Glib::Threads::Mutex::Lock rl (region_lock);
1070 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1071 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1072 boost::shared_ptr<Region> r = i->second;
1073 /* only store regions not attached to playlists */
1074 if (r->playlist() == 0) {
1075 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1076 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1078 child->add_child_nocopy (r->get_state ());
1083 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1085 if (!cassocs.empty()) {
1086 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1088 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1090 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1091 i->first->id().print (buf, sizeof (buf));
1092 can->add_property (X_("copy"), buf);
1093 i->second->id().print (buf, sizeof (buf));
1094 can->add_property (X_("original"), buf);
1095 ca->add_child_nocopy (*can);
1105 node->add_child_nocopy (_locations->get_state());
1108 Locations loc (*this);
1109 // for a template, just create a new Locations, populate it
1110 // with the default start and end, and get the state for that.
1111 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1112 range->set (max_framepos, 0);
1114 XMLNode& locations_state = loc.get_state();
1116 if (ARDOUR::Profile->get_trx() && _locations) {
1117 // For tracks we need stored the Auto Loop Range and all MIDI markers.
1118 for (Locations::LocationList::const_iterator i = _locations->list ().begin (); i != _locations->list ().end (); ++i) {
1119 if ((*i)->is_mark () || (*i)->is_auto_loop ()) {
1120 locations_state.add_child_nocopy ((*i)->get_state ());
1124 node->add_child_nocopy (locations_state);
1127 child = node->add_child ("Bundles");
1129 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1130 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1131 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1133 child->add_child_nocopy (b->get_state());
1138 child = node->add_child ("Routes");
1140 boost::shared_ptr<RouteList> r = routes.reader ();
1142 RoutePublicOrderSorter cmp;
1143 RouteList public_order (*r);
1144 public_order.sort (cmp);
1146 /* the sort should have put control outs first */
1149 assert (_monitor_out == public_order.front());
1152 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1153 if (!(*i)->is_auditioner()) {
1155 child->add_child_nocopy ((*i)->get_state());
1157 child->add_child_nocopy ((*i)->get_template());
1163 playlists->add_state (node, full_state);
1165 child = node->add_child ("RouteGroups");
1166 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1167 child->add_child_nocopy ((*i)->get_state());
1171 XMLNode* gain_child = node->add_child ("Click");
1172 gain_child->add_child_nocopy (_click_io->state (full_state));
1173 gain_child->add_child_nocopy (_click_gain->state (full_state));
1177 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1178 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1182 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1183 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1186 node->add_child_nocopy (_speakers->get_state());
1187 node->add_child_nocopy (_tempo_map->get_state());
1188 node->add_child_nocopy (get_control_protocol_state());
1191 node->add_child_copy (*_extra_xml);
1198 Session::get_control_protocol_state ()
1200 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1201 return cpm.get_state();
1205 Session::set_state (const XMLNode& node, int version)
1209 const XMLProperty* prop;
1212 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1214 if (node.name() != X_("Session")) {
1215 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1219 if ((prop = node.property ("name")) != 0) {
1220 _name = prop->value ();
1223 if ((prop = node.property (X_("sample-rate"))) != 0) {
1225 _nominal_frame_rate = atoi (prop->value());
1227 if (_nominal_frame_rate != _current_frame_rate) {
1228 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1229 if (r.get_value_or (0)) {
1235 setup_raid_path(_session_dir->root_path());
1237 if ((prop = node.property (X_("id-counter"))) != 0) {
1239 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1240 ID::init_counter (x);
1242 /* old sessions used a timebased counter, so fake
1243 the startup ID counter based on a standard
1248 ID::init_counter (now);
1251 if ((prop = node.property (X_("event-counter"))) != 0) {
1252 Evoral::init_event_id_counter (atoi (prop->value()));
1256 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1257 _midi_ports->set_midi_port_states (child->children());
1260 IO::disable_connecting ();
1262 Stateful::save_extra_xml (node);
1264 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1265 load_options (*child);
1266 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1267 load_options (*child);
1269 error << _("Session: XML state has no options section") << endmsg;
1272 if (version >= 3000) {
1273 if ((child = find_named_node (node, "Metadata")) == 0) {
1274 warning << _("Session: XML state has no metadata section") << endmsg;
1275 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1280 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1281 _speakers->set_state (*child, version);
1284 if ((child = find_named_node (node, "Sources")) == 0) {
1285 error << _("Session: XML state has no sources section") << endmsg;
1287 } else if (load_sources (*child)) {
1291 if ((child = find_named_node (node, "TempoMap")) == 0) {
1292 error << _("Session: XML state has no Tempo Map section") << endmsg;
1294 } else if (_tempo_map->set_state (*child, version)) {
1298 if ((child = find_named_node (node, "Locations")) == 0) {
1299 error << _("Session: XML state has no locations section") << endmsg;
1301 } else if (_locations->set_state (*child, version)) {
1305 locations_changed ();
1307 if (_session_range_location) {
1308 AudioFileSource::set_header_position_offset (_session_range_location->start());
1311 if ((child = find_named_node (node, "Regions")) == 0) {
1312 error << _("Session: XML state has no Regions section") << endmsg;
1314 } else if (load_regions (*child)) {
1318 if ((child = find_named_node (node, "Playlists")) == 0) {
1319 error << _("Session: XML state has no playlists section") << endmsg;
1321 } else if (playlists->load (*this, *child)) {
1325 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1327 } else if (playlists->load_unused (*this, *child)) {
1331 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1332 if (load_compounds (*child)) {
1337 if (version >= 3000) {
1338 if ((child = find_named_node (node, "Bundles")) == 0) {
1339 warning << _("Session: XML state has no bundles section") << endmsg;
1342 /* We can't load Bundles yet as they need to be able
1343 to convert from port names to Port objects, which can't happen until
1345 _bundle_xml_node = new XMLNode (*child);
1349 if (version < 3000) {
1350 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1351 error << _("Session: XML state has no diskstreams section") << endmsg;
1353 } else if (load_diskstreams_2X (*child, version)) {
1358 if ((child = find_named_node (node, "Routes")) == 0) {
1359 error << _("Session: XML state has no routes section") << endmsg;
1361 } else if (load_routes (*child, version)) {
1365 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1366 _diskstreams_2X.clear ();
1368 if (version >= 3000) {
1370 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1371 error << _("Session: XML state has no route groups section") << endmsg;
1373 } else if (load_route_groups (*child, version)) {
1377 } else if (version < 3000) {
1379 if ((child = find_named_node (node, "EditGroups")) == 0) {
1380 error << _("Session: XML state has no edit groups section") << endmsg;
1382 } else if (load_route_groups (*child, version)) {
1386 if ((child = find_named_node (node, "MixGroups")) == 0) {
1387 error << _("Session: XML state has no mix groups section") << endmsg;
1389 } else if (load_route_groups (*child, version)) {
1394 if ((child = find_named_node (node, "Click")) == 0) {
1395 warning << _("Session: XML state has no click section") << endmsg;
1396 } else if (_click_io) {
1397 setup_click_state (&node);
1400 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1401 ControlProtocolManager::instance().set_state (*child, version);
1404 update_route_record_state ();
1406 /* here beginneth the second phase ... */
1408 StateReady (); /* EMIT SIGNAL */
1421 Session::load_routes (const XMLNode& node, int version)
1424 XMLNodeConstIterator niter;
1425 RouteList new_routes;
1427 nlist = node.children();
1431 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1433 boost::shared_ptr<Route> route;
1434 if (version < 3000) {
1435 route = XMLRouteFactory_2X (**niter, version);
1437 route = XMLRouteFactory (**niter, version);
1441 error << _("Session: cannot create Route from XML description.") << endmsg;
1445 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1447 new_routes.push_back (route);
1450 BootMessage (_("Tracks/busses loaded; Adding to Session"));
1452 add_routes (new_routes, false, false, false);
1454 BootMessage (_("Finished adding tracks/busses"));
1459 boost::shared_ptr<Route>
1460 Session::XMLRouteFactory (const XMLNode& node, int version)
1462 boost::shared_ptr<Route> ret;
1464 if (node.name() != "Route") {
1468 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1470 DataType type = DataType::AUDIO;
1471 const XMLProperty* prop = node.property("default-type");
1474 type = DataType (prop->value());
1477 assert (type != DataType::NIL);
1481 boost::shared_ptr<Track> track;
1483 if (type == DataType::AUDIO) {
1484 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1486 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1489 if (track->init()) {
1493 if (track->set_state (node, version)) {
1497 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1498 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1503 enum Route::Flag flags = Route::Flag(0);
1504 const XMLProperty* prop = node.property("flags");
1506 flags = Route::Flag (string_2_enum (prop->value(), flags));
1509 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1511 if (r->init () == 0 && r->set_state (node, version) == 0) {
1512 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1513 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1522 boost::shared_ptr<Route>
1523 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1525 boost::shared_ptr<Route> ret;
1527 if (node.name() != "Route") {
1531 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1533 ds_prop = node.property (X_("diskstream"));
1536 DataType type = DataType::AUDIO;
1537 const XMLProperty* prop = node.property("default-type");
1540 type = DataType (prop->value());
1543 assert (type != DataType::NIL);
1547 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1548 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1552 if (i == _diskstreams_2X.end()) {
1553 error << _("Could not find diskstream for route") << endmsg;
1554 return boost::shared_ptr<Route> ();
1557 boost::shared_ptr<Track> track;
1559 if (type == DataType::AUDIO) {
1560 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1562 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1565 if (track->init()) {
1569 if (track->set_state (node, version)) {
1573 track->set_diskstream (*i);
1575 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1576 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1581 enum Route::Flag flags = Route::Flag(0);
1582 const XMLProperty* prop = node.property("flags");
1584 flags = Route::Flag (string_2_enum (prop->value(), flags));
1587 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1589 if (r->init () == 0 && r->set_state (node, version) == 0) {
1590 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1591 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1601 Session::load_regions (const XMLNode& node)
1604 XMLNodeConstIterator niter;
1605 boost::shared_ptr<Region> region;
1607 nlist = node.children();
1611 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1612 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1613 error << _("Session: cannot create Region from XML description.");
1614 const XMLProperty *name = (**niter).property("name");
1617 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1628 Session::load_compounds (const XMLNode& node)
1630 XMLNodeList calist = node.children();
1631 XMLNodeConstIterator caiter;
1632 XMLProperty *caprop;
1634 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1635 XMLNode* ca = *caiter;
1639 if ((caprop = ca->property (X_("original"))) == 0) {
1642 orig_id = caprop->value();
1644 if ((caprop = ca->property (X_("copy"))) == 0) {
1647 copy_id = caprop->value();
1649 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1650 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1652 if (!orig || !copy) {
1653 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1659 RegionFactory::add_compound_association (orig, copy);
1666 Session::load_nested_sources (const XMLNode& node)
1669 XMLNodeConstIterator niter;
1671 nlist = node.children();
1673 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1674 if ((*niter)->name() == "Source") {
1676 /* it may already exist, so don't recreate it unnecessarily
1679 XMLProperty* prop = (*niter)->property (X_("id"));
1681 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1685 ID source_id (prop->value());
1687 if (!source_by_id (source_id)) {
1690 SourceFactory::create (*this, **niter, true);
1692 catch (failed_constructor& err) {
1693 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1700 boost::shared_ptr<Region>
1701 Session::XMLRegionFactory (const XMLNode& node, bool full)
1703 const XMLProperty* type = node.property("type");
1707 const XMLNodeList& nlist = node.children();
1709 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1710 XMLNode *child = (*niter);
1711 if (child->name() == "NestedSource") {
1712 load_nested_sources (*child);
1716 if (!type || type->value() == "audio") {
1717 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1718 } else if (type->value() == "midi") {
1719 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1722 } catch (failed_constructor& err) {
1723 return boost::shared_ptr<Region> ();
1726 return boost::shared_ptr<Region> ();
1729 boost::shared_ptr<AudioRegion>
1730 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1732 const XMLProperty* prop;
1733 boost::shared_ptr<Source> source;
1734 boost::shared_ptr<AudioSource> as;
1736 SourceList master_sources;
1737 uint32_t nchans = 1;
1740 if (node.name() != X_("Region")) {
1741 return boost::shared_ptr<AudioRegion>();
1744 if ((prop = node.property (X_("channels"))) != 0) {
1745 nchans = atoi (prop->value().c_str());
1748 if ((prop = node.property ("name")) == 0) {
1749 cerr << "no name for this region\n";
1753 if ((prop = node.property (X_("source-0"))) == 0) {
1754 if ((prop = node.property ("source")) == 0) {
1755 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1756 return boost::shared_ptr<AudioRegion>();
1760 PBD::ID s_id (prop->value());
1762 if ((source = source_by_id (s_id)) == 0) {
1763 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1764 return boost::shared_ptr<AudioRegion>();
1767 as = boost::dynamic_pointer_cast<AudioSource>(source);
1769 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1770 return boost::shared_ptr<AudioRegion>();
1773 sources.push_back (as);
1775 /* pickup other channels */
1777 for (uint32_t n=1; n < nchans; ++n) {
1778 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1779 if ((prop = node.property (buf)) != 0) {
1781 PBD::ID id2 (prop->value());
1783 if ((source = source_by_id (id2)) == 0) {
1784 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1785 return boost::shared_ptr<AudioRegion>();
1788 as = boost::dynamic_pointer_cast<AudioSource>(source);
1790 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1791 return boost::shared_ptr<AudioRegion>();
1793 sources.push_back (as);
1797 for (uint32_t n = 0; n < nchans; ++n) {
1798 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1799 if ((prop = node.property (buf)) != 0) {
1801 PBD::ID id2 (prop->value());
1803 if ((source = source_by_id (id2)) == 0) {
1804 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1805 return boost::shared_ptr<AudioRegion>();
1808 as = boost::dynamic_pointer_cast<AudioSource>(source);
1810 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1811 return boost::shared_ptr<AudioRegion>();
1813 master_sources.push_back (as);
1818 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1820 /* a final detail: this is the one and only place that we know how long missing files are */
1822 if (region->whole_file()) {
1823 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1824 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1826 sfp->set_length (region->length());
1831 if (!master_sources.empty()) {
1832 if (master_sources.size() != nchans) {
1833 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1835 region->set_master_sources (master_sources);
1843 catch (failed_constructor& err) {
1844 return boost::shared_ptr<AudioRegion>();
1848 boost::shared_ptr<MidiRegion>
1849 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1851 const XMLProperty* prop;
1852 boost::shared_ptr<Source> source;
1853 boost::shared_ptr<MidiSource> ms;
1856 if (node.name() != X_("Region")) {
1857 return boost::shared_ptr<MidiRegion>();
1860 if ((prop = node.property ("name")) == 0) {
1861 cerr << "no name for this region\n";
1865 if ((prop = node.property (X_("source-0"))) == 0) {
1866 if ((prop = node.property ("source")) == 0) {
1867 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1868 return boost::shared_ptr<MidiRegion>();
1872 PBD::ID s_id (prop->value());
1874 if ((source = source_by_id (s_id)) == 0) {
1875 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1876 return boost::shared_ptr<MidiRegion>();
1879 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1881 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1882 return boost::shared_ptr<MidiRegion>();
1885 sources.push_back (ms);
1888 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1889 /* a final detail: this is the one and only place that we know how long missing files are */
1891 if (region->whole_file()) {
1892 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1893 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1895 sfp->set_length (region->length());
1903 catch (failed_constructor& err) {
1904 return boost::shared_ptr<MidiRegion>();
1909 Session::get_sources_as_xml ()
1912 XMLNode* node = new XMLNode (X_("Sources"));
1913 Glib::Threads::Mutex::Lock lm (source_lock);
1915 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1916 node->add_child_nocopy (i->second->get_state());
1923 Session::reset_write_sources (bool mark_write_complete, bool force)
1925 boost::shared_ptr<RouteList> rl = routes.reader();
1926 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1927 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1929 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
1930 tr->reset_write_sources(mark_write_complete, force);
1931 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
1937 Session::load_sources (const XMLNode& node)
1940 XMLNodeConstIterator niter;
1941 boost::shared_ptr<Source> source; /* don't need this but it stops some
1942 * versions of gcc complaining about
1943 * discarded return values.
1946 nlist = node.children();
1950 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1953 if ((source = XMLSourceFactory (**niter)) == 0) {
1954 error << _("Session: cannot create Source from XML description.") << endmsg;
1957 } catch (MissingSource& err) {
1961 if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
1962 error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
1963 PROGRAM_NAME) << endmsg;
1967 if (!no_questions_about_missing_files) {
1968 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1973 switch (user_choice) {
1975 /* user added a new search location, so try again */
1980 /* user asked to quit the entire session load
1985 no_questions_about_missing_files = true;
1989 no_questions_about_missing_files = true;
1996 case DataType::AUDIO:
1997 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
2000 case DataType::MIDI:
2001 /* The MIDI file is actually missing so
2002 * just create a new one in the same
2003 * location. Do not announce its
2007 if (!Glib::path_is_absolute (err.path)) {
2008 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
2010 /* this should be an unrecoverable error: we would be creating a MIDI file outside
2015 /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
2016 source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
2017 /* reset ID to match the missing one */
2018 source->set_id (**niter);
2019 /* Now we can announce it */
2020 SourceFactory::SourceCreated (source);
2031 boost::shared_ptr<Source>
2032 Session::XMLSourceFactory (const XMLNode& node)
2034 if (node.name() != "Source") {
2035 return boost::shared_ptr<Source>();
2039 /* note: do peak building in another thread when loading session state */
2040 return SourceFactory::create (*this, node, true);
2043 catch (failed_constructor& err) {
2044 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
2045 return boost::shared_ptr<Source>();
2050 Session::save_template (string template_name)
2052 if ((_state_of_the_state & CannotSave) || template_name.empty ()) {
2056 bool absolute_path = Glib::path_is_absolute (template_name);
2058 /* directory to put the template in */
2059 std::string template_dir_path;
2061 if (!absolute_path) {
2062 std::string user_template_dir(user_template_directory());
2064 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2065 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2066 user_template_dir, g_strerror (errno)) << endmsg;
2070 template_dir_path = Glib::build_filename (user_template_dir, template_name);
2072 template_dir_path = template_name;
2075 if (!ARDOUR::Profile->get_trx()) {
2076 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2077 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2078 template_dir_path) << endmsg;
2082 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2083 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2084 template_dir_path, g_strerror (errno)) << endmsg;
2090 std::string template_file_path;
2092 if (ARDOUR::Profile->get_trx()) {
2093 template_file_path = template_name;
2095 if (absolute_path) {
2096 template_file_path = Glib::build_filename (template_dir_path, Glib::path_get_basename (template_dir_path) + template_suffix);
2098 template_file_path = Glib::build_filename (template_dir_path, template_name + template_suffix);
2102 SessionSaveUnderway (); /* EMIT SIGNAL */
2106 tree.set_root (&get_template());
2107 if (!tree.write (template_file_path)) {
2108 error << _("template not saved") << endmsg;
2112 if (!ARDOUR::Profile->get_trx()) {
2113 /* copy plugin state directory */
2115 std::string template_plugin_state_path (Glib::build_filename (template_dir_path, X_("plugins")));
2117 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
2118 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
2119 template_plugin_state_path, g_strerror (errno)) << endmsg;
2122 copy_files (plugins_dir(), template_plugin_state_path);
2125 store_recent_templates (template_file_path);
2131 Session::refresh_disk_space ()
2133 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2135 Glib::Threads::Mutex::Lock lm (space_lock);
2137 /* get freespace on every FS that is part of the session path */
2139 _total_free_4k_blocks = 0;
2140 _total_free_4k_blocks_uncertain = false;
2142 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2144 struct statfs statfsbuf;
2145 statfs (i->path.c_str(), &statfsbuf);
2147 double const scale = statfsbuf.f_bsize / 4096.0;
2149 /* See if this filesystem is read-only */
2150 struct statvfs statvfsbuf;
2151 statvfs (i->path.c_str(), &statvfsbuf);
2153 /* f_bavail can be 0 if it is undefined for whatever
2154 filesystem we are looking at; Samba shares mounted
2155 via GVFS are an example of this.
2157 if (statfsbuf.f_bavail == 0) {
2158 /* block count unknown */
2160 i->blocks_unknown = true;
2161 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2162 /* read-only filesystem */
2164 i->blocks_unknown = false;
2166 /* read/write filesystem with known space */
2167 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2168 i->blocks_unknown = false;
2171 _total_free_4k_blocks += i->blocks;
2172 if (i->blocks_unknown) {
2173 _total_free_4k_blocks_uncertain = true;
2176 #elif defined PLATFORM_WINDOWS
2177 vector<string> scanned_volumes;
2178 vector<string>::iterator j;
2179 vector<space_and_path>::iterator i;
2180 DWORD nSectorsPerCluster, nBytesPerSector,
2181 nFreeClusters, nTotalClusters;
2185 _total_free_4k_blocks = 0;
2187 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2188 strncpy (disk_drive, (*i).path.c_str(), 3);
2192 volume_found = false;
2193 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2195 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2196 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2197 i->blocks = (uint32_t)(nFreeBytes / 4096);
2199 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2200 if (0 == j->compare(disk_drive)) {
2201 volume_found = true;
2206 if (!volume_found) {
2207 scanned_volumes.push_back(disk_drive);
2208 _total_free_4k_blocks += i->blocks;
2213 if (0 == _total_free_4k_blocks) {
2214 strncpy (disk_drive, path().c_str(), 3);
2217 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2219 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2220 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2221 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2228 Session::get_best_session_directory_for_new_audio ()
2230 vector<space_and_path>::iterator i;
2231 string result = _session_dir->root_path();
2233 /* handle common case without system calls */
2235 if (session_dirs.size() == 1) {
2239 /* OK, here's the algorithm we're following here:
2241 We want to select which directory to use for
2242 the next file source to be created. Ideally,
2243 we'd like to use a round-robin process so as to
2244 get maximum performance benefits from splitting
2245 the files across multiple disks.
2247 However, in situations without much diskspace, an
2248 RR approach may end up filling up a filesystem
2249 with new files while others still have space.
2250 Its therefore important to pay some attention to
2251 the freespace in the filesystem holding each
2252 directory as well. However, if we did that by
2253 itself, we'd keep creating new files in the file
2254 system with the most space until it was as full
2255 as all others, thus negating any performance
2256 benefits of this RAID-1 like approach.
2258 So, we use a user-configurable space threshold. If
2259 there are at least 2 filesystems with more than this
2260 much space available, we use RR selection between them.
2261 If not, then we pick the filesystem with the most space.
2263 This gets a good balance between the two
2267 refresh_disk_space ();
2269 int free_enough = 0;
2271 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2272 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2277 if (free_enough >= 2) {
2278 /* use RR selection process, ensuring that the one
2282 i = last_rr_session_dir;
2285 if (++i == session_dirs.end()) {
2286 i = session_dirs.begin();
2289 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2290 SessionDirectory sdir(i->path);
2291 if (sdir.create ()) {
2293 last_rr_session_dir = i;
2298 } while (i != last_rr_session_dir);
2302 /* pick FS with the most freespace (and that
2303 seems to actually work ...)
2306 vector<space_and_path> sorted;
2307 space_and_path_ascending_cmp cmp;
2309 sorted = session_dirs;
2310 sort (sorted.begin(), sorted.end(), cmp);
2312 for (i = sorted.begin(); i != sorted.end(); ++i) {
2313 SessionDirectory sdir(i->path);
2314 if (sdir.create ()) {
2316 last_rr_session_dir = i;
2326 Session::automation_dir () const
2328 return Glib::build_filename (_path, "automation");
2332 Session::analysis_dir () const
2334 return Glib::build_filename (_path, "analysis");
2338 Session::plugins_dir () const
2340 return Glib::build_filename (_path, "plugins");
2344 Session::externals_dir () const
2346 return Glib::build_filename (_path, "externals");
2350 Session::load_bundles (XMLNode const & node)
2352 XMLNodeList nlist = node.children();
2353 XMLNodeConstIterator niter;
2357 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2358 if ((*niter)->name() == "InputBundle") {
2359 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2360 } else if ((*niter)->name() == "OutputBundle") {
2361 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2363 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2372 Session::load_route_groups (const XMLNode& node, int version)
2374 XMLNodeList nlist = node.children();
2375 XMLNodeConstIterator niter;
2379 if (version >= 3000) {
2381 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2382 if ((*niter)->name() == "RouteGroup") {
2383 RouteGroup* rg = new RouteGroup (*this, "");
2384 add_route_group (rg);
2385 rg->set_state (**niter, version);
2389 } else if (version < 3000) {
2391 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2392 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2393 RouteGroup* rg = new RouteGroup (*this, "");
2394 add_route_group (rg);
2395 rg->set_state (**niter, version);
2404 state_file_filter (const string &str, void* /*arg*/)
2406 return (str.length() > strlen(statefile_suffix) &&
2407 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2411 remove_end(string state)
2413 string statename(state);
2415 string::size_type start,end;
2416 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2417 statename = statename.substr (start+1);
2420 if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2421 end = statename.length();
2424 return string(statename.substr (0, end));
2428 Session::possible_states (string path)
2430 vector<string> states;
2431 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2433 transform(states.begin(), states.end(), states.begin(), remove_end);
2435 sort (states.begin(), states.end());
2441 Session::possible_states () const
2443 return possible_states(_path);
2447 Session::add_route_group (RouteGroup* g)
2449 _route_groups.push_back (g);
2450 route_group_added (g); /* EMIT SIGNAL */
2452 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2453 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2454 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2460 Session::remove_route_group (RouteGroup& rg)
2462 list<RouteGroup*>::iterator i;
2464 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2465 _route_groups.erase (i);
2468 route_group_removed (); /* EMIT SIGNAL */
2472 /** Set a new order for our route groups, without adding or removing any.
2473 * @param groups Route group list in the new order.
2476 Session::reorder_route_groups (list<RouteGroup*> groups)
2478 _route_groups = groups;
2480 route_groups_reordered (); /* EMIT SIGNAL */
2486 Session::route_group_by_name (string name)
2488 list<RouteGroup *>::iterator i;
2490 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2491 if ((*i)->name() == name) {
2499 Session::all_route_group() const
2501 return *_all_route_group;
2505 Session::add_commands (vector<Command*> const & cmds)
2507 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2513 Session::begin_reversible_command (const string& name)
2515 begin_reversible_command (g_quark_from_string (name.c_str ()));
2518 /** Begin a reversible command using a GQuark to identify it.
2519 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2520 * but there must be as many begin...()s as there are commit...()s.
2523 Session::begin_reversible_command (GQuark q)
2525 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2526 to hold all the commands that are committed. This keeps the order of
2527 commands correct in the history.
2530 if (_current_trans == 0) {
2531 /* start a new transaction */
2532 assert (_current_trans_quarks.empty ());
2533 _current_trans = new UndoTransaction();
2534 _current_trans->set_name (g_quark_to_string (q));
2537 _current_trans_quarks.push_front (q);
2541 Session::abort_reversible_command ()
2543 if (_current_trans != 0) {
2544 _current_trans->clear();
2545 delete _current_trans;
2547 _current_trans_quarks.clear();
2552 Session::commit_reversible_command (Command *cmd)
2554 assert (_current_trans);
2555 assert (!_current_trans_quarks.empty ());
2560 _current_trans->add_command (cmd);
2563 _current_trans_quarks.pop_front ();
2565 if (!_current_trans_quarks.empty ()) {
2566 /* the transaction we're committing is not the top-level one */
2570 if (_current_trans->empty()) {
2571 /* no commands were added to the transaction, so just get rid of it */
2572 delete _current_trans;
2577 gettimeofday (&now, 0);
2578 _current_trans->set_timestamp (now);
2580 _history.add (_current_trans);
2585 accept_all_audio_files (const string& path, void* /*arg*/)
2587 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2591 if (!AudioFileSource::safe_audio_file_extension (path)) {
2599 accept_all_midi_files (const string& path, void* /*arg*/)
2601 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2605 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2606 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2607 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2611 accept_all_state_files (const string& path, void* /*arg*/)
2613 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2617 std::string const statefile_ext (statefile_suffix);
2618 if (path.length() >= statefile_ext.length()) {
2619 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2626 Session::find_all_sources (string path, set<string>& result)
2631 if (!tree.read (path)) {
2635 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2640 XMLNodeConstIterator niter;
2642 nlist = node->children();
2646 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2650 if ((prop = (*niter)->property (X_("type"))) == 0) {
2654 DataType type (prop->value());
2656 if ((prop = (*niter)->property (X_("name"))) == 0) {
2660 if (Glib::path_is_absolute (prop->value())) {
2661 /* external file, ignore */
2669 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2670 result.insert (found_path);
2678 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2680 vector<string> state_files;
2682 string this_snapshot_path;
2688 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2689 ripped = ripped.substr (0, ripped.length() - 1);
2692 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2694 if (state_files.empty()) {
2699 this_snapshot_path = _path;
2700 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2701 this_snapshot_path += statefile_suffix;
2703 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2705 if (exclude_this_snapshot && *i == this_snapshot_path) {
2709 if (find_all_sources (*i, result) < 0) {
2717 struct RegionCounter {
2718 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2719 AudioSourceList::iterator iter;
2720 boost::shared_ptr<Region> region;
2723 RegionCounter() : count (0) {}
2727 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2729 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2730 return r.get_value_or (1);
2734 Session::cleanup_regions ()
2736 bool removed = false;
2737 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2739 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2741 uint32_t used = playlists->region_use_count (i->second);
2743 if (used == 0 && !i->second->automatic ()) {
2745 RegionFactory::map_remove (i->second);
2750 // re-check to remove parent references of compound regions
2751 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2752 if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2755 assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2756 if (0 == playlists->region_use_count (i->second)) {
2757 RegionFactory::map_remove (i->second);
2762 /* dump the history list */
2769 Session::cleanup_sources (CleanupReport& rep)
2771 // FIXME: needs adaptation to midi
2773 vector<boost::shared_ptr<Source> > dead_sources;
2776 vector<string> candidates;
2777 vector<string> unused;
2778 set<string> all_sources;
2787 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2789 /* consider deleting all unused playlists */
2791 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2796 /* sync the "all regions" property of each playlist with its current state
2799 playlists->sync_all_regions_with_regions ();
2801 /* find all un-used sources */
2806 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2808 SourceMap::iterator tmp;
2813 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2817 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2818 dead_sources.push_back (i->second);
2819 i->second->drop_references ();
2825 /* build a list of all the possible audio directories for the session */
2827 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2828 SessionDirectory sdir ((*i).path);
2829 asp += sdir.sound_path();
2831 audio_path += asp.to_string();
2834 /* build a list of all the possible midi directories for the session */
2836 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2837 SessionDirectory sdir ((*i).path);
2838 msp += sdir.midi_path();
2840 midi_path += msp.to_string();
2842 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
2843 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
2845 /* find all sources, but don't use this snapshot because the
2846 state file on disk still references sources we may have already
2850 find_all_sources_across_snapshots (all_sources, true);
2852 /* add our current source list
2855 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2856 boost::shared_ptr<FileSource> fs;
2857 SourceMap::iterator tmp = i;
2860 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2862 if (!fs->is_stub()) {
2864 if (playlists->source_use_count (fs) != 0) {
2865 all_sources.insert (fs->path());
2868 /* we might not remove this source from disk, because it may be used
2869 by other snapshots, but its not being used in this version
2870 so lets get rid of it now, along with any representative regions
2874 RegionFactory::remove_regions_using_source (i->second);
2877 // also remove source from all_sources
2879 for (set<string>::iterator j = all_sources.begin(); j != all_sources.end(); ++j) {
2880 spath = Glib::path_get_basename (*j);
2881 if ( spath == i->second->name () ) {
2882 all_sources.erase (j);
2893 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
2898 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2900 tmppath1 = canonical_path (spath);
2901 tmppath2 = canonical_path ((*i));
2903 if (tmppath1 == tmppath2) {
2910 unused.push_back (spath);
2914 /* now try to move all unused files into the "dead" directory(ies) */
2916 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2917 struct stat statbuf;
2921 /* don't move the file across filesystems, just
2922 stick it in the `dead_dir_name' directory
2923 on whichever filesystem it was already on.
2926 if ((*x).find ("/sounds/") != string::npos) {
2928 /* old school, go up 1 level */
2930 newpath = Glib::path_get_dirname (*x); // "sounds"
2931 newpath = Glib::path_get_dirname (newpath); // "session-name"
2935 /* new school, go up 4 levels */
2937 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2938 newpath = Glib::path_get_dirname (newpath); // "session-name"
2939 newpath = Glib::path_get_dirname (newpath); // "interchange"
2940 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2943 newpath = Glib::build_filename (newpath, dead_dir_name);
2945 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2946 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2950 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2952 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2954 /* the new path already exists, try versioning */
2956 char buf[PATH_MAX+1];
2960 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2963 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2964 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2968 if (version == 999) {
2969 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2973 newpath = newpath_v;
2978 /* it doesn't exist, or we can't read it or something */
2982 stat ((*x).c_str(), &statbuf);
2984 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2985 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2986 (*x), newpath, strerror (errno))
2991 /* see if there an easy to find peakfile for this file, and remove it.
2994 string base = basename_nosuffix (*x);
2995 base += "%A"; /* this is what we add for the channel suffix of all native files,
2996 or for the first channel of embedded files. it will miss
2997 some peakfiles for other channels
2999 string peakpath = peak_path (base);
3001 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
3002 if (::g_unlink (peakpath.c_str()) != 0) {
3003 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3004 peakpath, _path, strerror (errno))
3006 /* try to back out */
3007 ::rename (newpath.c_str(), _path.c_str());
3012 rep.paths.push_back (*x);
3013 rep.space += statbuf.st_size;
3016 /* dump the history list */
3020 /* save state so we don't end up a session file
3021 referring to non-existent sources.
3028 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3034 Session::cleanup_trash_sources (CleanupReport& rep)
3036 // FIXME: needs adaptation for MIDI
3038 vector<space_and_path>::iterator i;
3044 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3046 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
3048 clear_directory (dead_dir, &rep.space, &rep.paths);
3055 Session::set_dirty ()
3057 /* never mark session dirty during loading */
3059 if (_state_of_the_state & Loading) {
3063 bool was_dirty = dirty();
3065 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3069 DirtyChanged(); /* EMIT SIGNAL */
3075 Session::set_clean ()
3077 bool was_dirty = dirty();
3079 _state_of_the_state = Clean;
3083 DirtyChanged(); /* EMIT SIGNAL */
3088 Session::set_deletion_in_progress ()
3090 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3094 Session::clear_deletion_in_progress ()
3096 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3100 Session::add_controllable (boost::shared_ptr<Controllable> c)
3102 /* this adds a controllable to the list managed by the Session.
3103 this is a subset of those managed by the Controllable class
3104 itself, and represents the only ones whose state will be saved
3105 as part of the session.
3108 Glib::Threads::Mutex::Lock lm (controllables_lock);
3109 controllables.insert (c);
3112 struct null_deleter { void operator()(void const *) const {} };
3115 Session::remove_controllable (Controllable* c)
3117 if (_state_of_the_state & Deletion) {
3121 Glib::Threads::Mutex::Lock lm (controllables_lock);
3123 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3125 if (x != controllables.end()) {
3126 controllables.erase (x);
3130 boost::shared_ptr<Controllable>
3131 Session::controllable_by_id (const PBD::ID& id)
3133 Glib::Threads::Mutex::Lock lm (controllables_lock);
3135 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3136 if ((*i)->id() == id) {
3141 return boost::shared_ptr<Controllable>();
3144 boost::shared_ptr<Controllable>
3145 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3147 boost::shared_ptr<Controllable> c;
3148 boost::shared_ptr<Route> r;
3150 switch (desc.top_level_type()) {
3151 case ControllableDescriptor::NamedRoute:
3153 std::string str = desc.top_level_name();
3154 if (str == "Master" || str == "master") {
3156 } else if (str == "control" || str == "listen") {
3159 r = route_by_name (desc.top_level_name());
3164 case ControllableDescriptor::RemoteControlID:
3165 r = route_by_remote_id (desc.rid());
3173 switch (desc.subtype()) {
3174 case ControllableDescriptor::Gain:
3175 c = r->gain_control ();
3178 case ControllableDescriptor::Trim:
3179 c = r->trim()->gain_control ();
3182 case ControllableDescriptor::Solo:
3183 c = r->solo_control();
3186 case ControllableDescriptor::Mute:
3187 c = r->mute_control();
3190 case ControllableDescriptor::Recenable:
3192 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3195 c = t->rec_enable_control ();
3200 case ControllableDescriptor::PanDirection:
3202 c = r->pannable()->pan_azimuth_control;
3206 case ControllableDescriptor::PanWidth:
3208 c = r->pannable()->pan_width_control;
3212 case ControllableDescriptor::PanElevation:
3214 c = r->pannable()->pan_elevation_control;
3218 case ControllableDescriptor::Balance:
3219 /* XXX simple pan control */
3222 case ControllableDescriptor::PluginParameter:
3224 uint32_t plugin = desc.target (0);
3225 uint32_t parameter_index = desc.target (1);
3227 /* revert to zero based counting */
3233 if (parameter_index > 0) {
3237 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3240 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3241 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3246 case ControllableDescriptor::SendGain:
3248 uint32_t send = desc.target (0);
3250 /* revert to zero-based counting */
3256 boost::shared_ptr<Processor> p = r->nth_send (send);
3259 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3260 boost::shared_ptr<Amp> a = s->amp();
3263 c = s->amp()->gain_control();
3270 /* relax and return a null pointer */
3278 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3281 Stateful::add_instant_xml (node, _path);
3284 if (write_to_config) {
3285 Config->add_instant_xml (node);
3290 Session::instant_xml (const string& node_name)
3292 return Stateful::instant_xml (node_name, _path);
3296 Session::save_history (string snapshot_name)
3304 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3305 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3309 if (snapshot_name.empty()) {
3310 snapshot_name = _current_snapshot_name;
3313 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3314 const string backup_filename = history_filename + backup_suffix;
3315 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3316 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3318 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3319 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3320 error << _("could not backup old history file, current history not saved") << endmsg;
3325 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3327 if (!tree.write (xml_path))
3329 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3331 if (g_remove (xml_path.c_str()) != 0) {
3332 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3333 xml_path, g_strerror (errno)) << endmsg;
3335 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3336 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3337 backup_path, g_strerror (errno)) << endmsg;
3347 Session::restore_history (string snapshot_name)
3351 if (snapshot_name.empty()) {
3352 snapshot_name = _current_snapshot_name;
3355 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3356 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3358 info << "Loading history from " << xml_path << endmsg;
3360 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3361 info << string_compose (_("%1: no history file \"%2\" for this session."),
3362 _name, xml_path) << endmsg;
3366 if (!tree.read (xml_path)) {
3367 error << string_compose (_("Could not understand session history file \"%1\""),
3368 xml_path) << endmsg;
3375 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3378 UndoTransaction* ut = new UndoTransaction ();
3381 ut->set_name(t->property("name")->value());
3382 stringstream ss(t->property("tv-sec")->value());
3384 ss.str(t->property("tv-usec")->value());
3386 ut->set_timestamp(tv);
3388 for (XMLNodeConstIterator child_it = t->children().begin();
3389 child_it != t->children().end(); child_it++)
3391 XMLNode *n = *child_it;
3394 if (n->name() == "MementoCommand" ||
3395 n->name() == "MementoUndoCommand" ||
3396 n->name() == "MementoRedoCommand") {
3398 if ((c = memento_command_factory(n))) {
3402 } else if (n->name() == "NoteDiffCommand") {
3403 PBD::ID id (n->property("midi-source")->value());
3404 boost::shared_ptr<MidiSource> midi_source =
3405 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3407 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3409 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3412 } else if (n->name() == "SysExDiffCommand") {
3414 PBD::ID id (n->property("midi-source")->value());
3415 boost::shared_ptr<MidiSource> midi_source =
3416 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3418 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3420 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3423 } else if (n->name() == "PatchChangeDiffCommand") {
3425 PBD::ID id (n->property("midi-source")->value());
3426 boost::shared_ptr<MidiSource> midi_source =
3427 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3429 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3431 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3434 } else if (n->name() == "StatefulDiffCommand") {
3435 if ((c = stateful_diff_command_factory (n))) {
3436 ut->add_command (c);
3439 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3450 Session::config_changed (std::string p, bool ours)
3456 if (p == "seamless-loop") {
3458 } else if (p == "rf-speed") {
3460 } else if (p == "auto-loop") {
3462 } else if (p == "auto-input") {
3464 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3465 /* auto-input only makes a difference if we're rolling */
3466 set_track_monitor_input_status (!config.get_auto_input());
3469 } else if (p == "punch-in") {
3473 if ((location = _locations->auto_punch_location()) != 0) {
3475 if (config.get_punch_in ()) {
3476 replace_event (SessionEvent::PunchIn, location->start());
3478 remove_event (location->start(), SessionEvent::PunchIn);
3482 } else if (p == "punch-out") {
3486 if ((location = _locations->auto_punch_location()) != 0) {
3488 if (config.get_punch_out()) {
3489 replace_event (SessionEvent::PunchOut, location->end());
3491 clear_events (SessionEvent::PunchOut);
3495 } else if (p == "edit-mode") {
3497 Glib::Threads::Mutex::Lock lm (playlists->lock);
3499 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3500 (*i)->set_edit_mode (Config->get_edit_mode ());
3503 } else if (p == "use-video-sync") {
3505 waiting_for_sync_offset = config.get_use_video_sync();
3507 } else if (p == "mmc-control") {
3509 //poke_midi_thread ();
3511 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3513 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3515 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3517 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3519 } else if (p == "midi-control") {
3521 //poke_midi_thread ();
3523 } else if (p == "raid-path") {
3525 setup_raid_path (config.get_raid_path());
3527 } else if (p == "timecode-format") {
3531 } else if (p == "video-pullup") {
3535 } else if (p == "seamless-loop") {
3537 if (play_loop && transport_rolling()) {
3538 // to reset diskstreams etc
3539 request_play_loop (true);
3542 } else if (p == "rf-speed") {
3544 cumulative_rf_motion = 0;
3547 } else if (p == "click-sound") {
3549 setup_click_sounds (1);
3551 } else if (p == "click-emphasis-sound") {
3553 setup_click_sounds (-1);
3555 } else if (p == "clicking") {
3557 if (Config->get_clicking()) {
3558 if (_click_io && click_data) { // don't require emphasis data
3565 } else if (p == "click-gain") {
3568 _click_gain->set_gain (Config->get_click_gain(), this);
3571 } else if (p == "send-mtc") {
3573 if (Config->get_send_mtc ()) {
3574 /* mark us ready to send */
3575 next_quarter_frame_to_send = 0;
3578 } else if (p == "send-mmc") {
3580 _mmc->enable_send (Config->get_send_mmc ());
3582 } else if (p == "midi-feedback") {
3584 session_midi_feedback = Config->get_midi_feedback();
3586 } else if (p == "jack-time-master") {
3588 engine().reset_timebase ();
3590 } else if (p == "native-file-header-format") {
3592 if (!first_file_header_format_reset) {
3593 reset_native_file_format ();
3596 first_file_header_format_reset = false;
3598 } else if (p == "native-file-data-format") {
3600 if (!first_file_data_format_reset) {
3601 reset_native_file_format ();
3604 first_file_data_format_reset = false;
3606 } else if (p == "external-sync") {
3607 if (!config.get_external_sync()) {
3608 drop_sync_source ();
3610 switch_to_sync_source (Config->get_sync_source());
3612 } else if (p == "denormal-model") {
3614 } else if (p == "history-depth") {
3615 set_history_depth (Config->get_history_depth());
3616 } else if (p == "remote-model") {
3617 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3620 } else if (p == "initial-program-change") {
3622 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3625 buf[0] = MIDI::program; // channel zero by default
3626 buf[1] = (Config->get_initial_program_change() & 0x7f);
3628 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3630 } else if (p == "solo-mute-override") {
3631 // catch_up_on_solo_mute_override ();
3632 } else if (p == "listen-position" || p == "pfl-position") {
3633 listen_position_changed ();
3634 } else if (p == "solo-control-is-listen-control") {
3635 solo_control_mode_changed ();
3636 } else if (p == "solo-mute-gain") {
3637 _solo_cut_control->Changed();
3638 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3639 last_timecode_valid = false;
3640 } else if (p == "playback-buffer-seconds") {
3641 AudioSource::allocate_working_buffers (frame_rate());
3642 } else if (p == "ltc-source-port") {
3643 reconnect_ltc_input ();
3644 } else if (p == "ltc-sink-port") {
3645 reconnect_ltc_output ();
3646 } else if (p == "timecode-generator-offset") {
3647 ltc_tx_parse_offset();
3654 Session::set_history_depth (uint32_t d)
3656 _history.set_depth (d);
3660 Session::load_diskstreams_2X (XMLNode const & node, int)
3663 XMLNodeConstIterator citer;
3665 clist = node.children();
3667 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3670 /* diskstreams added automatically by DiskstreamCreated handler */
3671 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3672 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3673 _diskstreams_2X.push_back (dsp);
3675 error << _("Session: unknown diskstream type in XML") << endmsg;
3679 catch (failed_constructor& err) {
3680 error << _("Session: could not load diskstream via XML state") << endmsg;
3688 /** Connect things to the MMC object */
3690 Session::setup_midi_machine_control ()
3692 _mmc = new MIDI::MachineControl;
3693 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3695 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3696 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3697 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3698 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3699 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3700 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3701 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3702 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3703 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3704 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3705 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3706 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3707 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3709 /* also handle MIDI SPP because its so common */
3711 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3712 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3713 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3716 boost::shared_ptr<Controllable>
3717 Session::solo_cut_control() const
3719 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3720 controls in Ardour that currently get presented to the user in the GUI that require
3721 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3723 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3724 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3728 return _solo_cut_control;
3732 Session::rename (const std::string& new_name)
3734 string legal_name = legalize_for_path (new_name);
3740 string const old_sources_root = _session_dir->sources_root();
3742 if (!_writable || (_state_of_the_state & CannotSave)) {
3743 error << _("Cannot rename read-only session.") << endmsg;
3744 return 0; // don't show "messed up" warning
3746 if (record_status() == Recording) {
3747 error << _("Cannot rename session while recording") << endmsg;
3748 return 0; // don't show "messed up" warning
3751 StateProtector stp (this);
3756 * interchange subdirectory
3760 * Backup files are left unchanged and not renamed.
3763 /* Windows requires that we close all files before attempting the
3764 * rename. This works on other platforms, but isn't necessary there.
3765 * Leave it in place for all platforms though, since it may help
3766 * catch issues that could arise if the way Source files work ever
3767 * change (since most developers are not using Windows).
3770 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
3771 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3777 /* pass one: not 100% safe check that the new directory names don't
3781 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3785 /* this is a stupid hack because Glib::path_get_dirname() is
3786 * lexical-only, and so passing it /a/b/c/ gives a different
3787 * result than passing it /a/b/c ...
3790 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3791 oldstr = oldstr.substr (0, oldstr.length() - 1);
3794 string base = Glib::path_get_dirname (oldstr);
3796 newstr = Glib::build_filename (base, legal_name);
3798 cerr << "Looking for " << newstr << endl;
3800 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3801 cerr << " exists\n";
3810 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3816 /* this is a stupid hack because Glib::path_get_dirname() is
3817 * lexical-only, and so passing it /a/b/c/ gives a different
3818 * result than passing it /a/b/c ...
3821 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3822 oldstr = oldstr.substr (0, oldstr.length() - 1);
3825 string base = Glib::path_get_dirname (oldstr);
3826 newstr = Glib::build_filename (base, legal_name);
3828 cerr << "for " << oldstr << " new dir = " << newstr << endl;
3830 cerr << "Rename " << oldstr << " => " << newstr << endl;
3831 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3832 cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3833 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3837 /* Reset path in "session dirs" */
3842 /* reset primary SessionDirectory object */
3845 (*_session_dir) = newstr;
3850 /* now rename directory below session_dir/interchange */
3852 string old_interchange_dir;
3853 string new_interchange_dir;
3855 /* use newstr here because we renamed the path
3856 * (folder/directory) that used to be oldstr to newstr above
3859 v.push_back (newstr);
3860 v.push_back (interchange_dir_name);
3861 v.push_back (Glib::path_get_basename (oldstr));
3863 old_interchange_dir = Glib::build_filename (v);
3866 v.push_back (newstr);
3867 v.push_back (interchange_dir_name);
3868 v.push_back (legal_name);
3870 new_interchange_dir = Glib::build_filename (v);
3872 cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
3874 if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
3875 cerr << string_compose (_("renaming %s as %2 failed (%3)"),
3876 old_interchange_dir, new_interchange_dir,
3879 error << string_compose (_("renaming %s as %2 failed (%3)"),
3880 old_interchange_dir, new_interchange_dir,
3889 oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
3890 newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
3892 cerr << "Rename " << oldstr << " => " << newstr << endl;
3894 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3895 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3896 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3902 oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
3904 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3905 newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
3907 cerr << "Rename " << oldstr << " => " << newstr << endl;
3909 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3910 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3911 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3916 /* remove old name from recent sessions */
3917 remove_recent_sessions (_path);
3920 /* update file source paths */
3922 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3923 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3925 string p = fs->path ();
3926 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3928 SourceFactory::setup_peakfile(i->second, true);
3932 _current_snapshot_name = new_name;
3937 /* save state again to get everything just right */
3939 save_state (_current_snapshot_name);
3941 /* add to recent sessions */
3943 store_recent_sessions (new_name, _path);
3949 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
3951 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
3955 if (!tree.read (xmlpath)) {
3963 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
3966 bool found_sr = false;
3967 bool found_data_format = false;
3969 if (get_session_info_from_path (tree, xmlpath)) {
3975 const XMLProperty* prop;
3976 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
3977 sample_rate = atoi (prop->value());
3981 const XMLNodeList& children (tree.root()->children());
3982 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
3983 const XMLNode* child = *c;
3984 if (child->name() == "Config") {
3985 const XMLNodeList& options (child->children());
3986 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
3987 const XMLNode* option = *oc;
3988 const XMLProperty* name = option->property("name");
3994 if (name->value() == "native-file-data-format") {
3995 const XMLProperty* value = option->property ("value");
3997 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
3999 found_data_format = true;
4005 if (found_data_format) {
4010 return !(found_sr && found_data_format); // zero if they are both found
4013 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
4014 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
4017 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
4021 SourcePathMap source_path_map;
4023 boost::shared_ptr<AudioFileSource> afs;
4028 Glib::Threads::Mutex::Lock lm (source_lock);
4030 cerr << " total sources = " << sources.size();
4032 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4033 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4039 if (fs->within_session()) {
4043 if (source_path_map.find (fs->path()) != source_path_map.end()) {
4044 source_path_map[fs->path()].push_back (fs);
4046 SeveralFileSources v;
4048 source_path_map.insert (make_pair (fs->path(), v));
4054 cerr << " fsources = " << total << endl;
4056 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
4058 /* tell caller where we are */
4060 string old_path = i->first;
4062 callback (n, total, old_path);
4064 cerr << old_path << endl;
4068 switch (i->second.front()->type()) {
4069 case DataType::AUDIO:
4070 new_path = new_audio_source_path_for_embedded (old_path);
4073 case DataType::MIDI:
4074 /* XXX not implemented yet */
4078 if (new_path.empty()) {
4082 cerr << "Move " << old_path << " => " << new_path << endl;
4084 if (!copy_file (old_path, new_path)) {
4085 cerr << "failed !\n";
4089 /* make sure we stop looking in the external
4090 dir/folder. Remember, this is an all-or-nothing
4091 operations, it doesn't merge just some files.
4093 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
4095 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
4096 (*f)->set_path (new_path);
4101 save_state ("", false, false);
4107 bool accept_all_files (string const &, void *)
4113 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4115 /* 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.
4120 make_new_media_path (string old_path, string new_session_folder, string new_session_path)
4122 /* typedir is the "midifiles" or "audiofiles" etc. part of the path. */
4124 string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4126 v.push_back (new_session_folder); /* full path */
4127 v.push_back (interchange_dir_name);
4128 v.push_back (new_session_path); /* just one directory/folder */
4129 v.push_back (typedir);
4130 v.push_back (Glib::path_get_basename (old_path));
4132 return Glib::build_filename (v);
4136 Session::save_as (SaveAs& saveas)
4138 vector<string> files;
4139 string current_folder = Glib::path_get_dirname (_path);
4140 string new_folder = legalize_for_path (saveas.new_name);
4141 string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4142 int64_t total_bytes = 0;
4146 int32_t internal_file_cnt = 0;
4148 vector<string> do_not_copy_extensions;
4149 do_not_copy_extensions.push_back (statefile_suffix);
4150 do_not_copy_extensions.push_back (pending_suffix);
4151 do_not_copy_extensions.push_back (backup_suffix);
4152 do_not_copy_extensions.push_back (temp_suffix);
4153 do_not_copy_extensions.push_back (history_suffix);
4155 /* get total size */
4157 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4159 /* need to clear this because
4160 * find_files_matching_filter() is cumulative
4165 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4167 all += files.size();
4169 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4171 g_stat ((*i).c_str(), &gsb);
4172 total_bytes += gsb.st_size;
4176 /* save old values so we can switch back if we are not switching to the new session */
4178 string old_path = _path;
4179 string old_name = _name;
4180 string old_snapshot = _current_snapshot_name;
4181 string old_sd = _session_dir->root_path();
4182 vector<string> old_search_path[DataType::num_types];
4183 string old_config_search_path[DataType::num_types];
4185 old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4186 old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4187 old_config_search_path[DataType::AUDIO] = config.get_audio_search_path ();
4188 old_config_search_path[DataType::MIDI] = config.get_midi_search_path ();
4190 /* switch session directory */
4192 (*_session_dir) = to_dir;
4194 /* create new tree */
4196 if (!_session_dir->create()) {
4197 saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4202 /* copy all relevant files. Find each location in session_dirs,
4203 * and copy files from there to target.
4206 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4208 /* need to clear this because
4209 * find_files_matching_filter() is cumulative
4214 const size_t prefix_len = (*sd).path.size();
4216 /* Work just on the files within this session dir */
4218 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4220 /* add dir separator to protect against collisions with
4221 * track names (e.g. track named "audiofiles" or
4225 static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
4226 static const std::string midifile_dir_string = string (midi_dir_name) + G_DIR_SEPARATOR;
4227 static const std::string analysis_dir_string = analysis_dir() + G_DIR_SEPARATOR;
4229 /* copy all the files. Handling is different for media files
4230 than others because of the *silly* subtree we have below the interchange
4231 folder. That really was a bad idea, but I'm not fixing it as part of
4232 implementing ::save_as().
4235 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4237 std::string from = *i;
4240 string filename = Glib::path_get_basename (from);
4241 std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
4242 if (filename == ".DS_STORE") {
4247 if (from.find (audiofile_dir_string) != string::npos) {
4249 /* audio file: only copy if asked */
4251 if (saveas.include_media && saveas.copy_media) {
4253 string to = make_new_media_path (*i, to_dir, new_folder);
4255 info << "media file copying from " << from << " to " << to << endmsg;
4257 if (!copy_file (from, to)) {
4258 throw Glib::FileError (Glib::FileError::IO_ERROR,
4259 string_compose(_("\ncopying \"%1\" failed !"), from));
4263 /* we found media files inside the session folder */
4265 internal_file_cnt++;
4267 } else if (from.find (midifile_dir_string) != string::npos) {
4269 /* midi file: always copy unless
4270 * creating an empty new session
4273 if (saveas.include_media) {
4275 string to = make_new_media_path (*i, to_dir, new_folder);
4277 info << "media file copying from " << from << " to " << to << endmsg;
4279 if (!copy_file (from, to)) {
4280 throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4284 /* we found media files inside the session folder */
4286 internal_file_cnt++;
4288 } else if (from.find (analysis_dir_string) != string::npos) {
4290 /* make sure analysis dir exists in
4291 * new session folder, but we're not
4292 * copying analysis files here, see
4296 (void) g_mkdir_with_parents (analysis_dir().c_str(), 775);
4301 /* normal non-media file. Don't copy state, history, etc.
4304 bool do_copy = true;
4306 for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
4307 if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
4308 /* end of filename matches extension, do not copy file */
4314 if (!saveas.copy_media && from.find (peakfile_suffix) != string::npos) {
4315 /* don't copy peakfiles if
4316 * we're not copying media
4322 string to = Glib::build_filename (to_dir, from.substr (prefix_len));
4324 info << "attempting to make directory/folder " << to << endmsg;
4326 if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
4327 throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
4330 info << "attempting to copy " << from << " to " << to << endmsg;
4332 if (!copy_file (from, to)) {
4333 throw Glib::FileError (Glib::FileError::IO_ERROR,
4334 string_compose(_("\ncopying \"%1\" failed !"), from));
4339 /* measure file size even if we're not going to copy so that our Progress
4340 signals are correct, since we included these do-not-copy files
4341 in the computation of the total size and file count.
4345 g_stat (from.c_str(), &gsb);
4346 copied += gsb.st_size;
4349 double fraction = (double) copied / total_bytes;
4351 bool keep_going = true;
4353 if (saveas.copy_media) {
4355 /* no need or expectation of this if
4356 * media is not being copied, because
4357 * it will be fast(ish).
4360 /* tell someone "X percent, file M of N"; M is one-based */
4362 boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
4370 throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
4376 /* copy optional folders, if any */
4378 string old = plugins_dir ();
4379 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4380 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4381 copy_files (old, newdir);
4384 old = externals_dir ();
4385 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4386 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4387 copy_files (old, newdir);
4390 old = automation_dir ();
4391 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4392 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4393 copy_files (old, newdir);
4396 if (saveas.include_media) {
4398 if (saveas.copy_media) {
4399 #ifndef PLATFORM_WINDOWS
4400 /* There are problems with analysis files on
4401 * Windows, because they used a colon in their
4402 * names as late as 4.0. Colons are not legal
4403 * under Windows even if NTFS allows them.
4405 * This is a tricky problem to solve so for
4406 * just don't copy these files. They will be
4407 * regenerated as-needed anyway, subject to the
4408 * existing issue that the filenames will be
4409 * rejected by Windows, which is a separate
4410 * problem (though related).
4413 /* only needed if we are copying media, since the
4414 * analysis data refers to media data
4417 old = analysis_dir ();
4418 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4419 string newdir = Glib::build_filename (to_dir, "analysis");
4420 copy_files (old, newdir);
4422 #endif /* PLATFORM_WINDOWS */
4428 _current_snapshot_name = saveas.new_name;
4429 _name = saveas.new_name;
4431 if (saveas.include_media && !saveas.copy_media) {
4433 /* reset search paths of the new session (which we're pretending to be right now) to
4434 include the original session search path, so we can still find all audio.
4437 if (internal_file_cnt) {
4438 for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
4439 ensure_search_path_includes (*s, DataType::AUDIO);
4442 /* we do not do this for MIDI because we copy
4443 all MIDI files if saveas.include_media is
4449 bool was_dirty = dirty ();
4451 save_state ("", false, false, !saveas.include_media);
4452 save_default_options ();
4454 if (saveas.copy_media && saveas.copy_external) {
4455 if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
4456 throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
4460 saveas.final_session_folder_name = _path;
4462 store_recent_sessions (_name, _path);
4464 if (!saveas.switch_to) {
4466 /* switch back to the way things were */
4470 _current_snapshot_name = old_snapshot;
4472 (*_session_dir) = old_sd;
4478 if (internal_file_cnt) {
4479 /* reset these to their original values */
4480 config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
4481 config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
4486 /* prune session dirs, and update disk space statistics
4491 session_dirs.clear ();
4492 session_dirs.push_back (sp);
4493 refresh_disk_space ();
4495 /* ensure that all existing tracks reset their current capture source paths
4497 reset_write_sources (true, true);
4499 /* the copying above was based on actually discovering files, not just iterating over the sources list.
4500 But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
4503 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4504 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4510 if (fs->within_session()) {
4511 string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
4512 fs->set_path (newpath);
4517 } catch (Glib::FileError& e) {
4519 saveas.failure_message = e.what();
4521 /* recursively remove all the directories */
4523 remove_directory (to_dir);
4531 saveas.failure_message = _("unknown reason");
4533 /* recursively remove all the directories */
4535 remove_directory (to_dir);