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);
275 /* Reset all panners */
277 Delivery::reset_panners ();
279 /* this will cause the CPM to instantiate any protocols that are in use
280 * (or mandatory), which will pass it this Session, and then call
281 * set_state() on each instantiated protocol to match stored state.
284 ControlProtocolManager::instance().set_session (this);
286 /* This must be done after the ControlProtocolManager set_session above,
287 as it will set states for ports which the ControlProtocolManager creates.
290 // XXX set state of MIDI::Port's
291 // MidiPortManager::instance()->set_port_states (Config->midi_port_states ());
293 /* And this must be done after the MIDI::Manager::set_port_states as
294 * it will try to make connections whose details are loaded by set_port_states.
299 /* Let control protocols know that we are now all connected, so they
300 * could start talking to surfaces if they want to.
303 ControlProtocolManager::instance().midi_connectivity_established ();
305 if (_is_new && !no_auto_connect()) {
306 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock());
307 auto_connect_master_bus ();
310 _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
312 /* update latencies */
314 initialize_latencies ();
316 _locations->added.connect_same_thread (*this, boost::bind (&Session::location_added, this, _1));
317 _locations->removed.connect_same_thread (*this, boost::bind (&Session::location_removed, this, _1));
318 _locations->changed.connect_same_thread (*this, boost::bind (&Session::locations_changed, this));
320 } catch (AudioEngine::PortRegistrationFailure& err) {
321 /* handle this one in a different way than all others, so that its clear what happened */
322 error << err.what() << endmsg;
328 BootMessage (_("Reset Remote Controls"));
330 // send_full_time_code (0);
331 _engine.transport_locate (0);
333 send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdMmcReset));
334 send_immediate_mmc (MIDI::MachineControlCommand (Timecode::Time ()));
336 MIDI::Name::MidiPatchManager::instance().set_session (this);
339 /* initial program change will be delivered later; see ::config_changed() */
341 _state_of_the_state = Clean;
343 Port::set_connecting_blocked (false);
345 DirtyChanged (); /* EMIT SIGNAL */
349 } else if (state_was_pending) {
351 remove_pending_capture_state ();
352 state_was_pending = false;
359 Session::raid_path () const
361 Searchpath raid_search_path;
363 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
364 raid_search_path += (*i).path;
367 return raid_search_path.to_string ();
371 Session::setup_raid_path (string path)
380 session_dirs.clear ();
382 Searchpath search_path(path);
383 Searchpath sound_search_path;
384 Searchpath midi_search_path;
386 for (Searchpath::const_iterator i = search_path.begin(); i != search_path.end(); ++i) {
388 sp.blocks = 0; // not needed
389 session_dirs.push_back (sp);
391 SessionDirectory sdir(sp.path);
393 sound_search_path += sdir.sound_path ();
394 midi_search_path += sdir.midi_path ();
397 // reset the round-robin soundfile path thingie
398 last_rr_session_dir = session_dirs.begin();
402 Session::path_is_within_session (const std::string& path)
404 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
405 if (PBD::path_is_within (i->path, path)) {
413 Session::ensure_subdirs ()
417 dir = session_directory().peak_path();
419 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
420 error << string_compose(_("Session: cannot create session peakfile folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
424 dir = session_directory().sound_path();
426 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
427 error << string_compose(_("Session: cannot create session sounds dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
431 dir = session_directory().midi_path();
433 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
434 error << string_compose(_("Session: cannot create session midi dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
438 dir = session_directory().dead_path();
440 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
441 error << string_compose(_("Session: cannot create session dead sounds folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
445 dir = session_directory().export_path();
447 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
448 error << string_compose(_("Session: cannot create session export folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
452 dir = analysis_dir ();
454 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
455 error << string_compose(_("Session: cannot create session analysis folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
459 dir = plugins_dir ();
461 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
462 error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
466 dir = externals_dir ();
468 if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
469 error << string_compose(_("Session: cannot create session externals folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
476 /** @param session_template directory containing session template, or empty.
477 * Caller must not hold process lock.
480 Session::create (const string& session_template, BusProfile* bus_profile)
482 if (g_mkdir_with_parents (_path.c_str(), 0755) < 0) {
483 error << string_compose(_("Session: cannot create session folder \"%1\" (%2)"), _path, strerror (errno)) << endmsg;
487 if (ensure_subdirs ()) {
491 _writable = exists_and_writable (_path);
493 if (!session_template.empty()) {
494 std::string in_path = (ARDOUR::Profile->get_trx () ? session_template : session_template_dir_to_file (session_template));
496 ifstream in(in_path.c_str());
499 /* no need to call legalize_for_path() since the string
500 * in session_template is already a legal path name
502 string out_path = Glib::build_filename (_session_dir->root_path(), _name + statefile_suffix);
504 ofstream out(out_path.c_str());
510 if (!ARDOUR::Profile->get_trx()) {
511 /* Copy plugin state files from template to new session */
512 std::string template_plugins = Glib::build_filename (session_template, X_("plugins"));
513 copy_recurse (template_plugins, plugins_dir ());
519 error << string_compose (_("Could not open %1 for writing session template"), out_path)
525 error << string_compose (_("Could not open session template %1 for reading"), in_path)
532 /* set initial start + end point */
534 _state_of_the_state = Clean;
536 /* set up Master Out and Control Out if necessary */
541 ChanCount count(DataType::AUDIO, bus_profile->master_out_channels);
543 // Waves Tracks: always create master bus for Tracks
544 if (ARDOUR::Profile->get_trx() || bus_profile->master_out_channels) {
545 boost::shared_ptr<Route> r (new Route (*this, _("Master"), Route::MasterOut, DataType::AUDIO));
549 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
550 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
553 Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
554 r->input()->ensure_io (count, false, this);
555 r->output()->ensure_io (count, false, this);
561 /* prohibit auto-connect to master, because there isn't one */
562 bus_profile->output_ac = AutoConnectOption (bus_profile->output_ac & ~AutoConnectMaster);
566 add_routes (rl, false, false, false);
569 // Waves Tracks: Skip this. Always use autoconnection for Tracks
570 if (!ARDOUR::Profile->get_trx()) {
572 /* this allows the user to override settings with an environment variable.
575 if (no_auto_connect()) {
576 bus_profile->input_ac = AutoConnectOption (0);
577 bus_profile->output_ac = AutoConnectOption (0);
580 Config->set_input_auto_connect (bus_profile->input_ac);
581 Config->set_output_auto_connect (bus_profile->output_ac);
585 if (Config->get_use_monitor_bus() && bus_profile) {
586 add_monitor_section ();
593 Session::maybe_write_autosave()
595 if (dirty() && record_status() != Recording) {
596 save_state("", true);
601 Session::remove_pending_capture_state ()
603 std::string pending_state_file_path(_session_dir->root_path());
605 pending_state_file_path = Glib::build_filename (pending_state_file_path, legalize_for_path (_current_snapshot_name) + pending_suffix);
607 if (!Glib::file_test (pending_state_file_path, Glib::FILE_TEST_EXISTS)) return;
609 if (g_remove (pending_state_file_path.c_str()) != 0) {
610 error << string_compose(_("Could not remove pending capture state at path \"%1\" (%2)"),
611 pending_state_file_path, g_strerror (errno)) << endmsg;
615 /** Rename a state file.
616 * @param old_name Old snapshot name.
617 * @param new_name New snapshot name.
620 Session::rename_state (string old_name, string new_name)
622 if (old_name == _current_snapshot_name || old_name == _name) {
623 /* refuse to rename the current snapshot or the "main" one */
627 const string old_xml_filename = legalize_for_path (old_name) + statefile_suffix;
628 const string new_xml_filename = legalize_for_path (new_name) + statefile_suffix;
630 const std::string old_xml_path(Glib::build_filename (_session_dir->root_path(), old_xml_filename));
631 const std::string new_xml_path(Glib::build_filename (_session_dir->root_path(), new_xml_filename));
633 if (::g_rename (old_xml_path.c_str(), new_xml_path.c_str()) != 0) {
634 error << string_compose(_("could not rename snapshot %1 to %2 (%3)"),
635 old_name, new_name, g_strerror(errno)) << endmsg;
639 /** Remove a state file.
640 * @param snapshot_name Snapshot name.
643 Session::remove_state (string snapshot_name)
645 if (!_writable || snapshot_name == _current_snapshot_name || snapshot_name == _name) {
646 // refuse to remove the current snapshot or the "main" one
650 std::string xml_path(_session_dir->root_path());
652 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
654 if (!create_backup_file (xml_path)) {
655 // don't remove it if a backup can't be made
656 // create_backup_file will log the error.
661 if (g_remove (xml_path.c_str()) != 0) {
662 error << string_compose(_("Could not remove session file at path \"%1\" (%2)"),
663 xml_path, g_strerror (errno)) << endmsg;
667 /** @param snapshot_name Name to save under, without .ardour / .pending prefix */
669 Session::save_state (string snapshot_name, bool pending, bool switch_to_snapshot, bool template_only)
672 std::string xml_path(_session_dir->root_path());
674 /* prevent concurrent saves from different threads */
676 Glib::Threads::Mutex::Lock lm (save_state_lock);
678 if (!_writable || (_state_of_the_state & CannotSave)) {
682 if (g_atomic_int_get(&_suspend_save)) {
686 _save_queued = false;
688 if (!_engine.connected ()) {
689 error << string_compose (_("the %1 audio engine is not connected and state saving would lose all I/O connections. Session not saved"),
695 /* tell sources we're saving first, in case they write out to a new file
696 * which should be saved with the state rather than the old one */
697 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
699 i->second->session_saved();
700 } catch (Evoral::SMF::FileError& e) {
701 error << string_compose ("Could not write to MIDI file %1; MIDI data not saved.", e.file_name ()) << endmsg;
705 SessionSaveUnderway (); /* EMIT SIGNAL */
708 tree.set_root (&get_template());
710 tree.set_root (&get_state());
713 if (snapshot_name.empty()) {
714 snapshot_name = _current_snapshot_name;
715 } else if (switch_to_snapshot) {
716 _current_snapshot_name = snapshot_name;
721 /* proper save: use statefile_suffix (.ardour in English) */
723 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + statefile_suffix);
725 /* make a backup copy of the old file */
727 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS) && !create_backup_file (xml_path)) {
728 // create_backup_file will log the error
734 /* pending save: use pending_suffix (.pending in English) */
735 xml_path = Glib::build_filename (xml_path, legalize_for_path (snapshot_name) + pending_suffix);
738 std::string tmp_path(_session_dir->root_path());
739 tmp_path = Glib::build_filename (tmp_path, legalize_for_path (snapshot_name) + temp_suffix);
741 cerr << "actually writing state to " << tmp_path << endl;
743 if (!tree.write (tmp_path)) {
744 error << string_compose (_("state could not be saved to %1"), tmp_path) << endmsg;
745 if (g_remove (tmp_path.c_str()) != 0) {
746 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
747 tmp_path, g_strerror (errno)) << endmsg;
753 cerr << "renaming state to " << xml_path << endl;
755 if (::g_rename (tmp_path.c_str(), xml_path.c_str()) != 0) {
756 error << string_compose (_("could not rename temporary session file %1 to %2 (%3)"),
757 tmp_path, xml_path, g_strerror(errno)) << endmsg;
758 if (g_remove (tmp_path.c_str()) != 0) {
759 error << string_compose(_("Could not remove temporary session file at path \"%1\" (%2)"),
760 tmp_path, g_strerror (errno)) << endmsg;
768 save_history (snapshot_name);
770 bool was_dirty = dirty();
772 _state_of_the_state = StateOfTheState (_state_of_the_state & ~Dirty);
775 DirtyChanged (); /* EMIT SIGNAL */
778 StateSaved (snapshot_name); /* EMIT SIGNAL */
785 Session::restore_state (string snapshot_name)
787 if (load_state (snapshot_name) == 0) {
788 set_state (*state_tree->root(), Stateful::loading_state_version);
795 Session::load_state (string snapshot_name)
800 state_was_pending = false;
802 /* check for leftover pending state from a crashed capture attempt */
804 std::string xmlpath(_session_dir->root_path());
805 xmlpath = Glib::build_filename (xmlpath, legalize_for_path (snapshot_name) + pending_suffix);
807 if (Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
809 /* there is pending state from a crashed capture attempt */
811 boost::optional<int> r = AskAboutPendingState();
812 if (r.get_value_or (1)) {
813 state_was_pending = true;
817 if (!state_was_pending) {
818 xmlpath = Glib::build_filename (_session_dir->root_path(), snapshot_name);
821 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
822 xmlpath = Glib::build_filename (_session_dir->root_path(), legalize_for_path (snapshot_name) + statefile_suffix);
823 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
824 error << string_compose(_("%1: session file \"%2\" doesn't exist!"), _name, xmlpath) << endmsg;
829 state_tree = new XMLTree;
833 _writable = exists_and_writable (xmlpath) && exists_and_writable(Glib::path_get_dirname(xmlpath));
835 if (!state_tree->read (xmlpath)) {
836 error << string_compose(_("Could not understand session file %1"), xmlpath) << endmsg;
842 XMLNode& root (*state_tree->root());
844 if (root.name() != X_("Session")) {
845 error << string_compose (_("Session file %1 is not a session"), xmlpath) << endmsg;
851 const XMLProperty* prop;
853 if ((prop = root.property ("version")) == 0) {
854 /* no version implies very old version of Ardour */
855 Stateful::loading_state_version = 1000;
857 if (prop->value().find ('.') != string::npos) {
858 /* old school version format */
859 if (prop->value()[0] == '2') {
860 Stateful::loading_state_version = 2000;
862 Stateful::loading_state_version = 3000;
865 Stateful::loading_state_version = atoi (prop->value());
869 if (Stateful::loading_state_version < CURRENT_SESSION_FILE_VERSION && _writable) {
871 std::string backup_path(_session_dir->root_path());
872 std::string backup_filename = string_compose ("%1-%2%3", legalize_for_path (snapshot_name), Stateful::loading_state_version, statefile_suffix);
873 backup_path = Glib::build_filename (backup_path, backup_filename);
875 // only create a backup for a given statefile version once
877 if (!Glib::file_test (backup_path, Glib::FILE_TEST_EXISTS)) {
879 VersionMismatch (xmlpath, backup_path);
881 if (!copy_file (xmlpath, backup_path)) {;
891 Session::load_options (const XMLNode& node)
893 LocaleGuard lg (X_("C"));
894 config.set_variables (node);
899 Session::save_default_options ()
901 return config.save_state();
911 Session::get_template()
913 /* if we don't disable rec-enable, diskstreams
914 will believe they need to store their capture
915 sources in their state node.
918 disable_record (false);
924 Session::state (bool full_state)
926 XMLNode* node = new XMLNode("Session");
930 snprintf(buf, sizeof(buf), "%d", CURRENT_SESSION_FILE_VERSION);
931 node->add_property("version", buf);
933 /* store configuration settings */
937 node->add_property ("name", _name);
938 snprintf (buf, sizeof (buf), "%" PRId64, _nominal_frame_rate);
939 node->add_property ("sample-rate", buf);
941 if (session_dirs.size() > 1) {
945 vector<space_and_path>::iterator i = session_dirs.begin();
946 vector<space_and_path>::iterator next;
948 ++i; /* skip the first one */
952 while (i != session_dirs.end()) {
956 if (next != session_dirs.end()) {
957 p += G_SEARCHPATH_SEPARATOR;
966 child = node->add_child ("Path");
967 child->add_content (p);
971 /* save the ID counter */
973 snprintf (buf, sizeof (buf), "%" PRIu64, ID::counter());
974 node->add_property ("id-counter", buf);
976 /* save the event ID counter */
978 snprintf (buf, sizeof (buf), "%d", Evoral::event_id_counter());
979 node->add_property ("event-counter", buf);
981 /* various options */
983 list<XMLNode*> midi_port_nodes = _midi_ports->get_midi_port_states();
984 if (!midi_port_nodes.empty()) {
985 XMLNode* midi_port_stuff = new XMLNode ("MIDIPorts");
986 for (list<XMLNode*>::const_iterator n = midi_port_nodes.begin(); n != midi_port_nodes.end(); ++n) {
987 midi_port_stuff->add_child_nocopy (**n);
989 node->add_child_nocopy (*midi_port_stuff);
992 node->add_child_nocopy (config.get_variables ());
994 node->add_child_nocopy (ARDOUR::SessionMetadata::Metadata()->get_state());
996 child = node->add_child ("Sources");
999 Glib::Threads::Mutex::Lock sl (source_lock);
1001 for (SourceMap::iterator siter = sources.begin(); siter != sources.end(); ++siter) {
1003 /* Don't save information about non-file Sources, or
1004 * about non-destructive file sources that are empty
1005 * and unused by any regions.
1008 boost::shared_ptr<FileSource> fs;
1010 if ((fs = boost::dynamic_pointer_cast<FileSource> (siter->second)) != 0) {
1012 if (!fs->destructive()) {
1013 if (fs->empty() && !fs->used()) {
1018 child->add_child_nocopy (siter->second->get_state());
1023 child = node->add_child ("Regions");
1026 Glib::Threads::Mutex::Lock rl (region_lock);
1027 const RegionFactory::RegionMap& region_map (RegionFactory::all_regions());
1028 for (RegionFactory::RegionMap::const_iterator i = region_map.begin(); i != region_map.end(); ++i) {
1029 boost::shared_ptr<Region> r = i->second;
1030 /* only store regions not attached to playlists */
1031 if (r->playlist() == 0) {
1032 if (boost::dynamic_pointer_cast<AudioRegion>(r)) {
1033 child->add_child_nocopy ((boost::dynamic_pointer_cast<AudioRegion>(r))->get_basic_state ());
1035 child->add_child_nocopy (r->get_state ());
1040 RegionFactory::CompoundAssociations& cassocs (RegionFactory::compound_associations());
1042 if (!cassocs.empty()) {
1043 XMLNode* ca = node->add_child (X_("CompoundAssociations"));
1045 for (RegionFactory::CompoundAssociations::iterator i = cassocs.begin(); i != cassocs.end(); ++i) {
1047 XMLNode* can = new XMLNode (X_("CompoundAssociation"));
1048 i->first->id().print (buf, sizeof (buf));
1049 can->add_property (X_("copy"), buf);
1050 i->second->id().print (buf, sizeof (buf));
1051 can->add_property (X_("original"), buf);
1052 ca->add_child_nocopy (*can);
1062 node->add_child_nocopy (_locations->get_state());
1065 Locations loc (*this);
1066 // for a template, just create a new Locations, populate it
1067 // with the default start and end, and get the state for that.
1068 Location* range = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
1069 range->set (max_framepos, 0);
1071 XMLNode& locations_state = loc.get_state();
1073 if (ARDOUR::Profile->get_trx() && _locations) {
1074 for (Locations::LocationList::const_iterator i = _locations->list ().begin (); i != _locations->list ().end (); ++i) {
1075 if ((*i)->is_mark () || (*i)->is_auto_loop ()) {
1076 locations_state.add_child_nocopy ((*i)->get_state ());
1080 node->add_child_nocopy (locations_state);
1083 child = node->add_child ("Bundles");
1085 boost::shared_ptr<BundleList> bundles = _bundles.reader ();
1086 for (BundleList::iterator i = bundles->begin(); i != bundles->end(); ++i) {
1087 boost::shared_ptr<UserBundle> b = boost::dynamic_pointer_cast<UserBundle> (*i);
1089 child->add_child_nocopy (b->get_state());
1094 child = node->add_child ("Routes");
1096 boost::shared_ptr<RouteList> r = routes.reader ();
1098 RoutePublicOrderSorter cmp;
1099 RouteList public_order (*r);
1100 public_order.sort (cmp);
1102 /* the sort should have put control outs first */
1105 assert (_monitor_out == public_order.front());
1108 for (RouteList::iterator i = public_order.begin(); i != public_order.end(); ++i) {
1109 if (!(*i)->is_auditioner()) {
1111 child->add_child_nocopy ((*i)->get_state());
1113 child->add_child_nocopy ((*i)->get_template());
1119 playlists->add_state (node, full_state);
1121 child = node->add_child ("RouteGroups");
1122 for (list<RouteGroup *>::iterator i = _route_groups.begin(); i != _route_groups.end(); ++i) {
1123 child->add_child_nocopy ((*i)->get_state());
1127 XMLNode* gain_child = node->add_child ("Click");
1128 gain_child->add_child_nocopy (_click_io->state (full_state));
1129 gain_child->add_child_nocopy (_click_gain->state (full_state));
1133 XMLNode* ltc_input_child = node->add_child ("LTC-In");
1134 ltc_input_child->add_child_nocopy (_ltc_input->state (full_state));
1138 XMLNode* ltc_output_child = node->add_child ("LTC-Out");
1139 ltc_output_child->add_child_nocopy (_ltc_output->state (full_state));
1142 node->add_child_nocopy (_speakers->get_state());
1143 node->add_child_nocopy (_tempo_map->get_state());
1144 node->add_child_nocopy (get_control_protocol_state());
1147 node->add_child_copy (*_extra_xml);
1154 Session::get_control_protocol_state ()
1156 ControlProtocolManager& cpm (ControlProtocolManager::instance());
1157 return cpm.get_state();
1161 Session::set_state (const XMLNode& node, int version)
1165 const XMLProperty* prop;
1168 _state_of_the_state = StateOfTheState (_state_of_the_state|CannotSave);
1170 if (node.name() != X_("Session")) {
1171 fatal << _("programming error: Session: incorrect XML node sent to set_state()") << endmsg;
1175 if ((prop = node.property ("name")) != 0) {
1176 _name = prop->value ();
1179 if ((prop = node.property (X_("sample-rate"))) != 0) {
1181 _nominal_frame_rate = atoi (prop->value());
1183 if (_nominal_frame_rate != _current_frame_rate) {
1184 boost::optional<int> r = AskAboutSampleRateMismatch (_nominal_frame_rate, _current_frame_rate);
1185 if (r.get_value_or (0)) {
1191 setup_raid_path(_session_dir->root_path());
1193 if ((prop = node.property (X_("id-counter"))) != 0) {
1195 sscanf (prop->value().c_str(), "%" PRIu64, &x);
1196 ID::init_counter (x);
1198 /* old sessions used a timebased counter, so fake
1199 the startup ID counter based on a standard
1204 ID::init_counter (now);
1207 if ((prop = node.property (X_("event-counter"))) != 0) {
1208 Evoral::init_event_id_counter (atoi (prop->value()));
1212 if ((child = find_named_node (node, "MIDIPorts")) != 0) {
1213 _midi_ports->set_midi_port_states (child->children());
1216 IO::disable_connecting ();
1218 Stateful::save_extra_xml (node);
1220 if (((child = find_named_node (node, "Options")) != 0)) { /* old style */
1221 load_options (*child);
1222 } else if ((child = find_named_node (node, "Config")) != 0) { /* new style */
1223 load_options (*child);
1225 error << _("Session: XML state has no options section") << endmsg;
1228 if (version >= 3000) {
1229 if ((child = find_named_node (node, "Metadata")) == 0) {
1230 warning << _("Session: XML state has no metadata section") << endmsg;
1231 } else if ( ARDOUR::SessionMetadata::Metadata()->set_state (*child, version) ) {
1236 if ((child = find_named_node (node, X_("Speakers"))) != 0) {
1237 _speakers->set_state (*child, version);
1240 if ((child = find_named_node (node, "Sources")) == 0) {
1241 error << _("Session: XML state has no sources section") << endmsg;
1243 } else if (load_sources (*child)) {
1247 if ((child = find_named_node (node, "TempoMap")) == 0) {
1248 error << _("Session: XML state has no Tempo Map section") << endmsg;
1250 } else if (_tempo_map->set_state (*child, version)) {
1254 if ((child = find_named_node (node, "Locations")) == 0) {
1255 error << _("Session: XML state has no locations section") << endmsg;
1257 } else if (_locations->set_state (*child, version)) {
1261 locations_changed ();
1263 if (_session_range_location) {
1264 AudioFileSource::set_header_position_offset (_session_range_location->start());
1267 if ((child = find_named_node (node, "Regions")) == 0) {
1268 error << _("Session: XML state has no Regions section") << endmsg;
1270 } else if (load_regions (*child)) {
1274 if ((child = find_named_node (node, "Playlists")) == 0) {
1275 error << _("Session: XML state has no playlists section") << endmsg;
1277 } else if (playlists->load (*this, *child)) {
1281 if ((child = find_named_node (node, "UnusedPlaylists")) == 0) {
1283 } else if (playlists->load_unused (*this, *child)) {
1287 if ((child = find_named_node (node, "CompoundAssociations")) != 0) {
1288 if (load_compounds (*child)) {
1293 if (version >= 3000) {
1294 if ((child = find_named_node (node, "Bundles")) == 0) {
1295 warning << _("Session: XML state has no bundles section") << endmsg;
1298 /* We can't load Bundles yet as they need to be able
1299 to convert from port names to Port objects, which can't happen until
1301 _bundle_xml_node = new XMLNode (*child);
1305 if (version < 3000) {
1306 if ((child = find_named_node (node, X_("DiskStreams"))) == 0) {
1307 error << _("Session: XML state has no diskstreams section") << endmsg;
1309 } else if (load_diskstreams_2X (*child, version)) {
1314 if ((child = find_named_node (node, "Routes")) == 0) {
1315 error << _("Session: XML state has no routes section") << endmsg;
1317 } else if (load_routes (*child, version)) {
1321 /* our diskstreams list is no longer needed as they are now all owned by their Route */
1322 _diskstreams_2X.clear ();
1324 if (version >= 3000) {
1326 if ((child = find_named_node (node, "RouteGroups")) == 0) {
1327 error << _("Session: XML state has no route groups section") << endmsg;
1329 } else if (load_route_groups (*child, version)) {
1333 } else if (version < 3000) {
1335 if ((child = find_named_node (node, "EditGroups")) == 0) {
1336 error << _("Session: XML state has no edit groups section") << endmsg;
1338 } else if (load_route_groups (*child, version)) {
1342 if ((child = find_named_node (node, "MixGroups")) == 0) {
1343 error << _("Session: XML state has no mix groups section") << endmsg;
1345 } else if (load_route_groups (*child, version)) {
1350 if ((child = find_named_node (node, "Click")) == 0) {
1351 warning << _("Session: XML state has no click section") << endmsg;
1352 } else if (_click_io) {
1353 setup_click_state (&node);
1356 if ((child = find_named_node (node, ControlProtocolManager::state_node_name)) != 0) {
1357 ControlProtocolManager::instance().set_state (*child, version);
1360 update_route_record_state ();
1362 /* here beginneth the second phase ... */
1364 StateReady (); /* EMIT SIGNAL */
1377 Session::load_routes (const XMLNode& node, int version)
1380 XMLNodeConstIterator niter;
1381 RouteList new_routes;
1383 nlist = node.children();
1387 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1389 boost::shared_ptr<Route> route;
1390 if (version < 3000) {
1391 route = XMLRouteFactory_2X (**niter, version);
1393 route = XMLRouteFactory (**niter, version);
1397 error << _("Session: cannot create Route from XML description.") << endmsg;
1401 BootMessage (string_compose (_("Loaded track/bus %1"), route->name()));
1403 new_routes.push_back (route);
1406 BootMessage (_("Tracks/busses loaded; Adding to Session"));
1408 add_routes (new_routes, false, false, false);
1410 BootMessage (_("Finished adding tracks/busses"));
1415 boost::shared_ptr<Route>
1416 Session::XMLRouteFactory (const XMLNode& node, int version)
1418 boost::shared_ptr<Route> ret;
1420 if (node.name() != "Route") {
1424 XMLNode* ds_child = find_named_node (node, X_("Diskstream"));
1426 DataType type = DataType::AUDIO;
1427 const XMLProperty* prop = node.property("default-type");
1430 type = DataType (prop->value());
1433 assert (type != DataType::NIL);
1437 boost::shared_ptr<Track> track;
1439 if (type == DataType::AUDIO) {
1440 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1442 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1445 if (track->init()) {
1449 if (track->set_state (node, version)) {
1453 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1454 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1459 enum Route::Flag flags = Route::Flag(0);
1460 const XMLProperty* prop = node.property("flags");
1462 flags = Route::Flag (string_2_enum (prop->value(), flags));
1465 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1467 if (r->init () == 0 && r->set_state (node, version) == 0) {
1468 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1469 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1478 boost::shared_ptr<Route>
1479 Session::XMLRouteFactory_2X (const XMLNode& node, int version)
1481 boost::shared_ptr<Route> ret;
1483 if (node.name() != "Route") {
1487 XMLProperty const * ds_prop = node.property (X_("diskstream-id"));
1489 ds_prop = node.property (X_("diskstream"));
1492 DataType type = DataType::AUDIO;
1493 const XMLProperty* prop = node.property("default-type");
1496 type = DataType (prop->value());
1499 assert (type != DataType::NIL);
1503 list<boost::shared_ptr<Diskstream> >::iterator i = _diskstreams_2X.begin ();
1504 while (i != _diskstreams_2X.end() && (*i)->id() != ds_prop->value()) {
1508 if (i == _diskstreams_2X.end()) {
1509 error << _("Could not find diskstream for route") << endmsg;
1510 return boost::shared_ptr<Route> ();
1513 boost::shared_ptr<Track> track;
1515 if (type == DataType::AUDIO) {
1516 track.reset (new AudioTrack (*this, X_("toBeResetFroXML")));
1518 track.reset (new MidiTrack (*this, X_("toBeResetFroXML")));
1521 if (track->init()) {
1525 if (track->set_state (node, version)) {
1529 track->set_diskstream (*i);
1531 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1532 // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
1537 enum Route::Flag flags = Route::Flag(0);
1538 const XMLProperty* prop = node.property("flags");
1540 flags = Route::Flag (string_2_enum (prop->value(), flags));
1543 boost::shared_ptr<Route> r (new Route (*this, X_("toBeResetFroXML"), flags));
1545 if (r->init () == 0 && r->set_state (node, version) == 0) {
1546 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
1547 // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
1557 Session::load_regions (const XMLNode& node)
1560 XMLNodeConstIterator niter;
1561 boost::shared_ptr<Region> region;
1563 nlist = node.children();
1567 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1568 if ((region = XMLRegionFactory (**niter, false)) == 0) {
1569 error << _("Session: cannot create Region from XML description.");
1570 const XMLProperty *name = (**niter).property("name");
1573 error << " " << string_compose (_("Can not load state for region '%1'"), name->value());
1584 Session::load_compounds (const XMLNode& node)
1586 XMLNodeList calist = node.children();
1587 XMLNodeConstIterator caiter;
1588 XMLProperty *caprop;
1590 for (caiter = calist.begin(); caiter != calist.end(); ++caiter) {
1591 XMLNode* ca = *caiter;
1595 if ((caprop = ca->property (X_("original"))) == 0) {
1598 orig_id = caprop->value();
1600 if ((caprop = ca->property (X_("copy"))) == 0) {
1603 copy_id = caprop->value();
1605 boost::shared_ptr<Region> orig = RegionFactory::region_by_id (orig_id);
1606 boost::shared_ptr<Region> copy = RegionFactory::region_by_id (copy_id);
1608 if (!orig || !copy) {
1609 warning << string_compose (_("Regions in compound description not found (ID's %1 and %2): ignored"),
1615 RegionFactory::add_compound_association (orig, copy);
1622 Session::load_nested_sources (const XMLNode& node)
1625 XMLNodeConstIterator niter;
1627 nlist = node.children();
1629 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1630 if ((*niter)->name() == "Source") {
1632 /* it may already exist, so don't recreate it unnecessarily
1635 XMLProperty* prop = (*niter)->property (X_("id"));
1637 error << _("Nested source has no ID info in session file! (ignored)") << endmsg;
1641 ID source_id (prop->value());
1643 if (!source_by_id (source_id)) {
1646 SourceFactory::create (*this, **niter, true);
1648 catch (failed_constructor& err) {
1649 error << string_compose (_("Cannot reconstruct nested source for region %1"), name()) << endmsg;
1656 boost::shared_ptr<Region>
1657 Session::XMLRegionFactory (const XMLNode& node, bool full)
1659 const XMLProperty* type = node.property("type");
1663 const XMLNodeList& nlist = node.children();
1665 for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter) {
1666 XMLNode *child = (*niter);
1667 if (child->name() == "NestedSource") {
1668 load_nested_sources (*child);
1672 if (!type || type->value() == "audio") {
1673 return boost::shared_ptr<Region>(XMLAudioRegionFactory (node, full));
1674 } else if (type->value() == "midi") {
1675 return boost::shared_ptr<Region>(XMLMidiRegionFactory (node, full));
1678 } catch (failed_constructor& err) {
1679 return boost::shared_ptr<Region> ();
1682 return boost::shared_ptr<Region> ();
1685 boost::shared_ptr<AudioRegion>
1686 Session::XMLAudioRegionFactory (const XMLNode& node, bool /*full*/)
1688 const XMLProperty* prop;
1689 boost::shared_ptr<Source> source;
1690 boost::shared_ptr<AudioSource> as;
1692 SourceList master_sources;
1693 uint32_t nchans = 1;
1696 if (node.name() != X_("Region")) {
1697 return boost::shared_ptr<AudioRegion>();
1700 if ((prop = node.property (X_("channels"))) != 0) {
1701 nchans = atoi (prop->value().c_str());
1704 if ((prop = node.property ("name")) == 0) {
1705 cerr << "no name for this region\n";
1709 if ((prop = node.property (X_("source-0"))) == 0) {
1710 if ((prop = node.property ("source")) == 0) {
1711 error << _("Session: XMLNode describing a AudioRegion is incomplete (no source)") << endmsg;
1712 return boost::shared_ptr<AudioRegion>();
1716 PBD::ID s_id (prop->value());
1718 if ((source = source_by_id (s_id)) == 0) {
1719 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), s_id) << endmsg;
1720 return boost::shared_ptr<AudioRegion>();
1723 as = boost::dynamic_pointer_cast<AudioSource>(source);
1725 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), s_id) << endmsg;
1726 return boost::shared_ptr<AudioRegion>();
1729 sources.push_back (as);
1731 /* pickup other channels */
1733 for (uint32_t n=1; n < nchans; ++n) {
1734 snprintf (buf, sizeof(buf), X_("source-%d"), n);
1735 if ((prop = node.property (buf)) != 0) {
1737 PBD::ID id2 (prop->value());
1739 if ((source = source_by_id (id2)) == 0) {
1740 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1741 return boost::shared_ptr<AudioRegion>();
1744 as = boost::dynamic_pointer_cast<AudioSource>(source);
1746 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1747 return boost::shared_ptr<AudioRegion>();
1749 sources.push_back (as);
1753 for (uint32_t n = 0; n < nchans; ++n) {
1754 snprintf (buf, sizeof(buf), X_("master-source-%d"), n);
1755 if ((prop = node.property (buf)) != 0) {
1757 PBD::ID id2 (prop->value());
1759 if ((source = source_by_id (id2)) == 0) {
1760 error << string_compose(_("Session: XMLNode describing a AudioRegion references an unknown source id =%1"), id2) << endmsg;
1761 return boost::shared_ptr<AudioRegion>();
1764 as = boost::dynamic_pointer_cast<AudioSource>(source);
1766 error << string_compose(_("Session: XMLNode describing a AudioRegion references a non-audio source id =%1"), id2) << endmsg;
1767 return boost::shared_ptr<AudioRegion>();
1769 master_sources.push_back (as);
1774 boost::shared_ptr<AudioRegion> region (boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::create (sources, node)));
1776 /* a final detail: this is the one and only place that we know how long missing files are */
1778 if (region->whole_file()) {
1779 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1780 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1782 sfp->set_length (region->length());
1787 if (!master_sources.empty()) {
1788 if (master_sources.size() != nchans) {
1789 error << _("Session: XMLNode describing an AudioRegion is missing some master sources; ignored") << endmsg;
1791 region->set_master_sources (master_sources);
1799 catch (failed_constructor& err) {
1800 return boost::shared_ptr<AudioRegion>();
1804 boost::shared_ptr<MidiRegion>
1805 Session::XMLMidiRegionFactory (const XMLNode& node, bool /*full*/)
1807 const XMLProperty* prop;
1808 boost::shared_ptr<Source> source;
1809 boost::shared_ptr<MidiSource> ms;
1812 if (node.name() != X_("Region")) {
1813 return boost::shared_ptr<MidiRegion>();
1816 if ((prop = node.property ("name")) == 0) {
1817 cerr << "no name for this region\n";
1821 if ((prop = node.property (X_("source-0"))) == 0) {
1822 if ((prop = node.property ("source")) == 0) {
1823 error << _("Session: XMLNode describing a MidiRegion is incomplete (no source)") << endmsg;
1824 return boost::shared_ptr<MidiRegion>();
1828 PBD::ID s_id (prop->value());
1830 if ((source = source_by_id (s_id)) == 0) {
1831 error << string_compose(_("Session: XMLNode describing a MidiRegion references an unknown source id =%1"), s_id) << endmsg;
1832 return boost::shared_ptr<MidiRegion>();
1835 ms = boost::dynamic_pointer_cast<MidiSource>(source);
1837 error << string_compose(_("Session: XMLNode describing a MidiRegion references a non-midi source id =%1"), s_id) << endmsg;
1838 return boost::shared_ptr<MidiRegion>();
1841 sources.push_back (ms);
1844 boost::shared_ptr<MidiRegion> region (boost::dynamic_pointer_cast<MidiRegion> (RegionFactory::create (sources, node)));
1845 /* a final detail: this is the one and only place that we know how long missing files are */
1847 if (region->whole_file()) {
1848 for (SourceList::iterator sx = sources.begin(); sx != sources.end(); ++sx) {
1849 boost::shared_ptr<SilentFileSource> sfp = boost::dynamic_pointer_cast<SilentFileSource> (*sx);
1851 sfp->set_length (region->length());
1859 catch (failed_constructor& err) {
1860 return boost::shared_ptr<MidiRegion>();
1865 Session::get_sources_as_xml ()
1868 XMLNode* node = new XMLNode (X_("Sources"));
1869 Glib::Threads::Mutex::Lock lm (source_lock);
1871 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
1872 node->add_child_nocopy (i->second->get_state());
1879 Session::reset_write_sources (bool mark_write_complete, bool force)
1881 boost::shared_ptr<RouteList> rl = routes.reader();
1882 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1883 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
1886 // block state saving
1887 _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
1888 tr->reset_write_sources(mark_write_complete, force);
1889 _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
1895 Session::load_sources (const XMLNode& node)
1898 XMLNodeConstIterator niter;
1899 boost::shared_ptr<Source> source; /* don't need this but it stops some
1900 * versions of gcc complaining about
1901 * discarded return values.
1904 nlist = node.children();
1908 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
1911 if ((source = XMLSourceFactory (**niter)) == 0) {
1912 error << _("Session: cannot create Source from XML description.") << endmsg;
1915 } catch (MissingSource& err) {
1919 if (err.type == DataType::MIDI && Glib::path_is_absolute (err.path)) {
1920 error << string_compose (_("A external MIDI file is missing. %1 cannot currently recover from missing external MIDI files"),
1921 PROGRAM_NAME) << endmsg;
1925 if (!no_questions_about_missing_files) {
1926 user_choice = MissingFile (this, err.path, err.type).get_value_or (-1);
1931 switch (user_choice) {
1933 /* user added a new search location, so try again */
1938 /* user asked to quit the entire session load
1943 no_questions_about_missing_files = true;
1947 no_questions_about_missing_files = true;
1954 case DataType::AUDIO:
1955 source = SourceFactory::createSilent (*this, **niter, max_framecnt, _current_frame_rate);
1958 case DataType::MIDI:
1959 /* The MIDI file is actually missing so
1960 * just create a new one in the same
1961 * location. Do not announce its
1965 if (!Glib::path_is_absolute (err.path)) {
1966 fullpath = Glib::build_filename (source_search_path (DataType::MIDI).front(), err.path);
1968 /* this should be an unrecoverable error: we would be creating a MIDI file outside
1973 /* Note that we do not announce the source just yet - we need to reset its ID before we do that */
1974 source = SourceFactory::createWritable (DataType::MIDI, *this, fullpath, false, _current_frame_rate, false, false);
1975 /* reset ID to match the missing one */
1976 source->set_id (**niter);
1977 /* Now we can announce it */
1978 SourceFactory::SourceCreated (source);
1989 boost::shared_ptr<Source>
1990 Session::XMLSourceFactory (const XMLNode& node)
1992 if (node.name() != "Source") {
1993 return boost::shared_ptr<Source>();
1997 /* note: do peak building in another thread when loading session state */
1998 return SourceFactory::create (*this, node, true);
2001 catch (failed_constructor& err) {
2002 error << string_compose (_("Found a sound file that cannot be used by %1. Talk to the programmers."), PROGRAM_NAME) << endmsg;
2003 return boost::shared_ptr<Source>();
2008 Session::save_template (string template_name)
2010 if ((_state_of_the_state & CannotSave) || template_name.empty ()) {
2014 bool absolute_path = Glib::path_is_absolute (template_name);
2016 /* directory to put the template in */
2017 std::string template_dir_path;
2019 if (!absolute_path) {
2020 std::string user_template_dir(user_template_directory());
2022 if (g_mkdir_with_parents (user_template_dir.c_str(), 0755) != 0) {
2023 error << string_compose(_("Could not create templates directory \"%1\" (%2)"),
2024 user_template_dir, g_strerror (errno)) << endmsg;
2028 template_dir_path = Glib::build_filename (user_template_dir, template_name);
2030 template_dir_path = template_name;
2033 if (!ARDOUR::Profile->get_trx()) {
2034 if (Glib::file_test (template_dir_path, Glib::FILE_TEST_EXISTS)) {
2035 warning << string_compose(_("Template \"%1\" already exists - new version not created"),
2036 template_dir_path) << endmsg;
2040 if (g_mkdir_with_parents (template_dir_path.c_str(), 0755) != 0) {
2041 error << string_compose(_("Could not create directory for Session template\"%1\" (%2)"),
2042 template_dir_path, g_strerror (errno)) << endmsg;
2048 std::string template_file_path;
2050 if (ARDOUR::Profile->get_trx()) {
2051 template_file_path = template_name;
2053 if (absolute_path) {
2054 template_file_path = Glib::build_filename (template_dir_path, Glib::path_get_basename (template_dir_path) + template_suffix);
2056 template_file_path = Glib::build_filename (template_dir_path, template_name + template_suffix);
2060 SessionSaveUnderway (); /* EMIT SIGNAL */
2064 tree.set_root (&get_template());
2065 if (!tree.write (template_file_path)) {
2066 error << _("template not saved") << endmsg;
2070 if (!ARDOUR::Profile->get_trx()) {
2071 /* copy plugin state directory */
2073 std::string template_plugin_state_path (Glib::build_filename (template_dir_path, X_("plugins")));
2075 if (g_mkdir_with_parents (template_plugin_state_path.c_str(), 0755) != 0) {
2076 error << string_compose(_("Could not create directory for Session template plugin state\"%1\" (%2)"),
2077 template_plugin_state_path, g_strerror (errno)) << endmsg;
2080 copy_files (plugins_dir(), template_plugin_state_path);
2083 store_recent_templates (template_file_path);
2089 Session::refresh_disk_space ()
2091 #if __APPLE__ || (HAVE_SYS_VFS_H && HAVE_SYS_STATVFS_H)
2093 Glib::Threads::Mutex::Lock lm (space_lock);
2095 /* get freespace on every FS that is part of the session path */
2097 _total_free_4k_blocks = 0;
2098 _total_free_4k_blocks_uncertain = false;
2100 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2102 struct statfs statfsbuf;
2103 statfs (i->path.c_str(), &statfsbuf);
2105 double const scale = statfsbuf.f_bsize / 4096.0;
2107 /* See if this filesystem is read-only */
2108 struct statvfs statvfsbuf;
2109 statvfs (i->path.c_str(), &statvfsbuf);
2111 /* f_bavail can be 0 if it is undefined for whatever
2112 filesystem we are looking at; Samba shares mounted
2113 via GVFS are an example of this.
2115 if (statfsbuf.f_bavail == 0) {
2116 /* block count unknown */
2118 i->blocks_unknown = true;
2119 } else if (statvfsbuf.f_flag & ST_RDONLY) {
2120 /* read-only filesystem */
2122 i->blocks_unknown = false;
2124 /* read/write filesystem with known space */
2125 i->blocks = (uint32_t) floor (statfsbuf.f_bavail * scale);
2126 i->blocks_unknown = false;
2129 _total_free_4k_blocks += i->blocks;
2130 if (i->blocks_unknown) {
2131 _total_free_4k_blocks_uncertain = true;
2134 #elif defined PLATFORM_WINDOWS
2135 vector<string> scanned_volumes;
2136 vector<string>::iterator j;
2137 vector<space_and_path>::iterator i;
2138 DWORD nSectorsPerCluster, nBytesPerSector,
2139 nFreeClusters, nTotalClusters;
2143 _total_free_4k_blocks = 0;
2145 for (i = session_dirs.begin(); i != session_dirs.end(); i++) {
2146 strncpy (disk_drive, (*i).path.c_str(), 3);
2150 volume_found = false;
2151 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2153 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2154 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2155 i->blocks = (uint32_t)(nFreeBytes / 4096);
2157 for (j = scanned_volumes.begin(); j != scanned_volumes.end(); j++) {
2158 if (0 == j->compare(disk_drive)) {
2159 volume_found = true;
2164 if (!volume_found) {
2165 scanned_volumes.push_back(disk_drive);
2166 _total_free_4k_blocks += i->blocks;
2171 if (0 == _total_free_4k_blocks) {
2172 strncpy (disk_drive, path().c_str(), 3);
2175 if (0 != (GetDiskFreeSpace(disk_drive, &nSectorsPerCluster, &nBytesPerSector, &nFreeClusters, &nTotalClusters)))
2177 int64_t nBytesPerCluster = nBytesPerSector * nSectorsPerCluster;
2178 int64_t nFreeBytes = nBytesPerCluster * (int64_t)nFreeClusters;
2179 _total_free_4k_blocks = (uint32_t)(nFreeBytes / 4096);
2186 Session::get_best_session_directory_for_new_audio ()
2188 vector<space_and_path>::iterator i;
2189 string result = _session_dir->root_path();
2191 /* handle common case without system calls */
2193 if (session_dirs.size() == 1) {
2197 /* OK, here's the algorithm we're following here:
2199 We want to select which directory to use for
2200 the next file source to be created. Ideally,
2201 we'd like to use a round-robin process so as to
2202 get maximum performance benefits from splitting
2203 the files across multiple disks.
2205 However, in situations without much diskspace, an
2206 RR approach may end up filling up a filesystem
2207 with new files while others still have space.
2208 Its therefore important to pay some attention to
2209 the freespace in the filesystem holding each
2210 directory as well. However, if we did that by
2211 itself, we'd keep creating new files in the file
2212 system with the most space until it was as full
2213 as all others, thus negating any performance
2214 benefits of this RAID-1 like approach.
2216 So, we use a user-configurable space threshold. If
2217 there are at least 2 filesystems with more than this
2218 much space available, we use RR selection between them.
2219 If not, then we pick the filesystem with the most space.
2221 This gets a good balance between the two
2225 refresh_disk_space ();
2227 int free_enough = 0;
2229 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2230 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2235 if (free_enough >= 2) {
2236 /* use RR selection process, ensuring that the one
2240 i = last_rr_session_dir;
2243 if (++i == session_dirs.end()) {
2244 i = session_dirs.begin();
2247 if ((*i).blocks * 4096 >= Config->get_disk_choice_space_threshold()) {
2248 SessionDirectory sdir(i->path);
2249 if (sdir.create ()) {
2251 last_rr_session_dir = i;
2256 } while (i != last_rr_session_dir);
2260 /* pick FS with the most freespace (and that
2261 seems to actually work ...)
2264 vector<space_and_path> sorted;
2265 space_and_path_ascending_cmp cmp;
2267 sorted = session_dirs;
2268 sort (sorted.begin(), sorted.end(), cmp);
2270 for (i = sorted.begin(); i != sorted.end(); ++i) {
2271 SessionDirectory sdir(i->path);
2272 if (sdir.create ()) {
2274 last_rr_session_dir = i;
2284 Session::automation_dir () const
2286 return Glib::build_filename (_path, "automation");
2290 Session::analysis_dir () const
2292 return Glib::build_filename (_path, "analysis");
2296 Session::plugins_dir () const
2298 return Glib::build_filename (_path, "plugins");
2302 Session::externals_dir () const
2304 return Glib::build_filename (_path, "externals");
2308 Session::load_bundles (XMLNode const & node)
2310 XMLNodeList nlist = node.children();
2311 XMLNodeConstIterator niter;
2315 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2316 if ((*niter)->name() == "InputBundle") {
2317 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, true)));
2318 } else if ((*niter)->name() == "OutputBundle") {
2319 add_bundle (boost::shared_ptr<UserBundle> (new UserBundle (**niter, false)));
2321 error << string_compose(_("Unknown node \"%1\" found in Bundles list from session file"), (*niter)->name()) << endmsg;
2330 Session::load_route_groups (const XMLNode& node, int version)
2332 XMLNodeList nlist = node.children();
2333 XMLNodeConstIterator niter;
2337 if (version >= 3000) {
2339 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2340 if ((*niter)->name() == "RouteGroup") {
2341 RouteGroup* rg = new RouteGroup (*this, "");
2342 add_route_group (rg);
2343 rg->set_state (**niter, version);
2347 } else if (version < 3000) {
2349 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2350 if ((*niter)->name() == "EditGroup" || (*niter)->name() == "MixGroup") {
2351 RouteGroup* rg = new RouteGroup (*this, "");
2352 add_route_group (rg);
2353 rg->set_state (**niter, version);
2362 state_file_filter (const string &str, void* /*arg*/)
2364 return (str.length() > strlen(statefile_suffix) &&
2365 str.find (statefile_suffix) == (str.length() - strlen (statefile_suffix)));
2369 remove_end(string state)
2371 string statename(state);
2373 string::size_type start,end;
2374 if ((start = statename.find_last_of (G_DIR_SEPARATOR)) != string::npos) {
2375 statename = statename.substr (start+1);
2378 if ((end = statename.rfind(statefile_suffix)) == string::npos) {
2379 end = statename.length();
2382 return string(statename.substr (0, end));
2386 Session::possible_states (string path)
2388 vector<string> states;
2389 find_files_matching_filter (states, path, state_file_filter, 0, false, false);
2391 transform(states.begin(), states.end(), states.begin(), remove_end);
2393 sort (states.begin(), states.end());
2399 Session::possible_states () const
2401 return possible_states(_path);
2405 Session::add_route_group (RouteGroup* g)
2407 _route_groups.push_back (g);
2408 route_group_added (g); /* EMIT SIGNAL */
2410 g->RouteAdded.connect_same_thread (*this, boost::bind (&Session::route_added_to_route_group, this, _1, _2));
2411 g->RouteRemoved.connect_same_thread (*this, boost::bind (&Session::route_removed_from_route_group, this, _1, _2));
2412 g->PropertyChanged.connect_same_thread (*this, boost::bind (&Session::route_group_property_changed, this, g));
2418 Session::remove_route_group (RouteGroup& rg)
2420 list<RouteGroup*>::iterator i;
2422 if ((i = find (_route_groups.begin(), _route_groups.end(), &rg)) != _route_groups.end()) {
2423 _route_groups.erase (i);
2426 route_group_removed (); /* EMIT SIGNAL */
2430 /** Set a new order for our route groups, without adding or removing any.
2431 * @param groups Route group list in the new order.
2434 Session::reorder_route_groups (list<RouteGroup*> groups)
2436 _route_groups = groups;
2438 route_groups_reordered (); /* EMIT SIGNAL */
2444 Session::route_group_by_name (string name)
2446 list<RouteGroup *>::iterator i;
2448 for (i = _route_groups.begin(); i != _route_groups.end(); ++i) {
2449 if ((*i)->name() == name) {
2457 Session::all_route_group() const
2459 return *_all_route_group;
2463 Session::add_commands (vector<Command*> const & cmds)
2465 for (vector<Command*>::const_iterator i = cmds.begin(); i != cmds.end(); ++i) {
2471 Session::begin_reversible_command (const string& name)
2473 begin_reversible_command (g_quark_from_string (name.c_str ()));
2476 /** Begin a reversible command using a GQuark to identify it.
2477 * begin_reversible_command() and commit_reversible_command() calls may be nested,
2478 * but there must be as many begin...()s as there are commit...()s.
2481 Session::begin_reversible_command (GQuark q)
2483 /* If nested begin/commit pairs are used, we create just one UndoTransaction
2484 to hold all the commands that are committed. This keeps the order of
2485 commands correct in the history.
2488 if (_current_trans == 0) {
2489 /* start a new transaction */
2490 assert (_current_trans_quarks.empty ());
2491 _current_trans = new UndoTransaction();
2492 _current_trans->set_name (g_quark_to_string (q));
2495 _current_trans_quarks.push_front (q);
2499 Session::abort_reversible_command ()
2501 if (_current_trans != 0) {
2502 _current_trans->clear();
2503 delete _current_trans;
2505 _current_trans_quarks.clear();
2510 Session::commit_reversible_command (Command *cmd)
2512 assert (_current_trans);
2513 assert (!_current_trans_quarks.empty ());
2518 _current_trans->add_command (cmd);
2521 _current_trans_quarks.pop_front ();
2523 if (!_current_trans_quarks.empty ()) {
2524 /* the transaction we're committing is not the top-level one */
2528 if (_current_trans->empty()) {
2529 /* no commands were added to the transaction, so just get rid of it */
2530 delete _current_trans;
2535 gettimeofday (&now, 0);
2536 _current_trans->set_timestamp (now);
2538 _history.add (_current_trans);
2543 accept_all_audio_files (const string& path, void* /*arg*/)
2545 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2549 if (!AudioFileSource::safe_audio_file_extension (path)) {
2557 accept_all_midi_files (const string& path, void* /*arg*/)
2559 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2563 return ((path.length() > 4 && path.find (".mid") != (path.length() - 4)) ||
2564 (path.length() > 4 && path.find (".smf") != (path.length() - 4)) ||
2565 (path.length() > 5 && path.find (".midi") != (path.length() - 5)));
2569 accept_all_state_files (const string& path, void* /*arg*/)
2571 if (!Glib::file_test (path, Glib::FILE_TEST_IS_REGULAR)) {
2575 std::string const statefile_ext (statefile_suffix);
2576 if (path.length() >= statefile_ext.length()) {
2577 return (0 == path.compare (path.length() - statefile_ext.length(), statefile_ext.length(), statefile_ext));
2584 Session::find_all_sources (string path, set<string>& result)
2589 if (!tree.read (path)) {
2593 if ((node = find_named_node (*tree.root(), "Sources")) == 0) {
2598 XMLNodeConstIterator niter;
2600 nlist = node->children();
2604 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
2608 if ((prop = (*niter)->property (X_("type"))) == 0) {
2612 DataType type (prop->value());
2614 if ((prop = (*niter)->property (X_("name"))) == 0) {
2618 if (Glib::path_is_absolute (prop->value())) {
2619 /* external file, ignore */
2627 if (FileSource::find (*this, type, prop->value(), true, is_new, chan, found_path)) {
2628 result.insert (found_path);
2636 Session::find_all_sources_across_snapshots (set<string>& result, bool exclude_this_snapshot)
2638 vector<string> state_files;
2640 string this_snapshot_path;
2646 if (ripped[ripped.length()-1] == G_DIR_SEPARATOR) {
2647 ripped = ripped.substr (0, ripped.length() - 1);
2650 find_files_matching_filter (state_files, ripped, accept_all_state_files, (void *) 0, true, true);
2652 if (state_files.empty()) {
2657 this_snapshot_path = _path;
2658 this_snapshot_path += legalize_for_path (_current_snapshot_name);
2659 this_snapshot_path += statefile_suffix;
2661 for (vector<string>::iterator i = state_files.begin(); i != state_files.end(); ++i) {
2663 if (exclude_this_snapshot && *i == this_snapshot_path) {
2667 if (find_all_sources (*i, result) < 0) {
2675 struct RegionCounter {
2676 typedef std::map<PBD::ID,boost::shared_ptr<AudioSource> > AudioSourceList;
2677 AudioSourceList::iterator iter;
2678 boost::shared_ptr<Region> region;
2681 RegionCounter() : count (0) {}
2685 Session::ask_about_playlist_deletion (boost::shared_ptr<Playlist> p)
2687 boost::optional<int> r = AskAboutPlaylistDeletion (p);
2688 return r.get_value_or (1);
2692 Session::cleanup_regions ()
2694 bool removed = false;
2695 const RegionFactory::RegionMap& regions (RegionFactory::regions());
2697 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2699 uint32_t used = playlists->region_use_count (i->second);
2701 if (used == 0 && !i->second->automatic ()) {
2703 RegionFactory::map_remove (i->second);
2708 // re-check to remove parent references of compound regions
2709 for (RegionFactory::RegionMap::const_iterator i = regions.begin(); i != regions.end(); ++i) {
2710 if (!(i->second->whole_file() && i->second->max_source_level() > 0)) {
2713 assert(boost::dynamic_pointer_cast<PlaylistSource>(i->second->source (0)) != 0);
2714 if (0 == playlists->region_use_count (i->second)) {
2715 RegionFactory::map_remove (i->second);
2720 /* dump the history list */
2727 Session::cleanup_sources (CleanupReport& rep)
2729 // FIXME: needs adaptation to midi
2731 vector<boost::shared_ptr<Source> > dead_sources;
2734 vector<string> candidates;
2735 vector<string> unused;
2736 set<string> all_sources;
2745 _state_of_the_state = (StateOfTheState) (_state_of_the_state | InCleanup);
2747 /* consider deleting all unused playlists */
2749 if (playlists->maybe_delete_unused (boost::bind (Session::ask_about_playlist_deletion, _1))) {
2754 /* sync the "all regions" property of each playlist with its current state
2757 playlists->sync_all_regions_with_regions ();
2759 /* find all un-used sources */
2764 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2766 SourceMap::iterator tmp;
2771 /* do not bother with files that are zero size, otherwise we remove the current "nascent"
2775 if (!i->second->used() && (i->second->length(i->second->timeline_position() > 0))) {
2776 dead_sources.push_back (i->second);
2777 i->second->drop_references ();
2783 /* build a list of all the possible audio directories for the session */
2785 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2786 SessionDirectory sdir ((*i).path);
2787 asp += sdir.sound_path();
2789 audio_path += asp.to_string();
2792 /* build a list of all the possible midi directories for the session */
2794 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
2795 SessionDirectory sdir ((*i).path);
2796 msp += sdir.midi_path();
2798 midi_path += msp.to_string();
2800 find_files_matching_filter (candidates, audio_path, accept_all_audio_files, (void *) 0, true, true);
2801 find_files_matching_filter (candidates, midi_path, accept_all_midi_files, (void *) 0, true, true);
2803 /* find all sources, but don't use this snapshot because the
2804 state file on disk still references sources we may have already
2808 find_all_sources_across_snapshots (all_sources, true);
2810 /* add our current source list
2813 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ) {
2814 boost::shared_ptr<FileSource> fs;
2815 SourceMap::iterator tmp = i;
2818 if ((fs = boost::dynamic_pointer_cast<FileSource> (i->second)) != 0) {
2820 if (!fs->is_stub()) {
2822 if (playlists->source_use_count (fs) != 0) {
2823 all_sources.insert (fs->path());
2826 /* we might not remove this source from disk, because it may be used
2827 by other snapshots, but its not being used in this version
2828 so lets get rid of it now, along with any representative regions
2832 RegionFactory::remove_regions_using_source (i->second);
2835 // also remove source from all_sources
2837 for (set<string>::iterator j = all_sources.begin(); j != all_sources.end(); ++j) {
2838 spath = Glib::path_get_basename (*j);
2839 if ( spath == i->second->name () ) {
2840 all_sources.erase (j);
2851 for (vector<string>::iterator x = candidates.begin(); x != candidates.end(); ++x) {
2856 for (set<string>::iterator i = all_sources.begin(); i != all_sources.end(); ++i) {
2858 tmppath1 = canonical_path (spath);
2859 tmppath2 = canonical_path ((*i));
2861 if (tmppath1 == tmppath2) {
2868 unused.push_back (spath);
2872 /* now try to move all unused files into the "dead" directory(ies) */
2874 for (vector<string>::iterator x = unused.begin(); x != unused.end(); ++x) {
2875 struct stat statbuf;
2879 /* don't move the file across filesystems, just
2880 stick it in the `dead_dir_name' directory
2881 on whichever filesystem it was already on.
2884 if ((*x).find ("/sounds/") != string::npos) {
2886 /* old school, go up 1 level */
2888 newpath = Glib::path_get_dirname (*x); // "sounds"
2889 newpath = Glib::path_get_dirname (newpath); // "session-name"
2893 /* new school, go up 4 levels */
2895 newpath = Glib::path_get_dirname (*x); // "audiofiles" or "midifiles"
2896 newpath = Glib::path_get_dirname (newpath); // "session-name"
2897 newpath = Glib::path_get_dirname (newpath); // "interchange"
2898 newpath = Glib::path_get_dirname (newpath); // "session-dir"
2901 newpath = Glib::build_filename (newpath, dead_dir_name);
2903 if (g_mkdir_with_parents (newpath.c_str(), 0755) < 0) {
2904 error << string_compose(_("Session: cannot create dead file folder \"%1\" (%2)"), newpath, strerror (errno)) << endmsg;
2908 newpath = Glib::build_filename (newpath, Glib::path_get_basename ((*x)));
2910 if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
2912 /* the new path already exists, try versioning */
2914 char buf[PATH_MAX+1];
2918 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), version);
2921 while (Glib::file_test (newpath_v.c_str(), Glib::FILE_TEST_EXISTS) && version < 999) {
2922 snprintf (buf, sizeof (buf), "%s.%d", newpath.c_str(), ++version);
2926 if (version == 999) {
2927 error << string_compose (_("there are already 1000 files with names like %1; versioning discontinued"),
2931 newpath = newpath_v;
2936 /* it doesn't exist, or we can't read it or something */
2940 stat ((*x).c_str(), &statbuf);
2942 if (::rename ((*x).c_str(), newpath.c_str()) != 0) {
2943 error << string_compose (_("cannot rename unused file source from %1 to %2 (%3)"),
2944 (*x), newpath, strerror (errno))
2949 /* see if there an easy to find peakfile for this file, and remove it.
2952 string base = basename_nosuffix (*x);
2953 base += "%A"; /* this is what we add for the channel suffix of all native files,
2954 or for the first channel of embedded files. it will miss
2955 some peakfiles for other channels
2957 string peakpath = peak_path (base);
2959 if (Glib::file_test (peakpath.c_str(), Glib::FILE_TEST_EXISTS)) {
2960 if (::g_unlink (peakpath.c_str()) != 0) {
2961 error << string_compose (_("cannot remove peakfile %1 for %2 (%3)"),
2962 peakpath, _path, strerror (errno))
2964 /* try to back out */
2965 ::rename (newpath.c_str(), _path.c_str());
2970 rep.paths.push_back (*x);
2971 rep.space += statbuf.st_size;
2974 /* dump the history list */
2978 /* save state so we don't end up a session file
2979 referring to non-existent sources.
2986 _state_of_the_state = (StateOfTheState) (_state_of_the_state & ~InCleanup);
2992 Session::cleanup_trash_sources (CleanupReport& rep)
2994 // FIXME: needs adaptation for MIDI
2996 vector<space_and_path>::iterator i;
3002 for (i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3004 dead_dir = Glib::build_filename ((*i).path, dead_dir_name);
3006 clear_directory (dead_dir, &rep.space, &rep.paths);
3013 Session::set_dirty ()
3015 /* never mark session dirty during loading */
3017 if (_state_of_the_state & Loading) {
3021 bool was_dirty = dirty();
3023 _state_of_the_state = StateOfTheState (_state_of_the_state | Dirty);
3027 DirtyChanged(); /* EMIT SIGNAL */
3033 Session::set_clean ()
3035 bool was_dirty = dirty();
3037 _state_of_the_state = Clean;
3041 DirtyChanged(); /* EMIT SIGNAL */
3046 Session::set_deletion_in_progress ()
3048 _state_of_the_state = StateOfTheState (_state_of_the_state | Deletion);
3052 Session::clear_deletion_in_progress ()
3054 _state_of_the_state = StateOfTheState (_state_of_the_state & (~Deletion));
3058 Session::add_controllable (boost::shared_ptr<Controllable> c)
3060 /* this adds a controllable to the list managed by the Session.
3061 this is a subset of those managed by the Controllable class
3062 itself, and represents the only ones whose state will be saved
3063 as part of the session.
3066 Glib::Threads::Mutex::Lock lm (controllables_lock);
3067 controllables.insert (c);
3070 struct null_deleter { void operator()(void const *) const {} };
3073 Session::remove_controllable (Controllable* c)
3075 if (_state_of_the_state & Deletion) {
3079 Glib::Threads::Mutex::Lock lm (controllables_lock);
3081 Controllables::iterator x = controllables.find (boost::shared_ptr<Controllable>(c, null_deleter()));
3083 if (x != controllables.end()) {
3084 controllables.erase (x);
3088 boost::shared_ptr<Controllable>
3089 Session::controllable_by_id (const PBD::ID& id)
3091 Glib::Threads::Mutex::Lock lm (controllables_lock);
3093 for (Controllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
3094 if ((*i)->id() == id) {
3099 return boost::shared_ptr<Controllable>();
3102 boost::shared_ptr<Controllable>
3103 Session::controllable_by_descriptor (const ControllableDescriptor& desc)
3105 boost::shared_ptr<Controllable> c;
3106 boost::shared_ptr<Route> r;
3108 switch (desc.top_level_type()) {
3109 case ControllableDescriptor::NamedRoute:
3111 std::string str = desc.top_level_name();
3112 if (str == "Master" || str == "master") {
3114 } else if (str == "control" || str == "listen") {
3117 r = route_by_name (desc.top_level_name());
3122 case ControllableDescriptor::RemoteControlID:
3123 r = route_by_remote_id (desc.rid());
3131 switch (desc.subtype()) {
3132 case ControllableDescriptor::Gain:
3133 c = r->gain_control ();
3136 case ControllableDescriptor::Trim:
3137 c = r->trim()->gain_control ();
3140 case ControllableDescriptor::Solo:
3141 c = r->solo_control();
3144 case ControllableDescriptor::Mute:
3145 c = r->mute_control();
3148 case ControllableDescriptor::Recenable:
3150 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(r);
3153 c = t->rec_enable_control ();
3158 case ControllableDescriptor::PanDirection:
3160 c = r->pannable()->pan_azimuth_control;
3164 case ControllableDescriptor::PanWidth:
3166 c = r->pannable()->pan_width_control;
3170 case ControllableDescriptor::PanElevation:
3172 c = r->pannable()->pan_elevation_control;
3176 case ControllableDescriptor::Balance:
3177 /* XXX simple pan control */
3180 case ControllableDescriptor::PluginParameter:
3182 uint32_t plugin = desc.target (0);
3183 uint32_t parameter_index = desc.target (1);
3185 /* revert to zero based counting */
3191 if (parameter_index > 0) {
3195 boost::shared_ptr<Processor> p = r->nth_plugin (plugin);
3198 c = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
3199 p->control(Evoral::Parameter(PluginAutomation, 0, parameter_index)));
3204 case ControllableDescriptor::SendGain:
3206 uint32_t send = desc.target (0);
3208 /* revert to zero-based counting */
3214 boost::shared_ptr<Processor> p = r->nth_send (send);
3217 boost::shared_ptr<Send> s = boost::dynamic_pointer_cast<Send>(p);
3218 boost::shared_ptr<Amp> a = s->amp();
3221 c = s->amp()->gain_control();
3228 /* relax and return a null pointer */
3236 Session::add_instant_xml (XMLNode& node, bool write_to_config)
3239 Stateful::add_instant_xml (node, _path);
3242 if (write_to_config) {
3243 Config->add_instant_xml (node);
3248 Session::instant_xml (const string& node_name)
3250 return Stateful::instant_xml (node_name, _path);
3254 Session::save_history (string snapshot_name)
3262 if (!Config->get_save_history() || Config->get_saved_history_depth() < 0 ||
3263 (_history.undo_depth() == 0 && _history.redo_depth() == 0)) {
3267 if (snapshot_name.empty()) {
3268 snapshot_name = _current_snapshot_name;
3271 const string history_filename = legalize_for_path (snapshot_name) + history_suffix;
3272 const string backup_filename = history_filename + backup_suffix;
3273 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), history_filename));
3274 const std::string backup_path(Glib::build_filename (_session_dir->root_path(), backup_filename));
3276 if (Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3277 if (::g_rename (xml_path.c_str(), backup_path.c_str()) != 0) {
3278 error << _("could not backup old history file, current history not saved") << endmsg;
3283 tree.set_root (&_history.get_state (Config->get_saved_history_depth()));
3285 if (!tree.write (xml_path))
3287 error << string_compose (_("history could not be saved to %1"), xml_path) << endmsg;
3289 if (g_remove (xml_path.c_str()) != 0) {
3290 error << string_compose(_("Could not remove history file at path \"%1\" (%2)"),
3291 xml_path, g_strerror (errno)) << endmsg;
3293 if (::g_rename (backup_path.c_str(), xml_path.c_str()) != 0) {
3294 error << string_compose (_("could not restore history file from backup %1 (%2)"),
3295 backup_path, g_strerror (errno)) << endmsg;
3305 Session::restore_history (string snapshot_name)
3309 if (snapshot_name.empty()) {
3310 snapshot_name = _current_snapshot_name;
3313 const std::string xml_filename = legalize_for_path (snapshot_name) + history_suffix;
3314 const std::string xml_path(Glib::build_filename (_session_dir->root_path(), xml_filename));
3316 info << "Loading history from " << xml_path << endmsg;
3318 if (!Glib::file_test (xml_path, Glib::FILE_TEST_EXISTS)) {
3319 info << string_compose (_("%1: no history file \"%2\" for this session."),
3320 _name, xml_path) << endmsg;
3324 if (!tree.read (xml_path)) {
3325 error << string_compose (_("Could not understand session history file \"%1\""),
3326 xml_path) << endmsg;
3333 for (XMLNodeConstIterator it = tree.root()->children().begin(); it != tree.root()->children().end(); it++) {
3336 UndoTransaction* ut = new UndoTransaction ();
3339 ut->set_name(t->property("name")->value());
3340 stringstream ss(t->property("tv-sec")->value());
3342 ss.str(t->property("tv-usec")->value());
3344 ut->set_timestamp(tv);
3346 for (XMLNodeConstIterator child_it = t->children().begin();
3347 child_it != t->children().end(); child_it++)
3349 XMLNode *n = *child_it;
3352 if (n->name() == "MementoCommand" ||
3353 n->name() == "MementoUndoCommand" ||
3354 n->name() == "MementoRedoCommand") {
3356 if ((c = memento_command_factory(n))) {
3360 } else if (n->name() == "NoteDiffCommand") {
3361 PBD::ID id (n->property("midi-source")->value());
3362 boost::shared_ptr<MidiSource> midi_source =
3363 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3365 ut->add_command (new MidiModel::NoteDiffCommand(midi_source->model(), *n));
3367 error << _("Failed to downcast MidiSource for NoteDiffCommand") << endmsg;
3370 } else if (n->name() == "SysExDiffCommand") {
3372 PBD::ID id (n->property("midi-source")->value());
3373 boost::shared_ptr<MidiSource> midi_source =
3374 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3376 ut->add_command (new MidiModel::SysExDiffCommand (midi_source->model(), *n));
3378 error << _("Failed to downcast MidiSource for SysExDiffCommand") << endmsg;
3381 } else if (n->name() == "PatchChangeDiffCommand") {
3383 PBD::ID id (n->property("midi-source")->value());
3384 boost::shared_ptr<MidiSource> midi_source =
3385 boost::dynamic_pointer_cast<MidiSource, Source>(source_by_id(id));
3387 ut->add_command (new MidiModel::PatchChangeDiffCommand (midi_source->model(), *n));
3389 error << _("Failed to downcast MidiSource for PatchChangeDiffCommand") << endmsg;
3392 } else if (n->name() == "StatefulDiffCommand") {
3393 if ((c = stateful_diff_command_factory (n))) {
3394 ut->add_command (c);
3397 error << string_compose(_("Couldn't figure out how to make a Command out of a %1 XMLNode."), n->name()) << endmsg;
3408 Session::config_changed (std::string p, bool ours)
3414 if (p == "seamless-loop") {
3416 } else if (p == "rf-speed") {
3418 } else if (p == "auto-loop") {
3420 } else if (p == "auto-input") {
3422 if (Config->get_monitoring_model() == HardwareMonitoring && transport_rolling()) {
3423 /* auto-input only makes a difference if we're rolling */
3424 set_track_monitor_input_status (!config.get_auto_input());
3427 } else if (p == "punch-in") {
3431 if ((location = _locations->auto_punch_location()) != 0) {
3433 if (config.get_punch_in ()) {
3434 replace_event (SessionEvent::PunchIn, location->start());
3436 remove_event (location->start(), SessionEvent::PunchIn);
3440 } else if (p == "punch-out") {
3444 if ((location = _locations->auto_punch_location()) != 0) {
3446 if (config.get_punch_out()) {
3447 replace_event (SessionEvent::PunchOut, location->end());
3449 clear_events (SessionEvent::PunchOut);
3453 } else if (p == "edit-mode") {
3455 Glib::Threads::Mutex::Lock lm (playlists->lock);
3457 for (SessionPlaylists::List::iterator i = playlists->playlists.begin(); i != playlists->playlists.end(); ++i) {
3458 (*i)->set_edit_mode (Config->get_edit_mode ());
3461 } else if (p == "use-video-sync") {
3463 waiting_for_sync_offset = config.get_use_video_sync();
3465 } else if (p == "mmc-control") {
3467 //poke_midi_thread ();
3469 } else if (p == "mmc-device-id" || p == "mmc-receive-id" || p == "mmc-receive-device-id") {
3471 _mmc->set_receive_device_id (Config->get_mmc_receive_device_id());
3473 } else if (p == "mmc-send-id" || p == "mmc-send-device-id") {
3475 _mmc->set_send_device_id (Config->get_mmc_send_device_id());
3477 } else if (p == "midi-control") {
3479 //poke_midi_thread ();
3481 } else if (p == "raid-path") {
3483 setup_raid_path (config.get_raid_path());
3485 } else if (p == "timecode-format") {
3489 } else if (p == "video-pullup") {
3493 } else if (p == "seamless-loop") {
3495 if (play_loop && transport_rolling()) {
3496 // to reset diskstreams etc
3497 request_play_loop (true);
3500 } else if (p == "rf-speed") {
3502 cumulative_rf_motion = 0;
3505 } else if (p == "click-sound") {
3507 setup_click_sounds (1);
3509 } else if (p == "click-emphasis-sound") {
3511 setup_click_sounds (-1);
3513 } else if (p == "clicking") {
3515 if (Config->get_clicking()) {
3516 if (_click_io && click_data) { // don't require emphasis data
3523 } else if (p == "click-gain") {
3526 _click_gain->set_gain (Config->get_click_gain(), this);
3529 } else if (p == "send-mtc") {
3531 if (Config->get_send_mtc ()) {
3532 /* mark us ready to send */
3533 next_quarter_frame_to_send = 0;
3536 } else if (p == "send-mmc") {
3538 _mmc->enable_send (Config->get_send_mmc ());
3540 } else if (p == "midi-feedback") {
3542 session_midi_feedback = Config->get_midi_feedback();
3544 } else if (p == "jack-time-master") {
3546 engine().reset_timebase ();
3548 } else if (p == "native-file-header-format") {
3550 if (!first_file_header_format_reset) {
3551 reset_native_file_format ();
3554 first_file_header_format_reset = false;
3556 } else if (p == "native-file-data-format") {
3558 if (!first_file_data_format_reset) {
3559 reset_native_file_format ();
3562 first_file_data_format_reset = false;
3564 } else if (p == "external-sync") {
3565 if (!config.get_external_sync()) {
3566 drop_sync_source ();
3568 switch_to_sync_source (Config->get_sync_source());
3570 } else if (p == "denormal-model") {
3572 } else if (p == "history-depth") {
3573 set_history_depth (Config->get_history_depth());
3574 } else if (p == "remote-model") {
3575 /* XXX DO SOMETHING HERE TO TELL THE GUI THAT WE NEED
3578 } else if (p == "initial-program-change") {
3580 if (_mmc->output_port() && Config->get_initial_program_change() >= 0) {
3583 buf[0] = MIDI::program; // channel zero by default
3584 buf[1] = (Config->get_initial_program_change() & 0x7f);
3586 _mmc->output_port()->midimsg (buf, sizeof (buf), 0);
3588 } else if (p == "solo-mute-override") {
3589 // catch_up_on_solo_mute_override ();
3590 } else if (p == "listen-position" || p == "pfl-position") {
3591 listen_position_changed ();
3592 } else if (p == "solo-control-is-listen-control") {
3593 solo_control_mode_changed ();
3594 } else if (p == "solo-mute-gain") {
3595 _solo_cut_control->Changed();
3596 } else if (p == "timecode-offset" || p == "timecode-offset-negative") {
3597 last_timecode_valid = false;
3598 } else if (p == "playback-buffer-seconds") {
3599 AudioSource::allocate_working_buffers (frame_rate());
3600 } else if (p == "ltc-source-port") {
3601 reconnect_ltc_input ();
3602 } else if (p == "ltc-sink-port") {
3603 reconnect_ltc_output ();
3604 } else if (p == "timecode-generator-offset") {
3605 ltc_tx_parse_offset();
3612 Session::set_history_depth (uint32_t d)
3614 _history.set_depth (d);
3618 Session::load_diskstreams_2X (XMLNode const & node, int)
3621 XMLNodeConstIterator citer;
3623 clist = node.children();
3625 for (citer = clist.begin(); citer != clist.end(); ++citer) {
3628 /* diskstreams added automatically by DiskstreamCreated handler */
3629 if ((*citer)->name() == "AudioDiskstream" || (*citer)->name() == "DiskStream") {
3630 boost::shared_ptr<AudioDiskstream> dsp (new AudioDiskstream (*this, **citer));
3631 _diskstreams_2X.push_back (dsp);
3633 error << _("Session: unknown diskstream type in XML") << endmsg;
3637 catch (failed_constructor& err) {
3638 error << _("Session: could not load diskstream via XML state") << endmsg;
3646 /** Connect things to the MMC object */
3648 Session::setup_midi_machine_control ()
3650 _mmc = new MIDI::MachineControl;
3651 _mmc->set_ports (_midi_ports->mmc_input_port(), _midi_ports->mmc_output_port());
3653 _mmc->Play.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3654 _mmc->DeferredPlay.connect_same_thread (*this, boost::bind (&Session::mmc_deferred_play, this, _1));
3655 _mmc->Stop.connect_same_thread (*this, boost::bind (&Session::mmc_stop, this, _1));
3656 _mmc->FastForward.connect_same_thread (*this, boost::bind (&Session::mmc_fast_forward, this, _1));
3657 _mmc->Rewind.connect_same_thread (*this, boost::bind (&Session::mmc_rewind, this, _1));
3658 _mmc->Pause.connect_same_thread (*this, boost::bind (&Session::mmc_pause, this, _1));
3659 _mmc->RecordPause.connect_same_thread (*this, boost::bind (&Session::mmc_record_pause, this, _1));
3660 _mmc->RecordStrobe.connect_same_thread (*this, boost::bind (&Session::mmc_record_strobe, this, _1));
3661 _mmc->RecordExit.connect_same_thread (*this, boost::bind (&Session::mmc_record_exit, this, _1));
3662 _mmc->Locate.connect_same_thread (*this, boost::bind (&Session::mmc_locate, this, _1, _2));
3663 _mmc->Step.connect_same_thread (*this, boost::bind (&Session::mmc_step, this, _1, _2));
3664 _mmc->Shuttle.connect_same_thread (*this, boost::bind (&Session::mmc_shuttle, this, _1, _2, _3));
3665 _mmc->TrackRecordStatusChange.connect_same_thread (*this, boost::bind (&Session::mmc_record_enable, this, _1, _2, _3));
3667 /* also handle MIDI SPP because its so common */
3669 _mmc->SPPStart.connect_same_thread (*this, boost::bind (&Session::spp_start, this));
3670 _mmc->SPPContinue.connect_same_thread (*this, boost::bind (&Session::spp_continue, this));
3671 _mmc->SPPStop.connect_same_thread (*this, boost::bind (&Session::spp_stop, this));
3674 boost::shared_ptr<Controllable>
3675 Session::solo_cut_control() const
3677 /* the solo cut control is a bit of an anomaly, at least as of Febrary 2011. There are no other
3678 controls in Ardour that currently get presented to the user in the GUI that require
3679 access as a Controllable and are also NOT owned by some SessionObject (e.g. Route, or MonitorProcessor).
3681 its actually an RCConfiguration parameter, so we use a ProxyControllable to wrap
3682 it up as a Controllable. Changes to the Controllable will just map back to the RCConfiguration
3686 return _solo_cut_control;
3690 Session::rename (const std::string& new_name)
3692 string legal_name = legalize_for_path (new_name);
3698 string const old_sources_root = _session_dir->sources_root();
3700 if (!_writable || (_state_of_the_state & CannotSave)) {
3701 error << _("Cannot rename read-only session.") << endmsg;
3702 return 0; // don't show "messed up" warning
3704 if (record_status() == Recording) {
3705 error << _("Cannot rename session while recording") << endmsg;
3706 return 0; // don't show "messed up" warning
3709 StateProtector stp (this);
3714 * interchange subdirectory
3718 * Backup files are left unchanged and not renamed.
3721 /* Windows requires that we close all files before attempting the
3722 * rename. This works on other platforms, but isn't necessary there.
3723 * Leave it in place for all platforms though, since it may help
3724 * catch issues that could arise if the way Source files work ever
3725 * change (since most developers are not using Windows).
3728 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
3729 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3735 /* pass one: not 100% safe check that the new directory names don't
3739 for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3743 /* this is a stupid hack because Glib::path_get_dirname() is
3744 * lexical-only, and so passing it /a/b/c/ gives a different
3745 * result than passing it /a/b/c ...
3748 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3749 oldstr = oldstr.substr (0, oldstr.length() - 1);
3752 string base = Glib::path_get_dirname (oldstr);
3754 newstr = Glib::build_filename (base, legal_name);
3756 cerr << "Looking for " << newstr << endl;
3758 if (Glib::file_test (newstr, Glib::FILE_TEST_EXISTS)) {
3759 cerr << " exists\n";
3768 for (vector<space_and_path>::iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
3774 /* this is a stupid hack because Glib::path_get_dirname() is
3775 * lexical-only, and so passing it /a/b/c/ gives a different
3776 * result than passing it /a/b/c ...
3779 if (oldstr[oldstr.length()-1] == G_DIR_SEPARATOR) {
3780 oldstr = oldstr.substr (0, oldstr.length() - 1);
3783 string base = Glib::path_get_dirname (oldstr);
3784 newstr = Glib::build_filename (base, legal_name);
3786 cerr << "for " << oldstr << " new dir = " << newstr << endl;
3788 cerr << "Rename " << oldstr << " => " << newstr << endl;
3789 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3790 cerr << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3791 error << string_compose (_("renaming %s as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3795 /* Reset path in "session dirs" */
3800 /* reset primary SessionDirectory object */
3803 (*_session_dir) = newstr;
3808 /* now rename directory below session_dir/interchange */
3810 string old_interchange_dir;
3811 string new_interchange_dir;
3813 /* use newstr here because we renamed the path
3814 * (folder/directory) that used to be oldstr to newstr above
3817 v.push_back (newstr);
3818 v.push_back (interchange_dir_name);
3819 v.push_back (Glib::path_get_basename (oldstr));
3821 old_interchange_dir = Glib::build_filename (v);
3824 v.push_back (newstr);
3825 v.push_back (interchange_dir_name);
3826 v.push_back (legal_name);
3828 new_interchange_dir = Glib::build_filename (v);
3830 cerr << "Rename " << old_interchange_dir << " => " << new_interchange_dir << endl;
3832 if (::g_rename (old_interchange_dir.c_str(), new_interchange_dir.c_str()) != 0) {
3833 cerr << string_compose (_("renaming %s as %2 failed (%3)"),
3834 old_interchange_dir, new_interchange_dir,
3837 error << string_compose (_("renaming %s as %2 failed (%3)"),
3838 old_interchange_dir, new_interchange_dir,
3847 oldstr = Glib::build_filename (new_path, _current_snapshot_name + statefile_suffix);
3848 newstr= Glib::build_filename (new_path, legal_name + statefile_suffix);
3850 cerr << "Rename " << oldstr << " => " << newstr << endl;
3852 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3853 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3854 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3860 oldstr = Glib::build_filename (new_path, _current_snapshot_name) + history_suffix;
3862 if (Glib::file_test (oldstr, Glib::FILE_TEST_EXISTS)) {
3863 newstr = Glib::build_filename (new_path, legal_name) + history_suffix;
3865 cerr << "Rename " << oldstr << " => " << newstr << endl;
3867 if (::g_rename (oldstr.c_str(), newstr.c_str()) != 0) {
3868 cerr << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endl;
3869 error << string_compose (_("renaming %1 as %2 failed (%3)"), oldstr, newstr, g_strerror (errno)) << endmsg;
3874 /* remove old name from recent sessions */
3875 remove_recent_sessions (_path);
3878 /* update file source paths */
3880 for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
3881 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3883 string p = fs->path ();
3884 boost::replace_all (p, old_sources_root, _session_dir->sources_root());
3886 SourceFactory::setup_peakfile(i->second, true);
3890 _current_snapshot_name = new_name;
3895 /* save state again to get everything just right */
3897 save_state (_current_snapshot_name);
3899 /* add to recent sessions */
3901 store_recent_sessions (new_name, _path);
3907 Session::get_session_info_from_path (XMLTree& tree, const string& xmlpath)
3909 if (!Glib::file_test (xmlpath, Glib::FILE_TEST_EXISTS)) {
3913 if (!tree.read (xmlpath)) {
3921 Session::get_info_from_path (const string& xmlpath, float& sample_rate, SampleFormat& data_format)
3924 bool found_sr = false;
3925 bool found_data_format = false;
3927 if (get_session_info_from_path (tree, xmlpath)) {
3933 const XMLProperty* prop;
3934 if ((prop = tree.root()->property (X_("sample-rate"))) != 0) {
3935 sample_rate = atoi (prop->value());
3939 const XMLNodeList& children (tree.root()->children());
3940 for (XMLNodeList::const_iterator c = children.begin(); c != children.end(); ++c) {
3941 const XMLNode* child = *c;
3942 if (child->name() == "Config") {
3943 const XMLNodeList& options (child->children());
3944 for (XMLNodeList::const_iterator oc = options.begin(); oc != options.end(); ++oc) {
3945 const XMLNode* option = *oc;
3946 const XMLProperty* name = option->property("name");
3952 if (name->value() == "native-file-data-format") {
3953 const XMLProperty* value = option->property ("value");
3955 SampleFormat fmt = (SampleFormat) string_2_enum (option->property ("value")->value(), fmt);
3957 found_data_format = true;
3963 if (found_data_format) {
3968 return !(found_sr && found_data_format); // zero if they are both found
3971 typedef std::vector<boost::shared_ptr<FileSource> > SeveralFileSources;
3972 typedef std::map<std::string,SeveralFileSources> SourcePathMap;
3975 Session::bring_all_sources_into_session (boost::function<void(uint32_t,uint32_t,string)> callback)
3979 SourcePathMap source_path_map;
3981 boost::shared_ptr<AudioFileSource> afs;
3986 Glib::Threads::Mutex::Lock lm (source_lock);
3988 cerr << " total sources = " << sources.size();
3990 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
3991 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
3997 if (fs->within_session()) {
4001 if (source_path_map.find (fs->path()) != source_path_map.end()) {
4002 source_path_map[fs->path()].push_back (fs);
4004 SeveralFileSources v;
4006 source_path_map.insert (make_pair (fs->path(), v));
4012 cerr << " fsources = " << total << endl;
4014 for (SourcePathMap::iterator i = source_path_map.begin(); i != source_path_map.end(); ++i) {
4016 /* tell caller where we are */
4018 string old_path = i->first;
4020 callback (n, total, old_path);
4022 cerr << old_path << endl;
4026 switch (i->second.front()->type()) {
4027 case DataType::AUDIO:
4028 new_path = new_audio_source_path_for_embedded (old_path);
4031 case DataType::MIDI:
4032 /* XXX not implemented yet */
4036 if (new_path.empty()) {
4040 cerr << "Move " << old_path << " => " << new_path << endl;
4042 if (!copy_file (old_path, new_path)) {
4043 cerr << "failed !\n";
4047 /* make sure we stop looking in the external
4048 dir/folder. Remember, this is an all-or-nothing
4049 operations, it doesn't merge just some files.
4051 remove_dir_from_search_path (Glib::path_get_dirname (old_path), i->second.front()->type());
4053 for (SeveralFileSources::iterator f = i->second.begin(); f != i->second.end(); ++f) {
4054 (*f)->set_path (new_path);
4059 save_state ("", false, false);
4065 bool accept_all_files (string const &, void *)
4071 Session::save_as_bring_callback (uint32_t,uint32_t,string)
4073 /* 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.
4078 make_new_media_path (string old_path, string new_session_folder, string new_session_path)
4080 /* typedir is the "midifiles" or "audiofiles" etc. part of the path. */
4082 string typedir = Glib::path_get_basename (Glib::path_get_dirname (old_path));
4084 v.push_back (new_session_folder); /* full path */
4085 v.push_back (interchange_dir_name);
4086 v.push_back (new_session_path); /* just one directory/folder */
4087 v.push_back (typedir);
4088 v.push_back (Glib::path_get_basename (old_path));
4090 return Glib::build_filename (v);
4094 Session::save_as (SaveAs& saveas)
4096 vector<string> files;
4097 string current_folder = Glib::path_get_dirname (_path);
4098 string new_folder = legalize_for_path (saveas.new_name);
4099 string to_dir = Glib::build_filename (saveas.new_parent_folder, new_folder);
4100 int64_t total_bytes = 0;
4104 int32_t internal_file_cnt = 0;
4106 vector<string> do_not_copy_extensions;
4107 do_not_copy_extensions.push_back (statefile_suffix);
4108 do_not_copy_extensions.push_back (pending_suffix);
4109 do_not_copy_extensions.push_back (backup_suffix);
4110 do_not_copy_extensions.push_back (temp_suffix);
4111 do_not_copy_extensions.push_back (history_suffix);
4113 /* get total size */
4115 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4117 /* need to clear this because
4118 * find_files_matching_filter() is cumulative
4123 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4125 all += files.size();
4127 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4129 g_stat ((*i).c_str(), &gsb);
4130 total_bytes += gsb.st_size;
4134 /* save old values so we can switch back if we are not switching to the new session */
4136 string old_path = _path;
4137 string old_name = _name;
4138 string old_snapshot = _current_snapshot_name;
4139 string old_sd = _session_dir->root_path();
4140 vector<string> old_search_path[DataType::num_types];
4141 string old_config_search_path[DataType::num_types];
4143 old_search_path[DataType::AUDIO] = source_search_path (DataType::AUDIO);
4144 old_search_path[DataType::MIDI] = source_search_path (DataType::MIDI);
4145 old_config_search_path[DataType::AUDIO] = config.get_audio_search_path ();
4146 old_config_search_path[DataType::MIDI] = config.get_midi_search_path ();
4148 /* switch session directory */
4150 (*_session_dir) = to_dir;
4152 /* create new tree */
4154 if (!_session_dir->create()) {
4155 saveas.failure_message = string_compose (_("Cannot create new session folder %1"), to_dir);
4160 /* copy all relevant files. Find each location in session_dirs,
4161 * and copy files from there to target.
4164 for (vector<space_and_path>::const_iterator sd = session_dirs.begin(); sd != session_dirs.end(); ++sd) {
4166 /* need to clear this because
4167 * find_files_matching_filter() is cumulative
4172 const size_t prefix_len = (*sd).path.size();
4174 /* Work just on the files within this session dir */
4176 find_files_matching_filter (files, (*sd).path, accept_all_files, 0, false, true, true);
4178 /* add dir separator to protect against collisions with
4179 * track names (e.g. track named "audiofiles" or
4183 static const std::string audiofile_dir_string = string (sound_dir_name) + G_DIR_SEPARATOR;
4184 static const std::string midifile_dir_string = string (midi_dir_name) + G_DIR_SEPARATOR;
4185 static const std::string analysis_dir_string = analysis_dir() + G_DIR_SEPARATOR;
4187 /* copy all the files. Handling is different for media files
4188 than others because of the *silly* subtree we have below the interchange
4189 folder. That really was a bad idea, but I'm not fixing it as part of
4190 implementing ::save_as().
4193 for (vector<string>::iterator i = files.begin(); i != files.end(); ++i) {
4195 std::string from = *i;
4198 string filename = Glib::path_get_basename (from);
4199 std::transform (filename.begin(), filename.end(), filename.begin(), ::toupper);
4200 if (filename == ".DS_STORE") {
4205 if (from.find (audiofile_dir_string) != string::npos) {
4207 /* audio file: only copy if asked */
4209 if (saveas.include_media && saveas.copy_media) {
4211 string to = make_new_media_path (*i, to_dir, new_folder);
4213 info << "media file copying from " << from << " to " << to << endmsg;
4215 if (!copy_file (from, to)) {
4216 throw Glib::FileError (Glib::FileError::IO_ERROR,
4217 string_compose(_("\ncopying \"%1\" failed !"), from));
4221 /* we found media files inside the session folder */
4223 internal_file_cnt++;
4225 } else if (from.find (midifile_dir_string) != string::npos) {
4227 /* midi file: always copy unless
4228 * creating an empty new session
4231 if (saveas.include_media) {
4233 string to = make_new_media_path (*i, to_dir, new_folder);
4235 info << "media file copying from " << from << " to " << to << endmsg;
4237 if (!copy_file (from, to)) {
4238 throw Glib::FileError (Glib::FileError::IO_ERROR, "copy failed");
4242 /* we found media files inside the session folder */
4244 internal_file_cnt++;
4246 } else if (from.find (analysis_dir_string) != string::npos) {
4248 /* make sure analysis dir exists in
4249 * new session folder, but we're not
4250 * copying analysis files here, see
4254 (void) g_mkdir_with_parents (analysis_dir().c_str(), 775);
4259 /* normal non-media file. Don't copy state, history, etc.
4262 bool do_copy = true;
4264 for (vector<string>::iterator v = do_not_copy_extensions.begin(); v != do_not_copy_extensions.end(); ++v) {
4265 if ((from.length() > (*v).length()) && (from.find (*v) == from.length() - (*v).length())) {
4266 /* end of filename matches extension, do not copy file */
4272 if (!saveas.copy_media && from.find (peakfile_suffix) != string::npos) {
4273 /* don't copy peakfiles if
4274 * we're not copying media
4280 string to = Glib::build_filename (to_dir, from.substr (prefix_len));
4282 info << "attempting to make directory/folder " << to << endmsg;
4284 if (g_mkdir_with_parents (Glib::path_get_dirname (to).c_str(), 0755)) {
4285 throw Glib::FileError (Glib::FileError::IO_ERROR, "cannot create required directory");
4288 info << "attempting to copy " << from << " to " << to << endmsg;
4290 if (!copy_file (from, to)) {
4291 throw Glib::FileError (Glib::FileError::IO_ERROR,
4292 string_compose(_("\ncopying \"%1\" failed !"), from));
4297 /* measure file size even if we're not going to copy so that our Progress
4298 signals are correct, since we included these do-not-copy files
4299 in the computation of the total size and file count.
4303 g_stat (from.c_str(), &gsb);
4304 copied += gsb.st_size;
4307 double fraction = (double) copied / total_bytes;
4309 bool keep_going = true;
4311 if (saveas.copy_media) {
4313 /* no need or expectation of this if
4314 * media is not being copied, because
4315 * it will be fast(ish).
4318 /* tell someone "X percent, file M of N"; M is one-based */
4320 boost::optional<bool> res = saveas.Progress (fraction, cnt, all);
4328 throw Glib::FileError (Glib::FileError::FAILED, "copy cancelled");
4334 /* copy optional folders, if any */
4336 string old = plugins_dir ();
4337 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4338 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4339 copy_files (old, newdir);
4342 old = externals_dir ();
4343 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4344 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4345 copy_files (old, newdir);
4348 old = automation_dir ();
4349 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4350 string newdir = Glib::build_filename (to_dir, Glib::path_get_basename (old));
4351 copy_files (old, newdir);
4354 if (saveas.include_media) {
4356 if (saveas.copy_media) {
4357 #ifndef PLATFORM_WINDOWS
4358 /* There are problems with analysis files on
4359 * Windows, because they used a colon in their
4360 * names as late as 4.0. Colons are not legal
4361 * under Windows even if NTFS allows them.
4363 * This is a tricky problem to solve so for
4364 * just don't copy these files. They will be
4365 * regenerated as-needed anyway, subject to the
4366 * existing issue that the filenames will be
4367 * rejected by Windows, which is a separate
4368 * problem (though related).
4371 /* only needed if we are copying media, since the
4372 * analysis data refers to media data
4375 old = analysis_dir ();
4376 if (Glib::file_test (old, Glib::FILE_TEST_EXISTS)) {
4377 string newdir = Glib::build_filename (to_dir, "analysis");
4378 copy_files (old, newdir);
4380 #endif /* PLATFORM_WINDOWS */
4386 _current_snapshot_name = saveas.new_name;
4387 _name = saveas.new_name;
4389 if (saveas.include_media && !saveas.copy_media) {
4391 /* reset search paths of the new session (which we're pretending to be right now) to
4392 include the original session search path, so we can still find all audio.
4395 if (internal_file_cnt) {
4396 for (vector<string>::iterator s = old_search_path[DataType::AUDIO].begin(); s != old_search_path[DataType::AUDIO].end(); ++s) {
4397 ensure_search_path_includes (*s, DataType::AUDIO);
4400 /* we do not do this for MIDI because we copy
4401 all MIDI files if saveas.include_media is
4407 bool was_dirty = dirty ();
4409 save_state ("", false, false, !saveas.include_media);
4410 save_default_options ();
4412 if (saveas.copy_media && saveas.copy_external) {
4413 if (bring_all_sources_into_session (boost::bind (&Session::save_as_bring_callback, this, _1, _2, _3))) {
4414 throw Glib::FileError (Glib::FileError::NO_SPACE_LEFT, "consolidate failed");
4418 saveas.final_session_folder_name = _path;
4420 store_recent_sessions (_name, _path);
4422 if (!saveas.switch_to) {
4424 /* switch back to the way things were */
4428 _current_snapshot_name = old_snapshot;
4430 (*_session_dir) = old_sd;
4436 if (internal_file_cnt) {
4437 /* reset these to their original values */
4438 config.set_audio_search_path (old_config_search_path[DataType::AUDIO]);
4439 config.set_midi_search_path (old_config_search_path[DataType::MIDI]);
4444 /* prune session dirs, and update disk space statistics
4449 session_dirs.clear ();
4450 session_dirs.push_back (sp);
4451 refresh_disk_space ();
4453 /* ensure that all existing tracks reset their current capture source paths
4455 reset_write_sources (true, true);
4457 /* the copying above was based on actually discovering files, not just iterating over the sources list.
4458 But if we're going to switch to the new (copied) session, we need to change the paths in the sources also.
4461 for (SourceMap::const_iterator i = sources.begin(); i != sources.end(); ++i) {
4462 boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (i->second);
4468 if (fs->within_session()) {
4469 string newpath = make_new_media_path (fs->path(), to_dir, new_folder);
4470 fs->set_path (newpath);
4475 } catch (Glib::FileError& e) {
4477 saveas.failure_message = e.what();
4479 /* recursively remove all the directories */
4481 remove_directory (to_dir);
4489 saveas.failure_message = _("unknown reason");
4491 /* recursively remove all the directories */
4493 remove_directory (to_dir);