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);
370 Session::session_loaded ()
374 _state_of_the_state = Clean;
376 DirtyChanged (); /* EMIT SIGNAL */
380 } else if (state_was_pending) {
382 remove_pending_capture_state ();
383 state_was_pending = false;
386 /* Now, finally, we can fill the playback buffers */
388 BootMessage (_("Filling playback buffers"));
390 boost::shared_ptr<RouteList> rl = routes.reader();
391 for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) {
392 boost::shared_ptr<Track> trk = boost::dynamic_pointer_cast<Track> (*r);
393 if (trk && !trk->hidden()) {
394 trk->seek (_transport_frame, true);
400 Session::raid_path () const
402 Searchpath raid_search_path;
404 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
405 raid_search_path += (*i).path;
408 return raid_search_path.to_string ();
412 Session::setup_raid_path (string path)
421 session_dirs.clear ();
423 Searchpath search_path(path);
424 Searchpath sound_search_path;
425 Searchpath midi_search_path;
427 for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
429 sp.blocks = 0; // not needed
430 session_dirs.push_back (sp);
432 SessionDirectory sdir(sp.path);
434 sound_search_path += sdir.sound_path ();
435 midi_search_path += sdir.midi_path ();
438 // reset the round-robin soundfile path thingie
439 last_rr_session_dir = session_dirs.begin();
443 Session::path_is_within_session (const std::string& path)
445 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
446 if (PBD::path_is_within (i->path, path)) {
454 Session::ensure_subdirs ()
458 dir = session_directory().peak_path();
460 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
461 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
465 dir = session_directory().sound_path();
467 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
468 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
472 dir = session_directory().midi_path();
474 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
475 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
479 dir = session_directory().dead_path();
481 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
482 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
486 dir = session_directory().export_path();
488 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
489 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
493 dir = analysis_dir ();
495 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
496 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
500 dir = plugins_dir ();
502 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
503 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
507 dir = externals_dir ();
509 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
510 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
517 /** @param session_template directory containing session template, or empty.
518 * Caller must not hold process lock.
521 Session::create (const string& session_template, BusProfile* bus_profile)
523 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
524 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
528 if (ensure_subdirs ()) {
532 _writable = exists_and_writable (_path);
534 if (!session_template.empty()) {
535 std::string in_path = (ARDOUR::Profile->get_trx () ? session_template : session_template_dir_to_file (session_template));
537 ifstream in(in_path.c_str());
540 /* no need to call legalize_for_path() since the string
541 * in session_template is already a legal path name
543 string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
545 ofstream out(out_path.c_str());
551 if (!ARDOUR::Profile->get_trx()) {
552 /* Copy plugin state files from template to new session */
553 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
554 copy_recurse (template_plugins, plugins_dir ());
560 error << string_compose (_("Could not open %1 for writing session template"), out_path)
566 error << string_compose (_("Could not open session template %1 for reading"), in_path)
573 /* set initial start + end point */
575 _state_of_the_state = Clean;
577 /* set up Master Out and Control Out if necessary */
582 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
584 // Waves Tracks: always create master bus for Tracks
585 if (ARDOUR::Profile->get_trx() || bus_profile->master_out_channels) {
586 boost::shared_ptr<Route> r (new Route (*this, _("Master"), Route::MasterOut, DataType::AUDIO));
590 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
591 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
594 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
595 r->input()->ensure_io (count, false, this);
596 r->output()->ensure_io (count, false, this);
602 /* prohibit auto-connect to master, because there isn't one */
603 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
607 add_routes (rl, false, false, false);
610 // Waves Tracks: Skip this. Always use autoconnection for Tracks
611 if (!ARDOUR::Profile->get_trx()) {
613 /* this allows the user to override settings with an environment variable.
616 if (no_auto_connect()) {
617 bus_profile->input_ac = AutoConnectOption (0);
618 bus_profile->output_ac = AutoConnectOption (0);
621 Config->set_input_auto_connect (bus_profile->input_ac);
622 Config->set_output_auto_connect (bus_profile->output_ac);
626 if (Config->get_use_monitor_bus() && bus_profile) {
627 add_monitor_section ();
634 Session::maybe_write_autosave()
636 if (dirty() && record_status() != Recording) {
637 save_state("", true);
642 Session::remove_pending_capture_state ()
644 std::string pending_state_file_path(_session_dir->root_path());
646 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
648 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
650 if (g_remove (pending_state_file_path.c_str()) != 0) {
651 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
652 pending_state_file_path, g_strerror (errno)) << endmsg;
656 /** Rename a state file.
657 * @param old_name Old snapshot name.
658 * @param new_name New snapshot name.
661 Session::rename_state (string old_name, string new_name)
663 if (old_name == _current_snapshot_name || old_name == _name) {
664 /* refuse to rename the current snapshot or the "main" one */
668 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
669 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
671 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
672 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
674 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
675 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
676 old_name, new_name, g_strerror(errno)) << endmsg;
680 /** Remove a state file.
681 * @param snapshot_name Snapshot name.
684 Session::remove_state (string snapshot_name)
686 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
687 // refuse to remove the current snapshot or the "main" one
691 std::string xml_path(_session_dir->root_path());
693 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
695 if (!create_backup_file (xml_path)) {
696 // don't remove it if a backup can't be made
697 // create_backup_file will log the error.
702 if (g_remove (xml_path.c_str()) != 0) {
703 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
704 xml_path, g_strerror (errno)) << endmsg;
708 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
710 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot, bool template_only)
713 std::string xml_path(_session_dir->root_path());
715 /* prevent concurrent saves from different threads */
717 Glib::Threads::Mutex::Lock lm (save_state_lock);
719 if (!_writable || (_state_of_the_state & CannotSave)) {
723 if (g_atomic_int_get(&_suspend_save)) {
727 _save_queued = false;
729 if (!_engine.connected ()) {
730 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
736 /* tell sources we're saving first, in case they write out to a new file
737 * which should be saved with the state rather than the old one */
738 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
740 i->second->session_saved();
741 } catch (Evoral::SMF::FileError& e) {
742 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
746 SessionSaveUnderway (); /* EMIT SIGNAL */
749 tree.set_root (&get_template());
751 tree.set_root (&get_state());
754 if (snapshot_name.empty()) {
755 snapshot_name = _current_snapshot_name;
756 } else if (switch_to_snapshot) {
757 _current_snapshot_name = snapshot_name;
762 /* proper save: use statefile_suffix (.ardour in English) */
764 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
766 /* make a backup copy of the old file */
768 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
769 // create_backup_file will log the error
775 /* pending save: use pending_suffix (.pending in English) */
776 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
779 std::string tmp_path(_session_dir->root_path());
780 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
782 cerr << "actually writing state to " << tmp_path << endl;
784 if (!tree.write (tmp_path)) {
785 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
786 if (g_remove (tmp_path.c_str()) != 0) {
787 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
788 tmp_path, g_strerror (errno)) << endmsg;
794 cerr << "renaming state to " << xml_path << endl;
796 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
797 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
798 tmp_path, xml_path, g_strerror(errno)) << endmsg;
799 if (g_remove (tmp_path.c_str()) != 0) {
800 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
801 tmp_path, g_strerror (errno)) << endmsg;
809 save_history (snapshot_name);
811 bool was_dirty = dirty();
813 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
816 DirtyChanged (); /* EMIT SIGNAL */
819 StateSaved (snapshot_name); /* EMIT SIGNAL */
826 Session::restore_state (string snapshot_name)
828 if (load_state (snapshot_name) == 0) {
829 set_state (*state_tree->root(), Stateful::loading_state_version);
836 Session::load_state (string snapshot_name)
841 state_was_pending = false;
843 /* check for leftover pending state from a crashed capture attempt */
845 std::string xmlpath(_session_dir->root_path());
846 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
848 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
850 /* there is pending state from a crashed capture attempt */
852 boost::optional<int> r = AskAboutPendingState();
853 if (r.get_value_or (1)) {
854 state_was_pending = true;
858 if (!state_was_pending) {
859 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
862 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
863 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
864 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
865 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
870 state_tree = new XMLTree;
874 _writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
876 if (!state_tree->read (xmlpath)) {
877 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
883 XMLNode& root (*state_tree->root());
885 if (root.name() != X_("Session")) {
886 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
892 const XMLProperty* prop;
894 if ((prop = root.property ("version")) == 0) {
895 /* no version implies very old version of Ardour */
896 Stateful::loading_state_version = 1000;
898 if (prop->value().find ('.') != string::npos) {
899 /* old school version format */
900 if (prop->value()[0] == '2') {
901 Stateful::loading_state_version = 2000;
903 Stateful::loading_state_version = 3000;
906 Stateful::loading_state_version = atoi (prop->value());
910 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
912 std::string backup_path(_session_dir->root_path());
913 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
914 backup_path = Glib::build_filename (backup_path, backup_filename);
916 // only create a backup for a given statefile version once
918 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
920 VersionMismatch (xmlpath, backup_path);
922 if (!copy_file (xmlpath, backup_path)) {;
932 Session::load_options (const XMLNode& node)
934 LocaleGuard lg (X_("C"));
935 config.set_variables (node);
940 Session::save_default_options ()
942 return config.save_state();
952 Session::get_template()
954 /* if we don't disable rec-enable, diskstreams
955 will believe they need to store their capture
956 sources in their state node.
959 disable_record (false);
965 Session::state (bool full_state)
967 XMLNode* node = new XMLNode("Session");
971 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
972 node->add_property("version", buf);
974 /* store configuration settings */
978 node->add_property ("name", _name);
979 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
980 node->add_property ("sample-rate", buf);
982 if (session_dirs.size() > 1) {
986 vector<space_and_path>::iterator i = session_dirs.begin();
987 vector<space_and_path>::iterator next;
989 ++i; /* skip the first one */
993 while (i != session_dirs.end()) {
997 if (next != session_dirs.end()) {
998 p += G_SEARCHPATH_SEPARATOR;
1007 child = node->add_child ("Path");
1008 child->add_content (p);
1012 /* save the ID counter */
1014 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
1015 node->add_property ("id-counter", buf);
1017 /* save the event ID counter */
1019 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
1020 node->add_property ("event-counter", buf);
1022 /* various options */
1024 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
1025 if (!midi_port_nodes.empty()) {
1026 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
1027 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
1028 midi_port_stuff->add_child_nocopy (**n);
1030 node->add_child_nocopy (*midi_port_stuff);
1033 node->add_child_nocopy (config.get_variables ());
1035 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
1037 child = node->add_child ("Sources");
1040 Glib::Threads::Mutex::Lock sl (source_lock);
1042 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1044 /* Don't save information about non-file Sources, or
1045 * about non-destructive file sources that are empty
1046 * and unused by any regions.
1049 boost::shared_ptr<FileSource> fs;
1051 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1053 if (!fs->destructive()) {
1054 if (fs->empty() && !fs->used()) {
1059 child->add_child_nocopy (siter->second->get_state());
1064 child = node->add_child ("Regions");
1067 Glib::Threads::Mutex::Lock rl (region_lock);
1068 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1069 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1070 boost::shared_ptr<Region> r = i->second;
1071 /* only store regions not attached to playlists */
1072 if (r->playlist() == 0) {
1073 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1074 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1076 child->add_child_nocopy (r->get_state ());
1081 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1083 if (!cassocs.empty()) {
1084 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1086 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1088 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1089 i->first->id().print (buf, sizeof (buf));
1090 can->add_property (X_("copy"), buf);
1091 i->second->id().print (buf, sizeof (buf));
1092 can->add_property (X_("original"), buf);
1093 ca->add_child_nocopy (*can);
1103 node->add_child_nocopy (_locations->get_state());
1106 Locations loc (*this);
1107 // for a template, just create a new Locations, populate it
1108 // with the default start and end, and get the state for that.
1109 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1110 range->set (max_framepos, 0);
1112 XMLNode& locations_state = loc.get_state();
1114 if (ARDOUR::Profile->get_trx() && _locations) {
1115 // For tracks we need stored the Auto Loop Range and all MIDI markers.
1116 for (Locations::LocationList::const_iterator i = _locations->list ().begin (); i != _locations->list ().end (); ++i) {
1117 if ((*i)->is_mark () || (*i)->is_auto_loop ()) {
1118 locations_state.add_child_nocopy ((*i)->get_state ());
1122 node->add_child_nocopy (locations_state);
1125 child = node->add_child ("Bundles");
1127 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1128 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1129 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1131 child->add_child_nocopy (b->get_state());
1136 child = node->add_child ("Routes");
1138 boost::shared_ptr<RouteList> r = routes.reader ();
1140 RoutePublicOrderSorter cmp;
1141 RouteList public_order (*r);
1142 public_order.sort (cmp);
1144 /* the sort should have put control outs first */
1147 assert (_monitor_out == public_order.front());
1150 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1151 if (!(*i)->is_auditioner()) {
1153 child->add_child_nocopy ((*i)->get_state());
1155 child->add_child_nocopy ((*i)->get_template());
1161 playlists->add_state (node, full_state);
1163 child = node->add_child ("RouteGroups");
1164 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1165 child->add_child_nocopy ((*i)->get_state());
1169 XMLNode* gain_child = node->add_child ("Click");
1170 gain_child->add_child_nocopy (_click_io->state (full_state));
1171 gain_child->add_child_nocopy (_click_gain->state (full_state));
1175 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1176 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1180 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1181 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1184 node->add_child_nocopy (_speakers->get_state());
1185 node->add_child_nocopy (_tempo_map->get_state());
1186 node->add_child_nocopy (get_control_protocol_state());
1189 node->add_child_copy (*_extra_xml);
1196 Session::get_control_protocol_state ()
1198 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1199 return cpm.get_state();
1203 Session::set_state (const XMLNode& node, int version)
1207 const XMLProperty* prop;
1210 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1212 if (node.name() != X_("Session")) {
1213 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1217 if ((prop = node.property ("name")) != 0) {
1218 _name = prop->value ();
1221 if ((prop = node.property (X_("sample-rate"))) != 0) {
1223 _nominal_frame_rate = atoi (prop->value());
1225 if (_nominal_frame_rate != _current_frame_rate) {
1226 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1227 if (r.get_value_or (0)) {
1233 setup_raid_path(_session_dir->root_path());
1235 if ((prop = node.property (X_("id-counter"))) != 0) {
1237 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1238 ID::init_counter (x);
1240 /* old sessions used a timebased counter, so fake
1241 the startup ID counter based on a standard
1246 ID::init_counter (now);
1249 if ((prop = node.property (X_("event-counter"))) != 0) {
1250 Evoral::init_event_id_counter (atoi (prop->value()));
1254 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1255 _midi_ports->set_midi_port_states (child->children());
1258 IO::disable_connecting ();
1260 Stateful::save_extra_xml (node);
1262 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1263 load_options (*child);
1264 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1265 load_options (*child);
1267 error << _("Session: XML state has no options section") << endmsg;
1270 if (version >= 3000) {
1271 if ((child = find_named_node (node, "Metadata")) == 0) {
1272 warning << _("Session: XML state has no metadata section") << endmsg;
1273 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1278 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1279 _speakers->set_state (*child, version);
1282 if ((child = find_named_node (node, "Sources")) == 0) {
1283 error << _("Session: XML state has no sources section") << endmsg;
1285 } else if (load_sources (*child)) {
1289 if ((child = find_named_node (node, "TempoMap")) == 0) {
1290 error << _("Session: XML state has no Tempo Map section") << endmsg;
1292 } else if (_tempo_map->set_state (*child, version)) {
1296 if ((child = find_named_node (node, "Locations")) == 0) {
1297 error << _("Session: XML state has no locations section") << endmsg;
1299 } else if (_locations->set_state (*child, version)) {
1303 locations_changed ();
1305 if (_session_range_location) {
1306 AudioFileSource::set_header_position_offset (_session_range_location->start());
1309 if ((child = find_named_node (node, "Regions")) == 0) {
1310 error << _("Session: XML state has no Regions section") << endmsg;
1312 } else if (load_regions (*child)) {
1316 if ((child = find_named_node (node, "Playlists")) == 0) {
1317 error << _("Session: XML state has no playlists section") << endmsg;
1319 } else if (playlists->load (*this, *child)) {
1323 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1325 } else if (playlists->load_unused (*this, *child)) {
1329 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1330 if (load_compounds (*child)) {
1335 if (version >= 3000) {
1336 if ((child = find_named_node (node, "Bundles")) == 0) {
1337 warning << _("Session: XML state has no bundles section") << endmsg;
1340 /* We can't load Bundles yet as they need to be able
1341 to convert from port names to Port objects, which can't happen until
1343 _bundle_xml_node = new XMLNode (*child);
1347 if (version < 3000) {
1348 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1349 error << _("Session: XML state has no diskstreams section") << endmsg;
1351 } else if (load_diskstreams_2X (*child, version)) {
1356 if ((child = find_named_node (node, "Routes")) == 0) {
1357 error << _("Session: XML state has no routes section") << endmsg;
1359 } else if (load_routes (*child, version)) {
1363 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1364 _diskstreams_2X.clear ();
1366 if (version >= 3000) {
1368 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1369 error << _("Session: XML state has no route groups section") << endmsg;
1371 } else if (load_route_groups (*child, version)) {
1375 } else if (version < 3000) {
1377 if ((child = find_named_node (node, "EditGroups")) == 0) {
1378 error << _("Session: XML state has no edit groups section") << endmsg;
1380 } else if (load_route_groups (*child, version)) {
1384 if ((child = find_named_node (node, "MixGroups")) == 0) {
1385 error << _("Session: XML state has no mix groups section") << endmsg;
1387 } else if (load_route_groups (*child, version)) {
1392 if ((child = find_named_node (node, "Click")) == 0) {
1393 warning << _("Session: XML state has no click section") << endmsg;
1394 } else if (_click_io) {
1395 setup_click_state (&node);
1398 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1399 ControlProtocolManager::instance().set_state (*child, version);
1402 update_route_record_state ();
1404 /* here beginneth the second phase ... */
1406 StateReady (); /* EMIT SIGNAL */
1419 Session::load_routes (const XMLNode& node, int version)
1422 XMLNodeConstIterator niter;
1423 RouteList new_routes;
1425 nlist = node.children();
1429 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1431 boost::shared_ptr<Route> route;
1432 if (version < 3000) {
1433 route = XMLRouteFactory_2X (**niter, version);
1435 route = XMLRouteFactory (**niter, version);
1439 error << _("Session: cannot create Route from XML description.") << endmsg;
1443 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1445 new_routes.push_back (route);
1448 BootMessage (_("Tracks/busses loaded; Adding to Session"));
1450 add_routes (new_routes, false, false, false);
1452 BootMessage (_("Finished adding tracks/busses"));
1457 boost::shared_ptr<Route>
1458 Session::XMLRouteFactory (const XMLNode& node, int version)
1460 boost::shared_ptr<Route> ret;
1462 if (node.name() != "Route") {
1466 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1468 DataType type = DataType::AUDIO;
1469 const XMLProperty* prop = node.property("default-type");
1472 type = DataType (prop->value());
1475 assert (type != DataType::NIL);
1479 boost::shared_ptr<Track> track;
1481 if (type == DataType::AUDIO) {
1482 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1484 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1487 if (track->init()) {
1491 if (track->set_state (node, version)) {
1495 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1496 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1501 enum Route::Flag flags = Route::Flag(0);
1502 const XMLProperty* prop = node.property("flags");
1504 flags = Route::Flag (string_2_enum (prop->value(), flags));
1507 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1509 if (r->init () == 0 && r->set_state (node, version) == 0) {
1510 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1511 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1520 boost::shared_ptr<Route>
1521 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1523 boost::shared_ptr<Route> ret;
1525 if (node.name() != "Route") {
1529 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1531 ds_prop = node.property (X_("diskstream"));
1534 DataType type = DataType::AUDIO;
1535 const XMLProperty* prop = node.property("default-type");
1538 type = DataType (prop->value());
1541 assert (type != DataType::NIL);
1545 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1546 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1550 if (i == _diskstreams_2X.end()) {
1551 error << _("Could not find diskstream for route") << endmsg;
1552 return boost::shared_ptr<Route> ();
1555 boost::shared_ptr<Track> track;
1557 if (type == DataType::AUDIO) {
1558 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1560 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1563 if (track->init()) {
1567 if (track->set_state (node, version)) {
1571 track->set_diskstream (*i);
1573 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1574 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1579 enum Route::Flag flags = Route::Flag(0);
1580 const XMLProperty* prop = node.property("flags");
1582 flags = Route::Flag (string_2_enum (prop->value(), flags));
1585 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1587 if (r->init () == 0 && r->set_state (node, version) == 0) {
1588 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1589 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1599 Session::load_regions (const XMLNode& node)
1602 XMLNodeConstIterator niter;
1603 boost::shared_ptr<Region> region;
1605 nlist = node.children();
1609 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1610 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1611 error << _("Session: cannot create Region from XML description.");
1612 const XMLProperty *name = (**niter).property("name");
1615 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1626 Session::load_compounds (const XMLNode& node)
1628 XMLNodeList calist = node.children();
1629 XMLNodeConstIterator caiter;
1630 XMLProperty *caprop;
1632 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1633 XMLNode* ca = *caiter;
1637 if ((caprop = ca->property (X_("original"))) == 0) {
1640 orig_id = caprop->value();
1642 if ((caprop = ca->property (X_("copy"))) == 0) {
1645 copy_id = caprop->value();
1647 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1648 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1650 if (!orig || !copy) {
1651 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1657 RegionFactory::add_compound_association (orig, copy);
1664 Session::load_nested_sources (const XMLNode& node)
1667 XMLNodeConstIterator niter;
1669 nlist = node.children();
1671 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1672 if ((*niter)->name() == "Source") {
1674 /* it may already exist, so don't recreate it unnecessarily
1677 XMLProperty* prop = (*niter)->property (X_("id"));
1679 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1683 ID source_id (prop->value());
1685 if (!source_by_id (source_id)) {
1688 SourceFactory::create (*this, **niter, true);
1690 catch (failed_constructor& err) {
1691 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1698 boost::shared_ptr<Region>
1699 Session::XMLRegionFactory (const XMLNode& node, bool full)
1701 const XMLProperty* type = node.property("type");
1705 const XMLNodeList& nlist = node.children();
1707 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1708 XMLNode *child = (*niter);
1709 if (child->name() == "NestedSource") {
1710 load_nested_sources (*child);
1714 if (!type || type->value() == "audio") {
1715 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1716 } else if (type->value() == "midi") {
1717 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1720 } catch (failed_constructor& err) {
1721 return boost::shared_ptr<Region> ();
1724 return boost::shared_ptr<Region> ();
1727 boost::shared_ptr<AudioRegion>
1728 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1730 const XMLProperty* prop;
1731 boost::shared_ptr<Source> source;
1732 boost::shared_ptr<AudioSource> as;
1734 SourceList master_sources;
1735 uint32_t nchans = 1;
1738 if (node.name() != X_("Region")) {
1739 return boost::shared_ptr<AudioRegion>();
1742 if ((prop = node.property (X_("channels"))) != 0) {
1743 nchans = atoi (prop->value().c_str());
1746 if ((prop = node.property ("name")) == 0) {
1747 cerr << "no name for this region\n";
1751 if ((prop = node.property (X_("source-0"))) == 0) {
1752 if ((prop = node.property ("source")) == 0) {
1753 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1754 return boost::shared_ptr<AudioRegion>();
1758 PBD::ID s_id (prop->value());
1760 if ((source = source_by_id (s_id)) == 0) {
1761 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1762 return boost::shared_ptr<AudioRegion>();
1765 as = boost::dynamic_pointer_cast<AudioSource>(source);
1767 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1768 return boost::shared_ptr<AudioRegion>();
1771 sources.push_back (as);
1773 /* pickup other channels */
1775 for (uint32_t n=1; n < nchans; ++n) {
1776 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1777 if ((prop = node.property (buf)) != 0) {
1779 PBD::ID id2 (prop->value());
1781 if ((source = source_by_id (id2)) == 0) {
1782 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1783 return boost::shared_ptr<AudioRegion>();
1786 as = boost::dynamic_pointer_cast<AudioSource>(source);
1788 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1789 return boost::shared_ptr<AudioRegion>();
1791 sources.push_back (as);
1795 for (uint32_t n = 0; n < nchans; ++n) {
1796 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1797 if ((prop = node.property (buf)) != 0) {
1799 PBD::ID id2 (prop->value());
1801 if ((source = source_by_id (id2)) == 0) {
1802 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1803 return boost::shared_ptr<AudioRegion>();
1806 as = boost::dynamic_pointer_cast<AudioSource>(source);
1808 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1809 return boost::shared_ptr<AudioRegion>();
1811 master_sources.push_back (as);
1816 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1818 /* a final detail: this is the one and only place that we know how long missing files are */
1820 if (region->whole_file()) {
1821 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1822 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1824 sfp->set_length (region->length());
1829 if (!master_sources.empty()) {
1830 if (master_sources.size() != nchans) {
1831 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1833 region->set_master_sources (master_sources);
1841 catch (failed_constructor& err) {
1842 return boost::shared_ptr<AudioRegion>();
1846 boost::shared_ptr<MidiRegion>
1847 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1849 const XMLProperty* prop;
1850 boost::shared_ptr<Source> source;
1851 boost::shared_ptr<MidiSource> ms;
1854 if (node.name() != X_("Region")) {
1855 return boost::shared_ptr<MidiRegion>();
1858 if ((prop = node.property ("name")) == 0) {
1859 cerr << "no name for this region\n";
1863 if ((prop = node.property (X_("source-0"))) == 0) {
1864 if ((prop = node.property ("source")) == 0) {
1865 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1866 return boost::shared_ptr<MidiRegion>();
1870 PBD::ID s_id (prop->value());
1872 if ((source = source_by_id (s_id)) == 0) {
1873 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1874 return boost::shared_ptr<MidiRegion>();
1877 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1879 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1880 return boost::shared_ptr<MidiRegion>();
1883 sources.push_back (ms);
1886 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1887 /* a final detail: this is the one and only place that we know how long missing files are */
1889 if (region->whole_file()) {
1890 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1891 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1893 sfp->set_length (region->length());
1901 catch (failed_constructor& err) {
1902 return boost::shared_ptr<MidiRegion>();
1907 Session::get_sources_as_xml ()
1910 XMLNode* node = new XMLNode (X_("Sources"));
1911 Glib::Threads::Mutex::Lock lm (source_lock);
1913 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1914 node->add_child_nocopy (i->second->get_state());
1921 Session::reset_write_sources (bool mark_write_complete, bool force)
1923 boost::shared_ptr<RouteList> rl = routes.reader();
1924 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1925 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1927 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
1928 tr->reset_write_sources(mark_write_complete, force);
1929 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
1935 Session::load_sources (const XMLNode& node)
1938 XMLNodeConstIterator niter;
1939 boost::shared_ptr<Source> source; /* don't need this but it stops some
1940 * versions of gcc complaining about
1941 * discarded return values.
1944 nlist = node.children();
1948 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1951 if ((source = XMLSourceFactory (**niter)) == 0) {
1952 error << _("Session: cannot create Source from XML description.") << endmsg;
1955 } catch (MissingSource& err) {
1959 if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
1960 error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
1961 PROGRAM_NAME) << endmsg;
1965 if (!no_questions_about_missing_files) {
1966 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1971 switch (user_choice) {
1973 /* user added a new search location, so try again */
1978 /* user asked to quit the entire session load
1983 no_questions_about_missing_files = true;
1987 no_questions_about_missing_files = true;
1994 case DataType::AUDIO:
1995 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1998 case DataType::MIDI:
1999 /* The MIDI file is actually missing so
2000 * just create a new one in the same
2001 * location. Do not announce its
2005 if (!Glib::path_is_absolute (err.path)) {
2006 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
2008 /* this should be an unrecoverable error: we would be creating a MIDI file outside
2013 /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
2014 source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
2015 /* reset ID to match the missing one */
2016 source->set_id (**niter);
2017 /* Now we can announce it */
2018 SourceFactory::SourceCreated (source);
2029 boost::shared_ptr<Source>
2030 Session::XMLSourceFactory (const XMLNode& node)
2032 if (node.name() != "Source") {
2033 return boost::shared_ptr<Source>();
2037 /* note: do peak building in another thread when loading session state */
2038 return SourceFactory::create (*this, node, true);
2041 catch (failed_constructor& err) {
2042 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
2043 return boost::shared_ptr<Source>();
2048 Session::save_template (string template_name)
2050 if ((_state_of_the_state & CannotSave) || template_name.empty ()) {
2054 bool absolute_path = Glib::path_is_absolute (template_name);
2056 /* directory to put the template in */
2057 std::string template_dir_path;
2059 if (!absolute_path) {
2060 std::string user_template_dir(user_template_directory());
2062 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2063 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2064 user_template_dir, g_strerror (errno)) << endmsg;
2068 template_dir_path = Glib::build_filename (user_template_dir, template_name);
2070 template_dir_path = template_name;
2073 if (!ARDOUR::Profile->get_trx()) {
2074 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2075 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2076 template_dir_path) << endmsg;
2080 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2081 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2082 template_dir_path, g_strerror (errno)) << endmsg;
2088 std::string template_file_path;
2090 if (ARDOUR::Profile->get_trx()) {
2091 template_file_path = template_name;
2093 if (absolute_path) {
2094 template_file_path = Glib::build_filename (template_dir_path, Glib::path_get_basename (template_dir_path) + template_suffix);
2096 template_file_path = Glib::build_filename (template_dir_path, template_name + template_suffix);
2100 SessionSaveUnderway (); /* EMIT SIGNAL */
2104 tree.set_root (&get_template());
2105 if (!tree.write (template_file_path)) {
2106 error << _("template not saved") << endmsg;
2110 if (!ARDOUR::Profile->get_trx()) {
2111 /* copy plugin state directory */
2113 std::string template_plugin_state_path (Glib::build_filename (template_dir_path, X_("plugins")));
2115 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
2116 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
2117 template_plugin_state_path, g_strerror (errno)) << endmsg;
2120 copy_files (plugins_dir(), template_plugin_state_path);
2123 store_recent_templates (template_file_path);
2129 Session::refresh_disk_space ()
2131 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2133 Glib::Threads::Mutex::Lock lm (space_lock);
2135 /* get freespace on every FS that is part of the session path */
2137 _total_free_4k_blocks = 0;
2138 _total_free_4k_blocks_uncertain = false;
2140 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2142 struct statfs statfsbuf;
2143 statfs (i->path.c_str(), &statfsbuf);
2145 double const scale = statfsbuf.f_bsize / 4096.0;
2147 /* See if this filesystem is read-only */
2148 struct statvfs statvfsbuf;
2149 statvfs (i->path.c_str(), &statvfsbuf);
2151 /* f_bavail can be 0 if it is undefined for whatever
2152 filesystem we are looking at; Samba shares mounted
2153 via GVFS are an example of this.
2155 if (statfsbuf.f_bavail == 0) {
2156 /* block count unknown */
2158 i->blocks_unknown = true;
2159 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2160 /* read-only filesystem */
2162 i->blocks_unknown = false;
2164 /* read/write filesystem with known space */
2165 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2166 i->blocks_unknown = false;
2169 _total_free_4k_blocks += i->blocks;
2170 if (i->blocks_unknown) {
2171 _total_free_4k_blocks_uncertain = true;
2174 #elif defined PLATFORM_WINDOWS
2175 vector<string> scanned_volumes;
2176 vector<string>::iterator j;
2177 vector<space_and_path>::iterator i;
2178 DWORD nSectorsPerCluster, nBytesPerSector,
2179 nFreeClusters, nTotalClusters;
2183 _total_free_4k_blocks = 0;
2185 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2186 strncpy (disk_drive, (*i).path.c_str(), 3);
2190 volume_found = false;
2191 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2193 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2194 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2195 i->blocks = (uint32_t)(nFreeBytes / 4096);
2197 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2198 if (0 == j->compare(disk_drive)) {
2199 volume_found = true;
2204 if (!volume_found) {
2205 scanned_volumes.push_back(disk_drive);
2206 _total_free_4k_blocks += i->blocks;
2211 if (0 == _total_free_4k_blocks) {
2212 strncpy (disk_drive, path().c_str(), 3);
2215 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2217 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2218 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2219 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2226 Session::get_best_session_directory_for_new_audio ()
2228 vector<space_and_path>::iterator i;
2229 string result = _session_dir->root_path();
2231 /* handle common case without system calls */
2233 if (session_dirs.size() == 1) {
2237 /* OK, here's the algorithm we're following here:
2239 We want to select which directory to use for
2240 the next file source to be created. Ideally,
2241 we'd like to use a round-robin process so as to
2242 get maximum performance benefits from splitting
2243 the files across multiple disks.
2245 However, in situations without much diskspace, an
2246 RR approach may end up filling up a filesystem
2247 with new files while others still have space.
2248 Its therefore important to pay some attention to
2249 the freespace in the filesystem holding each
2250 directory as well. However, if we did that by
2251 itself, we'd keep creating new files in the file
2252 system with the most space until it was as full
2253 as all others, thus negating any performance
2254 benefits of this RAID-1 like approach.
2256 So, we use a user-configurable space threshold. If
2257 there are at least 2 filesystems with more than this
2258 much space available, we use RR selection between them.
2259 If not, then we pick the filesystem with the most space.
2261 This gets a good balance between the two
2265 refresh_disk_space ();
2267 int free_enough = 0;
2269 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2270 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2275 if (free_enough >= 2) {
2276 /* use RR selection process, ensuring that the one
2280 i = last_rr_session_dir;
2283 if (++i == session_dirs.end()) {
2284 i = session_dirs.begin();
2287 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2288 SessionDirectory sdir(i->path);
2289 if (sdir.create ()) {
2291 last_rr_session_dir = i;
2296 } while (i != last_rr_session_dir);
2300 /* pick FS with the most freespace (and that
2301 seems to actually work ...)
2304 vector<space_and_path> sorted;
2305 space_and_path_ascending_cmp cmp;
2307 sorted = session_dirs;
2308 sort (sorted.begin(), sorted.end(), cmp);
2310 for (i = sorted.begin(); i != sorted.end(); ++i) {
2311 SessionDirectory sdir(i->path);
2312 if (sdir.create ()) {
2314 last_rr_session_dir = i;
2324 Session::automation_dir () const
2326 return Glib::build_filename (_path, "automation");
2330 Session::analysis_dir () const
2332 return Glib::build_filename (_path, "analysis");
2336 Session::plugins_dir () const
2338 return Glib::build_filename (_path, "plugins");
2342 Session::externals_dir () const
2344 return Glib::build_filename (_path, "externals");
2348 Session::load_bundles (XMLNode const & node)
2350 XMLNodeList nlist = node.children();
2351 XMLNodeConstIterator niter;
2355 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2356 if ((*niter)->name() == "InputBundle") {
2357 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2358 } else if ((*niter)->name() == "OutputBundle") {
2359 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2361 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2370 Session::load_route_groups (const XMLNode& node, int version)
2372 XMLNodeList nlist = node.children();
2373 XMLNodeConstIterator niter;
2377 if (version >= 3000) {
2379 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2380 if ((*niter)->name() == "RouteGroup") {
2381 RouteGroup* rg = new RouteGroup (*this, "");
2382 add_route_group (rg);
2383 rg->set_state (**niter, version);
2387 } else if (version < 3000) {
2389 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2390 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2391 RouteGroup* rg = new RouteGroup (*this, "");
2392 add_route_group (rg);
2393 rg->set_state (**niter, version);
2402 state_file_filter (const string &str, void* /*arg*/)
2404 return (str.length() > strlen(statefile_suffix) &&
2405 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2409 remove_end(string state)
2411 string statename(state);
2413 string::size_type start,end;
2414 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2415 statename = statename.substr (start+1);
2418 if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2419 end = statename.length();
2422 return string(statename.substr (0, end));
2426 Session::possible_states (string path)
2428 vector<string> states;
2429 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2431 transform(states.begin(), states.end(), states.begin(), remove_end);
2433 sort (states.begin(), states.end());
2439 Session::possible_states () const
2441 return possible_states(_path);
2445 Session::add_route_group (RouteGroup* g)
2447 _route_groups.push_back (g);
2448 route_group_added (g); /* EMIT SIGNAL */
2450 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2451 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2452 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2458 Session::remove_route_group (RouteGroup& rg)
2460 list<RouteGroup*>::iterator i;
2462 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2463 _route_groups.erase (i);
2466 route_group_removed (); /* EMIT SIGNAL */
2470 /** Set a new order for our route groups, without adding or removing any.
2471 * @param groups Route group list in the new order.
2474 Session::reorder_route_groups (list<RouteGroup*> groups)
2476 _route_groups = groups;
2478 route_groups_reordered (); /* EMIT SIGNAL */
2484 Session::route_group_by_name (string name)
2486 list<RouteGroup *>::iterator i;
2488 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2489 if ((*i)->name() == name) {
2497 Session::all_route_group() const
2499 return *_all_route_group;
2503 Session::add_commands (vector<Command*> const & cmds)
2505 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2511 Session::begin_reversible_command (const string& name)
2513 begin_reversible_command (g_quark_from_string (name.c_str ()));
2516 /** Begin a reversible command using a GQuark to identify it.
2517 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2518 * but there must be as many begin...()s as there are commit...()s.
2521 Session::begin_reversible_command (GQuark q)
2523 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2524 to hold all the commands that are committed. This keeps the order of
2525 commands correct in the history.
2528 if (_current_trans == 0) {
2529 /* start a new transaction */
2530 assert (_current_trans_quarks.empty ());
2531 _current_trans = new UndoTransaction();
2532 _current_trans->set_name (g_quark_to_string (q));
2535 _current_trans_quarks.push_front (q);
2539 Session::abort_reversible_command ()
2541 if (_current_trans != 0) {
2542 _current_trans->clear();
2543 delete _current_trans;
2545 _current_trans_quarks.clear();
2550 Session::commit_reversible_command (Command *cmd)
2552 assert (_current_trans);
2553 assert (!_current_trans_quarks.empty ());
2558 _current_trans->add_command (cmd);
2561 _current_trans_quarks.pop_front ();
2563 if (!_current_trans_quarks.empty ()) {
2564 /* the transaction we're committing is not the top-level one */
2568 if (_current_trans->empty()) {
2569 /* no commands were added to the transaction, so just get rid of it */
2570 delete _current_trans;
2575 gettimeofday (&now, 0);
2576 _current_trans->set_timestamp (now);
2578 _history.add (_current_trans);
2583 accept_all_audio_files (const string& path, void* /*arg*/)
2585 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2589 if (!AudioFileSource::safe_audio_file_extension (path)) {
2597 accept_all_midi_files (const string& path, void* /*arg*/)
2599 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2603 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2604 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2605 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2609 accept_all_state_files (const string& path, void* /*arg*/)
2611 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2615 std::string const statefile_ext (statefile_suffix);
2616 if (path.length() >= statefile_ext.length()) {
2617 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2624 Session::find_all_sources (string path, set<string>& result)
2629 if (!tree.read (path)) {
2633 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2638 XMLNodeConstIterator niter;
2640 nlist = node->children();
2644 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2648 if ((prop = (*niter)->property (X_("type"))) == 0) {
2652 DataType type (prop->value());
2654 if ((prop = (*niter)->property (X_("name"))) == 0) {
2658 if (Glib::path_is_absolute (prop->value())) {
2659 /* external file, ignore */
2667 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2668 result.insert (found_path);
2676 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2678 vector<string> state_files;
2680 string this_snapshot_path;
2686 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2687 ripped = ripped.substr (0, ripped.length() - 1);
2690 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2692 if (state_files.empty()) {
2697 this_snapshot_path = _path;
2698 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2699 this_snapshot_path += statefile_suffix;
2701 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2703 if (exclude_this_snapshot && *i == this_snapshot_path) {
2707 if (find_all_sources (*i, result) < 0) {
2715 struct RegionCounter {
2716 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2717 AudioSourceList::iterator iter;
2718 boost::shared_ptr<Region> region;
2721 RegionCounter() : count (0) {}
2725 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2727 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2728 return r.get_value_or (1);
2732 Session::cleanup_regions ()
2734 bool removed = false;
2735 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2737 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2739 uint32_t used = playlists->region_use_count (i->second);
2741 if (used == 0 && !i->second->automatic ()) {
2743 RegionFactory::map_remove (i->second);
2748 // re-check to remove parent references of compound regions
2749 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2750 if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2753 assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2754 if (0 == playlists->region_use_count (i->second)) {
2755 RegionFactory::map_remove (i->second);
2760 /* dump the history list */
2767 Session::cleanup_sources (CleanupReport& rep)
2769 // FIXME: needs adaptation to midi
2771 vector<boost::shared_ptr<Source> > dead_sources;
2774 vector<string> candidates;
2775 vector<string> unused;
2776 set<string> all_sources;
2785 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2787 /* consider deleting all unused playlists */
2789 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2794 /* sync the "all regions" property of each playlist with its current state
2797 playlists->sync_all_regions_with_regions ();
2799 /* find all un-used sources */
2804 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2806 SourceMap::iterator tmp;
2811 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2815 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2816 dead_sources.push_back (i->second);
2817 i->second->drop_references ();
2823 /* build a list of all the possible audio directories for the session */
2825 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2826 SessionDirectory sdir ((*i).path);
2827 asp += sdir.sound_path();
2829 audio_path += asp.to_string();
2832 /* build a list of all the possible midi directories for the session */
2834 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2835 SessionDirectory sdir ((*i).path);
2836 msp += sdir.midi_path();
2838 midi_path += msp.to_string();
2840 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
2841 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
2843 /* find all sources, but don't use this snapshot because the
2844 state file on disk still references sources we may have already
2848 find_all_sources_across_snapshots (all_sources, true);
2850 /* add our current source list
2853 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2854 boost::shared_ptr<FileSource> fs;
2855 SourceMap::iterator tmp = i;
2858 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2860 if (!fs->is_stub()) {
2862 if (playlists->source_use_count (fs) != 0) {
2863 all_sources.insert (fs->path());
2866 /* we might not remove this source from disk, because it may be used
2867 by other snapshots, but its not being used in this version
2868 so lets get rid of it now, along with any representative regions
2872 RegionFactory::remove_regions_using_source (i->second);
2875 // also remove source from all_sources
2877 for (set<string>::iterator j = all_sources.begin(); j != all_sources.end(); ++j) {
2878 spath = Glib::path_get_basename (*j);
2879 if ( spath == i->second->name () ) {
2880 all_sources.erase (j);
2891 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
2896 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2898 tmppath1 = canonical_path (spath);
2899 tmppath2 = canonical_path ((*i));
2901 if (tmppath1 == tmppath2) {
2908 unused.push_back (spath);
2912 /* now try to move all unused files into the "dead" directory(ies) */
2914 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2915 struct stat statbuf;
2919 /* don't move the file across filesystems, just
2920 stick it in the `dead_dir_name' directory
2921 on whichever filesystem it was already on.
2924 if ((*x).find ("/sounds/") != string::npos) {
2926 /* old school, go up 1 level */
2928 newpath = Glib::path_get_dirname (*x); // "sounds"
2929 newpath = Glib::path_get_dirname (newpath); // "session-name"
2933 /* new school, go up 4 levels */
2935 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2936 newpath = Glib::path_get_dirname (newpath); // "session-name"
2937 newpath = Glib::path_get_dirname (newpath); // "interchange"
2938 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2941 newpath = Glib::build_filename (newpath, dead_dir_name);
2943 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2944 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2948 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2950 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2952 /* the new path already exists, try versioning */
2954 char buf[PATH_MAX+1];
2958 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2961 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2962 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2966 if (version == 999) {
2967 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2971 newpath = newpath_v;
2976 /* it doesn't exist, or we can't read it or something */
2980 stat ((*x).c_str(), &statbuf);
2982 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2983 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2984 (*x), newpath, strerror (errno))
2989 /* see if there an easy to find peakfile for this file, and remove it.
2992 string base = basename_nosuffix (*x);
2993 base += "%A"; /* this is what we add for the channel suffix of all native files,
2994 or for the first channel of embedded files. it will miss
2995 some peakfiles for other channels
2997 string peakpath = peak_path (base);
2999 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
3000 if (::g_unlink (peakpath.c_str()) != 0) {
3001 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
3002 peakpath, _path, strerror (errno))
3004 /* try to back out */
3005 ::rename (newpath.c_str(), _path.c_str());
3010 rep.paths.push_back (*x);
3011 rep.space += statbuf.st_size;
3014 /* dump the history list */
3018 /* save state so we don't end up a session file
3019 referring to non-existent sources.
3026 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
3032 Session::cleanup_trash_sources (CleanupReport& rep)
3034 // FIXME: needs adaptation for MIDI
3036 vector<space_and_path>::iterator i;
3042 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3044 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
3046 clear_directory (dead_dir, &rep.space, &rep.paths);
3053 Session::set_dirty ()
3055 /* never mark session dirty during loading */
3057 if (_state_of_the_state & Loading) {
3061 bool was_dirty = dirty();
3063 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3067 DirtyChanged(); /* EMIT SIGNAL */
3073 Session::set_clean ()
3075 bool was_dirty = dirty();
3077 _state_of_the_state = Clean;
3081 DirtyChanged(); /* EMIT SIGNAL */
3086 Session::set_deletion_in_progress ()
3088 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3092 Session::clear_deletion_in_progress ()
3094 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3098 Session::add_controllable (boost::shared_ptr<Controllable> c)
3100 /* this adds a controllable to the list managed by the Session.
3101 this is a subset of those managed by the Controllable class
3102 itself, and represents the only ones whose state will be saved
3103 as part of the session.
3106 Glib::Threads::Mutex::Lock lm (controllables_lock);
3107 controllables.insert (c);
3110 struct null_deleter { void operator()(void const *) const {} };
3113 Session::remove_controllable (Controllable* c)
3115 if (_state_of_the_state & Deletion) {
3119 Glib::Threads::Mutex::Lock lm (controllables_lock);
3121 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3123 if (x != controllables.end()) {
3124 controllables.erase (x);
3128 boost::shared_ptr<Controllable>
3129 Session::controllable_by_id (const PBD::ID& id)
3131 Glib::Threads::Mutex::Lock lm (controllables_lock);
3133 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3134 if ((*i)->id() == id) {
3139 return boost::shared_ptr<Controllable>();
3142 boost::shared_ptr<Controllable>
3143 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3145 boost::shared_ptr<Controllable> c;
3146 boost::shared_ptr<Route> r;
3148 switch (desc.top_level_type()) {
3149 case ControllableDescriptor::NamedRoute:
3151 std::string str = desc.top_level_name();
3152 if (str == "Master" || str == "master") {
3154 } else if (str == "control" || str == "listen") {
3157 r = route_by_name (desc.top_level_name());
3162 case ControllableDescriptor::RemoteControlID:
3163 r = route_by_remote_id (desc.rid());
3171 switch (desc.subtype()) {
3172 case ControllableDescriptor::Gain:
3173 c = r->gain_control ();
3176 case ControllableDescriptor::Trim:
3177 c = r->trim()->gain_control ();
3180 case ControllableDescriptor::Solo:
3181 c = r->solo_control();
3184 case ControllableDescriptor::Mute:
3185 c = r->mute_control();
3188 case ControllableDescriptor::Recenable:
3190 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3193 c = t->rec_enable_control ();
3198 case ControllableDescriptor::PanDirection:
3200 c = r->pannable()->pan_azimuth_control;
3204 case ControllableDescriptor::PanWidth:
3206 c = r->pannable()->pan_width_control;
3210 case ControllableDescriptor::PanElevation:
3212 c = r->pannable()->pan_elevation_control;
3216 case ControllableDescriptor::Balance:
3217 /* XXX simple pan control */
3220 case ControllableDescriptor::PluginParameter:
3222 uint32_t plugin = desc.target (0);
3223 uint32_t parameter_index = desc.target (1);
3225 /* revert to zero based counting */
3231 if (parameter_index > 0) {
3235 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3238 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3239 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3244 case ControllableDescriptor::SendGain:
3246 uint32_t send = desc.target (0);
3248 /* revert to zero-based counting */
3254 boost::shared_ptr<Processor> p = r->nth_send (send);
3257 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3258 boost::shared_ptr<Amp> a = s->amp();
3261 c = s->amp()->gain_control();
3268 /* relax and return a null pointer */
3276 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3279 Stateful::add_instant_xml (node, _path);
3282 if (write_to_config) {
3283 Config->add_instant_xml (node);
3288 Session::instant_xml (const string& node_name)
3290 return Stateful::instant_xml (node_name, _path);
3294 Session::save_history (string snapshot_name)
3302 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3303 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3307 if (snapshot_name.empty()) {
3308 snapshot_name = _current_snapshot_name;
3311 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3312 const string backup_filename = history_filename + backup_suffix;
3313 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3314 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3316 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3317 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3318 error << _("could not backup old history file, current history not saved") << endmsg;
3323 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3325 if (!tree.write (xml_path))
3327 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3329 if (g_remove (xml_path.c_str()) != 0) {
3330 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3331 xml_path, g_strerror (errno)) << endmsg;
3333 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3334 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3335 backup_path, g_strerror (errno)) << endmsg;
3345 Session::restore_history (string snapshot_name)
3349 if (snapshot_name.empty()) {
3350 snapshot_name = _current_snapshot_name;
3353 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3354 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3356 info << "Loading history from " << xml_path << endmsg;
3358 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3359 info << string_compose (_("%1: no history file \"%2\" for this session."),
3360 _name, xml_path) << endmsg;
3364 if (!tree.read (xml_path)) {
3365 error << string_compose (_("Could not understand session history file \"%1\""),
3366 xml_path) << endmsg;
3373 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3376 UndoTransaction* ut = new UndoTransaction ();
3379 ut->set_name(t->property("name")->value());
3380 stringstream ss(t->property("tv-sec")->value());
3382 ss.str(t->property("tv-usec")->value());
3384 ut->set_timestamp(tv);
3386 for (XMLNodeConstIterator child_it = t->children().begin();
3387 child_it != t->children().end(); child_it++)
3389 XMLNode *n = *child_it;
3392 if (n->name() == "MementoCommand" ||
3393 n->name() == "MementoUndoCommand" ||
3394 n->name() == "MementoRedoCommand") {
3396 if ((c = memento_command_factory(n))) {
3400 } else if (n->name() == "NoteDiffCommand") {
3401 PBD::ID id (n->property("midi-source")->value());
3402 boost::shared_ptr<MidiSource> midi_source =
3403 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3405 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3407 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3410 } else if (n->name() == "SysExDiffCommand") {
3412 PBD::ID id (n->property("midi-source")->value());
3413 boost::shared_ptr<MidiSource> midi_source =
3414 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3416 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3418 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3421 } else if (n->name() == "PatchChangeDiffCommand") {
3423 PBD::ID id (n->property("midi-source")->value());
3424 boost::shared_ptr<MidiSource> midi_source =
3425 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3427 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3429 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3432 } else if (n->name() == "StatefulDiffCommand") {
3433 if ((c = stateful_diff_command_factory (n))) {
3434 ut->add_command (c);
3437 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3448 Session::config_changed (std::string p, bool ours)
3454 if (p == "seamless-loop") {
3456 } else if (p == "rf-speed") {
3458 } else if (p == "auto-loop") {
3460 } else if (p == "auto-input") {
3462 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3463 /* auto-input only makes a difference if we're rolling */
3464 set_track_monitor_input_status (!config.get_auto_input());
3467 } else if (p == "punch-in") {
3471 if ((location = _locations->auto_punch_location()) != 0) {
3473 if (config.get_punch_in ()) {
3474 replace_event (SessionEvent::PunchIn, location->start());
3476 remove_event (location->start(), SessionEvent::PunchIn);
3480 } else if (p == "punch-out") {
3484 if ((location = _locations->auto_punch_location()) != 0) {
3486 if (config.get_punch_out()) {
3487 replace_event (SessionEvent::PunchOut, location->end());
3489 clear_events (SessionEvent::PunchOut);
3493 } else if (p == "edit-mode") {
3495 Glib::Threads::Mutex::Lock lm (playlists->lock);
3497 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3498 (*i)->set_edit_mode (Config->get_edit_mode ());
3501 } else if (p == "use-video-sync") {
3503 waiting_for_sync_offset = config.get_use_video_sync();
3505 } else if (p == "mmc-control") {
3507 //poke_midi_thread ();
3509 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3511 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3513 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3515 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3517 } else if (p == "midi-control") {
3519 //poke_midi_thread ();
3521 } else if (p == "raid-path") {
3523 setup_raid_path (config.get_raid_path());
3525 } else if (p == "timecode-format") {
3529 } else if (p == "video-pullup") {
3533 } else if (p == "seamless-loop") {
3535 if (play_loop && transport_rolling()) {
3536 // to reset diskstreams etc
3537 request_play_loop (true);
3540 } else if (p == "rf-speed") {
3542 cumulative_rf_motion = 0;
3545 } else if (p == "click-sound") {
3547 setup_click_sounds (1);
3549 } else if (p == "click-emphasis-sound") {
3551 setup_click_sounds (-1);
3553 } else if (p == "clicking") {
3555 if (Config->get_clicking()) {
3556 if (_click_io && click_data) { // don't require emphasis data
3563 } else if (p == "click-gain") {
3566 _click_gain->set_gain (Config->get_click_gain(), this);
3569 } else if (p == "send-mtc") {
3571 if (Config->get_send_mtc ()) {
3572 /* mark us ready to send */
3573 next_quarter_frame_to_send = 0;
3576 } else if (p == "send-mmc") {
3578 _mmc->enable_send (Config->get_send_mmc ());
3580 } else if (p == "midi-feedback") {
3582 session_midi_feedback = Config->get_midi_feedback();
3584 } else if (p == "jack-time-master") {
3586 engine().reset_timebase ();
3588 } else if (p == "native-file-header-format") {
3590 if (!first_file_header_format_reset) {
3591 reset_native_file_format ();
3594 first_file_header_format_reset = false;
3596 } else if (p == "native-file-data-format") {
3598 if (!first_file_data_format_reset) {
3599 reset_native_file_format ();
3602 first_file_data_format_reset = false;
3604 } else if (p == "external-sync") {
3605 if (!config.get_external_sync()) {
3606 drop_sync_source ();
3608 switch_to_sync_source (Config->get_sync_source());
3610 } else if (p == "denormal-model") {
3612 } else if (p == "history-depth") {
3613 set_history_depth (Config->get_history_depth());
3614 } else if (p == "remote-model") {
3615 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3618 } else if (p == "initial-program-change") {
3620 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3623 buf[0] = MIDI::program; // channel zero by default
3624 buf[1] = (Config->get_initial_program_change() & 0x7f);
3626 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3628 } else if (p == "solo-mute-override") {
3629 // catch_up_on_solo_mute_override ();
3630 } else if (p == "listen-position" || p == "pfl-position") {
3631 listen_position_changed ();
3632 } else if (p == "solo-control-is-listen-control") {
3633 solo_control_mode_changed ();
3634 } else if (p == "solo-mute-gain") {
3635 _solo_cut_control->Changed();
3636 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3637 last_timecode_valid = false;
3638 } else if (p == "playback-buffer-seconds") {
3639 AudioSource::allocate_working_buffers (frame_rate());
3640 } else if (p == "ltc-source-port") {
3641 reconnect_ltc_input ();
3642 } else if (p == "ltc-sink-port") {
3643 reconnect_ltc_output ();
3644 } else if (p == "timecode-generator-offset") {
3645 ltc_tx_parse_offset();
3652 Session::set_history_depth (uint32_t d)
3654 _history.set_depth (d);
3658 Session::load_diskstreams_2X (XMLNode const & node, int)
3661 XMLNodeConstIterator citer;
3663 clist = node.children();
3665 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3668 /* diskstreams added automatically by DiskstreamCreated handler */
3669 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3670 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3671 _diskstreams_2X.push_back (dsp);
3673 error << _("Session: unknown diskstream type in XML") << endmsg;
3677 catch (failed_constructor& err) {
3678 error << _("Session: could not load diskstream via XML state") << endmsg;
3686 /** Connect things to the MMC object */
3688 Session::setup_midi_machine_control ()
3690 _mmc = new MIDI::MachineControl;
3691 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3693 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3694 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3695 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3696 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3697 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3698 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3699 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3700 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3701 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3702 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3703 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3704 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3705 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3707 /* also handle MIDI SPP because its so common */
3709 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3710 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3711 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3714 boost::shared_ptr<Controllable>
3715 Session::solo_cut_control() const
3717 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3718 controls in Ardour that currently get presented to the user in the GUI that require
3719 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3721 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3722 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3726 return _solo_cut_control;
3730 Session::rename (const std::string& new_name)
3732 string legal_name = legalize_for_path (new_name);
3738 string const old_sources_root = _session_dir->sources_root();
3740 if (!_writable || (_state_of_the_state & CannotSave)) {
3741 error << _("Cannot rename read-only session.") << endmsg;
3742 return 0; // don't show "messed up" warning
3744 if (record_status() == Recording) {
3745 error << _("Cannot rename session while recording") << endmsg;
3746 return 0; // don't show "messed up" warning
3749 StateProtector stp (this);
3754 * interchange subdirectory
3758 * Backup files are left unchanged and not renamed.
3761 /* Windows requires that we close all files before attempting the
3762 * rename. This works on other platforms, but isn't necessary there.
3763 * Leave it in place for all platforms though, since it may help
3764 * catch issues that could arise if the way Source files work ever
3765 * change (since most developers are not using Windows).
3768 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
3769 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3775 /* pass one: not 100% safe check that the new directory names don't
3779 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3783 /* this is a stupid hack because Glib::path_get_dirname() is
3784 * lexical-only, and so passing it /a/b/c/ gives a different
3785 * result than passing it /a/b/c ...
3788 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3789 oldstr = oldstr.substr (0, oldstr.length() - 1);
3792 string base = Glib::path_get_dirname (oldstr);
3794 newstr = Glib::build_filename (base, legal_name);
3796 cerr << "Looking for " << newstr << endl;
3798 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3799 cerr << " exists\n";
3808 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3814 /* this is a stupid hack because Glib::path_get_dirname() is
3815 * lexical-only, and so passing it /a/b/c/ gives a different
3816 * result than passing it /a/b/c ...
3819 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3820 oldstr = oldstr.substr (0, oldstr.length() - 1);
3823 string base = Glib::path_get_dirname (oldstr);
3824 newstr = Glib::build_filename (base, legal_name);
3826 cerr << "for " << oldstr << " new dir = " << newstr << endl;
3828 cerr << "Rename " << oldstr << " => " << newstr << endl;
3829 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3830 cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3831 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3835 /* Reset path in "session dirs" */
3840 /* reset primary SessionDirectory object */
3843 (*_session_dir) = newstr;
3848 /* now rename directory below session_dir/interchange */
3850 string old_interchange_dir;
3851 string new_interchange_dir;
3853 /* use newstr here because we renamed the path
3854 * (folder/directory) that used to be oldstr to newstr above
3857 v.push_back (newstr);
3858 v.push_back (interchange_dir_name);
3859 v.push_back (Glib::path_get_basename (oldstr));
3861 old_interchange_dir = Glib::build_filename (v);
3864 v.push_back (newstr);
3865 v.push_back (interchange_dir_name);
3866 v.push_back (legal_name);
3868 new_interchange_dir = Glib::build_filename (v);
3870 cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
3872 if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
3873 cerr << string_compose (_("renaming %s as %2 failed (%3)"),
3874 old_interchange_dir, new_interchange_dir,
3877 error << string_compose (_("renaming %s as %2 failed (%3)"),
3878 old_interchange_dir, new_interchange_dir,
3887 oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
3888 newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
3890 cerr << "Rename " << oldstr << " => " << newstr << endl;
3892 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3893 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3894 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3900 oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
3902 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3903 newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
3905 cerr << "Rename " << oldstr << " => " << newstr << endl;
3907 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3908 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3909 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3914 /* remove old name from recent sessions */
3915 remove_recent_sessions (_path);
3918 /* update file source paths */
3920 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3921 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3923 string p = fs->path ();
3924 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3926 SourceFactory::setup_peakfile(i->second, true);
3930 _current_snapshot_name = new_name;
3935 /* save state again to get everything just right */
3937 save_state (_current_snapshot_name);
3939 /* add to recent sessions */
3941 store_recent_sessions (new_name, _path);
3947 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
3949 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
3953 if (!tree.read (xmlpath)) {
3961 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
3964 bool found_sr = false;
3965 bool found_data_format = false;
3967 if (get_session_info_from_path (tree, xmlpath)) {
3973 const XMLProperty* prop;
3974 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
3975 sample_rate = atoi (prop->value());
3979 const XMLNodeList& children (tree.root()->children());
3980 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
3981 const XMLNode* child = *c;
3982 if (child->name() == "Config") {
3983 const XMLNodeList& options (child->children());
3984 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
3985 const XMLNode* option = *oc;
3986 const XMLProperty* name = option->property("name");
3992 if (name->value() == "native-file-data-format") {
3993 const XMLProperty* value = option->property ("value");
3995 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
3997 found_data_format = true;
4003 if (found_data_format) {
4008 return !(found_sr && found_data_format); // zero if they are both found
4011 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
4012 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
4015 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
4019 SourcePathMap source_path_map;
4021 boost::shared_ptr<AudioFileSource> afs;
4026 Glib::Threads::Mutex::Lock lm (source_lock);
4028 cerr << " total sources = " << sources.size();
4030 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4031 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4037 if (fs->within_session()) {
4041 if (source_path_map.find (fs->path()) != source_path_map.end()) {
4042 source_path_map[fs->path()].push_back (fs);
4044 SeveralFileSources v;
4046 source_path_map.insert (make_pair (fs->path(), v));
4052 cerr << " fsources = " << total << endl;
4054 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
4056 /* tell caller where we are */
4058 string old_path = i->first;
4060 callback (n, total, old_path);
4062 cerr << old_path << endl;
4066 switch (i->second.front()->type()) {
4067 case DataType::AUDIO:
4068 new_path = new_audio_source_path_for_embedded (old_path);
4071 case DataType::MIDI:
4072 /* XXX not implemented yet */
4076 if (new_path.empty()) {
4080 cerr << "Move " << old_path << " => " << new_path << endl;
4082 if (!copy_file (old_path, new_path)) {
4083 cerr << "failed !\n";
4087 /* make sure we stop looking in the external
4088 dir/folder. Remember, this is an all-or-nothing
4089 operations, it doesn't merge just some files.
4091 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
4093 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
4094 (*f)->set_path (new_path);
4099 save_state ("", false, false);
4105 bool accept_all_files (string const &, void *)
4111 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4113 /* 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.
4118 make_new_media_path (string old_path, string new_session_folder, string new_session_path)
4120 /* typedir is the "midifiles" or "audiofiles" etc. part of the path. */
4122 string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4124 v.push_back (new_session_folder); /* full path */
4125 v.push_back (interchange_dir_name);
4126 v.push_back (new_session_path); /* just one directory/folder */
4127 v.push_back (typedir);
4128 v.push_back (Glib::path_get_basename (old_path));
4130 return Glib::build_filename (v);
4134 Session::save_as (SaveAs& saveas)
4136 vector<string> files;
4137 string current_folder = Glib::path_get_dirname (_path);
4138 string new_folder = legalize_for_path (saveas.new_name);
4139 string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4140 int64_t total_bytes = 0;
4144 int32_t internal_file_cnt = 0;
4146 vector<string> do_not_copy_extensions;
4147 do_not_copy_extensions.push_back (statefile_suffix);
4148 do_not_copy_extensions.push_back (pending_suffix);
4149 do_not_copy_extensions.push_back (backup_suffix);
4150 do_not_copy_extensions.push_back (temp_suffix);
4151 do_not_copy_extensions.push_back (history_suffix);
4153 /* get total size */
4155 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4157 /* need to clear this because
4158 * find_files_matching_filter() is cumulative
4163 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4165 all += files.size();
4167 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4169 g_stat ((*i).c_str(), &gsb);
4170 total_bytes += gsb.st_size;
4174 /* save old values so we can switch back if we are not switching to the new session */
4176 string old_path = _path;
4177 string old_name = _name;
4178 string old_snapshot = _current_snapshot_name;
4179 string old_sd = _session_dir->root_path();
4180 vector<string> old_search_path[DataType::num_types];
4181 string old_config_search_path[DataType::num_types];
4183 old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4184 old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4185 old_config_search_path[DataType::AUDIO] = config.get_audio_search_path ();
4186 old_config_search_path[DataType::MIDI] = config.get_midi_search_path ();
4188 /* switch session directory */
4190 (*_session_dir) = to_dir;
4192 /* create new tree */
4194 if (!_session_dir->create()) {
4195 saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4200 /* copy all relevant files. Find each location in session_dirs,
4201 * and copy files from there to target.
4204 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4206 /* need to clear this because
4207 * find_files_matching_filter() is cumulative
4212 const size_t prefix_len = (*sd).path.size();
4214 /* Work just on the files within this session dir */
4216 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4218 /* add dir separator to protect against collisions with
4219 * track names (e.g. track named "audiofiles" or
4223 static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
4224 static const std::string midifile_dir_string = string (midi_dir_name) + G_DIR_SEPARATOR;
4225 static const std::string analysis_dir_string = analysis_dir() + G_DIR_SEPARATOR;
4227 /* copy all the files. Handling is different for media files
4228 than others because of the *silly* subtree we have below the interchange
4229 folder. That really was a bad idea, but I'm not fixing it as part of
4230 implementing ::save_as().
4233 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4235 std::string from = *i;
4238 string filename = Glib::path_get_basename (from);
4239 std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
4240 if (filename == ".DS_STORE") {
4245 if (from.find (audiofile_dir_string) != string::npos) {
4247 /* audio file: only copy if asked */
4249 if (saveas.include_media && saveas.copy_media) {
4251 string to = make_new_media_path (*i, to_dir, new_folder);
4253 info << "media file copying from " << from << " to " << to << endmsg;
4255 if (!copy_file (from, to)) {
4256 throw Glib::FileError (Glib::FileError::IO_ERROR,
4257 string_compose(_("\ncopying \"%1\" failed !"), from));
4261 /* we found media files inside the session folder */
4263 internal_file_cnt++;
4265 } else if (from.find (midifile_dir_string) != string::npos) {
4267 /* midi file: always copy unless
4268 * creating an empty new session
4271 if (saveas.include_media) {
4273 string to = make_new_media_path (*i, to_dir, new_folder);
4275 info << "media file copying from " << from << " to " << to << endmsg;
4277 if (!copy_file (from, to)) {
4278 throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4282 /* we found media files inside the session folder */
4284 internal_file_cnt++;
4286 } else if (from.find (analysis_dir_string) != string::npos) {
4288 /* make sure analysis dir exists in
4289 * new session folder, but we're not
4290 * copying analysis files here, see
4294 (void) g_mkdir_with_parents (analysis_dir().c_str(), 775);
4299 /* normal non-media file. Don't copy state, history, etc.
4302 bool do_copy = true;
4304 for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
4305 if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
4306 /* end of filename matches extension, do not copy file */
4312 if (!saveas.copy_media && from.find (peakfile_suffix) != string::npos) {
4313 /* don't copy peakfiles if
4314 * we're not copying media
4320 string to = Glib::build_filename (to_dir, from.substr (prefix_len));
4322 info << "attempting to make directory/folder " << to << endmsg;
4324 if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
4325 throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
4328 info << "attempting to copy " << from << " to " << to << endmsg;
4330 if (!copy_file (from, to)) {
4331 throw Glib::FileError (Glib::FileError::IO_ERROR,
4332 string_compose(_("\ncopying \"%1\" failed !"), from));
4337 /* measure file size even if we're not going to copy so that our Progress
4338 signals are correct, since we included these do-not-copy files
4339 in the computation of the total size and file count.
4343 g_stat (from.c_str(), &gsb);
4344 copied += gsb.st_size;
4347 double fraction = (double) copied / total_bytes;
4349 bool keep_going = true;
4351 if (saveas.copy_media) {
4353 /* no need or expectation of this if
4354 * media is not being copied, because
4355 * it will be fast(ish).
4358 /* tell someone "X percent, file M of N"; M is one-based */
4360 boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
4368 throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
4374 /* copy optional folders, if any */
4376 string old = plugins_dir ();
4377 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4378 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4379 copy_files (old, newdir);
4382 old = externals_dir ();
4383 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4384 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4385 copy_files (old, newdir);
4388 old = automation_dir ();
4389 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4390 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4391 copy_files (old, newdir);
4394 if (saveas.include_media) {
4396 if (saveas.copy_media) {
4397 #ifndef PLATFORM_WINDOWS
4398 /* There are problems with analysis files on
4399 * Windows, because they used a colon in their
4400 * names as late as 4.0. Colons are not legal
4401 * under Windows even if NTFS allows them.
4403 * This is a tricky problem to solve so for
4404 * just don't copy these files. They will be
4405 * regenerated as-needed anyway, subject to the
4406 * existing issue that the filenames will be
4407 * rejected by Windows, which is a separate
4408 * problem (though related).
4411 /* only needed if we are copying media, since the
4412 * analysis data refers to media data
4415 old = analysis_dir ();
4416 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4417 string newdir = Glib::build_filename (to_dir, "analysis");
4418 copy_files (old, newdir);
4420 #endif /* PLATFORM_WINDOWS */
4426 _current_snapshot_name = saveas.new_name;
4427 _name = saveas.new_name;
4429 if (saveas.include_media && !saveas.copy_media) {
4431 /* reset search paths of the new session (which we're pretending to be right now) to
4432 include the original session search path, so we can still find all audio.
4435 if (internal_file_cnt) {
4436 for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
4437 ensure_search_path_includes (*s, DataType::AUDIO);
4440 /* we do not do this for MIDI because we copy
4441 all MIDI files if saveas.include_media is
4447 bool was_dirty = dirty ();
4449 save_state ("", false, false, !saveas.include_media);
4450 save_default_options ();
4452 if (saveas.copy_media && saveas.copy_external) {
4453 if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
4454 throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
4458 saveas.final_session_folder_name = _path;
4460 store_recent_sessions (_name, _path);
4462 if (!saveas.switch_to) {
4464 /* switch back to the way things were */
4468 _current_snapshot_name = old_snapshot;
4470 (*_session_dir) = old_sd;
4476 if (internal_file_cnt) {
4477 /* reset these to their original values */
4478 config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
4479 config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
4484 /* prune session dirs, and update disk space statistics
4489 session_dirs.clear ();
4490 session_dirs.push_back (sp);
4491 refresh_disk_space ();
4493 /* ensure that all existing tracks reset their current capture source paths
4495 reset_write_sources (true, true);
4497 /* the copying above was based on actually discovering files, not just iterating over the sources list.
4498 But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
4501 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4502 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4508 if (fs->within_session()) {
4509 string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
4510 fs->set_path (newpath);
4515 } catch (Glib::FileError& e) {
4517 saveas.failure_message = e.what();
4519 /* recursively remove all the directories */
4521 remove_directory (to_dir);
4529 saveas.failure_message = _("unknown reason");
4531 /* recursively remove all the directories */
4533 remove_directory (to_dir);